@deslop/workbench 0.0.330 → 0.0.342

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/client/assets/agent-BATV5D0O.js +1 -0
  2. package/dist/client/assets/agent-K-v27T1K.js +2 -0
  3. package/dist/client/assets/{button-DJfQFnBl.js → button-f42ZKq6E.js} +11 -11
  4. package/dist/client/assets/diff-BwOj6t_o.js +217 -0
  5. package/dist/client/assets/{diff-5y5Ly0fZ.js → diff-COOvYjfB.js} +2 -2
  6. package/dist/client/assets/{external-link-DSkEzLiB.js → external-link-DR7_wu3r.js} +1 -1
  7. package/dist/client/assets/{fallbacks-2XEEl4BI.js → fallbacks-D-9MltuA.js} +1 -1
  8. package/dist/client/assets/{index-CU4FmmbE.js → index-DCRiD9Nz.js} +3 -3
  9. package/dist/client/assets/index-DNWcrdqu.css +2 -0
  10. package/dist/client/assets/input-group-mMwtG03E.js +153 -0
  11. package/dist/client/assets/loader-circle-DEYAvEPU.js +1 -0
  12. package/dist/client/assets/portless-C8dLcQQw.js +2 -0
  13. package/dist/client/assets/{portless-DRWo8KFX.js → portless-nerboxiJ.js} +1 -1
  14. package/dist/client/assets/{resizable-BICft2JP.js → resizable-ChkQg6Mj.js} +1 -1
  15. package/dist/client/assets/route-DAz8IJkt.js +2 -0
  16. package/dist/client/assets/route-GFqYSDK4.js +45 -0
  17. package/dist/client/assets/run-B16WQaws.js +2 -0
  18. package/dist/client/assets/run-BHEbhvk3.js +1 -0
  19. package/dist/client/assets/state-BOj5tZ-Q.js +2 -0
  20. package/dist/client/assets/terminal-B410vkZ0.js +1 -0
  21. package/dist/client/assets/{terminal-CPpKsotd.js → terminal-BQ9AR6VK.js} +2 -2
  22. package/dist/client/assets/terminal-Br297Oa8.js +2 -0
  23. package/dist/client/assets/{triangle-alert-DrGIVhEI.js → triangle-alert-CQsOhrGn.js} +1 -1
  24. package/dist/client/index.html +12 -12
  25. package/dist/{execAsync-Gqapz_ET.mjs → execAsync-CgtnVVso.mjs} +1 -1
  26. package/dist/{getMachineId-bsd-D2D8E0zh.mjs → getMachineId-bsd-DYUtJhPR.mjs} +2 -2
  27. package/dist/{getMachineId-darwin-DD7WkQgq.mjs → getMachineId-darwin-BYjMzwa2.mjs} +2 -2
  28. package/dist/{getMachineId-linux-NsJbNTda.mjs → getMachineId-linux-7FQ_TPIw.mjs} +1 -1
  29. package/dist/{getMachineId-unsupported-BdKw63O1.mjs → getMachineId-unsupported-CqYci84U.mjs} +1 -1
  30. package/dist/{getMachineId-win-CpX0o49t.mjs → getMachineId-win-BxTTz_Ds.mjs} +2 -2
  31. package/dist/server.js +1316 -1056
  32. package/package.json +3 -3
  33. package/dist/client/assets/agent-BAplunWJ.js +0 -1
  34. package/dist/client/assets/agent-DORiXY9q.js +0 -2
  35. package/dist/client/assets/diff-Cu8yhVQs.js +0 -217
  36. package/dist/client/assets/index-BX6N5TyF.css +0 -2
  37. package/dist/client/assets/input-group-tkTwlIFp.js +0 -153
  38. package/dist/client/assets/loader-circle-vwjgn9E1.js +0 -1
  39. package/dist/client/assets/portless-Cn_0jtX4.js +0 -2
  40. package/dist/client/assets/route-D-VRm0UM.js +0 -2
  41. package/dist/client/assets/route-DAzFV54O.js +0 -45
  42. package/dist/client/assets/run-C08WVAIM.js +0 -1
  43. package/dist/client/assets/run-Dx2tn3Qe.js +0 -2
  44. package/dist/client/assets/state-DrPxOHMO.js +0 -2
  45. package/dist/client/assets/terminal-BGn5gevX.js +0 -2
  46. package/dist/client/assets/terminal-BTXMxFEq.js +0 -1
package/dist/server.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env -S node --max-old-space-size=8192
2
2
  import { createRequire } from "node:module";
3
3
  import * as Http from "node:http";
4
4
  import { createServer } from "node:http";
@@ -4562,7 +4562,7 @@ const isSome$1 = (fa) => fa._tag === "Some";
4562
4562
  /** @internal */
4563
4563
  const none$1 = /*#__PURE__*/ Object.create(NoneProto);
4564
4564
  /** @internal */
