@join-pantheon/cli 0.24.4 → 0.25.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/README.md +22 -1
- package/dist/admin-stats.js +97 -0
- package/dist/cli.js +60 -7
- package/dist/client.js +2 -0
- package/dist/decision-ui.js +31 -9
- package/dist/doctor.js +101 -60
- package/dist/feedback.js +3 -0
- package/dist/grants.js +38 -17
- package/dist/humanize.js +2 -0
- package/dist/install.js +97 -21
- package/dist/mcp-instructions.js +85 -0
- package/dist/mcp-supervisor.js +2 -1
- package/dist/mcp.js +47 -82
- package/dist/measure.js +142 -0
- package/dist/notice.js +7 -2
- package/dist/relay.js +43 -2
- package/dist/roster-file.js +17 -0
- package/dist/run-failure.js +97 -0
- package/dist/setup-guide.js +30 -2
- package/dist/tools.js +9 -2
- package/dist/tray.js +10 -3
- package/dist/worker-policy.js +3 -1
- package/dist/worker.js +107 -13
- package/helper/macos/main.swift +22 -1
- package/helper/macos/menubar.swift +41 -11
- package/package.json +1 -1
|
@@ -78,7 +78,9 @@ struct Item {
|
|
|
78
78
|
/// "praneet · 2d ago · pantheon"
|
|
79
79
|
var subtitle: String {
|
|
80
80
|
var parts: [String] = []
|
|
81
|
-
|
|
81
|
+
// Who is asking, on every kind. A decision row used to say only "11h ago",
|
|
82
|
+
// which is the one fact a reader could already guess.
|
|
83
|
+
if kind == "owed" { parts.append("you owe") } else if !who.isEmpty { parts.append(who) }
|
|
82
84
|
if when > 0 { parts.append(Item.age(when)) }
|
|
83
85
|
if !space.isEmpty { parts.append(space) }
|
|
84
86
|
return parts.joined(separator: " · ")
|
|
@@ -179,11 +181,30 @@ final class RowView: NSView {
|
|
|
179
181
|
private var overCopy = false
|
|
180
182
|
private var copied = false
|
|
181
183
|
|
|
184
|
+
private let titleLines: Int
|
|
185
|
+
private static let titleFont = NSFont.systemFont(ofSize: 13, weight: .medium)
|
|
186
|
+
private static let lineHeight: CGFloat = 17
|
|
187
|
+
|
|
188
|
+
/// How many lines this title needs, at most two. A one-line row truncated
|
|
189
|
+
/// mid-word ("Sid asked: Sid is asking: is this work in producti…") hid the
|
|
190
|
+
/// only part worth reading; two lines carry almost every real title whole.
|
|
191
|
+
static func lines(for text: String, width: CGFloat) -> Int {
|
|
192
|
+
let para = NSMutableParagraphStyle()
|
|
193
|
+
para.lineBreakMode = .byWordWrapping
|
|
194
|
+
let h = (text as NSString).boundingRect(
|
|
195
|
+
with: NSSize(width: width, height: .greatestFiniteMagnitude),
|
|
196
|
+
options: [.usesLineFragmentOrigin, .usesFontLeading],
|
|
197
|
+
attributes: [.font: titleFont, .paragraphStyle: para]).height
|
|
198
|
+
return max(1, min(2, Int(ceil(h / lineHeight))))
|
|
199
|
+
}
|
|
200
|
+
|
|
182
201
|
init(item: Item, width: CGFloat, onOpen: @escaping (Item) -> Void, onCopy: @escaping (Item) -> Void) {
|
|
183
202
|
self.item = item
|
|
184
203
|
self.onOpen = onOpen
|
|
185
204
|
self.onCopy = onCopy
|
|
186
|
-
|
|
205
|
+
self.titleLines = RowView.lines(for: item.title, width: width - 14 - 48)
|
|
206
|
+
let textHeight = CGFloat(titleLines) * RowView.lineHeight
|
|
207
|
+
super.init(frame: NSRect(x: 0, y: 0, width: width, height: textHeight + (item.subtitle.isEmpty ? 13 : 29)))
|
|
187
208
|
setAccessibilityRole(.button)
|
|
188
209
|
setAccessibilityLabel("\(item.title). \(item.subtitle). Return opens it; the button on the right copies the question.")
|
|
189
210
|
}
|
|
@@ -191,6 +212,7 @@ final class RowView: NSView {
|
|
|
191
212
|
|
|
192
213
|
private var copyRect: NSRect { NSRect(x: bounds.maxX - 42, y: bounds.midY - 12, width: 28, height: 24) }
|
|
193
214
|
|
|
215
|
+
|
|
194
216
|
override func updateTrackingAreas() {
|
|
195
217
|
super.updateTrackingAreas()
|
|
196
218
|
for a in trackingAreas { removeTrackingArea(a) }
|
|
@@ -227,17 +249,25 @@ final class RowView: NSView {
|
|
|
227
249
|
let fg: NSColor = selected ? .selectedMenuItemTextColor : .labelColor
|
|
228
250
|
let dim: NSColor = selected ? NSColor.selectedMenuItemTextColor.withAlphaComponent(0.7) : .secondaryLabelColor
|
|
229
251
|
let para = NSMutableParagraphStyle()
|
|
230
|
-
para.lineBreakMode = .
|
|
252
|
+
para.lineBreakMode = .byWordWrapping // break between words, not inside one
|
|
253
|
+
para.lineSpacing = 0
|
|
254
|
+
let flat = NSMutableParagraphStyle()
|
|
255
|
+
flat.lineBreakMode = .byTruncatingTail
|
|
231
256
|
let textWidth = bounds.width - 14 - 48
|
|
232
257
|
let hasSub = !item.subtitle.isEmpty
|
|
233
|
-
let
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
258
|
+
let titleHeight = CGFloat(titleLines) * RowView.lineHeight
|
|
259
|
+
let titleY = bounds.maxY - 7 - titleHeight
|
|
260
|
+
let cell = NSTextFieldCell() // gives the last visible line its ellipsis
|
|
261
|
+
cell.attributedStringValue = NSAttributedString(string: item.title, attributes: [
|
|
262
|
+
.font: RowView.titleFont, .foregroundColor: fg, .paragraphStyle: para,
|
|
263
|
+
])
|
|
264
|
+
cell.truncatesLastVisibleLine = true
|
|
265
|
+
cell.wraps = true
|
|
266
|
+
cell.drawInterior(withFrame: NSRect(x: 12, y: titleY, width: textWidth, height: titleHeight), in: self)
|
|
237
267
|
if hasSub {
|
|
238
268
|
NSAttributedString(string: item.subtitle, attributes: [
|
|
239
|
-
.font: NSFont.systemFont(ofSize: 11), .foregroundColor: dim, .paragraphStyle:
|
|
240
|
-
]).draw(in: NSRect(x: 14, y: bounds.
|
|
269
|
+
.font: NSFont.systemFont(ofSize: 11), .foregroundColor: dim, .paragraphStyle: flat,
|
|
270
|
+
]).draw(in: NSRect(x: 14, y: bounds.minY + 6, width: textWidth, height: 14))
|
|
241
271
|
}
|
|
242
272
|
|
|
243
273
|
// the copy control
|
|
@@ -406,7 +436,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
|
|
|
406
436
|
addRows(menu, theirs.count == 1 ? "Waiting on \(who)" : "Waiting on \(who) · \(theirs.count)", theirs)
|
|
407
437
|
}
|
|
408
438
|
if !decisions.isEmpty {
|
|
409
|
-
menu.addItem(makeItem(
|
|
439
|
+
menu.addItem(makeItem(decisions.count > 1 ? "Review all \(decisions.count) in \(state.surfaceName)" : "Review it in \(state.surfaceName)", #selector(openAllDecisions)))
|
|
410
440
|
}
|
|
411
441
|
}
|
|
412
442
|
menu.addItem(.separator())
|
|
@@ -826,7 +856,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
|
|
|
826
856
|
for item in items.prefix(6) {
|
|
827
857
|
let mi = NSMenuItem(title: item.title, action: nil, keyEquivalent: "")
|
|
828
858
|
mi.toolTip = item.detail
|
|
829
|
-
mi.view = RowView(item: item, width:
|
|
859
|
+
mi.view = RowView(item: item, width: 430,
|
|
830
860
|
onOpen: { [weak self] it in self?.showDetail(it) },
|
|
831
861
|
onCopy: { [weak self] it in self?.copyPrompt(it) })
|
|
832
862
|
menu.addItem(mi)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@join-pantheon/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "Let your coding agent collaborate directly with your teammates' agents — ask, agree an interface, and deliver, without a human relaying messages.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|