agentix-cli 0.57.0 → 0.59.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 (123) hide show
  1. package/apps/mac-voice/Sources/AgentXVoice/Config.swift +19 -5
  2. package/apps/mac-voice/Sources/AgentXVoice/HistoryClient.swift +55 -0
  3. package/apps/mac-voice/Sources/AgentXVoice/HistoryModel.swift +153 -0
  4. package/apps/mac-voice/Sources/AgentXVoice/HistoryWindow.swift +301 -0
  5. package/apps/mac-voice/Sources/AgentXVoice/LocalSTT.swift +79 -0
  6. package/apps/mac-voice/Sources/AgentXVoice/ModelStore.swift +184 -0
  7. package/apps/mac-voice/Sources/AgentXVoice/Orb.swift +131 -169
  8. package/apps/mac-voice/Sources/AgentXVoice/Panel.swift +174 -35
  9. package/apps/mac-voice/Sources/AgentXVoice/Parakeet.swift +264 -0
  10. package/apps/mac-voice/Sources/AgentXVoice/PillPlacement.swift +70 -0
  11. package/apps/mac-voice/Sources/AgentXVoice/Recorder.swift +81 -3
  12. package/apps/mac-voice/Sources/AgentXVoice/ResultCard.swift +26 -22
  13. package/apps/mac-voice/Sources/AgentXVoice/SettingsWindow.swift +10 -2
  14. package/apps/mac-voice/Sources/AgentXVoice/SileroVAD.swift +92 -0
  15. package/apps/mac-voice/Sources/AgentXVoice/Speech.swift +7 -5
  16. package/apps/mac-voice/Sources/AgentXVoice/StatusMenu.swift +23 -6
  17. package/apps/mac-voice/Sources/AgentXVoice/TurnEnd.swift +110 -0
  18. package/apps/mac-voice/Sources/AgentXVoice/VoiceSettings.swift +23 -0
  19. package/apps/mac-voice/Sources/AgentXVoice/main.swift +47 -70
  20. package/apps/mac-voice/build.sh +10 -1
  21. package/dist/{App-Z5VOAUXB.js → App-QEJGXZTY.js} +2 -2
  22. package/dist/{ChatApp-BE7ONQKS.js → ChatApp-VKWQN5GM.js} +2 -2
  23. package/dist/{agent-Q74EISKP.js → agent-MJKLI2L5.js} +2 -2
  24. package/dist/{board-dashboard-A7PQOI6C.js → board-dashboard-2KVT72J7.js} +221 -138
  25. package/dist/board-dashboard-2KVT72J7.js.map +1 -0
  26. package/dist/{chunk-I2LYULR4.js → chunk-2XZGHIVP.js} +5 -5
  27. package/dist/{chunk-5LLGIX5M.js → chunk-3EVCHRJF.js} +2 -2
  28. package/dist/{chunk-6QNPCVRN.js → chunk-4ZTV6JV7.js} +3 -3
  29. package/dist/chunk-4ZTV6JV7.js.map +1 -0
  30. package/dist/{chunk-VI7GBDKV.js → chunk-5OF3EGCZ.js} +2 -2
  31. package/dist/{chunk-RXEAACVH.js → chunk-6DUTIPTY.js} +2 -2
  32. package/dist/{chunk-CQUVUVXR.js → chunk-6ZV2QFXE.js} +2 -2
  33. package/dist/{chunk-2MIOMYT2.js → chunk-DAAWUFO4.js} +2 -2
  34. package/dist/{chunk-547G3HYQ.js → chunk-EJQOKSKP.js} +2 -2
  35. package/dist/{chunk-POL7RAJQ.js → chunk-ILXW3ERG.js} +117 -117
  36. package/dist/chunk-ILXW3ERG.js.map +1 -0
  37. package/dist/{chunk-ERL6AS3O.js → chunk-IW4XIZAZ.js} +8 -8
  38. package/dist/{chunk-ERL6AS3O.js.map → chunk-IW4XIZAZ.js.map} +1 -1
  39. package/dist/{chunk-Q6SMLSRO.js → chunk-JUY77L7C.js} +2 -2
  40. package/dist/{chunk-KW7TIOS3.js → chunk-K62U5EJJ.js} +2 -2
  41. package/dist/{chunk-KKGFZEXS.js → chunk-L5OCF33B.js} +37 -36
  42. package/dist/chunk-L5OCF33B.js.map +1 -0
  43. package/dist/{chunk-XTD3SZIP.js → chunk-N5GOBLUI.js} +2 -2
  44. package/dist/{chunk-VVBGPT6W.js → chunk-OIDMPPV5.js} +2 -2
  45. package/dist/{chunk-OZZPJ2YG.js → chunk-SDBU6747.js} +190 -177
  46. package/dist/chunk-SDBU6747.js.map +1 -0
  47. package/dist/{chunk-NKMFHEGV.js → chunk-WFPRVZBA.js} +2 -2
  48. package/dist/{chunk-6OABTCRA.js → chunk-WI5R64WO.js} +2 -2
  49. package/dist/{chunk-5W7NJHCS.js → chunk-YCIZ2WHX.js} +2 -2
  50. package/dist/{chunk-U5YBQJ5Q.js → chunk-YQU74AOL.js} +2 -2
  51. package/dist/{chunk-V7ZK6ZIO.js → chunk-YRB75GMN.js} +2 -2
  52. package/dist/cli.js +1 -1
  53. package/dist/client-X2PTYKVX.js +2 -0
  54. package/dist/{config-P6YXC6XZ.js → config-XB2ORKWS.js} +2 -2
  55. package/dist/config-mutator-KMXR3XDG.js +2 -0
  56. package/dist/doctor-6BIMNEGU.js +2 -0
  57. package/dist/index.d.ts +17 -0
  58. package/dist/index.js +1 -1
  59. package/dist/program-DHDC6XYB.js +2 -0
  60. package/dist/{promote-KVPLDSKT.js → promote-GBR6YSQW.js} +2 -2
  61. package/dist/query-672RGMXO.js +2 -0
  62. package/dist/{registry-AUOI4TW2.js → registry-P535FNLB.js} +2 -2
  63. package/dist/{request-planner-LMZ5ZAXC.js → request-planner-KHTCHF7N.js} +2 -2
  64. package/dist/{review-candidates-WCBXLLDS.js → review-candidates-Y5KCRUNU.js} +2 -2
  65. package/dist/{routing-FBASYKUL.js → routing-RWCCDJ4D.js} +2 -2
  66. package/dist/schedule-tool-H46AK53H.js +2 -0
  67. package/dist/scheduler-3XLWBCX7.js +2 -0
  68. package/dist/{seat-DBFW3Z5P.js → seat-PJPKLH6L.js} +2 -2
  69. package/dist/{select-6CNVVFA5.js → select-VMTJAX5X.js} +2 -2
  70. package/dist/{set-enabled-AYZH3KSB.js → set-enabled-LPXH3ZQP.js} +2 -2
  71. package/dist/{tool-PKS4NBZ6.js → tool-MWXG44OT.js} +2 -2
  72. package/dist/wiki-QHMHVFWU.js +2 -0
  73. package/package.json +1 -1
  74. package/dist/board-dashboard-A7PQOI6C.js.map +0 -1
  75. package/dist/chunk-6QNPCVRN.js.map +0 -1
  76. package/dist/chunk-KKGFZEXS.js.map +0 -1
  77. package/dist/chunk-OZZPJ2YG.js.map +0 -1
  78. package/dist/chunk-POL7RAJQ.js.map +0 -1
  79. package/dist/client-EFP2PKA3.js +0 -2
  80. package/dist/config-mutator-3GKXLTHH.js +0 -2
  81. package/dist/doctor-JEWMHXYH.js +0 -2
  82. package/dist/program-7DUQJDSQ.js +0 -2
  83. package/dist/query-AGOMCYTT.js +0 -2
  84. package/dist/schedule-tool-RJRJ63SS.js +0 -2
  85. package/dist/scheduler-ATA7Z44S.js +0 -2
  86. package/dist/wiki-QW6BDNEQ.js +0 -2
  87. /package/dist/{App-Z5VOAUXB.js.map → App-QEJGXZTY.js.map} +0 -0
  88. /package/dist/{ChatApp-BE7ONQKS.js.map → ChatApp-VKWQN5GM.js.map} +0 -0
  89. /package/dist/{agent-Q74EISKP.js.map → agent-MJKLI2L5.js.map} +0 -0
  90. /package/dist/{chunk-I2LYULR4.js.map → chunk-2XZGHIVP.js.map} +0 -0
  91. /package/dist/{chunk-5LLGIX5M.js.map → chunk-3EVCHRJF.js.map} +0 -0
  92. /package/dist/{chunk-VI7GBDKV.js.map → chunk-5OF3EGCZ.js.map} +0 -0
  93. /package/dist/{chunk-RXEAACVH.js.map → chunk-6DUTIPTY.js.map} +0 -0
  94. /package/dist/{chunk-CQUVUVXR.js.map → chunk-6ZV2QFXE.js.map} +0 -0
  95. /package/dist/{chunk-2MIOMYT2.js.map → chunk-DAAWUFO4.js.map} +0 -0
  96. /package/dist/{chunk-547G3HYQ.js.map → chunk-EJQOKSKP.js.map} +0 -0
  97. /package/dist/{chunk-Q6SMLSRO.js.map → chunk-JUY77L7C.js.map} +0 -0
  98. /package/dist/{chunk-KW7TIOS3.js.map → chunk-K62U5EJJ.js.map} +0 -0
  99. /package/dist/{chunk-XTD3SZIP.js.map → chunk-N5GOBLUI.js.map} +0 -0
  100. /package/dist/{chunk-VVBGPT6W.js.map → chunk-OIDMPPV5.js.map} +0 -0
  101. /package/dist/{chunk-NKMFHEGV.js.map → chunk-WFPRVZBA.js.map} +0 -0
  102. /package/dist/{chunk-6OABTCRA.js.map → chunk-WI5R64WO.js.map} +0 -0
  103. /package/dist/{chunk-5W7NJHCS.js.map → chunk-YCIZ2WHX.js.map} +0 -0
  104. /package/dist/{chunk-U5YBQJ5Q.js.map → chunk-YQU74AOL.js.map} +0 -0
  105. /package/dist/{chunk-V7ZK6ZIO.js.map → chunk-YRB75GMN.js.map} +0 -0
  106. /package/dist/{client-EFP2PKA3.js.map → client-X2PTYKVX.js.map} +0 -0
  107. /package/dist/{config-P6YXC6XZ.js.map → config-XB2ORKWS.js.map} +0 -0
  108. /package/dist/{config-mutator-3GKXLTHH.js.map → config-mutator-KMXR3XDG.js.map} +0 -0
  109. /package/dist/{doctor-JEWMHXYH.js.map → doctor-6BIMNEGU.js.map} +0 -0
  110. /package/dist/{program-7DUQJDSQ.js.map → program-DHDC6XYB.js.map} +0 -0
  111. /package/dist/{promote-KVPLDSKT.js.map → promote-GBR6YSQW.js.map} +0 -0
  112. /package/dist/{query-AGOMCYTT.js.map → query-672RGMXO.js.map} +0 -0
  113. /package/dist/{registry-AUOI4TW2.js.map → registry-P535FNLB.js.map} +0 -0
  114. /package/dist/{request-planner-LMZ5ZAXC.js.map → request-planner-KHTCHF7N.js.map} +0 -0
  115. /package/dist/{review-candidates-WCBXLLDS.js.map → review-candidates-Y5KCRUNU.js.map} +0 -0
  116. /package/dist/{routing-FBASYKUL.js.map → routing-RWCCDJ4D.js.map} +0 -0
  117. /package/dist/{schedule-tool-RJRJ63SS.js.map → schedule-tool-H46AK53H.js.map} +0 -0
  118. /package/dist/{scheduler-ATA7Z44S.js.map → scheduler-3XLWBCX7.js.map} +0 -0
  119. /package/dist/{seat-DBFW3Z5P.js.map → seat-PJPKLH6L.js.map} +0 -0
  120. /package/dist/{select-6CNVVFA5.js.map → select-VMTJAX5X.js.map} +0 -0
  121. /package/dist/{set-enabled-AYZH3KSB.js.map → set-enabled-LPXH3ZQP.js.map} +0 -0
  122. /package/dist/{tool-PKS4NBZ6.js.map → tool-MWXG44OT.js.map} +0 -0
  123. /package/dist/{wiki-QW6BDNEQ.js.map → wiki-QHMHVFWU.js.map} +0 -0
