| Safe Haskell | None |
|---|---|
| Language | GHC2024 |
Free.Agent.Cli
Description
Synopsis
- data Cli = Cli {
- cliCommand :: FilePath
- cliArgv :: Text -> Maybe Text -> [String]
- cliStdin :: Text -> String
- cliSessionFile :: FilePath
- cliSessionId :: Text -> Maybe Text
- cliStale :: ExitCode -> Text -> Bool
- cliScrub :: Text -> Text
- cliStderr :: StderrPolicy
- cliStderrTee :: Maybe FilePath
- cliTranscript :: Maybe (IORef Int, FilePath)
- data StderrPolicy
- hermesCli :: Maybe Text -> Maybe Text -> FilePath -> Cli
- kimiCli :: Maybe Text -> Maybe Text -> FilePath -> Cli
- grokCli :: Maybe Text -> FilePath -> Cli
- parseSessionId :: Text -> Maybe Text
- cleanCliOut :: Text -> Text
- cliQuery :: Cli -> Text -> IO Text
- cliQueryBS :: Cli -> Text -> IO ByteString
- cliShard :: Text -> Cli -> IO (Shard IO [Post Text] [Post Text])
- data TranscriptRecord = TranscriptRecord {
- trPostId :: Int
- trTimestamp :: UTCTime
- trExitCode :: Int
- trElapsedMs :: Int
- trSessionId :: Maybe Text
- trRaw :: Text
- encodeTranscriptLine :: TranscriptRecord -> Text
- queryShard :: Text -> (Text -> IO Text) -> IO (Shard IO [Post Text] [Post Text])
- queryShardWith :: (Text -> [Post Text] -> [PostId] -> Text -> [Post Text]) -> Text -> (Text -> IO Text) -> IO (Shard IO [Post Text] [Post Text])
- synthShard :: Text -> (Text -> IO Text) -> IO (Shard IO [Post Text] [Post Text])
- echoShard :: Text -> IO (Shard IO [Post Text] [Post Text])
- runShardIO :: Shard IO [Post Text] [Post Text] -> [Post Text] -> IO [Post Text]
- sessionPrompt :: [Post Text] -> Text
- replyPosts :: Text -> [Post Text] -> [PostId] -> Text -> [Post Text]
- synthesisPosts :: Text -> [Post Text] -> [PostId] -> Text -> [Post Text]
Invocation recipe
Invocation recipe for a CLI agent.
Everything a session needs is plain data; there are no laws here beyond what the CLI itself honours.
Constructors
| Cli | |
Fields
| |
data StderrPolicy Source #
stderr routing for a CLI agent's output channels.
Precedent: Muster.Connector posts -- stdout -- / -- stderr --
marked sections; StderrMark is the in-body equivalent.
Constructors
| StderrDrop | Discard stderr (use with |
| StderrMerge | Concatenate stdout and stderr (the historical behaviour). |
| StderrMark | Append stderr after a |
Instances
| Eq StderrPolicy Source # | |
Defined in Free.Agent.Cli | |
| Show StderrPolicy Source # | |
Defined in Free.Agent.Cli Methods showsPrec :: Int -> StderrPolicy -> ShowS # show :: StderrPolicy -> String # showList :: [StderrPolicy] -> ShowS # | |
hermesCli :: Maybe Text -> Maybe Text -> FilePath -> Cli Source #
Recipe for the hermes CLI: hermes chat -q <prompt> … --resume <sid>.
kimiCli :: Maybe Text -> Maybe Text -> FilePath -> Cli Source #
Recipe for the kimi CLI: kimi -p <prompt> [-m <model>] [--provider <provider>] [-r <sid>],
text output. kimi prints a plain-text resume hint line, so scraping and
scrubbing are line-oriented — no JSON needed. Note: kimi exits 0 even
when the prompt fails (and --auto cannot combine with -p), so stale
detection is output-based.
stderr (thinking tool progress notices) is dropped from the reply
but teed raw to <sessionFile>.stderr.log — interiority stays
searchable, never silently dropped.
grokCli :: Maybe Text -> FilePath -> Cli Source #
Recipe for the grok CLI: grok -p <prompt> --output-format json
[--resume <sid>]. Plain output carries no session id, so the JSON
format is used and the text/sessionId@ fields are extracted.
cleanCliOut :: Text -> Text Source #
Hermes-flavoured TUI noise filter: drops session chatter, decorative rules, and ANSI lines; keeps plain reply text with no trailing newline.
Query
cliQuery :: Cli -> Text -> IO Text Source #
One query against a CLI agent. First call (or no stored session) runs fresh; subsequent calls resume the stored session id. A stale session falls back to fresh and records the new id. Scraped ids are re-persisted on every successful call, so server-side session rotation is followed.
cliQueryBS :: Cli -> Text -> IO ByteString Source #
Like cliQuery but returns raw stdout as ByteString before
any decoding or filtering. Uses CreatePipe to read bytes directly
from the process rather than going through the locale-aware String
path of readCreateProcessWithExitCode.
Shard adapters
cliShard :: Text -> Cli -> IO (Shard IO [Post Text] [Post Text]) Source #
A live CLI agent as a list Shard. Session file and process stay
inside IO — apply-only at this boundary. who is the agent nick
(from on emitted posts).
Transcript
data TranscriptRecord Source #
One transcript record, as JSONL appended to the transcript log.
Constructors
| TranscriptRecord | |
Fields
| |
encodeTranscriptLine :: TranscriptRecord -> Text Source #
Encode a transcript record as a single JSON line (no trailing newline).
Generic adapters (re-exported from Query)
queryShard :: Text -> (Text -> IO Text) -> IO (Shard IO [Post Text] [Post Text]) #
Opaque evaluate seat: any Text -> IO Text behind list ends.
Commit assembles a session prompt from the input posts; emit is
replyPosts of the query result (empty = quiet).
TODO: this generic seat does not have access to stamped log ids, so emitted replies carry no thread edge. Callers that need provenance should use a variant that supplies parent ids.
queryShardWith :: (Text -> [Post Text] -> [PostId] -> Text -> [Post Text]) -> Text -> (Text -> IO Text) -> IO (Shard IO [Post Text] [Post Text]) #
queryShard parameterised on the reply-to-posts builder.
synthShard :: Text -> (Text -> IO Text) -> IO (Shard IO [Post Text] [Post Text]) #
Opaque synthesis seat: like queryShard, but the emit cites every
input's sender as ancestry (synthesisPosts). For seats that fold the
whole input into one answer — the honest-provenance twin of
queryShard.
TODO: like queryShard, the generic seat has no ids and therefore emits
syntheses without thread edges.
echoShard :: Text -> IO (Shard IO [Post Text] [Post Text]) #
Mock seat: reply body is the session prompt (echo).
Demonstrates the living-agent path without a real query.
runShardIO :: Shard IO [Post Text] [Post Text] -> [Post Text] -> IO [Post Text] #
One closed shard turn: commit ins, emit replies.
sessionPrompt :: [Post Text] -> Text #
Session assembly for the opaque seat: bodies, oldest-first, one per line.
This is the discoverable side of the boundary (data). How the query folds it is not.
replyPosts :: Text -> [Post Text] -> [PostId] -> Text -> [Post Text] #
Build reply posts from a cleaned agent response.
Addresses the last input's sender, preserves any other names on the
original wire (e.g. the bus channel), and threads onto the last input's
PostId when one is supplied. Empty reply → no posts (quiet).
The caller passes one PostId per input post in the same order. If the
ids are missing or misaligned, the reply is still addressed correctly but
carries no thread edge (see mkPost) — the honest fallback when a shard
does not have access to the stamped log.
synthesisPosts :: Text -> [Post Text] -> [PostId] -> Text -> [Post Text] #
Build one synthesis post from a cleaned agent response.
The honest twin of replyPosts for seats that fold every input into
their answer: ancestry cites every input's PostId (see synthesis),
and the audience is every input's sender and wire name, minus self.
Empty reply or no inputs → no posts (quiet).
The caller passes one PostId per input post. If ids are missing the
synthesis is still addressed correctly but carries no thread edge.