agentix-cli 0.97.0 → 0.98.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/apps/mac-voice/Sources/AgentXVoice/PlayActs.swift +35 -8
  2. package/apps/mac-voice/Sources/AgentXVoice/PlayMath.swift +17 -9
  3. package/apps/mac-voice/Sources/AgentXVoice/PlayMotion.swift +110 -0
  4. package/apps/mac-voice/Sources/AgentXVoice/PlayStage.swift +43 -5
  5. package/dist/{App-6R4I6QPE.js → App-XLQDP26J.js} +2 -2
  6. package/dist/{ChatApp-R3O4BJ24.js → ChatApp-DRDUXZ66.js} +2 -2
  7. package/dist/{agent-P6GPE7HD.js → agent-QHM3J2XS.js} +2 -2
  8. package/dist/{board-dashboard-AKQHIY4J.js → board-dashboard-AIT26JTK.js} +4 -4
  9. package/dist/{chunk-QPIMPKZ2.js → chunk-4BCAH7XI.js} +2 -2
  10. package/dist/{chunk-3S4IYAOC.js → chunk-B32A6OOY.js} +2 -2
  11. package/dist/{chunk-QHAO6U7U.js → chunk-BERHVF3T.js} +2 -2
  12. package/dist/{chunk-TWC4CYTU.js → chunk-BHKWXFJD.js} +5 -5
  13. package/dist/{chunk-Q53XKCRL.js → chunk-BTLW2RML.js} +2 -2
  14. package/dist/{chunk-55HM3SUN.js → chunk-DRUEPGLP.js} +2 -2
  15. package/dist/{chunk-SZ5TGL25.js → chunk-DXJRMPGH.js} +2 -2
  16. package/dist/{chunk-ZCQCUA4J.js → chunk-GJ5EJVMZ.js} +2 -2
  17. package/dist/{chunk-2GFSHO24.js → chunk-IQJ7UZVV.js} +2 -2
  18. package/dist/{chunk-6W3SCPDK.js → chunk-J4JVKVEK.js} +2 -2
  19. package/dist/{chunk-MDFUSQ6S.js → chunk-J64VIHL5.js} +2 -2
  20. package/dist/{chunk-ERPEU2ZR.js → chunk-JREA25GJ.js} +3 -3
  21. package/dist/chunk-JREA25GJ.js.map +1 -0
  22. package/dist/{chunk-WLKO6FOL.js → chunk-JZJ7AZJD.js} +2 -2
  23. package/dist/{chunk-4BG3WJSP.js → chunk-LXJGLNVG.js} +2 -2
  24. package/dist/{chunk-LXHTVVJV.js → chunk-OFVMUBIP.js} +2 -2
  25. package/dist/{chunk-TOGRRWBX.js → chunk-QUU5RJ7D.js} +2 -2
  26. package/dist/{chunk-F3DW5ZJN.js → chunk-S2GPUSBU.js} +2 -2
  27. package/dist/{chunk-C2POHIWJ.js → chunk-SJMOZY7Y.js} +2 -2
  28. package/dist/{chunk-3SF7PLHF.js → chunk-WWCVQHV3.js} +6 -6
  29. package/dist/{chunk-3SF7PLHF.js.map → chunk-WWCVQHV3.js.map} +1 -1
  30. package/dist/{chunk-X4S2I233.js → chunk-YYCFI4VP.js} +2 -2
  31. package/dist/{chunk-DGVTRG5Q.js → chunk-Z4FY64BS.js} +2 -2
  32. package/dist/cli.js +1 -1
  33. package/dist/{client-UQKCIEHA.js → client-BLUCLNIS.js} +2 -2
  34. package/dist/{config-OE23UC5C.js → config-ZUMI4IY4.js} +2 -2
  35. package/dist/config-mutator-S3CD2IWQ.js +2 -0
  36. package/dist/{doctor-QQ7YLJK4.js → doctor-XGQW5SMD.js} +2 -2
  37. package/dist/index.js +1 -1
  38. package/dist/{program-O5RQ6NRG.js → program-FK7REU2M.js} +14 -14
  39. package/dist/{promote-AW4TJXXT.js → promote-K5LP5Q6Z.js} +2 -2
  40. package/dist/{query-24BGIJCZ.js → query-LHXSINM2.js} +2 -2
  41. package/dist/{registry-GZT2OSBK.js → registry-OQUO6NCW.js} +2 -2
  42. package/dist/{request-planner-U6HHKWLX.js → request-planner-TW5OCKTF.js} +2 -2
  43. package/dist/{review-candidates-LJUJCVFA.js → review-candidates-EFELFOSY.js} +2 -2
  44. package/dist/{routing-WCYPBKFH.js → routing-TSRZLD7B.js} +2 -2
  45. package/dist/schedule-tool-JUHRVU5D.js +2 -0
  46. package/dist/scheduler-EHJPTULN.js +2 -0
  47. package/dist/{seat-5PBTFTGS.js → seat-NIPWHLKC.js} +2 -2
  48. package/dist/{select-JD7MSY25.js → select-UAKDLN76.js} +2 -2
  49. package/dist/{set-enabled-MUSO2KJL.js → set-enabled-74DLXMSM.js} +2 -2
  50. package/dist/{tool-Y7SOGJ2S.js → tool-CEBL57UW.js} +2 -2
  51. package/dist/{tool-FMKGK474.js → tool-TEGHFORD.js} +2 -2
  52. package/dist/wiki-WOK4SCB7.js +2 -0
  53. package/package.json +1 -1
  54. package/dist/chunk-ERPEU2ZR.js.map +0 -1
  55. package/dist/config-mutator-2UK5GX4B.js +0 -2
  56. package/dist/schedule-tool-E7ER2XOI.js +0 -2
  57. package/dist/scheduler-FK3LOWU2.js +0 -2
  58. package/dist/wiki-SJRTAYMT.js +0 -2
  59. /package/dist/{App-6R4I6QPE.js.map → App-XLQDP26J.js.map} +0 -0
  60. /package/dist/{ChatApp-R3O4BJ24.js.map → ChatApp-DRDUXZ66.js.map} +0 -0
  61. /package/dist/{agent-P6GPE7HD.js.map → agent-QHM3J2XS.js.map} +0 -0
  62. /package/dist/{board-dashboard-AKQHIY4J.js.map → board-dashboard-AIT26JTK.js.map} +0 -0
  63. /package/dist/{chunk-QPIMPKZ2.js.map → chunk-4BCAH7XI.js.map} +0 -0
  64. /package/dist/{chunk-3S4IYAOC.js.map → chunk-B32A6OOY.js.map} +0 -0
  65. /package/dist/{chunk-QHAO6U7U.js.map → chunk-BERHVF3T.js.map} +0 -0
  66. /package/dist/{chunk-TWC4CYTU.js.map → chunk-BHKWXFJD.js.map} +0 -0
  67. /package/dist/{chunk-Q53XKCRL.js.map → chunk-BTLW2RML.js.map} +0 -0
  68. /package/dist/{chunk-55HM3SUN.js.map → chunk-DRUEPGLP.js.map} +0 -0
  69. /package/dist/{chunk-SZ5TGL25.js.map → chunk-DXJRMPGH.js.map} +0 -0
  70. /package/dist/{chunk-ZCQCUA4J.js.map → chunk-GJ5EJVMZ.js.map} +0 -0
  71. /package/dist/{chunk-2GFSHO24.js.map → chunk-IQJ7UZVV.js.map} +0 -0
  72. /package/dist/{chunk-6W3SCPDK.js.map → chunk-J4JVKVEK.js.map} +0 -0
  73. /package/dist/{chunk-MDFUSQ6S.js.map → chunk-J64VIHL5.js.map} +0 -0
  74. /package/dist/{chunk-WLKO6FOL.js.map → chunk-JZJ7AZJD.js.map} +0 -0
  75. /package/dist/{chunk-4BG3WJSP.js.map → chunk-LXJGLNVG.js.map} +0 -0
  76. /package/dist/{chunk-LXHTVVJV.js.map → chunk-OFVMUBIP.js.map} +0 -0
  77. /package/dist/{chunk-TOGRRWBX.js.map → chunk-QUU5RJ7D.js.map} +0 -0
  78. /package/dist/{chunk-F3DW5ZJN.js.map → chunk-S2GPUSBU.js.map} +0 -0
  79. /package/dist/{chunk-C2POHIWJ.js.map → chunk-SJMOZY7Y.js.map} +0 -0
  80. /package/dist/{chunk-X4S2I233.js.map → chunk-YYCFI4VP.js.map} +0 -0
  81. /package/dist/{chunk-DGVTRG5Q.js.map → chunk-Z4FY64BS.js.map} +0 -0
  82. /package/dist/{client-UQKCIEHA.js.map → client-BLUCLNIS.js.map} +0 -0
  83. /package/dist/{config-OE23UC5C.js.map → config-ZUMI4IY4.js.map} +0 -0
  84. /package/dist/{config-mutator-2UK5GX4B.js.map → config-mutator-S3CD2IWQ.js.map} +0 -0
  85. /package/dist/{doctor-QQ7YLJK4.js.map → doctor-XGQW5SMD.js.map} +0 -0
  86. /package/dist/{program-O5RQ6NRG.js.map → program-FK7REU2M.js.map} +0 -0
  87. /package/dist/{promote-AW4TJXXT.js.map → promote-K5LP5Q6Z.js.map} +0 -0
  88. /package/dist/{query-24BGIJCZ.js.map → query-LHXSINM2.js.map} +0 -0
  89. /package/dist/{registry-GZT2OSBK.js.map → registry-OQUO6NCW.js.map} +0 -0
  90. /package/dist/{request-planner-U6HHKWLX.js.map → request-planner-TW5OCKTF.js.map} +0 -0
  91. /package/dist/{review-candidates-LJUJCVFA.js.map → review-candidates-EFELFOSY.js.map} +0 -0
  92. /package/dist/{routing-WCYPBKFH.js.map → routing-TSRZLD7B.js.map} +0 -0
  93. /package/dist/{schedule-tool-E7ER2XOI.js.map → schedule-tool-JUHRVU5D.js.map} +0 -0
  94. /package/dist/{scheduler-FK3LOWU2.js.map → scheduler-EHJPTULN.js.map} +0 -0
  95. /package/dist/{seat-5PBTFTGS.js.map → seat-NIPWHLKC.js.map} +0 -0
  96. /package/dist/{select-JD7MSY25.js.map → select-UAKDLN76.js.map} +0 -0
  97. /package/dist/{set-enabled-MUSO2KJL.js.map → set-enabled-74DLXMSM.js.map} +0 -0
  98. /package/dist/{tool-Y7SOGJ2S.js.map → tool-CEBL57UW.js.map} +0 -0
  99. /package/dist/{tool-FMKGK474.js.map → tool-TEGHFORD.js.map} +0 -0
  100. /package/dist/{wiki-SJRTAYMT.js.map → wiki-WOK4SCB7.js.map} +0 -0
