Cairn · module

Cairn.Effects

lean/Cairn/Effects.lean

The outside world as data (docs/effects.md): the time the host reports, the requests an app can make and the replies they get, and the subscriptions an app can ask for. Cairn.Input builds Effect and Event on these; the runtime's handling is Cairn.Runtime.World.

Order

Structures 3

structure

Cairn.Time

lean/Cairn/Effects.lean:17
Time : Type

The host's clock. mono is monotonic milliseconds (timers and durations use it); wall is milliseconds since the Unix epoch, UTC, and zone the local offset from UTC in seconds (for dates).

Fields
mono : Nat
wall : Int
zone : Int
Instances

Inhabited Repr

structure

Cairn.Secret

lean/Cairn/Effects.lean:58
Secret : Type

A header whose value comes from a secret the host reads when it sends the request, so the secret never reaches Lean, a frame or a log: header: scheme ++ value, where value is read from source.

Fields
header : String
scheme : String
source : Secret.Source
Instances

Repr Inhabited

structure

Cairn.Level

lean/Cairn/Effects.lean:224
Level : Type

One 20 ms window of a recording (320 samples at 16 kHz), as integers.

Fields
sumSq : Nat

The sum of its samples' squares.

peak : Nat

Its largest absolute sample (Int16.min counts as Int16.max).

Instances

Inhabited Repr

Inductive types 11

inductive

Cairn.Fault

lean/Cairn/Effects.lean:24
Fault : Type

Why a request failed. Failure is an ordinary reply.

Constructors
notFound : Fault
denied : Fault
timeout : Fault
network : Fault
invalid : Fault
other : Fault
Instances

Repr Inhabited

inductive

Cairn.Permission

lean/Cairn/Effects.lean:29
Permission : Type

A permission the person grants the app in System Settings (TCC).

Constructors
accessibility : Permission

Privacy & Security › Accessibility: typing into other apps, hearing a global key.

microphone : Permission

Privacy & Security › Microphone: recording.

Instances

Repr Inhabited

inductive

Cairn.Part

lean/Cairn/Effects.lean:37
Part : Type

A part of an upload body: bytes Lean built, or audio the host holds.

Constructors
bytes (b : ByteArray) : Part
wav (clip start : Nat) (stop : Option Nat) : Part

The recording of clip, 20 ms windows [start, stop) (320 samples each; to the end of the recording, with any partial last window, for none), as a WAV file: 16 kHz, mono, 16-bit PCM. Lean never sees the samples.

Instances

BEq Inhabited Repr

inductive

Cairn.Secret.Source

lean/Cairn/Effects.lean:46
Source : Type

Where the host reads a secret's value as it sends a request.

Constructors
env (file name : String) : Source

The environment variable name if set and not empty, else name's line in the KEY=value file file (Yap's API key).

keychain (account : String) : Source

The generic password item account in the login keychain, under the app's bundle identifier as its service (docs/effects.md, "Secrets in the Keychain").

Instances

Inhabited Repr

inductive

Cairn.Request

lean/Cairn/Effects.lean:71
Request : Type

Something the host does that answers back. Closed: adding a kind is a constructor, its encoding, a Reply.answers case and one host handler (docs/effects.md).

Constructors
readFile (path : String) : Request
writeFile (path : String) (data : ByteArray) : Request

Replace the file atomically, creating missing parent directories.

playSound (name : String) : Request

A named system sound ("Tink", "Pop", "Basso", …).

http (method url : String) (headers : List (String × String))
  (body : ByteArray) (timeoutMs : Nat) (secret : Option Secret := none)
  (capture : List (String × String) := []) (redact : Bool := false) : Request

An HTTP request. With a secret, the host adds its header as it sends (a missing secret answers failed notFound and sends nothing). With a non-empty capture, a 2xx reply whose body is a JSON object has each listed top-level string field ((field, account)) written to the Keychain item account and its value replaced by "" in the body Lean receives; all or nothing: a body that isn't a JSON object, or a listed field that is missing, repeated or not a string, answers failed invalid and writes nothing. Other replies pass through as they came. With redact, the request carries a secret the person typed (a secure field's text, Cairn.Text.SecureField): every dump, log and report prints its URL, headers and body as <redacted N bytes>, and the host sends it as given.

appendFile (path : String) (data : ByteArray) : Request

Append to the file, creating it (mode 600) and missing parent directories.

listDir (path : String) : Request

