agentix-cli 0.110.0 → 0.111.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.
- package/apps/mac-voice/Sources/AgentXVoice/Panel.swift +77 -30
- package/apps/mac-voice/Sources/AgentXVoice/PanelAnswer.swift +3 -2
- package/apps/mac-voice/Sources/AgentXVoice/PillForm.swift +55 -0
- package/apps/mac-voice/Sources/AgentXVoice/PillMenu.swift +8 -7
- package/apps/mac-voice/Sources/AgentXVoice/SettingsLook.swift +2 -2
- package/apps/mac-voice/Sources/AgentXVoice/StatusMenu.swift +5 -6
- package/apps/mac-voice/Sources/AgentXVoice/main.swift +7 -6
- package/dist/{App-4VWAQOVA.js → App-T4Q7SW6M.js} +2 -2
- package/dist/{ChatApp-KOTGUDZH.js → ChatApp-BKUJUIDL.js} +2 -2
- package/dist/{agent-CGRHC2IS.js → agent-YZVEXFE7.js} +2 -2
- package/dist/{board-dashboard-SAYBNLZW.js → board-dashboard-3TVUCOSI.js} +411 -257
- package/dist/board-dashboard-3TVUCOSI.js.map +1 -0
- package/dist/{chunk-UVMCAZL7.js → chunk-4FU4BFCH.js} +2 -2
- package/dist/{chunk-NIW75USA.js → chunk-4NFDDTGA.js} +2 -2
- package/dist/{chunk-2VGYRETU.js → chunk-53OS4TDU.js} +2 -2
- package/dist/{chunk-J32LSOBJ.js → chunk-7UNS34CN.js} +2 -2
- package/dist/chunk-AV7T3SYT.js +111 -0
- package/dist/chunk-AV7T3SYT.js.map +1 -0
- package/dist/chunk-DTQQ4DAY.js +154 -0
- package/dist/chunk-DTQQ4DAY.js.map +1 -0
- package/dist/{chunk-SFPMS55Z.js → chunk-DUBCOGQB.js} +49 -48
- package/dist/chunk-DUBCOGQB.js.map +1 -0
- package/dist/{chunk-BFOB6ERR.js → chunk-DXWDVKMX.js} +2 -2
- package/dist/{chunk-BZKGQMU2.js → chunk-FBODSJU6.js} +2 -2
- package/dist/{chunk-UTV4DRAW.js → chunk-GQMUFSKB.js} +14 -14
- package/dist/{chunk-UTV4DRAW.js.map → chunk-GQMUFSKB.js.map} +1 -1
- package/dist/{chunk-4UCDWEC4.js → chunk-HCTWKWS3.js} +2 -2
- package/dist/{chunk-EC6DKMR5.js → chunk-KDD6FPQ6.js} +238 -238
- package/dist/chunk-KDD6FPQ6.js.map +1 -0
- package/dist/{chunk-5O6PIO7F.js → chunk-LWYKS5JU.js} +2 -2
- package/dist/{chunk-QQAZ6EJP.js → chunk-M2L6S3Z5.js} +2 -2
- package/dist/{chunk-6F2E5NQA.js → chunk-QJP37VVA.js} +2 -2
- package/dist/{chunk-QFP4YZII.js → chunk-RS2T53EC.js} +2 -2
- package/dist/{chunk-E5OV6RTG.js → chunk-RXLU6HJ6.js} +3 -3
- package/dist/chunk-RXLU6HJ6.js.map +1 -0
- package/dist/{chunk-D7M4WQFU.js → chunk-SIOWVLZG.js} +4 -4
- package/dist/chunk-SIOWVLZG.js.map +1 -0
- package/dist/{chunk-BG6SOGKT.js → chunk-U52IS3AF.js} +2 -2
- package/dist/{chunk-RJ7DASOU.js → chunk-UIBUZ2N3.js} +25 -10
- package/dist/chunk-UIBUZ2N3.js.map +1 -0
- package/dist/{chunk-MJWJ3JVA.js → chunk-WSKQUKCF.js} +2 -2
- package/dist/{chunk-S4NZUPIN.js → chunk-WXQQO2PD.js} +2 -2
- package/dist/{chunk-FHI5WPFO.js → chunk-WYSNRZV4.js} +4 -4
- package/dist/chunk-WYSNRZV4.js.map +1 -0
- package/dist/{chunk-CJR26JUI.js → chunk-XEOT2F4C.js} +2 -2
- package/dist/{chunk-3Z5P2CWS.js → chunk-XF26QNAW.js} +2 -2
- package/dist/{chunk-CJL5OPNQ.js → chunk-Z7L74GGT.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/{client-VYMTUZKN.js → client-O7SPKO5X.js} +2 -2
- package/dist/config-ZHQYXFOJ.js +2 -0
- package/dist/config-mutator-RS2NTDNO.js +2 -0
- package/dist/{doctor-GHUPUBET.js → doctor-XP7O45RC.js} +2 -2
- package/dist/{grants-Y667GZAU.js → grants-M4K6WXOO.js} +2 -2
- package/dist/index.d.ts +68 -15
- package/dist/index.js +1 -1
- package/dist/{program-V2JEVJAD.js → program-EZLJIVQX.js} +187 -182
- package/dist/program-EZLJIVQX.js.map +1 -0
- package/dist/{promote-KY3Y2PVU.js → promote-UGWANGI2.js} +2 -2
- package/dist/{query-BYCRYDM3.js → query-ZET7Z5FT.js} +2 -2
- package/dist/registry-UXWOY52B.js +2 -0
- package/dist/request-planner-W5YLKCGG.js +6 -0
- package/dist/request-planner-W5YLKCGG.js.map +1 -0
- package/dist/{review-candidates-56ZPJNXW.js → review-candidates-GU4S5VQH.js} +2 -2
- package/dist/{routing-WKS2CZYF.js → routing-GJ4VXKIC.js} +2 -2
- package/dist/schedule-tool-HD4LWKVC.js +2 -0
- package/dist/scheduler-3LEHZHWJ.js +2 -0
- package/dist/seat-L6XJ2BFA.js +2 -0
- package/dist/select-T7CKKLC2.js +2 -0
- package/dist/{select-73JC2YBN.js.map → select-T7CKKLC2.js.map} +1 -1
- package/dist/{set-enabled-WQAO4BFF.js → set-enabled-U2HGNY2O.js} +2 -2
- package/dist/{surface-usage-CH3SHO77.js → surface-usage-HCJTUS6Z.js} +2 -2
- package/dist/{tool-QDU6MY6B.js → tool-2FMWZB4N.js} +2 -2
- package/dist/{tool-GCPMPPUE.js → tool-TX622HEB.js} +2 -2
- package/dist/wiki-MYJBOJSM.js +2 -0
- package/dist/workspace-setup-HAV4CQV7.js +2 -0
- package/package.json +2 -1
- package/dist/board-dashboard-SAYBNLZW.js.map +0 -1
- package/dist/chunk-3TY6YJHO.js +0 -153
- package/dist/chunk-3TY6YJHO.js.map +0 -1
- package/dist/chunk-D7M4WQFU.js.map +0 -1
- package/dist/chunk-E5OV6RTG.js.map +0 -1
- package/dist/chunk-EC6DKMR5.js.map +0 -1
- package/dist/chunk-FHI5WPFO.js.map +0 -1
- package/dist/chunk-RJ7DASOU.js.map +0 -1
- package/dist/chunk-SFPMS55Z.js.map +0 -1
- package/dist/chunk-UDJAODAB.js +0 -100
- package/dist/chunk-UDJAODAB.js.map +0 -1
- package/dist/config-J6CNV23P.js +0 -2
- package/dist/config-mutator-RGC72OEU.js +0 -2
- package/dist/program-V2JEVJAD.js.map +0 -1
- package/dist/registry-NDFYNQG4.js +0 -2
- package/dist/request-planner-YOUVO3BR.js +0 -2
- package/dist/request-planner-YOUVO3BR.js.map +0 -1
- package/dist/schedule-tool-4L6QAILN.js +0 -2
- package/dist/scheduler-65SE3WJJ.js +0 -2
- package/dist/seat-EO3EVBH3.js +0 -2
- package/dist/select-73JC2YBN.js +0 -2
- package/dist/wiki-CQZE5Z5C.js +0 -2
- package/dist/workspace-setup-EA3G42NY.js +0 -2
- /package/dist/{App-4VWAQOVA.js.map → App-T4Q7SW6M.js.map} +0 -0
- /package/dist/{ChatApp-KOTGUDZH.js.map → ChatApp-BKUJUIDL.js.map} +0 -0
- /package/dist/{agent-CGRHC2IS.js.map → agent-YZVEXFE7.js.map} +0 -0
- /package/dist/{chunk-UVMCAZL7.js.map → chunk-4FU4BFCH.js.map} +0 -0
- /package/dist/{chunk-NIW75USA.js.map → chunk-4NFDDTGA.js.map} +0 -0
- /package/dist/{chunk-2VGYRETU.js.map → chunk-53OS4TDU.js.map} +0 -0
- /package/dist/{chunk-J32LSOBJ.js.map → chunk-7UNS34CN.js.map} +0 -0
- /package/dist/{chunk-BFOB6ERR.js.map → chunk-DXWDVKMX.js.map} +0 -0
- /package/dist/{chunk-BZKGQMU2.js.map → chunk-FBODSJU6.js.map} +0 -0
- /package/dist/{chunk-4UCDWEC4.js.map → chunk-HCTWKWS3.js.map} +0 -0
- /package/dist/{chunk-5O6PIO7F.js.map → chunk-LWYKS5JU.js.map} +0 -0
- /package/dist/{chunk-QQAZ6EJP.js.map → chunk-M2L6S3Z5.js.map} +0 -0
- /package/dist/{chunk-6F2E5NQA.js.map → chunk-QJP37VVA.js.map} +0 -0
- /package/dist/{chunk-QFP4YZII.js.map → chunk-RS2T53EC.js.map} +0 -0
- /package/dist/{chunk-BG6SOGKT.js.map → chunk-U52IS3AF.js.map} +0 -0
- /package/dist/{chunk-MJWJ3JVA.js.map → chunk-WSKQUKCF.js.map} +0 -0
- /package/dist/{chunk-S4NZUPIN.js.map → chunk-WXQQO2PD.js.map} +0 -0
- /package/dist/{chunk-CJR26JUI.js.map → chunk-XEOT2F4C.js.map} +0 -0
- /package/dist/{chunk-3Z5P2CWS.js.map → chunk-XF26QNAW.js.map} +0 -0
- /package/dist/{chunk-CJL5OPNQ.js.map → chunk-Z7L74GGT.js.map} +0 -0
- /package/dist/{client-VYMTUZKN.js.map → client-O7SPKO5X.js.map} +0 -0
- /package/dist/{config-J6CNV23P.js.map → config-ZHQYXFOJ.js.map} +0 -0
- /package/dist/{config-mutator-RGC72OEU.js.map → config-mutator-RS2NTDNO.js.map} +0 -0
- /package/dist/{doctor-GHUPUBET.js.map → doctor-XP7O45RC.js.map} +0 -0
- /package/dist/{grants-Y667GZAU.js.map → grants-M4K6WXOO.js.map} +0 -0
- /package/dist/{promote-KY3Y2PVU.js.map → promote-UGWANGI2.js.map} +0 -0
- /package/dist/{query-BYCRYDM3.js.map → query-ZET7Z5FT.js.map} +0 -0
- /package/dist/{registry-NDFYNQG4.js.map → registry-UXWOY52B.js.map} +0 -0
- /package/dist/{review-candidates-56ZPJNXW.js.map → review-candidates-GU4S5VQH.js.map} +0 -0
- /package/dist/{routing-WKS2CZYF.js.map → routing-GJ4VXKIC.js.map} +0 -0
- /package/dist/{schedule-tool-4L6QAILN.js.map → schedule-tool-HD4LWKVC.js.map} +0 -0
- /package/dist/{scheduler-65SE3WJJ.js.map → scheduler-3LEHZHWJ.js.map} +0 -0
- /package/dist/{seat-EO3EVBH3.js.map → seat-L6XJ2BFA.js.map} +0 -0
- /package/dist/{set-enabled-WQAO4BFF.js.map → set-enabled-U2HGNY2O.js.map} +0 -0
- /package/dist/{surface-usage-CH3SHO77.js.map → surface-usage-HCJTUS6Z.js.map} +0 -0
- /package/dist/{tool-QDU6MY6B.js.map → tool-2FMWZB4N.js.map} +0 -0
- /package/dist/{tool-GCPMPPUE.js.map → tool-TX622HEB.js.map} +0 -0
- /package/dist/{wiki-CQZE5Z5C.js.map → wiki-MYJBOJSM.js.map} +0 -0
- /package/dist/{workspace-setup-EA3G42NY.js.map → workspace-setup-HAV4CQV7.js.map} +0 -0
|
@@ -36,10 +36,15 @@ final class Panel: NSPanel {
|
|
|
36
36
|
let separator = NSBox()
|
|
37
37
|
/// Hidden by close, Esc or the menu until the next talk key.
|
|
38
38
|
var dismissed = false
|
|
39
|
-
///
|
|
40
|
-
/// buttons, dragged and remembered apart from the pill
|
|
41
|
-
///
|
|
42
|
-
|
|
39
|
+
/// Full, or reduced (#457): the orb alone, a small circle with no words
|
|
40
|
+
/// and no buttons, dragged and remembered apart from the pill; with the
|
|
41
|
+
/// character standing in for the orb, the character alone, its speech
|
|
42
|
+
/// bubble gone. A click, a call, an answer to read or a caption opens
|
|
43
|
+
/// the full pill over the reduced form, and once the turn is over it
|
|
44
|
+
/// goes back by itself (PillForm.swift).
|
|
45
|
+
private(set) var form = PillForm()
|
|
46
|
+
/// The reduced form shows now.
|
|
47
|
+
var reduced: Bool { form.reduced }
|
|
43
48
|
/// Told when the pill reduces or opens.
|
|
44
49
|
var onReduced: ((Bool) -> Void)?
|
|
45
50
|
/// Above zero while the app moves or resizes the pill, so only a drag
|
|
@@ -153,7 +158,7 @@ final class Panel: NSPanel {
|
|
|
153
158
|
let onRow = convertToScreen(row.convert(row.bounds, to: nil)).contains(start)
|
|
154
159
|
// Reduced, a click opens the pill; it does not start talking.
|
|
155
160
|
if moved < 4 && onRow {
|
|
156
|
-
if reduced { MainActor.assumeIsolated {
|
|
161
|
+
if reduced { MainActor.assumeIsolated { open(clicked: true) } } else { onClick?() }
|
|
157
162
|
}
|
|
158
163
|
}
|
|
159
164
|
super.mouseUp(with: event)
|
|
@@ -219,7 +224,7 @@ final class Panel: NSPanel {
|
|
|
219
224
|
}
|
|
220
225
|
}
|
|
221
226
|
|
|
222
|
-
/// A call must not be missed behind
|
|
227
|
+
/// A call must not be missed behind the reduced form: it opens the full pill.
|
|
223
228
|
var opensFullPill: Bool {
|
|
224
229
|
switch self {
|
|
225
230
|
case .ringing, .onCall: return true
|
|
@@ -343,7 +348,7 @@ final class Panel: NSPanel {
|
|
|
343
348
|
let above = growth.above
|
|
344
349
|
row.frame = NSRect(x: 0, y: above ? 0 : answerHeight, width: bounds.width, height: h)
|
|
345
350
|
// Reduced, the orb is all there is: in the middle of its circle.
|
|
346
|
-
orb.frame.origin.x = reduced ? (bounds.width - Self.orbFrame) / 2 : 28 - Self.orbFrame / 2
|
|
351
|
+
orb.frame.origin.x = reduced && showsOrb ? (bounds.width - Self.orbFrame) / 2 : 28 - Self.orbFrame / 2
|
|
347
352
|
// Reduced either way, the row is not laid out: nothing of it shows.
|
|
348
353
|
if reduced || small > 0 { return }
|
|
349
354
|
closeButton.frame.origin.x = bounds.width - 28
|
|
@@ -395,27 +400,61 @@ final class Panel: NSPanel {
|
|
|
395
400
|
restorePosition()
|
|
396
401
|
}
|
|
397
402
|
|
|
398
|
-
///
|
|
399
|
-
///
|
|
400
|
-
/// in for the orb.
|
|
403
|
+
/// The menu, or voice.startReduced: the reduced form is the assistant's
|
|
404
|
+
/// from now on, or the full pill is. The two forms keep their own places.
|
|
401
405
|
@MainActor
|
|
402
406
|
func setReduced(_ on: Bool) {
|
|
403
|
-
|
|
407
|
+
let was = reduced
|
|
408
|
+
form.choose(reduced: on)
|
|
409
|
+
guard was != on else { return }
|
|
410
|
+
reform()
|
|
411
|
+
render(current)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/// The full pill over the chosen reduced form, for a while: clicked,
|
|
415
|
+
/// until a turn has run; for a call, an answer or a caption, until it
|
|
416
|
+
/// is over. Then it goes back by itself, in `render`.
|
|
417
|
+
@MainActor
|
|
418
|
+
func open(clicked: Bool = false) {
|
|
419
|
+
guard form.open(clicked: clicked) else { return }
|
|
420
|
+
reform()
|
|
421
|
+
if clicked { render(current) }
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/// The form changed: its shape, and its own place.
|
|
425
|
+
@MainActor
|
|
426
|
+
private func reform() {
|
|
404
427
|
collapse(animated: false)
|
|
405
|
-
|
|
406
|
-
|
|
428
|
+
shape()
|
|
429
|
+
restorePosition()
|
|
430
|
+
invalidateShadow()
|
|
431
|
+
onReduced?(reduced)
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/// The pill's shape for its form: the orb's circle while reduced with
|
|
435
|
+
/// an orb to hold. Reduced with the character, the pill keeps its own
|
|
436
|
+
/// shape and is hidden instead (`render`): the character shows the state.
|
|
437
|
+
@MainActor
|
|
438
|
+
private func shape() {
|
|
439
|
+
let circle = reduced && showsOrb
|
|
440
|
+
clip?.isHidden = circle
|
|
407
441
|
closeButton.isHidden = true
|
|
408
|
-
miniOrbs.isHidden =
|
|
409
|
-
|
|
442
|
+
miniOrbs.isHidden = circle || busyCount == 0
|
|
443
|
+
// Shrunk to its dots, the bubble's shape and size are the
|
|
444
|
+
// character's to set (`attach`), and the full bubble comes back at
|
|
445
|
+
// once for what opens it.
|
|
446
|
+
guard circle || small == 0 else { return }
|
|
447
|
+
(contentView as? Surface)?.shape(circle: circle ? PillPlacement.orbSize.height : nil)
|
|
410
448
|
placing += 1
|
|
411
|
-
setContentSize(
|
|
449
|
+
setContentSize(circle ? PillPlacement.orbSize : Self.size)
|
|
412
450
|
placing -= 1
|
|
413
|
-
restorePosition()
|
|
414
|
-
invalidateShadow()
|
|
415
|
-
render(current)
|
|
416
|
-
onReduced?(on)
|
|
417
451
|
}
|
|
418
452
|
|
|
453
|
+
/// Something to read or to use is on the pill: an answer, the call
|
|
454
|
+
/// buttons, or a caption. The full pill stays for it.
|
|
455
|
+
@MainActor
|
|
456
|
+
private var holds: Bool { expanded || callBar.mode != .hidden || caption != nil }
|
|
457
|
+
|
|
419
458
|
/// The character's speech bubble (#491): the pill sits above `head`,
|
|
420
459
|
/// the top of the character, and goes where it goes, grown or not,
|
|
421
460
|
/// never over it (#554). `small` of the way reduced to its dots,
|
|
@@ -443,12 +482,11 @@ final class Panel: NSPanel {
|
|
|
443
482
|
guard bubble != nil else { return }
|
|
444
483
|
bubble = nil
|
|
445
484
|
isMovableByWindowBackground = true
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
}
|
|
485
|
+
let shrunk = small > 0
|
|
486
|
+
if shrunk { shrink(0) }
|
|
487
|
+
// The dots' shape undone, or the orb's circle back: the shape the
|
|
488
|
+
// form has.
|
|
489
|
+
if shrunk || reduced { shape() }
|
|
452
490
|
restorePosition()
|
|
453
491
|
}
|
|
454
492
|
|
|
@@ -497,10 +535,12 @@ final class Panel: NSPanel {
|
|
|
497
535
|
@MainActor
|
|
498
536
|
func setShowsOrb(_ on: Bool) {
|
|
499
537
|
guard showsOrb != on else { return }
|
|
500
|
-
if !on { setReduced(false) }
|
|
501
538
|
showsOrb = on
|
|
502
539
|
orb.isHidden = !on
|
|
503
540
|
orb.setOnScreen(on && isVisible)
|
|
541
|
+
// Reduced, the form follows the look: the orb's circle, or the
|
|
542
|
+
// character alone with the bubble hidden.
|
|
543
|
+
if reduced { shape(); render(current) }
|
|
504
544
|
if let content = contentView { layoutContent(content.bounds) }
|
|
505
545
|
}
|
|
506
546
|
|
|
@@ -555,8 +595,13 @@ final class Panel: NSPanel {
|
|
|
555
595
|
/// corruption that traps somewhere unrelated an hour later.
|
|
556
596
|
@MainActor
|
|
557
597
|
func render(_ state: State) {
|
|
558
|
-
if reduced && state.opensFullPill { setReduced(false) }
|
|
559
598
|
current = state
|
|
599
|
+
// A call, or a caption to read, must not be missed behind the
|
|
600
|
+
// reduced form: the full pill opens for it.
|
|
601
|
+
if reduced && (state.opensFullPill || caption != nil) { open() }
|
|
602
|
+
// The turn over, and nothing left to read or to use: back to the
|
|
603
|
+
// reduced form by itself (#457).
|
|
604
|
+
if form.rendered(atRest: state.isMeta, holds: holds) { reform() }
|
|
560
605
|
// The agent's colour, except where the state is the message: an
|
|
561
606
|
// error, or notifications held.
|
|
562
607
|
let tint: NSColor
|
|
@@ -593,9 +638,11 @@ final class Panel: NSPanel {
|
|
|
593
638
|
// Grown into an answer, it stays until it collapses, idle or not;
|
|
594
639
|
// so does a pill with agents still busy in its mini orbs.
|
|
595
640
|
// Reduced, the orb is the assistant's place on screen: it stays, idle or not.
|
|
641
|
+
// Reduced with the character, the bubble is gone: the character shows the state.
|
|
596
642
|
// A caption shows like any words; away with none, the hint does not.
|
|
597
643
|
let quiet = state.isMeta && !expanded && busyCount == 0
|
|
598
|
-
|
|
644
|
+
let gone = reduced && !showsOrb
|
|
645
|
+
if dismissed || gone || (quiet && idle == .nothing) || (quiet && idle == .hint && !alwaysVisible && !reduced) { hide() } else { show() }
|
|
599
646
|
// After showing or hiding: a still character draws its bubble's
|
|
600
647
|
// tail only while the bubble is on screen.
|
|
601
648
|
onLook?(state, tint, colors)
|
|
@@ -624,7 +671,7 @@ final class Panel: NSPanel {
|
|
|
624
671
|
@MainActor
|
|
625
672
|
func showCall(_ mode: CallBar.Mode) {
|
|
626
673
|
guard mode != callBar.mode else { return }
|
|
627
|
-
if mode != .hidden {
|
|
674
|
+
if mode != .hidden { open() }
|
|
628
675
|
callBar.show(mode)
|
|
629
676
|
if let content = contentView { layoutContent(content.bounds) }
|
|
630
677
|
}
|
|
@@ -23,8 +23,9 @@ extension Panel {
|
|
|
23
23
|
@MainActor
|
|
24
24
|
func grow(answerHeight: CGFloat) {
|
|
25
25
|
guard !dismissed else { return }
|
|
26
|
-
// An answer to read, or one that asks: the full pill opens for it
|
|
27
|
-
|
|
26
|
+
// An answer to read, or one that asks: the full pill opens for it,
|
|
27
|
+
// and goes back to the reduced form once it has gone.
|
|
28
|
+
open()
|
|
28
29
|
shrink(0)
|
|
29
30
|
let pill = collapsedFrame()
|
|
30
31
|
guard let visible = bubble?.visible ?? visibleFrame(for: pill) else { return }
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/// The pill's two forms (#457): full, or reduced. Reduced, the pill is its
|
|
2
|
+
/// orb alone, a small circle with no words and no buttons; with the
|
|
3
|
+
/// character, it is the character alone, with no speech bubble.
|
|
4
|
+
///
|
|
5
|
+
/// Which form is chosen, which one shows, and when the full form goes back
|
|
6
|
+
/// by itself. The reduced form is a choice (the menu, or voice.startReduced)
|
|
7
|
+
/// that the full pill opens over for a while: a click opens it until a turn
|
|
8
|
+
/// has run; a call, an answer to read or a caption until that is over. Then
|
|
9
|
+
/// it goes back to the reduced form on its own. Free of AppKit, so the
|
|
10
|
+
/// tests can drive it.
|
|
11
|
+
struct PillForm: Equatable {
|
|
12
|
+
/// The reduced form is the one chosen.
|
|
13
|
+
private(set) var chosen = false
|
|
14
|
+
/// The reduced form shows now.
|
|
15
|
+
private(set) var reduced = false
|
|
16
|
+
/// Open over the reduced form, something has happened since that sends
|
|
17
|
+
/// it back once over: a turn, a call, an answer or a caption.
|
|
18
|
+
private(set) var pending = false
|
|
19
|
+
|
|
20
|
+
/// The menu or the setting: the reduced form, or the full one, from now on.
|
|
21
|
+
mutating func choose(reduced on: Bool) {
|
|
22
|
+
chosen = on
|
|
23
|
+
reduced = on
|
|
24
|
+
pending = false
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/// The full form over the reduced one. A click opens it until a turn
|
|
28
|
+
/// has run; a call, an answer or a caption until it is over. True when
|
|
29
|
+
/// the form changed.
|
|
30
|
+
@discardableResult
|
|
31
|
+
mutating func open(clicked: Bool = false) -> Bool {
|
|
32
|
+
guard reduced else { return false }
|
|
33
|
+
reduced = false
|
|
34
|
+
pending = !clicked
|
|
35
|
+
return true
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/// What is on screen now: `atRest` while idle (or holding
|
|
39
|
+
/// notifications), `holds` while there is something to read or to use:
|
|
40
|
+
/// an answer, the call buttons, a caption. True when the full form
|
|
41
|
+
/// goes back to the reduced one: it is chosen, a turn has run or
|
|
42
|
+
/// something was held since it opened, and that is over.
|
|
43
|
+
@discardableResult
|
|
44
|
+
mutating func rendered(atRest: Bool, holds: Bool) -> Bool {
|
|
45
|
+
guard chosen, !reduced else { return false }
|
|
46
|
+
if !atRest || holds {
|
|
47
|
+
pending = true
|
|
48
|
+
return false
|
|
49
|
+
}
|
|
50
|
+
guard pending else { return false }
|
|
51
|
+
reduced = true
|
|
52
|
+
pending = false
|
|
53
|
+
return true
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -14,12 +14,13 @@ enum PillMenu {
|
|
|
14
14
|
!isChecked(showPill: showPill, visible: visible)
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
/// The item that reduces the pill
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
/// The item that reduces the pill, or brings the full one back: to its
|
|
18
|
+
/// orb, or with the character (which stands in for the orb) to the
|
|
19
|
+
/// character alone, without its speech bubble. The title follows what
|
|
20
|
+
/// is on screen, so a pill open for a while over the chosen orb still
|
|
21
|
+
/// offers to reduce.
|
|
22
|
+
static func reduceTitle(reduced: Bool, character: Bool = false) -> String {
|
|
23
|
+
if character { return reduced ? "Show speech bubble" : "Reduce to character" }
|
|
24
|
+
return reduced ? "Show full pill" : "Reduce to orb"
|
|
20
25
|
}
|
|
21
|
-
|
|
22
|
-
/// Only a pill that has its orb can be reduced to it: while the
|
|
23
|
-
/// character stands in for the orb, there is nothing to reduce to.
|
|
24
|
-
static func canReduce(showsOrb: Bool) -> Bool { showsOrb }
|
|
25
26
|
}
|
|
@@ -69,8 +69,8 @@ struct LookSection: View {
|
|
|
69
69
|
Text("Character").tag("character")
|
|
70
70
|
}
|
|
71
71
|
if let startReduced {
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
// The orb alone, or the character alone without its bubble.
|
|
73
|
+
Toggle("Start reduced", isOn: startReduced)
|
|
74
74
|
}
|
|
75
75
|
if let stroll {
|
|
76
76
|
Toggle("Character strolls when idle", isOn: stroll)
|
|
@@ -49,10 +49,9 @@ final class StatusMenu: NSObject, NSMenuDelegate {
|
|
|
49
49
|
var onResetPosition: (() -> Void)?
|
|
50
50
|
/// Whether the pill is on screen, for "Hide pill" and "Show floating pill".
|
|
51
51
|
var pillVisible: () -> Bool = { false }
|
|
52
|
-
/// Whether the pill is reduced to its orb,
|
|
52
|
+
/// Whether the pill is reduced: to its orb, or to the character alone.
|
|
53
53
|
var pillReduced: () -> Bool = { false }
|
|
54
|
-
|
|
55
|
-
/// Reduce the pill to its orb (true), or open it again.
|
|
54
|
+
/// Reduce the pill (true), or open it again.
|
|
56
55
|
var onReduce: ((Bool) -> Void)?
|
|
57
56
|
/// The character look: whether the character is on screen. Nil with
|
|
58
57
|
/// the orb look.
|
|
@@ -253,9 +252,9 @@ final class StatusMenu: NSObject, NSMenuDelegate {
|
|
|
253
252
|
let pill = action("Show floating pill", #selector(togglePill), key: "")
|
|
254
253
|
pill.state = PillMenu.isChecked(showPill: Config.showPill, visible: pillVisible()) ? .on : .off
|
|
255
254
|
menu.addItem(pill)
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
255
|
+
// The pill to its orb, or the character to itself without its bubble.
|
|
256
|
+
menu.addItem(action(PillMenu.reduceTitle(reduced: pillReduced(), character: characterVisible() != nil),
|
|
257
|
+
#selector(toggleReduce), key: ""))
|
|
259
258
|
let orb = action("Animated orb", #selector(toggleOrb), key: "")
|
|
260
259
|
orb.state = Config.animatedOrb ? .on : .off
|
|
261
260
|
menu.addItem(orb)
|
|
@@ -223,10 +223,11 @@ final class App: NSObject, NSApplicationDelegate {
|
|
|
223
223
|
character.animates = IdlePlay.gap(saved.general.animations)
|
|
224
224
|
if !asCharacter { panel.detach() }
|
|
225
225
|
idleWords()
|
|
226
|
-
// voice.startReduced is how the assistant starts: read once.
|
|
226
|
+
// voice.startReduced is how the assistant starts: read once. With
|
|
227
|
+
// the character, it starts without its bubble.
|
|
227
228
|
if !startApplied {
|
|
228
229
|
startApplied = true
|
|
229
|
-
if saved.general.startReduced == true
|
|
230
|
+
if saved.general.startReduced == true { panel.summon(); panel.setReduced(true) }
|
|
230
231
|
}
|
|
231
232
|
if settingsWindow.model.recording == nil { registerHotkeys() }
|
|
232
233
|
// Colours may have changed.
|
|
@@ -439,12 +440,12 @@ final class App: NSObject, NSApplicationDelegate {
|
|
|
439
440
|
statusMenu.pillVisible = { [weak self] in self?.panel.isVisible ?? false }
|
|
440
441
|
statusMenu.onHidePill = { [weak self] in self?.dismissPill() }
|
|
441
442
|
statusMenu.pillReduced = { [weak self] in self?.panel.reduced ?? false }
|
|
442
|
-
statusMenu.canReduce = { [weak self] in PillMenu.canReduce(showsOrb: self?.panel.showsOrb ?? true) }
|
|
443
443
|
statusMenu.onReduce = { [weak self] on in
|
|
444
444
|
guard let self else { return }
|
|
445
|
-
Log.info("pill: \(on ? "reduced
|
|
446
|
-
// Asking for the
|
|
447
|
-
|
|
445
|
+
Log.info("pill: \(on ? "reduced" : "opened")")
|
|
446
|
+
// Asking for the reduced form brings back a pill, or a
|
|
447
|
+
// character, that was dismissed.
|
|
448
|
+
if on { self.summonPill() }
|
|
448
449
|
self.panel.setReduced(on)
|
|
449
450
|
}
|
|
450
451
|
statusMenu.characterVisible = { [weak self] in self?.character.onScreen }
|
|
@@ -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-
|
|
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-XEOT2F4C.js";import"./chunk-SIOWVLZG.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(`
|
|
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-
|
|
8
|
+
//# sourceMappingURL=App-T4Q7SW6M.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-
|
|
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-XEOT2F4C.js";import"./chunk-SIOWVLZG.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(`
|
|
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-
|
|
7
|
+
//# sourceMappingURL=ChatApp-BKUJUIDL.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{A as a,B as b,C as c}from"./chunk-
|
|
2
|
-
//# sourceMappingURL=agent-
|
|
1
|
+
import{A as a,B as b,C as c}from"./chunk-HCTWKWS3.js";import"./chunk-SFQUP3BP.js";import"./chunk-QOYAX2FT.js";import"./chunk-5MUJZODV.js";import"./chunk-7I7IEX4S.js";import"./chunk-JHCI6XCJ.js";import"./chunk-DSYKYZMT.js";import"./chunk-QIJLFPWE.js";export{a as createAgentContext,b as generate,c as generateStream};
|
|
2
|
+
//# sourceMappingURL=agent-YZVEXFE7.js.map
|