agentix-cli 0.94.1 → 0.96.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 (114) hide show
  1. package/apps/mac-voice/Sources/AgentXVoice/Character.swift +4 -0
  2. package/apps/mac-voice/Sources/AgentXVoice/Config.swift +26 -9
  3. package/apps/mac-voice/Sources/AgentXVoice/Panel.swift +56 -7
  4. package/apps/mac-voice/Sources/AgentXVoice/PanelAnswer.swift +2 -0
  5. package/apps/mac-voice/Sources/AgentXVoice/PillMenu.swift +9 -0
  6. package/apps/mac-voice/Sources/AgentXVoice/PillPlacement.swift +15 -4
  7. package/apps/mac-voice/Sources/AgentXVoice/PlayMath.swift +250 -0
  8. package/apps/mac-voice/Sources/AgentXVoice/PlayRead.swift +98 -0
  9. package/apps/mac-voice/Sources/AgentXVoice/PlayStage.swift +164 -0
  10. package/apps/mac-voice/Sources/AgentXVoice/SettingsLook.swift +6 -0
  11. package/apps/mac-voice/Sources/AgentXVoice/SettingsWindow.swift +4 -1
  12. package/apps/mac-voice/Sources/AgentXVoice/StatusMenu.swift +23 -0
  13. package/apps/mac-voice/Sources/AgentXVoice/Surface.swift +19 -0
  14. package/apps/mac-voice/Sources/AgentXVoice/VoiceSettings.swift +8 -2
  15. package/apps/mac-voice/Sources/AgentXVoice/main.swift +73 -0
  16. package/apps/mac-voice/build.sh +1 -1
  17. package/dist/{App-Y62EOIB4.js → App-UHSIO3UE.js} +2 -2
  18. package/dist/{ChatApp-VIGYSGG4.js → ChatApp-LLTFBLJY.js} +2 -2
  19. package/dist/{agent-AGBADNWK.js → agent-6RJ633MQ.js} +2 -2
  20. package/dist/{board-dashboard-MHMYOBKA.js → board-dashboard-A3ZEI4F6.js} +4 -4
  21. package/dist/{chunk-IWEN3YNQ.js → chunk-44UGVUN7.js} +2 -2
  22. package/dist/{chunk-73NSSC6K.js → chunk-4XHKJZLJ.js} +2 -2
  23. package/dist/{chunk-EWE2TJMN.js → chunk-6DCY2JCB.js} +5 -5
  24. package/dist/{chunk-BP52VVCW.js → chunk-6NECC6YS.js} +2 -2
  25. package/dist/{chunk-IBXHC3ZV.js → chunk-76IOF3DK.js} +171 -171
  26. package/dist/chunk-76IOF3DK.js.map +1 -0
  27. package/dist/{chunk-LKBUTSYP.js → chunk-ALWMYA2B.js} +2 -2
  28. package/dist/{chunk-HJUBCA7O.js → chunk-DU6536CC.js} +2 -2
  29. package/dist/{chunk-2MMC5LHF.js → chunk-EBVB727L.js} +2 -2
  30. package/dist/{chunk-Q4R4OS5S.js → chunk-GHXSBJZS.js} +2 -2
  31. package/dist/{chunk-KA6K25T4.js → chunk-IPDEWVVT.js} +2 -2
  32. package/dist/{chunk-C6PWAEVX.js → chunk-J2MHITWR.js} +2 -2
  33. package/dist/{chunk-PS3UB5PH.js → chunk-KEKO4S45.js} +2 -2
  34. package/dist/{chunk-MIRBKQHA.js → chunk-KIGFWUKP.js} +2 -2
  35. package/dist/{chunk-5EOFTPQB.js → chunk-MKF6HSBA.js} +2 -2
  36. package/dist/{chunk-74S7PKIX.js → chunk-QZIEYDIY.js} +2 -2
  37. package/dist/{chunk-DS7CDASP.js → chunk-TE44E733.js} +2 -2
  38. package/dist/{chunk-5PFTUGP4.js → chunk-VO2GNAKB.js} +2 -2
  39. package/dist/{chunk-VUSDWZ6L.js → chunk-XEKZKH3W.js} +2 -2
  40. package/dist/{chunk-VUSDWZ6L.js.map → chunk-XEKZKH3W.js.map} +1 -1
  41. package/dist/{chunk-M56MKNAG.js → chunk-ZVW645NU.js} +2 -2
  42. package/dist/{chunk-T2IDDOSX.js → chunk-ZYJDAT3E.js} +2 -2
  43. package/dist/{chunk-OQHC7TJL.js → chunk-ZZSNM2RI.js} +2 -2
  44. package/dist/cli.js +1 -1
  45. package/dist/{client-RMUEJMV5.js → client-ARS6ZFT2.js} +2 -2
  46. package/dist/{config-M2Z4HTZI.js → config-XO5Z3BO5.js} +2 -2
  47. package/dist/config-mutator-MJX4EIYV.js +2 -0
  48. package/dist/{doctor-W6OQ7JI2.js → doctor-VUK3JE6Z.js} +2 -2
  49. package/dist/index.d.ts +14 -0
  50. package/dist/index.js +1 -1
  51. package/dist/{program-6G2IS3WF.js → program-QO72D2EL.js} +166 -166
  52. package/dist/program-QO72D2EL.js.map +1 -0
  53. package/dist/{promote-YH3MNZFF.js → promote-UGQXA4KV.js} +2 -2
  54. package/dist/{query-BJC5VVS5.js → query-DL7RHPMA.js} +2 -2
  55. package/dist/{registry-EJTSQEBJ.js → registry-YIPKBRBH.js} +2 -2
  56. package/dist/{request-planner-MKVEPQGA.js → request-planner-L2FAVNKP.js} +2 -2
  57. package/dist/{review-candidates-OAG3DMQR.js → review-candidates-RPUP4XBU.js} +2 -2
  58. package/dist/{routing-U4VI4PAH.js → routing-G66SVTRO.js} +2 -2
  59. package/dist/schedule-tool-FOWPIWKP.js +2 -0
  60. package/dist/scheduler-GFVUPAD6.js +2 -0
  61. package/dist/{seat-CVOTWLEN.js → seat-ZPH7DA5L.js} +2 -2
  62. package/dist/{select-FNERAHZI.js → select-2WTV2BI2.js} +2 -2
  63. package/dist/{set-enabled-3C7AVZ65.js → set-enabled-KI2FINQD.js} +2 -2
  64. package/dist/{tool-KR4MDO2R.js → tool-2P4LRWN4.js} +2 -2
  65. package/dist/{tool-H7CDGZJ6.js → tool-ZFQ46KU3.js} +2 -2
  66. package/dist/wiki-XATGT3DI.js +2 -0
  67. package/package.json +1 -1
  68. package/dist/chunk-IBXHC3ZV.js.map +0 -1
  69. package/dist/config-mutator-L2LCW5ES.js +0 -2
  70. package/dist/program-6G2IS3WF.js.map +0 -1
  71. package/dist/schedule-tool-ZTTZBTXA.js +0 -2
  72. package/dist/scheduler-4RLL7YOW.js +0 -2
  73. package/dist/wiki-HA3U33SO.js +0 -2
  74. /package/dist/{App-Y62EOIB4.js.map → App-UHSIO3UE.js.map} +0 -0
  75. /package/dist/{ChatApp-VIGYSGG4.js.map → ChatApp-LLTFBLJY.js.map} +0 -0
  76. /package/dist/{agent-AGBADNWK.js.map → agent-6RJ633MQ.js.map} +0 -0
  77. /package/dist/{board-dashboard-MHMYOBKA.js.map → board-dashboard-A3ZEI4F6.js.map} +0 -0
  78. /package/dist/{chunk-IWEN3YNQ.js.map → chunk-44UGVUN7.js.map} +0 -0
  79. /package/dist/{chunk-73NSSC6K.js.map → chunk-4XHKJZLJ.js.map} +0 -0
  80. /package/dist/{chunk-EWE2TJMN.js.map → chunk-6DCY2JCB.js.map} +0 -0
  81. /package/dist/{chunk-BP52VVCW.js.map → chunk-6NECC6YS.js.map} +0 -0
  82. /package/dist/{chunk-LKBUTSYP.js.map → chunk-ALWMYA2B.js.map} +0 -0
  83. /package/dist/{chunk-HJUBCA7O.js.map → chunk-DU6536CC.js.map} +0 -0
  84. /package/dist/{chunk-2MMC5LHF.js.map → chunk-EBVB727L.js.map} +0 -0
  85. /package/dist/{chunk-Q4R4OS5S.js.map → chunk-GHXSBJZS.js.map} +0 -0
  86. /package/dist/{chunk-KA6K25T4.js.map → chunk-IPDEWVVT.js.map} +0 -0
  87. /package/dist/{chunk-C6PWAEVX.js.map → chunk-J2MHITWR.js.map} +0 -0
  88. /package/dist/{chunk-PS3UB5PH.js.map → chunk-KEKO4S45.js.map} +0 -0
  89. /package/dist/{chunk-MIRBKQHA.js.map → chunk-KIGFWUKP.js.map} +0 -0
  90. /package/dist/{chunk-5EOFTPQB.js.map → chunk-MKF6HSBA.js.map} +0 -0
  91. /package/dist/{chunk-74S7PKIX.js.map → chunk-QZIEYDIY.js.map} +0 -0
  92. /package/dist/{chunk-DS7CDASP.js.map → chunk-TE44E733.js.map} +0 -0
  93. /package/dist/{chunk-5PFTUGP4.js.map → chunk-VO2GNAKB.js.map} +0 -0
  94. /package/dist/{chunk-M56MKNAG.js.map → chunk-ZVW645NU.js.map} +0 -0
  95. /package/dist/{chunk-T2IDDOSX.js.map → chunk-ZYJDAT3E.js.map} +0 -0
  96. /package/dist/{chunk-OQHC7TJL.js.map → chunk-ZZSNM2RI.js.map} +0 -0
  97. /package/dist/{client-RMUEJMV5.js.map → client-ARS6ZFT2.js.map} +0 -0
  98. /package/dist/{config-M2Z4HTZI.js.map → config-XO5Z3BO5.js.map} +0 -0
  99. /package/dist/{config-mutator-L2LCW5ES.js.map → config-mutator-MJX4EIYV.js.map} +0 -0
  100. /package/dist/{doctor-W6OQ7JI2.js.map → doctor-VUK3JE6Z.js.map} +0 -0
  101. /package/dist/{promote-YH3MNZFF.js.map → promote-UGQXA4KV.js.map} +0 -0
  102. /package/dist/{query-BJC5VVS5.js.map → query-DL7RHPMA.js.map} +0 -0
  103. /package/dist/{registry-EJTSQEBJ.js.map → registry-YIPKBRBH.js.map} +0 -0
  104. /package/dist/{request-planner-MKVEPQGA.js.map → request-planner-L2FAVNKP.js.map} +0 -0
  105. /package/dist/{review-candidates-OAG3DMQR.js.map → review-candidates-RPUP4XBU.js.map} +0 -0
  106. /package/dist/{routing-U4VI4PAH.js.map → routing-G66SVTRO.js.map} +0 -0
  107. /package/dist/{schedule-tool-ZTTZBTXA.js.map → schedule-tool-FOWPIWKP.js.map} +0 -0
  108. /package/dist/{scheduler-4RLL7YOW.js.map → scheduler-GFVUPAD6.js.map} +0 -0
  109. /package/dist/{seat-CVOTWLEN.js.map → seat-ZPH7DA5L.js.map} +0 -0
  110. /package/dist/{select-FNERAHZI.js.map → select-2WTV2BI2.js.map} +0 -0
  111. /package/dist/{set-enabled-3C7AVZ65.js.map → set-enabled-KI2FINQD.js.map} +0 -0
  112. /package/dist/{tool-KR4MDO2R.js.map → tool-2P4LRWN4.js.map} +0 -0
  113. /package/dist/{tool-H7CDGZJ6.js.map → tool-ZFQ46KU3.js.map} +0 -0
  114. /package/dist/{wiki-HA3U33SO.js.map → wiki-XATGT3DI.js.map} +0 -0