The names in a directory (not . and ..), sorted by their UTF-8 bytes.

deleteFile (path : String) : Request

Remove a file or a symbolic link; never a directory.

frontmostApp : Request

The app in front: its process id and name.

permission (p : Permission) (prompt : Bool) : Request

Whether the app holds p; with prompt, the system also asks the person if it doesn't.

typeText (pid : Nat) (text : String) (pressReturn : Bool) : Request

Bring process pid to the front and type text into it as key events, then Return if pressReturn. Needs Accessibility.

upload (method url : String) (headers : List (String × String))
  (secret : Option Secret) (body : List Part) (timeoutMs : Nat) : Request

http with a body of parts the host assembles and an optional secret header (OpenAI's transcription request: multipart framing from Lean, the clip's WAV and the key from the host).

forgetClip (clip : Nat) : Request

The host may drop the clip's samples.

openItem (target : String) : Request

Open target with its default app (the Finder for a folder, the default editor for a text file, System Settings for its URLs): a path (~/ is the home folder) or a URL with a scheme.

appRunning (bundleId : String) : Request

Whether an app with this bundle identifier is running.

readDefault (domain key : String) : Request

The value of key in the defaults domain domain (defaults read domain key), as UTF-8 text: a string as it is, a number or a boolean as its text (booleans as 1 or 0).

makeDir (path : String) : Request

Create the directory and its missing parents, each private (mode 700); done if it is already a directory.

loadImage (source : String) (reload : Bool) : Request

Load the image at source (a file path, ~/ for the home folder, or an http/https URL) and answer its size in pixels (Reply.image); the host keeps the decoded pixels under source and paints them for Style.images that name it. Lean never sees the pixels. An image the host already holds is answered from what it holds, unless reload, which reads source again.

forgetSecret (account : String) : Request

Delete the Keychain item account (Secret.Source.keychain): done, also when there is none.

Instances

Inhabited Repr BEq

inductive

Cairn.Request.Kind

lean/Cairn/Effects.lean:135
Kind : Type

The kind of a request, without its payload: what the runtime remembers while it is pending.

Constructors
readFile : Kind
writeFile : Kind
playSound : Kind
http : Kind
appendFile : Kind
listDir : Kind
deleteFile : Kind
frontmostApp : Kind
permission : Kind
typeText : Kind
upload : Kind
forgetClip : Kind
openItem : Kind
appRunning : Kind
readDefault : Kind
makeDir : Kind
loadImage : Kind
forgetSecret : Kind
Instances

Repr Inhabited

inductive

Cairn.Reply

lean/Cairn/Effects.lean:164
Reply : Type
Constructors
done : Reply

writeFile, appendFile, deleteFile, makeDir, forgetSecret and playSound succeeded.

bytes (data : ByteArray) : Reply

readFile's contents, or readDefault's value.

http (status : Nat) (headers : List (String × String)) (body : ByteArray) :
  Reply

An HTTP response, whatever its status.

failed (fault : Fault) (message : String) : Reply

Any request can fail.

names (names : List String) : Reply

listDir's names.

app (pid : Nat) (name : String) : Reply

frontmostApp's process id and name (empty when it has none).

flag (granted : Bool) : Reply

permission's or appRunning's answer.

image (width height : Nat) : Reply

loadImage's answer: the image's size in pixels (after its orientation is applied).

Instances

Repr Inhabited BEq

inductive

Cairn.Sub

lean/Cairn/Effects.lean:202
Sub : Type

An outside input an app asks for, as data derived from its state.

Constructors
every (ms : Nat) : Sub

A tick every ms milliseconds (at least 1), from the host.

watchFile (path : String) : Sub

changed whenever the file at path changes: written, replaced, created or removed.

record (clip : Nat) : Sub

Record clip from the microphone while active: started once the microphone is running, then audio; or failed if it can't start. Stopping it stops the microphone. The host keeps the samples for Part.wav. Needs Microphone.

globalKey (code : Nat) (modifier : Option Nat) : Sub

