agentix-cli 0.115.0 → 0.117.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 (133) hide show
  1. package/apps/mac-voice/Sources/AgentXVoice/AnswerView.swift +24 -2
  2. package/apps/mac-voice/Sources/AgentXVoice/ListenAgain.swift +26 -0
  3. package/apps/mac-voice/Sources/AgentXVoice/main.swift +54 -0
  4. package/dist/{App-6OMMZW2M.js → App-UQP7UQYV.js} +2 -2
  5. package/dist/{ChatApp-EDDROHNA.js → ChatApp-VGSP5O6N.js} +2 -2
  6. package/dist/{agent-VPM3EEUB.js → agent-MO27U4Y7.js} +2 -2
  7. package/dist/{board-dashboard-4GQ7RTH3.js → board-dashboard-CSS7XMIZ.js} +255 -224
  8. package/dist/board-dashboard-CSS7XMIZ.js.map +1 -0
  9. package/dist/chunk-2WK5A3UV.js +482 -0
  10. package/dist/chunk-2WK5A3UV.js.map +1 -0
  11. package/dist/{chunk-S4XSVAAG.js → chunk-45GOH6F7.js} +2 -2
  12. package/dist/chunk-45YETJY4.js +2 -0
  13. package/dist/chunk-45YETJY4.js.map +1 -0
  14. package/dist/{chunk-CJJULHPJ.js → chunk-4ELAUGOP.js} +4 -4
  15. package/dist/{chunk-5FY7PWXW.js → chunk-5PPMPCHG.js} +2 -2
  16. package/dist/{chunk-BU4LE2RT.js → chunk-746KHKT4.js} +2 -2
  17. package/dist/{chunk-QLB76BGE.js → chunk-BQ2HJ7TS.js} +2 -2
  18. package/dist/{chunk-PITMPRVP.js → chunk-CKQ2YDFP.js} +2 -2
  19. package/dist/{chunk-7T7IXLLA.js → chunk-CUZTLQH2.js} +2 -2
  20. package/dist/chunk-DMHQIACQ.js +3 -0
  21. package/dist/chunk-DMHQIACQ.js.map +1 -0
  22. package/dist/chunk-EMGB23H5.js +3 -0
  23. package/dist/chunk-EMGB23H5.js.map +1 -0
  24. package/dist/chunk-FJI5GRBH.js +54 -0
  25. package/dist/chunk-FJI5GRBH.js.map +1 -0
  26. package/dist/chunk-GRMCAO3Q.js +2 -0
  27. package/dist/chunk-GRMCAO3Q.js.map +1 -0
  28. package/dist/{chunk-PX2AOZ5G.js → chunk-HVZVFCJX.js} +2 -2
  29. package/dist/{chunk-BXYKFWAI.js → chunk-HYGMWCUU.js} +2 -2
  30. package/dist/{chunk-ECBVOIIK.js → chunk-IZMXAXW3.js} +182 -182
  31. package/dist/chunk-IZMXAXW3.js.map +1 -0
  32. package/dist/{chunk-YE4HKOS5.js → chunk-J2YLOGNN.js} +2 -2
  33. package/dist/{chunk-2NYP4OQU.js → chunk-LNY6N73E.js} +4 -4
  34. package/dist/{chunk-2NYP4OQU.js.map → chunk-LNY6N73E.js.map} +1 -1
  35. package/dist/{chunk-EVXL6X2R.js → chunk-MSP25HE5.js} +58 -58
  36. package/dist/{chunk-EVXL6X2R.js.map → chunk-MSP25HE5.js.map} +1 -1
  37. package/dist/{chunk-MG5LRE5B.js → chunk-OJ7KM2UO.js} +2 -2
  38. package/dist/{chunk-4STXRZZS.js → chunk-PFK3QO6S.js} +2 -2
  39. package/dist/{chunk-K3BG77KK.js → chunk-PMQ47IPT.js} +2 -2
  40. package/dist/{chunk-KTF4YF4M.js → chunk-T2VDHVYW.js} +2 -2
  41. package/dist/{chunk-J5TZ6QGD.js → chunk-VEHTVYP6.js} +2 -2
  42. package/dist/{chunk-SDOSQ6TJ.js → chunk-VRXJW6JJ.js} +2 -2
  43. package/dist/{chunk-UQX2HY5M.js → chunk-W7WNRPNQ.js} +2 -2
  44. package/dist/cli.js +1 -1
  45. package/dist/{client-VUNPLVCG.js → client-5UMNDY7Z.js} +2 -2
  46. package/dist/{config-HE2LGTTG.js → config-O44DOHFW.js} +2 -2
  47. package/dist/config-mutator-PRLY2TCE.js +2 -0
  48. package/dist/doctor-NKPH74F7.js +2 -0
  49. package/dist/index.d.ts +55 -5
  50. package/dist/index.js +1 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/{program-53CQJEUZ.js → program-RHIJYCEJ.js} +191 -187
  53. package/dist/program-RHIJYCEJ.js.map +1 -0
  54. package/dist/{promote-4PPJJ6AW.js → promote-ZRNVPWTD.js} +2 -2
  55. package/dist/push-DID6RZYI.js +2 -0
  56. package/dist/push-bridge-VPTQNM43.js +2 -0
  57. package/dist/push-store-L5QHMSST.js +2 -0
  58. package/dist/{query-ETDKC7WC.js → query-HURONGKA.js} +2 -2
  59. package/dist/{registry-AMETOJ3S.js → registry-AYGFAKTC.js} +2 -2
  60. package/dist/{request-planner-VFWWT5XR.js → request-planner-ZZRSOBQZ.js} +2 -2
  61. package/dist/{review-candidates-2PI4CGZO.js → review-candidates-KHH47PK7.js} +2 -2
  62. package/dist/routing-GUBKKWPT.js +2 -0
  63. package/dist/schedule-tool-VH77T3N3.js +2 -0
  64. package/dist/scheduler-SZ4YYXJE.js +2 -0
  65. package/dist/{seat-TVNR245I.js → seat-CVTTTE5V.js} +2 -2
  66. package/dist/{select-KY7B4HAS.js → select-OUTM6OBC.js} +2 -2
  67. package/dist/{set-enabled-NEINY2I2.js → set-enabled-2QKQRVUN.js} +2 -2
  68. package/dist/token-store-AY6OBDVI.js +2 -0
  69. package/dist/token-store-AY6OBDVI.js.map +1 -0
  70. package/dist/{tool-5JGMWH62.js → tool-OFXHMLE5.js} +2 -2
  71. package/dist/{tool-MQQ2W5LJ.js → tool-XY7QGHLV.js} +2 -2
  72. package/dist/wiki-46GMWX34.js +2 -0
  73. package/dist/wiki-46GMWX34.js.map +1 -0
  74. package/package.json +1 -1
  75. package/dist/board-dashboard-4GQ7RTH3.js.map +0 -1
  76. package/dist/chunk-2QSG53RN.js +0 -482
  77. package/dist/chunk-2QSG53RN.js.map +0 -1
  78. package/dist/chunk-ACFQBLPX.js +0 -3
  79. package/dist/chunk-ACFQBLPX.js.map +0 -1
  80. package/dist/chunk-ECBVOIIK.js.map +0 -1
  81. package/dist/chunk-IGORU3XR.js +0 -54
  82. package/dist/chunk-IGORU3XR.js.map +0 -1
  83. package/dist/config-mutator-22AVTST2.js +0 -2
  84. package/dist/doctor-6RDRST4G.js +0 -2
  85. package/dist/program-53CQJEUZ.js.map +0 -1
  86. package/dist/push-HEDA6P3B.js +0 -2
  87. package/dist/push-HEDA6P3B.js.map +0 -1
  88. package/dist/push-store-5VJ4FNI4.js +0 -2
  89. package/dist/routing-M7MDLD7Q.js +0 -2
  90. package/dist/schedule-tool-2EQ53IOQ.js +0 -2
  91. package/dist/scheduler-YGVINPZF.js +0 -2
  92. package/dist/token-store-YBSU2DTV.js +0 -2
  93. package/dist/wiki-COAUQ6TQ.js +0 -2
  94. /package/dist/{App-6OMMZW2M.js.map → App-UQP7UQYV.js.map} +0 -0
  95. /package/dist/{ChatApp-EDDROHNA.js.map → ChatApp-VGSP5O6N.js.map} +0 -0
  96. /package/dist/{agent-VPM3EEUB.js.map → agent-MO27U4Y7.js.map} +0 -0
  97. /package/dist/{chunk-S4XSVAAG.js.map → chunk-45GOH6F7.js.map} +0 -0
  98. /package/dist/{chunk-CJJULHPJ.js.map → chunk-4ELAUGOP.js.map} +0 -0
  99. /package/dist/{chunk-5FY7PWXW.js.map → chunk-5PPMPCHG.js.map} +0 -0
  100. /package/dist/{chunk-BU4LE2RT.js.map → chunk-746KHKT4.js.map} +0 -0
  101. /package/dist/{chunk-QLB76BGE.js.map → chunk-BQ2HJ7TS.js.map} +0 -0
  102. /package/dist/{chunk-PITMPRVP.js.map → chunk-CKQ2YDFP.js.map} +0 -0
  103. /package/dist/{chunk-7T7IXLLA.js.map → chunk-CUZTLQH2.js.map} +0 -0
  104. /package/dist/{chunk-PX2AOZ5G.js.map → chunk-HVZVFCJX.js.map} +0 -0
  105. /package/dist/{chunk-BXYKFWAI.js.map → chunk-HYGMWCUU.js.map} +0 -0
  106. /package/dist/{chunk-YE4HKOS5.js.map → chunk-J2YLOGNN.js.map} +0 -0
  107. /package/dist/{chunk-MG5LRE5B.js.map → chunk-OJ7KM2UO.js.map} +0 -0
  108. /package/dist/{chunk-4STXRZZS.js.map → chunk-PFK3QO6S.js.map} +0 -0
  109. /package/dist/{chunk-K3BG77KK.js.map → chunk-PMQ47IPT.js.map} +0 -0
  110. /package/dist/{chunk-KTF4YF4M.js.map → chunk-T2VDHVYW.js.map} +0 -0
  111. /package/dist/{chunk-J5TZ6QGD.js.map → chunk-VEHTVYP6.js.map} +0 -0
  112. /package/dist/{chunk-SDOSQ6TJ.js.map → chunk-VRXJW6JJ.js.map} +0 -0
  113. /package/dist/{chunk-UQX2HY5M.js.map → chunk-W7WNRPNQ.js.map} +0 -0
  114. /package/dist/{client-VUNPLVCG.js.map → client-5UMNDY7Z.js.map} +0 -0
  115. /package/dist/{config-HE2LGTTG.js.map → config-O44DOHFW.js.map} +0 -0
  116. /package/dist/{config-mutator-22AVTST2.js.map → config-mutator-PRLY2TCE.js.map} +0 -0
  117. /package/dist/{doctor-6RDRST4G.js.map → doctor-NKPH74F7.js.map} +0 -0
  118. /package/dist/{promote-4PPJJ6AW.js.map → promote-ZRNVPWTD.js.map} +0 -0
  119. /package/dist/{push-store-5VJ4FNI4.js.map → push-DID6RZYI.js.map} +0 -0
  120. /package/dist/{query-ETDKC7WC.js.map → push-bridge-VPTQNM43.js.map} +0 -0
  121. /package/dist/{registry-AMETOJ3S.js.map → push-store-L5QHMSST.js.map} +0 -0
  122. /package/dist/{routing-M7MDLD7Q.js.map → query-HURONGKA.js.map} +0 -0
  123. /package/dist/{schedule-tool-2EQ53IOQ.js.map → registry-AYGFAKTC.js.map} +0 -0
  124. /package/dist/{request-planner-VFWWT5XR.js.map → request-planner-ZZRSOBQZ.js.map} +0 -0
  125. /package/dist/{review-candidates-2PI4CGZO.js.map → review-candidates-KHH47PK7.js.map} +0 -0
  126. /package/dist/{scheduler-YGVINPZF.js.map → routing-GUBKKWPT.js.map} +0 -0
  127. /package/dist/{seat-TVNR245I.js.map → schedule-tool-VH77T3N3.js.map} +0 -0
  128. /package/dist/{token-store-YBSU2DTV.js.map → scheduler-SZ4YYXJE.js.map} +0 -0
  129. /package/dist/{wiki-COAUQ6TQ.js.map → seat-CVTTTE5V.js.map} +0 -0
  130. /package/dist/{select-KY7B4HAS.js.map → select-OUTM6OBC.js.map} +0 -0
  131. /package/dist/{set-enabled-NEINY2I2.js.map → set-enabled-2QKQRVUN.js.map} +0 -0
  132. /package/dist/{tool-5JGMWH62.js.map → tool-OFXHMLE5.js.map} +0 -0
  133. /package/dist/{tool-MQQ2W5LJ.js.map → tool-XY7QGHLV.js.map} +0 -0
