agentix-cli 0.101.1 → 0.102.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/Character.swift +9 -3
- package/apps/mac-voice/Sources/AgentXVoice/Guide.swift +12 -5
- package/apps/mac-voice/Sources/AgentXVoice/GuideMath.swift +11 -0
- package/apps/mac-voice/Sources/AgentXVoice/Panel.swift +19 -2
- package/apps/mac-voice/Sources/AgentXVoice/main.swift +18 -2
- package/dist/{chunk-GOPJG2RG.js → chunk-5YRB5E2C.js} +180 -180
- package/dist/{chunk-GOPJG2RG.js.map → chunk-5YRB5E2C.js.map} +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{program-2G53UFIU.js → program-SHI2N2YH.js} +5 -5
- package/dist/program-SHI2N2YH.js.map +1 -0
- package/dist/web/activity-graph.global.js +13 -13
- package/dist/web/activity-graph.global.js.map +1 -1
- package/package.json +1 -1
- package/dist/program-2G53UFIU.js.map +0 -1
|
@@ -69,6 +69,11 @@ final class CharacterHost {
|
|
|
69
69
|
private var carried: (from: NSPoint, rest: CGPoint)?
|
|
70
70
|
/// What the answering agent sent it to show (#482), and its mark.
|
|
71
71
|
private let guide = CharacterGuide()
|
|
72
|
+
/// Sent somewhere, and what its bubble says there (#562).
|
|
73
|
+
var sent: Bool { guide.showing != nil }
|
|
74
|
+
var caption: String? { guide.caption }
|
|
75
|
+
/// Told when it is sent somewhere, to its next stop or back.
|
|
76
|
+
var onGuide: (() -> Void)?
|
|
72
77
|
/// A still picture: Reduce Motion, or "Animated orb" off.
|
|
73
78
|
private var still: Bool { !animated || reduceMotion }
|
|
74
79
|
/// The look is the character: whether it is on screen. Nil with the orb.
|
|
@@ -147,12 +152,13 @@ final class CharacterHost {
|
|
|
147
152
|
}
|
|
148
153
|
|
|
149
154
|
/// Go beside `rect` and mark it, or with nil go back to where it rests.
|
|
150
|
-
func guide(to rect: NSRect?, mark kind: GuideMath.Mark = .none) {
|
|
155
|
+
func guide(to rect: NSRect?, mark kind: GuideMath.Mark = .none, caption: String? = nil) {
|
|
151
156
|
if shown, !hidden, carried == nil, let rect {
|
|
152
|
-
guide.show(rect, kind, color: view.stops[2], animated: !still)
|
|
157
|
+
guide.show(rect, kind, caption: caption, color: view.stops[2], animated: !still)
|
|
153
158
|
} else {
|
|
154
159
|
guide.end()
|
|
155
160
|
}
|
|
161
|
+
onGuide?()
|
|
156
162
|
redraw()
|
|
157
163
|
}
|
|
158
164
|
|
|
@@ -192,7 +198,7 @@ final class CharacterHost {
|
|
|
192
198
|
switch phase {
|
|
193
199
|
case .began:
|
|
194
200
|
let mouse = pointerSource()
|
|
195
|
-
if body.contains(mouse) { guide.end(glide: false); carried = (mouse, CGPoint(x: body.midX, y: rest.y)) }
|
|
201
|
+
if body.contains(mouse) { guide.end(glide: false); onGuide?(); carried = (mouse, CGPoint(x: body.midX, y: rest.y)) }
|
|
196
202
|
case .moved:
|
|
197
203
|
if carried != nil { tick() }
|
|
198
204
|
case .ended:
|
|
@@ -10,6 +10,9 @@ enum GuideClient {
|
|
|
10
10
|
/// Nil: back to where it rests.
|
|
11
11
|
let rect: Rect?
|
|
12
12
|
let mark: String
|
|
13
|
+
/// What its bubble says at the stop (#562). Nil: no bubble there,
|
|
14
|
+
/// and a daemon too old to send one.
|
|
15
|
+
let text: String?
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
/// GET /voice/guide: the command after `seq`, as soon as there is
|
|
@@ -34,8 +37,8 @@ final class GuideWatcher {
|
|
|
34
37
|
private var task: Task<Void, Never>?
|
|
35
38
|
/// The character is on screen.
|
|
36
39
|
var wanted: (() -> Bool)?
|
|
37
|
-
/// Show this, in AppKit coordinates, or go home.
|
|
38
|
-
var onCommand: ((NSRect?, GuideMath.Mark) -> Void)?
|
|
40
|
+
/// Show this, in AppKit coordinates, with this caption, or go home.
|
|
41
|
+
var onCommand: ((NSRect?, GuideMath.Mark, String?) -> Void)?
|
|
39
42
|
|
|
40
43
|
/// (Re)start the wait. Called again when the character comes on screen
|
|
41
44
|
/// or leaves it, so a wait already open is ended: cancelling it closes
|
|
@@ -53,7 +56,7 @@ final class GuideWatcher {
|
|
|
53
56
|
private func turn() async {
|
|
54
57
|
guard wanted?() == true, let command = await GuideClient.next(after: seq) else {
|
|
55
58
|
// Hidden, or the daemon is gone: nothing is left on screen.
|
|
56
|
-
if away { away = false; onCommand?(nil, .none) }
|
|
59
|
+
if away { away = false; onCommand?(nil, .none, nil) }
|
|
57
60
|
try? await Task.sleep(nanoseconds: 2_000_000_000)
|
|
58
61
|
return
|
|
59
62
|
}
|
|
@@ -65,7 +68,7 @@ final class GuideWatcher {
|
|
|
65
68
|
}
|
|
66
69
|
away = rect != nil
|
|
67
70
|
Log.info("guide: \(rect.map { "to \(Int($0.minX)),\(Int($0.minY)) \(Int($0.width))x\(Int($0.height)) \(command.mark)" } ?? "home")")
|
|
68
|
-
onCommand?(rect, GuideMath.Mark(rawValue: command.mark) ?? .box)
|
|
71
|
+
onCommand?(rect, GuideMath.Mark(rawValue: command.mark) ?? .box, rect == nil ? nil : command.text)
|
|
69
72
|
}
|
|
70
73
|
}
|
|
71
74
|
|
|
@@ -74,13 +77,16 @@ final class GuideWatcher {
|
|
|
74
77
|
@MainActor
|
|
75
78
|
final class CharacterGuide {
|
|
76
79
|
private(set) var showing: NSRect?
|
|
80
|
+
/// What its bubble says there (#562).
|
|
81
|
+
private(set) var caption: String?
|
|
77
82
|
private let mark = GuideMark()
|
|
78
83
|
/// On its way up or down, to what it shows or back; and the last frame.
|
|
79
84
|
private var gliding = false
|
|
80
85
|
private var ticked = 0.0
|
|
81
86
|
|
|
82
|
-
func show(_ rect: NSRect, _ kind: GuideMath.Mark, color: NSColor, animated: Bool) {
|
|
87
|
+
func show(_ rect: NSRect, _ kind: GuideMath.Mark, caption text: String?, color: NSColor, animated: Bool) {
|
|
83
88
|
showing = rect
|
|
89
|
+
caption = text
|
|
84
90
|
gliding = true
|
|
85
91
|
mark.show(kind, around: rect, color: color, animated: animated)
|
|
86
92
|
}
|
|
@@ -89,6 +95,7 @@ final class CharacterGuide {
|
|
|
89
95
|
func end(glide: Bool = true) {
|
|
90
96
|
gliding = glide && showing != nil
|
|
91
97
|
showing = nil
|
|
98
|
+
caption = nil
|
|
92
99
|
mark.hide()
|
|
93
100
|
}
|
|
94
101
|
|
|
@@ -40,6 +40,17 @@ enum GuideMath {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
/// What the bubble says while the assistant has nothing to say (#562).
|
|
44
|
+
enum Idle: Equatable { case hint, caption(String), nothing }
|
|
45
|
+
|
|
46
|
+
/// At a stop the bubble says the command's caption, and with none
|
|
47
|
+
/// there is no bubble; the idle hint is for where it rests, not for
|
|
48
|
+
/// a stop, the way there or a play. `away`: sent somewhere, or playing.
|
|
49
|
+
static func idle(caption: String?, away: Bool) -> Idle {
|
|
50
|
+
if let caption, !caption.isEmpty { return .caption(caption) }
|
|
51
|
+
return away ? .nothing : .hint
|
|
52
|
+
}
|
|
53
|
+
|
|
43
54
|
/// One frame of its way up or down to where it is sent: most of the
|
|
44
55
|
/// way in a third of a second, and there once it is within a point.
|
|
45
56
|
static func glide(_ y: CGFloat, toward goal: CGFloat, dt: Double) -> CGFloat {
|
|
@@ -130,6 +130,10 @@ final class Panel: NSPanel {
|
|
|
130
130
|
var small: CGFloat = 0
|
|
131
131
|
let dots = BubbleDots()
|
|
132
132
|
|
|
133
|
+
/// What the bubble says while the assistant is idle (#562): the hint,
|
|
134
|
+
/// the caption of what the character shows, or nothing while it is away.
|
|
135
|
+
private(set) var idle = GuideMath.Idle.hint
|
|
136
|
+
|
|
133
137
|
/// Told of every state rendered, so the menu-bar icon can follow.
|
|
134
138
|
var onRender: ((State) -> Void)?
|
|
135
139
|
|
|
@@ -569,7 +573,10 @@ final class Panel: NSPanel {
|
|
|
569
573
|
}
|
|
570
574
|
orb.show(state.orbPhase, tint: tint, colors: colors)
|
|
571
575
|
|
|
572
|
-
if state.isMeta {
|
|
576
|
+
if state.isMeta, case .caption(let words) = idle {
|
|
577
|
+
label.textColor = .labelColor
|
|
578
|
+
setText(words)
|
|
579
|
+
} else if state.isMeta {
|
|
573
580
|
stopMarquee()
|
|
574
581
|
label.attributedStringValue = Brand.metaString(state.text, color: state.color)
|
|
575
582
|
label.frame.origin.x = 0
|
|
@@ -583,7 +590,9 @@ final class Panel: NSPanel {
|
|
|
583
590
|
// Grown into an answer, it stays until it collapses, idle or not;
|
|
584
591
|
// so does a pill with agents still busy in its mini orbs.
|
|
585
592
|
// Reduced, the orb is the assistant's place on screen: it stays, idle or not.
|
|
586
|
-
|
|
593
|
+
// A caption shows like any words; away with none, the hint does not.
|
|
594
|
+
let quiet = state.isMeta && !expanded && busyCount == 0
|
|
595
|
+
if dismissed || (quiet && idle == .nothing) || (quiet && idle == .hint && !alwaysVisible && !reduced) { hide() } else { show() }
|
|
587
596
|
// After showing or hiding: a still character draws its bubble's
|
|
588
597
|
// tail only while the bubble is on screen.
|
|
589
598
|
onLook?(state, tint, colors)
|
|
@@ -591,6 +600,14 @@ final class Panel: NSPanel {
|
|
|
591
600
|
onRender?(state)
|
|
592
601
|
}
|
|
593
602
|
|
|
603
|
+
/// The character was sent somewhere or back, or a play began or ended.
|
|
604
|
+
@MainActor
|
|
605
|
+
func setIdle(_ words: GuideMath.Idle) {
|
|
606
|
+
guard words != idle else { return }
|
|
607
|
+
idle = words
|
|
608
|
+
render(current)
|
|
609
|
+
}
|
|
610
|
+
|
|
594
611
|
/// On screen with something to use: an answer, an error or the call
|
|
595
612
|
/// buttons. The character does not play with the pointer then (#537).
|
|
596
613
|
@MainActor
|
|
@@ -86,6 +86,8 @@ final class App: NSObject, NSApplicationDelegate {
|
|
|
86
86
|
// An agent ringing the owner (#321).
|
|
87
87
|
private let callWatcher = CallWatcher()
|
|
88
88
|
private let guideWatcher = GuideWatcher()
|
|
89
|
+
/// A play runs, or its picture is being taken (#562).
|
|
90
|
+
private var playing = false
|
|
89
91
|
private let ringer = Ringer()
|
|
90
92
|
/// The call ringing on the pill now.
|
|
91
93
|
private var ringingCall: IncomingCall?
|
|
@@ -236,6 +238,12 @@ final class App: NSObject, NSApplicationDelegate {
|
|
|
236
238
|
&& !busy && !recorder.isRecording && !play.running
|
|
237
239
|
}
|
|
238
240
|
|
|
241
|
+
/// What the idle bubble says (#562): no hint at a guide stop, on the
|
|
242
|
+
/// way there or during a play; the stop's caption if it has one.
|
|
243
|
+
private func idleWords() {
|
|
244
|
+
panel.setIdle(GuideMath.idle(caption: character.caption, away: character.sent || playing))
|
|
245
|
+
}
|
|
246
|
+
|
|
239
247
|
/// "Play on this page" (#505): one picture of the character's screen, the
|
|
240
248
|
/// lines of text read on it, and the character plays on the picture,
|
|
241
249
|
/// differently each time. The page itself is never touched.
|
|
@@ -252,12 +260,17 @@ final class App: NSObject, NSApplicationDelegate {
|
|
|
252
260
|
}
|
|
253
261
|
let stops = character.stops, size = screen.frame.size
|
|
254
262
|
let start = PlayMath.Point(x: foot.x - screen.frame.minX, y: screen.frame.maxY - foot.y)
|
|
255
|
-
// Off its edge, so it is not in the picture twice
|
|
263
|
+
// Off its edge, so it is not in the picture twice; its idle
|
|
264
|
+
// bubble too, which would stay in the picture all the play long.
|
|
256
265
|
character.setShown(false)
|
|
266
|
+
playing = true
|
|
267
|
+
idleWords()
|
|
257
268
|
Task { @MainActor in
|
|
258
269
|
try? await Task.sleep(nanoseconds: 150_000_000)
|
|
259
270
|
guard let picture = PlayRead.picture(of: screen), !busy, !recorder.isRecording else {
|
|
271
|
+
playing = false
|
|
260
272
|
character.setShown(settings?.general.look == "character")
|
|
273
|
+
idleWords()
|
|
261
274
|
return
|
|
262
275
|
}
|
|
263
276
|
play.start(picture: picture, on: screen, stops: stops, at: start)
|
|
@@ -403,7 +416,9 @@ final class App: NSObject, NSApplicationDelegate {
|
|
|
403
416
|
statusMenu.onPlay = { [weak self] in self?.startPlay() }
|
|
404
417
|
play.onEnd = { [weak self] in
|
|
405
418
|
guard let self else { return }
|
|
419
|
+
self.playing = false
|
|
406
420
|
self.character.setShown(self.settings?.general.look == "character")
|
|
421
|
+
self.idleWords()
|
|
407
422
|
}
|
|
408
423
|
panel.onShown = { [weak self] in self?.character.redraw() }
|
|
409
424
|
panel.onDismiss = { [weak self] in self?.dismissPill() }
|
|
@@ -511,7 +526,8 @@ final class App: NSObject, NSApplicationDelegate {
|
|
|
511
526
|
callWatcher.start()
|
|
512
527
|
// The answering agent sends the character to something (#482).
|
|
513
528
|
guideWatcher.wanted = { [weak self] in self?.character.onScreen == true }
|
|
514
|
-
guideWatcher.onCommand = { [weak self] rect, mark in self?.character.guide(to: rect, mark: mark) }
|
|
529
|
+
guideWatcher.onCommand = { [weak self] rect, mark, caption in self?.character.guide(to: rect, mark: mark, caption: caption) }
|
|
530
|
+
character.onGuide = { [weak self] in self?.idleWords() }
|
|
515
531
|
guideWatcher.start()
|
|
516
532
|
character.onScreenChanged = { [weak self] in self?.guideWatcher.start() }
|
|
517
533
|
|