agent_profile/adapter/
continue.rs1use std::path::PathBuf;
11
12use super::{
13 Adapter, AdapterEvidence, AdapterMetadata, Capability, CapabilityClaim, CapabilityState,
14 ConflictOption, Mechanism, PathKind, PlanContext, PlannedLaunch, SupportLevel, profile_dir,
15};
16use crate::config::AppRoot;
17use crate::error::Result;
18use crate::name::ProfileName;
19
20const FLAG: &str = "--config";
21const FILE_NAME: &str = "config.yaml";
22
23const CONFIG_OPTION: ConflictOption = ConflictOption { long: &[FLAG], short: None };
27
28pub const INITIAL_CONFIG: &[u8] = b"";
32
33static METADATA: AdapterMetadata = AdapterMetadata {
34 id: "continue",
35 executable: "cn",
36 mechanism: Mechanism::FlagFile(CONFIG_OPTION),
37 support: SupportLevel::Experimental,
38 evidence: AdapterEvidence {
39 mechanism_id: "continue-config-file-v1",
40 verified_at: "2026-10-17",
41 upstream_version: "1.5.47",
42 source_url: "measured",
43 notes: "measured in a sandbox at 1.5.47: --help lists `--config <path> Configuration file for \
44 the assistant` and a launch with it exits 0; the delta at both watched locations was \
45 `(no change: nothing was created, moved or removed at the watched locations)` — the agent \
46 writes nothing before it needs the network (§9 outcome 5); the candidate sweep accepted \
47 the empty file, `# nothing` and {} (all exit 0), and the strings scan found CONTINUE_API_KEY, \
48 ANTHROPIC_API_KEY and OPENAI_API_KEY documented",
49 },
50 capabilities: &[
51 CapabilityClaim {
52 capability: Capability::ConfigIsolation,
53 state: CapabilityState::Unknown,
54 basis: "unmeasured: the probe's delta at both watched locations — the target and the default \
55 `/home/agent/.continue` — was `(no change: nothing was created, moved or removed at the \
56 watched locations)`, so whether the agent's own config writes would follow a configured \
57 file was not observable while the agent writes nothing before it needs the network \
58 (§9 outcome 5)",
59 },
60 CapabilityClaim {
61 capability: Capability::CredentialIsolation,
62 state: CapabilityState::Unknown,
63 basis: "unmeasured: no login/auth step ran and no credential-bearing file surfaced anywhere in \
64 the delta, so where stored credentials live was not established; the documented bypass \
65 variables are `CONTINUE_API_KEY`, `ANTHROPIC_API_KEY` and `OPENAI_API_KEY` \
66 (strings: `documented CONTINUE_API_KEY: present`)",
67 },
68 CapabilityClaim {
69 capability: Capability::StateIsolation,
70 state: CapabilityState::Unknown,
71 basis: "unmeasured: the agent's only pre-network write was `.continue/logs/cn.log`, present at \
72 the default location at baseline, and the measured delta recorded \
73 `(no change: nothing was created, moved or removed at the watched locations)`, so no \
74 state write was observable to place (§9 outcome 5)",
75 },
76 ],
77 env: &[],
78 conflicts: &[],
82 credential_env: &["CONTINUE_API_KEY", "ANTHROPIC_API_KEY", "OPENAI_API_KEY"],
83};
84
85#[derive(Debug, Clone, Copy)]
87pub struct Continue;
88
89impl Adapter for Continue {
90 fn metadata(&self) -> &'static AdapterMetadata {
91 &METADATA
92 }
93
94 fn paths(&self, root: &AppRoot, profile: &ProfileName) -> Vec<(PathBuf, PathKind)> {
95 let dir = profile_dir(root, profile, METADATA.id);
96 let file = dir.join(FILE_NAME);
97 vec![(dir, PathKind::Dir), (file, PathKind::File { contents: INITIAL_CONFIG })]
98 }
99
100 fn plan(&self, ctx: &PlanContext<'_>) -> Result<PlannedLaunch> {
101 METADATA.mechanism.plan(self, ctx)
102 }
103}