The key with virtual key code code (with modifier, the NSEvent.ModifierFlags bit that tells a modifier key's press from its release): keyDown, keyUp, and otherKey for any other key pressed while it is down. Needs Accessibility.

imageCache (bytes : Nat) : Sub

Keep the host's decoded images (Request.loadImage) within about bytes bytes of pixels while active: past it the host drops the images used least recently, never one the latest frame draws nor the one it just loaded, and reports each with evicted (^1011). Without it the host keeps every image. The smallest budget of those active wins.

Instances

Inhabited Repr

inductive

Cairn.SubEvent

lean/Cairn/Effects.lean:232
SubEvent : Type

What an active subscription reports.

Constructors
tick : SubEvent

every's tick.

changed : SubEvent

watchFile's file changed.

audio (frames peak : Nat) (windows : List Level) : SubEvent

record: frames more samples, their largest absolute value peak, and the 20 ms windows they complete, in order from the start of the clip.

started (t : Nat) : SubEvent

record: the microphone is running, since monotonic milliseconds t (when its start returned). Sent once, before any audio, and never after a failed that says it could not start.

keyDown (t : Nat) : SubEvent

globalKey: the key went down or up, or another key went down while it was held, at monotonic milliseconds t (the clock of Time.mono).

keyUp (t : Nat) : SubEvent
otherKey (t : Nat) : SubEvent
failed (fault : Fault) (message : String) : SubEvent

The subscription could not run (a permission missing, no microphone). It may still be running; an app stops it by not asking for it.

evicted (source : String) : SubEvent

imageCache: the host dropped source's pixels; sent after they are gone. An app that forgets the image when it hears this (Images.evicted, which also stops waiting for its loads) never takes an image for ready while the host has no pixels for it (Images.Cache.ready_held).

Instances

Repr Inhabited

inductive

Cairn.SubCmd

lean/Cairn/Effects.lean:260
SubCmd : Type

Runtime → host: start or stop a subscription, under the runtime's id for it.

Constructors
start (id : Nat) (s : Sub) : SubCmd
stop (id : Nat) : SubCmd
Instances

Inhabited Repr

inductive

Cairn.Msg

lean/Cairn/Effects.lean:267
Msg : Type

Runtime → app, through App.receive: the outside world.

Constructors
clock (t : Time) : Msg

The current time, delivered before anything else whenever it changed.

timer (name : String) : Msg

A timer the app set has come due.

reply (id : Nat) (r : Reply) : Msg

The answer to request id.

sub (s : Sub) (e : SubEvent) : Msg

An event from an active subscription.

Instances

Repr BEq Inhabited

Definitions 5

def

Cairn.Secret.bearer

lean/Cairn/Effects.lean:65
bearer (account : String) : Secret

Authorization: Bearer <value of the Keychain item account>.

def

Cairn.Request.kind

lean/Cairn/Effects.lean:142
kind : Request → Kind
def

Cairn.Request.redact

lean/Cairn/Effects.lean:152
redact : Request → Bool

Whether the request is marked as carrying a typed secret (http's redact).

def

Cairn.Request.Kind.capped

lean/Cairn/Effects.lean:159
capped : Kind → Bool

The kinds that count toward the cap on requests in flight (App.maxInFlight, docs/effects.md "Requests in flight"): the ones that can take seconds on the network. The others (files, sounds, permissions, typing) are sent at once.

def

Cairn.Reply.answers

lean/Cairn/Effects.lean:185
answers : Request.Kind → Reply → Bool

Whether a reply has the shape that answers a request of kind k.

Instances 43

instance

instReprByteArray_cairn

lean/Cairn/Effects.lean:10
instReprByteArray_cairn : Repr ByteArray

Byte payloads print as their size. (Core has no Repr ByteArray.)

instance

Cairn.instInhabitedTime

lean/Cairn/Effects.lean:21
instInhabitedTime : Inhabited Time
instance

Cairn.instDecidableEqTime

lean/Cairn/Effects.lean:21
instDecidableEqTime : DecidableEq Time
instance

Cairn.instReprTime

lean/Cairn/Effects.lean:21
instReprTime : Repr Time
instance

Cairn.instDecidableEqFault

lean/Cairn/Effects.lean:26
instDecidableEqFault : DecidableEq Fault
instance

Cairn.instReprFault

lean/Cairn/Effects.lean:26
instReprFault : Repr Fault
instance

Cairn.instInhabitedFault

lean/Cairn/Effects.lean:26
instInhabitedFault : Inhabited Fault
instance

Cairn.instReprPermission

lean/Cairn/Effects.lean:34
instReprPermission : Repr Permission
instance

Cairn.instDecidableEqPermission

lean/Cairn/Effects.lean:34
instDecidableEqPermission : DecidableEq Permission
instance

Cairn.instInhabitedPermission

lean/Cairn/Effects.lean:34
instInhabitedPermission : Inhabited Permission
instance

Cairn.instBEqPart

lean/Cairn/Effects.lean:43
instBEqPart : BEq Part
instance

Cairn.instInhabitedPart

lean/Cairn/Effects.lean:43
instInhabitedPart : Inhabited Part
instance

Cairn.instReprPart

lean/Cairn/Effects.lean:43
instReprPart : Repr Part
instance

Cairn.Secret.instInhabitedSource

lean/Cairn/Effects.lean:53
instInhabitedSource : Inhabited Source
instance

Cairn.Secret.instDecidableEqSource

lean/Cairn/Effects.lean:53
instDecidableEqSource : DecidableEq Source
instance

Cairn.Secret.instReprSource

lean/Cairn/Effects.lean:53
instReprSource : Repr Source
instance

Cairn.instReprSecret

lean/Cairn/Effects.lean:62
instReprSecret : Repr Secret
instance

Cairn.instInhabitedSecret

lean/Cairn/Effects.lean:62
instInhabitedSecret : Inhabited Secret
instance

Cairn.instDecidableEqSecret

lean/Cairn/Effects.lean:62
instDecidableEqSecret : DecidableEq Secret
instance

Cairn.instInhabitedRequest

lean/Cairn/Effects.lean:130
instInhabitedRequest : Inhabited Request
instance

Cairn.instReprRequest

lean/Cairn/Effects.lean:130
instReprRequest : Repr Request
instance

Cairn.instBEqRequest

lean/Cairn/Effects.lean:130
instBEqRequest : BEq Request
instance

Cairn.Request.instReprKind

lean/Cairn/Effects.lean:140
instReprKind : Repr Kind
instance

Cairn.Request.instDecidableEqKind

lean/Cairn/Effects.lean:140
instDecidableEqKind : DecidableEq Kind
instance

Cairn.Request.instInhabitedKind

lean/Cairn/Effects.lean:140
instInhabitedKind : Inhabited Kind
instance

Cairn.instReprReply

lean/Cairn/Effects.lean:182
instReprReply : Repr Reply
instance

Cairn.instInhabitedReply

lean/Cairn/Effects.lean:182
instInhabitedReply : Inhabited Reply
instance

Cairn.instBEqReply

lean/Cairn/Effects.lean:182
instBEqReply : BEq Reply
instance

Cairn.instInhabitedSub

lean/Cairn/Effects.lean:220
instInhabitedSub : Inhabited Sub
instance

Cairn.instReprSub

lean/Cairn/Effects.lean:220
instReprSub : Repr Sub
instance

Cairn.instDecidableEqSub

lean/Cairn/Effects.lean:220
instDecidableEqSub : DecidableEq Sub
instance

Cairn.instInhabitedLevel

lean/Cairn/Effects.lean:229
instInhabitedLevel : Inhabited Level
instance

Cairn.instReprLevel

lean/Cairn/Effects.lean:229
instReprLevel : Repr Level
instance

Cairn.instDecidableEqLevel

lean/Cairn/Effects.lean:229
instDecidableEqLevel : DecidableEq Level
instance

Cairn.instReprSubEvent

lean/Cairn/Effects.lean:257
instReprSubEvent : Repr SubEvent
instance

Cairn.instDecidableEqSubEvent

lean/Cairn/Effects.lean:257
instDecidableEqSubEvent : DecidableEq SubEvent
instance

Cairn.instInhabitedSubEvent

lean/Cairn/Effects.lean:257
instInhabitedSubEvent : Inhabited SubEvent
instance

Cairn.instInhabitedSubCmd

lean/Cairn/Effects.lean:263
instInhabitedSubCmd : Inhabited SubCmd
instance

Cairn.instDecidableEqSubCmd

lean/Cairn/Effects.lean:263
instDecidableEqSubCmd : DecidableEq SubCmd
instance

Cairn.instReprSubCmd

lean/Cairn/Effects.lean:263
instReprSubCmd : Repr SubCmd
instance

Cairn.instReprMsg

lean/Cairn/Effects.lean:276
instReprMsg : Repr Msg
instance

Cairn.instBEqMsg

lean/Cairn/Effects.lean:276
instBEqMsg : BEq Msg
instance

Cairn.instInhabitedMsg

lean/Cairn/Effects.lean:276
instInhabitedMsg : Inhabited Msg