@@ -5,12 +5,23 @@ import Foundation
5
5
  /// different play each time. Numbers only, like `PlayMath`.
6
6
  extension PlayMath {
7
7
  /// A piece cut out of the picture and drawn somewhere else: which
8
- /// part of the picture, where its top-left corner is now, and how far
9
- /// it has turned (radians).
8
+ /// part of the picture, where its top-left corner is now, how far it
9
+ /// has turned (radians), and the page's colour around it, which is
10
+ /// left out so only its ink moves.
10
11
  struct Piece: Equatable {
11
12
  var from: Rect
12
13
  var at: Point
13
14
  var turn = 0.0
15
+ var paper: UInt32 = 0xFFFFFF
16
+ }
17
+
18
+ /// How much of a pixel of a moved piece is drawn, 0…1: none of the
19
+ /// page's colour, all of the ink, and the soft edge of a letter in
20
+ /// between. Without it a flying letter carries a box of page with it
21
+ /// and covers the text it passes.
22
+ static func ink(r: UInt8, g: UInt8, b: UInt8, paper: UInt32) -> Double {
23
+ let far = max(abs(Int(r) - Int(paper >> 16 & 0xFF)), abs(Int(g) - Int(paper >> 8 & 0xFF)), abs(Int(b) - Int(paper & 0xFF)))
24
+ return min(max(Double(far - 10) / 40, 0), 1)
14
25
  }
15
26
 
16
27
  /// A piece from the moment it leaves its place. Its place is covered
@@ -36,18 +47,22 @@ extension PlayMath {
36
47
  static let gravity = 1400.0
37
48
  static let lift = 0.35
38
49
 
39
- /// Where a thrown piece is `seconds` after it left. It stops on the
40
- /// bottom of the picture and at its sides.
50
+ /// Where a thrown piece is `seconds` after it left. It bounces once
51
+ /// on the bottom of the picture and lies still, and stops at its sides.
41
52
  static func thrown(_ source: Rect, v: Point, spin: Double, rise: Double, after seconds: Double,
42
53
  width: Double, height: Double) -> Piece {
43
54
  let floor = max(height - source.h - rise, source.y)
44
55
  let landing = (-v.y + (v.y * v.y + 2 * gravity * (floor - source.y)).squareRoot()) / gravity
45
56
  let s = min(max(seconds, 0), landing)
46
- let x = min(max(source.x + v.x * s, 0), max(width - source.w, 0))
57
+ // How fast it comes down, and the bounce that makes: a third as
58
+ // fast, sideways too.
59
+ let hit = v.y + gravity * landing
60
+ let more = min(max(seconds - landing, 0), PlayMotion.bounceTime(speed: hit, gravity: gravity))
61
+ let x = min(max(source.x + v.x * (s + more / 3), 0), max(width - source.w, 0))
47
62
  // It turns about as fast as `spin`, and lands flat: the right way
48
63
  // up or upside down.
49
64
  let flat = (spin * landing / .pi).rounded() * .pi
50
- return Piece(from: source, at: Point(x: x, y: source.y + v.y * s + gravity * s * s / 2), turn: landing > 0 ? flat * s / landing : 0)
65
+ return Piece(from: source, at: Point(x: x, y: source.y + v.y * s + gravity * s * s / 2 - PlayMotion.bounce(more, speed: hit, gravity: gravity)), turn: landing > 0 ? flat * s / landing : 0)
51
66
  }
52
67
 
53
68
  /// What it can do to a line.
@@ -107,17 +122,29 @@ extension Play {
107
122
  f.gone.append((cover(cut.source), cut.paper))
108
123
  switch cut.path {
109
124
  case .thrown(let v, let spin, let rise):
110
- f.pieces.append(P.thrown(cut.source, v: v, spin: spin, rise: rise, after: f.t - cut.start, width: size.x, height: size.y))
125
+ var piece = P.thrown(cut.source, v: v, spin: spin, rise: rise, after: f.t - cut.start, width: size.x, height: size.y)
126
+ piece.paper = cut.paper
127
+ f.pieces.append(piece)
111
128
  case .held(let until, let to):
112
129
  // From its place to above the head, and from there down.
113
130
  let head = P.Point(x: f.at.x - cut.source.w / 2, y: f.at.y - P.top - cut.source.h)
114
131
  let a = f.t < until ? P.Point(x: cut.source.x, y: cut.source.y) : head, b = f.t < until ? head : to
115
132
  let q = M.ease(f.t < until ? M.span(f.t, cut.start, cut.start + P.lift) : M.span(f.t, until, until + P.lift))
116
- f.pieces.append(P.Piece(from: cut.source, at: P.Point(x: a.x + (b.x - a.x) * q, y: a.y + (b.y - a.y) * q)))
133
+ f.pieces.append(P.Piece(from: cut.source, at: P.Point(x: a.x + (b.x - a.x) * q, y: a.y + (b.y - a.y) * q), paper: cut.paper))
117
134
  }
118
135
  }
119
136
  }
120
137
 
138
+ /// How far along a move it is: a jump crouches first and lands at the
139
+ /// end, a walk and a wipe start and stop, the rest keep one pace.
140
+ func body(_ m: Move, at t: Double) -> PlayMotion.Body {
141
+ switch m.kind {
142
+ case .jump, .carry: return PlayMotion.jump(t - m.start, of: m.duration)
143
+ case .walk, .wipe: return PlayMotion.glide(t - m.start, of: m.duration)
144
+ default: return PlayMotion.Body(travel: M.span(t, m.start, m.end))
145
+ }
146
+ }
147
+
121
148
  /// Which way it faces during a move, and its pose without the motion.
122
149
  func look(_ m: Move) -> (face: Double, pose: M.Pose) {
123
150
  let way: Double = m.to.x >= m.from.x ? 1 : -1
@@ -90,6 +90,7 @@ enum PlayMath {
90
90
  struct Play {
91
91
  typealias P = PlayMath
92
92
  typealias M = CharacterMath
93
+ typealias Mo = PlayMotion
93
94
 
94
95
  enum Kind { case jump, walk, eat, wipe, kick, stomp, fall, lift, carry, drop, rest }
95
96
 
@@ -131,13 +132,16 @@ struct Play {
131
132
  self.lines = lines
132
133
  self.size = size
133
134
  var at = start, now = 0.0
135
+ /// The seconds of a jump over `points`: its crouch, its time in
136
+ /// the air and its landing.
137
+ func leap(_ points: Double) -> Double { Mo.crouch + 0.34 + points / 900 + Mo.landing }
134
138
  func add(_ kind: Kind, to: P.Point, _ seconds: Double, line: Int = 0, words: Range<Int> = 0..<0) -> Move {
135
139
  Move(kind: kind, from: at, to: to, start: now, duration: seconds, line: line, words: words)
136
140
  }
137
141
  /// Get to `to` first: a jump, unless it is already there.
138
142
  func reach(_ to: P.Point, into list: inout [Move]) {
139
143
  guard at != to else { return }
140
- let m = add(.jump, to: to, 0.5 + hypot(to.x - at.x, to.y - at.y) / 900)
144
+ let m = add(.jump, to: to, leap(hypot(to.x - at.x, to.y - at.y)))
141
145
  list.append(m); at = to; now = m.end
142
146
  }
143
147
  var list: [Move] = [], cuts: [P.Cut] = []
@@ -183,8 +187,10 @@ struct Play {
183
187
  let word = lines[i].words[w]
184
188
  reach(P.Point(x: word.rect.x - P.mouth - 4, y: lines[i].rect.midY + P.middle), into: &list)
185
189
  let m = stay(.kick, 0.6, line: i)
186
- for (k, letter) in P.letters(of: word).enumerated() {
187
- throwing(letter, line: i, at: m.start + 0.25, v: P.Point(x: 150 + 40 * Double(k), y: -320 - 30 * Double(k % 3)),
190
+ // The letters leave one after the other, the nearest first.
191
+ let letters = P.letters(of: word)
192
+ for (k, letter) in letters.enumerated() {
193
+ throwing(letter, line: i, at: m.start + 0.25 + Mo.stagger(k, of: letters.count), v: P.Point(x: 150 + 40 * Double(k), y: -320 - 30 * Double(k % 3)),
188
194
  spin: 4 + Double(k % 3))
189
195
  }
190
196
  case .stomp(let i):
@@ -207,7 +213,7 @@ struct Play {
207
213
  let word = lines[i].words[w].rect, home = lines[j].rect
208
214
  reach(P.Point(x: word.x - P.mouth - 4, y: lines[i].rect.midY + P.middle), into: &list)
209
215
  let up = stay(.lift, P.lift, line: i)
210
- let m = add(.carry, to: P.Point(x: home.maxX - 4, y: home.y), 0.5 + hypot(home.maxX - 4 - at.x, home.y - at.y) / 900, line: j)
216
+ let m = add(.carry, to: P.Point(x: home.maxX - 4, y: home.y), leap(hypot(home.maxX - 4 - at.x, home.y - at.y)), line: j)
211
217
  list.append(m); at = m.to; now = m.end
212
218
  let down = stay(.drop, P.lift, line: j)
213
219
  // After the line, or on top of its end when the page stops there.
@@ -228,12 +234,13 @@ struct Play {
228
234
  let m = moves[i], p = M.span(t, m.start, m.end)
229
235
  var f = Frame(t: t, done: t >= duration)
230
236
 
231
- f.at = P.Point(x: m.from.x + (m.to.x - m.from.x) * p, y: m.from.y + (m.to.y - m.from.y) * p)
237
+ let body = body(m, at: t)
238
+ f.at = P.Point(x: m.from.x + (m.to.x - m.from.x) * body.travel, y: m.from.y + (m.to.y - m.from.y) * body.travel)
232
239
  switch m.kind {
233
240
  case .jump, .carry:
234
241
  // An arc over both ends, kept inside the picture.
235
242
  let rise = 30 + hypot(m.to.x - m.from.x, m.to.y - m.from.y) * 0.12
236
- f.at.y -= min(rise, max(min(m.from.y, m.to.y) - P.top, 0)) * 4 * p * (1 - p)
243
+ f.at.y -= min(rise, max(min(m.from.y, m.to.y) - P.top, 0)) * body.air
237
244
  // Three hops on the spot.
238
245
  case .stomp: f.at.y -= min(22, max(m.from.y - P.top, 0)) * abs(sin(3 * .pi * p))
239
246
  // Faster and faster.
@@ -249,10 +256,11 @@ struct Play {
249
256
  f.face = before.face + (now.face - before.face) * into
250
257
  f.pose = M.blend(before.pose, now.pose, eyes: into, body: into, marks: into)
251
258
  switch m.kind {
252
- case .walk: f.pose.lift += 3 * into * abs(sin(2 * .pi * t * 2.2))
259
+ // A step every 50 points, smaller while it starts and stops.
260
+ case .walk: f.pose.lift += 3 * body.speed * abs(sin(.pi * abs(f.at.x - m.from.x) / 50))
253
261
  case .jump, .carry:
254
- let air = sin(.pi * p)
255
- f.pose.sy *= 1 + 0.12 * air; f.pose.sx *= 1 - 0.08 * air
262
+ f.pose.sy *= body.sy; f.pose.sx *= body.sx
263
+ f.pose.lift *= 1 - 0.5 * body.dip
256
264
  case .eat:
257
265
  let bite = into * (0.5 + 0.5 * sin(2 * .pi * t / P.perLetter))
258
266
  f.pose.sy *= 1 - 0.08 * bite; f.pose.sx *= 1 + 0.05 * bite
@@ -0,0 +1,110 @@
1
+ import Foundation
2
+
3
+ /// How things move in play mode (#505), after the rules the videos are
4
+ /// made with: nothing starts or stops at full speed, a jump is announced
5
+ /// by a crouch and ends in a soft landing, letters leave one after the
6
+ /// other, and what falls bounces once before it lies still. Numbers only.
7
+ enum PlayMotion {
8
+ typealias M = CharacterMath
9
+
10
+ /// Fast start, slow stop; and slow start, fast end.
11
+ static func out(_ p: Double) -> Double { 1 - into(1 - p) }
12
+ static func into(_ p: Double) -> Double {
13
+ let p = min(max(p, 0), 1)
14
+ return p * p
15
+ }
16
+
17
+ /// The body at one moment of a move: how far along its way (0…1),
18
+ /// how high in its arc (0…1), its stretch, how deep it sits on its
19
+ /// feet (0…1) and how fast it goes (0…1).
20
+ struct Body: Equatable {
21
+ var travel = 0.0, air = 0.0
22
+ var sx = 1.0, sy = 1.0
23
+ var dip = 0.0
24
+ var speed = 0.0
25
+ }
26
+
27
+ /// Seconds: the crouch before a jump, the landing after it, and the
28
+ /// start and the stop of a walk.
29
+ static let crouch = 0.16
30
+ static let landing = 0.26
31
+ static let walkUp = 0.2
32
+ static let walkDown = 0.26
33
+ /// How much taller the body is at full stretch, and how much shorter
34
+ /// at the deepest of a crouch and of a landing.
35
+ static let stretch = 0.14
36
+ static let squat = 0.16
37
+ static let squash = 0.2
38
+
39
+ /// A jump of `duration` seconds, `t` seconds in. It crouches first
40
+ /// and goes nowhere, leaves stretched, is round at the top, comes
41
+ /// down stretched, and lands: squashed, a little too tall once, then
42
+ /// still. It has arrived when the landing begins.
43
+ static func jump(_ t: Double, of duration: Double) -> Body {
44
+ guard duration > 0 else { return Body(travel: 1) }
45
+ let t = min(max(t, 0), duration)
46
+ let before = min(crouch, duration * 0.25), after = min(landing, duration * 0.3)
47
+ // A jump too short for a whole landing changes shape less, not faster.
48
+ let long = stretch * after / landing, flat = squash * after / landing
49
+ if t < before {
50
+ // Down slowly, up fast: the push.
51
+ let q = t / before
52
+ let deep = q < 0.65 ? out(q / 0.65) : 1 - into((q - 0.65) / 0.35)
53
+ return Body(sx: 1 + squat * 0.7 * deep, sy: 1 - squat * deep, dip: deep)
54
+ }
55
+ if t <= duration - after {
56
+ let u = M.span(t, before, duration - after)
57
+ // Stretched while it moves fast up or down, round at the top.
58
+ let more = long * abs(1 - 2 * u) * min(u / 0.12, 1)
59
+ return Body(travel: u, air: 4 * u * (1 - u), sx: 1 - more * 0.6, sy: 1 + more, speed: 1)
60
+ }
61
+ let more = keys([(0, long), (0.4, -flat), (0.72, 0.04), (1, 0)], at: (t - (duration - after)) / after)
62
+ return Body(travel: 1, sx: 1 - more * 0.6, sy: 1 + more, dip: max(-more / flat, 0))
63
+ }
64
+
65
+ /// A walk, or a wipe, of `duration` seconds, `t` seconds in: it gets
66
+ /// up to speed, keeps it, and slows to a stop.
67
+ static func glide(_ t: Double, of duration: Double) -> Body {
68
+ guard duration > 0 else { return Body(travel: 1) }
69
+ let t = min(max(t, 0), duration)
70
+ let up = min(walkUp, duration / 3), down = min(walkDown, duration / 3)
71
+ // Full speed, in ways a second.
72
+ let top = 1 / (duration - up / 2 - down / 2)
73
+ if t < up { return Body(travel: top * t * t / (2 * up), speed: t / up) }
74
+ if t <= duration - down { return Body(travel: top * (t - up / 2), speed: 1) }
75
+ let left = duration - t
76
+ return Body(travel: 1 - top * left * left / (2 * down), speed: left / down)
77
+ }
78
+
79
+ /// When the `k`th of `count` things starts after the first: one after
80
+ /// the other, and all gone within 0.4 seconds, so it reads as one go.
81
+ static func stagger(_ k: Int, of count: Int) -> Double {
82
+ guard count > 1 else { return 0 }
83
+ return Double(k) * min(0.035, 0.4 / Double(count - 1))
84
+ }
85
+
86
+ /// How high something is above where it landed, `seconds` after it
87
+ /// hit at `speed` (points a second) under `gravity`: one bounce, a
88
+ /// third as fast as it came down, then it lies still.
89
+ static func bounce(_ seconds: Double, speed: Double, gravity: Double) -> Double {
90
+ let up = abs(speed) / 3
91
+ guard seconds > 0, gravity > 0 else { return 0 }
92
+ return max(up * seconds - gravity * seconds * seconds / 2, 0)
93
+ }
94
+
95
+ /// The seconds that bounce lasts.
96
+ static func bounceTime(speed: Double, gravity: Double) -> Double {
97
+ gravity > 0 ? 2 * abs(speed) / 3 / gravity : 0
98
+ }
99
+
100
+ /// The value at `p` between (place, value) keys in order, eased from
101
+ /// each key to the next.
102
+ static func keys(_ keys: [(at: Double, value: Double)], at p: Double) -> Double {
103
+ guard let first = keys.first, let last = keys.last else { return 0 }
104
+ if p <= first.at { return first.value }
105
+ for (a, b) in zip(keys, keys.dropFirst()) where p <= b.at {
106
+ return a.value + (b.value - a.value) * M.ease(M.span(p, a.at, b.at))
107
+ }
108
+ return last.value
109
+ }
110
+ }
@@ -4,7 +4,7 @@ import AppKit
4
4
  /// words are gone, the pieces that moved, the cloth, and the character. The context is flipped,
5
5
  /// in the picture's points.
6
6
  enum PlayDraw {
7
- static func draw(_ frame: Play.Frame, in ctx: CGContext, stops: [NSColor], picture: CGImage?, scale: CGFloat) {
7
+ static func draw(_ frame: Play.Frame, in ctx: CGContext, stops: [NSColor], cutouts: PlayCutouts?) {
8
8
  for gone in frame.gone {
9
9
  let c = gone.paper
10
10
  ctx.setFillColor(CGColor(srgbRed: CGFloat(c >> 16 & 0xFF) / 255, green: CGFloat(c >> 8 & 0xFF) / 255,
@@ -13,7 +13,7 @@ enum PlayDraw {
13
13
  }
14
14
  for piece in frame.pieces {
15
15
  let from = cg(piece.from)
16
- guard let part = picture?.cropping(to: from.applying(CGAffineTransform(scaleX: scale, y: scale))) else { continue }
16
+ guard let part = cutouts?.image(from, paper: piece.paper) else { continue }
17
17
  ctx.saveGState()
18
18
  ctx.translateBy(x: piece.at.x + from.width / 2, y: piece.at.y + from.height / 2)
19
19
  ctx.rotate(by: piece.turn)
@@ -40,6 +40,41 @@ enum PlayDraw {
40
40
  private static func cg(_ r: PlayMath.Rect) -> CGRect { CGRect(x: r.x, y: r.y, width: r.w, height: r.h) }
41
41
  }
42
42
 
43
+ /// The pieces of the picture that move, each cut out once: the ink alone,
44
+ /// the page's colour around it left out (`PlayMath.ink`).
45
+ final class PlayCutouts {
46
+ private let picture: CGImage
47
+ /// Pixels of the picture per point.
48
+ private let scale: CGFloat
49
+ private var made: [[CGFloat]: CGImage] = [:]
50
+
51
+ init(picture: CGImage, scale: CGFloat) {
52
+ self.picture = picture
53
+ self.scale = scale
54
+ }
55
+
56
+ /// The part of the picture at `from` (points), without its paper.
57
+ func image(_ from: CGRect, paper: UInt32) -> CGImage? {
58
+ let key = [from.minX, from.minY, from.width, from.height]
59
+ if let done = made[key] { return done }
60
+ guard let part = picture.cropping(to: from.applying(CGAffineTransform(scaleX: scale, y: scale))),
61
+ let ctx = CGContext(data: nil, width: part.width, height: part.height, bitsPerComponent: 8, bytesPerRow: part.width * 4,
62
+ space: CGColorSpace(name: CGColorSpace.sRGB)!, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue),
63
+ let data = ctx.data else { return nil }
64
+ ctx.draw(part, in: CGRect(x: 0, y: 0, width: part.width, height: part.height))
65
+ let px = data.bindMemory(to: UInt8.self, capacity: part.width * part.height * 4)
66
+ for i in stride(from: 0, to: part.width * part.height * 4, by: 4) {
67
+ let a = PlayMath.ink(r: px[i], g: px[i + 1], b: px[i + 2], paper: paper)
68
+ // Premultiplied: the colour fades with it.
69
+ for k in 0..<3 { px[i + k] = UInt8(Double(px[i + k]) * a) }
70
+ px[i + 3] = UInt8(255 * a)
71
+ }
72
+ let image = ctx.makeImage()
73
+ made[key] = image
74
+ return image
75
+ }
76
+ }
77
+
43
78
  /// The stage: a frozen picture of the screen laid over everything, with
44
79
  /// the character playing on it. The real page is never touched: nothing
45
80
  /// is clicked, typed or changed, and what looks eaten or wiped is only
@@ -157,7 +192,8 @@ private final class PlayView: NSView {
157
192
  var shown = Play.Frame()
158
193
  var stops = CharacterDraw.stops(tint: Brand.accent, colors: nil)
159
194
  /// The picture under it: moved pieces are cut from it.
160
- var picture: CGImage?
195
+ var picture: CGImage? { didSet { cutouts = nil } }
196
+ private var cutouts: PlayCutouts?
161
197
  var onInput: (() -> Void)?
162
198
 
163
199
  override var isFlipped: Bool { true }
@@ -166,8 +202,10 @@ private final class PlayView: NSView {
166
202
 
167
203
  override func draw(_ dirtyRect: NSRect) {
168
204
  guard let ctx = NSGraphicsContext.current?.cgContext else { return }
169
- PlayDraw.draw(shown, in: ctx, stops: stops, picture: picture,
170
- scale: CGFloat(picture?.width ?? 0) / max(bounds.width, 1))
205
+ if cutouts == nil, let picture {
206
+ cutouts = PlayCutouts(picture: picture, scale: CGFloat(picture.width) / max(bounds.width, 1))
207
+ }
208
+ PlayDraw.draw(shown, in: ctx, stops: stops, cutouts: cutouts)
171
209
  }
172
210
 
173
211
  override func keyDown(with event: NSEvent) { onInput?() }
@@ -1,8 +1,8 @@
1
- import{a as F,b as L,c as U,d as N,e as O,f as H,g as j}from"./chunk-U2CKL755.js";import{b as B,c as D,d as A,e as P,g as M}from"./chunk-ZCQCUA4J.js";import"./chunk-ERPEU2ZR.js";import"./chunk-RJ7DASOU.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-QIJLFPWE.js";import{useEffect as R,useReducer as V,useRef as G}from"react";import{Box as i,Text as o,useApp as W,useInput as J}from"ink";import{randomUUID as z}from"crypto";async function*q(e){let r=[];e.type&&r.push(`type=${encodeURIComponent(e.type)}`);let t=`${e.baseUrl.replace(/\/+$/,"")}/events${r.length?`?${r.join("&")}`:""}`,n={Accept:"text/event-stream"};e.token&&(n.Authorization=`Bearer ${e.token}`);let s=await fetch(t,{headers:n,signal:e.signal});if(!s.ok||!s.body)throw new Error(`SSE connect failed: HTTP ${s.status}`);let u=s.body.getReader(),p=new TextDecoder,y="";try{for(;;){let{done:f,value:l}=await u.read();if(f)return;y+=p.decode(l,{stream:!0});let d;for(;(d=y.indexOf(`
1
+ import{a as F,b as L,c as U,d as N,e as O,f as H,g as j}from"./chunk-U2CKL755.js";import{b as B,c as D,d as A,e as P,g as M}from"./chunk-GJ5EJVMZ.js";import"./chunk-JREA25GJ.js";import"./chunk-RJ7DASOU.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-QIJLFPWE.js";import{useEffect as R,useReducer as V,useRef as G}from"react";import{Box as i,Text as o,useApp as W,useInput as J}from"ink";import{randomUUID as z}from"crypto";async function*q(e){let r=[];e.type&&r.push(`type=${encodeURIComponent(e.type)}`);let t=`${e.baseUrl.replace(/\/+$/,"")}/events${r.length?`?${r.join("&")}`:""}`,n={Accept:"text/event-stream"};e.token&&(n.Authorization=`Bearer ${e.token}`);let s=await fetch(t,{headers:n,signal:e.signal});if(!s.ok||!s.body)throw new Error(`SSE connect failed: HTTP ${s.status}`);let u=s.body.getReader(),p=new TextDecoder,y="";try{for(;;){let{done:f,value:l}=await u.read();if(f)return;y+=p.decode(l,{stream:!0});let d;for(;(d=y.indexOf(`
2
2
 
3
3
  `))>=0;){let h=y.slice(0,d);y=y.slice(d+2);let m=X(h);m&&(yield m)}}}finally{try{u.releaseLock()}catch{}}}function X(e){let r="message",t="";for(let s of e.split(`
4
4
  `))s.startsWith("event: ")?r=s.slice(7):s.startsWith("data: ")&&(t=s.slice(6));if(!t)return null;let n;try{n=JSON.parse(t)}catch{n=t}return{event:r,data:n}}import{jsx as a,jsxs as c}from"react/jsx-runtime";function $(e,r){return r<=0||e<0?0:e>=r?r-1:e}function E(){return`tui:${z().slice(0,12)}`}function k(e,r){let t=[...e,r];return t.length>50&&t.splice(0,t.length-50),t}function Y(e,r){switch(r.type){case"agents":return{...e,agents:r.data,cursor:{...e.cursor,agents:$(e.cursor.agents,r.data.length)}};case"processes":return{...e,processes:r.data,cursor:{...e.cursor,processes:$(e.cursor.processes,r.data.length)}};case"crons":return{...e,crons:r.data};case"event":{let t=[r.row,...e.events];t.length>200&&(t.length=200);let n=e.channels;return r.channelTally&&(n=new Map(e.channels),n.set(r.channelTally.channel,r.channelTally)),{...e,events:t,channels:n}}case"connError":return{...e,connError:r.error};case"tick":return{...e,lastTick:Date.now()};case"focus":return{...e,focus:r.pane};case"cursor":{let t=r.pane==="agents"?e.agents.length:r.pane==="processes"?e.processes.length:e.events.length;return{...e,cursor:{...e.cursor,[r.pane]:$(e.cursor[r.pane]+r.delta,t)}}}case"bottomRight":return{...e,bottomRight:r.pane};case"chatStart":return{...e,chat:{active:!0,agentId:r.agentId,chatId:E(),history:[],text:"",status:"idle",error:null}};case"chatExit":return{...e,chat:{...e.chat,active:!1}};case"chatClear":return{...e,chat:{...e.chat,chatId:E(),history:[],text:"",status:"idle",error:null}};case"chatText":return{...e,chat:{...e.chat,text:r.text}};case"chatSubmitStart":return{...e,chat:{...e.chat,history:k(e.chat.history,r.you),text:"",status:"sending",error:null}};case"chatSubmitDone":return{...e,chat:{...e.chat,history:k(e.chat.history,r.reply),status:"idle",error:null}};case"chatSubmitError":return{...e,chat:{...e.chat,history:k(e.chat.history,{role:"error",text:r.error,at:Date.now()}),status:"idle",error:r.error}};case"chatStreamStart":{let t=k(e.chat.history,r.you),n=k(t,{role:"agent",text:"",at:Date.now(),streaming:!0,tools:[]});return{...e,chat:{...e.chat,history:n,text:"",status:"sending",error:null}}}case"chatStreamDelta":{let t=e.chat.history.slice(),n=t[t.length-1];return n?.role==="agent"&&n.streaming&&(t[t.length-1]={...n,text:n.text+r.text}),{...e,chat:{...e.chat,history:t}}}case"chatStreamThinking":{let t=e.chat.history.slice(),n=t[t.length-1];return n?.role==="agent"&&n.streaming&&(t[t.length-1]={...n,thinking:(n.thinking??"")+r.text}),{...e,chat:{...e.chat,history:t}}}case"chatStreamTool":{let t=e.chat.history.slice(),n=t[t.length-1];return n?.role==="agent"&&n.streaming&&(t[t.length-1]={...n,tools:[...n.tools??[],{name:r.name,arg:r.arg,error:r.error}]}),{...e,chat:{...e.chat,history:t}}}case"chatStreamEnd":{let t=e.chat.history.slice(),n=t[t.length-1];return n?.role==="agent"&&n.streaming&&(t[t.length-1]=r.error?{...n,streaming:!1,role:"error",text:r.error}:{...n,streaming:!1,elapsedMs:r.elapsedMs,outTokens:r.outTokens}),{...e,chat:{...e.chat,history:t,status:"idle",error:r.error??null}}}case"toast":return{...e,toast:{text:r.text,color:r.color,at:Date.now()}};case"clearToast":return{...e,toast:null}}}var _={agents:[],processes:[],crons:[],events:[],channels:new Map,connError:null,lastTick:0,focus:"agents",cursor:{agents:0,processes:0,events:0},bottomRight:"crons",chat:{active:!1,agentId:null,chatId:E(),history:[],text:"",status:"idle",error:null},toast:null};function be({conn:e,pollMs:r=3e3}){let[t,n]=V(Y,_),{exit:s}=W(),u=G(null),p=G(null),y=t.agents.map(l=>l.id),f=t.chat.active?L(t.chat.text,y,process.cwd()):null;return R(()=>{if(!t.toast)return;let l=setTimeout(()=>n({type:"clearToast"}),3500);return()=>clearTimeout(l)},[t.toast]),J((l,d)=>{if(t.chat.active){if(d.escape){n({type:"chatExit"});return}if(d.ctrl&&l==="l"){n({type:"chatClear"});return}if(d.tab){let m=U(t.chat.text,p,y,process.cwd());m!==null&&n({type:"chatText",text:m});return}if(d.backspace||d.delete){p.current=null,n({type:"chatText",text:t.chat.text.slice(0,-1)});return}if(d.ctrl||d.meta)return;let h=N(l??"",d.return,t.chat.text);if(h.kind==="paste"||h.kind==="type"){p.current=null,n({type:"chatText",text:t.chat.text+h.text});return}if(h.kind==="continue"){n({type:"chatText",text:h.buffer});return}if(h.kind==="submit"){let m=h.text.trim(),g=t.chat.agentId;if(!m||!g||t.chat.status==="sending"){n({type:"chatText",text:""});return}p.current=null;let b=Date.now(),w=t.chat.chatId;n({type:"chatStreamStart",you:{role:"you",text:m,at:b}}),(async()=>{try{let C=await M(e,g,m,{channel:"tui",chatId:w,onText:x=>n({type:"chatStreamDelta",text:x}),onThinking:x=>n({type:"chatStreamThinking",text:x}),onTool:x=>{x.status==="start"&&x.name?n({type:"chatStreamTool",name:x.name,arg:x.arg}):x.status==="result"&&x.error&&n({type:"chatStreamTool",name:x.name??"tool",error:!0})}});n({type:"chatStreamEnd",elapsedMs:Date.now()-b,outTokens:C.usage?.outputTokens,error:C.error})}catch(C){n({type:"chatStreamEnd",elapsedMs:Date.now()-b,error:C?.message||String(C)})}})();return}return}if(l==="q"||d.ctrl&&l==="c"){u.current?.abort(),s();return}if(d.tab){let h=["agents","processes","events"],m=h.indexOf(t.focus);n({type:"focus",pane:h[(m+1)%h.length]});return}if(l==="a"){n({type:"focus",pane:"agents"});return}if(l==="p"){n({type:"focus",pane:"processes"});return}if(l==="e"){n({type:"focus",pane:"events"});return}if(l==="c"){n({type:"bottomRight",pane:t.bottomRight==="crons"?"channels":"crons"});return}if(d.upArrow){n({type:"cursor",pane:t.focus,delta:-1});return}if(d.downArrow){n({type:"cursor",pane:t.focus,delta:1});return}if(d.return&&t.focus==="agents"){let h=t.agents[t.cursor.agents];if(!h){n({type:"toast",text:"no agent selected",color:"yellow"});return}n({type:"chatStart",agentId:h.id});return}if(l==="k"&&t.focus==="processes"){let h=t.processes[t.cursor.processes];if(!h){n({type:"toast",text:"no process selected",color:"yellow"});return}(async()=>{try{await P(e,h.key,"tui"),n({type:"toast",text:`killed ${h.key.agentId}/${h.key.channel}/${h.key.chatId}`,color:"green"})}catch(m){n({type:"toast",text:`kill failed: ${m?.message||m}`,color:"red"})}})();return}}),R(()=>{let l=new AbortController;u.current=l;let d=!1,h=async()=>{try{let[g,b,w]=await Promise.all([B(e,l.signal).catch(()=>[]),D(e,l.signal).catch(()=>[]),A(e,l.signal).catch(()=>[])]);if(d)return;n({type:"agents",data:g}),n({type:"processes",data:b}),n({type:"crons",data:w}),n({type:"tick"}),n({type:"connError",error:null})}catch(g){d||n({type:"connError",error:g?.message||String(g)})}};h();let m=setInterval(h,r);return()=>{d=!0,clearInterval(m),l.abort()}},[e.baseUrl,e.token,r]),R(()=>{let l=!1,d=new AbortController,h=new Map;return(async()=>{let m=500;for(;!l;){try{for await(let g of q({baseUrl:e.baseUrl,token:e.token,signal:d.signal})){let b=ae(g),w;if(g.event==="channel"&&typeof g.data?.channel=="string"){let S=h.get(g.data.channel)??{channel:g.data.channel,inbound:0,outbound:0,lastAt:0,lastPreview:""},C=S.inbound+(g.data.direction==="in"?1:0),x=S.outbound+(g.data.direction==="out"?1:0);w={channel:g.data.channel,inbound:C,outbound:x,lastAt:b.at,lastPreview:(g.data.textPreview||"").slice(0,60)},h.set(g.data.channel,w)}n({type:"event",row:b,channelTally:w}),m=500}}catch(g){if(l)return;n({type:"connError",error:`events: ${g?.message||g}`})}await new Promise(g=>setTimeout(g,m)),m=Math.min(m*2,1e4)}})(),()=>{l=!0,d.abort()}},[e.baseUrl,e.token]),c(i,{flexDirection:"column",width:"100%",children:[a(K,{conn:e,lastTick:t.lastTick,connError:t.connError,chat:t.chat}),c(i,{flexDirection:"row",flexGrow:1,children:[c(i,{flexDirection:"column",width:"50%",children:[a(v,{title:"AGENTS",focused:!t.chat.active&&t.focus==="agents",children:a(Z,{rows:t.agents,cursor:t.cursor.agents,focused:!t.chat.active&&t.focus==="agents",talkingTo:t.chat.active?t.chat.agentId:null})}),a(v,{title:"PROCESSES",focused:!t.chat.active&&t.focus==="processes",children:a(ee,{rows:t.processes,cursor:t.cursor.processes,focused:!t.chat.active&&t.focus==="processes"})})]}),t.chat.active?a(oe,{chat:t.chat,suggest:f,agents:t.agents}):c(i,{flexDirection:"column",width:"50%",children:[a(v,{title:"LIVE EVENTS",focused:t.focus==="events",children:a(ne,{rows:t.events,cursor:t.cursor.events,focused:t.focus==="events"})}),a(v,{title:t.bottomRight==="crons"?"CRONS / SCHEDULES":"CHANNELS",focused:!1,children:t.bottomRight==="crons"?a(te,{rows:t.crons}):a(re,{rows:Array.from(t.channels.values())})})]})]}),a(Q,{focus:t.focus,bottomRight:t.bottomRight,chat:t.chat,toast:t.toast})]})}function K({conn:e,lastTick:r,connError:t,chat:n}){let s=t?c(o,{color:"red",children:["\u25CF ",t]}):r===0?a(o,{color:"yellow",children:"\u25CF connecting\u2026"}):a(o,{color:"green",children:"\u25CF live"}),u=n.active?c(o,{color:"green",bold:!0,children:["CHAT @",n.agentId]}):a(o,{bold:!0,children:"agentx tui"});return c(i,{paddingX:1,justifyContent:"space-between",children:[a(i,{children:u}),a(o,{dimColor:!0,children:e.baseUrl}),a(i,{children:s})]})}function Q({focus:e,bottomRight:r,chat:t,toast:n}){let s=t.active?["[Enter] send","[Esc] exit chat","[Ctrl-L] new session"]:[`[Tab/a/p/e] focus (now: ${e})`,e==="agents"?"[Enter] chat":null,e==="processes"?"[k] kill":null,`[c] ${r==="crons"?"\u2192channels":"\u2192crons"}`,"[\u2191/\u2193] move","[q] quit"].filter(Boolean);return c(i,{paddingX:1,borderStyle:"single",borderTop:!0,borderBottom:!1,borderLeft:!1,borderRight:!1,justifyContent:"space-between",children:[a(o,{dimColor:!0,children:s.join(" \xB7 ")}),n?a(o,{color:n.color,children:n.text}):a(o,{children:" "})]})}function v({title:e,focused:r,children:t}){return c(i,{flexDirection:"column",width:"100%",borderStyle:r?"double":"single",borderColor:r?"cyan":void 0,paddingX:1,children:[c(o,{bold:!0,color:r?"cyan":"white",children:[e,r?" \u25CF":""]}),a(i,{flexDirection:"column",marginTop:1,children:t})]})}function I(e,r){return e&&r?{inverse:!0}:{}}function Z({rows:e,cursor:r,focused:t,talkingTo:n}){return e.length===0?a(o,{dimColor:!0,children:"no agents"}):a(i,{flexDirection:"column",children:e.slice(0,12).map((s,u)=>{let p=I(t,u===r),y=s.errors>0?"red":s.active>0?"yellow":"green",f=s.id===n;return c(i,{children:[a(o,{...p,color:y,children:"\u25CF"}),c(o,{...p,children:[" ",T(s.name,14)]}),c(o,{...p,children:[T(s.tier,6)," "]}),c(o,{...p,children:[s.active,"/",s.total]}),s.errors>0?c(o,{...p,color:"red",children:[" err=",s.errors]}):null,f?a(o,{color:"green",children:" \u2194 chatting"}):null]},s.id)})})}function ee({rows:e,cursor:r,focused:t}){if(e.length===0)return a(o,{dimColor:!0,children:"no live processes"});let n=Date.now();return a(i,{flexDirection:"column",children:e.slice(0,12).map((s,u)=>{let p=I(t,u===r),y=Math.max(0,Math.round((n-(s.lastTurnAt||s.spawnedAt))/1e3)),f=s.state==="dead"?"red":s.state==="warm-hot"?"green":"yellow";return c(i,{children:[a(o,{...p,color:f,children:T(s.state,10)}),a(o,{...p,children:T(s.key.agentId,12)}),a(o,{...p,children:T(s.key.channel,10)}),c(o,{...p,children:[s.turnCount,"t ",y,"s"]})]},`${s.key.agentId}-${s.key.channel}-${s.key.chatId}-${u}`)})})}function te({rows:e}){return e.length===0?a(o,{dimColor:!0,children:"no crons"}):a(i,{flexDirection:"column",children:e.slice(0,12).map(r=>{let t=r.enabled?r.consecutiveErrors>0?a(o,{color:"red",children:"err"}):a(o,{color:"green",children:"ok"}):a(o,{dimColor:!0,children:"off"}),n=r.nextRun?new Date(r.nextRun).toLocaleTimeString():"\u2014";return c(i,{children:[a(o,{children:T(r.id,16)}),a(o,{dimColor:!0,children:T(r.schedule,12)}),a(o,{children:T(n,10)}),a(i,{children:t})]},r.id)})})}function re({rows:e}){if(e.length===0)return a(o,{dimColor:!0,children:"(waiting for channel events\u2026)"});let r=[...e].sort((t,n)=>n.lastAt-t.lastAt);return a(i,{flexDirection:"column",children:r.slice(0,12).map(t=>c(i,{children:[a(o,{children:T(t.channel,12)}),c(o,{color:"cyan",children:["\u2190",T(String(t.inbound),4)]}),c(o,{color:"magenta",children:["\u2192",T(String(t.outbound),4)]}),a(o,{dimColor:!0,children:t.lastPreview})]},t.channel))})}function ne({rows:e,cursor:r,focused:t}){return e.length===0?a(o,{dimColor:!0,children:"(waiting for events\u2026)"}):a(i,{flexDirection:"column",children:e.slice(0,18).map((n,s)=>{let u=I(t,s===r);return c(i,{children:[a(o,{...u,dimColor:!0,children:new Date(n.at).toLocaleTimeString().padEnd(10)}),a(o,{...u,color:ce(n.kind),children:T(n.kind,8)}),a(o,{...u,children:n.line})]},`${n.at}-${s}`)})})}function oe({chat:e,suggest:r,agents:t}){let n=e.history.slice(-14),s=t.find(f=>f.id===e.agentId),u=H(s?.tier??"",s?.model),p=e.status==="sending"?[...e.history].reverse().find(f=>f.role==="agent"&&f.streaming):void 0,y=e.status==="sending"?a(O,{startedAt:p?.at??Date.now(),phase:p?.text?"responding":"thinking",indent:""}):e.error?c(o,{color:"red",children:["\u25CF ",e.error]}):a(o,{dimColor:!0,children:"\u25CF ready"});return c(i,{flexDirection:"column",width:"50%",borderStyle:"double",borderColor:"green",paddingX:1,children:[c(i,{justifyContent:"space-between",children:[c(o,{bold:!0,color:"green",children:["CHAT \xB7 @",e.agentId]}),a(i,{children:y})]}),c(o,{children:[c(o,{color:u.color,bold:!0,children:[u.glyph," ",u.label]}),s?.model?c(o,{dimColor:!0,children:[" ",j(s.model)]}):null,c(o,{dimColor:!0,children:[" \xB7 ",e.chatId]})]}),a(i,{flexDirection:"column",flexGrow:1,marginTop:1,children:n.length===0?a(o,{dimColor:!0,children:"(type a message and press Enter \u2014 Esc exits, Ctrl-L starts fresh)"}):n.map((f,l)=>a(se,{turn:f,agentId:e.agentId},`${f.at}-${l}`))}),r?c(o,{dimColor:!0,children:[a(o,{color:"cyan",children:"\u21B9"})," ",r.items.slice(0,5).map((f,l)=>l===0?a(o,{color:"cyan",children:f},l):c(o,{children:[" ",f]},l))]}):null,c(i,{children:[a(o,{color:"cyan",children:"you \u203A "}),a(o,{children:e.text}),a(o,{inverse:!0,children:" "})]})]})}function se({turn:e,agentId:r}){if(e.role==="you")return c(i,{flexDirection:"column",marginBottom:1,children:[a(o,{color:"cyan",children:"you"}),e.text.split(`
5
5
  `).map((s,u)=>c(o,{children:[" ",s]},u))]});if(e.role==="error")return c(i,{flexDirection:"column",marginBottom:1,children:[a(o,{color:"red",children:"error"}),c(o,{color:"red",children:[" ",e.text]})]});let t=e.elapsedMs!=null?` \xB7 ${(e.elapsedMs/1e3).toFixed(1)}s${e.outTokens!=null?`, ${e.outTokens} tok`:""}`:e.streaming?" \xB7 \u2026":"",n=F(e.text,58,{balance:e.streaming});return c(i,{flexDirection:"column",marginBottom:1,children:[c(o,{color:"green",children:["@",r??"agent",a(o,{dimColor:!0,children:t})]}),e.thinking?e.thinking.split(`
6
6
  `).filter(s=>s.trim()).slice(-2).map((s,u)=>c(o,{dimColor:!0,italic:!0,children:[" ",s]},`th${u}`)):null,(e.tools??[]).map((s,u)=>c(o,{color:s.error?"red":"green",children:[" \u25CF ",c(o,{bold:!s.error,dimColor:s.error,children:[s.name,s.arg?c(o,{dimColor:!0,children:["(",s.arg,")"]}):null,s.error?" failed":""]})]},`tool${u}`)),n.split(`
7
7
  `).slice(0,14).map((s,u)=>c(o,{children:[" ",s]},u))]})}function ae(e){let r=e.data??{},t=typeof r.at=="string"||typeof r.at=="number"?new Date(r.at).getTime():Date.now(),n="";switch(e.event){case"run":n=`${r.phase??""} ${r.workflowId??""} ${(r.runId??"").slice(0,8)} ${r.nodeId??""}`.trim();break;case"task":n=`${r.phase??""} ${r.workflowId??""} ${Array.isArray(r.assignedTo)?r.assignedTo.join(","):""} ${r.title?`"${r.title}"`:""}`.trim();break;case"signal":n=`${r.name??""} (${r.scope??""}) ${r.workflowId??""}`.trim();break;case"mesh":n=`${r.peer??""} ${r.healthy?"healthy":"lost"} ${r.delta??""}`.trim();break;case"channel":{n=`${r.direction==="in"?"\u2190":"\u2192"} ${r.channel??""}:${r.chatId??""} ${r.textPreview??""}`.trim();break}case"status":n=`node=${r.node??""} agents=${r.agents??0} active=${(r.active??[]).length}`;break;default:n=typeof r=="string"?r:JSON.stringify(r).slice(0,80)}return{at:Number.isFinite(t)?t:Date.now(),kind:e.event,line:n}}function ce(e){switch(e){case"run":return"cyan";case"task":return"magenta";case"signal":return"green";case"mesh":return"blue";case"channel":return"yellow";default:return"white"}}function T(e,r){let t=(e??"").toString();return t.length>=r?t.slice(0,r-1)+" ":t+" ".repeat(r-t.length)}export{be as App};
8
- //# sourceMappingURL=App-6R4I6QPE.js.map
8
+ //# sourceMappingURL=App-XLQDP26J.js.map
@@ -1,7 +1,7 @@
1
- import{a as Y,b as Z,c as _,d as ee,e as te,f as ne,g as re}from"./chunk-U2CKL755.js";import{b as Q,g as X}from"./chunk-ZCQCUA4J.js";import"./chunk-ERPEU2ZR.js";import"./chunk-RJ7DASOU.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-QIJLFPWE.js";import{useCallback as oe,useMemo as H,useRef as P,useState as k}from"react";import{Box as g,Text as t,useApp as he,useInput as xe,useStdout as Te}from"ink";import{randomUUID as se}from"crypto";var m={accent:"cyan",agent:"green",working:"magenta",error:"red",muted:"gray"},q="\u25C7 agentx",F="\u258C";import{jsx as c,jsxs as o}from"react/jsx-runtime";var ie="/help /agent <id> /agents /clear /who /exit",be=[{cmd:"/agent",desc:"switch the target agent (/agent <id>)"},{cmd:"/agents",desc:"list registered agents"},{cmd:"/clear",desc:"start a fresh session"},{cmd:"/who",desc:"show agent + chat id"},{cmd:"/help",desc:"list commands"},{cmd:"/exit",desc:"quit the chat"}];function Pe({conn:n,agentId:p,channel:f,chatId:a,agents:h}){let{exit:w}=he(),{stdout:O}=Te(),V=Math.max(40,Math.min((O?.columns||80)-4,100)),[z,U]=k([]),[$,S]=k(null),[T,le]=k(p),[A,ae]=k(h),[E,ue]=k(a),[y,x]=k(""),[J,de]=k(""),W=P([]),u=P(-1),M=P(null),R=P(null),v=$?.live??!1,j=H(()=>Z(y,A.map(s=>s.id),process.cwd()),[y,A]),N=H(()=>{let s=/^\/(\w*)$/.exec(y);if(!s)return null;let e=be.filter(r=>r.cmd.slice(1).startsWith(s[1].toLowerCase()));return e.length?e:null},[y]),b=s=>de(s),K=oe(s=>{let e=se().slice(0,8),r=Date.now(),i=new AbortController;R.current=i;let d={id:e,you:s,agentId:T,segs:[],live:!0,startedAt:r};S({...d});let L=()=>S({...d,segs:d.segs.map(C=>({...C}))});(async()=>{try{let C=await X(n,T,s,{channel:f,chatId:E,signal:i.signal,onText:l=>{let I=d.segs[d.segs.length-1];I&&I.type==="text"?I.content=(I.content??"")+l:d.segs.push({type:"text",content:l}),L()},onThinking:l=>{d.thinking=(d.thinking??"")+l,L()},onTool:l=>{l.status==="start"&&l.name?(d.segs.push({type:"tool",name:l.name,arg:l.arg}),L()):l.status==="result"&&l.error&&(d.segs.push({type:"tool",name:l.name??"tool",error:!0}),L())}});U(l=>[...l,{...d,live:!1,elapsedMs:Date.now()-r,outTokens:C.usage?.outputTokens,error:C.error}]),S(null)}catch(C){let l=i.signal.aborted||C?.name==="AbortError";U(I=>[...I,{...d,live:!1,elapsedMs:Date.now()-r,interrupted:l,error:l?void 0:C?.message||String(C)}]),S(null)}finally{R.current===i&&(R.current=null)}})()},[n,T,f,E]),me=oe(s=>{let e=s.trim();if(e){if(W.current.push(e),u.current=-1,e==="/exit"||e==="/quit"){w();return}if(e==="/help"){b(ie);return}if(e==="/who"){b(`@${T} \xB7 chatId=${E} \xB7 channel=${f}`);return}if(e==="/clear"){let r=`chat-cli:${se().slice(0,12)}`;ue(r),U([]),b(`fresh chatId=${r} (warm process dropped)`);return}if(e==="/agents"){Q(n).then(r=>{ae(r),b(r.map(i=>i.id===T?`[${i.id}]`:i.id).join(" "))}).catch(r=>b(`failed to list agents: ${r?.message||r}`));return}if(e.startsWith("/agent ")){let r=e.slice(7).replace(/^@/,"").trim();if(!r){b("usage: /agent <id>");return}if(!A.find(i=>i.id===r)){b(`unknown agent: @${r}`);return}le(r),b(`now talking to @${r}`);return}if(e.startsWith("/")){b(`unknown command \xB7 ${ie}`);return}K(e)}},[n,T,A,f,E,w,K]);xe((s,e)=>{if(e.ctrl&&s==="c"){w();return}if(e.escape){if(v&&R.current){R.current.abort();return}w();return}if(e.tab){if(N){x(N[0].cmd+" ");return}let i=_(y,M,A.map(d=>d.id),process.cwd());i!==null&&(x(i),u.current=-1);return}if(e.upArrow){let i=W.current;if(!i.length)return;u.current=u.current<0?i.length-1:Math.max(0,u.current-1),x(i[u.current]??"");return}if(e.downArrow){let i=W.current;if(u.current<0)return;if(u.current=u.current+1,u.current>=i.length){u.current=-1,x("");return}x(i[u.current]??"");return}if(e.backspace||e.delete){M.current=null,x(i=>i.slice(0,-1));return}if(e.ctrl||e.meta)return;let r=ee(s??"",e.return,y);switch(r.kind){case"paste":M.current=null,x(i=>i+r.text),u.current=-1;return;case"type":M.current=null,x(i=>i+r.text),u.current=-1;return;case"continue":x(r.buffer);return;case"submit":if(v)return;M.current=null,x(""),me(r.text);return;case"none":return}});let G=v?m.working:m.accent,ge=y.length?y.split(`
1
+ import{a as Y,b as Z,c as _,d as ee,e as te,f as ne,g as re}from"./chunk-U2CKL755.js";import{b as Q,g as X}from"./chunk-GJ5EJVMZ.js";import"./chunk-JREA25GJ.js";import"./chunk-RJ7DASOU.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-QIJLFPWE.js";import{useCallback as oe,useMemo as H,useRef as P,useState as k}from"react";import{Box as g,Text as t,useApp as he,useInput as xe,useStdout as Te}from"ink";import{randomUUID as se}from"crypto";var m={accent:"cyan",agent:"green",working:"magenta",error:"red",muted:"gray"},q="\u25C7 agentx",F="\u258C";import{jsx as c,jsxs as o}from"react/jsx-runtime";var ie="/help /agent <id> /agents /clear /who /exit",be=[{cmd:"/agent",desc:"switch the target agent (/agent <id>)"},{cmd:"/agents",desc:"list registered agents"},{cmd:"/clear",desc:"start a fresh session"},{cmd:"/who",desc:"show agent + chat id"},{cmd:"/help",desc:"list commands"},{cmd:"/exit",desc:"quit the chat"}];function Pe({conn:n,agentId:p,channel:f,chatId:a,agents:h}){let{exit:w}=he(),{stdout:O}=Te(),V=Math.max(40,Math.min((O?.columns||80)-4,100)),[z,U]=k([]),[$,S]=k(null),[T,le]=k(p),[A,ae]=k(h),[E,ue]=k(a),[y,x]=k(""),[J,de]=k(""),W=P([]),u=P(-1),M=P(null),R=P(null),v=$?.live??!1,j=H(()=>Z(y,A.map(s=>s.id),process.cwd()),[y,A]),N=H(()=>{let s=/^\/(\w*)$/.exec(y);if(!s)return null;let e=be.filter(r=>r.cmd.slice(1).startsWith(s[1].toLowerCase()));return e.length?e:null},[y]),b=s=>de(s),K=oe(s=>{let e=se().slice(0,8),r=Date.now(),i=new AbortController;R.current=i;let d={id:e,you:s,agentId:T,segs:[],live:!0,startedAt:r};S({...d});let L=()=>S({...d,segs:d.segs.map(C=>({...C}))});(async()=>{try{let C=await X(n,T,s,{channel:f,chatId:E,signal:i.signal,onText:l=>{let I=d.segs[d.segs.length-1];I&&I.type==="text"?I.content=(I.content??"")+l:d.segs.push({type:"text",content:l}),L()},onThinking:l=>{d.thinking=(d.thinking??"")+l,L()},onTool:l=>{l.status==="start"&&l.name?(d.segs.push({type:"tool",name:l.name,arg:l.arg}),L()):l.status==="result"&&l.error&&(d.segs.push({type:"tool",name:l.name??"tool",error:!0}),L())}});U(l=>[...l,{...d,live:!1,elapsedMs:Date.now()-r,outTokens:C.usage?.outputTokens,error:C.error}]),S(null)}catch(C){let l=i.signal.aborted||C?.name==="AbortError";U(I=>[...I,{...d,live:!1,elapsedMs:Date.now()-r,interrupted:l,error:l?void 0:C?.message||String(C)}]),S(null)}finally{R.current===i&&(R.current=null)}})()},[n,T,f,E]),me=oe(s=>{let e=s.trim();if(e){if(W.current.push(e),u.current=-1,e==="/exit"||e==="/quit"){w();return}if(e==="/help"){b(ie);return}if(e==="/who"){b(`@${T} \xB7 chatId=${E} \xB7 channel=${f}`);return}if(e==="/clear"){let r=`chat-cli:${se().slice(0,12)}`;ue(r),U([]),b(`fresh chatId=${r} (warm process dropped)`);return}if(e==="/agents"){Q(n).then(r=>{ae(r),b(r.map(i=>i.id===T?`[${i.id}]`:i.id).join(" "))}).catch(r=>b(`failed to list agents: ${r?.message||r}`));return}if(e.startsWith("/agent ")){let r=e.slice(7).replace(/^@/,"").trim();if(!r){b("usage: /agent <id>");return}if(!A.find(i=>i.id===r)){b(`unknown agent: @${r}`);return}le(r),b(`now talking to @${r}`);return}if(e.startsWith("/")){b(`unknown command \xB7 ${ie}`);return}K(e)}},[n,T,A,f,E,w,K]);xe((s,e)=>{if(e.ctrl&&s==="c"){w();return}if(e.escape){if(v&&R.current){R.current.abort();return}w();return}if(e.tab){if(N){x(N[0].cmd+" ");return}let i=_(y,M,A.map(d=>d.id),process.cwd());i!==null&&(x(i),u.current=-1);return}if(e.upArrow){let i=W.current;if(!i.length)return;u.current=u.current<0?i.length-1:Math.max(0,u.current-1),x(i[u.current]??"");return}if(e.downArrow){let i=W.current;if(u.current<0)return;if(u.current=u.current+1,u.current>=i.length){u.current=-1,x("");return}x(i[u.current]??"");return}if(e.backspace||e.delete){M.current=null,x(i=>i.slice(0,-1));return}if(e.ctrl||e.meta)return;let r=ee(s??"",e.return,y);switch(r.kind){case"paste":M.current=null,x(i=>i+r.text),u.current=-1;return;case"type":M.current=null,x(i=>i+r.text),u.current=-1;return;case"continue":x(r.buffer);return;case"submit":if(v)return;M.current=null,x(""),me(r.text);return;case"none":return}});let G=v?m.working:m.accent,ge=y.length?y.split(`
2
2
  `):[""],B=A.find(s=>s.id===T),D=ne(B?.tier??"",B?.model),pe=O?.rows||24,fe=z.slice(-40);return o(g,{flexDirection:"column",height:pe,children:[o(g,{flexDirection:"column",flexGrow:1,justifyContent:"flex-end",overflow:"hidden",children:[z.length===0&&!$?o(g,{flexDirection:"column",children:[o(t,{children:[c(t,{color:m.accent,bold:!0,children:q}),c(t,{dimColor:!0,children:" \u2014 chat with "}),o(t,{color:m.accent,children:["@",T]}),c(t,{dimColor:!0,children:" via "}),o(t,{color:D.color,bold:!0,children:[D.glyph," ",D.label]}),B?.model?o(t,{dimColor:!0,children:[" (",B.model,")"]}):null]}),c(t,{dimColor:!0,children:"streaming \xB7 markdown \xB7 tools \xB7 type a message, or / for commands"})]}):null,fe.map(s=>c(ce,{turn:s,width:V},s.id)),$?c(ce,{turn:$,width:V}):null]}),N?c(g,{flexDirection:"column",marginTop:1,children:N.map((s,e)=>o(g,{children:[c(t,{color:e===0?m.accent:m.muted,bold:e===0,children:s.cmd.padEnd(10)}),c(t,{dimColor:!0,children:s.desc})]},s.cmd))}):j?o(g,{marginTop:1,children:[c(t,{color:m.accent,children:"\u21B9 "}),j.items.map((s,e)=>o(t,{color:e===0?m.accent:m.muted,children:[s,e<j.items.length-1?" ":""]},e))]}):J?c(g,{marginTop:1,children:c(t,{dimColor:!0,children:J})}):null,c(g,{borderStyle:"single",borderColor:G,borderLeft:!1,borderRight:!1,borderDimColor:!v,width:"100%",children:c(g,{flexDirection:"column",width:"100%",children:ge.map((s,e,r)=>o(g,{children:[c(t,{color:G,bold:!0,children:e===0?"\u203A ":" "}),c(t,{children:s}),e===r.length-1&&!v?c(t,{color:G,children:"\u258F"}):null]},e))})}),o(g,{justifyContent:"space-between",children:[o(t,{children:[c(t,{color:m.accent,bold:!0,children:q}),o(t,{dimColor:!0,children:[" \xB7 @",T," \xB7 "]}),o(t,{color:D.color,bold:!0,children:[D.glyph," ",D.label]}),B?.model?o(t,{dimColor:!0,children:[" ",re(B.model)]}):null]}),o(t,{dimColor:!0,children:["\u21B5 send / cmds @ mention esc ",v?"stop":"exit"]})]})]})}function ce({turn:n,width:p}){let f=H(()=>ye(n,p),[n,p]),a=n.segs.some(h=>h.type==="text"&&h.content);return o(g,{flexDirection:"column",marginBottom:1,children:[o(t,{color:m.accent,bold:!0,children:[F," you"]}),n.you.split(`
3
3
  `).map((h,w)=>o(t,{color:"white",children:[" ",h]},`u${w}`)),o(t,{color:m.agent,bold:!0,children:[F," ",n.agentId??"agent"]}),n.thinking?c(g,{flexDirection:"column",children:we(n.thinking,n.live?3:2).map((h,w)=>o(t,{dimColor:!0,italic:!0,children:[" ",h]},`th${w}`))}):null,f,n.live?c(te,{startedAt:n.startedAt,phase:a?"responding":"thinking",hint:"esc to interrupt"}):n.interrupted?o(t,{dimColor:!0,children:[" \u2298 interrupted \xB7 ",(n.elapsedMs/1e3).toFixed(1),"s"]}):n.error?o(t,{color:"red",children:[" \u2717 ",n.error]}):n.elapsedMs!=null?o(t,{dimColor:!0,children:[" \xB7 ",(n.elapsedMs/1e3).toFixed(1),"s",n.outTokens!=null?`, ${n.outTokens} tok`:""]}):null]})}function we(n,p){return n.split(`
4
4
  `).filter(a=>a.trim()).slice(-p)}function ye(n,p){let f=[];return n.segs.forEach((a,h)=>{a.type==="tool"?f.push(o(t,{color:a.error?"red":"green",children:[" ","\u25CF ",o(t,{bold:!a.error,dimColor:a.error,children:[a.name,a.arg?o(t,{dimColor:!0,children:["(",a.arg,")"]}):null,a.error?" failed":""]})]},h)):a.content&&f.push(c(t,{children:Ce(Y(a.content,p,{balance:n.live}))},h))}),f}function Ce(n){return n.split(`
5
5
  `).map(p=>p.length?" "+p:p).join(`
6
6
  `)}export{Pe as ChatApp};
7
- //# sourceMappingURL=ChatApp-R3O4BJ24.js.map
7
+ //# sourceMappingURL=ChatApp-DRDUXZ66.js.map
@@ -1,2 +1,2 @@
1
- import{A as a,B as b,C as c}from"./chunk-LXHTVVJV.js";import"./chunk-SFQUP3BP.js";import"./chunk-QOYAX2FT.js";import"./chunk-5MUJZODV.js";import"./chunk-7I7IEX4S.js";import"./chunk-JHCI6XCJ.js";import"./chunk-DSYKYZMT.js";import"./chunk-QIJLFPWE.js";export{a as createAgentContext,b as generate,c as generateStream};
2
- //# sourceMappingURL=agent-P6GPE7HD.js.map
1
+ import{A as a,B as b,C as c}from"./chunk-OFVMUBIP.js";import"./chunk-SFQUP3BP.js";import"./chunk-QOYAX2FT.js";import"./chunk-5MUJZODV.js";import"./chunk-7I7IEX4S.js";import"./chunk-JHCI6XCJ.js";import"./chunk-DSYKYZMT.js";import"./chunk-QIJLFPWE.js";export{a as createAgentContext,b as generate,c as generateStream};
2
+ //# sourceMappingURL=agent-QHM3J2XS.js.map