io library
dart:io-backed execution environment for VM, desktop, and mobile.
Separate entry point so the core library (flutter_agent_harness.dart)
stays pure Dart and web-compilable. Import this only from platform code
that is allowed to touch dart:io.
Classes
- AiinCallback
- One OAuth proxy redirect caught by AiinCallbackServer.
- AiinCallbackServer
- Loopback HTTP server catching the AIIN OAuth proxy redirect.
- CaffeinatePowerRunner
-
macOS runner: one
caffeinatechild per held assertion (per run by default, per session atpower.hold: session), bound to the fa pid by-w. Kill-safe: ProcessPowerAssertionHandle.release terminates the child even though-wwould also end it at process exit. - ChatGptOAuthCallback
- ChatGptOAuthLocalCallbackServer
- CliConfig
- Persisted CLI configuration.
- CodeMieSsoCallbackServer
- HubJoin
-
One accepted
join(spec § join). - HubSocket
- One live hub connection.
- HubTransport
-
Dials a hub URL (
ws://host:port/ws) — the only network operation the hub fabric performs. Implementations throw when the hub is unreachable or rejects the upgrade (wrong pairing token); the repository treats any throw as "not connected" and retries with backoff. - IoHubSocket
-
One live hub connection over a
dart:ioWebSocket. Binary frames are dropped at the boundary (the hub speaks text frames only and answers them with abad_frameerror). - IoHubTransport
-
A HubTransport over a
dart:ioWebSocket. - IoLspTransport
- An LspTransport over a spawned process's stdio.
- IoMcpByteChannel
- A McpByteChannel over a spawned process's stdio.
- IsolateSessionParseExecutor
- Parses every batch in a fresh short-lived isolate.
- LocalExecutionEnv
- Local ExecutionEnv: LocalFileSystem plus LocalShell.
- LocalFileSystem
-
Local-disk FileSystem backed by
dart:io. - LocalHub
- A complete in-memory DAP/1 hub for local development and tests.
- LocalShell
-
Minimal local shell backed by
dart:ioProcess. - OpenRouterOAuthLocalCallbackServer
- A one-shot HTTP server that captures the OpenRouter OAuth callback on localhost.
- ProcessPowerAssertionHandle
-
One spawned helper process holding an assertion.
releasekills the child (dropping the assertion immediately) and waits for its exit — BOUNDED by killTimeout (5s default): a helper that ignores SIGTERM gets one follow-up SIGKILL and release proceeds anyway (issue #326: an unbounded await on a stuck helper would hang the run's settle). An unexpected helper death flips held so/powernever reports a dead assertion as live. - QjsProcessRuntime
-
A
JsrRuntimeover aqjssubprocess using the stdio wire protocol. - SecureKeyRunResult
- Result of one helper-process invocation.
- SessionParseBatch
- One bounded batch of raw JSONL entry lines (never the header line).
- SessionParseExecutor
- Where CPU-bound session JSONL parsing runs (issue #199).
- SessionParseResult
- Per-line parse outcomes, parallel to SessionParseBatch.lines.
- Sqlite3Engine
-
A SqliteEngine opening databases through
package:sqlite3(FFI). - SystemdInhibitPowerRunner
-
Linux runner (best-effort):
systemd-inhibitholding idle (and, at thesystemlevel, sleep) inhibition while its watchdog command lives — the watchdog polls the fa pid, so the assertion dies with the fa process even if fa is SIGKILLed.
Constants
- envHubSecret → const String
-
The environment variable carrying the hub password for
fa hub serve(distinct fromDAP_MASTER_SECRET, which is the CLIENT credential). -
headlessTextExtensions
→ const Set<
String> - File extensions whose content is inlined as the headless prompt body.
- maxConcurrentSessionParseBatches → const int
- Max parse batches in flight on the executor path of parseSessionLines (issue #503): enough to keep the cores busy on a marathon walk, bounded so concurrent callers (windowed open + listing fan-out) never spawn an unbounded isolate storm.
- secureKeyServiceName → const String
- The service/account scope every backend namespaces its entries under.
- sessionParseBatchMaxBytes → const int
- Max chars per parse transfer.
- sessionParseBatchMaxLines → const int
- Max lines per parse transfer.
Properties
- secureKeyProcessRunner ↔ SecureKeyRunner
-
Direct access to the default runner for timeout tests.
getter/setter pair
- secureKeyProcessTimeout ↔ Duration
-
The per-invocation cap for helper processes (
security,secret-tool,powershell.exe) — they can block on a system keychain modal on a broken keychain. Tests shorten it.getter/setter pair
Functions
-
apiKeyEnvNames(
String provider) → List< String> -
The env names that can hold
provider's API key: the catalog spec's names (providerCatalog; copilot → COPILOT_GITHUB_TOKEN, kimi → KIMI_API_KEY, …), plus the two non-catalog slots; unknown kinds keep the historical OpenRouter/OpenAI pair. -
attachPathReference(
String path) → String -
The
[attached file: <path> — read it with your tools]marker: shared by the positional file-as-prompt resolution and the--attachnon-image passthrough (issue #196) so the wording cannot drift. -
buildRedactionPipeline(
RedactionConfig? config) → RedactionPipeline? -
Assembles the layered RedactionPipeline (issue #24) from the
redact:config section and this process's well-known secrets. Returnsnullwhen the section disables redaction (enabled: false) so the hooks never attach. Secret registration happens through buildSecretRedactor'spipelineparameter — call that first with this pipeline, or register later via RedactionPipeline.registerSecret. -
buildSecretRedactor(
{Map< String, String> roleSecrets = const {}, SecureKeyCache? keys, Map<String, String> ? env, RedactionPipeline? pipeline}) → SecretRedactor - Assembles the startup SecretRedactor: the API keys this CLI knows about (every catalog provider's env names, the web-search slots) are masked from tool results and the provider context so they cannot leak into the LLM conversation or the session files. The rotation stacks collected for the roles resolver and the values preloaded from the platform secure store (keychain values must never reach the transcript either) are redacted too. The spawned shell already inherits the process environment, so no env injection is needed here.
-
collectQueueSecrets(
List< ProviderQueueEntry> entries, SecureKeyCache keys, {Map<String, String> ? env}) → Map<String, String> -
Collects the secrets snapshot for the queue: each entry's
apiKeyEnvresolves from the environment, else the secure store (env wins — the same precedence as the roles snapshot). -
collectRoleSecrets(
ModelRolesConfig rolesConfig, SecureKeyCache keys, {Map< String, String> ? env}) → Map<String, String> -
Collects the secrets snapshot for the model-roles resolver: every
provider catalog env name plus its rotation stack (
NAME,NAME_2,NAME_3, ...), plus any base name referenced by an explicitapiKeyNamein the roles config. The platform secure store backs up base names where the environment has none (env wins; rotation stacks stay env-only — secure storage holds base names only). -
defaultHubStateFile(
{String? home, Map< String, String> ? environment}) → File -
The default hub state file (
~/.dap/hub.json) — the hub's master secret (the "hub password") and enrolled per-client secrets live here sofa hub serverestarts keep both.DAP_HUB_STATE_FILE(fromenvironment) wins outright;homeoverrides~(test seam). -
faProviderPreconfig(
CliArgs parsed, CliConfig saved, {required Map< String, String> env}) → EnvProviderPreconfig? -
The explicit
FA_PROVIDER_*env preconfig (Docker/headless):FA_PROVIDER_TYPE+FA_PROVIDER_NAME+FA_PROVIDER_CONFIG(a JSON object with requiredbaseUrl/modeland an optionalapiKeyEnvVar) plus the key env var the config references. Every text input has a_BASE64twin (FA_PROVIDER_CONFIG_BASE64,<apiKeyEnvVar>_BASE64) for platforms that mangle special characters; when both carry the same value the plain one is used. This is an explicit declaration, so it wins over the saved config restore too — a container that declares its provider in env vars runs on it, store or config notwithstanding. An explicit--providerflag means full manual control and disables the preconfig entirely (mixing the flag's provider with the env endpoint would be a silent misconfiguration). -
handleRelayRequest(
HttpRequest request, {required String? requireCredential(), required String? allowedOrigin}) → Future< void> -
One
POST /relaycall (issue #633): the desktop add-in taskpane has no extension to carry its provider HTTP, so the pane proxies it through the local hub, which fetches CORS-free by construction. The body is the SW-bridge request envelope{url, method?, headers?, bodyB64?}; the upstream answer is streamed back raw (status + content-type + body), so provider SSE flows through incrementally. -
hidShiftPollingEnabled(
Map< String, String> env) → bool -
Whether the session may poll the HID Shift state at all: the
FA_TUI_SHIFT_HIDkill switch wins, then SSH detection — an SSH session has no WindowServer attach, so the CoreGraphics call blocks instead of answering (issue #355). -
homeDirectory(
) → String? -
Returns the user's home directory, or
nullif it cannot be determined. -
hostPowerRunner(
{required int pid, String? os, PowerProcessLauncher? launcher}) → PowerAssertionRunner -
The platform runner: caffeinate on macOS, systemd-inhibit on Linux, a
no-op with an explicit note everywhere else.
osoverrides the detected platform (tests);launcheroverrides the spawn (tests). -
hubAuthVerdict(
String? credential, String? masterSecret, Iterable< String> enrolledSecrets) → HubAuthVerdict - Pure auth decision for one upgrade attempt (unit-testable — the socket wrapper stays trivial so the CRAP ratchet holds).
-
hubEnrollDecision(
{required bool isProtected, required bool isMaster, required String newSecret()}) → ({String? issueSecret, Map< String, Object?> reply}) -
Pure enroll decision for one
{"t":"enroll"}frame (the socket wrapper stays trivial so the CRAP ratchet holds):replyis the frame to send;issueSecretis the per-client credential to persist for the agent (null = nothing to persist — open hub or a refused enroll on a protected hub). -
hubUpgradeCredential(
String? authorizationHeader, Map< String, String> queryParameters) → String? -
The upgrade credential: the
Authorization: Bearerheader (native clients) or thedap_tokenquery param (browser WebSocket cannot set headers — the loopback hub accepts the query form). -
ioLspTransportFactory(
LspServerConfig config, String cwd) → Future< LspTransport> -
The process-capable LspTransportFactory for CLI/desktop hosts: spawns
config.command config.args...in the workspace root. -
ioMcpTransportFactory(
McpServerConfig server, String cwd) → Future< McpTransport> -
The process-capable McpTransportFactory for CLI/desktop hosts: spawns
command args...in the workspace root. Remote (HTTP) servers are pure Dart and never come through here — the manager routes them itself. -
isShiftPressedViaHid(
) → bool - The live Shift state from the HID system; false when CoreGraphics is unavailable. Call only after resolveHidShiftPressed gated the session — see the library docs.
-
loadCliConfig(
String homeDir) → CliConfig -
Loads CliConfig from
~/.fah/config.yaml. -
loadHubIdentity(
String path) → Future< HubIdentity> -
Loads the hub identity persisted at
path, creating it (mode 0600, atomic temp+rename) on first use. File format — the SAME lines the CLI'sfa_hub_clientkey files use — so a host may share one identity across surfaces when it wants to:ed25519:<seed b64>,x25519:<priv b64>,x25519pub:<pub b64>. The pub line is informational; keys are always re-derived from the private scalars, so a torn legacy write can never pair a mismatched pub. -
loadProjectCompactionEngine(
String projectDir) → CompactionEngine? -
Loads the PROJECT-level
compaction:section from<projectDir>/.fah/config.yaml— the engine choice travels with the repo (issue #148). Project wins over the user-levelcompaction:section; the runtime flag wins over both. Null when the file or the section is absent/unreadable; a present-but-invalid section throws ConfigException (strict, like the user config). -
loadProjectCubeSettings(
String projectDir) → CubeSettings? -
Loads the PROJECT-level
cube:section from<projectDir>/.fah/config.yaml— the git-backed sandbox default travels with the repo. Project wins over the user-levelcube:section. Null when the file or the section is absent/unreadable; a present-but-invalid section throws ConfigException (strict, like the user config). -
loadProjectMemoryConfig(
String projectDir) → MemoryConfig? -
Loads the PROJECT-level
memory:section from<projectDir>/.fah/config.yaml— the git-backed memory path travels with the repo (anyone cloning gets the pointer AND the memory). Project wins over the user-levelmemory:section. Null when the file or the section is absent/unreadable; a present-but-invalid section throws ConfigException (strict, like the user config). -
loadProjectSpillsConfig(
String projectDir) → SpillsConfig? -
Loads the PROJECT-level
spills:section from<projectDir>/.fah/config.yaml(issue #678) — the spilling thresholds travel with the repo. Project wins wholesale over the user-levelspills:section, like the other project sections. Null when the file or the section is absent; the parse itself is tolerant, so this never throws. -
loadProjectToolsConfig(
String projectDir) → ToolsConfig? -
Loads the PROJECT-level
tools:section from<projectDir>/.fah/config.yaml— the git-backed availability policy travels with the repo. The PROJECT scope is consumed live (separate from the saved global CliConfig.tools) so the deepest-wins resolution can stack both. Null when the file or the section is absent/unreadable; a present-but-invalid section throws ConfigException (strict, like the user config). -
loadProjectWireDump(
String projectDir) → bool? -
Loads the PROJECT-level
trajectory:section'swireDumpflag from<projectDir>/.fah/config.yaml(issue #385). Null when the file or the section is absent/unreadable; a present-but-invalid section throws ConfigException (strict, like the user config). -
loadPromptFile(
String path, {required String homeDir, required String baseDir, required String source}) → String -
Reads
pathas a prompt override file: YAML frontmatter is stripped (so theprompts/**Markdown sources can be copied verbatim as overrides) and the body is trimmed. A missing or unreadable file throws ConfigException prefixed withsource— never a silent fallback. -
loadPromptOverrideSource(
String value, {required String homeDir, required String baseDir, required String source}) → String - Resolves one raw override value: a file path per looksLikePromptFilePath (read via loadPromptFile), anything else is inline text (trimmed).
-
logFileFromEnv(
Map< String, String> env) → String? -
The
FA_LOG_FILEenv twin of the--log-fileflag: the tee path, for Docker/headless hosts that cannot pass flags. Absent or blank yields null (no tee intent); the flag wins when both are set. -
looksLikePromptFilePath(
String value) → bool -
Whether a raw
prompts:value names a file rather than inline text: an absolute path, a~/home-relative path, a.//../relative path, or anything ending in a Markdown/text extension (.md,.markdown,.txt). -
openBrowser(
String url) → Future< bool> -
Opens
urlin the user's default browser. -
optionalProviderApiKey(
String provider, SecureKeyCache keys, {String? baseUrl, Iterable< String> ? scopedKeyNames, Map<String, String> ? env}) → String? -
Resolves
provider's API key headlessly. On the catalog spec's DEFAULT endpoint: a genuine environment value of the catalog env names, then endpoint-scoped secure-store entries (FA_KEY_<HOST>— what /provider writes — plus any saved custom entry's name-scoped key for this endpoint), then legacy env-name store entries from older versions. On ANY OTHER endpoint only the endpoint-scoped entries resolve — the catalog env names describe the default endpoint and must never hijack a custom one (issue #40: the user'sOPENROUTER_API_KEYenvironment key silently serving api.z.ai), mirroring the shared resolveEndpointKey chain.envoverrides Platform.environment (tests). -
parseImagesSection(
Object? node) → ImageRegistryConfig? -
Parses the
images:section (session image registry, issue #171):registry(kill switch) andmaxPerRequest(per-request unique-image cap). Strict — a bad schema throws ConfigException instead of silently keeping the defaults. Public so the settings flow's reload-after-write (issue #395) reuses the same parser the boot runs. -
parseProviderTimeouts(
Object? node) → ProviderTimeoutsOverride? -
Parses the
providerTimeouts:section: provider watchdog overrides (see ProviderTimeoutsOverride). Strict — a bad schema throws ConfigException instead of silently keeping the defaults. Public so the settings-hub resilience flow (issue #393) reloads the saved section with the SAME parser boot uses. -
parseSessionEntryLinesSync(
SessionParseBatch batch) → SessionParseResult - Parses one batch right here — the inline executor's body and the isolate worker's entry point share it, so both paths run the exact same parse code (issue #199 AC4 parity).
-
parseSessionLines(
List< String> lines, {required String filePath, required int firstLineNumber, SessionParseExecutor? executor, bool shallowGiantCustoms = false}) → Future<List< SessionRecord?> > -
Parses
linesthroughexecutor— or inline, batch by batch, when it is null — and returns one slot per line in file order (nullwhere a line was torn/foreign). -
platformSecureKeyStore(
{SecureKeyRunner? runner, String? platform}) → SecureKeyStore -
Picks the SecureKeyStore for the host OS.
platformandrunnerare test seams; production callers use the defaults. -
probeHidShiftPolling(
{void entry(SendPort port)?, Duration timeout = const Duration(milliseconds: 300)}) → Future< bool> -
Runs
entryin a fresh isolate and waitstimeoutfor its completion ACK. True means the HID read COMPLETED in time — the session is healthy enough to poll; a hang (a GUI-less session where CoreGraphics blocks) answers false. Any message counts: the payload value is ignored. The isolate is killed unconditionally — a wedged probe never leaks. -
readHubState(
File file) → HubState - Reads the hub state file; a missing or invalid file counts as empty.
-
readHubStateSecret(
File file) → String? - Reads just the master secret from a hub state file; a missing or invalid file counts as "no password".
-
relayAllowedOrigin(
String? origin) → String? -
The CORS answer for a relay request's
origin: the allowlisted taskpane origins get their origin echoed back (never*— a hostile page must not be able to read this proxy), anything else gets null (= no CORS headers = the browser blocks the read). -
resolveEffectiveCliArgs(
CliArgs parsed, CliConfig saved, {required Map< String, String> env}) → ({CliArgs args, EnvProviderPreconfig? faPreconfig, String provider}) -
Provider/model restoration. Precedence: an explicit
--providerflag (full manual control, preconfigs disabled) > theFA_PROVIDER_*env declaration (faProviderPreconfig) > the savedprovider:(the persisted /provider switch) > the parsed default. Only kinds the legacy single-model path can build are restored (chatgpt-codex keeps the openai-completions default; its OAuth flow re-establishes on demand). -
resolveEnabledPlugins(
List< String> argPlugins, Map<String, dynamic> config) → Set<String> -
'hub'ships default-on. A.fah/packages.yamlentry enables a plugin with a truthy value (inspect_image:/hub: {url: …}) and opts it OUT with a falsy one (hub: false,hub:) — so only the keys with truthy values join the enabled set. -
resolveHeadlessPrompt(
{String? prompt, String? promptFile, List< String> positionals = const []}) → String? - Resolves the headless prompt from parsed CLI arguments.
-
resolveHidShiftPressed(
{Map< String, String> ? env, bool isMacOS = true, void probeEntry(SendPort port)?, Duration probeTimeout = const Duration(milliseconds: 300)}) → Future<bool Function()?> -
Resolves the TUI host callback for Shift detection: the HID poll when
the session allows it, null when it must stay off — a non-macOS host,
the kill switch, an SSH session, or a startup probe whose HID read
failed to complete in time (issue #355). Wiring keys on probe
COMPLETION, never on the live Shift value it happened to read. The
probe runs ONCE, at startup, off the UI isolate;
probeEntryis the test seam for the isolate payload. -
resolveInteractiveFileReference(
String text, {InputPromptFileFactory fileOf = _defaultFileOf}) → String - Resolves an interactive prompt that starts with a pasted file path.
-
resolvePromptFilePath(
String path, {required String homeDir, required String baseDir}) → String -
Expands a leading
~tohomeDirand resolves a relative path againstbaseDir. -
resolvePromptOverrides(
Map< String, String> raw, {required String homeDir, required String baseDir}) → PromptOverrides -
Resolves the validated raw
prompts:map (see parsePromptOverrideMap) into a PromptOverrides. Relative file paths resolve againstbaseDir(the CLI passes the agent cwd); thesystemalias canonicalizes tocli/mode_code. Missing files throw ConfigException. -
resolveProviderQueueAtBoot(
{required String projectDir, required String homeDir, Map< String, String> ? env}) → ProviderQueueResolution -
Resolves the FA_PROVIDERS_QUEUE scope chain at boot: the env var, the
project
.fah/config.yamlprovidersQueue:section, the user~/.fah/config.yamlone. Absent files/sections are not present; a present-but-invalid section throws ConfigException naming the file (strict, like every other config section). -
resolveStartupCubeSource(
{String? flagConfigPath, String? flagName, CubeSettings? project, CubeSettings? user}) → String? -
The startup cube source (fa_cube): explicit flags win, then the project
cube:section, then the usercube:section — each config section applies only when enabled. Null = start unsandboxed. -
roleKeyNames(
ModelRolesConfig rolesConfig) → Set< String> -
The explicit
apiKeyNames referenced by a roles config (the secure-store preload set; the catalog names are always preloaded). -
runAiinConnectCliFlow(
{required void onStatus(String), Future< bool> openBrowserFn(String) = openBrowser, Client? client, String authBaseUrl = aiinAuthBaseUrl, Duration timeout = const Duration(minutes: 5)}) → Future<AiinConnectResult?> - Runs the full AIIN connect flow for CLI/desktop hosts:
-
runChatGptOAuthCliFlow(
{required void onStatus(String), Future< bool> openBrowserFn(String) = openBrowser, Future<ChatGptOAuthCredentials> exchangeFn({required String code, required String redirectUri, required String verifier}) = _defaultExchange, Duration timeout = const Duration(minutes: 5)}) → Future<ChatGptOAuthCredentials?> -
runCodeMieSsoCliFlow(
{required String codeMieUrl, required void onStatus(String), Future< bool> openBrowserFn(String) = openBrowser}) → Future<CodeMieSsoCredentials?> - Runs the CodeMie SSO login: starts the callback server, opens (or prints) the organization's login URL, waits for the token, and decodes it into CodeMieSsoCredentials. Returns null on cancel/timeout/failure.
-
runOpenRouterOAuthCliFlow(
{required void onStatus(String), Future< bool> openBrowserFn(String url) = openBrowser, Future<OpenRouterOAuthKey> exchangeFn({required String code, required String codeVerifier, String? label}) = _defaultExchange, String keyLabel = openRouterDefaultKeyLabel}) → Future<OpenRouterOAuthKey?> - Runs the full automatic OAuth flow for the CLI: starts a localhost server, opens the browser, waits for the callback, and exchanges the code.
-
saveCliConfig(
String homeDir, CliConfig config) → Future< void> -
Saves CliConfig to
~/.fah/config.yaml. -
saveHubIdentity(
String path, HubIdentity identity) → Future< void> -
Saves
identity's seeds topath(the host's rotation/rebind path). -
secureKeyPreloadNames(
CliConfig saved, {required String? baseUrl}) → Set< String> -
Every provider key name the startup snapshot must preload: each catalog
provider's env names, the endpoint-scoped
FA_KEY_<HOST>name for every catalog default endpoint plus the configured endpoint and every saved custom provider's, the two non-catalog media slots, and the explicitapiKeyNames referenced by the roles config. -
splitServeA2aArgs(
List< String> args) → ({List<String> cliArgs, bool serveA2a, bool serveBridge}) -
fa serve [--a2a|--bridge] [--port N] [--token T]interception: the args parser does not know the serve forms, soargsis scanned for the bareserveinvocation and the serve-specific flags (and their values) are stripped from the list that reaches parseCliArgs. Exactly one serve form must be selected:serveA2a/serveBridgesay which, and the caller fails with the usage line when aserveinvocation carries neither, both, or is missing its marker. -
splitSessionParseBatches(
List< String> lines, {required String filePath, required int firstLineNumber, bool shallowGiantCustoms = false}) → List<SessionParseBatch> -
Splits
linesinto bounded transfer batches. Issue #199 E5: an oversize line becomes its own batch, so one huge record can never stall a batch beyond its own parse. -
startupApiKey(
String provider, SecureKeyCache keys, {required String? baseUrl, required List< CustomProviderEntry> customProviders, required bool defaultRoleResolved, required bool interactive, Map<String, String> ? env}) → String - Headless startup API-key resolution: a base URL other than the catalog default (--base-url or config baseUrl) means a user-configured endpoint: local llama.cpp/Ollama/LM Studio servers need no key at all, so the key is optional there (the hosted presets keep requiring one; the config default IS the OpenRouter URL, so compare values, not nullness). Roles mode already tolerates a missing key; the openai-completions adapter omits the Authorization header entirely when the key is empty. The interactive REPL can start without a key: the user can switch providers, models, or base URLs with slash commands before the first run. Headless mode needs a key immediately because it performs a single run and exits.
-
toolsSpecFromEnv(
Map< String, String> env) → ToolsConfig? -
Parses the
FA_TOOLSenv twin of the--toolsflag: the same csv spec, for Docker/headless hosts that cannot pass flags. Absent or empty yields null (no runtime intent); a malformed value throws ConfigException naming the bad token. -
webSearchSecrets(
{Map< String, String> ? env}) → InMemorySecretsStore - Web search works out of the box via keyless DuckDuckGo; keyed providers (Brave, Tavily) join the chain when their API key is in the environment.
-
writeHubState(
File file, {required String? masterSecret, required Map< String, String> clients}) → Future<void> -
Persists
{masterSecret, clients}(0600 — the file carries secrets). Best-effort: IO failures never take the hub down.
Typedefs
- HubAuthVerdict = ({bool allowed, bool isMaster})
-
The upgrade auth verdict:
allowed= the presented credential may connect at all;isMaster= it is the hub password itself (enroll is master-only on a protected hub). An open hub (no master secret) allows everything. -
HubState
= ({Map<
String, String> clients, String? masterSecret}) -
The parsed hub state file (
~/.dap/hub.json): the hub password and the enrolled per-client secrets. - InputPromptFileFactory = File Function(String path)
- Creates the File probed by resolveInteractiveFileReference.
-
PowerProcessLauncher
= Future<
Process> Function(String executable, List<String> arguments) -
Spawns a helper process;
Process.startin production, a fake in tests. -
SecureKeyRunner
= Future<
SecureKeyRunResult> Function(String executable, List<String> arguments, {Map<String, String> ? environment, String? stdin}) -
Runs one helper process for a SecureKeyStore backend, optionally piping
stdinand extending the childenvironment. Injectable so tests never spawn real processes.