@@ -19,9 +19,6 @@ final class App: NSObject, NSApplicationDelegate {
19
19
  private let panel = Panel()
20
20
  private let statusMenu = StatusMenu()
21
21
  private let card = ResultCard()
22
- private let orb = OrbOverlay()
23
- /// What the listener said this turn, shown under the orb.
24
- private var heardLine = ""
25
22
  /// The agent whose by-name answer is on screen now, while no turn runs.
26
23
  private var asideSpeaker: String?
27
24
  private let recorder = Recorder()
@@ -164,37 +161,28 @@ final class App: NSObject, NSApplicationDelegate {
164
161
  Log.info("settings: talk \(saved.general.hotkeys.talk), speech to text \(saved.general.stt)")
165
162
  }
166
163
 
167
- /// Who the panel and orb name: the agent a shortcut is asking, a
168
- /// by-name answer being spoken, else the agent our turn is asking,
169
- /// else the target.
164
+ /// Who the pill names and whose colour its orb wears: the agent a
165
+ /// shortcut is asking, a by-name answer being spoken, else the agent
166
+ /// our turn is asking, else the target.
170
167
  private var shownAgent: String {
171
168
  if let forcedAgent, recorder.isRecording { return forcedAgent }
172
169
  if let asideSpeaker { return asideSpeaker }
173
170
  return busy && !turnAgent.isEmpty ? turnAgent : Config.effectiveAgentID
174
171
  }
175
172
 
176
- /// The orb follows the pill's state: listening, thinking or speaking
177
- /// show it; idle and errors hide it.
178
- private func renderOrb(_ state: Panel.State) {
179
- guard Config.showOrb else { orb.hide(); return }
180
- let who = shownAgent
181
- let name = who.isEmpty ? "" : statusMenu.name(of: who)
182
- let tint = statusMenu.color(of: who)
183
- switch state {
184
- case .idle, .error:
185
- orb.hide()
186
- case .listening:
187
- heardLine = ""
188
- orb.show(.listening, name: name, tint: tint, line: "Listening…", status: "")
189
- case .thinking:
190
- orb.show(.thinking, name: name, tint: tint, line: heardLine, status: "Thinking…")
191
- case .working(let step, let secs):
192
- orb.show(.thinking, name: name, tint: tint, line: heardLine, status: "\(step) · \(secs)s")
193
- case .speaking:
194
- orb.show(.speaking, name: name, tint: tint, line: heardLine, status: "")
195
- case .saying(let text):
196
- orb.show(.speaking, name: name, tint: tint, line: text, status: "")
173
+ /// Close, Esc or "Hide pill": the pill goes and the voice stops, the
174
+ /// same stop as ⌘⌥. An open microphone closes without sending. The
175
+ /// next talk key brings the pill back.
176
+ private func dismissPill() {
177
+ Log.info("pill: dismissed")
178
+ panel.dismiss()
179
+ if recorder.isRecording {
180
+ stopPolling()
181
+ _ = recorder.stop()
182
+ forcedAgent = nil
183
+ talkCheck = nil
197
184
  }
185
+ stopSpeaking()
198
186
  }
199
187
 
200
188
  /// ⌘⌥V. Everything except the hotkey lives in `agentx paste`.
@@ -243,30 +231,33 @@ final class App: NSObject, NSApplicationDelegate {
243
231
  func applicationDidFinishLaunching(_ note: Notification) {
244
232
  NSApp.setActivationPolicy(.accessory)
245
233
  retireOlderInstances()
246
- panel.onRender = { [weak self] state in
247
- self?.statusMenu.show(state)
248
- self?.renderOrb(state)
249
- }
234
+ panel.onRender = { [weak self] state in self?.statusMenu.show(state) }
250
235
  panel.contextMenu = { [weak self] in self?.statusMenu.menu ?? NSMenu() }
251
236
  panel.agentName = { [weak self] in
252
237
  guard let self else { return "" }
253
238
  let who = self.shownAgent
254
239
  return who.isEmpty ? "" : self.statusMenu.name(of: who)
255
240
  }
256
- panel.alwaysVisible = Config.showPill
257
- panel.yieldsActiveStates = Config.showOrb
258
- orb.levelSource = { [weak self] in self?.recorder.level ?? 0 }
259
- card.anchor = { [weak self] in self?.orb.contentFrame }
260
- statusMenu.onOrbChanged = { [weak self] on in
261
- guard let self else { return }
262
- self.panel.yieldsActiveStates = on
263
- if !on { self.orb.hide() }
264
- if !self.busy && !self.recorder.isRecording { self.panel.render(.idle) }
241
+ panel.agentTint = { [weak self] in
242
+ guard let self else { return Brand.accent }
243
+ return self.statusMenu.color(of: self.shownAgent)
265
244
  }
245
+ panel.alwaysVisible = Config.showPill
246
+ panel.orb.setAnimated(Config.animatedOrb)
247
+ panel.orb.levelSource = { [weak self] in self?.recorder.level ?? 0 }
248
+ panel.onDismiss = { [weak self] in self?.dismissPill() }
249
+ panel.onMove = { [weak self] in self?.card.follow() }
250
+ card.anchor = { [weak self] in self?.panel.frame ?? .zero }
251
+ statusMenu.pillVisible = { [weak self] in self?.panel.isVisible ?? false }
252
+ statusMenu.onHidePill = { [weak self] in self?.dismissPill() }
253
+ statusMenu.onResetPosition = { [weak self] in self?.panel.resetPosition() }
254
+ statusMenu.onAnimatedOrbChanged = { [weak self] on in self?.panel.orb.setAnimated(on) }
266
255
  panel.render(.idle)
267
256
  statusMenu.onPillChanged = { [weak self] on in
268
257
  guard let self else { return }
269
258
  self.panel.alwaysVisible = on
259
+ // Asking for the pill brings back one that was dismissed.
260
+ if on { self.panel.summon() }
270
261
  if !self.busy && !self.recorder.isRecording { self.panel.render(.idle) }
271
262
  }
272
263
  statusMenu.onTargetChanged = { [weak self] id in
@@ -330,20 +321,14 @@ final class App: NSObject, NSApplicationDelegate {
330
321
  // Ending on SILENCE rather than a timer is the whole trick. A fixed
331
322
  // window either cuts people off mid-sentence or leaves the mic open
332
323
  // staring at them; the only honest signal that a sentence has finished
333
- // is the room going quiet.
324
+ // is the voice stopping. The recorder judges that (TurnEnd.swift).
334
325
 
335
- /// RMS above which the microphone is hearing a voice rather than a room.
336
- private let speechLevel: Float = 0.02
337
- /// Quiet this long after speech ends the turn.
338
- private let endSilence: TimeInterval = 1.2
339
326
  /// How long an unprompted follow-up window waits before giving up.
340
327
  private let followUpPatience: TimeInterval = 4.0
341
328
  /// How long a clicked session waits for you to start talking.
342
329
  private let clickPatience: TimeInterval = 8.0
343
330
 
344
331
  private var listenPoll: Timer?
345
- private var heardSpeech = false
346
- private var quietSince: Date?
347
332
  private var openedAt = Date()
348
333
  private var patience: TimeInterval = 8.0
349
334
  /// True when nothing was said and the window should close in silence.
@@ -352,14 +337,13 @@ final class App: NSObject, NSApplicationDelegate {
352
337
  /// Open the microphone with no key held.
353
338
  private func listenHandsFree(followUp: Bool) {
354
339
  guard !busy, !recorder.isRecording else { return }
340
+ recorder.endOfTurn = settings?.general.endOfTurn ?? "vad"
355
341
  do {
356
342
  try recorder.start()
357
343
  } catch {
358
344
  panel.render(.error(error.localizedDescription))
359
345
  return
360
346
  }
361
- heardSpeech = false
362
- quietSince = nil
363
347
  openedAt = Date()
364
348
  patience = followUp ? followUpPatience : clickPatience
365
349
  silentClose = followUp
@@ -378,23 +362,13 @@ final class App: NSObject, NSApplicationDelegate {
378
362
 
379
363
  private func pollLevel() {
380
364
  guard recorder.isRecording else { stopPolling(); return }
381
- let level = recorder.level
382
-
383
- if level > speechLevel {
384
- heardSpeech = true
385
- quietSince = nil
386
- return
387
- }
388
- if heardSpeech {
389
- // Speech has stopped. Give it a beat before deciding the
390
- // sentence is over — people pause inside sentences.
391
- let since = quietSince ?? Date()
392
- quietSince = since
393
- if Date().timeIntervalSince(since) >= endSilence {
394
- stopPolling()
395
- stopAndSend()
396
- }
365
+ switch recorder.turnState {
366
+ case .speaking: return
367
+ case .ended:
368
+ stopPolling()
369
+ stopAndSend()
397
370
  return
371
+ case .waiting: break
398
372
  }
399
373
  // Nothing said yet. Close quietly rather than making the person
400
374
  // dismiss a window they did not ask for.
@@ -440,6 +414,8 @@ final class App: NSObject, NSApplicationDelegate {
440
414
  // two ways of talking never fight over the microphone.
441
415
  stopPolling()
442
416
  guard !recorder.isRecording else { return }
417
+ // A dismissed pill comes back with the talk key.
418
+ panel.summon()
443
419
  // Option-Space is the door to everything spoken, always: our own
444
420
  // answer or step line stops now, and the daemon hushes any talk,
445
421
  // lesson or narration, remembering which it was. Even mid-turn —
@@ -451,6 +427,8 @@ final class App: NSObject, NSApplicationDelegate {
451
427
  lastSpokeAt = Date()
452
428
  talkCheck = Task { await AgentClient.hush() }
453
429
  Log.info("door: opened\(busy ? " (a turn is running)" : "")")
430
+ // Push-to-talk ends on key release; no end-of-turn detection needed.
431
+ recorder.endOfTurn = "hold"
454
432
  do {
455
433
  try recorder.start()
456
434
  asideSpeaker = nil
@@ -481,7 +459,8 @@ final class App: NSObject, NSApplicationDelegate {
481
459
 
482
460
  Task { @MainActor in
483
461
  var heard = ""
484
- do { heard = try await Speech.transcribe(wav: wav, engine: settings?.general.stt ?? "auto") }
462
+ do { heard = try await Speech.transcribe(wav: wav, engine: settings?.general.stt ?? "auto",
463
+ local: settings?.general.localStt ?? "mlx-whisper") }
485
464
  catch { Log.warn("transcription failed: \(error.localizedDescription)") }
486
465
  guard !heard.isEmpty else {
487
466
  _ = await door.value
@@ -495,8 +474,6 @@ final class App: NSObject, NSApplicationDelegate {
495
474
  return
496
475
  }
497
476
  Log.info("heard: \(heard)")
498
- heardLine = heard
499
- if orb.isVisible { orb.model.line = heard }
500
477
  let hushed = await door.value
501
478
  // Always through the door, even with nothing hushed: the
502
479
  // listener's turn is over, so the daemon's queue plays on.
@@ -580,8 +557,8 @@ final class App: NSObject, NSApplicationDelegate {
580
557
  card.show(spoken: answer.text, written: answer.written,
581
558
  buttons: answer.buttons, imageURL: answer.imageURL)
582
559
  }
583
- // Nothing else on screen: the orb shows this answer, in
584
- // this agent's colour, while it is spoken.
560
+ // Nothing else on screen: the pill shows this answer, its
561
+ // orb in this agent's colour, while it is spoken.
585
562
  let onScreen = !busy && !recorder.isRecording
586
563
  if onScreen { asideSpeaker = agent; panel.render(.saying(answer.text)) }
587
564
  await Speech.say(answer.text, agentID: answer.agentID ?? agent, kind: "answer", voice: answer.voice)
@@ -18,9 +18,18 @@ 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 SwiftUI \
21
+ -framework AppKit -framework AVFoundation -framework Carbon -framework CoreML -framework SwiftUI \
22
22
  -target arm64-apple-macosx14.0
23
23
 
24
+ # The on-device models from a terminal: fetch them, transcribe a file, see
25
+ # where a turn would end. Same sources as the app; the models themselves
26
+ # are downloaded on first use into ~/.agentx/models, never bundled.
27
+ swiftc -O \
28
+ -o "$BIN/agentx-voice-local" \
29
+ Sources/AgentXVoice/ModelStore.swift Sources/AgentXVoice/SileroVAD.swift \
30
+ Sources/AgentXVoice/Parakeet.swift Sources/AgentXVoice/TurnEnd.swift Tools/LocalSTT/main.swift \
31
+ -framework CoreML -target arm64-apple-macosx14.0
32
+
24
33
  cp Resources/Info.plist "$APP/Contents/Info.plist"
25
34
 
26
35
  # Ad-hoc signature. Unsigned bundles get a fresh TCC identity on every
@@ -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-5W7NJHCS.js";import"./chunk-ERL6AS3O.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-YCIZ2WHX.js";import"./chunk-IW4XIZAZ.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-Z5VOAUXB.js.map
8
+ //# sourceMappingURL=App-QEJGXZTY.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-5W7NJHCS.js";import"./chunk-ERL6AS3O.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-YCIZ2WHX.js";import"./chunk-IW4XIZAZ.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-BE7ONQKS.js.map
7
+ //# sourceMappingURL=ChatApp-VKWQN5GM.js.map
@@ -1,2 +1,2 @@
1
- import{A as a,B as b,C as c}from"./chunk-KW7TIOS3.js";import"./chunk-SFQUP3BP.js";import"./chunk-QOYAX2FT.js";import"./chunk-SZJMS7K4.js";import"./chunk-7I7IEX4S.js";import"./chunk-VDMYBPYB.js";import"./chunk-DSYKYZMT.js";import"./chunk-QIJLFPWE.js";export{a as createAgentContext,b as generate,c as generateStream};
2
- //# sourceMappingURL=agent-Q74EISKP.js.map
1
+ import{A as a,B as b,C as c}from"./chunk-K62U5EJJ.js";import"./chunk-SFQUP3BP.js";import"./chunk-QOYAX2FT.js";import"./chunk-SZJMS7K4.js";import"./chunk-7I7IEX4S.js";import"./chunk-VDMYBPYB.js";import"./chunk-DSYKYZMT.js";import"./chunk-QIJLFPWE.js";export{a as createAgentContext,b as generate,c as generateStream};
2
+ //# sourceMappingURL=agent-MJKLI2L5.js.map