@@ -31,6 +31,10 @@ final class AnswerView: NSView {
31
31
  var onHeight: ((CGFloat) -> Void)?
32
32
  /// "Open in chat". Set by the app.
33
33
  var onOpenChat: (() -> Void)?
34
+ /// "Listen again" (#492): say the answer again, or stop saying it.
35
+ /// Set by the app, which owns the speaking.
36
+ var onListenAgain: (() -> Void)?
37
+ private var listenButton: NSButton?
34
38
 
35
39
  private static let linkRow: CGFloat = 34
36
40
  private static let imageHeight: CGFloat = 120
@@ -50,9 +54,14 @@ final class AnswerView: NSView {
50
54
  links.edgeInsets = NSEdgeInsets(top: 4, left: 12, bottom: 8, right: 12)
51
55
  addSubview(links)
52
56
 
53
- // Copy and Open in chat, shown while the pointer is over the answer.
57
+ // Listen again, Copy and Open in chat, shown while the pointer is
58
+ // over the answer.
54
59
  actions.orientation = .horizontal
55
60
  actions.spacing = 2
61
+ let idle = ListenAgain.look(replaying: false)
62
+ let listen = actionButton(idle.symbol, idle.label, #selector(listenAgain))
63
+ listenButton = listen
64
+ actions.addArrangedSubview(listen)
56
65
  actions.addArrangedSubview(actionButton("doc.on.doc", "Copy the answer", #selector(copyAnswer)))
57
66
  actions.addArrangedSubview(actionButton("bubble.left.and.bubble.right", "Open in chat", #selector(openChat)))
58
67
  actions.isHidden = true
@@ -93,7 +102,8 @@ final class AnswerView: NSView {
93
102
  thumb.frame = NSRect(x: 12, y: h - imgH - 10, width: w - 24, height: imgH)
94
103
  web.frame = NSRect(x: 0, y: linkH, width: w, height: max(0, h - linkH - imgH - (imgH > 0 ? 16 : 0)))
95
104
  links.frame = NSRect(x: 0, y: 0, width: w, height: linkH)
96
- actions.frame = NSRect(x: w - 64, y: h - 32, width: 56, height: 26)
105
+ // Three 24-point buttons, 2 apart, with 3 points each side.
106
+ actions.frame = NSRect(x: w - 90, y: h - 32, width: 82, height: 26)
97
107
  }
98
108
 
99
109
  /// Does this turn have anything the spoken answer did not already
@@ -198,6 +208,18 @@ final class AnswerView: NSView {
198
208
 
199
209
  @objc private func openChat() { onOpenChat?() }
200
210
 
211
+ @objc private func listenAgain() { onListenAgain?() }
212
+
213
+ /// The speaker while the answer is being said again: a stop button,
214
+ /// so a second click stops it.
215
+ func setReplaying(_ on: Bool) {
216
+ guard let b = listenButton else { return }
217
+ let look = ListenAgain.look(replaying: on)
218
+ b.image = NSImage(systemSymbolName: look.symbol, accessibilityDescription: look.label)
219
+ b.toolTip = look.label
220
+ b.setAccessibilityLabel(look.label)
221
+ }
222
+
201
223
  /// Select-and-⌘C: the pill has no Edit menu to route the shortcut.
202
224
  func copySelection() { NSApp.sendAction(#selector(NSText.copy(_:)), to: web, from: nil) }
203
225
 
@@ -0,0 +1,26 @@
1
+ import Foundation
2
+
3
+ /// The answer's Listen again button (#492): what it shows, and what a
4
+ /// click does. A click speaks the answer in the pill again, from its
5
+ /// start, in its agent's voice; a click while it plays stops it.
6
+ enum ListenAgain {
7
+ enum Click: Equatable {
8
+ /// Queue the answer again on the daemon's speaking queue.
9
+ case speak
10
+ /// Stop it, the same stop as the stop shortcut.
11
+ case stop
12
+ /// No answer to say: nothing happens.
13
+ case nothing
14
+ }
15
+
16
+ static func click(replaying: Bool, text: String?) -> Click {
17
+ if replaying { return .stop }
18
+ guard let text, !text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { return .nothing }
19
+ return .speak
20
+ }
21
+
22
+ /// The SF Symbol and the label (tooltip and screen reader) for a state.
23
+ static func look(replaying: Bool) -> (symbol: String, label: String) {
24
+ replaying ? ("stop.fill", "Stop listening") : ("speaker.wave.2", "Listen again")
25
+ }
26
+ }
@@ -62,6 +62,11 @@ final class App: NSObject, NSApplicationDelegate {
62
62
  /// Waiting for our answer to be spoken by the daemon's queue. The door
63
63
  /// lets go of it: the answer stays queued and plays after the turn.
64
64
  private var speaking: Task<Void, Never>?
65
+ /// The answer in the pill, for Listen again (#492): what was said, by
66
+ /// which agent, in which voice.
67
+ private var shownAnswer: (text: String, agentID: String?, voice: VoiceChoice?)?
68
+ /// Listen again in progress; a second click stops it.
69
+ private var replaying: Task<Void, Never>?
65
70
  /// Words said while our own turn was still running: they go next, and
66
71
  /// the stale answer is not spoken.
67
72
  private var followUp: String?
@@ -437,6 +442,7 @@ final class App: NSObject, NSApplicationDelegate {
437
442
  return self.statusMenu.palette(of: self.shownAgent)
438
443
  }
439
444
  panel.answer.onOpenChat = { [weak self] in self?.openChat() }
445
+ panel.answer.onListenAgain = { [weak self] in self?.listenAgain() }
440
446
  statusMenu.pillVisible = { [weak self] in self?.panel.isVisible ?? false }
441
447
  statusMenu.onHidePill = { [weak self] in self?.dismissPill() }
442
448
  statusMenu.pillReduced = { [weak self] in self?.panel.reduced ?? false }
@@ -590,6 +596,8 @@ final class App: NSObject, NSApplicationDelegate {
590
596
  /// Open the microphone with no key held.
591
597
  private func listenHandsFree(followUp: Bool) {
592
598
  guard !busy, !recorder.isRecording else { return }
599
+ // A replay is playing (#492): the follow-up window would hear it.
600
+ if followUp && replaying != nil { return }
593
601
  recorder.endOfTurn = settings?.general.endOfTurn ?? "vad"
594
602
  do {
595
603
  try recorder.start()
@@ -665,9 +673,50 @@ final class App: NSObject, NSApplicationDelegate {
665
673
  asideSpeaker = nil
666
674
  lastSpokeAt = Date()
667
675
  Task { await Speech.stopAll() }
676
+ endReplay()
668
677
  if !recorder.isRecording { panel.render(rest) }
669
678
  }
670
679
 
680
+ /// Listen again (#492): the answer in the pill, said again from its
681
+ /// start in its agent's voice. It waits its turn on the daemon's
682
+ /// speaking queue like any line. A second click stops it, the same
683
+ /// stop as the stop shortcut.
684
+ private func listenAgain() {
685
+ switch ListenAgain.click(replaying: replaying != nil, text: shownAnswer?.text) {
686
+ case .nothing: return
687
+ case .stop: stopSpeaking(); return
688
+ case .speak: break
689
+ }
690
+ guard let shown = shownAnswer else { return }
691
+ // An open microphone would take the replay for the listener's
692
+ // words: it closes without sending.
693
+ if recorder.isRecording {
694
+ stopPolling()
695
+ _ = recorder.stop()
696
+ panel.render(rest)
697
+ }
698
+ Log.info("listen again (\(shown.agentID ?? "?"))")
699
+ // Nothing else on screen: the orb speaks while it is said.
700
+ let onScreen = !busy && asideSpeaker == nil
701
+ if onScreen { panel.render(.saying(shown.text)) }
702
+ panel.answer.setReplaying(true)
703
+ let line = Task { await Speech.say(shown.text, agentID: shown.agentID, kind: "answer", voice: shown.voice) }
704
+ replaying = line
705
+ Task { @MainActor [weak self] in
706
+ await line.value
707
+ guard let self, self.replaying == line else { return }
708
+ self.endReplay()
709
+ if onScreen && !self.busy && !self.recorder.isRecording && self.asideSpeaker == nil { self.panel.render(self.rest) }
710
+ }
711
+ }
712
+
713
+ /// The speaker button back to Listen again.
714
+ private func endReplay() {
715
+ replaying?.cancel()
716
+ replaying = nil
717
+ panel.answer.setReplaying(false)
718
+ }
719
+
671
720
  private func startListening() {
672
721
  // A held key overrides any hands-free window that is open, so the
673
722
  // two ways of talking never fight over the microphone.
@@ -684,6 +733,9 @@ final class App: NSObject, NSApplicationDelegate {
684
733
  Speech.stop()
685
734
  speaking?.cancel()
686
735
  speaking = nil
736
+ // A replay waits, hushed, like any answer, and plays again on
737
+ // resume: the button keeps it, so a click stops it rather than
738
+ // queueing a second copy. It lets go when the daemon's wait ends.
687
739
  lastSpokeAt = Date()
688
740
  talkCheck = Task { await AgentClient.hush() }
689
741
  Log.info("door: opened\(busy ? " (a turn is running)" : "")")
@@ -831,6 +883,7 @@ final class App: NSObject, NSApplicationDelegate {
831
883
  buttons: answer.buttons, imageURL: answer.imageURL) {
832
884
  panel.showAnswer(spoken: answer.text, written: answer.written,
833
885
  buttons: answer.buttons, imageURL: answer.imageURL)
886
+ shownAnswer = (answer.text, answer.agentID ?? agent, answer.voice)
834
887
  }
835
888
  // Nothing else on screen: the pill shows this answer, its
836
889
  // orb in this agent's colour, while it is spoken.
@@ -896,6 +949,7 @@ final class App: NSObject, NSApplicationDelegate {
896
949
  buttons: answer.buttons, imageURL: answer.imageURL) {
897
950
  panel.showAnswer(spoken: answer.text, written: answer.written,
898
951
  buttons: answer.buttons, imageURL: answer.imageURL)
952
+ shownAnswer = (answer.text, answer.agentID, voice)
899
953
  } else {
900
954
  panel.collapse()
901
955
  }
@@ -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-YE4HKOS5.js";import"./chunk-IGORU3XR.js";import"./chunk-UIBUZ2N3.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-J2YLOGNN.js";import"./chunk-FJI5GRBH.js";import"./chunk-BRK6M6LA.js";import"./chunk-UIBUZ2N3.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-6OMMZW2M.js.map
8
+ //# sourceMappingURL=App-UQP7UQYV.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-YE4HKOS5.js";import"./chunk-IGORU3XR.js";import"./chunk-UIBUZ2N3.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-J2YLOGNN.js";import"./chunk-FJI5GRBH.js";import"./chunk-BRK6M6LA.js";import"./chunk-UIBUZ2N3.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-EDDROHNA.js.map
7
+ //# sourceMappingURL=ChatApp-VGSP5O6N.js.map
@@ -1,2 +1,2 @@
1
- import{A as a,B as b,C as c}from"./chunk-4STXRZZS.js";import"./chunk-SFQUP3BP.js";import"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.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-VPM3EEUB.js.map
1
+ import{A as a,B as b,C as c}from"./chunk-PFK3QO6S.js";import"./chunk-SFQUP3BP.js";import"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.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-MO27U4Y7.js.map