4565
- const some$2 = (value) => {
4565
+ const some$1 = (value) => {
4566
4566
  const a = Object.create(SomeProto);
4567
4567
  a.value = value;
4568
4568
  return a;
@@ -5061,7 +5061,7 @@ const none = () => none$1;
5061
5061
  * @category constructors
5062
5062
  * @since 2.0.0
5063
5063
  */
5064
- const some$1 = some$2;
5064
+ const some = some$1;
5065
5065
  /**
5066
5066
  * Checks whether an `Option` is `None` (absent).
5067
5067
  *
@@ -5153,7 +5153,7 @@ const isSome = isSome$1;
5153
5153
  * @category pattern matching
5154
5154
  * @since 2.0.0
5155
5155
  */
5156
- const match$5 = /*#__PURE__*/ dual(2, (self, { onNone, onSome }) => isNone(self) ? onNone() : onSome(self.value));
5156
+ const match$4 = /*#__PURE__*/ dual(2, (self, { onNone, onSome }) => isNone(self) ? onNone() : onSome(self.value));
5157
5157
  /**
5158
5158
  * Extracts the value from a `Some`, or evaluates a fallback thunk on `None`.
5159
5159
  *
@@ -5256,7 +5256,7 @@ const orElse$3 = /*#__PURE__*/ dual(2, (self, that) => isNone(self) ? that() : s
5256
5256
  * @category converting
5257
5257
  * @since 4.0.0
5258
5258
  */
5259
- const fromNullishOr = (a) => a == null ? none() : some$1(a);
5259
+ const fromNullishOr = (a) => a == null ? none() : some(a);
5260
5260
  /**
5261
5261
  * Converts a possibly `undefined` value into an `Option`, leaving `null`
5262
5262
  * as a valid `Some`.
@@ -5291,7 +5291,7 @@ const fromNullishOr = (a) => a == null ? none() : some$1(a);
5291
5291
  * @category converting
5292
5292
  * @since 4.0.0
5293
5293
  */
5294
- const fromUndefinedOr = (a) => a === void 0 ? none() : some$1(a);
5294
+ const fromUndefinedOr = (a) => a === void 0 ? none() : some(a);
5295
5295
  /**
5296
5296
  * Extracts the value from a `Some`, or returns `undefined` for `None`.
5297
5297
  *
@@ -5355,7 +5355,7 @@ const getOrUndefined$1 = /*#__PURE__*/ getOrElse$1(constUndefined);
5355
5355
  * @category mapping
5356
5356
  * @since 2.0.0
5357
5357
  */
5358
- const map$9 = /*#__PURE__*/ dual(2, (self, f) => isNone(self) ? none() : some$1(f(self.value)));
5358
+ const map$9 = /*#__PURE__*/ dual(2, (self, f) => isNone(self) ? none() : some(f(self.value)));
5359
5359
  /**
5360
5360
  * Applies a function that returns an `Option` to the value of a `Some`,
5361
5361
  * flattening the result. Returns `None` if the input is `None`.
@@ -5442,7 +5442,7 @@ const flatMap$6 = /*#__PURE__*/ dual(2, (self, f) => isNone(self) ? none() : f(s
5442
5442
  * @category filtering
5443
5443
  * @since 2.0.0
5444
5444
  */
5445
- const filter$3 = /*#__PURE__*/ dual(2, (self, predicate) => isNone(self) ? none() : predicate(self.value) ? some$1(self.value) : none());
5445
+ const filter$2 = /*#__PURE__*/ dual(2, (self, predicate) => isNone(self) ? none() : predicate(self.value) ? some(self.value) : none());
5446
5446
  //#endregion
5447
5447
  //#region ../../node_modules/.pnpm/effect@4.0.0-beta.74/node_modules/effect/dist/Result.js
5448
5448
  /**
@@ -5501,37 +5501,6 @@ const succeed$7 = succeed$8;
5501
5501
  */
5502
5502
  const fail$7 = fail$8;
5503
5503
  /**
5504
- * Provides a pre-built failed `Result` whose failure value is `undefined`.
5505
- *
5506
- * **When to use**
5507
- *
5508
- * Use when a failure should act only as a control signal and no failure value
5509
- * is needed.
5510
- *
5511
- * **Details**
5512
- *
5513
- * This is equivalent to `Result.fail(undefined)` with type
5514
- * `Result<never, void>`, but reuses a shared `Failure` wrapper instead of
5515
- * allocating one each time.
5516
- *
5517
- * **Example** (Using a failure without a payload)
5518
- *
5519
- * ```ts
5520
- * import { Result } from "effect"
5521
- *
5522
- * const result = Result.failVoid
5523
- *
5524
- * console.log(Result.isFailure(result))
5525
- * // Output: true
5526
- * ```
5527
- *
5528
- * @see {@link fail} to create a Failure with a specific value
5529
- *
5530
- * @category constructors
5531
- * @since 4.0.0
5532
- */
5533
- const failVoid = /*#__PURE__*/ fail$7(void 0);
5534
- /**
5535
5504
  * Checks whether a value is a `Result` (either `Success` or `Failure`).
5536
5505
  *
5537
5506
  * **When to use**
@@ -5658,7 +5627,7 @@ const isSuccess$1 = isSuccess$2;
5658
5627
  * @category pattern matching
5659
5628
  * @since 2.0.0
5660
5629
  */
5661
- const match$4 = /*#__PURE__*/ dual(2, (self, { onFailure, onSuccess }) => isFailure$1(self) ? onFailure(self.failure) : onSuccess(self.success));
5630
+ const match$3 = /*#__PURE__*/ dual(2, (self, { onFailure, onSuccess }) => isFailure$1(self) ? onFailure(self.failure) : onSuccess(self.success));
5662
5631
  //#endregion
5663
5632
  //#region ../../node_modules/.pnpm/effect@4.0.0-beta.74/node_modules/effect/dist/Tuple.js
5664
5633
  /**
@@ -5725,6 +5694,57 @@ const headUnsafe = (self) => {
5725
5694
  if (result.done) throw new Error("headUnsafe: empty iterable");
5726
5695
  return result.value;
5727
5696
  };
5697
+ /**
5698
+ * Returns the first element that satisfies the specified
5699
+ * predicate, or `None` if no such element exists.
5700
+ *
5701
+ * **Example** (Finding the first match)
5702
+ *
5703
+ * ```ts
5704
+ * import { Iterable, Option } from "effect"
5705
+ *
5706
+ * const numbers = [1, 3, 4, 6, 8]
5707
+ * const firstEven = Iterable.findFirst(numbers, (x) => x % 2 === 0)
5708
+ * console.log(firstEven) // Option.some(4)
5709
+ *
5710
+ * const firstGreaterThan10 = Iterable.findFirst(numbers, (x) => x > 10)
5711
+ * console.log(firstGreaterThan10) // Option.none()
5712
+ *
5713
+ * // With index
5714
+ * const letters = ["a", "b", "c", "d"]
5715
+ * const atEvenIndex = Iterable.findFirst(letters, (_, i) => i % 2 === 0)
5716
+ * console.log(atEvenIndex) // Option.some("a")
5717
+ *
5718
+ * // Type refinement
5719
+ * const mixed: Array<string | number> = [1, "hello", 2, "world"]
5720
+ * const firstString = Iterable.findFirst(
5721
+ * mixed,
5722
+ * (x): x is string => typeof x === "string"
5723
+ * )
5724
+ * console.log(firstString) // Option.some("hello")
5725
+ *
5726
+ * // Transform during search
5727
+ * const findSquareRoot = Iterable.findFirst([1, 4, 9, 16], (x) => {
5728
+ * const sqrt = Math.sqrt(x)
5729
+ * return Number.isInteger(sqrt) ? Option.some(sqrt) : Option.none()
5730
+ * })
5731
+ * console.log(findSquareRoot) // Option.some(1)
5732
+ * ```
5733
+ *
5734
+ * @category elements
5735
+ * @since 2.0.0
5736
+ */
5737
+ const findFirst$3 = /*#__PURE__*/ dual(2, (self, f) => {
5738
+ let i = 0;
5739
+ for (const a of self) {
5740
+ const o = f(a, i);
5741
+ if (isBoolean(o)) {
5742
+ if (o) return some(a);
5743
+ } else if (isSome(o)) return o;
5744
+ i++;
5745
+ }
5746
+ return none();
5747
+ });
5728
5748
  const constEmpty = { [Symbol.iterator]() {
5729
5749
  return constEmptyIterator;
5730
5750
  } };
@@ -6034,6 +6054,61 @@ const Array$1 = globalThis.Array;
6034
6054
  */
6035
6055
  const allocate = (n) => new Array$1(n);
6036
6056
  /**
6057
+ * Creates a `NonEmptyArray` of length `n` where element `i` is computed by `f(i)`.
6058
+ *
6059
+ * **When to use**
6060
+ *
6061
+ * Use when you need an array whose values depend on the index.
6062
+ * - `n` is normalized to an integer >= 1 — always returns at least one element.
6063
+ * - Dual: `Array.makeBy(5, f)` or `pipe(5, Array.makeBy(f))`.
6064
+ *
6065
+ * **Example** (Generating values from indices)
6066
+ *
6067
+ * ```ts
6068
+ * import { Array } from "effect"
6069
+ *
6070
+ * const result = Array.makeBy(5, (n) => n * 2)
6071
+ * console.log(result) // [0, 2, 4, 6, 8]
6072
+ * ```
6073
+ *
6074
+ * @see {@link range} — create a range of integers
6075
+ * @see {@link replicate} — repeat a single value
6076
+ *
6077
+ * @category constructors
6078
+ * @since 2.0.0
6079
+ */
6080
+ const makeBy = /*#__PURE__*/ dual(2, (n, f) => {
6081
+ const max = Math.max(1, Math.floor(n));
6082
+ const out = new Array$1(max);
6083
+ for (let i = 0; i < max; i++) out[i] = f(i);
6084
+ return out;
6085
+ });
6086
+ /**
6087
+ * Creates a `NonEmptyArray` containing a range of integers, inclusive on both
6088
+ * ends.
6089
+ *
6090
+ * **When to use**
6091
+ *
6092
+ * Use when you need a sequence of consecutive integers.
6093
+ * - If `start > end`, returns `[start]`.
6094
+ * - Always returns a `NonEmptyArray`.
6095
+ *
6096
+ * **Example** (Creating a range)
6097
+ *
6098
+ * ```ts
6099
+ * import { Array } from "effect"
6100
+ *
6101
+ * const result = Array.range(1, 3)
6102
+ * console.log(result) // [1, 2, 3]
6103
+ * ```
6104
+ *
6105
+ * @see {@link makeBy} — generate values from a function
6106
+ *
6107
+ * @category constructors
6108
+ * @since 2.0.0
6109
+ */
6110
+ const range = (start, end) => start <= end ? makeBy(end - start + 1, (i) => start + i) : [start];
6111
+ /**
6037
6112
  * Converts an `Iterable` to an `Array`.
6038
6113
  *
6039
6114
  * **When to use**
@@ -6121,7 +6196,7 @@ const ensure = (self) => Array$1.isArray(self) ? self : [self];
6121
6196
  * @category pattern matching
6122
6197
  * @since 2.0.0
6123
6198
  */
6124
- const match$3 = /*#__PURE__*/ dual(2, (self, { onEmpty, onNonEmpty }) => isReadonlyArrayNonEmpty(self) ? onNonEmpty(self) : onEmpty());
6199
+ const match$2 = /*#__PURE__*/ dual(2, (self, { onEmpty, onNonEmpty }) => isReadonlyArrayNonEmpty(self) ? onNonEmpty(self) : onEmpty());
6125
6200
  /**
6126
6201
  * Adds a single element to the end of an iterable, returning a `NonEmptyArray`.
6127
6202
  *
@@ -6313,7 +6388,7 @@ const clamp = (i, as) => Math.floor(Math.min(Math.max(0, i), as.length));
6313
6388
  */
6314
6389
  const get$10 = /*#__PURE__*/ dual(2, (self, index) => {
6315
6390
  const i = Math.floor(index);
6316
- return isOutOfBounds(i, self) ? none() : some$1(self[i]);
6391
+ return isOutOfBounds(i, self) ? none() : some(self[i]);
6317
6392
  });
6318
6393
  /**
6319
6394
  * Reads an element at the given index, throwing if the index is out of bounds.
@@ -6417,7 +6492,7 @@ const headNonEmpty = /*#__PURE__*/ getUnsafe$1(0);
6417
6492
  * @category getters
6418
6493
  * @since 2.0.0
6419
6494
  */
6420
- const last = (self) => isReadonlyArrayNonEmpty(self) ? some$1(lastNonEmpty(self)) : none();
6495
+ const last = (self) => isReadonlyArrayNonEmpty(self) ? some(lastNonEmpty(self)) : none();
6421
6496
  /**
6422
6497
  * Returns the last element of a `NonEmptyReadonlyArray` directly (no `Option`
6423
6498
  * wrapper).
@@ -6464,77 +6539,98 @@ const lastNonEmpty = (self) => self[self.length - 1];
6464
6539
  */
6465
6540
  const tailNonEmpty = (self) => self.slice(1);
6466
6541
  /**
6467
- * Takes elements from the start while the predicate holds, stopping at the
6468
- * first element that fails.
6542
+ * Removes the first `n` elements, creating a new array.
6469
6543
  *
6470
6544
  * **When to use**
6471
6545
  *
6472
- * Use to keep the leading elements of an iterable while each element satisfies
6473
- * a predicate, returning the retained prefix as an array.
6546
+ * Use to keep the suffix of an iterable after skipping a fixed number of
6547
+ * leading elements.
6474
6548
  *
6475
6549
  * **Details**
6476
6550
  *
6477
- * - Supports refinements for type narrowing.
6478
- * - The predicate receives `(element, index)`.
6551
+ * - `n` is clamped to `[0, length]`.
6552
+ * - Returns a copy of the full array when `n <= 0`.
6479
6553
  *
6480
- * **Example** (Taking while condition holds)
6554
+ * **Example** (Dropping from the start)
6481
6555
  *
6482
6556
  * ```ts
6483
6557
  * import { Array } from "effect"
6484
6558
  *
6485
- * console.log(Array.takeWhile([1, 3, 2, 4, 1, 2], (x) => x < 4)) // [1, 3, 2]
6559
+ * console.log(Array.drop([1, 2, 3, 4, 5], 2)) // [3, 4, 5]
6486
6560
  * ```
6487
6561
  *
6488
- * @see {@link take} for keeping a fixed number of leading elements
6489
- * @see {@link dropWhile} for removing the matching prefix and keeping the rest
6490
- * @see {@link span} for splitting the matching prefix from the remaining elements
6562
+ * @see {@link dropRight} for removing a fixed number of elements from the end
6563
+ * @see {@link dropWhile} for removing a prefix based on a predicate instead of a fixed count
6564
+ * @see {@link take} for keeping a fixed number of elements from the start
6491
6565
  *
6492
6566
  * @category getters
6493
6567
  * @since 2.0.0
6494
6568
  */
6495
- const takeWhile = /*#__PURE__*/ dual(2, (self, predicate) => {
6496
- let i = 0;
6497
- const out = [];
6498
- for (const a of self) {
6499
- if (!predicate(a, i)) break;
6500
- out.push(a);
6501
- i++;
6502
- }
6503
- return out;
6569
+ const drop$1 = /*#__PURE__*/ dual(2, (self, n) => {
6570
+ const input = fromIterable$2(self);
6571
+ return input.slice(clamp(n, input), input.length);
6504
6572
  });
6505
6573
  /**
6506
- * Removes the first `n` elements, creating a new array.
6574
+ * Removes the last `n` elements, creating a new array.
6507
6575
  *
6508
6576
  * **When to use**
6509
6577
  *
6510
- * Use to keep the suffix of an iterable after skipping a fixed number of
6511
- * leading elements.
6578
+ * Use to remove the last `n` elements from an iterable.
6512
6579
  *
6513
6580
  * **Details**
6514
6581
  *
6515
- * - `n` is clamped to `[0, length]`.
6516
- * - Returns a copy of the full array when `n <= 0`.
6582
+ * `n` is clamped to `[0, length]`.
6517
6583
  *
6518
- * **Example** (Dropping from the start)
6584
+ * **Example** (Dropping from the end)
6519
6585
  *
6520
6586
  * ```ts
6521
6587
  * import { Array } from "effect"
6522
6588
  *
6523
- * console.log(Array.drop([1, 2, 3, 4, 5], 2)) // [3, 4, 5]
6589
+ * console.log(Array.dropRight([1, 2, 3, 4, 5], 2)) // [1, 2, 3]
6524
6590
  * ```
6525
6591
  *
6526
- * @see {@link dropRight} for removing a fixed number of elements from the end
6527
- * @see {@link dropWhile} for removing a prefix based on a predicate instead of a fixed count
6528
- * @see {@link take} for keeping a fixed number of elements from the start
6592
+ * @see {@link drop} remove from the start
6593
+ * @see {@link takeRight} keep from the end
6529
6594
  *
6530
6595
  * @category getters
6531
6596
  * @since 2.0.0
6532
6597
  */
6533
- const drop$1 = /*#__PURE__*/ dual(2, (self, n) => {
6598
+ const dropRight = /*#__PURE__*/ dual(2, (self, n) => {
6534
6599
  const input = fromIterable$2(self);
6535
- return input.slice(clamp(n, input), input.length);
6600
+ return input.slice(0, input.length - clamp(n, input));
6536
6601
  });
6537
6602
  /**
6603
+ * Returns the first element matching a predicate, refinement, or mapping
6604
+ * function, wrapped in `Option`.
6605
+ *
6606
+ * **When to use**
6607
+ *
6608
+ * Use to scan an iterable in iteration order and return the first selected
6609
+ * element or mapped value as an `Option`.
6610
+ *
6611
+ * **Details**
6612
+ *
6613
+ * - Accepts a predicate `(a, i) => boolean`, a refinement, or a function
6614
+ * `(a, i) => Option<B>` for simultaneous find-and-transform.
6615
+ * - Returns `Option.none()` if no element matches.
6616
+ *
6617
+ * **Example** (Finding the first match)
6618
+ *
6619
+ * ```ts
6620
+ * import { Array } from "effect"
6621
+ *
6622
+ * console.log(Array.findFirst([1, 2, 3, 4, 5], (x) => x > 3)) // Option.some(4)
6623
+ * ```
6624
+ *
6625
+ * @see {@link findLast} — search from the end
6626
+ * @see {@link findFirstIndex} — get the index instead
6627
+ * @see {@link findFirstWithIndex} — get both element and index
6628
+ *
6629
+ * @category elements
6630
+ * @since 2.0.0
6631
+ */
6632
+ const findFirst$2 = findFirst$3;
6633
+ /**
6538
6634
  * Reverses an iterable into a new array.
6539
6635
  *
6540
6636
  * **When to use**
@@ -6841,35 +6937,6 @@ const getSomes = (self) => {
6841
6937
  return out;
6842
6938
  };
6843
6939
  /**
6844
- * Extracts all success values from an iterable of `Result`s, discarding
6845
- * failures.
6846
- *
6847
- * **When to use**
6848
- *
6849
- * Use to collect only success values from `Result` values while discarding
6850
- * failures.
6851
- *
6852
- * **Example** (Extracting successes)
6853
- *
6854
- * ```ts
6855
- * import { Array, Result } from "effect"
6856
- *
6857
- * console.log(Array.getSuccesses([Result.succeed(1), Result.fail("err"), Result.succeed(2)]))
6858
- * // [1, 2]
6859
- * ```
6860
- *
6861
- * @see {@link getFailures} — extract failure values
6862
- * @see {@link separate} — split into failures and successes
6863
- *
6864
- * @category filtering
6865
- * @since 4.0.0
6866
- */
6867
- const getSuccesses = (self) => {
6868
- const out = [];
6869
- for (const a of self) if (isSuccess$1(a)) out.push(a.success);
6870
- return out;
6871
- };
6872
- /**
6873
6940
  * Keeps only elements satisfying a predicate (or refinement).
6874
6941
  *
6875
6942
  * **When to use**
@@ -6895,7 +6962,7 @@ const getSuccesses = (self) => {
6895
6962
  * @category filtering
6896
6963
  * @since 2.0.0
6897
6964
  */
6898
- const filter$2 = /*#__PURE__*/ dual(2, (self, predicate) => {
6965
+ const filter$1 = /*#__PURE__*/ dual(2, (self, predicate) => {
6899
6966
  const as = fromIterable$2(self);
6900
6967
  const out = [];
6901
6968
  for (let i = 0; i < as.length; i++) if (predicate(as[i], i)) out.push(as[i]);
@@ -6952,26 +7019,6 @@ const reduce = /*#__PURE__*/ dual(3, (self, b, f) => fromIterable$2(self).reduce
6952
7019
  */
6953
7020
  const every = /*#__PURE__*/ dual(2, (self, refinement) => self.every(refinement));
6954
7021
  /**
6955
- * Checks whether at least one element satisfies the predicate. Narrows the type
6956
- * to `NonEmptyReadonlyArray` on success.
6957
- *
6958
- * **Example** (Testing for any match)
6959
- *
6960
- * ```ts
6961
- * import { Array } from "effect"
6962
- *
6963
- * console.log(Array.some([1, 3, 4], (x) => x % 2 === 0)) // true
6964
- * console.log(Array.some([1, 3, 5], (x) => x % 2 === 0)) // false
6965
- * ```
6966
- *
6967
- * @see {@link every} — test if all elements match
6968
- * @see {@link contains} — test for a specific value
6969
- *
6970
- * @category elements
6971
- * @since 2.0.0
6972
- */
6973
- const some = /*#__PURE__*/ dual(2, (self, predicate) => self.some(predicate));
6974
- /**
6975
7022
  * Creates an `Equivalence` for arrays based on an element `Equivalence`. Two
6976
7023
  * arrays are equivalent when they have the same length and all elements are
6977
7024
  * pairwise equivalent.
@@ -7617,8 +7664,8 @@ const serviceNotFoundError = (service) => {
7617
7664
  * @since 2.0.0
7618
7665
  */
7619
7666
  const getOption = /*#__PURE__*/ dual(2, (self, service) => {
7620
- if (self.mapUnsafe.has(service.key)) return some$1(self.mapUnsafe.get(service.key));
7621
- return isReference(service) ? some$1(getDefaultValue(service)) : none();
7667
+ if (self.mapUnsafe.has(service.key)) return some(self.mapUnsafe.get(service.key));
7668
+ return isReference(service) ? some(getDefaultValue(service)) : none();
7622
7669
  });
7623
7670
  /**
7624
7671
  * Merges two `Context`s into one.
@@ -8168,7 +8215,7 @@ const weeks = (weeks) => make$61(weeks * 6048e5);
8168
8215
  * @category getters
8169
8216
  * @since 2.0.0
8170
8217
  */
8171
- const toMillis = (self) => match$2(fromInputUnsafe(self), {
8218
+ const toMillis = (self) => match$1(fromInputUnsafe(self), {
8172
8219
  onMillis: identity,
8173
8220
  onNanos: (nanos) => Number(nanos) / 1e6,
8174
8221
  onInfinity: () => Infinity,
@@ -8189,7 +8236,7 @@ const toMillis = (self) => match$2(fromInputUnsafe(self), {
8189
8236
  * @category getters
8190
8237
  * @since 2.0.0
8191
8238
  */
8192
- const toSeconds = (self) => match$2(fromInputUnsafe(self), {
8239
+ const toSeconds = (self) => match$1(fromInputUnsafe(self), {
8193
8240
  onMillis: (millis) => millis / 1e3,
8194
8241
  onNanos: (nanos) => Number(nanos) / 1e9,
8195
8242
  onInfinity: () => Infinity,
@@ -8252,7 +8299,7 @@ const toNanosUnsafe = (input) => {
8252
8299
  * @category pattern matching
8253
8300
  * @since 2.0.0
8254
8301
  */
8255
- const match$2 = /*#__PURE__*/ dual(2, (self, options) => {
8302
+ const match$1 = /*#__PURE__*/ dual(2, (self, options) => {
8256
8303
  switch (self.value._tag) {
8257
8304
  case "Millis": return options.onMillis(self.value.millis);
8258
8305
  case "Nanos": return options.onNanos(self.value.nanos);
@@ -9454,7 +9501,7 @@ const suspend$3 = /*#__PURE__*/ makePrimitive({
9454
9501
  }
9455
9502
  });
9456
9503
  /** @internal */
9457
- const fromResult$1 = /*#__PURE__*/ match$4({
9504
+ const fromResult$1 = /*#__PURE__*/ match$3({
9458
9505
  onFailure: fail$6,
9459
9506
  onSuccess: succeed$6
9460
9507
  });
@@ -9473,7 +9520,7 @@ const yieldNow$1 = /*#__PURE__*/ (/* @__PURE__ */ makePrimitive({
9473
9520
  }
9474
9521
  }))(0);
9475
9522
  /** @internal */
9476
- const succeedSome$1 = (a) => succeed$6(some$1(a));
9523
+ const succeedSome$1 = (a) => succeed$6(some(a));
9477
9524
  /** @internal */
9478
9525
  const succeedNone$1 = /*#__PURE__*/ succeed$6(/*#__PURE__*/ none());
9479
9526
  /** @internal */
@@ -9569,6 +9616,43 @@ const defineFunctionLength = (length, fn) => Object.defineProperty(fn, "length",
9569
9616
  value: length,
9570
9617
  configurable: true
9571
9618
  });
9619
+ const fnStackCleaner = /*#__PURE__*/ makeStackCleaner(2);
9620
+ /** @internal */
9621
+ const fn$1 = function() {
9622
+ const nameFirst = typeof arguments[0] === "string";
9623
+ const name = nameFirst ? arguments[0] : "Effect.fn";
9624
+ const spanOptions = nameFirst ? arguments[1] : void 0;
9625
+ const prevLimit = globalThis.Error.stackTraceLimit;
9626
+ globalThis.Error.stackTraceLimit = 2;
9627
+ const defError = new globalThis.Error();
9628
+ globalThis.Error.stackTraceLimit = prevLimit;
9629
+ if (nameFirst) return (body, ...pipeables) => makeFn(name, body, defError, pipeables, nameFirst, spanOptions);
9630
+ return makeFn(name, arguments[0], defError, Array.prototype.slice.call(arguments, 1), nameFirst, spanOptions);
9631
+ };
9632
+ const makeFn = (name, bodyOrOptions, defError, pipeables, addSpan, spanOptions) => {
9633
+ const body = typeof bodyOrOptions === "function" ? bodyOrOptions : pipeables.pop().bind(bodyOrOptions.self);
9634
+ return defineFunctionLength(body.length, function(...args) {
9635
+ let result = suspend$3(() => {
9636
+ const iter = body.apply(this, arguments);
9637
+ return isEffect$1(iter) ? iter : fromIteratorUnsafe(iter);
9638
+ });
9639
+ for (let i = 0; i < pipeables.length; i++) result = pipeables[i](result, ...args);
9640
+ if (!isEffect$1(result)) return result;
9641
+ const prevLimit = globalThis.Error.stackTraceLimit;
9642
+ globalThis.Error.stackTraceLimit = 2;
9643
+ const callError = new globalThis.Error();
9644
+ globalThis.Error.stackTraceLimit = prevLimit;
9645
+ return updateService$1(addSpan ? useSpan$1(name, spanOptions, (span) => provideParentSpan(result, span)) : result, CurrentStackFrame, (prev) => ({
9646
+ name,
9647
+ stack: fnStackCleaner(() => callError.stack),
9648
+ parent: {
9649
+ name: `${name} (definition)`,
9650
+ stack: fnStackCleaner(() => defError.stack),
9651
+ parent: prev
9652
+ }
9653
+ }));
9654
+ });
9655
+ };
9572
9656
  /** @internal */
9573
9657
  const fnUntracedEager$1 = (body, ...pipeables) => defineFunctionLength(body.length, pipeables.length === 0 ? function() {
9574
9658
  return fromIteratorEagerUnsafe(() => body.apply(this, arguments));
@@ -9628,7 +9712,7 @@ const as$1 = /*#__PURE__*/ dual(2, (self, value) => {
9628
9712
  return flatMap$4(self, (_) => b);
9629
9713
  });
9630
9714
  /** @internal */
9631
- const asSome$1 = (self) => map$6(self, some$1);
9715
+ const asSome = (self) => map$6(self, some);
9632
9716
  /** @internal */
9633
9717
  const andThen$1 = /*#__PURE__*/ dual(2, (self, f) => flatMap$4(self, (a) => isEffect$1(f) ? f : internalCall(() => f(a))));
9634
9718
  /** @internal */
@@ -9745,7 +9829,7 @@ const exitAsVoidAll = (exits) => {
9745
9829
  return failures.length === 0 ? exitVoid : exitFailCause(causeFromReasons(failures));
9746
9830
  };
9747
9831
  /** @internal */
9748
- const exitGetSuccess = (self) => exitIsSuccess(self) ? some$1(self.value) : none();
9832
+ const exitGetSuccess = (self) => exitIsSuccess(self) ? some(self.value) : none();
9749
9833
  /** @internal */
9750
9834
  const service$1 = (service) => service;
9751
9835
  /** @internal */
@@ -9787,7 +9871,7 @@ const provideServiceImpl = (self, service, implementation) => updateContext$1(se
9787
9871
  return add(s, service, implementation);
9788
9872
  });
9789
9873
  /** @internal */
9790
- const when$3 = /*#__PURE__*/ dual(2, (self, condition) => flatMap$4(condition, (pass) => pass ? asSome$1(self) : succeedNone$1));
9874
+ const when$3 = /*#__PURE__*/ dual(2, (self, condition) => flatMap$4(condition, (pass) => pass ? asSome(self) : succeedNone$1));
9791
9875
  /** @internal */
9792
9876
  const forever$1 = /*#__PURE__*/ dual((args) => isEffect$1(args[0]), (self, options) => whileLoop$1({
9793
9877
  while: constTrue,
@@ -9870,9 +9954,9 @@ const ignore$2 = /*#__PURE__*/ dual((args) => isEffect$1(args[0]), (self, option
9870
9954
  });
9871
9955
  });
9872
9956
  /** @internal */
9873
- const option$2 = (self) => match$1(self, {
9957
+ const option$2 = (self) => match(self, {
9874
9958
  onFailure: none,
9875
- onSuccess: some$1
9959
+ onSuccess: some
9876
9960
  });
9877
9961
  /** @internal */
9878
9962
  const result$1 = (self) => matchEager(self, {
@@ -9903,7 +9987,7 @@ const matchEffect$2 = /*#__PURE__*/ dual(2, (self, options) => matchCauseEffect$
9903
9987
  onSuccess: options.onSuccess
9904
9988
  }));
9905
9989
  /** @internal */
9906
- const match$1 = /*#__PURE__*/ dual(2, (self, options) => matchEffect$2(self, {
9990
+ const match = /*#__PURE__*/ dual(2, (self, options) => matchEffect$2(self, {
9907
9991
  onFailure: (error) => sync$1(() => options.onFailure(error)),
9908
9992
  onSuccess: (value) => sync$1(() => options.onSuccess(value))
9909
9993
  }));
@@ -9915,7 +9999,7 @@ const matchEager = /*#__PURE__*/ dual(2, (self, options) => {
9915
9999
  if (isFailure$1(error)) return self;
9916
10000
  return exitSucceed(options.onFailure(error.success));
9917
10001
  }
9918
- return match$1(self, options);
10002
+ return match(self, options);
9919
10003
  });
9920
10004
  /** @internal */
9921
10005
  const exit$1 = (self) => effectIsExit(self) ? exitSucceed(self) : exitPrimitive(self);
@@ -9935,7 +10019,7 @@ const exitPrimitive = /*#__PURE__*/ makePrimitive({
9935
10019
  /** @internal */
9936
10020
  const timeoutOrElse$1 = /*#__PURE__*/ dual(2, (self, options) => raceFirst$1(self, flatMap$4(sleep$1(options.duration), options.orElse)));
9937
10021
  /** @internal */
9938
- const timeoutOption$1 = /*#__PURE__*/ dual(2, (self, duration) => raceFirst$1(asSome$1(self), as$1(sleep$1(duration), none())));
10022
+ const timeoutOption$1 = /*#__PURE__*/ dual(2, (self, duration) => raceFirst$1(asSome(self), as$1(sleep$1(duration), none())));
9939
10023
  /** @internal */
9940
10024
  const ScopeTypeId = "~effect/Scope";
9941
10025
  /** @internal */
@@ -10179,7 +10263,7 @@ const findFirst$1 = /*#__PURE__*/ dual((args) => isIterable(args[0]) && !isEffec
10179
10263
  return succeed$6(none());
10180
10264
  }));
10181
10265
  const findFirstLoop = (iterator, index, predicate, value) => flatMap$4(predicate(value, index), (keep) => {
10182
- if (keep) return succeed$6(some$1(value));
10266
+ if (keep) return succeed$6(some(value));
10183
10267
  const next = iterator.next();
10184
10268
  if (!next.done) return findFirstLoop(iterator, index + 1, predicate, next.value);
10185
10269
  return succeed$6(none());
@@ -10513,12 +10597,12 @@ const NoopSpanProto = {
10513
10597
  const noopSpan = (options) => Object.assign(Object.create(NoopSpanProto), options);
10514
10598
  const filterDisablePropagation = (span) => {
10515
10599
  if (!span) return none();
10516
- return get$9(span.annotations, DisablePropagation) ? span._tag === "Span" ? filterDisablePropagation(getOrUndefined$1(span.parent)) : none() : some$1(span);
10600
+ return get$9(span.annotations, DisablePropagation) ? span._tag === "Span" ? filterDisablePropagation(getOrUndefined$1(span.parent)) : none() : some(span);
10517
10601
  };
10518
10602
  /** @internal */
10519
10603
  const makeSpanUnsafe = (fiber, name, options) => {
10520
10604
  const disablePropagation = !fiber.getRef(TracerEnabled$1) || options?.annotations && get$9(options.annotations, DisablePropagation);
10521
- const parent = options?.parent !== void 0 ? some$1(options.parent) : options?.root ? none() : filterDisablePropagation(fiber.currentSpan);
10605
+ const parent = options?.parent !== void 0 ? some(options.parent) : options?.root ? none() : filterDisablePropagation(fiber.currentSpan);
10522
10606
  let span;
10523
10607
  if (disablePropagation) span = noopSpan({
10524
10608
  name,
@@ -10597,6 +10681,13 @@ const withSpan$1 = function() {
10597
10681
  return (self, ...args) => useSpan$1(name, fnArg ? fnArg(...args) : options, (span) => withParentSpan$1(self, span, traceOptions));
10598
10682
  };
10599
10683
  /** @internal */
10684
+ const annotateCurrentSpan$1 = (...args) => withFiber$1((fiber) => {
10685
+ const span = fiber.currentSpanLocal;
10686
+ if (span) if (args.length === 1) for (const [key, value] of Object.entries(args[0])) span.attribute(key, value);
10687
+ else span.attribute(args[0], args[1]);
10688
+ return void_$3;
10689
+ });
10690
+ /** @internal */
10600
10691
  const ClockRef = /*#__PURE__*/ Reference("effect/Clock", { defaultValue: () => new ClockImpl() });
10601
10692
  const MAX_TIMER_MILLIS = 2 ** 31 - 1;
10602
10693
  var ClockImpl = class {
@@ -13786,12 +13877,12 @@ const nextPow2 = (n) => {
13786
13877
  * @since 2.0.0
13787
13878
  */
13788
13879
  const parse$2 = (s) => {
13789
- if (s === "NaN") return some$1(NaN);
13790
- if (s === "Infinity") return some$1(Infinity);
13791
- if (s === "-Infinity") return some$1(-Infinity);
13880
+ if (s === "NaN") return some(NaN);
13881
+ if (s === "Infinity") return some(Infinity);
13882
+ if (s === "-Infinity") return some(-Infinity);
13792
13883
  if (s.trim() === "") return none();
13793
13884
  const n = Number$4(s);
13794
- return Number$4.isNaN(n) ? none() : some$1(n);
13885
+ return Number$4.isNaN(n) ? none() : some(n);
13795
13886
  };
13796
13887
  globalThis.String;
13797
13888
  /**
@@ -13892,6 +13983,24 @@ const split$1 = /*#__PURE__*/ dual(2, (self, separator) => {
13892
13983
  return isArrayNonEmpty$1(out) ? out : [self];
13893
13984
  });
13894
13985
  /**
13986
+ * Returns `true` if `searchString` appears as a substring of `self`, at one or more positions that are
13987
+ * greater than or equal to `position`; otherwise, returns `false`.
13988
+ *
13989
+ * **Example** (Checking for substrings)
13990
+ *
13991
+ * ```ts
13992
+ * import { pipe, String } from "effect"
13993
+ * import * as assert from "node:assert"
13994
+ *
13995
+ * assert.deepStrictEqual(pipe("hello world", String.includes("world")), true)
13996
+ * assert.deepStrictEqual(pipe("hello world", String.includes("foo")), false)
13997
+ * ```
13998
+ *
13999
+ * @category predicates
14000
+ * @since 2.0.0
14001
+ */
14002
+ const includes = (searchString, position) => (self) => self.includes(searchString, position);
14003
+ /**
13895
14004
  * Returns `true` if the string starts with the specified search string.
13896
14005
  *
13897
14006
  * **Example** (Checking string prefixes)
@@ -15715,24 +15824,6 @@ const map$4 = map$6;
15715
15824
  */
15716
15825
  const as = as$1;
15717
15826
  /**
15718
- * Maps the success value of an `Effect` to `Some`, preserving failures.
15719
- *
15720
- * **Example** (Wrapping success in Option.some)
15721
- *
15722
- * ```ts
15723
- * import { Effect } from "effect"
15724
- *
15725
- * const program = Effect.asSome(Effect.succeed(42))
15726
- *
15727
- * Effect.runPromise(program).then(console.log)
15728
- * // { _id: 'Option', _tag: 'Some', value: 42 }
15729
- * ```
15730
- *
15731
- * @category mapping
15732
- * @since 2.0.0
15733
- */
15734
- const asSome = asSome$1;
15735
- /**
15736
15827
  * Maps the success value of an `Effect` to `void`, preserving failures.
15737
15828
  *
15738
15829
  * **Example** (Discarding success values)
@@ -17477,6 +17568,31 @@ const interruptibleMask = interruptibleMask$1;
17477
17568
  */
17478
17569
  const forever = forever$1;
17479
17570
  /**
17571
+ * Adds an annotation to the current span if available.
17572
+ *
17573
+ * **Example** (Annotating the current span)
17574
+ *
17575
+ * ```ts
17576
+ * import { Effect } from "effect"
17577
+ *
17578
+ * const program = Effect.gen(function*() {
17579
+ * yield* Effect.annotateCurrentSpan("userId", "123")
17580
+ * yield* Effect.annotateCurrentSpan({
17581
+ * operation: "user-lookup",
17582
+ * timestamp: Date.now()
17583
+ * })
17584
+ * yield* Effect.log("User lookup completed")
17585
+ * return "success"
17586
+ * })
17587
+ *
17588
+ * const traced = Effect.withSpan(program, "user-operation")
17589
+ * ```
17590
+ *
17591
+ * @category tracing
17592
+ * @since 2.0.0
17593
+ */
17594
+ const annotateCurrentSpan = annotateCurrentSpan$1;
17595
+ /**
17480
17596
  * Create a new span for tracing, and automatically close it when the effect
17481
17597
  * completes.
17482
17598
  *
@@ -17956,6 +18072,37 @@ const runSyncExit = runSyncExit$1;
17956
18072
  */
17957
18073
  const fnUntraced = fnUntraced$1;
17958
18074
  /**
18075
+ * Creates a traced function with an optional span name and `SpanOptionsNoTrace` that adds spans and stack frames, plus pipeable post-processing that receives the Effect and the original arguments.
18076
+ *
18077
+ * **Details**
18078
+ *
18079
+ * Pipeable functions run after the body and can transform the resulting Effect.
18080
+ *
18081
+ * **Example** (Defining traced effect functions)
18082
+ *
18083
+ * ```ts
18084
+ * import { Console, Effect } from "effect"
18085
+ *
18086
+ * // Create a named span and post-process the returned Effect.
18087
+ * const greet = Effect.fn("greet")(
18088
+ * function*(name: string) {
18089
+ * yield* Console.log(`Hello, ${name}`)
18090
+ * return name.length
18091
+ * },
18092
+ * Effect.map((length) => length + 1)
18093
+ * )
18094
+ *
18095
+ * const program = Effect.gen(function*() {
18096
+ * const result = yield* greet("Ada")
18097
+ * yield* Console.log(`Length: ${result}`)
18098
+ * })
18099
+ * ```
18100
+ *
18101
+ * @category functions
18102
+ * @since 3.11.0
18103
+ */
18104
+ const fn = fn$1;
18105
+ /**
17959
18106
  * Retrieves the `Clock` service from the context and provides it to the
17960
18107
  * specified effectful function.
17961
18108
  *
@@ -19108,14 +19255,14 @@ var OneOf = class extends Base$1 {
19108
19255
  };
19109
19256
  function makeFilterIssue(input, entry) {
19110
19257
  if (isIssue(entry)) return entry;
19111
- if (typeof entry === "string") return new InvalidValue(some$1(input), { message: entry });
19112
- const inner = typeof entry.issue === "string" ? new InvalidValue(some$1(input), { message: entry.issue }) : entry.issue;
19258
+ if (typeof entry === "string") return new InvalidValue(some(input), { message: entry });
19259
+ const inner = typeof entry.issue === "string" ? new InvalidValue(some(input), { message: entry.issue }) : entry.issue;
19113
19260
  return new Pointer(entry.path, inner);
19114
19261
  }
19115
19262
  /** @internal */
19116
19263
  function makeSingle(input, out) {
19117
19264
  if (out === void 0) return;
19118
- if (typeof out === "boolean") return out ? void 0 : new InvalidValue(some$1(input));
19265
+ if (typeof out === "boolean") return out ? void 0 : new InvalidValue(some(input));
19119
19266
  return makeFilterIssue(input, out);
19120
19267
  }
19121
19268
  /** @internal */
@@ -19123,7 +19270,7 @@ function make$55(input, ast, out) {
19123
19270
  if (Array.isArray(out)) {
19124
19271
  if (isReadonlyArrayNonEmpty(out)) {
19125
19272
  if (out.length === 1) return makeFilterIssue(input, out[0]);
19126
- return new Composite(ast, some$1(input), map$7(out, (entry) => makeFilterIssue(input, entry)));
19273
+ return new Composite(ast, some(input), map$7(out, (entry) => makeFilterIssue(input, entry)));
19127
19274
  }
19128
19275
  return;
19129
19276
  }
@@ -19599,8 +19746,8 @@ function transformOptional(f) {
19599
19746
  */
19600
19747
  function withDefault$1(defaultValue) {
19601
19748
  return new Getter((o) => {
19602
- const filtered = filter$3(o, isNotUndefined);
19603
- return isSome(filtered) ? succeed$3(filtered) : mapEager(defaultValue, some$1);
19749
+ const filtered = filter$2(o, isNotUndefined);
19750
+ return isSome(filtered) ? succeed$3(filtered) : mapEager(defaultValue, some);
19604
19751
  });
19605
19752
  }
19606
19753
  /**
@@ -19663,8 +19810,8 @@ function Number$3() {
19663
19810
  }
19664
19811
  function parseJson(options) {
19665
19812
  return onSome((input) => try_({
19666
- try: () => some$1(JSON.parse(input, options?.reviver)),
19667
- catch: (e) => new InvalidValue(some$1(input), { message: globalThis.String(e) })
19813
+ try: () => some(JSON.parse(input, options?.reviver)),
19814
+ catch: (e) => new InvalidValue(some(input), { message: globalThis.String(e) })
19668
19815
  }));
19669
19816
  }
19670
19817
  /**
@@ -19701,8 +19848,8 @@ function parseJson(options) {
19701
19848
  */
19702
19849
  function stringifyJson(options) {
19703
19850
  return onSome((input) => try_({
19704
- try: () => some$1(JSON.stringify(input, options?.replacer, options?.space)),
19705
- catch: (e) => new InvalidValue(some$1(input), { message: globalThis.String(e) })
19851
+ try: () => some(JSON.stringify(input, options?.replacer, options?.space)),
19852
+ catch: (e) => new InvalidValue(some(input), { message: globalThis.String(e) })
19706
19853
  }));
19707
19854
  }
19708
19855
  /**
@@ -20721,7 +20868,7 @@ var Declaration = class Declaration extends Base {
20721
20868
  const run = this.run(this.typeParameters);
20722
20869
  return (oinput, options) => {
20723
20870
  if (isNone(oinput)) return succeedNone;
20724
- return mapEager(run(oinput.value, this, options), some$1);
20871
+ return mapEager(run(oinput.value, this, options), some);
20725
20872
  };
20726
20873
  }
20727
20874
  /** @internal */
@@ -21212,7 +21359,7 @@ var Arrays = class Arrays extends Base {
21212
21359
  else return yield* fail$3(new Composite(ast, oinput, [issue]));
21213
21360
  }
21214
21361
  if (state.issues) return yield* fail$3(new Composite(ast, oinput, state.issues));
21215
- return some$1(state.output);
21362
+ return some(state.output);
21216
21363
  });
21217
21364
  }
21218
21365
  /** @internal */
@@ -21228,7 +21375,7 @@ var Arrays = class Arrays extends Base {
21228
21375
  };
21229
21376
  const parseArray = /*#__PURE__*/ iterateEager()({
21230
21377
  onItem(s, item, i) {
21231
- const value = i < s.len ? some$1(item) : none();
21378
+ const value = i < s.len ? some(item) : none();
21232
21379
  return s.getParser(s.tailThreshold, i).parser(value, s.options);
21233
21380
  },
21234
21381
  step(s, _, exit, i) {
@@ -21432,14 +21579,14 @@ var Objects = class Objects extends Base {
21432
21579
  if (ast.propertySignatures.length === 0 && ast.indexSignatures.length === 0) return fromRefinement(ast, isNotNullish);
21433
21580
  const parseIndexes = indexCount > 0 ? iterateEager()({
21434
21581
  onItem: fnUntracedEager(function* (s, [key, is]) {
21435
- const effKey = recur(indexSignatureParameterFromString(is.parameter))(some$1(key), s.options);
21582
+ const effKey = recur(indexSignatureParameterFromString(is.parameter))(some(key), s.options);
21436
21583
  const exitKey = effectIsExit(effKey) ? effKey : yield* exit(effKey);
21437
21584
  if (exitKey._tag === "Failure") {
21438
21585
  const eff = wrapPropertyKeyIssue(s, ast, key, exitKey);
21439
21586
  if (eff) yield* eff;
21440
21587
  return;
21441
21588
  }
21442
- const value = some$1(s.input[key]);
21589
+ const value = some(s.input[key]);
21443
21590
  const effValue = recur(is.type)(value, s.options);
21444
21591
  const exitValue = effectIsExit(effValue) ? effValue : yield* exit(effValue);
21445
21592
  if (exitValue._tag === "Failure") {
@@ -21509,9 +21656,9 @@ var Objects = class Objects extends Base {
21509
21656
  const keys = (inputKeys ?? Reflect.ownKeys(input)).concat(expectedKeys);
21510
21657
  const preserved = {};
21511
21658
  for (const key of keys) if (Object.hasOwn(out, key)) set$7(preserved, key, out[key]);
21512
- return some$1(preserved);
21659
+ return some(preserved);
21513
21660
  }
21514
- return some$1(out);
21661
+ return some(out);
21515
21662
  });
21516
21663
  }
21517
21664
  rebuild(recur, flipMerge) {
@@ -21543,7 +21690,7 @@ var Objects = class Objects extends Base {
21543
21690
  };
21544
21691
  const parseProperties = /*#__PURE__*/ iterateEager()({
21545
21692
  onItem(s, p) {
21546
- const value = Object.hasOwn(s.input, p.name) ? some$1(s.input[p.name]) : none();
21693
+ const value = Object.hasOwn(s.input, p.name) ? some(s.input[p.name]) : none();
21547
21694
  return p.parser(value, s.options);
21548
21695
  },
21549
21696
  step(s, p, exit) {
@@ -22343,7 +22490,7 @@ function isJson(u) {
22343
22490
  }
22344
22491
  }
22345
22492
  /** @internal */
22346
- const Json = /*#__PURE__*/ new Declaration([], () => (input, ast) => isJson(input) ? succeed$3(input) : fail$3(new InvalidType(ast, some$1(input))), {
22493
+ const Json = /*#__PURE__*/ new Declaration([], () => (input, ast) => isJson(input) ? succeed$3(input) : fail$3(new InvalidType(ast, some(input))), {
22347
22494
  typeConstructor: { _tag: "effect/Json" },
22348
22495
  generation: {
22349
22496
  runtime: `Schema.Json`,
@@ -22376,7 +22523,7 @@ function isStringTree(u) {
22376
22523
  }
22377
22524
  }
22378
22525
  /** @internal */
22379
- const unknownToStringTree = /*#__PURE__*/ new Link(/* @__PURE__ */ new Declaration([], () => (input, ast) => isStringTree(input) ? succeed$3(input) : fail$3(new InvalidType(ast, some$1(input))), {
22526
+ const unknownToStringTree = /*#__PURE__*/ new Link(/* @__PURE__ */ new Declaration([], () => (input, ast) => isStringTree(input) ? succeed$3(input) : fail$3(new InvalidType(ast, some(input))), {
22380
22527
  expected: "StringTree",
22381
22528
  toCodecStringTree: () => new Link(unknown, passthrough())
22382
22529
  }), /*#__PURE__*/ passthrough());
@@ -22397,7 +22544,7 @@ const unknownToStringTree = /*#__PURE__*/ new Link(/* @__PURE__ */ new Declarati
22397
22544
  */
22398
22545
  function nominal() {
22399
22546
  return Object.assign((input) => input, {
22400
- option: (input) => some$1(input),
22547
+ option: (input) => some(input),
22401
22548
  result: (input) => succeed$7(input),
22402
22549
  is: (_) => true
22403
22550
  });
@@ -23209,7 +23356,7 @@ const takeAll$2 = (self) => takeN(self, self.length);
23209
23356
  * @category elements
23210
23357
  * @since 4.0.0
23211
23358
  */
23212
- const take$4 = (self) => {
23359
+ const take$3 = (self) => {
23213
23360
  if (!self.head) return Empty$2;
23214
23361
  const message = self.head.array[self.head.offset];
23215
23362
  if (self.head.mutable) self.head.array[self.head.offset] = void 0;
@@ -23263,7 +23410,7 @@ const take$4 = (self) => {
23263
23410
  * @category mutations
23264
23411
  * @since 4.0.0
23265
23412
  */
23266
- const filter$1 = (self, f) => {
23413
+ const filter = (self, f) => {
23267
23414
  const array = [];
23268
23415
  let chunk = self.head;
23269
23416
  while (chunk) {
@@ -23329,7 +23476,7 @@ const filter$1 = (self, f) => {
23329
23476
  * @category mutations
23330
23477
  * @since 4.0.0
23331
23478
  */
23332
- const remove$5 = (self, value) => filter$1(self, (v) => v !== value);
23479
+ const remove$5 = (self, value) => filter(self, (v) => v !== value);
23333
23480
  //#endregion
23334
23481
  //#region ../../node_modules/.pnpm/effect@4.0.0-beta.74/node_modules/effect/dist/MutableRef.js
23335
23482
  const TypeId$38 = "~effect/MutableRef";
@@ -23911,7 +24058,7 @@ const unsubscribe = (self) => uninterruptible(withFiber((state) => {
23911
24058
  * @category subscriptions
23912
24059
  * @since 4.0.0
23913
24060
  */
23914
- const take$3 = (self) => suspend$2(() => {
24061
+ const take$2 = (self) => suspend$2(() => {
23915
24062
  if (self.shutdownFlag.current) return interrupt$1;
23916
24063
  if (self.replayWindow.remaining > 0) return succeed$3(self.replayWindow.take());
23917
24064
  const message = self.pollers.length === 0 ? self.subscription.poll() : Empty$2;
@@ -24657,7 +24804,7 @@ var BackPressureStrategy = class {
24657
24804
  onPubSubEmptySpaceUnsafe(pubsub, subscribers) {
24658
24805
  let keepPolling = true;
24659
24806
  while (keepPolling && !pubsub.isFull()) {
24660
- const publisher = take$4(this.publishers);
24807
+ const publisher = take$3(this.publishers);
24661
24808
  if (publisher === Empty$2) keepPolling = false;
24662
24809
  else {
24663
24810
  const [value, deferred] = publisher;
@@ -24696,7 +24843,7 @@ var BackPressureStrategy = class {
24696
24843
  }
24697
24844
  }
24698
24845
  removeUnsafe(deferred) {
24699
- filter$1(this.publishers, ([_, d]) => d !== deferred);
24846
+ filter(this.publishers, ([_, d]) => d !== deferred);
24700
24847
  }
24701
24848
  };
24702
24849
  /**
@@ -24769,7 +24916,7 @@ var DroppingStrategy = class {
24769
24916
  const strategyCompletePollersUnsafe = (strategy, pubsub, subscribers, subscription, pollers) => {
24770
24917
  let keepPolling = true;
24771
24918
  while (keepPolling && !subscription.isEmpty()) {
24772
- const poller = take$4(pollers);
24919
+ const poller = take$3(pollers);
24773
24920
  if (poller === Empty$2) {
24774
24921
  removeSubscribers(subscribers, subscription, pollers);
24775
24922
  if (pollers.length === 0) keepPolling = false;
@@ -25155,7 +25302,7 @@ const offer = (self, message) => suspend$3(() => {
25155
25302
  }
25156
25303
  return offerRemainingSingle(self, message);
25157
25304
  case "sliding":
25158
- take$4(self.messages);
25305
+ take$3(self.messages);
25159
25306
  append(self.messages, message);
25160
25307
  return exitTrue;
25161
25308
  }
@@ -25198,7 +25345,7 @@ const offerUnsafe = (self, message) => {
25198
25345
  if (self.state._tag !== "Open") return false;
25199
25346
  else if (self.messages.length >= self.capacity) {
25200
25347
  if (self.strategy === "sliding") {
25201
- take$4(self.messages);
25348
+ take$3(self.messages);
25202
25349
  append(self.messages, message);
25203
25350
  return true;
25204
25351
  } else if (self.capacity <= 0 && self.state.takers.size > 0) {
@@ -25561,7 +25708,7 @@ const takeBetween = (self, min, max) => suspend$3(() => takeBetweenUnsafe(self,
25561
25708
  * @category taking
25562
25709
  * @since 2.0.0
25563
25710
  */
25564
- const take$2 = (self) => suspend$3(() => takeUnsafe(self) ?? andThen$1(awaitTake(self), take$2(self)));
25711
+ const take$1 = (self) => suspend$3(() => takeUnsafe(self) ?? andThen$1(awaitTake(self), take$1(self)));
25565
25712
  /**
25566
25713
  * Attempts to take one message from the queue synchronously.
25567
25714
  *
@@ -25603,14 +25750,14 @@ const take$2 = (self) => suspend$3(() => takeUnsafe(self) ?? andThen$1(awaitTake
25603
25750
  const takeUnsafe = (self) => {
25604
25751
  if (self.state._tag === "Done") return self.state.exit;
25605
25752
  if (self.messages.length > 0) {
25606
- const message = take$4(self.messages);
25753
+ const message = take$3(self.messages);
25607
25754
  releaseCapacity(self);
25608
25755
  return exitSucceed(message);
25609
25756
  } else if (self.capacity <= 0 && self.state.offers.size > 0) {
25610
25757
  self.capacity = 1;
25611
25758
  releaseCapacity(self);
25612
25759
  self.capacity = 0;
25613
- const message = take$4(self.messages);
25760
+ const message = take$3(self.messages);
25614
25761
  releaseCapacity(self);
25615
25762
  return exitSucceed(message);
25616
25763
  }
@@ -25682,7 +25829,7 @@ const takeBetweenUnsafe = (self, min, max) => {
25682
25829
  self.capacity = 1;
25683
25830
  releaseCapacity(self);
25684
25831
  self.capacity = 0;
25685
- const messages = [take$4(self.messages)];
25832
+ const messages = [take$3(self.messages)];
25686
25833
  releaseCapacity(self);
25687
25834
  return exitSucceed(messages);
25688
25835
  }
@@ -25862,7 +26009,7 @@ var SemaphoreImpl = class {
25862
26009
  return (self) => uninterruptibleMask$1((restore) => {
25863
26010
  if (this.free < n) return succeedNone$1;
25864
26011
  this.taken += n;
25865
- return onExitPrimitive$1(restore(asSome$1(self)), () => {
26012
+ return onExitPrimitive$1(restore(asSome(self)), () => {
25866
26013
  this.updateTakenUnsafe(getCurrentFiber(), (taken) => taken - n);
25867
26014
  }, true);
25868
26015
  });
@@ -26244,7 +26391,7 @@ const fromIteratorArray = (iterator, chunkSize = DefaultChunkSize) => fromPull$1
26244
26391
  const state = iter.next();
26245
26392
  if (state.done) {
26246
26393
  if (buffer.length === 0) return done(state.value);
26247
- done$15 = some$1(state.value);
26394
+ done$15 = some(state.value);
26248
26395
  break;
26249
26396
  }
26250
26397
  buffer.push(state.value);
@@ -26284,7 +26431,7 @@ const fromIterableArray = (iterable, chunkSize = DefaultChunkSize) => fromIterat
26284
26431
  * @category constructors
26285
26432
  * @since 2.0.0
26286
26433
  */
26287
- const succeed$2 = (value) => fromEffect(succeed$3(value));
26434
+ const succeed$2 = (value) => fromEffect$1(succeed$3(value));
26288
26435
  /**
26289
26436
  * Represents a `Channel` that emits no elements.
26290
26437
  *
@@ -26427,7 +26574,7 @@ const die = (defect) => failCause(die$2(defect));
26427
26574
  * @category constructors
26428
26575
  * @since 2.0.0
26429
26576
  */
26430
- const fromEffect = (effect) => fromPull$1(sync(() => {
26577
+ const fromEffect$1 = (effect) => fromPull$1(sync(() => {
26431
26578
  let done$14 = false;
26432
26579
  return suspend$2(() => {
26433
26580
  if (done$14) return done();
@@ -26841,7 +26988,7 @@ const mapEffectConcurrent = (self, f, options) => fromTransformBracket(fnUntrace
26841
26988
  } else {
26842
26989
  const effects = yield* bounded(concurrencyN - 2);
26843
26990
  yield* addFinalizer$1(forkedScope, shutdown(queue));
26844
- yield* take$2(effects).pipe(flatten$1, flatMap$2((value) => offer(queue, value)), forever({ disableYield: true }), catchCause$1((cause) => failCause$1(queue, cause)), forkIn(forkedScope));
26991
+ yield* take$1(effects).pipe(flatten$1, flatMap$2((value) => offer(queue, value)), forever({ disableYield: true }), catchCause$1((cause) => failCause$1(queue, cause)), forkIn(forkedScope));
26845
26992
  let errorCause;
26846
26993
  const onExit = (exit) => {
26847
26994
  if (exit._tag === "Success") return;
@@ -26856,7 +27003,7 @@ const mapEffectConcurrent = (self, f, options) => fromTransformBracket(fnUntrace
26856
27003
  return offer(effects, join$1(fiber));
26857
27004
  }), forever({ disableYield: true }), catchCause$1((cause) => offer(effects, failCause$3(cause)).pipe(andThen(failCause$1(effects, cause)))), forkIn(forkedScope));
26858
27005
  }
26859
- return take$2(queue);
27006
+ return take$1(queue);
26860
27007
  }));
26861
27008
  /**
26862
27009
  * Maps each output element to a channel and flattens the child channel
@@ -26966,47 +27113,6 @@ const flattenArray = (self) => transformPull$1(self, (pull) => {
26966
27113
  }));
26967
27114
  });
26968
27115
  /**
26969
- * Filters arrays of elements emitted by a channel, applying the filter
26970
- * to each element within the arrays and only emitting non-empty filtered arrays.
26971
- *
26972
- * **Example** (Filtering array output)
26973
- *
26974
- * ```ts
26975
- * import { Array, Channel } from "effect"
26976
- *
26977
- * const nonEmptyArrayPredicate = Array.isReadonlyArrayNonEmpty
26978
- *
26979
- * // Create a channel that outputs arrays of mixed data
26980
- * const arrayChannel = Channel.fromIterable([
26981
- * Array.make(1, 2, 3, 4, 5),
26982
- * Array.make(6, 7, 8, 9, 10),
26983
- * Array.make(11, 12, 13, 14, 15)
26984
- * ]).pipe(Channel.filter(nonEmptyArrayPredicate))
26985
- *
26986
- * // Filter arrays to keep only even numbers
26987
- * const evenArraysChannel = Channel.filterArray(arrayChannel, (n) => n % 2 === 0)
26988
- * // Outputs: [2, 4], [6, 8, 10], [12, 14]
26989
- * // Note: Only non-empty filtered arrays are emitted
26990
- *
26991
- * // Arrays that would become empty after filtering are discarded entirely
26992
- * const oddChannel = Channel.fromIterable([
26993
- * Array.make(1, 3, 5),
26994
- * Array.make(2, 4),
26995
- * Array.make(7, 9)
26996
- * ]).pipe(Channel.filter(nonEmptyArrayPredicate))
26997
- * const filteredOddChannel = Channel.filterArray(oddChannel, (n) => n % 2 === 0)
26998
- * // Outputs: [2, 4] (the arrays [1,3,5] and [7,9] are discarded)
26999
- * ```
27000
- *
27001
- * @category filtering
27002
- * @since 4.0.0
27003
- */
27004
- const filterArray = /*#__PURE__*/ dual(2, (self, predicate) => transformPull$1(self, (pull) => succeed$3(flatMap$2(pull, function loop(arr) {
27005
- const passes = [];
27006
- for (let i = 0; i < arr.length; i++) if (predicate(arr[i])) passes.push(arr[i]);
27007
- return isReadonlyArrayNonEmpty(passes) ? succeed$3(passes) : flatMap$2(pull, loop);
27008
- }))));
27009
- /**
27010
27116
  * Catches any cause of failure from the channel and allows recovery by
27011
27117
  * creating a new channel based on the caught cause.
27012
27118
  *
@@ -27175,7 +27281,7 @@ const mergeAll = /*#__PURE__*/ dual(2, (channels, { bufferSize = 16, concurrency
27175
27281
  fibers.add(fiber);
27176
27282
  }
27177
27283
  }).pipe(catchCause$1((cause) => doneLatch.whenOpen(failCause$1(queue, cause))), forkIn(forkedScope));
27178
- return take$2(queue);
27284
+ return take$1(queue);
27179
27285
  })));
27180
27286
  /**
27181
27287
  * Returns a new channel, which is the merge of this channel and the specified
@@ -27224,7 +27330,7 @@ const merge$2 = /*#__PURE__*/ dual((args) => isChannel(args[0]) && isChannel(arg
27224
27330
  const runSide = (side, channel, scope) => toTransform(channel)(upstream, scope).pipe(flatMap$2((pull) => pull.pipe(flatMap$2((value) => offer(queue, value)), forever)), onError((cause) => andThen(close(scope, doneExitFromCause(cause)), onExit(side, cause))), forkIn(forkedScope));
27225
27331
  yield* runSide("left", left, forkUnsafe(forkedScope));
27226
27332
  yield* runSide("right", right, forkUnsafe(forkedScope));
27227
- return take$2(queue);
27333
+ return take$1(queue);
27228
27334
  })));
27229
27335
  /**
27230
27336
  * Splits upstream string chunks into lines, recognizing `\n`, `\r\n`, and
@@ -27306,7 +27412,7 @@ const splitLines$1 = () => fromTransform$1((upstream, _scope) => sync(() => {
27306
27412
  onSuccess: loop,
27307
27413
  onFailure: failCause$2,
27308
27414
  onDone: (leftover) => {
27309
- done$13 = some$1(leftover);
27415
+ done$13 = some(leftover);
27310
27416
  if (stringBuilder.length > 0 || midCRLF) {
27311
27417
  const last = stringBuilder;
27312
27418
  stringBuilder = "";
@@ -27464,35 +27570,6 @@ const runWith = (self, f, onHalt) => suspend$2(() => {
27464
27570
  */
27465
27571
  const provideContext$1 = /*#__PURE__*/ dual(2, (self, context) => fromTransform$1((upstream, scope) => map$4(provideContext$2(toTransform(self)(upstream, scope), context), provideContext$2(context))));
27466
27572
  /**
27467
- * Runs a channel and discards all output elements, returning only the final result.
27468
- *
27469
- * **Example** (Draining channel output at runtime)
27470
- *
27471
- * ```ts
27472
- * import { Channel, Data } from "effect"
27473
- *
27474
- * class DrainError extends Data.TaggedError("DrainError")<{
27475
- * readonly stage: string
27476
- * }> {}
27477
- *
27478
- * // Create a channel that outputs elements and completes with a result
27479
- * const resultChannel = Channel.fromIterable([1, 2, 3])
27480
- * const completedChannel = Channel.concatWith(
27481
- * resultChannel,
27482
- * () => Channel.succeed("completed")
27483
- * )
27484
- *
27485
- * // Drain all elements and get only the final result
27486
- * const drainEffect = Channel.runDrain(completedChannel)
27487
- *
27488
- * // Effect.runSync(drainEffect) // Returns: "completed"
27489
- * ```
27490
- *
27491
- * @category execution
27492
- * @since 2.0.0
27493
- */
27494
- const runDrain$1 = (self) => runWith(self, (pull) => forever(pull, { disableYield: true }));
27495
- /**
27496
27573
  * Runs a channel and applies an effect to each output element.
27497
27574
  *
27498
27575
  * **Example** (Running effects for each output)
@@ -27711,7 +27788,7 @@ const drain = /*#__PURE__*/ fromTransform((upstream) => catchDone(forever(upstre
27711
27788
  * @category collecting
27712
27789
  * @since 2.0.0
27713
27790
  */
27714
- const take$1 = (n) => fromTransform((upstream) => {
27791
+ const take = (n) => fromTransform((upstream) => {
27715
27792
  const taken = [];
27716
27793
  if (n <= 0) return succeed$3([taken]);
27717
27794
  let leftover = void 0;
@@ -27910,10 +27987,10 @@ const empty$9 = () => {
27910
27987
  * @since 2.0.0
27911
27988
  */
27912
27989
  const get$7 = /*#__PURE__*/ dual(2, (self, key) => {
27913
- if (self.backing.has(key)) return some$1(self.backing.get(key));
27990
+ if (self.backing.has(key)) return some(self.backing.get(key));
27914
27991
  else if (isSimpleKey(key)) return none();
27915
27992
  const refKey = referentialKeysCache.get(self);
27916
- if (refKey !== void 0) return self.backing.has(refKey) ? some$1(self.backing.get(refKey)) : none();
27993
+ if (refKey !== void 0) return self.backing.has(refKey) ? some(self.backing.get(refKey)) : none();
27917
27994
  const hash$5 = hash(key);
27918
27995
  const bucket = self.buckets.get(hash$5);
27919
27996
  if (bucket === void 0) return none();
@@ -27925,7 +28002,7 @@ const getFromBucket = (self, bucket, key) => {
27925
28002
  for (let i = 0, len = bucket.length; i < len; i++) if (equals$2(key, bucket[i])) {
27926
28003
  const refKey = bucket[i];
27927
28004
  referentialKeysCache.set(key, refKey);
27928
- return some$1(self.backing.get(refKey));
28005
+ return some(self.backing.get(refKey));
27929
28006
  }
27930
28007
  return none();
27931
28008
  };
@@ -28364,6 +28441,56 @@ const release = (self, key, entry) => withFiber((fiber) => {
28364
28441
  })), runForkWith(fiber.context), runIn(self.scope));
28365
28442
  return void_$1;
28366
28443
  });
28444
+ /**
28445
+ * Invalidates and removes a specific key from the RcMap. If the resource is not
28446
+ * currently in use (reference count is 0), it will be immediately released.
28447
+ *
28448
+ * **When to use**
28449
+ *
28450
+ * Use to remove a resource by key so the next access performs a fresh lookup.
28451
+ *
28452
+ * **Example** (Invalidating a resource)
28453
+ *
28454
+ * ```ts
28455
+ * import { Effect, RcMap } from "effect"
28456
+ *
28457
+ * Effect.gen(function*() {
28458
+ * const map = yield* RcMap.make({
28459
+ * lookup: (key: string) =>
28460
+ * Effect.acquireRelease(
28461
+ * Effect.succeed(`Resource: ${key}`),
28462
+ * () => Effect.log(`Released ${key}`)
28463
+ * )
28464
+ * })
28465
+ *
28466
+ * // Get a resource
28467
+ * yield* RcMap.get(map, "cache")
28468
+ *
28469
+ * // Invalidate the resource - it will be removed from the map
28470
+ * // and released if no longer in use
28471
+ * yield* RcMap.invalidate(map, "cache")
28472
+ *
28473
+ * // Next access will create a new resource
28474
+ * yield* RcMap.get(map, "cache")
28475
+ * }).pipe(Effect.scoped)
28476
+ * ```
28477
+ *
28478
+ * @see {@link get} for acquiring or retaining the resource for a key
28479
+ * @see {@link touch} for extending the idle lifetime without removing the entry
28480
+ *
28481
+ * @category combinators
28482
+ * @since 3.13.0
28483
+ */
28484
+ const invalidate = /*#__PURE__*/ dual(2, /*#__PURE__*/ fnUntraced(function* (self, key) {
28485
+ if (self.state._tag === "Closed") return;
28486
+ const o = get$7(self.state.map, key);
28487
+ if (o._tag === "None") return;
28488
+ const entry = o.value;
28489
+ remove$4(self.state.map, key);
28490
+ if (entry.refCount > 0) return;
28491
+ if (entry.fiber) yield* interrupt(entry.fiber);
28492
+ yield* close(entry.scope, void_$2);
28493
+ }, uninterruptible));
28367
28494
  //#endregion
28368
28495
  //#region ../../node_modules/.pnpm/effect@4.0.0-beta.74/node_modules/effect/dist/internal/rcRef.js
28369
28496
  const TypeId$30 = "~effect/RcRef";
@@ -28688,6 +28815,28 @@ const isStream = (u) => hasProperty(u, TypeId$29);
28688
28815
  */
28689
28816
  const fromChannel = fromChannel$2;
28690
28817
  /**
28818
+ * Creates a stream from an effect.
28819
+ *
28820
+ * **Example** (Creating a stream from an effect)
28821
+ *
28822
+ * ```ts
28823
+ * import { Console, Effect, Stream } from "effect"
28824
+ *
28825
+ * const program = Effect.gen(function*() {
28826
+ * const stream = Stream.fromEffect(Effect.succeed(42))
28827
+ * const values = yield* Stream.runCollect(stream)
28828
+ * yield* Console.log(values)
28829
+ * })
28830
+ *
28831
+ * Effect.runPromise(program)
28832
+ * // Output: [ 42 ]
28833
+ * ```
28834
+ *
28835
+ * @category constructors
28836
+ * @since 2.0.0
28837
+ */
28838
+ const fromEffect = (effect) => fromChannel(fromEffect$1(map$4(effect, of)));
28839
+ /**
28691
28840
  * Creates a stream from an effect producing a value of type `A` which repeats forever.
28692
28841
  *
28693
28842
  * **Example** (Repeating an effect forever)
@@ -29313,30 +29462,6 @@ const concat = /*#__PURE__*/ dual(2, (self, that) => flatten(fromArray([self, th
29313
29462
  * @since 2.0.0
29314
29463
  */
29315
29464
  const merge$1 = /*#__PURE__*/ dual((args) => isStream(args[0]) && isStream(args[1]), (self, that, options) => fromChannel(merge$2(toChannel(self), toChannel(that), options)));
29316
- /**
29317
- * Filters a stream to the elements that satisfy a predicate.
29318
- *
29319
- * **Example** (Filtering stream values)
29320
- *
29321
- * ```ts
29322
- * import { Console, Effect, Stream } from "effect"
29323
- *
29324
- * const program = Effect.gen(function*() {
29325
- * const stream = Stream.make(1, 2, 3, 4).pipe(
29326
- * Stream.filter((n) => n % 2 === 0)
29327
- * )
29328
- * const values = yield* Stream.runCollect(stream)
29329
- * yield* Console.log(values)
29330
- * })
29331
- *
29332
- * Effect.runPromise(program)
29333
- * // Output: [ 2, 4 ]
29334
- * ```
29335
- *
29336
- * @category filtering
29337
- * @since 2.0.0
29338
- */
29339
- const filter = /*#__PURE__*/ dual(2, (self, predicate) => fromChannel(filterArray(toChannel(self), predicate)));
29340
29465
  const catch_ = /*#__PURE__*/ dual(2, (self, f) => fromChannel(catch_$1(self.channel, (error) => f(error).channel)));
29341
29466
  /**
29342
29467
  * Turns typed failures into defects, making the stream infallible.
@@ -29364,30 +29489,6 @@ const catch_ = /*#__PURE__*/ dual(2, (self, f) => fromChannel(catch_$1(self.chan
29364
29489
  */
29365
29490
  const orDie = (self) => fromChannel(orDie$1(self.channel));
29366
29491
  /**
29367
- * Takes the first `n` elements from this stream, returning `Stream.empty` when `n < 1`.
29368
- *
29369
- * **Example** (Taking values from the left)
29370
- *
29371
- * ```ts
29372
- * import { Console, Effect, Stream } from "effect"
29373
- *
29374
- * const program = Effect.gen(function*() {
29375
- * const values = yield* Stream.make(1, 2, 3, 4, 5).pipe(
29376
- * Stream.take(3),
29377
- * Stream.runCollect
29378
- * )
29379
- * yield* Console.log(values)
29380
- * })
29381
- *
29382
- * Effect.runPromise(program)
29383
- * // Output: [ 1, 2, 3 ]
29384
- * ```
29385
- *
29386
- * @category filtering
29387
- * @since 2.0.0
29388
- */
29389
- const take = /*#__PURE__*/ dual(2, (self, n) => n < 1 ? empty$8 : takeUntil(self, (_, i) => i === n - 1));
29390
- /**
29391
29492
  * Takes elements until the predicate matches.
29392
29493
  *
29393
29494
  * **Details**
@@ -29563,7 +29664,7 @@ const debounce = /*#__PURE__*/ dual(2, (self, duration) => transformPull(self, f
29563
29664
  * @category grouping
29564
29665
  * @since 2.0.0
29565
29666
  */
29566
- const groupedWithin = /*#__PURE__*/ dual(3, (self, chunkSize, duration) => aggregateWithin(self, take$1(chunkSize), spaced(duration)));
29667
+ const groupedWithin = /*#__PURE__*/ dual(3, (self, chunkSize, duration) => aggregateWithin(self, take(chunkSize), spaced(duration)));
29567
29668
  /**
29568
29669
  * Applies a sink transducer to the stream and emits each sink result.
29569
29670
  *
@@ -29651,7 +29752,7 @@ const aggregateWithin = /*#__PURE__*/ dual(3, (self, sink, schedule) => fromChan
29651
29752
  const stepToBuffer = suspend$2(function loop() {
29652
29753
  return step(lastOutput).pipe(flatMap$2(() => !sinkHasInput ? loop() : offer(buffer, scheduleStep)), flatMap$2(() => never$1), catchDone(() => done()));
29653
29754
  });
29654
- const pullFromBuffer = take$2(buffer).pipe(flatMap$2((arr) => {
29755
+ const pullFromBuffer = take$1(buffer).pipe(flatMap$2((arr) => {
29655
29756
  if (arr === scheduleStep) return done();
29656
29757
  sinkHasInput = true;
29657
29758
  return succeed$3(arr);
@@ -29668,7 +29769,7 @@ const aggregateWithin = /*#__PURE__*/ dual(3, (self, sink, schedule) => fromChan
29668
29769
  });
29669
29770
  const catchSinkHalt = flatMap$2(([value, leftover_]) => {
29670
29771
  if (!sinkHasInput && buffer.state._tag === "Done") return done();
29671
- lastOutput = some$1(value);
29772
+ lastOutput = some(value);
29672
29773
  leftover = leftover_;
29673
29774
  return succeed$3(of(value));
29674
29775
  });
@@ -29939,32 +30040,6 @@ const runForEach = /*#__PURE__*/ dual(2, (self, f) => runForEach$1(self.channel,
29939
30040
  */
29940
30041
  const runForEachArray = /*#__PURE__*/ dual(2, (self, f) => runForEach$1(self.channel, f));
29941
30042
  /**
29942
- * Runs the stream for its effects, discarding emitted elements.
29943
- *
29944
- * **Example** (Draining a stream run)
29945
- *
29946
- * ```ts
29947
- * import { Console, Effect, Stream } from "effect"
29948
- *
29949
- * const program = Effect.gen(function*() {
29950
- * const stream = Stream.make(1, 2, 3).pipe(
29951
- * Stream.mapEffect((n) => Console.log(`Processing: ${n}`))
29952
- * )
29953
- *
29954
- * yield* Stream.runDrain(stream)
29955
- * })
29956
- *
29957
- * Effect.runPromise(program)
29958
- * // Processing: 1
29959
- * // Processing: 2
29960
- * // Processing: 3
29961
- * ```
29962
- *
29963
- * @category destructors
29964
- * @since 2.0.0
29965
- */
29966
- const runDrain = (self) => runDrain$1(self.channel);
29967
- /**
29968
30043
  * Concatenates all emitted strings into a single string.
29969
30044
  *
29970
30045
  * **Example** (Joining strings from a stream)
@@ -30248,7 +30323,7 @@ const make$42 = (impl) => FileSystem.of({
30248
30323
  return fromPull(succeed$3(flatMap$2(suspend$2(() => {
30249
30324
  if (bytesToRead !== void 0 && bytesToRead <= totalBytesRead) return done();
30250
30325
  return bytesToRead !== void 0 && bytesToRead - totalBytesRead < chunkSize ? file.readAlloc(bytesToRead - totalBytesRead) : readChunk;
30251
- }), match$5({
30326
+ }), match$4({
30252
30327
  onNone: () => done(),
30253
30328
  onSome: (buf) => {
30254
30329
  totalBytesRead += BigInt(buf.length);
@@ -31798,7 +31873,7 @@ var LeafNode = class LeafNode extends Node {
31798
31873
  return 1;
31799
31874
  }
31800
31875
  get(_shift, hash, key) {
31801
- if (this.hash === hash && equals$2(this.key, key)) return some$1(this.value);
31876
+ if (this.hash === hash && equals$2(this.key, key)) return some(this.value);
31802
31877
  return none();
31803
31878
  }
31804
31879
  has(_shift, hash, key) {
@@ -31851,7 +31926,7 @@ var CollisionNode = class CollisionNode extends Node {
31851
31926
  }
31852
31927
  get(_shift, hash, key) {
31853
31928
  if (this.hash !== hash) return none();
31854
- for (const [k, v] of this.entries) if (equals$2(k, key)) return some$1(v);
31929
+ for (const [k, v] of this.entries) if (equals$2(k, key)) return some(v);
31855
31930
  return none();
31856
31931
  }
31857
31932
  has(_shift, hash, key) {
@@ -32522,22 +32597,6 @@ const lambda = (f) => f;
32522
32597
  * @since 4.0.0
32523
32598
  */
32524
32599
  const map$1 = /*#__PURE__*/ dual(2, (self, f) => self === void 0 ? void 0 : f(self));
32525
- /**
32526
- * Pattern matches on an `A | undefined` value, running `onDefined` when the
32527
- * value is present or evaluating `onUndefined` when the value is `undefined`.
32528
- *
32529
- * **When to use**
32530
- *
32531
- * Use when you need to turn an `A | undefined` into a non-optional result by
32532
- * handling both the defined and undefined branches in one expression.
32533
- *
32534
- * @see {@link map} for transforming defined values while preserving `undefined`
32535
- * @see {@link getOrThrowWith} for throwing when the value is `undefined` instead of returning a fallback branch
32536
- *
32537
- * @category pattern matching
32538
- * @since 4.0.0
32539
- */
32540
- const match = /*#__PURE__*/ dual(2, (self, { onDefined, onUndefined }) => self === void 0 ? onUndefined() : onDefined(self));
32541
32600
  //#endregion
32542
32601
  //#region ../../node_modules/.pnpm/effect@4.0.0-beta.74/node_modules/effect/dist/SchemaParser.js
32543
32602
  /**
@@ -32801,7 +32860,7 @@ const mergeParseOptions = (options, overrideOptions) => overrideOptions === void
32801
32860
  /** @internal */
32802
32861
  function run(ast) {
32803
32862
  const parser = recur$1(ast);
32804
- return (input, options) => flatMapEager(parser(some$1(input), options ?? defaultParseOptions), (oa) => {
32863
+ return (input, options) => flatMapEager(parser(some(input), options ?? defaultParseOptions), (oa) => {
32805
32864
  if (oa._tag === "None") return fail$3(new InvalidValue(oa));
32806
32865
  return succeed$3(oa.value);
32807
32866
  });
@@ -33036,7 +33095,7 @@ function declareConstructor() {
33036
33095
  * @since 3.10.0
33037
33096
  */
33038
33097
  function declare(is, annotations) {
33039
- return declareConstructor()([], () => (input, ast) => is(input) ? succeed$3(input) : fail$3(new InvalidType(ast, some$1(input))), annotations);
33098
+ return declareConstructor()([], () => (input, ast) => is(input) ? succeed$3(input) : fail$3(new InvalidType(ast, some(input))), annotations);
33040
33099
  }
33041
33100
  /**
33042
33101
  * Returns `true` if `u` is a {@link SchemaError}.
@@ -33086,25 +33145,6 @@ function decodeUnknownEffect(schema, options) {
33086
33145
  };
33087
33146
  }
33088
33147
  /**
33089
- * Decodes a typed input (the schema's `Encoded` type) against a schema,
33090
- * returning an `Effect` that succeeds with the decoded value or fails with a
33091
- * {@link SchemaError}.
33092
- *
33093
- * **When to use**
33094
- *
33095
- * Use when the input is already typed as the schema's `Encoded` type.
33096
- *
33097
- * **Details**
33098
- *
33099
- * For `unknown` input use {@link decodeUnknownEffect}.
33100
- * Options may be provided either when creating the decoder or when applying it;
33101
- * application options override creation options.
33102
- *
33103
- * @category decoding
33104
- * @since 4.0.0
33105
- */
33106
- const decodeEffect = decodeUnknownEffect;
33107
- /**
33108
33148
  * Decodes an `unknown` input against a schema, returning an `Option` that is
33109
33149
  * `Some` with the decoded value on success or `None` on failure.
33110
33150
  *
@@ -33160,25 +33200,6 @@ function encodeUnknownEffect(schema, options) {
33160
33200
  };
33161
33201
  }
33162
33202
  /**
33163
- * Encodes a typed input (the schema's `Type`) against a schema, returning an
33164
- * `Effect` that succeeds with the encoded value or fails with a
33165
- * {@link SchemaError}.
33166
- *
33167
- * **When to use**
33168
- *
33169
- * Use when the input is already typed as the schema's `Type`.
33170
- *
33171
- * **Details**
33172
- *
33173
- * For `unknown` input use {@link encodeUnknownEffect}.
33174
- * Options may be provided either when creating the encoder or when applying it;
33175
- * application options override creation options.
33176
- *
33177
- * @category encoding
33178
- * @since 4.0.0
33179
- */
33180
- const encodeEffect = encodeUnknownEffect;
33181
- /**
33182
33203
  * Encodes a typed input (the schema's `Type`) against a schema synchronously,
33183
33204
  * throwing a {@link SchemaError} on failure.
33184
33205
  *
@@ -33901,15 +33922,15 @@ function isInt(annotations) {
33901
33922
  */
33902
33923
  function CauseReason(error, defect) {
33903
33924
  return make$35(declareConstructor()([error, defect], ([error, defect]) => (input, ast, options) => {
33904
- if (!isReason(input)) return fail$3(new InvalidType(ast, some$1(input)));
33925
+ if (!isReason(input)) return fail$3(new InvalidType(ast, some(input)));
33905
33926
  switch (input._tag) {
33906
33927
  case "Fail": return mapBothEager(decodeUnknownEffect$1(error)(input.error, options), {
33907
33928
  onSuccess: makeFailReason,
33908
- onFailure: (issue) => new Composite(ast, some$1(input), [new Pointer(["error"], issue)])
33929
+ onFailure: (issue) => new Composite(ast, some(input), [new Pointer(["error"], issue)])
33909
33930
  });
33910
33931
  case "Die": return mapBothEager(decodeUnknownEffect$1(defect)(input.defect, options), {
33911
33932
  onSuccess: makeDieReason,
33912
- onFailure: (issue) => new Composite(ast, some$1(input), [new Pointer(["defect"], issue)])
33933
+ onFailure: (issue) => new Composite(ast, some(input), [new Pointer(["defect"], issue)])
33913
33934
  });
33914
33935
  case "Interrupt": return succeed$3(input);
33915
33936
  }
@@ -34004,10 +34025,10 @@ function Cause(error, defect) {
34004
34025
  return make$35(declareConstructor()([error, defect], ([error, defect]) => {
34005
34026
  const failures = ArraySchema(CauseReason(error, defect));
34006
34027
  return (input, ast, options) => {
34007
- if (!isCause(input)) return fail$3(new InvalidType(ast, some$1(input)));
34028
+ if (!isCause(input)) return fail$3(new InvalidType(ast, some(input)));
34008
34029
  return mapBothEager(decodeUnknownEffect$1(failures)(input.reasons, options), {
34009
34030
  onSuccess: fromReasons,
34010
- onFailure: (issue) => new Composite(ast, some$1(input), [new Pointer(["failures"], issue)])
34031
+ onFailure: (issue) => new Composite(ast, some(input), [new Pointer(["failures"], issue)])
34011
34032
  });
34012
34033
  };
34013
34034
  }, {
@@ -34111,15 +34132,15 @@ function Exit(value, error, defect) {
34111
34132
  ], ([value, error, defect]) => {
34112
34133
  const cause = Cause(error, defect);
34113
34134
  return (input, ast, options) => {
34114
- if (!isExit(input)) return fail$3(new InvalidType(ast, some$1(input)));
34135
+ if (!isExit(input)) return fail$3(new InvalidType(ast, some(input)));
34115
34136
  switch (input._tag) {
34116
34137
  case "Success": return mapBothEager(decodeUnknownEffect$1(value)(input.value, options), {
34117
34138
  onSuccess: succeed$5,
34118
- onFailure: (issue) => new Composite(ast, some$1(input), [new Pointer(["value"], issue)])
34139
+ onFailure: (issue) => new Composite(ast, some(input), [new Pointer(["value"], issue)])
34119
34140
  });
34120
34141
  case "Failure": return mapBothEager(decodeUnknownEffect$1(cause)(input.cause, options), {
34121
34142
  onSuccess: failCause$3,
34122
- onFailure: (issue) => new Composite(ast, some$1(input), [new Pointer(["cause"], issue)])
34143
+ onFailure: (issue) => new Composite(ast, some(input), [new Pointer(["cause"], issue)])
34123
34144
  });
34124
34145
  }
34125
34146
  };
@@ -34347,7 +34368,7 @@ function getClassSchemaFactory(from, identifier, annotations) {
34347
34368
  if (memo === void 0) {
34348
34369
  const transformation = getClassTransformation(self);
34349
34370
  const to = make$35(new Declaration([from.ast], () => (input, ast) => {
34350
- return input instanceof self || hasProperty(input, getClassTypeId(identifier)) ? succeed$3(input) : fail$3(new InvalidType(ast, some$1(input)));
34371
+ return input instanceof self || hasProperty(input, getClassTypeId(identifier)) ? succeed$3(input) : fail$3(new InvalidType(ast, some(input)));
34351
34372
  }, {
34352
34373
  identifier,
34353
34374
  [ClassTypeId]: ([from]) => new Link(from, transformation),
@@ -35974,7 +35995,7 @@ const setUrlParams = /*#__PURE__*/ dual(2, (self, input) => makeWith$1(self.meth
35974
35995
  * @category combinators
35975
35996
  * @since 4.0.0
35976
35997
  */
35977
- const setHash = /*#__PURE__*/ dual(2, (self, hash) => makeWith$1(self.method, self.url, self.urlParams, some$1(hash), self.headers, self.body));
35998
+ const setHash = /*#__PURE__*/ dual(2, (self, hash) => makeWith$1(self.method, self.url, self.urlParams, some(hash), self.headers, self.body));
35978
35999
  /**
35979
36000
  * Sets the request body and updates `Content-Type` and `Content-Length` headers from the body metadata when available.
35980
36001
  *
@@ -36269,7 +36290,7 @@ var WebHttpClientResponse = class extends Class$2 {
36269
36290
  * @since 4.0.0
36270
36291
  */
36271
36292
  const toHeaders = (span) => fromRecordUnsafe({
36272
- b3: `${span.traceId}-${span.spanId}-${span.sampled ? "1" : "0"}${match$5(span.parent, {
36293
+ b3: `${span.traceId}-${span.spanId}-${span.sampled ? "1" : "0"}${match$4(span.parent, {
36273
36294
  onNone: () => "",
36274
36295
  onSome: (parent) => `-${parent.spanId}`
36275
36296
  })}`,
@@ -36308,7 +36329,7 @@ const b3 = (headers) => {
36308
36329
  if (!("b3" in headers)) return none();
36309
36330
  const parts = headers["b3"].split("-");
36310
36331
  if (parts.length < 2) return none();
36311
- return some$1(externalSpan({
36332
+ return some(externalSpan({
36312
36333
  traceId: parts[0],
36313
36334
  spanId: parts[1],
36314
36335
  sampled: parts[2] ? parts[2] === "1" : true
@@ -36327,7 +36348,7 @@ const b3 = (headers) => {
36327
36348
  */
36328
36349
  const xb3 = (headers) => {
36329
36350
  if (!headers["x-b3-traceid"] || !headers["x-b3-spanid"]) return none();
36330
- return some$1(externalSpan({
36351
+ return some(externalSpan({
36331
36352
  traceId: headers["x-b3-traceid"],
36332
36353
  spanId: headers["x-b3-spanid"],
36333
36354
  sampled: headers["x-b3-sampled"] ? headers["x-b3-sampled"] === "1" : true
@@ -36353,7 +36374,7 @@ const w3c = (headers) => {
36353
36374
  switch (version) {
36354
36375
  case "00":
36355
36376
  if (w3cTraceId.test(traceId) === false || w3cSpanId.test(spanId) === false) return none();
36356
- return some$1(externalSpan({
36377
+ return some(externalSpan({
36357
36378
  traceId,
36358
36379
  spanId,
36359
36380
  sampled: (parseInt(flags, 16) & 1) === 1
@@ -37801,7 +37822,7 @@ const causeResponseStripped = (cause) => {
37801
37822
  }
37802
37823
  return true;
37803
37824
  });
37804
- return [response ?? internalServerError, failures.length > 0 ? some$1(fromReasons(failures)) : none()];
37825
+ return [response ?? internalServerError, failures.length > 0 ? some(fromReasons(failures)) : none()];
37805
37826
  };
37806
37827
  const internalServerError = /*#__PURE__*/ empty({ status: 500 });
37807
37828
  const succeedInternalServerError = /*#__PURE__*/ succeed$3(internalServerError);
@@ -39570,7 +39591,7 @@ const toURL = (self) => {
39570
39591
  const host = self.headers.host ?? "localhost";
39571
39592
  const protocol = self.headers["x-forwarded-proto"] === "https" ? "https" : "http";
39572
39593
  try {
39573
- return some$1(new URL(self.url, `${protocol}://${host}`));
39594
+ return some(new URL(self.url, `${protocol}://${host}`));
39574
39595
  } catch {
39575
39596
  return none();
39576
39597
  }
@@ -39897,7 +39918,7 @@ const toString = (self) => {
39897
39918
  */
39898
39919
  var Generator = class extends Service()("effect/http/Etag/Generator") {};
39899
39920
  const fromFileInfo = (info) => {
39900
- const mtime = match$5(info.mtime, {
39921
+ const mtime = match$4(info.mtime, {
39901
39922
  onNone: () => "0",
39902
39923
  onSome: (mtime) => mtime.getTime().toString(16)
39903
39924
  });
@@ -40315,7 +40336,7 @@ const RouteTypeId = "~effect/http/HttpRouter/Route";
40315
40336
  const makeRoute = (options) => ({
40316
40337
  ...options,
40317
40338
  uninterruptible: options.uninterruptible ?? false,
40318
- prefix: typeof options.prefix === "string" ? some$1(options.prefix) : options.prefix ?? none(),
40339
+ prefix: typeof options.prefix === "string" ? some(options.prefix) : options.prefix ?? none(),
40319
40340
  [RouteTypeId]: RouteTypeId
40320
40341
  });
40321
40342
  /**
@@ -40370,7 +40391,7 @@ const prefixPath = /*#__PURE__*/ dual(2, (self, prefix) => {
40370
40391
  const prefixRoute = /*#__PURE__*/ dual(2, (self, prefix) => makeRoute({
40371
40392
  ...self,
40372
40393
  path: prefixPath(self.path, prefix),
40373
- prefix: match$5(self.prefix, {
40394
+ prefix: match$4(self.prefix, {
40374
40395
  onNone: () => prefix,
40375
40396
  onSome: (existingPrefix) => prefixPath(existingPrefix, prefix)
40376
40397
  })
@@ -40646,7 +40667,7 @@ function isStreamSchema(schema) {
40646
40667
  }
40647
40668
  /** @internal */
40648
40669
  function getStreamSchemas(schema) {
40649
- return isStreamSchema(schema) ? some$1({
40670
+ return isStreamSchema(schema) ? some({
40650
40671
  success: schema.success,
40651
40672
  error: schema.error
40652
40673
  }) : none();
@@ -43790,7 +43811,7 @@ const make$16 = /*#__PURE__*/ fnUntraced(function* (group, options) {
43790
43811
  }).pipe(provide$3(scope));
43791
43812
  yield* forkChild(whileLoop({
43792
43813
  while: constTrue,
43793
- body: constant(flatMap$2(take$2(disconnects), (clientId) => {
43814
+ body: constant(flatMap$2(take$1(disconnects), (clientId) => {
43794
43815
  clients.delete(clientId);
43795
43816
  return server.disconnect(clientId);
43796
43817
  })),
@@ -44950,7 +44971,7 @@ const withDefault = /*#__PURE__*/ dual(2, (self, defaultValue) => {
44950
44971
  * @category combinators
44951
44972
  * @since 2.0.0
44952
44973
  */
44953
- const option = (self) => self.pipe(map(some$1), withDefault(none()));
44974
+ const option = (self) => self.pipe(map(some), withDefault(none()));
44954
44975
  /**
44955
44976
  * Constructs a `Config<T>` from a value matching `Wrap<T>`.
44956
44977
  *
@@ -48976,10 +48997,10 @@ const makeFile = /*#__PURE__*/ (() => {
48976
48997
  }), (bytesRead) => {
48977
48998
  if (bytesRead === 0) return none();
48978
48999
  this.position = position + BigInt(bytesRead);
48979
- if (bytesRead === sizeNumber) return some$1(buffer);
49000
+ if (bytesRead === sizeNumber) return some(buffer);
48980
49001
  const dst = Buffer.allocUnsafeSlow(bytesRead);
48981
49002
  buffer.copy(dst, 0, 0, bytesRead);
48982
- return some$1(dst);
49003
+ return some(dst);
48983
49004
  });
48984
49005
  });
48985
49006
  }
@@ -49078,7 +49099,7 @@ const makeFileInfo = (stat) => ({
49078
49099
  uid: fromNullishOr(stat.uid),
49079
49100
  gid: fromNullishOr(stat.gid),
49080
49101
  size: Size(stat.size),
49081
- blksize: stat.blksize !== void 0 ? some$1(Size(stat.blksize)) : none(),
49102
+ blksize: stat.blksize !== void 0 ? some(Size(stat.blksize)) : none(),
49082
49103
  blocks: fromNullishOr(stat.blocks)
49083
49104
  });
49084
49105
  const stat = /*#__PURE__*/ (() => {
@@ -51641,39 +51662,6 @@ const layerFileSystem = (directory) => effect(KeyValueStore)(gen(function* () {
51641
51662
  })
51642
51663
  });
51643
51664
  }));
51644
- const SchemaStoreTypeId = "~effect/persistence/KeyValueStore/SchemaStore";
51645
- /**
51646
- * Adapts a `KeyValueStore` into a `SchemaStore` using the schema's JSON codec.
51647
- *
51648
- * @category SchemaStore
51649
- * @since 4.0.0
51650
- */
51651
- const toSchemaStore = (self, schema) => {
51652
- const jsonSchema = fromJsonString(toCodecJson(schema));
51653
- const decode = decodeEffect(jsonSchema);
51654
- const encode = encodeEffect(jsonSchema);
51655
- const get = (key) => flatMap$2(self.get(key), match({
51656
- onUndefined: () => succeedNone,
51657
- onDefined: (value) => asSome(decode(value))
51658
- }));
51659
- const set = (key, value) => flatMap$2(encode(value), (json) => self.set(key, json));
51660
- const modify = (key, f) => flatMap$2(get(key), (o) => {
51661
- if (isNone(o)) return succeedNone;
51662
- const newValue = f(o.value);
51663
- return as(set(key, newValue), some$1(newValue));
51664
- });
51665
- return {
51666
- [SchemaStoreTypeId]: SchemaStoreTypeId,
51667
- get,
51668
- set,
51669
- modify,
51670
- remove: self.remove,
51671
- clear: self.clear,
51672
- size: self.size,
51673
- has: self.has,
51674
- isEmpty: self.isEmpty
51675
- };
51676
- };
51677
51665
  //#endregion
51678
51666
  //#region ../../node_modules/.pnpm/effect@4.0.0-beta.74/node_modules/effect/dist/SubscriptionRef.js
51679
51667
  /**
@@ -52231,38 +52219,49 @@ var GitDiffSegment = class extends Class("GitDiffSegment")({
52231
52219
  type: Literals(["commit", "worktree"])
52232
52220
  }) {};
52233
52221
  var GitDiff = class extends Class("GitDiff")({
52222
+ fileContent: optional(String$1),
52234
52223
  filePath: String$1,
52235
52224
  patch: String$1,
52236
52225
  segments: ArraySchema(GitDiffSegment),
52237
52226
  status: GitDiffStatus
52238
52227
  }) {};
52239
- const GitReviewFrom = Union([Struct({
52240
- ref: String$1,
52241
- type: Literal("ref")
52242
- }), Struct({
52243
- base: String$1,
52244
- type: Literal("merge-base")
52245
- })]);
52246
- const GitReviewTo = Union([Struct({
52247
- ref: String$1,
52248
- type: Literal("ref")
52249
- }), Struct({ type: Literal("worktree") })]);
52228
+ const GitReviewTarget = Union([
52229
+ Struct({ _tag: Literal("changes") }),
52230
+ Struct({ _tag: Literal("local") }),
52231
+ Struct({ _tag: Literal("branch") }),
52232
+ Struct({
52233
+ _tag: Literal("commit"),
52234
+ hash: String$1
52235
+ })
52236
+ ]);
52250
52237
  var GitCommit = class extends Class("GitCommit")({
52251
52238
  hash: String$1,
52252
- parents: ArraySchema(String$1),
52253
52239
  shortHash: String$1,
52254
- subject: String$1,
52255
- wip: Boolean$1
52240
+ subject: String$1
52256
52241
  }) {};
52257
52242
  var GitReviewMetadata = class extends Class("GitReviewMetadata")({
52258
- base: String$1,
52259
- branch: String$1,
52260
- commits: ArraySchema(GitCommit),
52261
- defaultBranch: String$1,
52243
+ branchCommits: ArraySchema(GitCommit),
52262
52244
  dirty: Boolean$1,
52245
+ localCommits: ArraySchema(GitCommit),
52263
52246
  prUrl: optional(String$1),
52264
52247
  unpushedCommits: Boolean$1
52265
52248
  }) {};
52249
+ var GitReviewMark = class extends Class("GitReviewMark")({
52250
+ filePath: String$1,
52251
+ fingerprint: String$1,
52252
+ segmentId: String$1
52253
+ }) {};
52254
+ var GitReviewComment = class extends Class("GitReviewComment")({
52255
+ body: String$1,
52256
+ filePath: String$1,
52257
+ lineNumber: Number$1,
52258
+ resolved: Boolean$1,
52259
+ side: optional(Literals(["additions", "deletions"]))
52260
+ }) {};
52261
+ var GitReviewState = class extends Class("GitReviewState")({
52262
+ comments: ArraySchema(GitReviewComment),
52263
+ marks: ArraySchema(GitReviewMark)
52264
+ }) {};
52266
52265
  var GitHubReviewThread = class extends Class("GitHubReviewThread")({
52267
52266
  body: String$1,
52268
52267
  filePath: String$1,
@@ -52308,15 +52307,55 @@ var GitWorktreeStatus = class extends Class("GitWorktreeStatus")({
52308
52307
  unpushedCommits: Boolean$1,
52309
52308
  untracked: Boolean$1
52310
52309
  }) {};
52311
- var GitWorktree$1 = class extends Class("GitWorktree")({
52310
+ var GitWorktree = class extends Class("GitWorktree")({
52312
52311
  branch: optional(String$1),
52313
52312
  root: String$1,
52314
52313
  status: optional(GitWorktreeStatus)
52315
52314
  }) {};
52316
52315
  var GitProject = class extends Class("GitProject")({
52317
52316
  repository: GitRepository,
52318
- worktrees: ArraySchema(GitWorktree$1)
52317
+ worktrees: ArraySchema(GitWorktree)
52319
52318
  }) {};
52319
+ function gitReviewCommentKey(input) {
52320
+ return `${input.filePath}:${input.side ?? "additions"}:${input.lineNumber}`;
52321
+ }
52322
+ function gitReviewMarkKey(input) {
52323
+ return `${input.filePath}:${input.fingerprint}`;
52324
+ }
52325
+ function gitReviewStateSaveComment(state, comment) {
52326
+ const key = gitReviewCommentKey(comment);
52327
+ return new GitReviewState({
52328
+ comments: append$1(filter$1(state.comments, (currentComment) => gitReviewCommentKey(currentComment) !== key), new GitReviewComment({
52329
+ ...comment,
52330
+ resolved: false
52331
+ })),
52332
+ marks: state.marks
52333
+ });
52334
+ }
52335
+ function gitReviewStateResolveComment(state, input) {
52336
+ const key = gitReviewCommentKey(input);
52337
+ return new GitReviewState({
52338
+ comments: map$7(state.comments, (comment) => gitReviewCommentKey(comment) === key ? new GitReviewComment({
52339
+ ...comment,
52340
+ resolved: true
52341
+ }) : comment),
52342
+ marks: state.marks
52343
+ });
52344
+ }
52345
+ function gitReviewStateMark(state, marks) {
52346
+ const keys = new Set(map$7(marks, gitReviewMarkKey));
52347
+ return new GitReviewState({
52348
+ comments: state.comments,
52349
+ marks: appendAll(filter$1(state.marks, (mark) => !keys.has(gitReviewMarkKey(mark))), marks)
52350
+ });
52351
+ }
52352
+ function gitReviewStateUnmark(state, marks) {
52353
+ const keys = new Set(map$7(marks, gitReviewMarkKey));
52354
+ return new GitReviewState({
52355
+ comments: state.comments,
52356
+ marks: filter$1(state.marks, (mark) => !keys.has(gitReviewMarkKey(mark)))
52357
+ });
52358
+ }
52320
52359
  //#endregion
52321
52360
  //#region ../../packages/terminal/src/schema.ts
52322
52361
  var TerminalError = class extends TaggedErrorClass()("TerminalError", {
@@ -52350,6 +52389,14 @@ const TerminalUpdate = Union([Struct({
52350
52389
  }), TerminalEvent]);
52351
52390
  //#endregion
52352
52391
  //#region src/rpcs/contracts.ts
52392
+ const CreateWorktreeSource = Union([
52393
+ Struct({ _tag: Literal("local") }),
52394
+ Struct({
52395
+ _tag: Literal("remote"),
52396
+ remote: String$1
52397
+ }),
52398
+ Struct({ _tag: Literal("new") })
52399
+ ]);
52353
52400
  const TerminalPayload = Struct({
52354
52401
  args: optional(ArraySchema(String$1)),
52355
52402
  command: optional(String$1),
@@ -52380,24 +52427,9 @@ const AgentSession = Struct({
52380
52427
  "pi"
52381
52428
  ]),
52382
52429
  label: String$1,
52430
+ state: TerminalState,
52383
52431
  uuid: String$1
52384
52432
  });
52385
- var ReviewMark = class extends Class("ReviewMark")({
52386
- filePath: String$1,
52387
- fingerprint: String$1,
52388
- segmentId: String$1
52389
- }) {};
52390
- var ReviewComment = class extends Class("ReviewComment")({
52391
- body: String$1,
52392
- filePath: String$1,
52393
- lineNumber: Number$1,
52394
- resolved: optional(Boolean$1),
52395
- side: optional(Literals(["additions", "deletions"]))
52396
- }) {};
52397
- var ReviewState = class extends Class("ReviewState")({
52398
- comments: ArraySchema(ReviewComment),
52399
- marks: ArraySchema(ReviewMark)
52400
- }) {};
52401
52433
  var RpcContracts = class extends make$15(make$18("agents.create", {
52402
52434
  error: TerminalError,
52403
52435
  payload: Struct({
@@ -52432,71 +52464,56 @@ var RpcContracts = class extends make$15(make$18("agents.create", {
52432
52464
  success: GitBranchesSnapshot
52433
52465
  }), make$18("review.metadata", {
52434
52466
  error: GitError,
52435
- payload: Struct({
52436
- base: optional(String$1),
52437
- cwd: String$1
52438
- }),
52467
+ payload: Struct({ cwd: String$1 }),
52439
52468
  success: GitReviewMetadata
52440
- }), make$18("review.watchRange", {
52469
+ }), make$18("review.diffs", {
52441
52470
  error: GitError,
52442
52471
  payload: Struct({
52443
52472
  cwd: String$1,
52444
- from: GitReviewFrom,
52445
- to: GitReviewTo
52473
+ target: GitReviewTarget
52446
52474
  }),
52447
52475
  stream: true,
52448
52476
  success: ArraySchema(GitDiff)
52449
52477
  }), make$18("review.state.watch", {
52450
52478
  error: GitError,
52451
- payload: Struct({
52452
- base: String$1,
52453
- cwd: String$1
52454
- }),
52479
+ payload: Struct({ cwd: String$1 }),
52455
52480
  stream: true,
52456
- success: ReviewState
52481
+ success: GitReviewState
52457
52482
  }), make$18("review.state.mark", {
52458
52483
  error: GitError,
52459
52484
  payload: Struct({
52460
- base: String$1,
52461
52485
  cwd: String$1,
52462
- marks: ArraySchema(ReviewMark)
52486
+ marks: ArraySchema(GitReviewMark)
52463
52487
  })
52464
52488
  }), make$18("review.state.unmark", {
52465
52489
  error: GitError,
52466
52490
  payload: Struct({
52467
- base: String$1,
52468
52491
  cwd: String$1,
52469
- marks: ArraySchema(ReviewMark)
52492
+ marks: ArraySchema(GitReviewMark)
52470
52493
  })
52471
52494
  }), make$18("review.comments.save", {
52472
52495
  error: GitError,
52473
52496
  payload: Struct({
52474
- base: String$1,
52475
- comment: ReviewComment,
52497
+ comment: GitReviewComment,
52476
52498
  cwd: String$1
52477
52499
  })
52478
52500
  }), make$18("review.comments.resolve", {
52479
52501
  error: GitError,
52480
52502
  payload: Struct({
52481
- base: String$1,
52482
52503
  cwd: String$1,
52483
52504
  filePath: String$1,
52484
52505
  lineNumber: Number$1,
52485
52506
  side: optional(Literals(["additions", "deletions"]))
52486
52507
  })
52487
- }), make$18("review.createWipCommit", {
52508
+ }), make$18("review.commit", {
52488
52509
  error: GitError,
52489
52510
  payload: Struct({
52490
52511
  cwd: String$1,
52491
52512
  message: String$1
52492
52513
  })
52493
- }), make$18("review.commitAndPush", {
52514
+ }), make$18("review.push", {
52494
52515
  error: GitError,
52495
- payload: Struct({
52496
- base: String$1,
52497
- cwd: String$1,
52498
- message: String$1
52499
- })
52516
+ payload: Struct({ cwd: String$1 })
52500
52517
  }), make$18("review.githubThreads", {
52501
52518
  error: GitError,
52502
52519
  payload: Struct({ cwd: String$1 }),
@@ -52507,43 +52524,17 @@ var RpcContracts = class extends make$15(make$18("agents.create", {
52507
52524
  cwd: String$1,
52508
52525
  threadId: String$1
52509
52526
  })
52510
- }), make$18("review.stageFile", {
52511
- error: GitError,
52512
- payload: Struct({
52513
- cwd: String$1,
52514
- filePath: String$1
52515
- })
52516
- }), make$18("review.unstageFile", {
52517
- error: GitError,
52518
- payload: Struct({
52519
- cwd: String$1,
52520
- filePath: String$1
52521
- })
52522
- }), make$18("review.discardFile", {
52523
- error: GitError,
52524
- payload: Struct({
52525
- cwd: String$1,
52526
- filePath: String$1
52527
- })
52528
52527
  }), make$18("projects.createWorktree", {
52529
52528
  error: GitError,
52530
52529
  payload: Struct({
52531
- baseBranch: String$1,
52532
52530
  branch: String$1,
52533
52531
  cwd: String$1,
52534
- mode: Literals([
52535
- "existing-local",
52536
- "existing-remote",
52537
- "new-local"
52538
- ])
52532
+ source: CreateWorktreeSource
52539
52533
  }),
52540
52534
  success: String$1
52541
52535
  }), make$18("projects.deleteWorktree", {
52542
52536
  error: GitError,
52543
- payload: Struct({
52544
- cwd: String$1,
52545
- force: Boolean$1
52546
- })
52537
+ payload: Struct({ cwd: String$1 })
52547
52538
  }), make$18("runs.portless", {
52548
52539
  error: TerminalError,
52549
52540
  payload: Struct({ cwd: String$1 }),
@@ -52590,22 +52581,47 @@ var RpcContracts = class extends make$15(make$18("agents.create", {
52590
52581
  })) {};
52591
52582
  //#endregion
52592
52583
  //#region ../../packages/git/src/service.ts
52593
- const makeGitExecutor = gen(function* () {
52594
- const execString = yield* ChildProcessSpawner.useSync((spawner) => spawner.string);
52584
+ var GitCommand = class extends Service()("@deslop/git/service/GitCommand", { make: gen(function* () {
52585
+ const spawner = yield* ChildProcessSpawner;
52586
+ const string = fn("GitCommand.string")(function* (cwd, args) {
52587
+ yield* annotateCurrentSpan({
52588
+ command: args[0] ?? "git",
52589
+ cwd
52590
+ });
52591
+ return yield* scoped$3(gen(function* () {
52592
+ const handle = yield* pipe(spawner.spawn(make$40("git", args, {
52593
+ cwd,
52594
+ stderr: "pipe",
52595
+ stdout: "pipe"
52596
+ })), mapError$2((cause) => new GitError({ cause })));
52597
+ const output = yield* all({
52598
+ stderr: pipe(decodeText(handle.stderr), mkString, orElseSucceed(() => "")),
52599
+ stdout: pipe(decodeText(handle.stdout), mkString, orElseSucceed(() => ""))
52600
+ }, { concurrency: "unbounded" });
52601
+ const exitCode = yield* pipe(handle.exitCode, mapError$2((cause) => new GitError({ cause })));
52602
+ if (exitCode !== ExitCode(0)) return yield* new GitError({ cause: new Error(output.stderr || output.stdout || `git ${join$2(" ")(args)} exited with ${exitCode}`) });
52603
+ return output.stdout;
52604
+ })).pipe(withSpan("git.command", { attributes: {
52605
+ command: args[0] ?? "git",
52606
+ cwd
52607
+ } }));
52608
+ });
52595
52609
  return {
52596
- lines: fnUntraced(function* (cwd, args) {
52597
- return yield* pipe((yield* ChildProcessSpawner.useSync((spawner) => spawner.lines))(make$40("git", args, { cwd })), mapError$2((cause) => new GitError({ cause })));
52610
+ lines: fn("GitCommand.lines")(function* (cwd, args) {
52611
+ return pipe(yield* string(cwd, args), split$1(/\r?\n/u), filter$1(isNonEmpty$1));
52598
52612
  }),
52599
- string: fnUntraced(function* (cwd, args) {
52600
- return yield* pipe(execString(make$40("git", args, { cwd })), mapError$2((cause) => new GitError({ cause })));
52601
- })
52613
+ string
52602
52614
  };
52603
- });
52604
- function toArgs(to) {
52605
- return to.type === "ref" ? [to.ref] : empty$13();
52606
- }
52615
+ }) }) {
52616
+ static layer = effect(this, this.make);
52617
+ };
52618
+ const excludedDiscoveryEntries = new Set([
52619
+ ".git",
52620
+ "dist",
52621
+ "node_modules"
52622
+ ]);
52607
52623
  function segmentsByFile(segments) {
52608
- return reduce(segments, empty$6(), (groups, segment) => modifyAt(groups, segment.filePath, (current) => some$1(append$1(getOrElse$1(current, () => empty$13()), segment))));
52624
+ return reduce(segments, empty$6(), (groups, segment) => modifyAt(groups, segment.filePath, (current) => some(append$1(getOrElse$1(current, () => empty$13()), segment))));
52609
52625
  }
52610
52626
  function diffFromPatchChunk(chunk, segments) {
52611
52627
  const deleted = /^deleted file mode /mu.test(chunk);
@@ -52618,18 +52634,60 @@ function diffFromPatchChunk(chunk, segments) {
52618
52634
  status
52619
52635
  });
52620
52636
  }
52621
- function isWipSubject(subject) {
52622
- return subject === "wip" || startsWith("wip: ")(subject);
52637
+ function withDisplayedPatchSegments(diffs, id, type) {
52638
+ return map$7(diffs, (diff) => new GitDiff({
52639
+ fileContent: diff.fileContent,
52640
+ filePath: diff.filePath,
52641
+ patch: diff.patch,
52642
+ segments: [new GitDiffSegment({
52643
+ filePath: diff.filePath,
52644
+ fingerprint: diff.patch,
52645
+ id,
52646
+ type
52647
+ })],
52648
+ status: diff.status
52649
+ }));
52650
+ }
52651
+ function commitFromLogLine(line) {
52652
+ const parts = split$1("\0")(line);
52653
+ return new GitCommit({
52654
+ hash: parts[0],
52655
+ shortHash: parts[1] ?? "",
52656
+ subject: parts[2] ?? ""
52657
+ });
52658
+ }
52659
+ function parseWorktreeRecords(output) {
52660
+ const records = [];
52661
+ let current = {
52662
+ hasHead: false,
52663
+ root: ""
52664
+ };
52665
+ for (const field of split$1("\0")(output)) if (startsWith("worktree ")(field)) {
52666
+ if (isNonEmpty$1(current.root) && current.hasHead) records.push(current);
52667
+ current = {
52668
+ hasHead: false,
52669
+ root: replace(/^worktree\s+/u, "")(field)
52670
+ };
52671
+ } else if (startsWith("HEAD ")(field)) current = {
52672
+ ...current,
52673
+ hasHead: true
52674
+ };
52675
+ else if (startsWith("branch refs/heads/")(field)) current = {
52676
+ ...current,
52677
+ branch: replace(/^branch\s+refs\/heads\//u, "")(field)
52678
+ };
52679
+ if (isNonEmpty$1(current.root) && current.hasHead) records.push(current);
52680
+ return records;
52623
52681
  }
52624
52682
  var GitWorkspace = class extends Service()("@deslop/git/service/GitWorkspace", { make: gen(function* () {
52625
- const execString = yield* ChildProcessSpawner.useSync((spawner) => spawner.string);
52626
- const git = yield* makeGitExecutor;
52683
+ const git = yield* GitCommand;
52627
52684
  const fs = yield* FileSystem;
52628
52685
  const path = yield* Path$1;
52629
52686
  const home = yield* pipe(string("HOME"), withDefault(process.cwd()));
52630
52687
  const projects = yield* make$3(empty$13());
52631
52688
  const run = runForkWith(yield* context$1());
52632
- const getDefaultBranch = fnUntraced(function* (cwd) {
52689
+ const getDefaultBranch = fn("GitWorkspace.getDefaultBranch")(function* (cwd) {
52690
+ yield* annotateCurrentSpan({ cwd });
52633
52691
  return yield* pipe(git.string(cwd, [
52634
52692
  "symbolic-ref",
52635
52693
  "--short",
@@ -52640,16 +52698,26 @@ var GitWorkspace = class extends Service()("@deslop/git/service/GitWorkspace", {
52640
52698
  "main"
52641
52699
  ]), as("main"), catchTag("GitError", () => succeed$3("master")))));
52642
52700
  });
52643
- const getWorktreeStatus = fnUntraced(function* (cwd, branch) {
52644
- const counts = yield* pipe(git.string(cwd, [
52701
+ const getWorktreeStatus = fn("GitWorkspace.getWorktreeStatus")(function* (cwd, branch) {
52702
+ yield* annotateCurrentSpan({
52703
+ branch: branch ?? "",
52704
+ cwd
52705
+ });
52706
+ const upstream = branch === void 0 ? none() : yield* pipe(git.string(cwd, [
52707
+ "rev-parse",
52708
+ "--abbrev-ref",
52709
+ "--symbolic-full-name",
52710
+ `${branch}@{u}`
52711
+ ]), map$4(flow(trim, some)), orElseSucceed(() => none()));
52712
+ const counts = isNone(upstream) ? ["0", "0"] : yield* pipe(git.string(cwd, [
52645
52713
  "rev-list",
52646
52714
  "--left-right",
52647
52715
  "--count",
52648
- `origin/${branch ?? ""}...HEAD`
52716
+ `${upstream.value}...HEAD`
52649
52717
  ]), map$4(flow(trim, split$1(/\s+/u))), orElseSucceed(() => ["0", "0"]));
52650
52718
  return new GitWorktreeStatus({
52651
52719
  ahead: getOrElse$1(parse$2(counts[1] ?? "0"), () => 0),
52652
- behind: getOrElse$1(parse$2(counts[0]), () => 0),
52720
+ behind: getOrElse$1(parse$2(counts[0] ?? "0"), () => 0),
52653
52721
  dirtyTracked: yield* pipe(git.lines(cwd, [
52654
52722
  "status",
52655
52723
  "--porcelain",
@@ -52663,79 +52731,61 @@ var GitWorkspace = class extends Service()("@deslop/git/service/GitWorkspace", {
52663
52731
  ]), map$4((lines) => !isReadonlyArrayEmpty(lines)), orElseSucceed(() => false))
52664
52732
  });
52665
52733
  });
52666
- const collectRepositoriesFromRoots = fnUntraced(function* (roots, repositories) {
52667
- return yield* match$3(roots, {
52734
+ const collectRepositoriesFromRoots = fn("GitWorkspace.collectRepositoriesFromRoots")(function* (roots, repositories) {
52735
+ yield* annotateCurrentSpan({
52736
+ repositoryCount: length(repositories),
52737
+ rootCount: length(roots)
52738
+ });
52739
+ return yield* match$2(roots, {
52668
52740
  onEmpty: () => succeed$3(repositories),
52669
52741
  onNonEmpty: (remainingRoots) => {
52670
52742
  const root = remainingRoots[0];
52671
52743
  return pipe(fs.readDirectory(root), orElseSucceed(() => empty$13()), flatMap$2((entries) => {
52672
- if (contains(entries, ".git")) return pipe(git.string(root, [
52673
- "rev-parse",
52674
- "--path-format=absolute",
52675
- "--git-common-dir"
52676
- ]), map$4(trim), map$4((gitDirectory) => succeed$7(new GitRepository({
52677
- gitDirectory,
52678
- root
52679
- }))), orElseSucceed(() => failVoid), flatMap$2((repository) => collectRepositoriesFromRoots(drop$1(remainingRoots, 1), append$1(repositories, repository))));
52680
- return pipe(entries, filter$2((entry) => !(new Set([
52681
- ".git",
52682
- ".next",
52683
- ".turbo",
52684
- "build",
52685
- "coverage",
52686
- "dist",
52687
- "node_modules"
52688
- ]).has(entry) || startsWith(".")(entry) && entry !== ".git")), forEach$1((entry) => pipe(fs.stat(path.join(root, entry)), map$4((info) => info.type === "Directory" ? path.join(root, entry) : ""), orElseSucceed(() => ""))), flatMap$2((nextRoots) => collectRepositoriesFromRoots(pipe(nextRoots, filter$2(isNonEmpty$1), appendAll(drop$1(roots, 1))), repositories)));
52744
+ if (contains(entries, ".git")) return pipe(all({
52745
+ gitDirectory: pipe(git.string(root, [
52746
+ "rev-parse",
52747
+ "--path-format=absolute",
52748
+ "--git-common-dir"
52749
+ ]), map$4(trim)),
52750
+ worktrees: pipe(git.string(root, [
52751
+ "worktree",
52752
+ "list",
52753
+ "--porcelain",
52754
+ "-z"
52755
+ ]), map$4(parseWorktreeRecords))
52756
+ }, { concurrency: "unbounded" }), map$4((repository) => new GitRepository({
52757
+ gitDirectory: repository.gitDirectory,
52758
+ root: repository.worktrees[0]?.root ?? root
52759
+ })), option$1, flatMap$2((repository) => collectRepositoriesFromRoots(drop$1(remainingRoots, 1), pipe(repository, match$4({
52760
+ onNone: () => repositories,
52761
+ onSome: (value) => append$1(repositories, value)
52762
+ })))));
52763
+ return pipe(entries, filter$1((entry) => !excludedDiscoveryEntries.has(entry) && !(startsWith(".")(entry) && entry !== ".git")), forEach$1((entry) => pipe(fs.stat(path.join(root, entry)), map$4((info) => info.type === "Directory" ? path.join(root, entry) : ""), orElseSucceed(() => ""))), flatMap$2((nextRoots) => collectRepositoriesFromRoots(pipe(nextRoots, filter$1(isNonEmpty$1), appendAll(drop$1(roots, 1))), repositories)));
52689
52764
  }));
52690
52765
  }
52691
52766
  });
52692
52767
  });
52693
- const listWorktrees = fnUntraced(function* (cwd) {
52694
- return yield* pipe(yield* git.lines(cwd, [
52768
+ const listWorktrees = fn("GitWorkspace.listWorktrees")(function* (cwd) {
52769
+ yield* annotateCurrentSpan({ cwd });
52770
+ const worktrees = yield* pipe(git.string(cwd, [
52695
52771
  "worktree",
52696
52772
  "list",
52697
- "--porcelain"
52698
- ]), reduce({
52699
- currentBranch: "",
52700
- currentRoot: "",
52701
- hasCurrentCommit: false,
52702
- worktrees: empty$13()
52703
- }, (state, line) => {
52704
- if (startsWith("worktree ")(line)) return {
52705
- currentBranch: "",
52706
- currentRoot: replace(/^worktree\s+/u, "")(line),
52707
- hasCurrentCommit: false,
52708
- worktrees: isNonEmpty$1(state.currentRoot) && state.hasCurrentCommit ? append$1(state.worktrees, {
52709
- branch: state.currentBranch,
52710
- root: state.currentRoot
52711
- }) : state.worktrees
52712
- };
52713
- if (startsWith("HEAD ")(line)) return {
52714
- currentBranch: state.currentBranch,
52715
- currentRoot: state.currentRoot,
52716
- hasCurrentCommit: true,
52717
- worktrees: state.worktrees
52718
- };
52719
- if (startsWith("branch refs/heads/")(line)) return {
52720
- currentBranch: replace(/^branch\s+refs\/heads\//u, "")(line),
52721
- currentRoot: state.currentRoot,
52722
- hasCurrentCommit: state.hasCurrentCommit,
52723
- worktrees: state.worktrees
52724
- };
52725
- return state;
52726
- }), (state) => isNonEmpty$1(state.currentRoot) && state.hasCurrentCommit ? append$1(state.worktrees, {
52727
- branch: state.currentBranch,
52728
- root: state.currentRoot
52729
- }) : state.worktrees, forEach$1((worktree) => pipe(getWorktreeStatus(worktree.root, isNonEmpty$1(worktree.branch) ? worktree.branch : void 0), map$4((status) => new GitWorktree$1({
52730
- branch: isNonEmpty$1(worktree.branch) ? worktree.branch : void 0,
52773
+ "--porcelain",
52774
+ "-z"
52775
+ ]), flatMap$2((output) => pipe(sync(() => parseWorktreeRecords(output)), withSpan("GitWorkspace.parseWorktrees", { attributes: { cwd } }))));
52776
+ yield* annotateCurrentSpan({ worktreeCount: length(worktrees) });
52777
+ return yield* forEach$1(worktrees, (worktree) => pipe(getWorktreeStatus(worktree.root, worktree.branch), map$4((status) => new GitWorktree({
52778
+ branch: worktree.branch,
52731
52779
  root: worktree.root,
52732
52780
  status
52733
- })))));
52781
+ }))));
52734
52782
  });
52735
- const listRepositoriesFrom = fnUntraced(function* (cwd) {
52736
- return yield* pipe(fs.realPath(cwd), orElseSucceed(() => cwd), flatMap$2((root) => collectRepositoriesFromRoots([root], empty$13())), map$4((repositories) => pipe(repositories, getSuccesses, dedupeWith((left, right) => left.gitDirectory === right.gitDirectory))));
52783
+ const listRepositoriesFrom = fn("GitWorkspace.listRepositoriesFrom")(function* (cwd) {
52784
+ yield* annotateCurrentSpan({ cwd });
52785
+ return yield* pipe(fs.realPath(cwd), orElseSucceed(() => cwd), flatMap$2((root) => collectRepositoriesFromRoots([root], empty$13())), map$4((repositories) => pipe(repositories, dedupeWith((left, right) => left.gitDirectory === right.gitDirectory || left.root === right.root))));
52737
52786
  });
52738
- const listProjectsFrom = fnUntraced(function* (cwd) {
52787
+ const listProjectsFrom = fn("GitWorkspace.listProjectsFrom")(function* (cwd) {
52788
+ yield* annotateCurrentSpan({ cwd });
52739
52789
  return pipe(yield* pipe(listRepositoriesFrom(cwd), flatMap$2(forEach$1((repository) => option$1(pipe(listWorktrees(repository.root), map$4((discoveredWorktrees) => new GitProject({
52740
52790
  repository: new GitRepository({
52741
52791
  gitDirectory: repository.gitDirectory,
@@ -52744,17 +52794,15 @@ var GitWorkspace = class extends Service()("@deslop/git/service/GitWorkspace", {
52744
52794
  worktrees: sortWith(discoveredWorktrees, (worktree) => `${worktree.root === (discoveredWorktrees[0]?.root ?? repository.root) ? "0" : "1"}:${worktree.branch ?? ""}:${worktree.root}`, String$5)
52745
52795
  })))), { concurrency: "unbounded" }))), getSomes, sortWith((project) => project.repository.root, String$5));
52746
52796
  });
52747
- const refreshProjects = fnUntraced(function* () {
52797
+ const refreshProjects = fn("GitWorkspace.refreshProjects")(function* () {
52798
+ yield* annotateCurrentSpan({ cwd: home });
52748
52799
  yield* set(projects, yield* listProjectsFrom(home));
52749
52800
  });
52750
52801
  yield* refreshProjects();
52751
- yield* acquireRelease(sync(() => NFS.watch(home, () => {
52752
- run(refreshProjects());
52753
- })), (watcher) => sync(() => {
52754
- watcher.close();
52755
- }));
52802
+ yield* acquireRelease(sync(() => NFS.watch(home, () => void run(refreshProjects()))), (watcher) => sync(() => watcher.close()));
52756
52803
  return {
52757
- branches: fnUntraced(function* (cwd) {
52804
+ branches: fn("GitWorkspace.branches")(function* (cwd) {
52805
+ yield* annotateCurrentSpan({ cwd });
52758
52806
  return new GitBranchesSnapshot({
52759
52807
  branches: yield* pipe(git.lines(cwd, [
52760
52808
  "for-each-ref",
@@ -52767,38 +52815,23 @@ var GitWorkspace = class extends Service()("@deslop/git/service/GitWorkspace", {
52767
52815
  "for-each-ref",
52768
52816
  "--format=%(refname:short)",
52769
52817
  "refs/remotes"
52770
- ]), map$4((lines) => pipe(lines, filter$2((name) => !endsWith("/HEAD")(name)), map$7((name) => new GitBranch({
52818
+ ]), map$4((lines) => pipe(lines, filter$1((name) => !endsWith("/HEAD")(name)), map$7((name) => new GitBranch({
52771
52819
  name: pipe(split$1("/")(name), drop$1(1), join$2("/")),
52772
52820
  remote: split$1("/")(name)[0],
52773
52821
  type: "remote"
52774
- })), filter$2((branch) => isNonEmpty$1(branch.name)), appendAll(localBranches)))))),
52822
+ })), filter$1((branch) => isNonEmpty$1(branch.name)), appendAll(localBranches)))))),
52775
52823
  defaultBranch: yield* getDefaultBranch(cwd)
52776
52824
  });
52777
52825
  }),
52778
- clone: fnUntraced(function* (input) {
52779
- const targetDirectory = path.isAbsolute(input.directory) ? input.directory : path.join(input.cwd, input.directory);
52780
- yield* pipe(fs.makeDirectory(targetDirectory, { recursive: true }), ignore$1);
52781
- yield* pipe(execString(make$40("git", [
52782
- "clone",
52783
- "--depth",
52784
- "1",
52785
- "--single-branch",
52786
- input.url,
52787
- targetDirectory
52788
- ], { cwd: input.cwd })), asVoid, catch_$2(() => pipe(execString(make$40("git", [
52789
- "-C",
52790
- targetDirectory,
52791
- "pull",
52792
- "--ff-only"
52793
- ])), asVoid, mapError$2((cause) => new GitError({
52794
- cause,
52795
- message: `failed to update ${targetDirectory} from ${input.url}`
52796
- })))));
52797
- }),
52798
- createWorktree: fnUntraced(function* (input) {
52826
+ createWorktree: fn("GitWorkspace.createWorktree")(function* (input) {
52827
+ yield* annotateCurrentSpan({
52828
+ branch: input.branch,
52829
+ cwd: input.cwd
52830
+ });
52799
52831
  const targetDirectory = path.join(home, ".deslop", "worktrees", `${replaceAll(/[^a-zA-Z0-9._-]+/gu, "-")(path.basename(input.cwd))}-${replaceAll(/[^a-zA-Z0-9._-]+/gu, "-")(input.branch)}-${yield* nextIntBetween(1e5, 999999)}`);
52800
52832
  yield* pipe(fs.makeDirectory(path.dirname(targetDirectory), { recursive: true }), ignore$1);
52801
- if (input.mode === "existing-local") {
52833
+ if (input.source._tag === "local") {
52834
+ yield* annotateCurrentSpan({ source: "local" });
52802
52835
  yield* pipe(git.string(input.cwd, [
52803
52836
  "worktree",
52804
52837
  "add",
@@ -52808,116 +52841,220 @@ var GitWorkspace = class extends Service()("@deslop/git/service/GitWorkspace", {
52808
52841
  yield* refreshProjects();
52809
52842
  return targetDirectory;
52810
52843
  }
52811
- if (input.mode === "existing-remote") {
52844
+ if (input.source._tag === "remote") {
52845
+ const remoteBranch = `${input.source.remote}/${input.branch}`;
52846
+ yield* annotateCurrentSpan({
52847
+ remote: input.source.remote,
52848
+ source: "remote"
52849
+ });
52812
52850
  yield* pipe(git.string(input.cwd, [
52813
52851
  "fetch",
52814
- "--all",
52815
- "--prune"
52816
- ]), ignore$1);
52852
+ "--prune",
52853
+ input.source.remote
52854
+ ]), asVoid);
52817
52855
  yield* pipe(git.string(input.cwd, [
52818
52856
  "worktree",
52819
52857
  "add",
52820
52858
  "-b",
52821
52859
  input.branch,
52822
52860
  targetDirectory,
52823
- input.baseBranch
52861
+ remoteBranch
52824
52862
  ]), asVoid);
52825
52863
  yield* refreshProjects();
52826
52864
  return targetDirectory;
52827
52865
  }
52866
+ const defaultBranch = yield* getDefaultBranch(input.cwd);
52867
+ yield* annotateCurrentSpan({ source: "new" });
52828
52868
  yield* pipe(git.string(input.cwd, [
52829
52869
  "worktree",
52830
52870
  "add",
52831
52871
  "-b",
52832
52872
  input.branch,
52833
52873
  targetDirectory,
52834
- input.baseBranch
52874
+ `origin/${defaultBranch}`
52835
52875
  ]), asVoid);
52836
52876
  yield* refreshProjects();
52837
52877
  return targetDirectory;
52838
52878
  }),
52839
- deleteWorktree: fnUntraced(function* (input) {
52840
- const worktree = yield* pipe(git.lines(input.cwd, [
52879
+ deleteWorktree: fn("GitWorkspace.deleteWorktree")(function* (input) {
52880
+ yield* annotateCurrentSpan({ cwd: input.cwd });
52881
+ const worktrees = yield* pipe(git.string(input.cwd, [
52841
52882
  "worktree",
52842
52883
  "list",
52843
- "--porcelain"
52844
- ]), map$4((lines) => pipe(lines, reduce({
52845
- branch: "",
52846
- currentBranch: "",
52847
- currentRoot: "",
52848
- found: false,
52849
- mainRoot: input.cwd
52850
- }, (state, line) => {
52851
- if (state.found) return state;
52852
- if (startsWith("worktree ")(line)) return {
52853
- branch: state.branch,
52854
- currentBranch: "",
52855
- currentRoot: replace(/^worktree\s+/u, "")(line),
52856
- found: state.found,
52857
- mainRoot: state.mainRoot === input.cwd ? replace(/^worktree\s+/u, "")(line) : state.mainRoot
52858
- };
52859
- if (startsWith("branch refs/heads/")(line)) return {
52860
- branch: state.currentRoot === input.cwd ? replace(/^branch\s+refs\/heads\//u, "")(line) : state.branch,
52861
- currentBranch: replace(/^branch\s+refs\/heads\//u, "")(line),
52862
- currentRoot: state.currentRoot,
52863
- found: state.currentRoot === input.cwd,
52864
- mainRoot: state.mainRoot
52865
- };
52866
- return state;
52867
- }), (state) => ({
52868
- branch: isNonEmpty$1(state.branch) ? state.branch : void 0,
52869
- mainRoot: state.mainRoot
52870
- }))));
52871
- yield* pipe(git.string(worktree.mainRoot, [
52884
+ "--porcelain",
52885
+ "-z"
52886
+ ]), map$4(parseWorktreeRecords));
52887
+ const mainRoot = worktrees[0]?.root ?? input.cwd;
52888
+ const branch = pipe(worktrees, findFirst$2((worktree) => worktree.root === input.cwd), getOrUndefined$1)?.branch;
52889
+ yield* pipe(git.string(mainRoot, [
52872
52890
  "worktree",
52873
52891
  "remove",
52874
- ...input.force ? ["--force"] : [],
52892
+ "--force",
52875
52893
  input.cwd
52876
52894
  ]), asVoid);
52877
- if (isNotUndefined(worktree.branch)) yield* pipe(git.string(worktree.mainRoot, [
52895
+ if (isNotUndefined(branch)) yield* pipe(git.string(mainRoot, [
52878
52896
  "branch",
52879
52897
  "-D",
52880
- worktree.branch
52898
+ branch
52881
52899
  ]), ignore$1);
52882
52900
  yield* refreshProjects();
52883
52901
  }),
52884
52902
  listProjectsFrom,
52885
52903
  listRepositoriesFrom,
52886
52904
  listWorktrees,
52887
- projects
52905
+ projects,
52906
+ refreshProjects
52888
52907
  };
52889
52908
  }) }) {
52890
52909
  static layer = effect(this, this.make);
52891
52910
  };
52892
- var GitWorktree = class extends Service()("@deslop/git/service/GitWorktree", { make: fnUntraced(function* (config) {
52893
- const execString = yield* ChildProcessSpawner.useSync((spawner) => spawner.string);
52894
- const git = yield* makeGitExecutor;
52911
+ var GitMaintenance = class extends Service()("@deslop/git/service/GitMaintenance", { make: gen(function* () {
52912
+ const git = yield* GitCommand;
52895
52913
  const fs = yield* FileSystem;
52896
52914
  const path = yield* Path$1;
52897
- const hasWorktreeChanges = pipe(git.lines(config.cwd, ["status", "--porcelain"]), map$4((lines) => !isReadonlyArrayEmpty(lines)));
52898
- const resolveFrom = fnUntraced(function* (from) {
52899
- if (from.type === "ref") return from.ref;
52900
- return yield* pipe(git.string(config.cwd, [
52901
- "merge-base",
52902
- from.base,
52903
- "HEAD"
52904
- ]), map$4(trim));
52915
+ const home = yield* pipe(string("HOME"), withDefault(process.cwd()));
52916
+ const maintenanceLock = yield* make$47(1);
52917
+ const collectRepositoriesFromRoots = fn("GitMaintenance.collectRepositoriesFromRoots")(function* (roots, repositories) {
52918
+ yield* annotateCurrentSpan({
52919
+ repositoryCount: length(repositories),
52920
+ rootCount: length(roots)
52921
+ });
52922
+ return yield* match$2(roots, {
52923
+ onEmpty: () => succeed$3(repositories),
52924
+ onNonEmpty: (remainingRoots) => {
52925
+ const root = remainingRoots[0];
52926
+ return pipe(fs.readDirectory(root), orElseSucceed(() => empty$13()), flatMap$2((entries) => {
52927
+ if (contains(entries, ".git")) return pipe(all({
52928
+ gitDirectory: pipe(git.string(root, [
52929
+ "rev-parse",
52930
+ "--path-format=absolute",
52931
+ "--git-common-dir"
52932
+ ]), map$4(trim)),
52933
+ worktrees: pipe(git.string(root, [
52934
+ "worktree",
52935
+ "list",
52936
+ "--porcelain",
52937
+ "-z"
52938
+ ]), map$4(parseWorktreeRecords))
52939
+ }, { concurrency: "unbounded" }), map$4((repository) => new GitRepository({
52940
+ gitDirectory: repository.gitDirectory,
52941
+ root: repository.worktrees[0]?.root ?? root
52942
+ })), option$1, flatMap$2((repository) => collectRepositoriesFromRoots(drop$1(remainingRoots, 1), pipe(repository, match$4({
52943
+ onNone: () => repositories,
52944
+ onSome: (value) => append$1(repositories, value)
52945
+ })))));
52946
+ return pipe(entries, filter$1((entry) => !excludedDiscoveryEntries.has(entry) && !(startsWith(".")(entry) && entry !== ".git")), forEach$1((entry) => pipe(fs.stat(path.join(root, entry)), map$4((info) => info.type === "Directory" ? path.join(root, entry) : ""), orElseSucceed(() => ""))), flatMap$2((nextRoots) => collectRepositoriesFromRoots(pipe(nextRoots, filter$1(isNonEmpty$1), appendAll(drop$1(roots, 1))), repositories)));
52947
+ }));
52948
+ }
52949
+ });
52950
+ });
52951
+ const listRepositoriesFrom = fn("GitMaintenance.listRepositoriesFrom")(function* (cwd) {
52952
+ yield* annotateCurrentSpan({ cwd });
52953
+ return yield* pipe(fs.realPath(cwd), orElseSucceed(() => cwd), flatMap$2((root) => collectRepositoriesFromRoots([root], empty$13())), map$4((repositories) => pipe(repositories, dedupeWith((left, right) => left.gitDirectory === right.gitDirectory || left.root === right.root))));
52954
+ });
52955
+ const maintain = fn("GitMaintenance.maintain")(function* (cwd) {
52956
+ yield* annotateCurrentSpan({ cwd });
52957
+ yield* pipe(gen(function* () {
52958
+ const repositories = yield* listRepositoriesFrom(cwd);
52959
+ yield* annotateCurrentSpan({ repositoryCount: length(repositories) });
52960
+ yield* forEach$1(repositories, (repository) => gen(function* () {
52961
+ yield* pipe(git.string(repository.root, [
52962
+ "fetch",
52963
+ "--all",
52964
+ "--prune"
52965
+ ]), asVoid, withSpan("GitMaintenance.fetch", { attributes: { cwd: repository.root } }));
52966
+ const worktrees = parseWorktreeRecords(yield* git.string(repository.root, [
52967
+ "worktree",
52968
+ "list",
52969
+ "--porcelain",
52970
+ "-z"
52971
+ ]));
52972
+ yield* forEach$1(yield* git.lines(repository.root, [
52973
+ "for-each-ref",
52974
+ "refs/heads",
52975
+ "--format=%(refname:short)%00%(upstream:short)%00%(upstream:track)%00%(worktreepath)"
52976
+ ]), (row) => pipe(gen(function* () {
52977
+ const fields = split$1("\0")(row);
52978
+ const branch = fields[0];
52979
+ const upstream = fields[1] ?? "";
52980
+ const track = fields[2] ?? "";
52981
+ const worktreePath = fields[3] ?? pipe(worktrees, findFirst$2((worktree) => worktree.branch === branch), map$9((worktree) => worktree.root), getOrElse$1(() => ""));
52982
+ yield* annotateCurrentSpan({
52983
+ branch,
52984
+ cwd: repository.root
52985
+ });
52986
+ if (isEmpty$1(branch)) return;
52987
+ if (track === "[gone]") {
52988
+ if (isNonEmpty$1(worktreePath)) yield* pipe(git.string(repository.root, [
52989
+ "worktree",
52990
+ "remove",
52991
+ "--force",
52992
+ worktreePath
52993
+ ]), asVoid, withSpan("GitMaintenance.deleteWorktree", { attributes: {
52994
+ branch,
52995
+ cwd: repository.root
52996
+ } }));
52997
+ yield* pipe(git.string(repository.root, [
52998
+ "branch",
52999
+ "-D",
53000
+ branch
53001
+ ]), asVoid, withSpan("GitMaintenance.deleteBranch", { attributes: {
53002
+ branch,
53003
+ cwd: repository.root
53004
+ } }));
53005
+ return;
53006
+ }
53007
+ if (isEmpty$1(upstream) || !includes("behind")(track) || includes("ahead")(track)) return;
53008
+ if (isNonEmpty$1(worktreePath)) {
53009
+ yield* pipe(git.string(worktreePath, [
53010
+ "merge",
53011
+ "--ff-only",
53012
+ upstream
53013
+ ]), ignore$1, withSpan("GitMaintenance.fastForwardWorktree", { attributes: {
53014
+ branch,
53015
+ cwd: worktreePath
53016
+ } }));
53017
+ return;
53018
+ }
53019
+ yield* pipe(git.string(repository.root, [
53020
+ "merge-base",
53021
+ "--is-ancestor",
53022
+ branch,
53023
+ upstream
53024
+ ]), andThen(git.string(repository.root, [
53025
+ "branch",
53026
+ "-f",
53027
+ branch,
53028
+ upstream
53029
+ ])), ignore$1, withSpan("GitMaintenance.fastForwardBranch", { attributes: {
53030
+ branch,
53031
+ cwd: repository.root
53032
+ } }));
53033
+ }), withSpan("GitMaintenance.classifyBranch", { attributes: { cwd: repository.root } })), { concurrency: "unbounded" });
53034
+ }), { concurrency: "unbounded" });
53035
+ }), withPermit(maintenanceLock));
52905
53036
  });
53037
+ yield* pipe(maintain(home), ignore$1, andThen(sleep(seconds(180))), forever, forkScoped);
53038
+ return { maintain };
53039
+ }) }) {
53040
+ static layer = effect(this, this.make);
53041
+ };
53042
+ var GitReview = class extends Service()("@deslop/git/service/GitReview", { make: fn("GitReview.make")(function* (config) {
53043
+ const spawner = yield* ChildProcessSpawner;
53044
+ const git = yield* GitCommand;
53045
+ const fs = yield* FileSystem;
53046
+ const path = yield* Path$1;
53047
+ const hasWorktreeChanges = pipe(git.lines(config.cwd, ["status", "--porcelain"]), map$4((lines) => !isReadonlyArrayEmpty(lines)));
52906
53048
  function diffsFromPatch(patch, segments) {
52907
53049
  const groupedSegments = segmentsByFile(segments);
52908
- return pipe(patch.split(/(?=^diff --git )/mu), filter$2(isNonEmpty$1), map$7((chunk) => diffFromPatchChunk(chunk, groupedSegments)));
52909
- }
52910
- function attachSegments(diffs, segments) {
52911
- const groupedSegments = segmentsByFile(segments);
52912
- return map$7(diffs, (diff) => new GitDiff({
52913
- filePath: diff.filePath,
52914
- patch: diff.patch,
52915
- segments: getOrElse$1(get$1(groupedSegments, diff.filePath), () => empty$13()),
52916
- status: diff.status
52917
- }));
53050
+ return pipe(patch.split(/(?=^diff --git )/mu), filter$1((chunk) => /^diff --git /u.test(chunk)), map$7((chunk) => diffFromPatchChunk(chunk, groupedSegments)));
52918
53051
  }
52919
- const gitDiffs = fnUntraced(function* (input) {
52920
- return diffsFromPatch(yield* git.string(config.cwd, [
53052
+ const gitDiffs = fn("GitReview.gitDiffs")(function* (input) {
53053
+ yield* annotateCurrentSpan({
53054
+ cwd: config.cwd,
53055
+ segmentCount: length(input.segments)
53056
+ });
53057
+ const diffs = diffsFromPatch(yield* git.string(config.cwd, [
52921
53058
  "diff",
52922
53059
  ...input.args,
52923
53060
  "--ignore-all-space",
@@ -52925,54 +53062,53 @@ var GitWorktree = class extends Service()("@deslop/git/service/GitWorktree", { m
52925
53062
  "--ignore-cr-at-eol",
52926
53063
  "--patch",
52927
53064
  "--find-renames",
52928
- "-U999999",
52929
53065
  "--no-ext-diff"
52930
53066
  ]), input.segments);
53067
+ yield* annotateCurrentSpan({ diffCount: length(diffs) });
53068
+ return diffs;
53069
+ });
53070
+ const commitDiffs = fn("GitReview.commitDiffs")(function* (hash) {
53071
+ yield* annotateCurrentSpan({ cwd: config.cwd });
53072
+ const diffs = diffsFromPatch(yield* git.string(config.cwd, [
53073
+ "diff-tree",
53074
+ "--root",
53075
+ "--first-parent",
53076
+ "-m",
53077
+ "--patch",
53078
+ "--ignore-all-space",
53079
+ "--ignore-blank-lines",
53080
+ "--ignore-cr-at-eol",
53081
+ "--find-renames",
53082
+ "--no-ext-diff",
53083
+ hash
53084
+ ]), empty$13());
53085
+ yield* annotateCurrentSpan({ diffCount: length(diffs) });
53086
+ return diffs;
52931
53087
  });
52932
53088
  const untrackedDiffs = pipe(git.lines(config.cwd, [
52933
53089
  "ls-files",
52934
53090
  "--others",
52935
53091
  "--exclude-standard"
52936
- ]), flatMap$2((files) => forEach$1(files, (filePath) => pipe(fs.readFileString(path.join(config.cwd, filePath)), orElseSucceed(() => ""), map$4((content) => new GitDiff({
52937
- filePath,
52938
- patch: `diff --git a/${filePath} b/${filePath}\nnew file mode 100644\n--- /dev/null\n+++ b/${filePath}\n@@ -0,0 +1,${length(split$1("\n")(content))} @@\n${pipe(split$1("\n")(content), map$7((line) => `+${line}`), join$2("\n"))}`,
52939
- segments: [new GitDiffSegment({
53092
+ ]), flatMap$2((files) => forEach$1(files, (filePath) => pipe(fs.readFileString(path.join(config.cwd, filePath)), orElseSucceed(() => ""), map$4((content) => {
53093
+ const patch = `diff --git a/${filePath} b/${filePath}\nnew file mode 100644\n--- /dev/null\n+++ b/${filePath}\n@@ -0,0 +1,${length(split$1("\n")(content))} @@\n${pipe(split$1("\n")(content), map$7((line) => `+${line}`), join$2("\n"))}`;
53094
+ return new GitDiff({
52940
53095
  filePath,
52941
- fingerprint: content,
52942
- id: "HEAD->worktree",
52943
- type: "worktree"
52944
- })],
52945
- status: "added"
52946
- }))), { concurrency: "unbounded" })));
52947
- const commitSegmentDiffs = fnUntraced(function* (input) {
52948
- return pipe((yield* git.string(config.cwd, [
52949
- "log",
52950
- "--reverse",
52951
- "--format=%x00DESLOP-COMMIT%x00%H%x00%P",
52952
- "--find-renames",
52953
- "--name-only",
52954
- `${input.from}..${input.to}`
52955
- ])).split("\0DESLOP-COMMIT\0"), filter$2(isNonEmpty$1), flatMap$5((entry) => {
52956
- const lines = split$1("\n")(entry);
52957
- const header = lines[0];
52958
- const parts = split$1("\0")(header);
52959
- const commit = parts[0];
52960
- const id = `${pipe(parts[1] ?? "", split$1(" "), filter$2(isNonEmpty$1))[0] ?? `${commit}^`}->${commit}`;
52961
- return pipe(drop$1(lines, 1), filter$2(isNonEmpty$1), map$7((filePath) => new GitDiffSegment({
53096
+ patch,
53097
+ segments: [new GitDiffSegment({
52962
53098
  filePath,
52963
- fingerprint: `${id}:${filePath}`,
52964
- id,
52965
- type: "commit"
52966
- })));
52967
- }));
52968
- });
52969
- const reviewRangeDiffs = fnUntraced(function* (input) {
52970
- const from = yield* resolveFrom(input.from);
52971
- const to = input.to.type === "ref" ? input.to.ref : "HEAD";
52972
- if (from === "HEAD" && input.to.type === "worktree") return yield* pipe(untrackedDiffs, map$4(appendAll(pipe(yield* gitDiffs({
53099
+ fingerprint: patch,
53100
+ id: "HEAD->worktree",
53101
+ type: "worktree"
53102
+ })],
53103
+ status: "added"
53104
+ });
53105
+ })), { concurrency: "unbounded" })));
53106
+ const worktreeDiffs = gen(function* () {
53107
+ if (isReadonlyArrayEmpty(yield* git.lines(config.cwd, ["status", "--porcelain"]))) return empty$13();
53108
+ return yield* pipe(all([gitDiffs({
52973
53109
  args: ["HEAD"],
52974
53110
  segments: empty$13()
52975
- }), map$7((diff) => {
53111
+ }), untrackedDiffs], { concurrency: "unbounded" }), map$4(([trackedDiffs, untracked]) => appendAll(map$7(trackedDiffs, (diff) => {
52976
53112
  const segment = new GitDiffSegment({
52977
53113
  filePath: diff.filePath,
52978
53114
  fingerprint: diff.patch,
@@ -52985,41 +53121,95 @@ var GitWorktree = class extends Service()("@deslop/git/service/GitWorktree", { m
52985
53121
  segments: [segment],
52986
53122
  status: diff.status
52987
53123
  });
52988
- })))));
52989
- const [commitSegments, trackedWorktreeDiffs, untracked, diffs] = yield* all([
52990
- commitSegmentDiffs({
52991
- from,
52992
- to
52993
- }),
52994
- input.to.type === "worktree" ? gitDiffs({
52995
- args: ["HEAD"],
52996
- segments: empty$13()
52997
- }) : succeed$3(empty$13()),
52998
- input.to.type === "worktree" ? untrackedDiffs : succeed$3(empty$13()),
52999
- gitDiffs({
53000
- args: [from, ...toArgs(input.to)],
53001
- segments: empty$13()
53002
- })
53003
- ], { concurrency: "unbounded" });
53004
- const diffsWithSegments = attachSegments(diffs, appendAll(commitSegments, pipe(trackedWorktreeDiffs, map$7((diff) => new GitDiffSegment({
53124
+ }), untracked)));
53125
+ }).pipe(withSpan("GitReview.worktreeDiffs", { attributes: { cwd: config.cwd } }));
53126
+ const fileContent = fn("GitReview.fileContent")(function* (input) {
53127
+ yield* annotateCurrentSpan({
53128
+ cwd: config.cwd,
53129
+ filePath: input.filePath,
53130
+ target: input.target._tag
53131
+ });
53132
+ if (input.target._tag !== "commit") return yield* pipe(fs.readFileString(path.join(config.cwd, input.filePath)), orElseSucceed(() => ""));
53133
+ return yield* pipe(git.string(config.cwd, ["show", `${input.target.hash}:${input.filePath}`]), orElseSucceed(() => ""));
53134
+ });
53135
+ const withFileContent = fn("GitReview.withFileContent")(function* (input) {
53136
+ const contents = yield* forEach$1(input.diffs, (diff) => pipe(fileContent({
53005
53137
  filePath: diff.filePath,
53006
- fingerprint: diff.patch,
53007
- id: "HEAD->worktree",
53008
- type: "worktree"
53009
- })), appendAll(flatMap$5(untracked, (diff) => diff.segments)))));
53010
- if (input.to.type === "ref") return diffsWithSegments;
53011
- return appendAll(diffsWithSegments, untracked);
53138
+ target: input.target
53139
+ }), map$4((content) => [diff.filePath, content])), { concurrency: "unbounded" });
53140
+ const contentByFilePath = new Map(contents);
53141
+ return map$7(input.diffs, (diff) => contentByFilePath.has(diff.filePath) ? new GitDiff({
53142
+ fileContent: contentByFilePath.get(diff.filePath),
53143
+ filePath: diff.filePath,
53144
+ patch: diff.patch,
53145
+ segments: diff.segments,
53146
+ status: diff.status
53147
+ }) : diff);
53148
+ });
53149
+ const reviewDiffs = fn("GitReview.reviewDiffs")(function* (target) {
53150
+ yield* annotateCurrentSpan({
53151
+ cwd: config.cwd,
53152
+ target: target._tag
53153
+ });
53154
+ if (target._tag === "changes") return yield* withFileContent({
53155
+ diffs: yield* worktreeDiffs,
53156
+ target
53157
+ });
53158
+ if (target._tag === "commit") {
53159
+ const id = `${target.hash}^->${target.hash}`;
53160
+ const diffsWithSegments = withDisplayedPatchSegments(yield* commitDiffs(target.hash), id, "commit");
53161
+ yield* annotateCurrentSpan({ diffCount: length(diffsWithSegments) });
53162
+ return yield* withFileContent({
53163
+ diffs: diffsWithSegments,
53164
+ target
53165
+ });
53166
+ }
53167
+ const base = target._tag === "local" ? yield* localBase() : yield* branchDiffBase();
53168
+ const diffsWithSegments = withDisplayedPatchSegments(yield* aggregateDiffs(base), `${base}->worktree`, "worktree");
53169
+ yield* annotateCurrentSpan({ diffCount: length(diffsWithSegments) });
53170
+ return yield* withFileContent({
53171
+ diffs: diffsWithSegments,
53172
+ target
53173
+ });
53012
53174
  });
53013
- const ghString = fnUntraced(function* (args) {
53014
- return yield* pipe(execString(make$40("gh", args, { cwd: config.cwd })), mapError$2((cause) => new GitError({ cause })));
53175
+ const ghString = fn("gh.string")(function* (args) {
53176
+ yield* annotateCurrentSpan({
53177
+ command: args[0] ?? "gh",
53178
+ cwd: config.cwd
53179
+ });
53180
+ return yield* scoped$3(gen(function* () {
53181
+ const handle = yield* pipe(spawner.spawn(make$40("gh", args, {
53182
+ cwd: config.cwd,
53183
+ stderr: "pipe",
53184
+ stdout: "pipe"
53185
+ })), mapError$2((cause) => new GitError({ cause })));
53186
+ const output = yield* all({
53187
+ stderr: pipe(decodeText(handle.stderr), mkString, orElseSucceed(() => "")),
53188
+ stdout: pipe(decodeText(handle.stdout), mkString, orElseSucceed(() => ""))
53189
+ }, { concurrency: "unbounded" });
53190
+ const exitCode = yield* pipe(handle.exitCode, mapError$2((cause) => new GitError({ cause })));
53191
+ if (exitCode !== ExitCode(0)) return yield* new GitError({ cause: new Error(output.stderr || output.stdout || `gh ${join$2(" ")(args)} exited with ${exitCode}`) });
53192
+ return output.stdout;
53193
+ })).pipe(withSpan("gh.command", { attributes: {
53194
+ command: args[0] ?? "gh",
53195
+ cwd: config.cwd
53196
+ } }));
53015
53197
  });
53016
53198
  const currentBranch = pipe(git.string(config.cwd, ["branch", "--show-current"]), map$4(trim));
53017
53199
  const defaultBranchName = pipe(git.string(config.cwd, [
53018
53200
  "symbolic-ref",
53019
53201
  "--short",
53020
53202
  "refs/remotes/origin/HEAD"
53021
- ]), map$4(flow(trim, replace(/^origin\//u, ""))));
53022
- const branchBase = fnUntraced(function* (defaultBranch) {
53203
+ ]), map$4(flow(trim, replace(/^origin\//u, ""))), catchTag("GitError", () => pipe(git.string(config.cwd, [
53204
+ "rev-parse",
53205
+ "--verify",
53206
+ "main"
53207
+ ]), as("main"), catchTag("GitError", () => succeed$3("master")))));
53208
+ const branchBase = fn("GitReview.branchBase")(function* (defaultBranch) {
53209
+ yield* annotateCurrentSpan({
53210
+ cwd: config.cwd,
53211
+ defaultBranch
53212
+ });
53023
53213
  return yield* pipe([`origin/${defaultBranch}`, defaultBranch], findFirst((candidate) => pipe(git.string(config.cwd, [
53024
53214
  "rev-parse",
53025
53215
  "--verify",
@@ -53033,19 +53223,9 @@ var GitWorktree = class extends Service()("@deslop/git/service/GitWorktree", { m
53033
53223
  "url",
53034
53224
  "--jq",
53035
53225
  ".url"
53036
- ]), map$4(trim), map$4((url) => isNonEmpty$1(url) ? some$1(url) : none()), catchTag("GitError", () => succeed$3(none())));
53037
- function commitFromLogLine(line) {
53038
- const parts = split$1("\0")(line);
53039
- const subject = parts[2] ?? "";
53040
- return new GitCommit({
53041
- hash: parts[0],
53042
- parents: pipe(parts[3] ?? "", split$1(" "), filter$2(isNonEmpty$1)),
53043
- shortHash: parts[1] ?? "",
53044
- subject,
53045
- wip: isWipSubject(subject)
53046
- });
53047
- }
53048
- const commits = fnUntraced(function* (base) {
53226
+ ]), map$4(trim), map$4((url) => isNonEmpty$1(url) ? some(url) : none()), catchTag("GitError", () => succeed$3(none())));
53227
+ const commits = fn("GitReview.commits")(function* (base) {
53228
+ yield* annotateCurrentSpan({ cwd: config.cwd });
53049
53229
  const from = yield* pipe(git.string(config.cwd, [
53050
53230
  "merge-base",
53051
53231
  base,
@@ -53054,59 +53234,82 @@ var GitWorktree = class extends Service()("@deslop/git/service/GitWorktree", { m
53054
53234
  return yield* pipe(git.lines(config.cwd, [
53055
53235
  "log",
53056
53236
  "--max-count=80",
53057
- "--format=%H%x00%h%x00%s%x00%P",
53237
+ "--format=%H%x00%h%x00%s",
53058
53238
  `${from}..HEAD`
53059
53239
  ]), map$4(map$7(commitFromLogLine)));
53060
53240
  });
53241
+ const commitsBetween = fn("GitReview.commitsBetween")(function* (from, to) {
53242
+ yield* annotateCurrentSpan({ cwd: config.cwd });
53243
+ return yield* pipe(git.lines(config.cwd, [
53244
+ "log",
53245
+ "--max-count=80",
53246
+ "--format=%H%x00%h%x00%s",
53247
+ `${from}..${to}`
53248
+ ]), map$4(map$7(commitFromLogLine)));
53249
+ });
53061
53250
  const firstParentCommits = pipe(git.lines(config.cwd, [
53062
53251
  "log",
53063
53252
  "--first-parent",
53064
53253
  "--max-count=80",
53065
- "--format=%H%x00%h%x00%s%x00%P",
53254
+ "--format=%H%x00%h%x00%s",
53066
53255
  "HEAD"
53067
53256
  ]), map$4(map$7(commitFromLogLine)));
53068
- const pushCurrentBranch = gen(function* () {
53069
- const branch = yield* currentBranch;
53070
- yield* pipe(git.string(config.cwd, [
53071
- "push",
53072
- "-u",
53073
- "origin",
53074
- `HEAD:${branch}`
53075
- ]), asVoid);
53076
- });
53077
- const hasPushableCommits = pipe(gen(function* () {
53078
- const remoteBranch = `origin/${yield* currentBranch}`;
53079
- if (yield* pipe(git.string(config.cwd, [
53257
+ const hasPushableCommits = pipe(fn("GitReview.pushableCommitCount")(function* () {
53258
+ yield* annotateCurrentSpan({ cwd: config.cwd });
53259
+ const upstream = yield* pipe(git.string(config.cwd, [
53080
53260
  "rev-parse",
53081
- "--verify",
53082
- remoteBranch
53083
- ]), as(true), orElseSucceed(() => false))) return yield* git.lines(config.cwd, [
53084
- "log",
53085
- "--format=%s",
53086
- `${remoteBranch}..HEAD`
53087
- ]);
53261
+ "--abbrev-ref",
53262
+ "--symbolic-full-name",
53263
+ "@{u}"
53264
+ ]), map$4(flow(trim, some)), orElseSucceed(() => none()));
53265
+ if (isSome(upstream)) return yield* pipe(git.string(config.cwd, [
53266
+ "rev-list",
53267
+ "--count",
53268
+ `${upstream.value}..HEAD`
53269
+ ]), map$4(flow(trim, parse$2, getOrElse$1(() => 0))));
53088
53270
  const base = yield* branchBase(yield* defaultBranchName);
53089
53271
  const from = yield* pipe(git.string(config.cwd, [
53090
53272
  "merge-base",
53091
53273
  base,
53092
53274
  "HEAD"
53093
53275
  ]), map$4(trim), catchTag("GitError", () => succeed$3(base)));
53094
- return yield* git.lines(config.cwd, [
53095
- "log",
53096
- "--format=%s",
53276
+ return yield* pipe(git.string(config.cwd, [
53277
+ "rev-list",
53278
+ "--count",
53097
53279
  `${from}..HEAD`
53098
- ]);
53099
- }), map$4((subjects) => !some(subjects, isWipSubject) && !isReadonlyArrayEmpty(subjects)));
53100
- const createDraftPr = pipe(ghString([
53101
- "pr",
53102
- "create",
53103
- "--draft",
53104
- "--fill"
53105
- ]), map$4((output) => {
53106
- const url = output.match(/https?:\/\/\S+/u)?.[0] ?? trim(output);
53107
- return isNonEmpty$1(url) ? some$1(url) : none();
53108
- }));
53280
+ ]), map$4(flow(trim, parse$2, getOrElse$1(() => 0))));
53281
+ })(), map$4((count) => count > 0));
53282
+ const localBase = fn("GitReview.localBase")(function* () {
53283
+ const upstream = yield* pipe(git.string(config.cwd, [
53284
+ "rev-parse",
53285
+ "--abbrev-ref",
53286
+ "--symbolic-full-name",
53287
+ "@{u}"
53288
+ ]), map$4(flow(trim, some)), orElseSucceed(() => none()));
53289
+ if (isSome(upstream)) return upstream.value;
53290
+ const base = yield* branchBase(yield* defaultBranchName);
53291
+ return yield* pipe(git.string(config.cwd, [
53292
+ "merge-base",
53293
+ base,
53294
+ "HEAD"
53295
+ ]), map$4(trim), catchTag("GitError", () => succeed$3(base)));
53296
+ });
53297
+ const branchDiffBase = fn("GitReview.branchDiffBase")(function* () {
53298
+ const base = yield* branchBase(yield* defaultBranchName);
53299
+ return yield* pipe(git.string(config.cwd, [
53300
+ "merge-base",
53301
+ base,
53302
+ "HEAD"
53303
+ ]), map$4(trim), catchTag("GitError", () => succeed$3(base)));
53304
+ });
53305
+ const aggregateDiffs = fn("GitReview.aggregateDiffs")(function* (base) {
53306
+ return appendAll(yield* gitDiffs({
53307
+ args: [base],
53308
+ segments: empty$13()
53309
+ }), yield* untrackedDiffs);
53310
+ });
53109
53311
  const prReviewThreads = gen(function* () {
53312
+ yield* annotateCurrentSpan({ cwd: config.cwd });
53110
53313
  const pr = yield* pipe(ghString([
53111
53314
  "pr",
53112
53315
  "view",
@@ -53114,7 +53317,7 @@ var GitWorktree = class extends Service()("@deslop/git/service/GitWorktree", { m
53114
53317
  "number",
53115
53318
  "--jq",
53116
53319
  ".number"
53117
- ]), map$4(flow(trim, parse$2)), flatMap$2(match$5({
53320
+ ]), map$4(flow(trim, parse$2)), flatMap$2(match$4({
53118
53321
  onNone: () => new GitError({ message: "No PR found." }),
53119
53322
  onSome: succeed$3
53120
53323
  })));
@@ -53161,10 +53364,12 @@ var GitWorktree = class extends Service()("@deslop/git/service/GitWorktree", { m
53161
53364
  "-F",
53162
53365
  `number=${pr}`
53163
53366
  ]);
53164
- return pipe((yield* pipe(decodeUnknownEffect(fromJsonString(GitHubReviewThreadsResponse))(response), mapError$2((cause) => new GitError({
53367
+ const threads = (yield* pipe(decodeUnknownEffect(fromJsonString(GitHubReviewThreadsResponse))(response), mapError$2((cause) => new GitError({
53165
53368
  cause,
53166
53369
  message: "Failed to parse GitHub review threads."
53167
- })))).data?.repository?.pullRequest?.reviewThreads?.nodes ?? [], flatMap$5((thread) => pipe(thread.comments.nodes, map$7((comment) => new GitHubReviewThread({
53370
+ })))).data?.repository?.pullRequest?.reviewThreads?.nodes ?? [];
53371
+ yield* annotateCurrentSpan({ threadCount: length(threads) });
53372
+ return pipe(threads, flatMap$5((thread) => pipe(thread.comments.nodes, map$7((comment) => new GitHubReviewThread({
53168
53373
  body: comment.body,
53169
53374
  filePath: comment.path,
53170
53375
  id: thread.id,
@@ -53173,75 +53378,31 @@ var GitWorktree = class extends Service()("@deslop/git/service/GitWorktree", { m
53173
53378
  side: thread.diffSide === "LEFT" ? "deletions" : "additions",
53174
53379
  url: comment.url
53175
53380
  })))));
53176
- });
53381
+ }).pipe(withSpan("GitReview.reviewThreads", { attributes: { cwd: config.cwd } }));
53177
53382
  const worktreeChanges = pipe(make$43(void 0), merge$1(pipe(fs.watch(config.cwd), catch_(() => empty$8), map$2(() => void 0))), debounce(millis(50)));
53178
53383
  return {
53179
- commitAndPush: fnUntraced(function* (input) {
53180
- const oldestWip = pipe(yield* commits(input.base), takeWhile((commit) => commit.wip), last, getOrUndefined$1);
53181
- const dirty = yield* hasWorktreeChanges;
53182
- if (oldestWip) yield* pipe(git.string(config.cwd, [
53183
- "reset",
53184
- "--soft",
53185
- `${oldestWip.hash}^`
53186
- ]), asVoid);
53187
- else if (!dirty) return yield* new GitError({ message: "No changes to commit." });
53188
- yield* pipe(git.string(config.cwd, ["add", "-A"]), asVoid);
53189
- yield* pipe(git.string(config.cwd, [
53190
- "commit",
53191
- "-m",
53192
- input.message
53193
- ]), asVoid);
53194
- yield* pushCurrentBranch;
53195
- if (yield* hasPushableCommits) return yield* new GitError({ message: "Push completed but the branch still has unpushed commits." });
53196
- if ((yield* currentBranch) !== (yield* defaultBranchName) && isNone(yield* branchPrUrl)) yield* createDraftPr;
53197
- }),
53198
53384
  commits,
53199
- createWipCommit: fnUntraced(function* (message) {
53200
- if (!(yield* hasWorktreeChanges)) return yield* new GitError({ message: "No changes to commit." });
53201
- yield* pipe(git.string(config.cwd, ["add", "-A"]), asVoid);
53202
- const subject = pipe(message, trim, (value) => isEmpty$1(value) ? "wip" : `wip: ${value}`);
53203
- yield* pipe(git.string(config.cwd, [
53204
- "commit",
53205
- "-m",
53206
- subject
53207
- ]), asVoid);
53208
- }),
53209
- discardFile: fnUntraced(function* (filePath) {
53210
- yield* pipe(git.string(config.cwd, [
53211
- "reset",
53212
- "HEAD",
53213
- "--",
53214
- filePath
53215
- ]), ignore$1);
53216
- yield* pipe(git.string(config.cwd, [
53217
- "restore",
53218
- "--worktree",
53219
- "--source=HEAD",
53220
- "--",
53221
- filePath
53222
- ]), ignore$1);
53223
- yield* pipe(git.string(config.cwd, [
53224
- "clean",
53225
- "-fd",
53226
- "--",
53227
- filePath
53228
- ]), asVoid);
53229
- }),
53230
- metadata: fnUntraced(function* (input) {
53385
+ metadata: fn("GitReview.metadata")(function* () {
53386
+ yield* annotateCurrentSpan({ cwd: config.cwd });
53231
53387
  const branch = yield* currentBranch;
53232
53388
  const defaultBranch = yield* defaultBranchName;
53233
- const base = input?.base ?? (yield* branchBase(defaultBranch));
53389
+ const branchBaseRef = yield* branchDiffBase();
53390
+ const localCommits = yield* commitsBetween(yield* localBase(), "HEAD");
53391
+ const branchCommitCandidates = branch === defaultBranch ? yield* firstParentCommits : yield* commits(branchBaseRef);
53392
+ const localCommitHashes = new Set(map$7(localCommits, (commit) => commit.hash));
53234
53393
  return new GitReviewMetadata({
53235
- base,
53236
- branch,
53237
- commits: branch === defaultBranch ? yield* firstParentCommits : yield* commits(base),
53238
- defaultBranch,
53394
+ branchCommits: filter$1(branchCommitCandidates, (commit) => !localCommitHashes.has(commit.hash)),
53239
53395
  dirty: yield* hasWorktreeChanges,
53396
+ localCommits,
53240
53397
  prUrl: getOrUndefined$1(yield* branchPrUrl),
53241
53398
  unpushedCommits: yield* hasPushableCommits
53242
53399
  });
53243
53400
  }),
53244
- resolveReviewThread: fnUntraced(function* (threadId) {
53401
+ resolveReviewThread: fn("GitReview.resolveReviewThread")(function* (threadId) {
53402
+ yield* annotateCurrentSpan({
53403
+ cwd: config.cwd,
53404
+ threadId
53405
+ });
53245
53406
  yield* pipe(ghString([
53246
53407
  "api",
53247
53408
  "graphql",
@@ -53258,24 +53419,141 @@ var GitWorktree = class extends Service()("@deslop/git/service/GitWorktree", { m
53258
53419
  `threadId=${threadId}`
53259
53420
  ]), asVoid);
53260
53421
  }),
53261
- reviewRangeDiffs,
53422
+ reviewDiffs,
53262
53423
  reviewThreads: pipe(prReviewThreads, catchTag("GitError", () => succeed$3(empty$13()))),
53263
- stageFile: fnUntraced(function* (filePath) {
53424
+ watchReviewDiffs: (target) => {
53425
+ const diffs = pipe(reviewDiffs(target), catchTag("GitError", () => succeed$3(empty$13())));
53426
+ if (target._tag === "commit") return fromEffect(diffs);
53427
+ return fromEffect(diffs).pipe(concat(pipe(worktreeChanges, mapEffect(() => diffs))), changesWith((left, right) => length(left) === length(right) && every(left, (leftDiff, index) => isNotUndefined(right[index]) && leftDiff.filePath === right[index].filePath && leftDiff.status === right[index].status && leftDiff.patch === right[index].patch)));
53428
+ }
53429
+ };
53430
+ }) }) {
53431
+ static layer = flow(this.make, effect(this));
53432
+ };
53433
+ var GitCommitAction = class extends Service()("@deslop/git/service/GitCommitAction", { make: fn("GitCommitAction.make")(function* (config) {
53434
+ const spawner = yield* ChildProcessSpawner;
53435
+ const git = yield* GitCommand;
53436
+ const ghString = fn("gh.string")(function* (args) {
53437
+ yield* annotateCurrentSpan({
53438
+ command: args[0] ?? "gh",
53439
+ cwd: config.cwd
53440
+ });
53441
+ return yield* scoped$3(gen(function* () {
53442
+ const handle = yield* pipe(spawner.spawn(make$40("gh", args, {
53443
+ cwd: config.cwd,
53444
+ stderr: "pipe",
53445
+ stdout: "pipe"
53446
+ })), mapError$2((cause) => new GitError({ cause })));
53447
+ const output = yield* all({
53448
+ stderr: pipe(decodeText(handle.stderr), mkString, orElseSucceed(() => "")),
53449
+ stdout: pipe(decodeText(handle.stdout), mkString, orElseSucceed(() => ""))
53450
+ }, { concurrency: "unbounded" });
53451
+ const exitCode = yield* pipe(handle.exitCode, mapError$2((cause) => new GitError({ cause })));
53452
+ if (exitCode !== ExitCode(0)) return yield* new GitError({ cause: new Error(output.stderr || output.stdout || `gh ${join$2(" ")(args)} exited with ${exitCode}`) });
53453
+ return output.stdout;
53454
+ })).pipe(withSpan("gh.command", { attributes: {
53455
+ command: args[0] ?? "gh",
53456
+ cwd: config.cwd
53457
+ } }));
53458
+ });
53459
+ const hasWorktreeChanges = pipe(git.lines(config.cwd, ["status", "--porcelain"]), map$4((lines) => !isReadonlyArrayEmpty(lines)));
53460
+ const currentBranch = pipe(git.string(config.cwd, ["branch", "--show-current"]), map$4(trim));
53461
+ const defaultBranchName = pipe(git.string(config.cwd, [
53462
+ "symbolic-ref",
53463
+ "--short",
53464
+ "refs/remotes/origin/HEAD"
53465
+ ]), map$4(flow(trim, replace(/^origin\//u, ""))), catchTag("GitError", () => pipe(git.string(config.cwd, [
53466
+ "rev-parse",
53467
+ "--verify",
53468
+ "main"
53469
+ ]), as("main"), catchTag("GitError", () => succeed$3("master")))));
53470
+ const branchBase = fn("GitCommitAction.branchBase")(function* (defaultBranch) {
53471
+ yield* annotateCurrentSpan({
53472
+ cwd: config.cwd,
53473
+ defaultBranch
53474
+ });
53475
+ return yield* pipe([`origin/${defaultBranch}`, defaultBranch], findFirst((candidate) => pipe(git.string(config.cwd, [
53476
+ "rev-parse",
53477
+ "--verify",
53478
+ candidate
53479
+ ]), as(true), orElseSucceed(() => false))), map$4(getOrElse$1(() => "HEAD")));
53480
+ });
53481
+ const branchPrUrl = pipe(ghString([
53482
+ "pr",
53483
+ "view",
53484
+ "--json",
53485
+ "url",
53486
+ "--jq",
53487
+ ".url"
53488
+ ]), map$4(trim), map$4((url) => isNonEmpty$1(url) ? some(url) : none()), catchTag("GitError", () => succeed$3(none())));
53489
+ const hasPushableCommits = pipe(fn("GitCommitAction.pushableCommitCount")(function* () {
53490
+ yield* annotateCurrentSpan({ cwd: config.cwd });
53491
+ const upstream = yield* pipe(git.string(config.cwd, [
53492
+ "rev-parse",
53493
+ "--abbrev-ref",
53494
+ "--symbolic-full-name",
53495
+ "@{u}"
53496
+ ]), map$4(flow(trim, some)), orElseSucceed(() => none()));
53497
+ if (isSome(upstream)) return yield* pipe(git.string(config.cwd, [
53498
+ "rev-list",
53499
+ "--count",
53500
+ `${upstream.value}..HEAD`
53501
+ ]), map$4(flow(trim, parse$2, getOrElse$1(() => 0))));
53502
+ const base = yield* branchBase(yield* defaultBranchName);
53503
+ const from = yield* pipe(git.string(config.cwd, [
53504
+ "merge-base",
53505
+ base,
53506
+ "HEAD"
53507
+ ]), map$4(trim), catchTag("GitError", () => succeed$3(base)));
53508
+ return yield* pipe(git.string(config.cwd, [
53509
+ "rev-list",
53510
+ "--count",
53511
+ `${from}..HEAD`
53512
+ ]), map$4(flow(trim, parse$2, getOrElse$1(() => 0))));
53513
+ })(), map$4((count) => count > 0));
53514
+ const createDraftPr = pipe(ghString([
53515
+ "pr",
53516
+ "create",
53517
+ "--draft",
53518
+ "--fill"
53519
+ ]), map$4((output) => {
53520
+ const url = output.match(/https?:\/\/\S+/u)?.[0] ?? trim(output);
53521
+ return isNonEmpty$1(url) ? some(url) : none();
53522
+ }));
53523
+ return {
53524
+ commit: fn("GitCommitAction.commit")(function* (message) {
53525
+ yield* annotateCurrentSpan({ cwd: config.cwd });
53526
+ const dirty = yield* hasWorktreeChanges;
53527
+ yield* annotateCurrentSpan({ dirty });
53528
+ if (!dirty) return yield* new GitError({ message: "No changes to commit." });
53529
+ if (isEmpty$1(trim(message))) return yield* new GitError({ message: "Commit message required." });
53530
+ yield* pipe(git.string(config.cwd, ["add", "-A"]), asVoid, withSpan("GitCommitAction.stageAll"));
53264
53531
  yield* pipe(git.string(config.cwd, [
53265
- "add",
53266
- "--",
53267
- filePath
53268
- ]), asVoid);
53532
+ "commit",
53533
+ "-m",
53534
+ message
53535
+ ]), asVoid, withSpan("GitCommitAction.create"));
53269
53536
  }),
53270
- unstageFile: fnUntraced(function* (filePath) {
53537
+ push: fn("GitCommitAction.push")(function* () {
53538
+ yield* annotateCurrentSpan({ cwd: config.cwd });
53539
+ if (!(yield* hasPushableCommits)) return yield* new GitError({ message: "No unpushed commits." });
53540
+ const branch = yield* currentBranch;
53541
+ yield* annotateCurrentSpan({ branch });
53271
53542
  yield* pipe(git.string(config.cwd, [
53272
- "reset",
53273
- "HEAD",
53274
- "--",
53275
- filePath
53276
- ]), asVoid);
53277
- }),
53278
- watchReviewRangeDiffs: (input) => pipe(worktreeChanges, mapEffect(() => pipe(reviewRangeDiffs(input), catchTag("GitError", () => succeed$3(empty$13())))), changesWith((left, right) => length(left) === length(right) && every(left, (leftDiff, index) => isNotUndefined(right[index]) && leftDiff.filePath === right[index].filePath && leftDiff.status === right[index].status && leftDiff.patch === right[index].patch)))
53543
+ "push",
53544
+ "-u",
53545
+ "origin",
53546
+ `HEAD:${branch}`
53547
+ ]), asVoid, withSpan("GitCommitAction.push", { attributes: {
53548
+ branch,
53549
+ cwd: config.cwd
53550
+ } }));
53551
+ if (yield* hasPushableCommits) return yield* new GitError({ message: "Push completed but the branch still has unpushed commits." });
53552
+ if (branch !== (yield* defaultBranchName) && isNone(yield* branchPrUrl)) yield* pipe(createDraftPr, withSpan("GitCommitAction.createDraftPr", { attributes: {
53553
+ branch,
53554
+ cwd: config.cwd
53555
+ } }));
53556
+ })
53279
53557
  };
53280
53558
  }) }) {
53281
53559
  static layer = flow(this.make, effect(this));
@@ -53308,14 +53586,14 @@ const discover = fnUntraced(function* (cwd, input) {
53308
53586
  "package.json",
53309
53587
  "**/package.json"
53310
53588
  ], { cwd }));
53311
- return yield* pipe(pipe(split$1("\n")(output), filter$2((packagePath) => packagePath === "package.json" || endsWith("/package.json")(packagePath))), map$7((packagePath) => pipe(fs.readFileString(path.join(cwd, packagePath)), flatMap$2((source) => try_({
53589
+ return yield* pipe(pipe(split$1("\n")(output), filter$1((packagePath) => packagePath === "package.json" || endsWith("/package.json")(packagePath))), map$7((packagePath) => pipe(fs.readFileString(path.join(cwd, packagePath)), flatMap$2((source) => try_({
53312
53590
  catch: (error) => error,
53313
53591
  try: () => pipe(JSON.parse(source), decodeUnknownOption(PackageJson))
53314
53592
  })), catch_$2(() => succeed$3(none())), flatMap$2((packageJson) => {
53315
53593
  if (isNone(packageJson)) return succeed$3([]);
53316
53594
  const packageDirectory = packagePath === "package.json" ? cwd : path.join(cwd, path.dirname(packagePath));
53317
53595
  const folder = path.basename(packageDirectory);
53318
- const scriptEntries = pipe(Object.entries(packageJson.value.scripts ?? {}), filter$2((entry) => entry[0] === "dev" || startsWith("dev:")(entry[0])));
53596
+ const scriptEntries = pipe(Object.entries(packageJson.value.scripts ?? {}), filter$1((entry) => entry[0] === "dev" || startsWith("dev:")(entry[0])));
53319
53597
  const packageOrigin = input.origin([
53320
53598
  folder,
53321
53599
  path.basename(cwd),
@@ -53455,7 +53733,7 @@ const proxy = fnUntraced(function* (request, origin) {
53455
53733
  });
53456
53734
  const proxyWebSocket = fnUntraced(function* (request, origin) {
53457
53735
  const [pathname = "/", search = ""] = request.url.split("?");
53458
- const protocols = pipe(fromUndefinedOr(request.headers["sec-websocket-protocol"]), map$9((header) => pipe(header, split$1(","), map$7(trim), filter$2(isNonEmpty$1))));
53736
+ const protocols = pipe(fromUndefinedOr(request.headers["sec-websocket-protocol"]), map$9((header) => pipe(header, split$1(","), map$7(trim), filter$1(isNonEmpty$1))));
53459
53737
  const inbound = yield* request.upgrade;
53460
53738
  const upstreamUrl = new URL(origin);
53461
53739
  upstreamUrl.protocol = upstreamUrl.protocol === "https:" ? "wss:" : "ws:";
@@ -53611,7 +53889,6 @@ var import_addon_progress = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSM
53611
53889
  })(), e;
53612
53890
  })()));
53613
53891
  })))(), 1);
53614
- const eventBacklogCapacity = 512;
53615
53892
  const terminalReset = "\x1Bc";
53616
53893
  function parseTitleSignal(title) {
53617
53894
  const trimmed = title.trim();
@@ -53649,24 +53926,17 @@ function parseTitleSignal(title) {
53649
53926
  }
53650
53927
  function snapshotEvents(data, sequence) {
53651
53928
  if (data === "") return empty$13();
53652
- const events = [];
53653
- for (let index = 0; index < data.length; index += 256 * 1024) events.push({
53654
- data: data.slice(index, index + 256 * 1024),
53929
+ return pipe(range(0, Math.floor((data.length - 1) / (256 * 1024))), map$7((index) => ({
53930
+ data: data.slice(index * 256 * 1024, (index + 1) * 256 * 1024),
53655
53931
  sequence,
53656
53932
  type: "data"
53657
- });
53658
- return events;
53933
+ })));
53659
53934
  }
53660
53935
  function adjacentGroups(items, sameGroup, merge) {
53661
53936
  return pipe(items, reduce(empty$13(), (groups, item) => {
53662
- const next = groups;
53663
53937
  const previous = groups.at(-1);
53664
- if (previous === void 0 || !sameGroup(previous, item)) {
53665
- next.push(item);
53666
- return next;
53667
- }
53668
- next[next.length - 1] = merge(previous, item);
53669
- return next;
53938
+ if (previous === void 0 || !sameGroup(previous, item)) return append$1(groups, item);
53939
+ return append$1(dropRight(groups, 1), merge(previous, item));
53670
53940
  }));
53671
53941
  }
53672
53942
  function queuedDataGroups(items, merge) {
@@ -53686,13 +53956,9 @@ function queuedWriteGroups(items) {
53686
53956
  }
53687
53957
  var Terminal = class extends Service()("@deslop/terminal/service/Terminal", { make: fnUntraced(function* (config) {
53688
53958
  const dataQueue = yield* unbounded();
53689
- const screenQueue = yield* unbounded();
53690
53959
  const writeQueue = yield* unbounded();
53691
53960
  const resizeQueue = yield* sliding(1);
53692
- const events = yield* bounded$1({
53693
- capacity: 1024,
53694
- replay: eventBacklogCapacity
53695
- });
53961
+ const events = yield* bounded$1(1024);
53696
53962
  const lifecycleLock = yield* make$47(1);
53697
53963
  const screenLock = yield* make$47(1);
53698
53964
  const eventSequenceRef = yield* make$38(0);
@@ -53739,15 +54005,16 @@ var Terminal = class extends Service()("@deslop/terminal/service/Terminal", { ma
53739
54005
  };
53740
54006
  }));
53741
54007
  function setState(state) {
53742
- return update(stateRef, (current) => ({
54008
+ return update(stateRef, (current) => current.state === state ? current : {
53743
54009
  ...current,
53744
54010
  state
53745
- }));
54011
+ });
53746
54012
  }
53747
54013
  function setProgressState(progressState) {
53748
54014
  return update(stateRef, (current) => {
53749
54015
  if (current.state === "stopped" || current.state === "exited" || current.state === "failed") return current;
53750
54016
  const state = pipe(progressState.state, value, when(0, () => "idle"), when(2, () => "failed"), when(4, () => "waiting"), orElse(() => "running"));
54017
+ if (current.state === state) return current;
53751
54018
  return {
53752
54019
  ...current,
53753
54020
  state
@@ -53757,9 +54024,11 @@ var Terminal = class extends Service()("@deslop/terminal/service/Terminal", { ma
53757
54024
  function setTitle(title) {
53758
54025
  return update(stateRef, (current) => {
53759
54026
  if (!terminalStateActive(current.state)) return current;
54027
+ const next = parseTitleSignal(title);
54028
+ if (current.state === next.state && current.title === next.title) return current;
53760
54029
  return {
53761
54030
  ...current,
53762
- ...parseTitleSignal(title)
54031
+ ...next
53763
54032
  };
53764
54033
  });
53765
54034
  }
@@ -53871,16 +54140,11 @@ var Terminal = class extends Service()("@deslop/terminal/service/Terminal", { ma
53871
54140
  yield* stopProcess();
53872
54141
  return yield* spawnProcess();
53873
54142
  });
53874
- yield* pipe(fromQueue(dataQueue), groupedWithin(256, millis(8)), runForEach((items) => forEach$1(queuedDataGroups(fromIterable$2(items), mergeQueuedData), (item) => gen(function* () {
53875
- if ((yield* get$3(screenGenerationRef)) !== item.generation) return;
53876
- yield* offer(screenQueue, item);
53877
- }), { discard: true })), forkScoped);
53878
- yield* pipe(fromQueue(screenQueue), groupedWithin(256, millis(16)), runForEach((items) => forEach$1(queuedDataGroups(fromIterable$2(items), mergeQueuedData), writeScreen, { discard: true })), forkScoped);
54143
+ yield* pipe(fromQueue(dataQueue), groupedWithin(256, millis(16)), runForEach((items) => forEach$1(queuedDataGroups(fromIterable$2(items), mergeQueuedData), writeScreen, { discard: true })), forkScoped);
53879
54144
  yield* addFinalizer(() => all([
53880
54145
  stopProcess(),
53881
54146
  shutdown$1(events),
53882
54147
  shutdown(dataQueue),
53883
- shutdown(screenQueue),
53884
54148
  shutdown(writeQueue),
53885
54149
  shutdown(resizeQueue),
53886
54150
  sync(() => {
@@ -53910,7 +54174,7 @@ var Terminal = class extends Service()("@deslop/terminal/service/Terminal", { ma
53910
54174
  }
53911
54175
  });
53912
54176
  });
53913
- yield* pipe(fromQueue(resizeQueue), groupedWithin(32, millis(16)), runForEach((items) => pipe(last(fromIterable$2(items)), match$5({
54177
+ yield* pipe(fromQueue(resizeQueue), groupedWithin(32, millis(16)), runForEach((items) => pipe(last(fromIterable$2(items)), match$4({
53914
54178
  onNone: () => void_$1,
53915
54179
  onSome: resizeProcess
53916
54180
  }))), forkScoped);
@@ -53931,7 +54195,7 @@ var Terminal = class extends Service()("@deslop/terminal/service/Terminal", { ma
53931
54195
  const subscription = yield* subscribe(events);
53932
54196
  const snapshot = yield* requestSnapshot;
53933
54197
  const pending = yield* takeUpTo(subscription, Number.POSITIVE_INFINITY);
53934
- const replay = filter$2(pending, (event) => event.sequence > snapshot.sequence);
54198
+ const replay = filter$1(pending, (event) => event.sequence > snapshot.sequence);
53935
54199
  const replaySequence = replay.at(-1)?.sequence ?? snapshot.sequence;
53936
54200
  return pipe(fromIterable$1([
53937
54201
  {
@@ -53941,8 +54205,8 @@ var Terminal = class extends Service()("@deslop/terminal/service/Terminal", { ma
53941
54205
  },
53942
54206
  ...snapshotEvents(snapshot.data, snapshot.sequence),
53943
54207
  ...replay,
53944
- ...filter$2(pending, (event) => event.sequence > replaySequence)
53945
- ]), concat(fromEffectRepeat(take$3(subscription))));
54208
+ ...filter$1(pending, (event) => event.sequence > replaySequence)
54209
+ ]), concat(fromEffectRepeat(take$2(subscription))));
53946
54210
  })));
53947
54211
  const stateUpdates = unwrap$1(pipe(get(stateRef), map$4((state) => concat(drop(1)(changes(stateRef)))(make$43(state)))));
53948
54212
  const updates = merge$1(stateUpdates.pipe(map$2((state) => ({
@@ -53983,7 +54247,7 @@ const TerminalSessionKey = Struct({
53983
54247
  env: optional(Record(String$1, String$1)),
53984
54248
  sessionId: optional(String$1)
53985
54249
  });
53986
- const emptyReviewState = new ReviewState({
54250
+ const emptyReviewState = new GitReviewState({
53987
54251
  comments: empty$13(),
53988
54252
  marks: empty$13()
53989
54253
  });
@@ -54008,32 +54272,31 @@ function terminalSessionInput(session) {
54008
54272
  sessionId: session.sessionId
54009
54273
  };
54010
54274
  }
54011
- function commentKey(input) {
54012
- return `${input.filePath}:${input.side ?? "additions"}:${input.lineNumber}`;
54013
- }
54014
- function markKey(input) {
54015
- return `${input.filePath}:${input.segmentId}:${input.fingerprint}`;
54016
- }
54017
54275
  const TerminalSessions = make$46({
54018
54276
  idleTimeToLive: infinity,
54019
54277
  lookup: fnUntraced(function* (config) {
54020
54278
  return get$9(yield* buildWithScope(Terminal.layer(config), yield* scope), Terminal);
54021
54279
  })
54022
54280
  });
54023
- const GitWorktreeSessions = make$46({
54281
+ const GitReviewSessions = make$46({
54282
+ idleTimeToLive: zero$1,
54283
+ lookup: fnUntraced(function* (cwd) {
54284
+ return get$9(yield* buildWithScope(pipe(GitReview.layer({ cwd }), provide$2(GitCommand.layer)), yield* scope), GitReview);
54285
+ })
54286
+ });
54287
+ const GitCommitSessions = make$46({
54024
54288
  idleTimeToLive: minutes(5),
54025
54289
  lookup: fnUntraced(function* (cwd) {
54026
- return get$9(yield* buildWithScope(GitWorktree.layer({ cwd }), yield* scope), GitWorktree);
54290
+ return get$9(yield* buildWithScope(pipe(GitCommitAction.layer({ cwd }), provide$2(GitCommand.layer)), yield* scope), GitCommitAction);
54027
54291
  })
54028
54292
  });
54029
54293
  const RpcHandlers = RpcContracts.toLayer(gen(function* () {
54030
54294
  const git = yield* GitWorkspace;
54031
54295
  const terminals = yield* TerminalSessions;
54032
- const gitWorktrees = yield* GitWorktreeSessions;
54033
- const fs = yield* FileSystem;
54296
+ const gitReviews = yield* GitReviewSessions;
54297
+ const gitCommits = yield* GitCommitSessions;
54034
54298
  const portless = yield* Portless;
54035
54299
  const portlessScripts = yield* make$38(empty$6());
54036
- const reviewStore = toSchemaStore(yield* KeyValueStore, ReviewState);
54037
54300
  const portlessWorktrees = yield* make$46({
54038
54301
  idleTimeToLive: infinity,
54039
54302
  lookup: fnUntraced(function* (cwd) {
@@ -54072,39 +54335,46 @@ const RpcHandlers = RpcContracts.toLayer(gen(function* () {
54072
54335
  const getTerminal = fnUntraced(function* (input) {
54073
54336
  return yield* pipe(terminalSession(input), map$4(terminalSessionInput), flatMap$2((session) => get$6(terminals, session)));
54074
54337
  });
54075
- const reviewStateKey = fnUntraced(function* (input) {
54076
- const root = yield* pipe(fs.realPath(input.cwd), orElseSucceed(() => input.cwd));
54077
- return Buffer.from(`${root}\u0000${input.base}`, "utf8").toString("base64url");
54078
- });
54079
- const readReviewState = fnUntraced(function* (key) {
54080
- return yield* pipe(reviewStore.get(`review-state/${key}`), map$4(getOrElse$1(() => emptyReviewState)), orElseSucceed(() => emptyReviewState));
54081
- });
54082
- const reviewStates = yield* make$46({
54083
- idleTimeToLive: minutes(5),
54084
- lookup: fnUntraced(function* (key) {
54085
- return yield* make$3(yield* readReviewState(key));
54086
- })
54087
- });
54088
- const updateReviewState = fnUntraced(function* (input, f) {
54338
+ const reviewStates = yield* make$46({ lookup: fnUntraced(function* () {
54339
+ return yield* make$3(emptyReviewState);
54340
+ }) });
54341
+ const updateReviewState = fn("RpcHandlers.updateReviewState")(function* (cwd, f) {
54342
+ yield* annotateCurrentSpan({ cwd });
54089
54343
  return yield* pipe(scoped$3(gen(function* () {
54090
- const key = yield* reviewStateKey(input);
54091
- const state = yield* modify(yield* get$6(reviewStates, key), (current) => {
54344
+ yield* modify(yield* get$6(reviewStates, cwd), (current) => {
54092
54345
  const next = f(current);
54093
54346
  return [next, next];
54094
54347
  });
54095
- yield* reviewStore.set(`review-state/${key}`, state);
54096
54348
  })), mapError$2((cause) => new GitError({ cause })));
54097
54349
  });
54098
54350
  const agents = yield* make$3(empty$6());
54351
+ const removeAgent = fnUntraced(function* (payload) {
54352
+ const session = pipe(yield* get(agents), get$1(payload), getOrUndefined$1);
54353
+ yield* update(agents, (current) => remove$2(current, payload));
54354
+ if (session === void 0) return;
54355
+ const input = terminalSessionInput({
54356
+ args: session.args,
54357
+ command: session.command,
54358
+ cwd: session.cwd,
54359
+ sessionId: session.uuid
54360
+ });
54361
+ yield* pipe(get$6(terminals, input), flatMap$2((terminal) => terminal.stop()), ignore$1);
54362
+ yield* pipe(invalidate(terminals, input), ignore$1);
54363
+ });
54099
54364
  return RpcContracts.of({
54100
54365
  "agents.create": (payload) => gen(function* () {
54101
- const labelCount = pipe(fromIterable$2(values(yield* get(agents))), filter$2((agentSession) => agentSession.cwd === payload.cwd && agentSession.command === payload.command), length);
54366
+ const labelCount = pipe(fromIterable$2(values(yield* get(agents))), filter$1((agentSession) => agentSession.cwd === payload.cwd && agentSession.command === payload.command), length);
54102
54367
  const agentSession = {
54103
54368
  args: [...payload.args],
54104
54369
  command: payload.command,
54105
54370
  cwd: payload.cwd,
54106
54371
  icon: payload.icon,
54107
54372
  label: `${payload.label} ${labelCount + 1}`,
54373
+ state: {
54374
+ runId: 0,
54375
+ state: "starting",
54376
+ title: ""
54377
+ },
54108
54378
  uuid: randomUUID()
54109
54379
  };
54110
54380
  yield* update(agents, (sessions) => set$2(sessions, AgentSessionKey.make({
@@ -54118,68 +54388,58 @@ const RpcHandlers = RpcContracts.toLayer(gen(function* () {
54118
54388
  sessionId: agentSession.uuid
54119
54389
  })).pipe(map$4(terminalSessionInput), flatMap$2((input) => get$6(terminals, input)));
54120
54390
  yield* sessionTerminal.restart();
54121
- yield* pipe(sessionTerminal.stateUpdates, map$2((state) => state.state), filter((state) => state === "exited" || state === "failed" || state === "stopped"), take(1), runDrain, andThen(update(agents, (sessions) => remove$2(sessions, AgentSessionKey.make({
54122
- cwd: agentSession.cwd,
54123
- uuid: agentSession.uuid
54124
- })))), forkDetach);
54391
+ yield* pipe(sessionTerminal.stateUpdates, takeUntil((state) => state.state === "exited" || state.state === "failed" || state.state === "stopped"), runForEach((state) => gen(function* () {
54392
+ const key = AgentSessionKey.make({
54393
+ cwd: agentSession.cwd,
54394
+ uuid: agentSession.uuid
54395
+ });
54396
+ yield* update(agents, (sessions) => modifyAt(sessions, key, match$4({
54397
+ onNone: () => none(),
54398
+ onSome: (session) => some({
54399
+ ...session,
54400
+ state
54401
+ })
54402
+ })));
54403
+ if (state.state !== "exited" && state.state !== "failed" && state.state !== "stopped") return;
54404
+ yield* update(agents, (sessions) => remove$2(sessions, key));
54405
+ yield* pipe(invalidate(terminals, terminalSessionInput({
54406
+ args: agentSession.args,
54407
+ command: agentSession.command,
54408
+ cwd: agentSession.cwd,
54409
+ sessionId: agentSession.uuid
54410
+ })), ignore$1);
54411
+ })), forkDetach);
54125
54412
  return agentSession;
54126
54413
  }),
54127
- "agents.remove": (payload) => update(agents, (current) => remove$2(current, AgentSessionKey.make({
54128
- cwd: payload.cwd,
54129
- uuid: payload.uuid
54130
- }))),
54131
- "agents.watch": (payload) => unwrap$1(pipe(get(agents), map$4((current) => pipe(make$43(current), concat(drop(1)(changes(agents))), map$2((sessions) => pipe(fromIterable$2(values(sessions)), filter$2((session) => session.cwd === payload.cwd))))))),
54414
+ "agents.remove": (payload) => removeAgent(AgentSessionKey.make(payload)),
54415
+ "agents.watch": (payload) => unwrap$1(pipe(get(agents), map$4((current) => pipe(make$43(current), concat(drop(1)(changes(agents))), map$2((sessions) => pipe(fromIterable$2(values(sessions)), filter$1((session) => session.cwd === payload.cwd))))))),
54132
54416
  "projects.branches": (payload) => git.branches(payload.cwd),
54133
54417
  "projects.createWorktree": (payload) => git.createWorktree(payload),
54134
54418
  "projects.deleteWorktree": (payload) => git.deleteWorktree(payload),
54135
54419
  "projects.watch": () => unwrap$1(map$4(get(git.projects), (projects) => pipe(make$43(projects), concat(drop(1)(changes(git.projects)))))),
54136
- "review.comments.resolve": (payload) => updateReviewState(payload, (state) => {
54137
- const key = commentKey(payload);
54138
- return new ReviewState({
54139
- comments: filter$2(state.comments, (comment) => commentKey(comment) !== key),
54140
- marks: state.marks
54141
- });
54142
- }),
54143
- "review.comments.save": (payload) => updateReviewState(payload, (state) => {
54144
- const key = commentKey(payload.comment);
54145
- return new ReviewState({
54146
- comments: append$1(filter$2(state.comments, (comment) => commentKey(comment) !== key), new ReviewComment({
54147
- ...payload.comment,
54148
- resolved: false
54149
- })),
54150
- marks: state.marks
54151
- });
54152
- }),
54153
- "review.commitAndPush": (payload) => pipe(get$6(gitWorktrees, payload.cwd), flatMap$2((worktree) => worktree.commitAndPush({
54154
- base: payload.base,
54155
- message: payload.message
54156
- }))),
54157
- "review.createWipCommit": (payload) => pipe(get$6(gitWorktrees, payload.cwd), flatMap$2((worktree) => worktree.createWipCommit(payload.message))),
54158
- "review.discardFile": (payload) => pipe(get$6(gitWorktrees, payload.cwd), flatMap$2((worktree) => worktree.discardFile(payload.filePath))),
54159
- "review.githubThreads": (payload) => pipe(get$6(gitWorktrees, payload.cwd), flatMap$2((worktree) => worktree.reviewThreads)),
54160
- "review.githubThreads.resolve": (payload) => pipe(get$6(gitWorktrees, payload.cwd), flatMap$2((worktree) => worktree.resolveReviewThread(payload.threadId))),
54161
- "review.metadata": (payload) => pipe(get$6(gitWorktrees, payload.cwd), flatMap$2((worktree) => worktree.metadata({ base: payload.base }))),
54162
- "review.stageFile": (payload) => pipe(get$6(gitWorktrees, payload.cwd), flatMap$2((worktree) => worktree.stageFile(payload.filePath))),
54163
- "review.state.mark": (payload) => updateReviewState(payload, (state) => {
54164
- const keys = new Set(map$7(payload.marks, markKey));
54165
- return new ReviewState({
54166
- comments: state.comments,
54167
- marks: appendAll(filter$2(state.marks, (mark) => !keys.has(markKey(mark))), payload.marks)
54168
- });
54169
- }),
54170
- "review.state.unmark": (payload) => updateReviewState(payload, (state) => {
54171
- const keys = new Set(map$7(payload.marks, markKey));
54172
- return new ReviewState({
54173
- comments: state.comments,
54174
- marks: filter$2(state.marks, (mark) => !keys.has(markKey(mark)))
54175
- });
54176
- }),
54177
- "review.state.watch": (payload) => unwrap$1(pipe(reviewStateKey(payload), flatMap$2((key) => get$6(reviewStates, key)), flatMap$2((ref) => pipe(get(ref), map$4((state) => concat(drop(1)(changes(ref)))(make$43(state))))))),
54178
- "review.unstageFile": (payload) => pipe(get$6(gitWorktrees, payload.cwd), flatMap$2((worktree) => worktree.unstageFile(payload.filePath))),
54179
- "review.watchRange": (payload) => unwrap$1(pipe(get$6(gitWorktrees, payload.cwd), map$4((worktree) => worktree.watchReviewRangeDiffs({
54180
- from: payload.from,
54181
- to: payload.to
54182
- })))),
54420
+ "review.comments.resolve": (payload) => pipe(updateReviewState(payload.cwd, (state) => gitReviewStateResolveComment(state, payload)), withSpan("RpcHandlers.review.comments.resolve", { attributes: {
54421
+ cwd: payload.cwd,
54422
+ filePath: payload.filePath
54423
+ } })),
54424
+ "review.comments.save": (payload) => pipe(updateReviewState(payload.cwd, (state) => gitReviewStateSaveComment(state, payload.comment)), withSpan("RpcHandlers.review.comments.save", { attributes: {
54425
+ cwd: payload.cwd,
54426
+ filePath: payload.comment.filePath
54427
+ } })),
54428
+ "review.commit": (payload) => pipe(get$6(gitCommits, payload.cwd), flatMap$2((commit) => commit.commit(payload.message))),
54429
+ "review.diffs": (payload) => unwrap$1(pipe(get$6(gitReviews, payload.cwd), map$4((review) => review.watchReviewDiffs(payload.target)))),
54430
+ "review.githubThreads": (payload) => pipe(get$6(gitReviews, payload.cwd), flatMap$2((review) => review.reviewThreads)),
54431
+ "review.githubThreads.resolve": (payload) => pipe(get$6(gitReviews, payload.cwd), flatMap$2((review) => review.resolveReviewThread(payload.threadId))),
54432
+ "review.metadata": (payload) => pipe(get$6(gitReviews, payload.cwd), flatMap$2((review) => review.metadata())),
54433
+ "review.push": (payload) => pipe(get$6(gitCommits, payload.cwd), flatMap$2((commit) => commit.push())),
54434
+ "review.state.mark": (payload) => pipe(updateReviewState(payload.cwd, (state) => gitReviewStateMark(state, payload.marks)), withSpan("RpcHandlers.review.state.mark", { attributes: {
54435
+ cwd: payload.cwd,
54436
+ markCount: length(payload.marks)
54437
+ } })),
54438
+ "review.state.unmark": (payload) => pipe(updateReviewState(payload.cwd, (state) => gitReviewStateUnmark(state, payload.marks)), withSpan("RpcHandlers.review.state.unmark", { attributes: {
54439
+ cwd: payload.cwd,
54440
+ markCount: length(payload.marks)
54441
+ } })),
54442
+ "review.state.watch": (payload) => unwrap$1(pipe(get$6(reviewStates, payload.cwd), flatMap$2((ref) => pipe(get(ref), map$4((state) => concat(drop(1)(changes(ref)))(make$43(state))))))),
54183
54443
  "runs.portless": (payload) => get$6(portlessWorktrees, payload.cwd),
54184
54444
  "terminal.resize": (payload) => pipe(getTerminal(TerminalSessionKey.make(payload)), flatMap$2((sessionTerminal) => sessionTerminal.resize({
54185
54445
  cols: payload.cols,
@@ -60287,19 +60547,19 @@ var require_getMachineId = /* @__PURE__ */ __commonJSMin(((exports) => {
60287
60547
  async function getMachineId() {
60288
60548
  if (!getMachineIdImpl) switch (process$1.platform) {
60289
60549
  case "darwin":
60290
- getMachineIdImpl = (await import("./getMachineId-darwin-DD7WkQgq.mjs").then((m) => /* @__PURE__ */ __toESM(m.default))).getMachineId;
60550
+ getMachineIdImpl = (await import("./getMachineId-darwin-BYjMzwa2.mjs").then((m) => /* @__PURE__ */ __toESM(m.default))).getMachineId;
60291
60551
  break;
60292
60552
  case "linux":
60293
- getMachineIdImpl = (await import("./getMachineId-linux-NsJbNTda.mjs").then((m) => /* @__PURE__ */ __toESM(m.default))).getMachineId;
60553
+ getMachineIdImpl = (await import("./getMachineId-linux-7FQ_TPIw.mjs").then((m) => /* @__PURE__ */ __toESM(m.default))).getMachineId;
60294
60554
  break;
60295
60555
  case "freebsd":
60296
- getMachineIdImpl = (await import("./getMachineId-bsd-D2D8E0zh.mjs").then((m) => /* @__PURE__ */ __toESM(m.default))).getMachineId;
60556
+ getMachineIdImpl = (await import("./getMachineId-bsd-DYUtJhPR.mjs").then((m) => /* @__PURE__ */ __toESM(m.default))).getMachineId;
60297
60557
  break;
60298
60558
  case "win32":
60299
- getMachineIdImpl = (await import("./getMachineId-win-CpX0o49t.mjs").then((m) => /* @__PURE__ */ __toESM(m.default))).getMachineId;
60559
+ getMachineIdImpl = (await import("./getMachineId-win-BxTTz_Ds.mjs").then((m) => /* @__PURE__ */ __toESM(m.default))).getMachineId;
60300
60560
  break;
60301
60561
  default:
60302
- getMachineIdImpl = (await import("./getMachineId-unsupported-BdKw63O1.mjs").then((m) => /* @__PURE__ */ __toESM(m.default))).getMachineId;
60562
+ getMachineIdImpl = (await import("./getMachineId-unsupported-CqYci84U.mjs").then((m) => /* @__PURE__ */ __toESM(m.default))).getMachineId;
60303
60563
  break;
60304
60564
  }
60305
60565
  return getMachineIdImpl();
@@ -67751,7 +68011,7 @@ const isSampled = (traceFlags) => (traceFlags & TraceFlags.SAMPLED) === TraceFla
67751
68011
  const getOtelParent = (tracer, context, annotations) => {
67752
68012
  const otelParent = tracer.getSpan(context)?.spanContext();
67753
68013
  if (!otelParent) return none();
67754
- return some$1(externalSpan({
68014
+ return some(externalSpan({
67755
68015
  spanId: otelParent.spanId,
67756
68016
  traceId: otelParent.traceId,
67757
68017
  sampled: (otelParent.traceFlags & 1) === 1,
@@ -70962,7 +71222,7 @@ var import_src = (/* @__PURE__ */ __commonJSMin(((exports) => {
70962
71222
  });
70963
71223
  })))();
70964
71224
  function OtelLayer(serviceName) {
70965
- return unwrap$4(map$4(option(string("VITE_OTEL_URL")), match$5({
71225
+ return unwrap$4(map$4(option(string("VITE_OTEL_URL")), match$4({
70966
71226
  onNone: () => empty$11,
70967
71227
  onSome: (url) => layer(() => ({
70968
71228
  resource: { serviceName },
@@ -70972,7 +71232,7 @@ function OtelLayer(serviceName) {
70972
71232
  }
70973
71233
  //#endregion
70974
71234
  //#region src/lib/serverRuntime.ts
70975
- const LiveLayers = pipe(empty$11, provideMerge(RpcHandlers), provideMerge(Portless.layer), provideMerge(GitWorkspace.layer), provideMerge(unwrap$4(pipe(string("HOME"), withDefault(process.cwd()), map$4((home) => layerFileSystem(path.join(home, ".deslop")))))), provideMerge(OtelLayer("workbench-server")), provideMerge(layer$16), provideMerge(layerMsgPack));
71235
+ const LiveLayers = pipe(empty$11, provideMerge(RpcHandlers), provideMerge(Portless.layer), provideMerge(pipe(GitWorkspace.layer, provide$2(GitCommand.layer))), provideMerge(pipe(GitMaintenance.layer, provide$2(GitCommand.layer))), provideMerge(unwrap$4(pipe(string("HOME"), withDefault(process.cwd()), map$4((home) => layerFileSystem(path.join(home, ".deslop")))))), provideMerge(OtelLayer("workbench-server")), provideMerge(layer$16), provideMerge(layerMsgPack));
70976
71236
  //#endregion
70977
71237
  //#region src/main.server.ts
70978
71238
  runMain(pipe(serve(mergeAll$1(layerHttp({