agentix-cli 0.96.1 → 0.98.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 +4 -1
- package/apps/mac-voice/Sources/AgentXVoice/CharacterSim.swift +50 -4
- package/apps/mac-voice/Sources/AgentXVoice/PlayActs.swift +164 -0
- package/apps/mac-voice/Sources/AgentXVoice/PlayMath.swift +94 -46
- package/apps/mac-voice/Sources/AgentXVoice/PlayMotion.swift +110 -0
- package/apps/mac-voice/Sources/AgentXVoice/PlayStage.swift +56 -3
- package/apps/mac-voice/Sources/AgentXVoice/SettingsLook.swift +6 -0
- package/apps/mac-voice/Sources/AgentXVoice/SettingsWindow.swift +4 -1
- package/apps/mac-voice/Sources/AgentXVoice/VoiceSettings.swift +18 -1
- package/apps/mac-voice/Sources/AgentXVoice/main.swift +24 -10
- package/dist/{App-UHSIO3UE.js → App-XLQDP26J.js} +2 -2
- package/dist/{ChatApp-LLTFBLJY.js → ChatApp-DRDUXZ66.js} +2 -2
- package/dist/{agent-6RJ633MQ.js → agent-QHM3J2XS.js} +2 -2
- package/dist/{board-dashboard-A3ZEI4F6.js → board-dashboard-AIT26JTK.js} +4 -4
- package/dist/{chunk-ZZSNM2RI.js → chunk-4BCAH7XI.js} +2 -2
- package/dist/{chunk-ALWMYA2B.js → chunk-B32A6OOY.js} +2 -2
- package/dist/{chunk-VO2GNAKB.js → chunk-BERHVF3T.js} +2 -2
- package/dist/{chunk-6DCY2JCB.js → chunk-BHKWXFJD.js} +5 -5
- package/dist/{chunk-4XHKJZLJ.js → chunk-BTLW2RML.js} +2 -2
- package/dist/{chunk-DU6536CC.js → chunk-DRUEPGLP.js} +2 -2
- package/dist/{chunk-KIGFWUKP.js → chunk-DXJRMPGH.js} +2 -2
- package/dist/{chunk-IPDEWVVT.js → chunk-GJ5EJVMZ.js} +2 -2
- package/dist/{chunk-EBVB727L.js → chunk-IQJ7UZVV.js} +2 -2
- package/dist/{chunk-ZVW645NU.js → chunk-J4JVKVEK.js} +2 -2
- package/dist/{chunk-TE44E733.js → chunk-J64VIHL5.js} +2 -2
- package/dist/{chunk-XEKZKH3W.js → chunk-JREA25GJ.js} +4 -4
- package/dist/chunk-JREA25GJ.js.map +1 -0
- package/dist/{chunk-KEKO4S45.js → chunk-JZJ7AZJD.js} +2 -2
- package/dist/{chunk-MKF6HSBA.js → chunk-LXJGLNVG.js} +2 -2
- package/dist/{chunk-QZIEYDIY.js → chunk-OFVMUBIP.js} +2 -2
- package/dist/{chunk-GHXSBJZS.js → chunk-QUU5RJ7D.js} +2 -2
- package/dist/{chunk-ZYJDAT3E.js → chunk-S2GPUSBU.js} +2 -2
- package/dist/{chunk-J2MHITWR.js → chunk-SJMOZY7Y.js} +2 -2
- package/dist/{chunk-MNS4SBRR.js → chunk-WWCVQHV3.js} +149 -149
- package/dist/chunk-WWCVQHV3.js.map +1 -0
- package/dist/{chunk-44UGVUN7.js → chunk-YYCFI4VP.js} +2 -2
- package/dist/{chunk-6NECC6YS.js → chunk-Z4FY64BS.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/{client-ARS6ZFT2.js → client-BLUCLNIS.js} +2 -2
- package/dist/{config-XO5Z3BO5.js → config-ZUMI4IY4.js} +2 -2
- package/dist/config-mutator-S3CD2IWQ.js +2 -0
- package/dist/{doctor-VUK3JE6Z.js → doctor-XGQW5SMD.js} +2 -2
- package/dist/index.d.ts +7 -1
- package/dist/index.js +1 -1
- package/dist/{program-HUQB4IIO.js → program-FK7REU2M.js} +117 -117
- package/dist/program-FK7REU2M.js.map +1 -0
- package/dist/{promote-UGQXA4KV.js → promote-K5LP5Q6Z.js} +2 -2
- package/dist/{query-DL7RHPMA.js → query-LHXSINM2.js} +2 -2
- package/dist/{registry-YIPKBRBH.js → registry-OQUO6NCW.js} +2 -2
- package/dist/{request-planner-L2FAVNKP.js → request-planner-TW5OCKTF.js} +2 -2
- package/dist/{review-candidates-RPUP4XBU.js → review-candidates-EFELFOSY.js} +2 -2
- package/dist/{routing-G66SVTRO.js → routing-TSRZLD7B.js} +2 -2
- package/dist/schedule-tool-JUHRVU5D.js +2 -0
- package/dist/scheduler-EHJPTULN.js +2 -0
- package/dist/{seat-ZPH7DA5L.js → seat-NIPWHLKC.js} +2 -2
- package/dist/{select-2WTV2BI2.js → select-UAKDLN76.js} +2 -2
- package/dist/{set-enabled-KI2FINQD.js → set-enabled-74DLXMSM.js} +2 -2
- package/dist/{tool-ZFQ46KU3.js → tool-CEBL57UW.js} +2 -2
- package/dist/{tool-2P4LRWN4.js → tool-TEGHFORD.js} +2 -2
- package/dist/wiki-WOK4SCB7.js +2 -0
- package/package.json +1 -1
- package/dist/chunk-MNS4SBRR.js.map +0 -1
- package/dist/chunk-XEKZKH3W.js.map +0 -1
- package/dist/config-mutator-MJX4EIYV.js +0 -2
- package/dist/program-HUQB4IIO.js.map +0 -1
- package/dist/schedule-tool-FOWPIWKP.js +0 -2
- package/dist/scheduler-GFVUPAD6.js +0 -2
- package/dist/wiki-XATGT3DI.js +0 -2
- /package/dist/{App-UHSIO3UE.js.map → App-XLQDP26J.js.map} +0 -0
- /package/dist/{ChatApp-LLTFBLJY.js.map → ChatApp-DRDUXZ66.js.map} +0 -0
- /package/dist/{agent-6RJ633MQ.js.map → agent-QHM3J2XS.js.map} +0 -0
- /package/dist/{board-dashboard-A3ZEI4F6.js.map → board-dashboard-AIT26JTK.js.map} +0 -0
- /package/dist/{chunk-ZZSNM2RI.js.map → chunk-4BCAH7XI.js.map} +0 -0
- /package/dist/{chunk-ALWMYA2B.js.map → chunk-B32A6OOY.js.map} +0 -0
- /package/dist/{chunk-VO2GNAKB.js.map → chunk-BERHVF3T.js.map} +0 -0
- /package/dist/{chunk-6DCY2JCB.js.map → chunk-BHKWXFJD.js.map} +0 -0
- /package/dist/{chunk-4XHKJZLJ.js.map → chunk-BTLW2RML.js.map} +0 -0
- /package/dist/{chunk-DU6536CC.js.map → chunk-DRUEPGLP.js.map} +0 -0
- /package/dist/{chunk-KIGFWUKP.js.map → chunk-DXJRMPGH.js.map} +0 -0
- /package/dist/{chunk-IPDEWVVT.js.map → chunk-GJ5EJVMZ.js.map} +0 -0
- /package/dist/{chunk-EBVB727L.js.map → chunk-IQJ7UZVV.js.map} +0 -0
- /package/dist/{chunk-ZVW645NU.js.map → chunk-J4JVKVEK.js.map} +0 -0
- /package/dist/{chunk-TE44E733.js.map → chunk-J64VIHL5.js.map} +0 -0
- /package/dist/{chunk-KEKO4S45.js.map → chunk-JZJ7AZJD.js.map} +0 -0
- /package/dist/{chunk-MKF6HSBA.js.map → chunk-LXJGLNVG.js.map} +0 -0
- /package/dist/{chunk-QZIEYDIY.js.map → chunk-OFVMUBIP.js.map} +0 -0
- /package/dist/{chunk-GHXSBJZS.js.map → chunk-QUU5RJ7D.js.map} +0 -0
- /package/dist/{chunk-ZYJDAT3E.js.map → chunk-S2GPUSBU.js.map} +0 -0
- /package/dist/{chunk-J2MHITWR.js.map → chunk-SJMOZY7Y.js.map} +0 -0
- /package/dist/{chunk-44UGVUN7.js.map → chunk-YYCFI4VP.js.map} +0 -0
- /package/dist/{chunk-6NECC6YS.js.map → chunk-Z4FY64BS.js.map} +0 -0
- /package/dist/{client-ARS6ZFT2.js.map → client-BLUCLNIS.js.map} +0 -0
- /package/dist/{config-XO5Z3BO5.js.map → config-ZUMI4IY4.js.map} +0 -0
- /package/dist/{config-mutator-MJX4EIYV.js.map → config-mutator-S3CD2IWQ.js.map} +0 -0
- /package/dist/{doctor-VUK3JE6Z.js.map → doctor-XGQW5SMD.js.map} +0 -0
- /package/dist/{promote-UGQXA4KV.js.map → promote-K5LP5Q6Z.js.map} +0 -0
- /package/dist/{query-DL7RHPMA.js.map → query-LHXSINM2.js.map} +0 -0
- /package/dist/{registry-YIPKBRBH.js.map → registry-OQUO6NCW.js.map} +0 -0
- /package/dist/{request-planner-L2FAVNKP.js.map → request-planner-TW5OCKTF.js.map} +0 -0
- /package/dist/{review-candidates-RPUP4XBU.js.map → review-candidates-EFELFOSY.js.map} +0 -0
- /package/dist/{routing-G66SVTRO.js.map → routing-TSRZLD7B.js.map} +0 -0
- /package/dist/{schedule-tool-FOWPIWKP.js.map → schedule-tool-JUHRVU5D.js.map} +0 -0
- /package/dist/{scheduler-GFVUPAD6.js.map → scheduler-EHJPTULN.js.map} +0 -0
- /package/dist/{seat-ZPH7DA5L.js.map → seat-NIPWHLKC.js.map} +0 -0
- /package/dist/{select-2WTV2BI2.js.map → select-UAKDLN76.js.map} +0 -0
- /package/dist/{set-enabled-KI2FINQD.js.map → set-enabled-74DLXMSM.js.map} +0 -0
- /package/dist/{tool-ZFQ46KU3.js.map → tool-CEBL57UW.js.map} +0 -0
- /package/dist/{tool-2P4LRWN4.js.map → tool-TEGHFORD.js.map} +0 -0
- /package/dist/{wiki-XATGT3DI.js.map → wiki-WOK4SCB7.js.map} +0 -0
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
import AppKit
|
|
2
2
|
|
|
3
3
|
/// What play mode (#505) draws over the picture: the page's colour where
|
|
4
|
-
/// words are gone, the cloth, and the character. The context is flipped,
|
|
4
|
+
/// words are gone, the pieces that moved, the cloth, and the character. The context is flipped,
|
|
5
5
|
/// in the picture's points.
|
|
6
6
|
enum PlayDraw {
|
|
7
|
-
static func draw(_ frame: Play.Frame, in ctx: CGContext, stops: [NSColor]) {
|
|
7
|
+
static func draw(_ frame: Play.Frame, in ctx: CGContext, stops: [NSColor], cutouts: PlayCutouts?) {
|
|
8
8
|
for gone in frame.gone {
|
|
9
9
|
let c = gone.paper
|
|
10
10
|
ctx.setFillColor(CGColor(srgbRed: CGFloat(c >> 16 & 0xFF) / 255, green: CGFloat(c >> 8 & 0xFF) / 255,
|
|
11
11
|
blue: CGFloat(c & 0xFF) / 255, alpha: 1))
|
|
12
12
|
ctx.fill(cg(gone.rect))
|
|
13
13
|
}
|
|
14
|
+
for piece in frame.pieces {
|
|
15
|
+
let from = cg(piece.from)
|
|
16
|
+
guard let part = cutouts?.image(from, paper: piece.paper) else { continue }
|
|
17
|
+
ctx.saveGState()
|
|
18
|
+
ctx.translateBy(x: piece.at.x + from.width / 2, y: piece.at.y + from.height / 2)
|
|
19
|
+
ctx.rotate(by: piece.turn)
|
|
20
|
+
// The context is flipped; a picture is not.
|
|
21
|
+
ctx.scaleBy(x: 1, y: -1)
|
|
22
|
+
ctx.draw(part, in: CGRect(x: -from.width / 2, y: -from.height / 2, width: from.width, height: from.height))
|
|
23
|
+
ctx.restoreGState()
|
|
24
|
+
}
|
|
14
25
|
if let cloth = frame.cloth {
|
|
15
26
|
let path = CGPath(roundedRect: cg(cloth), cornerWidth: 4, cornerHeight: 4, transform: nil)
|
|
16
27
|
ctx.addPath(path)
|
|
@@ -29,6 +40,41 @@ enum PlayDraw {
|
|
|
29
40
|
private static func cg(_ r: PlayMath.Rect) -> CGRect { CGRect(x: r.x, y: r.y, width: r.w, height: r.h) }
|
|
30
41
|
}
|
|
31
42
|
|
|
43
|
+
/// The pieces of the picture that move, each cut out once: the ink alone,
|
|
44
|
+
/// the page's colour around it left out (`PlayMath.ink`).
|
|
45
|
+
final class PlayCutouts {
|
|
46
|
+
private let picture: CGImage
|
|
47
|
+
/// Pixels of the picture per point.
|
|
48
|
+
private let scale: CGFloat
|
|
49
|
+
private var made: [[CGFloat]: CGImage] = [:]
|
|
50
|
+
|
|
51
|
+
init(picture: CGImage, scale: CGFloat) {
|
|
52
|
+
self.picture = picture
|
|
53
|
+
self.scale = scale
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// The part of the picture at `from` (points), without its paper.
|
|
57
|
+
func image(_ from: CGRect, paper: UInt32) -> CGImage? {
|
|
58
|
+
let key = [from.minX, from.minY, from.width, from.height]
|
|
59
|
+
if let done = made[key] { return done }
|
|
60
|
+
guard let part = picture.cropping(to: from.applying(CGAffineTransform(scaleX: scale, y: scale))),
|
|
61
|
+
let ctx = CGContext(data: nil, width: part.width, height: part.height, bitsPerComponent: 8, bytesPerRow: part.width * 4,
|
|
62
|
+
space: CGColorSpace(name: CGColorSpace.sRGB)!, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue),
|
|
63
|
+
let data = ctx.data else { return nil }
|
|
64
|
+
ctx.draw(part, in: CGRect(x: 0, y: 0, width: part.width, height: part.height))
|
|
65
|
+
let px = data.bindMemory(to: UInt8.self, capacity: part.width * part.height * 4)
|
|
66
|
+
for i in stride(from: 0, to: part.width * part.height * 4, by: 4) {
|
|
67
|
+
let a = PlayMath.ink(r: px[i], g: px[i + 1], b: px[i + 2], paper: paper)
|
|
68
|
+
// Premultiplied: the colour fades with it.
|
|
69
|
+
for k in 0..<3 { px[i + k] = UInt8(Double(px[i + k]) * a) }
|
|
70
|
+
px[i + 3] = UInt8(255 * a)
|
|
71
|
+
}
|
|
72
|
+
let image = ctx.makeImage()
|
|
73
|
+
made[key] = image
|
|
74
|
+
return image
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
32
78
|
/// The stage: a frozen picture of the screen laid over everything, with
|
|
33
79
|
/// the character playing on it. The real page is never touched: nothing
|
|
34
80
|
/// is clicked, typed or changed, and what looks eaten or wiped is only
|
|
@@ -73,6 +119,7 @@ final class PlayHost {
|
|
|
73
119
|
backdrop.layer?.contents = picture
|
|
74
120
|
let view = PlayView(frame: bounds)
|
|
75
121
|
view.stops = stops
|
|
122
|
+
view.picture = picture
|
|
76
123
|
view.shown = Play.Frame(at: foot, pose: CharacterMath.pose(.working))
|
|
77
124
|
view.onInput = { [weak self] in self?.end("a key or a click") }
|
|
78
125
|
backdrop.addSubview(view)
|
|
@@ -144,6 +191,9 @@ private final class PlayWindow: NSPanel {
|
|
|
144
191
|
private final class PlayView: NSView {
|
|
145
192
|
var shown = Play.Frame()
|
|
146
193
|
var stops = CharacterDraw.stops(tint: Brand.accent, colors: nil)
|
|
194
|
+
/// The picture under it: moved pieces are cut from it.
|
|
195
|
+
var picture: CGImage? { didSet { cutouts = nil } }
|
|
196
|
+
private var cutouts: PlayCutouts?
|
|
147
197
|
var onInput: (() -> Void)?
|
|
148
198
|
|
|
149
199
|
override var isFlipped: Bool { true }
|
|
@@ -152,7 +202,10 @@ private final class PlayView: NSView {
|
|
|
152
202
|
|
|
153
203
|
override func draw(_ dirtyRect: NSRect) {
|
|
154
204
|
guard let ctx = NSGraphicsContext.current?.cgContext else { return }
|
|
155
|
-
|
|
205
|
+
if cutouts == nil, let picture {
|
|
206
|
+
cutouts = PlayCutouts(picture: picture, scale: CGFloat(picture.width) / max(bounds.width, 1))
|
|
207
|
+
}
|
|
208
|
+
PlayDraw.draw(shown, in: ctx, stops: stops, cutouts: cutouts)
|
|
156
209
|
}
|
|
157
210
|
|
|
158
211
|
override func keyDown(with event: NSEvent) { onInput?() }
|
|
@@ -57,6 +57,8 @@ struct LookSection: View {
|
|
|
57
57
|
@Binding var look: String
|
|
58
58
|
/// Nil hides the control: the daemon is older than the reduced pill.
|
|
59
59
|
var startReduced: Binding<Bool>?
|
|
60
|
+
/// Nil hides the control: the daemon is older than the stroll.
|
|
61
|
+
var stroll: Binding<Bool>?
|
|
60
62
|
|
|
61
63
|
var body: some View {
|
|
62
64
|
Section {
|
|
@@ -68,6 +70,10 @@ struct LookSection: View {
|
|
|
68
70
|
Toggle("Start reduced to the orb", isOn: startReduced)
|
|
69
71
|
.disabled(look == "character")
|
|
70
72
|
}
|
|
73
|
+
if let stroll {
|
|
74
|
+
Toggle("Character strolls when idle", isOn: stroll)
|
|
75
|
+
.disabled(look != "character")
|
|
76
|
+
}
|
|
71
77
|
} header: {
|
|
72
78
|
Text("Assistant")
|
|
73
79
|
} footer: {
|
|
@@ -378,7 +378,10 @@ private struct GeneralTab: View {
|
|
|
378
378
|
set: { model.draft?.general.look = $0 }),
|
|
379
379
|
startReduced: draft.general.startReduced == nil ? nil
|
|
380
380
|
: Binding(get: { model.draft?.general.startReduced ?? false },
|
|
381
|
-
set: { model.draft?.general.startReduced = $0 })
|
|
381
|
+
set: { model.draft?.general.startReduced = $0 }),
|
|
382
|
+
stroll: draft.general.stroll == nil ? nil
|
|
383
|
+
: Binding(get: { model.draft?.general.stroll ?? false },
|
|
384
|
+
set: { model.draft?.general.stroll = $0 }))
|
|
382
385
|
}
|
|
383
386
|
if draft.general.card != nil {
|
|
384
387
|
AnswerCardSection(card: Binding(get: { model.draft?.general.card ?? .standard },
|
|
@@ -32,13 +32,17 @@ struct VoiceSettings: Codable, Equatable {
|
|
|
32
32
|
/// The pill starts reduced to its orb. Nil from a daemon older
|
|
33
33
|
/// than the reduced pill.
|
|
34
34
|
var startReduced: Bool?
|
|
35
|
+
/// The character takes a stroll when it has nothing to do. Nil
|
|
36
|
+
/// from a daemon older than the stroll.
|
|
37
|
+
var stroll: Bool?
|
|
35
38
|
|
|
36
39
|
init(provider: String, fallback: String, stt: String, localStt: String = "mlx-whisper",
|
|
37
40
|
endOfTurn: String = "vad", hotkeys: Hotkeys, card: Card? = nil, look: String? = nil,
|
|
38
|
-
startReduced: Bool? = nil) {
|
|
41
|
+
startReduced: Bool? = nil, stroll: Bool? = nil) {
|
|
39
42
|
self.provider = provider; self.fallback = fallback; self.stt = stt
|
|
40
43
|
self.localStt = localStt; self.endOfTurn = endOfTurn; self.hotkeys = hotkeys
|
|
41
44
|
self.card = card; self.look = look; self.startReduced = startReduced
|
|
45
|
+
self.stroll = stroll
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
/// A daemon from before these fields leaves them out: the defaults.
|
|
@@ -53,6 +57,7 @@ struct VoiceSettings: Codable, Equatable {
|
|
|
53
57
|
card = try c.decodeIfPresent(Card.self, forKey: .card)
|
|
54
58
|
look = try c.decodeIfPresent(String.self, forKey: .look)
|
|
55
59
|
startReduced = try c.decodeIfPresent(Bool.self, forKey: .startReduced)
|
|
60
|
+
stroll = try c.decodeIfPresent(Bool.self, forKey: .stroll)
|
|
56
61
|
}
|
|
57
62
|
}
|
|
58
63
|
struct Voice: Codable, Equatable {
|
|
@@ -113,6 +118,7 @@ struct VoiceSettings: Codable, Equatable {
|
|
|
113
118
|
if self.general.endOfTurn != old.general.endOfTurn { general["endOfTurn"] = self.general.endOfTurn }
|
|
114
119
|
if let look = self.general.look, look != old.general.look { general["look"] = look }
|
|
115
120
|
if let start = self.general.startReduced, start != old.general.startReduced { general["startReduced"] = start }
|
|
121
|
+
if let stroll = self.general.stroll, stroll != old.general.stroll { general["stroll"] = stroll }
|
|
116
122
|
var keys: [String: Any] = [:]
|
|
117
123
|
if self.general.hotkeys.talk != old.general.hotkeys.talk { keys["talk"] = self.general.hotkeys.talk }
|
|
118
124
|
if self.general.hotkeys.stop != old.general.hotkeys.stop { keys["stop"] = self.general.hotkeys.stop }
|
|
@@ -157,6 +163,17 @@ struct VoiceSettings: Codable, Equatable {
|
|
|
157
163
|
min(30, pow(2, Double(max(1, failures))))
|
|
158
164
|
}
|
|
159
165
|
|
|
166
|
+
/// Seconds between reads once the daemon has answered, so a change
|
|
167
|
+
/// made outside the app shows without a restart.
|
|
168
|
+
static let rereadDelay: Double = 5
|
|
169
|
+
|
|
170
|
+
/// Whether a read from the daemon replaces what the app holds: it
|
|
171
|
+
/// differs, and nothing was saved here while it was on its way. A read
|
|
172
|
+
/// that started before a save in the window carries the old settings.
|
|
173
|
+
static func replaces(_ read: VoiceSettings, held: VoiceSettings?, heldWhenAsked: VoiceSettings?) -> Bool {
|
|
174
|
+
held == heldWhenAsked && read != held
|
|
175
|
+
}
|
|
176
|
+
|
|
160
177
|
/// The fields a preview speaks with: the draft's voice for one agent.
|
|
161
178
|
func previewVoice(for id: String) -> [String: Any] {
|
|
162
179
|
guard let v = agents.first(where: { $0.id == id })?.voice else { return [:] }
|
|
@@ -35,7 +35,8 @@ final class App: NSObject, NSApplicationDelegate {
|
|
|
35
35
|
private var agentHotkeys: [Hotkey] = []
|
|
36
36
|
private let settingsWindow = SettingsWindow()
|
|
37
37
|
/// The saved settings: shortcuts and the speech-to-text engine. Read
|
|
38
|
-
/// from the daemon at launch
|
|
38
|
+
/// from the daemon at launch, every few seconds after that, and after
|
|
39
|
+
/// every save; defaults until then.
|
|
39
40
|
private var settings: VoiceSettings?
|
|
40
41
|
/// The agent a per-agent shortcut is asking; nil for the talk key.
|
|
41
42
|
private var forcedAgent: String?
|
|
@@ -213,6 +214,7 @@ final class App: NSObject, NSApplicationDelegate {
|
|
|
213
214
|
let asCharacter = saved.general.look == "character"
|
|
214
215
|
panel.setShowsOrb(!asCharacter)
|
|
215
216
|
character.setShown(asCharacter)
|
|
217
|
+
character.strolls = saved.general.stroll == true
|
|
216
218
|
if !asCharacter { panel.detach() }
|
|
217
219
|
// voice.startReduced is how the assistant starts: read once.
|
|
218
220
|
if !startApplied {
|
|
@@ -234,8 +236,8 @@ final class App: NSObject, NSApplicationDelegate {
|
|
|
234
236
|
}
|
|
235
237
|
|
|
236
238
|
/// "Play on this page" (#505): one picture of the character's screen, the
|
|
237
|
-
/// lines of text read on it, and the character plays the
|
|
238
|
-
///
|
|
239
|
+
/// lines of text read on it, and the character plays on the picture,
|
|
240
|
+
/// differently each time. The page itself is never touched.
|
|
239
241
|
private func startPlay() {
|
|
240
242
|
let foot = character.foot
|
|
241
243
|
guard canPlay, let screen = NSScreen.screens.first(where: { $0.frame.contains(foot) }) ?? NSScreen.screens.first
|
|
@@ -265,9 +267,9 @@ final class App: NSObject, NSApplicationDelegate {
|
|
|
265
267
|
// Ended while its text was read, and maybe started again since:
|
|
266
268
|
// these lines belong to a picture that is gone.
|
|
267
269
|
guard play.running, play.number == number else { return }
|
|
268
|
-
let steps = PlayMath.
|
|
270
|
+
let steps = PlayMath.script(lines, width: size.width, height: size.height, seed: .random(in: 0 ... .max))
|
|
269
271
|
if steps.isEmpty { play.end("no line of text to play on") }
|
|
270
|
-
else { play.play(Play(lines: lines, steps: steps, start: start)) }
|
|
272
|
+
else { play.play(Play(lines: lines, steps: steps, start: start, size: PlayMath.Point(x: size.width, y: size.height))) }
|
|
271
273
|
}
|
|
272
274
|
}
|
|
273
275
|
|
|
@@ -459,14 +461,26 @@ final class App: NSObject, NSApplicationDelegate {
|
|
|
459
461
|
}
|
|
460
462
|
// At login the app can start before the daemon answers. Keep
|
|
461
463
|
// asking: one missed read left the orb and the built-in
|
|
462
|
-
// shortcuts until the app was restarted.
|
|
464
|
+
// shortcuts until the app was restarted. And keep reading once it
|
|
465
|
+
// has answered (#482): a change made in the Terminal or in
|
|
466
|
+
// agentx.json shows without a restart. Not during a play, which
|
|
467
|
+
// has put the character away, and not while the microphone is
|
|
468
|
+
// open: applying registers the shortcuts again, and the release
|
|
469
|
+
// of a held talk key would be lost. The next read applies it.
|
|
463
470
|
Task { @MainActor in
|
|
464
471
|
var failures = 0
|
|
465
472
|
while true {
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
473
|
+
let asked = settings
|
|
474
|
+
guard let saved = await AgentClient.settings() else {
|
|
475
|
+
failures += 1
|
|
476
|
+
if failures == 1 { Log.warn("settings: the daemon did not answer, asking again") }
|
|
477
|
+
try? await Task.sleep(for: .seconds(VoiceSettings.retryDelay(after: failures)))
|
|
478
|
+
continue
|
|
479
|
+
}
|
|
480
|
+
failures = 0
|
|
481
|
+
if !play.running, !recorder.isRecording,
|
|
482
|
+
VoiceSettings.replaces(saved, held: settings, heldWhenAsked: asked) { apply(saved) }
|
|
483
|
+
try? await Task.sleep(for: .seconds(VoiceSettings.rereadDelay))
|
|
470
484
|
}
|
|
471
485
|
}
|
|
472
486
|
|
|
@@ -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-GJ5EJVMZ.js";import"./chunk-JREA25GJ.js";import"./chunk-RJ7DASOU.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-QIJLFPWE.js";import{useEffect as R,useReducer as V,useRef as G}from"react";import{Box as i,Text as o,useApp as W,useInput as J}from"ink";import{randomUUID as z}from"crypto";async function*q(e){let r=[];e.type&&r.push(`type=${encodeURIComponent(e.type)}`);let t=`${e.baseUrl.replace(/\/+$/,"")}/events${r.length?`?${r.join("&")}`:""}`,n={Accept:"text/event-stream"};e.token&&(n.Authorization=`Bearer ${e.token}`);let s=await fetch(t,{headers:n,signal:e.signal});if(!s.ok||!s.body)throw new Error(`SSE connect failed: HTTP ${s.status}`);let u=s.body.getReader(),p=new TextDecoder,y="";try{for(;;){let{done:f,value:l}=await u.read();if(f)return;y+=p.decode(l,{stream:!0});let d;for(;(d=y.indexOf(`
|
|
2
2
|
|
|
3
3
|
`))>=0;){let h=y.slice(0,d);y=y.slice(d+2);let m=X(h);m&&(yield m)}}}finally{try{u.releaseLock()}catch{}}}function X(e){let r="message",t="";for(let s of e.split(`
|
|
4
4
|
`))s.startsWith("event: ")?r=s.slice(7):s.startsWith("data: ")&&(t=s.slice(6));if(!t)return null;let n;try{n=JSON.parse(t)}catch{n=t}return{event:r,data:n}}import{jsx as a,jsxs as c}from"react/jsx-runtime";function $(e,r){return r<=0||e<0?0:e>=r?r-1:e}function E(){return`tui:${z().slice(0,12)}`}function k(e,r){let t=[...e,r];return t.length>50&&t.splice(0,t.length-50),t}function Y(e,r){switch(r.type){case"agents":return{...e,agents:r.data,cursor:{...e.cursor,agents:$(e.cursor.agents,r.data.length)}};case"processes":return{...e,processes:r.data,cursor:{...e.cursor,processes:$(e.cursor.processes,r.data.length)}};case"crons":return{...e,crons:r.data};case"event":{let t=[r.row,...e.events];t.length>200&&(t.length=200);let n=e.channels;return r.channelTally&&(n=new Map(e.channels),n.set(r.channelTally.channel,r.channelTally)),{...e,events:t,channels:n}}case"connError":return{...e,connError:r.error};case"tick":return{...e,lastTick:Date.now()};case"focus":return{...e,focus:r.pane};case"cursor":{let t=r.pane==="agents"?e.agents.length:r.pane==="processes"?e.processes.length:e.events.length;return{...e,cursor:{...e.cursor,[r.pane]:$(e.cursor[r.pane]+r.delta,t)}}}case"bottomRight":return{...e,bottomRight:r.pane};case"chatStart":return{...e,chat:{active:!0,agentId:r.agentId,chatId:E(),history:[],text:"",status:"idle",error:null}};case"chatExit":return{...e,chat:{...e.chat,active:!1}};case"chatClear":return{...e,chat:{...e.chat,chatId:E(),history:[],text:"",status:"idle",error:null}};case"chatText":return{...e,chat:{...e.chat,text:r.text}};case"chatSubmitStart":return{...e,chat:{...e.chat,history:k(e.chat.history,r.you),text:"",status:"sending",error:null}};case"chatSubmitDone":return{...e,chat:{...e.chat,history:k(e.chat.history,r.reply),status:"idle",error:null}};case"chatSubmitError":return{...e,chat:{...e.chat,history:k(e.chat.history,{role:"error",text:r.error,at:Date.now()}),status:"idle",error:r.error}};case"chatStreamStart":{let t=k(e.chat.history,r.you),n=k(t,{role:"agent",text:"",at:Date.now(),streaming:!0,tools:[]});return{...e,chat:{...e.chat,history:n,text:"",status:"sending",error:null}}}case"chatStreamDelta":{let t=e.chat.history.slice(),n=t[t.length-1];return n?.role==="agent"&&n.streaming&&(t[t.length-1]={...n,text:n.text+r.text}),{...e,chat:{...e.chat,history:t}}}case"chatStreamThinking":{let t=e.chat.history.slice(),n=t[t.length-1];return n?.role==="agent"&&n.streaming&&(t[t.length-1]={...n,thinking:(n.thinking??"")+r.text}),{...e,chat:{...e.chat,history:t}}}case"chatStreamTool":{let t=e.chat.history.slice(),n=t[t.length-1];return n?.role==="agent"&&n.streaming&&(t[t.length-1]={...n,tools:[...n.tools??[],{name:r.name,arg:r.arg,error:r.error}]}),{...e,chat:{...e.chat,history:t}}}case"chatStreamEnd":{let t=e.chat.history.slice(),n=t[t.length-1];return n?.role==="agent"&&n.streaming&&(t[t.length-1]=r.error?{...n,streaming:!1,role:"error",text:r.error}:{...n,streaming:!1,elapsedMs:r.elapsedMs,outTokens:r.outTokens}),{...e,chat:{...e.chat,history:t,status:"idle",error:r.error??null}}}case"toast":return{...e,toast:{text:r.text,color:r.color,at:Date.now()}};case"clearToast":return{...e,toast:null}}}var _={agents:[],processes:[],crons:[],events:[],channels:new Map,connError:null,lastTick:0,focus:"agents",cursor:{agents:0,processes:0,events:0},bottomRight:"crons",chat:{active:!1,agentId:null,chatId:E(),history:[],text:"",status:"idle",error:null},toast:null};function be({conn:e,pollMs:r=3e3}){let[t,n]=V(Y,_),{exit:s}=W(),u=G(null),p=G(null),y=t.agents.map(l=>l.id),f=t.chat.active?L(t.chat.text,y,process.cwd()):null;return R(()=>{if(!t.toast)return;let l=setTimeout(()=>n({type:"clearToast"}),3500);return()=>clearTimeout(l)},[t.toast]),J((l,d)=>{if(t.chat.active){if(d.escape){n({type:"chatExit"});return}if(d.ctrl&&l==="l"){n({type:"chatClear"});return}if(d.tab){let m=U(t.chat.text,p,y,process.cwd());m!==null&&n({type:"chatText",text:m});return}if(d.backspace||d.delete){p.current=null,n({type:"chatText",text:t.chat.text.slice(0,-1)});return}if(d.ctrl||d.meta)return;let h=N(l??"",d.return,t.chat.text);if(h.kind==="paste"||h.kind==="type"){p.current=null,n({type:"chatText",text:t.chat.text+h.text});return}if(h.kind==="continue"){n({type:"chatText",text:h.buffer});return}if(h.kind==="submit"){let m=h.text.trim(),g=t.chat.agentId;if(!m||!g||t.chat.status==="sending"){n({type:"chatText",text:""});return}p.current=null;let b=Date.now(),w=t.chat.chatId;n({type:"chatStreamStart",you:{role:"you",text:m,at:b}}),(async()=>{try{let C=await M(e,g,m,{channel:"tui",chatId:w,onText:x=>n({type:"chatStreamDelta",text:x}),onThinking:x=>n({type:"chatStreamThinking",text:x}),onTool:x=>{x.status==="start"&&x.name?n({type:"chatStreamTool",name:x.name,arg:x.arg}):x.status==="result"&&x.error&&n({type:"chatStreamTool",name:x.name??"tool",error:!0})}});n({type:"chatStreamEnd",elapsedMs:Date.now()-b,outTokens:C.usage?.outputTokens,error:C.error})}catch(C){n({type:"chatStreamEnd",elapsedMs:Date.now()-b,error:C?.message||String(C)})}})();return}return}if(l==="q"||d.ctrl&&l==="c"){u.current?.abort(),s();return}if(d.tab){let h=["agents","processes","events"],m=h.indexOf(t.focus);n({type:"focus",pane:h[(m+1)%h.length]});return}if(l==="a"){n({type:"focus",pane:"agents"});return}if(l==="p"){n({type:"focus",pane:"processes"});return}if(l==="e"){n({type:"focus",pane:"events"});return}if(l==="c"){n({type:"bottomRight",pane:t.bottomRight==="crons"?"channels":"crons"});return}if(d.upArrow){n({type:"cursor",pane:t.focus,delta:-1});return}if(d.downArrow){n({type:"cursor",pane:t.focus,delta:1});return}if(d.return&&t.focus==="agents"){let h=t.agents[t.cursor.agents];if(!h){n({type:"toast",text:"no agent selected",color:"yellow"});return}n({type:"chatStart",agentId:h.id});return}if(l==="k"&&t.focus==="processes"){let h=t.processes[t.cursor.processes];if(!h){n({type:"toast",text:"no process selected",color:"yellow"});return}(async()=>{try{await P(e,h.key,"tui"),n({type:"toast",text:`killed ${h.key.agentId}/${h.key.channel}/${h.key.chatId}`,color:"green"})}catch(m){n({type:"toast",text:`kill failed: ${m?.message||m}`,color:"red"})}})();return}}),R(()=>{let l=new AbortController;u.current=l;let d=!1,h=async()=>{try{let[g,b,w]=await Promise.all([B(e,l.signal).catch(()=>[]),D(e,l.signal).catch(()=>[]),A(e,l.signal).catch(()=>[])]);if(d)return;n({type:"agents",data:g}),n({type:"processes",data:b}),n({type:"crons",data:w}),n({type:"tick"}),n({type:"connError",error:null})}catch(g){d||n({type:"connError",error:g?.message||String(g)})}};h();let m=setInterval(h,r);return()=>{d=!0,clearInterval(m),l.abort()}},[e.baseUrl,e.token,r]),R(()=>{let l=!1,d=new AbortController,h=new Map;return(async()=>{let m=500;for(;!l;){try{for await(let g of q({baseUrl:e.baseUrl,token:e.token,signal:d.signal})){let b=ae(g),w;if(g.event==="channel"&&typeof g.data?.channel=="string"){let S=h.get(g.data.channel)??{channel:g.data.channel,inbound:0,outbound:0,lastAt:0,lastPreview:""},C=S.inbound+(g.data.direction==="in"?1:0),x=S.outbound+(g.data.direction==="out"?1:0);w={channel:g.data.channel,inbound:C,outbound:x,lastAt:b.at,lastPreview:(g.data.textPreview||"").slice(0,60)},h.set(g.data.channel,w)}n({type:"event",row:b,channelTally:w}),m=500}}catch(g){if(l)return;n({type:"connError",error:`events: ${g?.message||g}`})}await new Promise(g=>setTimeout(g,m)),m=Math.min(m*2,1e4)}})(),()=>{l=!0,d.abort()}},[e.baseUrl,e.token]),c(i,{flexDirection:"column",width:"100%",children:[a(K,{conn:e,lastTick:t.lastTick,connError:t.connError,chat:t.chat}),c(i,{flexDirection:"row",flexGrow:1,children:[c(i,{flexDirection:"column",width:"50%",children:[a(v,{title:"AGENTS",focused:!t.chat.active&&t.focus==="agents",children:a(Z,{rows:t.agents,cursor:t.cursor.agents,focused:!t.chat.active&&t.focus==="agents",talkingTo:t.chat.active?t.chat.agentId:null})}),a(v,{title:"PROCESSES",focused:!t.chat.active&&t.focus==="processes",children:a(ee,{rows:t.processes,cursor:t.cursor.processes,focused:!t.chat.active&&t.focus==="processes"})})]}),t.chat.active?a(oe,{chat:t.chat,suggest:f,agents:t.agents}):c(i,{flexDirection:"column",width:"50%",children:[a(v,{title:"LIVE EVENTS",focused:t.focus==="events",children:a(ne,{rows:t.events,cursor:t.cursor.events,focused:t.focus==="events"})}),a(v,{title:t.bottomRight==="crons"?"CRONS / SCHEDULES":"CHANNELS",focused:!1,children:t.bottomRight==="crons"?a(te,{rows:t.crons}):a(re,{rows:Array.from(t.channels.values())})})]})]}),a(Q,{focus:t.focus,bottomRight:t.bottomRight,chat:t.chat,toast:t.toast})]})}function K({conn:e,lastTick:r,connError:t,chat:n}){let s=t?c(o,{color:"red",children:["\u25CF ",t]}):r===0?a(o,{color:"yellow",children:"\u25CF connecting\u2026"}):a(o,{color:"green",children:"\u25CF live"}),u=n.active?c(o,{color:"green",bold:!0,children:["CHAT @",n.agentId]}):a(o,{bold:!0,children:"agentx tui"});return c(i,{paddingX:1,justifyContent:"space-between",children:[a(i,{children:u}),a(o,{dimColor:!0,children:e.baseUrl}),a(i,{children:s})]})}function Q({focus:e,bottomRight:r,chat:t,toast:n}){let s=t.active?["[Enter] send","[Esc] exit chat","[Ctrl-L] new session"]:[`[Tab/a/p/e] focus (now: ${e})`,e==="agents"?"[Enter] chat":null,e==="processes"?"[k] kill":null,`[c] ${r==="crons"?"\u2192channels":"\u2192crons"}`,"[\u2191/\u2193] move","[q] quit"].filter(Boolean);return c(i,{paddingX:1,borderStyle:"single",borderTop:!0,borderBottom:!1,borderLeft:!1,borderRight:!1,justifyContent:"space-between",children:[a(o,{dimColor:!0,children:s.join(" \xB7 ")}),n?a(o,{color:n.color,children:n.text}):a(o,{children:" "})]})}function v({title:e,focused:r,children:t}){return c(i,{flexDirection:"column",width:"100%",borderStyle:r?"double":"single",borderColor:r?"cyan":void 0,paddingX:1,children:[c(o,{bold:!0,color:r?"cyan":"white",children:[e,r?" \u25CF":""]}),a(i,{flexDirection:"column",marginTop:1,children:t})]})}function I(e,r){return e&&r?{inverse:!0}:{}}function Z({rows:e,cursor:r,focused:t,talkingTo:n}){return e.length===0?a(o,{dimColor:!0,children:"no agents"}):a(i,{flexDirection:"column",children:e.slice(0,12).map((s,u)=>{let p=I(t,u===r),y=s.errors>0?"red":s.active>0?"yellow":"green",f=s.id===n;return c(i,{children:[a(o,{...p,color:y,children:"\u25CF"}),c(o,{...p,children:[" ",T(s.name,14)]}),c(o,{...p,children:[T(s.tier,6)," "]}),c(o,{...p,children:[s.active,"/",s.total]}),s.errors>0?c(o,{...p,color:"red",children:[" err=",s.errors]}):null,f?a(o,{color:"green",children:" \u2194 chatting"}):null]},s.id)})})}function ee({rows:e,cursor:r,focused:t}){if(e.length===0)return a(o,{dimColor:!0,children:"no live processes"});let n=Date.now();return a(i,{flexDirection:"column",children:e.slice(0,12).map((s,u)=>{let p=I(t,u===r),y=Math.max(0,Math.round((n-(s.lastTurnAt||s.spawnedAt))/1e3)),f=s.state==="dead"?"red":s.state==="warm-hot"?"green":"yellow";return c(i,{children:[a(o,{...p,color:f,children:T(s.state,10)}),a(o,{...p,children:T(s.key.agentId,12)}),a(o,{...p,children:T(s.key.channel,10)}),c(o,{...p,children:[s.turnCount,"t ",y,"s"]})]},`${s.key.agentId}-${s.key.channel}-${s.key.chatId}-${u}`)})})}function te({rows:e}){return e.length===0?a(o,{dimColor:!0,children:"no crons"}):a(i,{flexDirection:"column",children:e.slice(0,12).map(r=>{let t=r.enabled?r.consecutiveErrors>0?a(o,{color:"red",children:"err"}):a(o,{color:"green",children:"ok"}):a(o,{dimColor:!0,children:"off"}),n=r.nextRun?new Date(r.nextRun).toLocaleTimeString():"\u2014";return c(i,{children:[a(o,{children:T(r.id,16)}),a(o,{dimColor:!0,children:T(r.schedule,12)}),a(o,{children:T(n,10)}),a(i,{children:t})]},r.id)})})}function re({rows:e}){if(e.length===0)return a(o,{dimColor:!0,children:"(waiting for channel events\u2026)"});let r=[...e].sort((t,n)=>n.lastAt-t.lastAt);return a(i,{flexDirection:"column",children:r.slice(0,12).map(t=>c(i,{children:[a(o,{children:T(t.channel,12)}),c(o,{color:"cyan",children:["\u2190",T(String(t.inbound),4)]}),c(o,{color:"magenta",children:["\u2192",T(String(t.outbound),4)]}),a(o,{dimColor:!0,children:t.lastPreview})]},t.channel))})}function ne({rows:e,cursor:r,focused:t}){return e.length===0?a(o,{dimColor:!0,children:"(waiting for events\u2026)"}):a(i,{flexDirection:"column",children:e.slice(0,18).map((n,s)=>{let u=I(t,s===r);return c(i,{children:[a(o,{...u,dimColor:!0,children:new Date(n.at).toLocaleTimeString().padEnd(10)}),a(o,{...u,color:ce(n.kind),children:T(n.kind,8)}),a(o,{...u,children:n.line})]},`${n.at}-${s}`)})})}function oe({chat:e,suggest:r,agents:t}){let n=e.history.slice(-14),s=t.find(f=>f.id===e.agentId),u=H(s?.tier??"",s?.model),p=e.status==="sending"?[...e.history].reverse().find(f=>f.role==="agent"&&f.streaming):void 0,y=e.status==="sending"?a(O,{startedAt:p?.at??Date.now(),phase:p?.text?"responding":"thinking",indent:""}):e.error?c(o,{color:"red",children:["\u25CF ",e.error]}):a(o,{dimColor:!0,children:"\u25CF ready"});return c(i,{flexDirection:"column",width:"50%",borderStyle:"double",borderColor:"green",paddingX:1,children:[c(i,{justifyContent:"space-between",children:[c(o,{bold:!0,color:"green",children:["CHAT \xB7 @",e.agentId]}),a(i,{children:y})]}),c(o,{children:[c(o,{color:u.color,bold:!0,children:[u.glyph," ",u.label]}),s?.model?c(o,{dimColor:!0,children:[" ",j(s.model)]}):null,c(o,{dimColor:!0,children:[" \xB7 ",e.chatId]})]}),a(i,{flexDirection:"column",flexGrow:1,marginTop:1,children:n.length===0?a(o,{dimColor:!0,children:"(type a message and press Enter \u2014 Esc exits, Ctrl-L starts fresh)"}):n.map((f,l)=>a(se,{turn:f,agentId:e.agentId},`${f.at}-${l}`))}),r?c(o,{dimColor:!0,children:[a(o,{color:"cyan",children:"\u21B9"})," ",r.items.slice(0,5).map((f,l)=>l===0?a(o,{color:"cyan",children:f},l):c(o,{children:[" ",f]},l))]}):null,c(i,{children:[a(o,{color:"cyan",children:"you \u203A "}),a(o,{children:e.text}),a(o,{inverse:!0,children:" "})]})]})}function se({turn:e,agentId:r}){if(e.role==="you")return c(i,{flexDirection:"column",marginBottom:1,children:[a(o,{color:"cyan",children:"you"}),e.text.split(`
|
|
5
5
|
`).map((s,u)=>c(o,{children:[" ",s]},u))]});if(e.role==="error")return c(i,{flexDirection:"column",marginBottom:1,children:[a(o,{color:"red",children:"error"}),c(o,{color:"red",children:[" ",e.text]})]});let t=e.elapsedMs!=null?` \xB7 ${(e.elapsedMs/1e3).toFixed(1)}s${e.outTokens!=null?`, ${e.outTokens} tok`:""}`:e.streaming?" \xB7 \u2026":"",n=F(e.text,58,{balance:e.streaming});return c(i,{flexDirection:"column",marginBottom:1,children:[c(o,{color:"green",children:["@",r??"agent",a(o,{dimColor:!0,children:t})]}),e.thinking?e.thinking.split(`
|
|
6
6
|
`).filter(s=>s.trim()).slice(-2).map((s,u)=>c(o,{dimColor:!0,italic:!0,children:[" ",s]},`th${u}`)):null,(e.tools??[]).map((s,u)=>c(o,{color:s.error?"red":"green",children:[" \u25CF ",c(o,{bold:!s.error,dimColor:s.error,children:[s.name,s.arg?c(o,{dimColor:!0,children:["(",s.arg,")"]}):null,s.error?" failed":""]})]},`tool${u}`)),n.split(`
|
|
7
7
|
`).slice(0,14).map((s,u)=>c(o,{children:[" ",s]},u))]})}function ae(e){let r=e.data??{},t=typeof r.at=="string"||typeof r.at=="number"?new Date(r.at).getTime():Date.now(),n="";switch(e.event){case"run":n=`${r.phase??""} ${r.workflowId??""} ${(r.runId??"").slice(0,8)} ${r.nodeId??""}`.trim();break;case"task":n=`${r.phase??""} ${r.workflowId??""} ${Array.isArray(r.assignedTo)?r.assignedTo.join(","):""} ${r.title?`"${r.title}"`:""}`.trim();break;case"signal":n=`${r.name??""} (${r.scope??""}) ${r.workflowId??""}`.trim();break;case"mesh":n=`${r.peer??""} ${r.healthy?"healthy":"lost"} ${r.delta??""}`.trim();break;case"channel":{n=`${r.direction==="in"?"\u2190":"\u2192"} ${r.channel??""}:${r.chatId??""} ${r.textPreview??""}`.trim();break}case"status":n=`node=${r.node??""} agents=${r.agents??0} active=${(r.active??[]).length}`;break;default:n=typeof r=="string"?r:JSON.stringify(r).slice(0,80)}return{at:Number.isFinite(t)?t:Date.now(),kind:e.event,line:n}}function ce(e){switch(e){case"run":return"cyan";case"task":return"magenta";case"signal":return"green";case"mesh":return"blue";case"channel":return"yellow";default:return"white"}}function T(e,r){let t=(e??"").toString();return t.length>=r?t.slice(0,r-1)+" ":t+" ".repeat(r-t.length)}export{be as App};
|
|
8
|
-
//# sourceMappingURL=App-
|
|
8
|
+
//# sourceMappingURL=App-XLQDP26J.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-GJ5EJVMZ.js";import"./chunk-JREA25GJ.js";import"./chunk-RJ7DASOU.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-QIJLFPWE.js";import{useCallback as oe,useMemo as H,useRef as P,useState as k}from"react";import{Box as g,Text as t,useApp as he,useInput as xe,useStdout as Te}from"ink";import{randomUUID as se}from"crypto";var m={accent:"cyan",agent:"green",working:"magenta",error:"red",muted:"gray"},q="\u25C7 agentx",F="\u258C";import{jsx as c,jsxs as o}from"react/jsx-runtime";var ie="/help /agent <id> /agents /clear /who /exit",be=[{cmd:"/agent",desc:"switch the target agent (/agent <id>)"},{cmd:"/agents",desc:"list registered agents"},{cmd:"/clear",desc:"start a fresh session"},{cmd:"/who",desc:"show agent + chat id"},{cmd:"/help",desc:"list commands"},{cmd:"/exit",desc:"quit the chat"}];function Pe({conn:n,agentId:p,channel:f,chatId:a,agents:h}){let{exit:w}=he(),{stdout:O}=Te(),V=Math.max(40,Math.min((O?.columns||80)-4,100)),[z,U]=k([]),[$,S]=k(null),[T,le]=k(p),[A,ae]=k(h),[E,ue]=k(a),[y,x]=k(""),[J,de]=k(""),W=P([]),u=P(-1),M=P(null),R=P(null),v=$?.live??!1,j=H(()=>Z(y,A.map(s=>s.id),process.cwd()),[y,A]),N=H(()=>{let s=/^\/(\w*)$/.exec(y);if(!s)return null;let e=be.filter(r=>r.cmd.slice(1).startsWith(s[1].toLowerCase()));return e.length?e:null},[y]),b=s=>de(s),K=oe(s=>{let e=se().slice(0,8),r=Date.now(),i=new AbortController;R.current=i;let d={id:e,you:s,agentId:T,segs:[],live:!0,startedAt:r};S({...d});let L=()=>S({...d,segs:d.segs.map(C=>({...C}))});(async()=>{try{let C=await X(n,T,s,{channel:f,chatId:E,signal:i.signal,onText:l=>{let I=d.segs[d.segs.length-1];I&&I.type==="text"?I.content=(I.content??"")+l:d.segs.push({type:"text",content:l}),L()},onThinking:l=>{d.thinking=(d.thinking??"")+l,L()},onTool:l=>{l.status==="start"&&l.name?(d.segs.push({type:"tool",name:l.name,arg:l.arg}),L()):l.status==="result"&&l.error&&(d.segs.push({type:"tool",name:l.name??"tool",error:!0}),L())}});U(l=>[...l,{...d,live:!1,elapsedMs:Date.now()-r,outTokens:C.usage?.outputTokens,error:C.error}]),S(null)}catch(C){let l=i.signal.aborted||C?.name==="AbortError";U(I=>[...I,{...d,live:!1,elapsedMs:Date.now()-r,interrupted:l,error:l?void 0:C?.message||String(C)}]),S(null)}finally{R.current===i&&(R.current=null)}})()},[n,T,f,E]),me=oe(s=>{let e=s.trim();if(e){if(W.current.push(e),u.current=-1,e==="/exit"||e==="/quit"){w();return}if(e==="/help"){b(ie);return}if(e==="/who"){b(`@${T} \xB7 chatId=${E} \xB7 channel=${f}`);return}if(e==="/clear"){let r=`chat-cli:${se().slice(0,12)}`;ue(r),U([]),b(`fresh chatId=${r} (warm process dropped)`);return}if(e==="/agents"){Q(n).then(r=>{ae(r),b(r.map(i=>i.id===T?`[${i.id}]`:i.id).join(" "))}).catch(r=>b(`failed to list agents: ${r?.message||r}`));return}if(e.startsWith("/agent ")){let r=e.slice(7).replace(/^@/,"").trim();if(!r){b("usage: /agent <id>");return}if(!A.find(i=>i.id===r)){b(`unknown agent: @${r}`);return}le(r),b(`now talking to @${r}`);return}if(e.startsWith("/")){b(`unknown command \xB7 ${ie}`);return}K(e)}},[n,T,A,f,E,w,K]);xe((s,e)=>{if(e.ctrl&&s==="c"){w();return}if(e.escape){if(v&&R.current){R.current.abort();return}w();return}if(e.tab){if(N){x(N[0].cmd+" ");return}let i=_(y,M,A.map(d=>d.id),process.cwd());i!==null&&(x(i),u.current=-1);return}if(e.upArrow){let i=W.current;if(!i.length)return;u.current=u.current<0?i.length-1:Math.max(0,u.current-1),x(i[u.current]??"");return}if(e.downArrow){let i=W.current;if(u.current<0)return;if(u.current=u.current+1,u.current>=i.length){u.current=-1,x("");return}x(i[u.current]??"");return}if(e.backspace||e.delete){M.current=null,x(i=>i.slice(0,-1));return}if(e.ctrl||e.meta)return;let r=ee(s??"",e.return,y);switch(r.kind){case"paste":M.current=null,x(i=>i+r.text),u.current=-1;return;case"type":M.current=null,x(i=>i+r.text),u.current=-1;return;case"continue":x(r.buffer);return;case"submit":if(v)return;M.current=null,x(""),me(r.text);return;case"none":return}});let G=v?m.working:m.accent,ge=y.length?y.split(`
|
|
2
2
|
`):[""],B=A.find(s=>s.id===T),D=ne(B?.tier??"",B?.model),pe=O?.rows||24,fe=z.slice(-40);return o(g,{flexDirection:"column",height:pe,children:[o(g,{flexDirection:"column",flexGrow:1,justifyContent:"flex-end",overflow:"hidden",children:[z.length===0&&!$?o(g,{flexDirection:"column",children:[o(t,{children:[c(t,{color:m.accent,bold:!0,children:q}),c(t,{dimColor:!0,children:" \u2014 chat with "}),o(t,{color:m.accent,children:["@",T]}),c(t,{dimColor:!0,children:" via "}),o(t,{color:D.color,bold:!0,children:[D.glyph," ",D.label]}),B?.model?o(t,{dimColor:!0,children:[" (",B.model,")"]}):null]}),c(t,{dimColor:!0,children:"streaming \xB7 markdown \xB7 tools \xB7 type a message, or / for commands"})]}):null,fe.map(s=>c(ce,{turn:s,width:V},s.id)),$?c(ce,{turn:$,width:V}):null]}),N?c(g,{flexDirection:"column",marginTop:1,children:N.map((s,e)=>o(g,{children:[c(t,{color:e===0?m.accent:m.muted,bold:e===0,children:s.cmd.padEnd(10)}),c(t,{dimColor:!0,children:s.desc})]},s.cmd))}):j?o(g,{marginTop:1,children:[c(t,{color:m.accent,children:"\u21B9 "}),j.items.map((s,e)=>o(t,{color:e===0?m.accent:m.muted,children:[s,e<j.items.length-1?" ":""]},e))]}):J?c(g,{marginTop:1,children:c(t,{dimColor:!0,children:J})}):null,c(g,{borderStyle:"single",borderColor:G,borderLeft:!1,borderRight:!1,borderDimColor:!v,width:"100%",children:c(g,{flexDirection:"column",width:"100%",children:ge.map((s,e,r)=>o(g,{children:[c(t,{color:G,bold:!0,children:e===0?"\u203A ":" "}),c(t,{children:s}),e===r.length-1&&!v?c(t,{color:G,children:"\u258F"}):null]},e))})}),o(g,{justifyContent:"space-between",children:[o(t,{children:[c(t,{color:m.accent,bold:!0,children:q}),o(t,{dimColor:!0,children:[" \xB7 @",T," \xB7 "]}),o(t,{color:D.color,bold:!0,children:[D.glyph," ",D.label]}),B?.model?o(t,{dimColor:!0,children:[" ",re(B.model)]}):null]}),o(t,{dimColor:!0,children:["\u21B5 send / cmds @ mention esc ",v?"stop":"exit"]})]})]})}function ce({turn:n,width:p}){let f=H(()=>ye(n,p),[n,p]),a=n.segs.some(h=>h.type==="text"&&h.content);return o(g,{flexDirection:"column",marginBottom:1,children:[o(t,{color:m.accent,bold:!0,children:[F," you"]}),n.you.split(`
|
|
3
3
|
`).map((h,w)=>o(t,{color:"white",children:[" ",h]},`u${w}`)),o(t,{color:m.agent,bold:!0,children:[F," ",n.agentId??"agent"]}),n.thinking?c(g,{flexDirection:"column",children:we(n.thinking,n.live?3:2).map((h,w)=>o(t,{dimColor:!0,italic:!0,children:[" ",h]},`th${w}`))}):null,f,n.live?c(te,{startedAt:n.startedAt,phase:a?"responding":"thinking",hint:"esc to interrupt"}):n.interrupted?o(t,{dimColor:!0,children:[" \u2298 interrupted \xB7 ",(n.elapsedMs/1e3).toFixed(1),"s"]}):n.error?o(t,{color:"red",children:[" \u2717 ",n.error]}):n.elapsedMs!=null?o(t,{dimColor:!0,children:[" \xB7 ",(n.elapsedMs/1e3).toFixed(1),"s",n.outTokens!=null?`, ${n.outTokens} tok`:""]}):null]})}function we(n,p){return n.split(`
|
|
4
4
|
`).filter(a=>a.trim()).slice(-p)}function ye(n,p){let f=[];return n.segs.forEach((a,h)=>{a.type==="tool"?f.push(o(t,{color:a.error?"red":"green",children:[" ","\u25CF ",o(t,{bold:!a.error,dimColor:a.error,children:[a.name,a.arg?o(t,{dimColor:!0,children:["(",a.arg,")"]}):null,a.error?" failed":""]})]},h)):a.content&&f.push(c(t,{children:Ce(Y(a.content,p,{balance:n.live}))},h))}),f}function Ce(n){return n.split(`
|
|
5
5
|
`).map(p=>p.length?" "+p:p).join(`
|
|
6
6
|
`)}export{Pe as ChatApp};
|
|
7
|
-
//# sourceMappingURL=ChatApp-
|
|
7
|
+
//# sourceMappingURL=ChatApp-DRDUXZ66.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-OFVMUBIP.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-QHM3J2XS.js.map
|