Let agents show and drive Page view tabs on the iPhone
This commit is contained in:
@@ -118,6 +118,7 @@ final class API: Sendable {
|
||||
config.httpAdditionalHeaders = [
|
||||
"Byre-Client": clientID,
|
||||
"Byre-Commit": Bundle.main.object(forInfoDictionaryKey: "ByreCommit") as! String,
|
||||
"Byre-Device": deviceKind,
|
||||
"Byre-Host": deviceName,
|
||||
]
|
||||
config.proxyConfigurations = [tailnetNode.proxy()]
|
||||
|
||||
@@ -278,6 +278,17 @@ final class Pages {
|
||||
}
|
||||
return png
|
||||
}
|
||||
#else
|
||||
func capture(_ view: WKWebView) async throws -> Data {
|
||||
guard view.window != nil, !view.isHidden else {
|
||||
throw ApiError(status: 0, message: "the tab isn't on screen: the human has the page view closed or another tab showing")
|
||||
}
|
||||
let image = try await view.takeSnapshot(configuration: nil)
|
||||
guard let png = image.pngData() else {
|
||||
throw ApiError(status: 0, message: "couldn't encode the capture as PNG")
|
||||
}
|
||||
return png
|
||||
}
|
||||
#endif
|
||||
|
||||
func close() {
|
||||
|
||||
@@ -7,12 +7,13 @@ typealias ClientRequest = Components.Schemas.ClientRequest
|
||||
typealias ClientReply = Components.Schemas.ClientReply
|
||||
typealias ClientSync = Components.Schemas.ClientSync
|
||||
|
||||
#if os(macOS)
|
||||
private let retryAfter = Duration.seconds(2)
|
||||
private let checkEvery = Duration.seconds(10)
|
||||
private let staleAfter: TimeInterval = 25
|
||||
private let maxOutput = 64 << 10
|
||||
private let maxMessage = 256 << 20
|
||||
|
||||
#if os(macOS)
|
||||
private let maxOutput = 64 << 10
|
||||
private let maxRead = 64 << 20
|
||||
private let copyTimeoutMs = 10 * 60 * 1000
|
||||
private let hands = Hands()
|
||||
@@ -27,6 +28,7 @@ private let signScript = """
|
||||
esac
|
||||
exec "$program" --status-fd=2 -bsau "$(git config user.signingkey || echo "$1")" >"$2"
|
||||
"""
|
||||
#endif
|
||||
|
||||
@MainActor
|
||||
final class Remote {
|
||||
@@ -157,6 +159,10 @@ final class Remote {
|
||||
|
||||
private func perform(_ req: ClientRequest) async throws -> ClientReply {
|
||||
switch req.op {
|
||||
#if os(iOS)
|
||||
case .bash, .exec, .upload, .download, .readFile, .writeFile, .hands, .sign:
|
||||
throw ApiError(status: 0, message: "an iPhone only shows and drives pages and files in byre's app (show_page, show_file, drive_page)")
|
||||
#else
|
||||
case .bash:
|
||||
let home = FileManager.default.homeDirectoryForCurrentUser.path
|
||||
let (code, output) = try await spawn(["/bin/zsh", "-l", "-c", req.command ?? ""], in: home, timeoutMs: req.timeoutMs ?? 120_000)
|
||||
@@ -190,6 +196,7 @@ final class Remote {
|
||||
case .sign:
|
||||
let (code, status, signature) = try await sign(Data(req.data?.data ?? []), as: req.ident ?? "", timeoutMs: req.timeoutMs ?? 120_000)
|
||||
return ClientReply(id: req.id, exitCode: code, output: status, data: Base64EncodedData(signature))
|
||||
#endif
|
||||
case .openPage:
|
||||
if let address = req.url {
|
||||
guard let url = URL(string: address) else {
|
||||
@@ -219,6 +226,7 @@ final class Remote {
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS)
|
||||
private func sign(_ payload: Data, as ident: String, timeoutMs: Int) async throws -> (Int, String, Data) {
|
||||
let fm = FileManager.default
|
||||
let dir = fm.temporaryDirectory.appending(path: "byre-sign-\(UUID().uuidString)", directoryHint: .isDirectory)
|
||||
@@ -293,8 +301,10 @@ final class Remote {
|
||||
}
|
||||
try fm.moveItem(at: entries[0], to: target)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if os(macOS)
|
||||
private func expand(_ path: String) -> URL {
|
||||
URL(filePath: (path as NSString).expandingTildeInPath)
|
||||
}
|
||||
|
||||
@@ -254,13 +254,7 @@ final class Connection {
|
||||
store.startGlobalStream(after: status.lastEventSeq) { [weak self] in
|
||||
self?.reconnected(status.startedAt)
|
||||
}
|
||||
#if os(macOS)
|
||||
store.remote.start()
|
||||
#else
|
||||
if let sync = Servers.shared.sync {
|
||||
store.reportSync(sync)
|
||||
}
|
||||
#endif
|
||||
forwards.sync(store.api, Set(store.activeTasks().map(\.task.id)))
|
||||
Notifier.shared.deliver()
|
||||
return true
|
||||
|
||||
@@ -89,9 +89,7 @@ final class Store {
|
||||
let imageCache = ImageCache()
|
||||
let events = Listeners<ByreEvent>()
|
||||
let paneFocus: PaneFocus
|
||||
#if os(macOS)
|
||||
let remote: Remote
|
||||
#endif
|
||||
let forwards: Forwards
|
||||
let pages: Pages
|
||||
|
||||
@@ -115,10 +113,8 @@ final class Store {
|
||||
self.pages = pages
|
||||
leadFeed = Feed(shown: { true })
|
||||
paneFocus = PaneFocus(api: api)
|
||||
#if os(macOS)
|
||||
remote = Remote(api: api)
|
||||
remote.store = self
|
||||
#endif
|
||||
pages.popup = { [weak self] page in
|
||||
self?.openPage(page)
|
||||
}
|
||||
@@ -144,9 +140,7 @@ final class Store {
|
||||
stopped = true
|
||||
globalStream?.stop()
|
||||
leadStream?.stop()
|
||||
#if os(macOS)
|
||||
remote.stop()
|
||||
#endif
|
||||
drafts?.flush()
|
||||
await paneFocus.leave()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user