@@ -0,0 +1,164 @@
1
+ import AppKit
2
+
3
+ /// What play mode (#505) draws over the picture: the page's colour where
4
+ /// words are gone, the cloth, and the character. The context is flipped,
5
+ /// in the picture's points.
6
+ enum PlayDraw {
7
+ static func draw(_ frame: Play.Frame, in ctx: CGContext, stops: [NSColor]) {
8
+ for gone in frame.gone {
9
+ let c = gone.paper
10
+ ctx.setFillColor(CGColor(srgbRed: CGFloat(c >> 16 & 0xFF) / 255, green: CGFloat(c >> 8 & 0xFF) / 255,
11
+ blue: CGFloat(c & 0xFF) / 255, alpha: 1))
12
+ ctx.fill(cg(gone.rect))
13
+ }
14
+ if let cloth = frame.cloth {
15
+ let path = CGPath(roundedRect: cg(cloth), cornerWidth: 4, cornerHeight: 4, transform: nil)
16
+ ctx.addPath(path)
17
+ ctx.setFillColor(stops[4].cgColor)
18
+ ctx.fillPath()
19
+ ctx.addPath(path)
20
+ ctx.setStrokeColor(stops[1].cgColor)
21
+ ctx.setLineWidth(1)
22
+ ctx.strokePath()
23
+ }
24
+ let shown = CharacterSim.Frame(pose: frame.pose, x: frame.at.x, face: frame.face, t: frame.t)
25
+ CharacterDraw.draw(shown, in: ctx, edge: CGPoint(x: frame.at.x, y: frame.at.y), origin: 0,
26
+ unit: CGFloat(PlayMath.unit), stops: stops)
27
+ }
28
+
29
+ private static func cg(_ r: PlayMath.Rect) -> CGRect { CGRect(x: r.x, y: r.y, width: r.w, height: r.h) }
30
+ }
31
+
32
+ /// The stage: a frozen picture of the screen laid over everything, with
33
+ /// the character playing on it. The real page is never touched: nothing
34
+ /// is clicked, typed or changed, and what looks eaten or wiped is only
35
+ /// painted over on the picture.
36
+ ///
37
+ /// The page behind goes stale while the picture is up, so play ends on
38
+ /// the first real input: any key, a click, a scroll, another app or Space
39
+ /// coming forward. Unlike the character on its edge, this window does
40
+ /// take keys and clicks, for that one purpose.
41
+ @MainActor
42
+ final class PlayHost {
43
+ private var window: NSPanel?
44
+ private var timer: Timer?
45
+ private var observers: [(NotificationCenter, NSObjectProtocol)] = []
46
+ private var script: Play?
47
+ private var began = 0.0
48
+ /// Raised by each `start`, so a text read that outlives its play can
49
+ /// tell that the picture now up is not the one it read.
50
+ private(set) var number = 0
51
+ /// Told each time a play is over.
52
+ var onEnd: (() -> Void)?
53
+
54
+ var running: Bool { window != nil }
55
+
56
+ /// Lay `picture` over `screen`, the character waiting at `foot` (the
57
+ /// picture's points) until `play(_:)` gives it a script: reading the
58
+ /// text takes a moment, and the page must not move meanwhile.
59
+ func start(picture: CGImage, on screen: NSScreen, stops: [NSColor], at foot: PlayMath.Point) {
60
+ guard !running else { return }
61
+ script = nil
62
+ number += 1
63
+ let panel = PlayWindow(contentRect: screen.frame, styleMask: [.borderless, .nonactivatingPanel],
64
+ backing: .buffered, defer: false)
65
+ panel.level = .screenSaver
66
+ panel.collectionBehavior = [.fullScreenAuxiliary]
67
+ panel.hasShadow = false
68
+ panel.hidesOnDeactivate = false
69
+
70
+ let bounds = NSRect(origin: .zero, size: screen.frame.size)
71
+ let backdrop = NSView(frame: bounds)
72
+ backdrop.wantsLayer = true
73
+ backdrop.layer?.contents = picture
74
+ let view = PlayView(frame: bounds)
75
+ view.stops = stops
76
+ view.shown = Play.Frame(at: foot, pose: CharacterMath.pose(.working))
77
+ view.onInput = { [weak self] in self?.end("a key or a click") }
78
+ backdrop.addSubview(view)
79
+ panel.contentView = backdrop
80
+ panel.setFrame(screen.frame, display: true)
81
+ window = panel
82
+ panel.makeKeyAndOrderFront(nil)
83
+ panel.makeFirstResponder(view)
84
+
85
+ func watch(_ center: NotificationCenter, _ name: Notification.Name, _ object: Any?, _ why: String) {
86
+ observers.append((center, center.addObserver(forName: name, object: object, queue: .main) { [weak self] _ in
87
+ MainActor.assumeIsolated { self?.end(why) }
88
+ }))
89
+ }
90
+ watch(.default, NSWindow.didResignKeyNotification, panel, "another window came forward")
91
+ watch(NSWorkspace.shared.notificationCenter, NSWorkspace.activeSpaceDidChangeNotification, nil, "the Space changed")
92
+ watch(.default, NSApplication.didChangeScreenParametersNotification, nil, "the screens changed")
93
+
94
+ let shownAt = ProcessInfo.processInfo.systemUptime
95
+ let frames = Timer(timeInterval: 1.0 / 30, repeats: true) { [weak self, weak view] _ in
96
+ MainActor.assumeIsolated {
97
+ guard let self, let view else { return }
98
+ let now = ProcessInfo.processInfo.systemUptime
99
+ if let script = self.script {
100
+ view.shown = script.frame(at: now - self.began)
101
+ } else {
102
+ // Its thinking dots hop while it waits.
103
+ view.shown.t = now - shownAt
104
+ }
105
+ view.needsDisplay = true
106
+ if view.shown.done { self.end("the script ended") }
107
+ }
108
+ }
109
+ RunLoop.main.add(frames, forMode: .common)
110
+ timer = frames
111
+ }
112
+
113
+ /// The script to play on the picture that is up. Nothing happens if
114
+ /// the play has ended meanwhile.
115
+ func play(_ script: Play) {
116
+ guard running, self.script == nil else { return }
117
+ self.script = script
118
+ began = ProcessInfo.processInfo.systemUptime
119
+ Log.info("play: started, \(script.lines.count) lines read, \(String(format: "%.1f", script.duration)) s")
120
+ }
121
+
122
+ /// Take the picture away and drop it. Safe to call when no play runs.
123
+ func end(_ why: String) {
124
+ guard let panel = window else { return }
125
+ window = nil
126
+ timer?.invalidate()
127
+ timer = nil
128
+ for (center, observer) in observers { center.removeObserver(observer) }
129
+ observers = []
130
+ panel.orderOut(nil)
131
+ panel.contentView?.layer?.contents = nil
132
+ panel.contentView = nil
133
+ Log.info("play: ended, \(why)")
134
+ onEnd?()
135
+ }
136
+ }
137
+
138
+ /// Borderless, and still able to take the keys that end the play.
139
+ private final class PlayWindow: NSPanel {
140
+ override var canBecomeKey: Bool { true }
141
+ }
142
+
143
+ /// The drawing over the picture. Every key, click and scroll ends the play.
144
+ private final class PlayView: NSView {
145
+ var shown = Play.Frame()
146
+ var stops = CharacterDraw.stops(tint: Brand.accent, colors: nil)
147
+ var onInput: (() -> Void)?
148
+
149
+ override var isFlipped: Bool { true }
150
+ override var acceptsFirstResponder: Bool { true }
151
+ override func acceptsFirstMouse(for event: NSEvent?) -> Bool { true }
152
+
153
+ override func draw(_ dirtyRect: NSRect) {
154
+ guard let ctx = NSGraphicsContext.current?.cgContext else { return }
155
+ PlayDraw.draw(shown, in: ctx, stops: stops)
156
+ }
157
+
158
+ override func keyDown(with event: NSEvent) { onInput?() }
159
+ override func performKeyEquivalent(with event: NSEvent) -> Bool { onInput?(); return true }
160
+ override func mouseDown(with event: NSEvent) { onInput?() }
161
+ override func rightMouseDown(with event: NSEvent) { onInput?() }
162
+ override func otherMouseDown(with event: NSEvent) { onInput?() }
163
+ override func scrollWheel(with event: NSEvent) { onInput?() }
164
+ }
@@ -55,6 +55,8 @@ struct PalettePicker: View {
55
55
  /// "Shown as": the orb, or the character that stands in for it (#458).
56
56
  struct LookSection: View {
57
57
  @Binding var look: String
58
+ /// Nil hides the control: the daemon is older than the reduced pill.
59
+ var startReduced: Binding<Bool>?
58
60
 
59
61
  var body: some View {
60
62
  Section {
@@ -62,6 +64,10 @@ struct LookSection: View {
62
64
  Text("Orb").tag("orb")
63
65
  Text("Character").tag("character")
64
66
  }
67
+ if let startReduced {
68
+ Toggle("Start reduced to the orb", isOn: startReduced)
69
+ .disabled(look == "character")
70
+ }
65
71
  } header: {
66
72
  Text("Assistant")
67
73
  } footer: {
@@ -375,7 +375,10 @@ private struct GeneralTab: View {
375
375
  }
376
376
  if draft.general.look != nil {
377
377
  LookSection(look: Binding(get: { model.draft?.general.look ?? "orb" },
378
- set: { model.draft?.general.look = $0 }))
378
+ set: { model.draft?.general.look = $0 }),
379
+ startReduced: draft.general.startReduced == nil ? nil
380
+ : Binding(get: { model.draft?.general.startReduced ?? false },
381
+ set: { model.draft?.general.startReduced = $0 }))
379
382
  }
380
383
  if draft.general.card != nil {
381
384
  AnswerCardSection(card: Binding(get: { model.draft?.general.card ?? .standard },
@@ -49,12 +49,20 @@ final class StatusMenu: NSObject, NSMenuDelegate {
49
49
  var onResetPosition: (() -> Void)?
50
50
  /// Whether the pill is on screen, for "Hide pill" and "Show floating pill".
51
51
  var pillVisible: () -> Bool = { false }
52
+ /// Whether the pill is reduced to its orb, and whether it can be.
53
+ var pillReduced: () -> Bool = { false }
54
+ var canReduce: () -> Bool = { true }
55
+ /// Reduce the pill to its orb (true), or open it again.
56
+ var onReduce: ((Bool) -> Void)?
52
57
  /// The character look: whether the character is on screen. Nil with
53
58
  /// the orb look.
54
59
  var characterVisible: () -> Bool? = { nil }
55
60
  /// Bring a hidden character back, and let its bubble show again.
56
61
  var onShowCharacter: (() -> Void)?
57
62
  var onSettings: (() -> Void)?
63
+ /// Play mode (#505): whether a play can start now, and start one.
64
+ var playReady: () -> Bool = { false }
65
+ var onPlay: (() -> Void)?
58
66
 
59
67
  override init() {
60
68
  super.init()
@@ -245,9 +253,20 @@ final class StatusMenu: NSObject, NSMenuDelegate {
245
253
  let pill = action("Show floating pill", #selector(togglePill), key: "")
246
254
  pill.state = PillMenu.isChecked(showPill: Config.showPill, visible: pillVisible()) ? .on : .off
247
255
  menu.addItem(pill)
256
+ let reduce = action(PillMenu.reduceTitle(reduced: pillReduced()), #selector(toggleReduce), key: "")
257
+ reduce.isEnabled = pillReduced() || canReduce()
258
+ menu.addItem(reduce)
248
259
  let orb = action("Animated orb", #selector(toggleOrb), key: "")
249
260
  orb.state = Config.animatedOrb ? .on : .off
250
261
  menu.addItem(orb)
262
+ let mode = action("Play mode", #selector(togglePlayMode), key: "")
263
+ mode.state = Config.playMode ? .on : .off
264
+ menu.addItem(mode)
265
+ if Config.playMode {
266
+ let play = action("Play on this page", #selector(startPlay), key: "")
267
+ play.isEnabled = playReady()
268
+ menu.addItem(play)
269
+ }
251
270
  // The character hides with its bubble, and has no bubble at rest.
252
271
  switch characterVisible() {
253
272
  case true?: menu.addItem(action("Hide character", #selector(hidePill), key: ""))
@@ -313,6 +332,10 @@ final class StatusMenu: NSObject, NSMenuDelegate {
313
332
  onAnimatedOrbChanged?(Config.animatedOrb)
314
333
  }
315
334
 
335
+ @objc private func toggleReduce() { onReduce?(!pillReduced()) }
336
+ @objc private func togglePlayMode() { Config.playMode.toggle() }
337
+ @objc private func startPlay() { onPlay?() }
338
+
316
339
  @objc private func hidePill() { onHidePill?() }
317
340
  @objc private func showCharacter() { onShowCharacter?() }
318
341
  @objc private func resetPosition() { onResetPosition?() }
@@ -50,6 +50,25 @@ final class Surface: NSVisualEffectView {
50
50
  @available(*, unavailable)
51
51
  required init?(coder: NSCoder) { fatalError("not from a nib") }
52
52
 
53
+ /// The pill's own shape, or a circle `diameter` across for the pill
54
+ /// reduced to its orb. The stretchable mask cannot make a circle: its
55
+ /// corners would be wider than the view.
56
+ func shape(circle diameter: CGFloat?) {
57
+ guard let diameter else {
58
+ layer?.cornerRadius = Brand.Radius.lg
59
+ layer?.cornerCurve = .continuous
60
+ maskImage = Self.mask(radius: Brand.Radius.lg)
61
+ return
62
+ }
63
+ layer?.cornerRadius = diameter / 2
64
+ layer?.cornerCurve = .circular
65
+ maskImage = NSImage(size: NSSize(width: diameter, height: diameter), flipped: false) { rect in
66
+ NSColor.black.setFill()
67
+ NSBezierPath(ovalIn: rect).fill()
68
+ return true
69
+ }
70
+ }
71
+
53
72
  override func resizeSubviews(withOldSize oldSize: NSSize) {
54
73
  super.resizeSubviews(withOldSize: oldSize)
55
74
  layoutContent?(bounds)
@@ -29,12 +29,16 @@ struct VoiceSettings: Codable, Equatable {
29
29
  /// What shows the assistant's state: "orb" or "character". Nil
30
30
  /// from a daemon older than the character.
31
31
  var look: String?
32
+ /// The pill starts reduced to its orb. Nil from a daemon older
33
+ /// than the reduced pill.
34
+ var startReduced: Bool?
32
35
 
33
36
  init(provider: String, fallback: String, stt: String, localStt: String = "mlx-whisper",
34
- endOfTurn: String = "vad", hotkeys: Hotkeys, card: Card? = nil, look: String? = nil) {
37
+ endOfTurn: String = "vad", hotkeys: Hotkeys, card: Card? = nil, look: String? = nil,
38
+ startReduced: Bool? = nil) {
35
39
  self.provider = provider; self.fallback = fallback; self.stt = stt
36
40
  self.localStt = localStt; self.endOfTurn = endOfTurn; self.hotkeys = hotkeys
37
- self.card = card; self.look = look
41
+ self.card = card; self.look = look; self.startReduced = startReduced
38
42
  }
39
43
 
40
44
  /// A daemon from before these fields leaves them out: the defaults.
@@ -48,6 +52,7 @@ struct VoiceSettings: Codable, Equatable {
48
52
  hotkeys = try c.decode(Hotkeys.self, forKey: .hotkeys)
49
53
  card = try c.decodeIfPresent(Card.self, forKey: .card)
50
54
  look = try c.decodeIfPresent(String.self, forKey: .look)
55
+ startReduced = try c.decodeIfPresent(Bool.self, forKey: .startReduced)
51
56
  }
52
57
  }
53
58
  struct Voice: Codable, Equatable {
@@ -107,6 +112,7 @@ struct VoiceSettings: Codable, Equatable {
107
112
  if self.general.localStt != old.general.localStt { general["localStt"] = self.general.localStt }
108
113
  if self.general.endOfTurn != old.general.endOfTurn { general["endOfTurn"] = self.general.endOfTurn }
109
114
  if let look = self.general.look, look != old.general.look { general["look"] = look }
115
+ if let start = self.general.startReduced, start != old.general.startReduced { general["startReduced"] = start }
110
116
  var keys: [String: Any] = [:]
111
117
  if self.general.hotkeys.talk != old.general.hotkeys.talk { keys["talk"] = self.general.hotkeys.talk }
112
118
  if self.general.hotkeys.stop != old.general.hotkeys.stop { keys["stop"] = self.general.hotkeys.stop }
@@ -20,6 +20,10 @@ final class App: NSObject, NSApplicationDelegate {
20
20
  private let statusMenu = StatusMenu()
21
21
  /// Stands in for the pill's orb when voice.look is "character".
22
22
  private let character = CharacterHost()
23
+ /// voice.startReduced has been applied for this launch.
24
+ private var startApplied = false
25
+ /// The character playing on a frozen picture of the screen (#505).
26
+ private let play = PlayHost()
23
27
  /// The agent whose by-name answer is on screen now, while no turn runs.
24
28
  private var asideSpeaker: String?
25
29
  private let recorder = Recorder()
@@ -210,12 +214,63 @@ final class App: NSObject, NSApplicationDelegate {
210
214
  panel.setShowsOrb(!asCharacter)
211
215
  character.setShown(asCharacter)
212
216
  if !asCharacter { panel.detach() }
217
+ // voice.startReduced is how the assistant starts: read once.
218
+ if !startApplied {
219
+ startApplied = true
220
+ if saved.general.startReduced == true, !asCharacter { panel.summon(); panel.setReduced(true) }
221
+ }
213
222
  if settingsWindow.model.recording == nil { registerHotkeys() }
214
223
  // Colours may have changed.
215
224
  statusMenu.refresh()
216
225
  Log.info("settings: talk \(saved.general.hotkeys.talk), speech to text \(saved.general.stt)")
217
226
  }
218
227
 
228
+ /// A play can start: the character shows and may move, and the
229
+ /// assistant has nothing to say or hear.
230
+ private var canPlay: Bool {
231
+ character.onScreen == true && Config.animatedOrb
232
+ && !NSWorkspace.shared.accessibilityDisplayShouldReduceMotion
233
+ && !busy && !recorder.isRecording && !play.running
234
+ }
235
+
236
+ /// "Play on this page" (#505): one picture of the character's screen, the
237
+ /// lines of text read on it, and the character plays the built-in
238
+ /// script on the picture. The page itself is never touched.
239
+ private func startPlay() {
240
+ let foot = character.foot
241
+ guard canPlay, let screen = NSScreen.screens.first(where: { $0.frame.contains(foot) }) ?? NSScreen.screens.first
242
+ else { return }
243
+ guard PlayRead.allowed else {
244
+ PlayRead.ask()
245
+ Log.warn("play: no Screen Recording permission; allow AgentX Voice in System Settings, then quit and reopen it")
246
+ panel.render(.error("Allow Screen Recording"))
247
+ resetSoon()
248
+ return
249
+ }
250
+ let stops = character.stops, size = screen.frame.size
251
+ let start = PlayMath.Point(x: foot.x - screen.frame.minX, y: screen.frame.maxY - foot.y)
252
+ // Off its edge, so it is not in the picture twice.
253
+ character.setShown(false)
254
+ Task { @MainActor in
255
+ try? await Task.sleep(nanoseconds: 150_000_000)
256
+ guard let picture = PlayRead.picture(of: screen), !busy, !recorder.isRecording else {
257
+ character.setShown(settings?.general.look == "character")
258
+ return
259
+ }
260
+ play.start(picture: picture, on: screen, stops: stops, at: start)
261
+ let number = play.number
262
+ let asked = ProcessInfo.processInfo.systemUptime
263
+ let lines = await Task.detached { PlayRead.lines(in: picture, size: size) }.value
264
+ Log.info("play: \(lines.count) lines read in \(Int((ProcessInfo.processInfo.systemUptime - asked) * 1000)) ms")
265
+ // Ended while its text was read, and maybe started again since:
266
+ // these lines belong to a picture that is gone.
267
+ guard play.running, play.number == number else { return }
268
+ let steps = PlayMath.demo(lines, width: size.width, height: size.height)
269
+ if steps.isEmpty { play.end("no line of text to play on") }
270
+ else { play.play(Play(lines: lines, steps: steps, start: start)) }
271
+ }
272
+ }
273
+
219
274
  /// Who the pill names and whose colour its orb wears: the agent a
220
275
  /// shortcut is asking, a by-name answer being spoken, else the agent
221
276
  /// our turn is asking, else the target.
@@ -337,6 +392,14 @@ final class App: NSObject, NSApplicationDelegate {
337
392
  }
338
393
  panel.onLook = { [weak self] state, tint, colors in
339
394
  self?.character.show(state.activity, tint: tint, colors: colors)
395
+ // The assistant has something to show: play gives way.
396
+ if state.activity != .idle { self?.play.end("the assistant is busy") }
397
+ }
398
+ statusMenu.playReady = { [weak self] in self?.canPlay ?? false }
399
+ statusMenu.onPlay = { [weak self] in self?.startPlay() }
400
+ play.onEnd = { [weak self] in
401
+ guard let self else { return }
402
+ self.character.setShown(self.settings?.general.look == "character")
340
403
  }
341
404
  panel.onShown = { [weak self] in self?.character.redraw() }
342
405
  panel.onDismiss = { [weak self] in self?.dismissPill() }
@@ -347,6 +410,15 @@ final class App: NSObject, NSApplicationDelegate {
347
410
  panel.answer.onOpenChat = { [weak self] in self?.openChat() }
348
411
  statusMenu.pillVisible = { [weak self] in self?.panel.isVisible ?? false }
349
412
  statusMenu.onHidePill = { [weak self] in self?.dismissPill() }
413
+ statusMenu.pillReduced = { [weak self] in self?.panel.reduced ?? false }
414
+ statusMenu.canReduce = { [weak self] in PillMenu.canReduce(showsOrb: self?.panel.showsOrb ?? true) }
415
+ statusMenu.onReduce = { [weak self] on in
416
+ guard let self else { return }
417
+ Log.info("pill: \(on ? "reduced to the orb" : "opened")")
418
+ // Asking for the orb brings back a pill that was dismissed.
419
+ if on { self.panel.summon() }
420
+ self.panel.setReduced(on)
421
+ }
350
422
  statusMenu.characterVisible = { [weak self] in self?.character.onScreen }
351
423
  statusMenu.onShowCharacter = { [weak self] in self?.summonPill() }
352
424
  // Each does nothing with the other's look.
@@ -548,6 +620,7 @@ final class App: NSObject, NSApplicationDelegate {
548
620
  // A held key overrides any hands-free window that is open, so the
549
621
  // two ways of talking never fight over the microphone.
550
622
  stopPolling()
623
+ play.end("the talk key")
551
624
  guard !recorder.isRecording else { return }
552
625
  // A dismissed pill comes back with the talk key.
553
626
  summonPill()
@@ -18,7 +18,7 @@ rm -rf build && mkdir -p "$BIN" "$APP/Contents/Resources"
18
18
  swiftc -O \
19
19
  -o "$BIN/AgentXVoice" \
20
20
  Sources/AgentXVoice/*.swift \
21
- -framework AppKit -framework AVFoundation -framework Carbon -framework CoreML -framework SwiftUI \
21
+ -framework AppKit -framework AVFoundation -framework Carbon -framework CoreML -framework SwiftUI -framework Vision \
22
22
  -target arm64-apple-macosx14.0
23
23
 
24
24
  # The on-device models from a terminal: fetch them, transcribe a file, see
@@ -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-KA6K25T4.js";import"./chunk-VUSDWZ6L.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-IPDEWVVT.js";import"./chunk-XEKZKH3W.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-Y62EOIB4.js.map
8
+ //# sourceMappingURL=App-UHSIO3UE.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-KA6K25T4.js";import"./chunk-VUSDWZ6L.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-IPDEWVVT.js";import"./chunk-XEKZKH3W.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-VIGYSGG4.js.map
7
+ //# sourceMappingURL=ChatApp-LLTFBLJY.js.map
@@ -1,2 +1,2 @@
1
- import{A as a,B as b,C as c}from"./chunk-74S7PKIX.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-AGBADNWK.js.map
1
+ import{A as a,B as b,C as c}from"./chunk-QZIEYDIY.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-6RJ633MQ.js.map