@getbourdon/participants 0.2.3 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/base.d.ts +109 -0
  2. package/dist/base.js +88 -0
  3. package/dist/index.d.ts +42 -1083
  4. package/dist/index.js +53 -6590
  5. package/dist/network-base.d.ts +108 -0
  6. package/dist/network-base.js +248 -0
  7. package/dist/readers/cascade.d.ts +49 -0
  8. package/dist/readers/cascade.js +428 -0
  9. package/dist/readers/claude-code-automations.d.ts +62 -0
  10. package/dist/readers/claude-code-automations.js +693 -0
  11. package/dist/readers/claude-code.d.ts +50 -0
  12. package/dist/readers/claude-code.js +583 -0
  13. package/dist/readers/claude-desktop-code.d.ts +54 -0
  14. package/dist/readers/claude-desktop-code.js +526 -0
  15. package/dist/readers/claude-desktop-cowork.d.ts +47 -0
  16. package/dist/readers/claude-desktop-cowork.js +659 -0
  17. package/dist/readers/codex-automations.d.ts +55 -0
  18. package/dist/readers/codex-automations.js +519 -0
  19. package/dist/readers/codex-sessions.d.ts +88 -0
  20. package/dist/readers/codex-sessions.js +194 -0
  21. package/dist/readers/copilot-automations.d.ts +64 -0
  22. package/dist/readers/copilot-automations.js +530 -0
  23. package/dist/readers/copilot-cli.d.ts +45 -0
  24. package/dist/readers/copilot-cli.js +416 -0
  25. package/dist/readers/copilot-vscode.d.ts +54 -0
  26. package/dist/readers/copilot-vscode.js +553 -0
  27. package/dist/readers/copilot.d.ts +59 -0
  28. package/dist/readers/copilot.js +413 -0
  29. package/dist/readers/cursor-automations.d.ts +57 -0
  30. package/dist/readers/cursor-automations.js +685 -0
  31. package/dist/readers/cursor.d.ts +50 -0
  32. package/dist/readers/cursor.js +670 -0
  33. package/dist/readers/github-copilot.d.ts +34 -0
  34. package/dist/readers/github-copilot.js +242 -0
  35. package/dist/readers/hermes.d.ts +37 -0
  36. package/dist/readers/hermes.js +426 -0
  37. package/dist/readers/openclaw.d.ts +78 -0
  38. package/dist/readers/openclaw.js +386 -0
  39. package/dist/registry.d.ts +39 -0
  40. package/dist/registry.js +98 -0
  41. package/dist/sqlite-base.d.ts +65 -0
  42. package/dist/sqlite-base.js +163 -0
  43. package/package.json +6 -6
package/dist/index.d.ts CHANGED
@@ -1,1084 +1,43 @@
1
- import { L5ManifestModel, SessionModel, VisibilityPolicyModel } from '@getbourdon/l5';
2
- export { EntityModel, L5ManifestModel, SessionModel, Visibility, VisibilityPolicyModel, applyVisibility, filterForFederation, toDict, validateManifest } from '@getbourdon/l5';
3
- import DatabaseT from 'better-sqlite3';
4
-
5
1
  /**
6
- * Bourdon participant base — the Protocol → TS interface, errors, and the
7
- * AgentStore / HealthStatus types. Faithful port of `participants/base.py`.
8
- *
9
- * The L5 dataclass model (AgentInfo/Entity/Session/VisibilityPolicy/L5Manifest),
10
- * the `toDict` omission rules, and the visibility helpers all live in
11
- * `@getbourdon/l5` and are reused verbatim — only THAT output shape is the parity
12
- * contract. This module owns the participant CONTRACT surface around them.
13
- *
14
- * Contract semantics (enforced by every reader, asserted by the conformance
15
- * fixtures, never by trust):
16
- * 1. visibility filter BEFORE emission (`filterForFederation`) — private wins.
17
- * 2. deterministic / idempotent `exportL5` — same store → identical `toDict`.
18
- * 3. `healthCheck` NEVER throws — catch-all → degraded/blocked.
19
- * 4. every native string through `@getbourdon/redaction` before it enters L5.
20
- */
21
-
22
- /** Tied to Bourdon spec v0.1 — same literals as the Python oracle. */
23
- declare const CONTRACT_VERSION = "0.1";
24
- declare const SPEC_VERSION = "0.1";
25
- /** Base class for participant errors. */
26
- declare class ParticipantError extends Error {
27
- constructor(message?: string);
28
- }
29
- /** Raised by `discover()` when the native store cannot be found or read.
30
- * Non-fatal: L6 skips this agent rather than aborting the whole export. */
31
- declare class ParticipantDiscoveryError extends ParticipantError {
32
- }
33
- /** Raised by `exportL5()` / `exportSessions()` when an export fails mid-op
34
- * (the store WAS present — distinct from a discovery miss). */
35
- declare class ParticipantExportError extends ParticipantError {
36
- }
37
- /** Raised when the native store's version is outside the supported range.
38
- * Subtype of discovery error (a version mismatch is a discovery-time miss). */
39
- declare class ParticipantVersionMismatchError extends ParticipantDiscoveryError {
40
- }
41
- /** Metadata describing the native agent store. Returned by `discover()`. */
42
- interface AgentStore {
43
- path: string;
44
- version: string;
45
- metadata: Record<string, unknown>;
46
- }
47
- /** Returned by `healthCheck()`. Consumed by the `bourdon doctor` CLI. */
48
- interface HealthStatus {
49
- status: "ok" | "degraded" | "blocked";
50
- reason?: string;
51
- details: Record<string, unknown>;
52
- /** A human-runnable command to remedy a non-ok status. */
53
- proposedFix?: string;
54
- }
55
- /**
56
- * Structural interface every participant must satisfy (the Python
57
- * `@runtime_checkable Protocol`). Duck-typed at registration: a class is a
58
- * participant iff it has `agentId` + `agentType` + `exportL5` + `healthCheck`.
59
- *
60
- * Optional members (`displayName`, a `defaultNativePath` static) are documented
61
- * here as in the Python Protocol; discovery + the setup wizard fall back to
62
- * sensible defaults when absent.
63
- */
64
- interface BourdonParticipant {
65
- agentId: string;
66
- agentType: string;
67
- nativePath: string;
68
- /** Human-friendly label (e.g. "GitHub Copilot"). Optional. */
69
- displayName?: string;
70
- /** Quarantined-class marker (Python `QUARANTINED_CLASS`). When true, the CLI
71
- * requires `--i-understand-the-risk` to register the agent trusted, and its
72
- * exports are staged for operator review rather than written to the live
73
- * store (spec D6: quarantine follows the content, not the invoker). Absent =
74
- * a normal, non-quarantined participant. Read by `bourdon agent add/set-tier`
75
- * (cli/src/commands/federation.ts). */
76
- quarantinedClass?: boolean;
77
- /** Confirm the native store exists; return metadata. Throws
78
- * {@link ParticipantDiscoveryError} when missing/unreadable. */
79
- discover(): AgentStore;
80
- /** Build the L5 manifest from native memory, applying the visibility filter
81
- * BEFORE return. Deterministic — same store yields the same manifest. */
82
- exportL5(since?: Date): L5ManifestModel;
83
- /** Export recent sessions in normalized schema. */
84
- exportSessions(since?: Date, limit?: number): SessionModel[];
85
- /** Return ok / degraded / blocked with a reason. MUST NOT throw. */
86
- healthCheck(): HealthStatus;
87
- }
88
- /**
89
- * Tiny structural guard mirroring Python's `_PARTICIPANT_MARKER_ATTRS`
90
- * duck-type: a value is a participant iff it carries the four marker members.
91
- */
92
- declare function isParticipant(obj: unknown): obj is BourdonParticipant;
93
- /**
94
- * Environment variable holding the deployment's own project-name recognition
95
- * vocabulary, as a comma-separated list (e.g.
96
- * `BOURDON_PROJECT_HINTS="Acme Portal,Widget API,internal-tools"`).
97
- */
98
- declare const PROJECT_HINTS_ENV = "BOURDON_PROJECT_HINTS";
99
- /**
100
- * Project-name hints used to tag sessions with a project focus.
101
- *
102
- * Bourdon ships **no** project roster of its own — the `defaults` a reader
103
- * passes are limited to product-neutral names (this product, plus the agent
104
- * surfaces it federates). A deployment that wants its own projects recognized
105
- * sets {@link PROJECT_HINTS_ENV}; those entries are appended to `defaults`.
106
- *
107
- * Matching downstream is case-insensitive substring matching, so entries are
108
- * de-duplicated case-insensitively here while preserving first-seen order and
109
- * the original casing (which is what gets emitted as the project name).
110
- *
111
- * Mirrors Python `participants.base.load_project_hints`.
112
- */
113
- declare function loadProjectHints(defaults?: readonly string[]): readonly string[];
114
-
115
- /**
116
- * Shared read-only SQLite + normalization helpers — port of
117
- * `participants/_sqlite_base.py`.
118
- *
119
- * A SQLite-backed participant (hermes today; cursor/copilot_cli in the follow-on
120
- * slice) reads a foreign agent's native DB read-only so a live writer's lock can
121
- * never block the export, probes the schema defensively (native schemas drift
122
- * across versions), and turns epoch timestamps + paths into the L5 shapes.
123
- *
124
- * `better-sqlite3` is a NATIVE addon. It is loaded lazily through `createRequire`
125
- * inside a try/catch so this package — and the file/network readers — keep
126
- * working even on a toolchain where the addon failed to build: in that case
127
- * {@link sqliteAvailable} returns false and the sqlite readers degrade rather
128
- * than crashing import. Nothing here applies visibility or builds manifests;
129
- * that stays in the participant (per PARTICIPANT_CONTRACT.md).
130
- */
131
-
132
- /** A better-sqlite3 connection (re-exported type alias for reader signatures). */
133
- type SqliteDatabase = DatabaseT.Database;
134
- /** True when the better-sqlite3 native addon loaded successfully. Tests gate
135
- * the SQLite-reader assertions on this so a missing addon skips, not fails. */
136
- declare function sqliteAvailable(): boolean;
137
- interface OpenReadonlyOptions {
138
- /** `immutable=1`: skip locks + ignore the WAL. Only for genuinely static
139
- * snapshots; against a live writer it risks stale reads / SQLITE_CORRUPT. */
140
- immutable?: boolean;
141
- /** SQLite busy-timeout in milliseconds (Python's `timeout=2.0` seconds). */
142
- timeoutMs?: number;
143
- }
144
- /**
145
- * Open a SQLite DB read-only so a live writer is never disturbed. The default
146
- * (`immutable` omitted) is the safe `mode=ro`: it respects SQLite locking and
147
- * reads the `-wal` sidecar of a live, actively-writing agent. Raises on a
148
- * genuine open failure; callers wanting the never-raises contract use
149
- * {@link tryOpenReadonly}.
150
- */
151
- declare function openReadonly(dbPath: string, opts?: OpenReadonlyOptions): SqliteDatabase;
152
- /**
153
- * Like {@link openReadonly} but returns null instead of raising — for the
154
- * export/health path where a missing or corrupt DB must degrade to "no rows".
155
- */
156
- declare function tryOpenReadonly(dbPath: string, opts?: OpenReadonlyOptions): SqliteDatabase | null;
157
- /** True if `name` is a table in the connected DB (swallows errors → false). */
158
- declare function tableExists(db: SqliteDatabase, name: string): boolean;
159
- /** Column names for `table` (empty set if absent / on error). PRAGMA cannot be
160
- * parameterized, matching the Python f-string. */
161
- declare function tableColumns(db: SqliteDatabase, table: string): Set<string>;
162
- /**
163
- * Convert epoch seconds (number/string) to an ISO `YYYY-MM-DD` UTC date, or
164
- * null for missing/unparseable values. Mirrors `epoch_to_iso_date`.
165
- */
166
- declare function epochToIsoDate(value: unknown): string | null;
167
- /**
168
- * Convert epoch seconds to a full ISO 8601 UTC datetime, or null. The offset is
169
- * rendered `+00:00` (Python `datetime(...).isoformat()` style) rather than `Z`.
170
- */
171
- declare function epochToIsoDatetime(value: unknown): string | null;
172
- /**
173
- * Derive a lowercase project key from a working-directory path: the basename
174
- * lowercased, or null when the cwd is empty or its basename is "generic"
175
- * (carries no project identity). Mirrors `project_key_from_cwd`.
176
- */
177
- declare function projectKeyFromCwd(cwd: string | null | undefined, genericNames?: ReadonlySet<string>): string | null;
178
- /** Turn a slug-ish key (`my-cool_project`) into a Title Case label. */
179
- declare function friendlyLabel(key: string): string;
180
-
181
- /**
182
- * Network-shaped participant base — port of `participants/_network_base.py`
183
- * (v0.3 adapter contract). Same `exportL5` / `exportSessions` half as a file
184
- * participant; only the discovery half differs (fetch from an authenticated
185
- * API). The base provides the three guarantees so adapters don't reimplement:
186
- *
187
- * 1. Local TTL cache under `~/.cache/bourdon/<slug>/payload.json` storing ONLY
188
- * `{fetched_at, payload}` — NEVER the token. A cache hit = zero network.
189
- * 2. Graceful degradation: network down → serve the most recent cached payload
190
- * (even expired) and report `degraded` (not silence).
191
- * 3. Auth boundary: an injected lazy {@link AuthProvider} (env / keychain).
192
- * An invalid token (401/403 non-ratelimit) ALWAYS propagates as `blocked`
193
- * and is NEVER masked by stale cache; a missing token serves stale when a
194
- * cache exists, else blocks; rate-limit degrades.
195
- *
196
- * A subclass sets `participantSlug` / `agentId` / `agentType` (+ `nativePath`)
197
- * and implements `fetchPayload(token)` + `payloadToL5(payload)` (pure, no I/O).
198
- */
199
-
200
- declare const NETWORK_CONTRACT_VERSION = "0.3";
201
- /** Default cache TTL — adapters override via `cacheTtlSeconds`. */
202
- declare const DEFAULT_CACHE_TTL_SECONDS: number;
203
- /** Transport failure / timeout / 5xx / rate-limit — recoverable via cache fallback. */
204
- declare class NetworkUnavailable extends ParticipantError {
205
- }
206
- /** 401/403 / missing credential — NOT recoverable via cache. The user must fix
207
- * auth; surfaced as `blocked`, never silently served from stale cache (stale
208
- * data would mask a broken token indefinitely). */
209
- declare class ParticipantAuthError extends ParticipantError {
210
- }
211
- /** A zero-arg callable returning the token string, or null if no credential is
212
- * available. Kept a callable (not a bare string) so the token is fetched lazily
213
- * at call time and never sits in the participant's fields or the cache. */
214
- type AuthProvider = () => string | null;
215
- /** Auth provider that reads a token from an environment variable. */
216
- declare function envAuthProvider(varName: string): AuthProvider;
217
- /** `$XDG_CACHE_HOME/bourdon` or `~/.cache/bourdon`. */
218
- declare function defaultCacheRoot(): string;
219
- /** A cached payload + the wall-clock time it was fetched (epoch seconds). */
220
- declare class CacheEntry {
221
- readonly fetchedAt: number;
222
- readonly payload: Record<string, unknown>;
223
- constructor(fetchedAt: number, payload: Record<string, unknown>);
224
- get ageSeconds(): number;
225
- isFresh(ttlSeconds: number): boolean;
226
- }
227
- /**
228
- * A tiny JSON file cache, one file per participant slug. Stores only
229
- * `{fetched_at, payload}` — never the auth token. Read/write are best-effort: a
230
- * corrupt or unwritable cache degrades to "no cache", never raises.
231
- */
232
- declare class PayloadCache {
233
- readonly slug: string;
234
- readonly root: string;
235
- readonly path: string;
236
- constructor(slug: string, rootDir?: string);
237
- read(): CacheEntry | null;
238
- write(payload: Record<string, unknown>): void;
239
- }
240
- interface NetworkParticipantOptions {
241
- authProvider?: AuthProvider | null;
242
- cacheRoot?: string;
243
- }
244
- /**
245
- * Base for participants whose native state lives behind an authenticated API.
246
- * Caching, degradation, the auth boundary, and the
247
- * `discover`/`exportL5`/`exportSessions`/`healthCheck` plumbing live here;
248
- * subclasses provide only `fetchPayload` + `payloadToL5`.
249
- */
250
- declare abstract class NetworkParticipant implements BourdonParticipant {
251
- participantSlug: string;
252
- agentId: string;
253
- agentType: string;
254
- cacheTtlSeconds: number;
255
- nativePath: string;
256
- protected readonly authProvider: AuthProvider | null;
257
- private readonly cacheRoot?;
258
- private cacheInstance?;
259
- constructor(opts?: NetworkParticipantOptions);
260
- /** Lazily built so it reads the SUBCLASS's `participantSlug` — subclass field
261
- * initializers run after `super()`, so building the cache in the constructor
262
- * would capture the base "network" slug instead. */
263
- protected get cache(): PayloadCache;
264
- /** Do the authenticated API call; return a JSON-serializable dict. Raise
265
- * {@link NetworkUnavailable} on transport/5xx/rate-limit (→ cache fallback) or
266
- * {@link ParticipantAuthError} on 401/403 (→ blocked, no fallback). */
267
- abstract fetchPayload(token: string): Record<string, unknown>;
268
- /** Normalize a (fresh or cached) payload into an L5 manifest. Pure, no I/O. */
269
- abstract payloadToL5(payload: Record<string, unknown>): L5ManifestModel;
270
- /**
271
- * Resolve (payload, source) where source is 'cache' | 'network' | 'stale-cache'.
272
- * 1. Fresh cache hit → 'cache' (no network)
273
- * 2. Miss/expired + token → 'network' (fetch + refresh cache)
274
- * 3. Net fails + any cache → 'stale-cache' (serve last good payload)
275
- * 4. Net fails + no cache → raise
276
- * Auth errors are never swallowed — they propagate so health surfaces
277
- * 'blocked' rather than serving stale data behind a dead token.
278
- */
279
- protected getPayload(): {
280
- payload: Record<string, unknown>;
281
- source: string;
282
- };
283
- discover(): AgentStore;
284
- exportL5(_since?: Date): L5ManifestModel;
285
- exportSessions(since?: Date, limit?: number): SessionModel[];
286
- healthCheck(): HealthStatus;
287
- }
288
-
289
- /**
290
- * Hermes participant — normalize Hermes Agent (Nous Research) memory + sessions
291
- * into L5. Port of `participants/hermes.py`.
292
- *
293
- * Reads two surfaces under `~/.hermes/` (override `$HERMES_HOME`):
294
- * * `state.db` — a SQLite store (`sessions` + `messages` tables). Recent
295
- * non-archived sessions + project entities (from cwd basename) come from it.
296
- * * `memories/{memory.md,user.md}` — durable cross-session facts (one
297
- * Markdown bullet/line per memory). The highest-signal entities.
298
- *
299
- * Read-only (`mode=ro`), deterministic, visibility-enforced-before-emission,
300
- * and redaction on every native string. `healthCheck` never throws; `discover`
301
- * raises only {@link ParticipantDiscoveryError}.
302
- */
303
-
304
- /** External participant for local Hermes Agent memory + sessions. */
305
- declare class HermesParticipant implements BourdonParticipant {
306
- agentId: string;
307
- agentType: string;
308
- displayName: string;
309
- nativePath: string;
310
- private readonly home;
311
- static defaultNativePath(home?: string): string;
312
- /** `hermesHome` is the `.hermes` directory itself (matching the Python ctor). */
313
- constructor(hermesHome?: string);
314
- private sources;
315
- discover(): AgentStore;
316
- exportSessions(since?: Date, limit?: number): SessionModel[];
317
- exportL5(since?: Date): L5ManifestModel;
318
- healthCheck(): HealthStatus;
319
- }
320
-
321
- /**
322
- * Claude Code participant — reads agent-brain + auto-memory + MCP knowledge
323
- * graph. Port of `participants/claude_code.py`.
324
- *
325
- * Three optional sources (the participant degrades gracefully):
326
- * 1. agent-brain/ — git-synced markdown records
327
- * 2. ~/.claude/projects/<ws>/memory/ — per-machine auto-memory frontmatter
328
- * 3. ~/claude-memory/memory.jsonl — MCP knowledge-graph JSONL
329
- *
330
- * For back-compat the pre-rename env var (`CLAUDE_BRAIN`) and the pre-rename
331
- * directory name are still accepted — see BRAIN_DIR_NAMES / BRAIN_ENV_VARS.
332
- *
333
- * Privacy: entities typed `person` (+ family/contact variants) and observations
334
- * containing credential-like strings default to PRIVATE and are filtered before
335
- * federation. Entities are deduped by case-insensitive name and sorted
336
- * alphabetically.
337
- */
338
-
339
- /** External participant for Anthropic's Claude Code CLI. */
340
- declare class ClaudeCodeParticipant implements BourdonParticipant {
341
- agentId: string;
342
- agentType: string;
343
- nativePath: string;
344
- /** Public so a hermetic test can seed the discovered sources directly (path
345
- * RESOLUTION is not the parity contract — only the export output shape is). */
346
- brainPath: string | null;
347
- autoMemoryPath: string | null;
348
- knowledgeGraphPath: string | null;
349
- static defaultNativePath(home?: string): string;
350
- constructor();
351
- discover(): AgentStore;
352
- exportL5(since?: Date): L5ManifestModel;
353
- exportSessions(since?: Date, limit?: number): SessionModel[];
354
- healthCheck(): HealthStatus;
355
- }
356
-
357
- /**
358
- * GitHub-embedded Copilot participant — the v0.3 network-adapter reference.
359
- * Port of `participants/github_copilot.py`.
360
- *
361
- * Cloud-side Copilot (PR review, `@copilot` comments) persists nothing on the
362
- * user's machine — its state lives on github.com. This adapter federates it by
363
- * reading the user's GitHub activity over the REST API. The
364
- * {@link NetworkParticipant} base provides the cache, degradation, and auth
365
- * boundary; this class provides only the GitHub-specific fetch + payload→L5.
366
- *
367
- * Auth: a token with `repo` + `read:user` scope, sourced from `$GITHUB_TOKEN` /
368
- * `$GH_TOKEN`, else `gh auth token`. Fetched lazily; never stored in the cache
369
- * or the manifest.
370
- */
371
-
372
- /** Resolve a GitHub token: env var first, then the `gh` CLI keychain. */
373
- declare function ghTokenProvider(): string | null;
374
- /** Federates cloud-side GitHub Copilot activity via the GitHub REST API. */
375
- declare class GitHubCopilotParticipant extends NetworkParticipant {
376
- participantSlug: string;
377
- agentId: string;
378
- agentType: string;
379
- nativePath: string;
380
- displayName: string;
381
- private readonly maxResults;
382
- constructor(opts?: NetworkParticipantOptions & {
383
- maxResults?: number;
384
- });
385
- static defaultNativePath(): string;
386
- fetchPayload(token: string): Record<string, unknown>;
387
- payloadToL5(payload: Record<string, unknown>): L5ManifestModel;
388
- }
389
-
390
- /**
391
- * Cursor participant — reads Cursor's (the AI-first IDE) SQLite-backed
392
- * workspace/composer state and normalizes it into L5. Port of
393
- * `participants/cursor.py` + the extraction helper `participants/_cursor_sqlite.py`.
394
- *
395
- * Cursor stores workspace state in `state.vscdb` SQLite DBs at platform-specific
396
- * paths (`~/.config/Cursor/`, `~/Library/Application Support/Cursor/`,
397
- * `%APPDATA%/Cursor/`). This reader discovers those stores, reads the `ItemTable`
398
- * key/value rows read-only, parses the composer/chat records into sessions +
399
- * project/topic entities, and merges curated `.cursor/memory/short-index.json`
400
- * entities alongside them.
401
- *
402
- * SQLite access: the Python oracle copies each DB (+ its `-wal`/`-shm`
403
- * companions) to a tmp file and opens it read-write so SQLite folds the WAL into
404
- * a consistent snapshot. The TS mirror instead leans on {@link tryOpenReadonly}
405
- * (`mode=ro`), which respects SQLite locking and reads the `-wal` sidecar of a
406
- * live writer — the same consistent view without the copy. Read-only,
407
- * deterministic, visibility-enforced-before-emission, redaction on every native
408
- * string; `healthCheck` never throws.
409
- */
410
-
411
- /** External participant for Cursor's SQLite workspace state. */
412
- declare class CursorParticipant implements BourdonParticipant {
413
- agentId: string;
414
- agentType: string;
415
- private readonly cursorDir;
416
- private readonly workspaceRoot;
417
- private readonly policy;
418
- /**
419
- * Conventional Cursor config dir (`~/.cursor`) used by the setup wizard. The
420
- * wizard probes `~/.cursor` for presence; the SQLite workspace state that
421
- * `exportL5` actually reads lives at {@link defaultCursorDir}. Detection and
422
- * extraction intentionally use different anchors.
423
- */
424
- static defaultNativePath(home?: string): string;
425
- constructor(cursorDir?: string | null, workspaceRoot?: string | null);
426
- get nativePath(): string;
427
- discover(): AgentStore;
428
- exportSessions(since?: Date, limit?: number): SessionModel[];
429
- exportL5(since?: Date): L5ManifestModel;
430
- healthCheck(): HealthStatus;
431
- private extract;
432
- }
433
-
434
- /**
435
- * GitHub Copilot (local convention) participant — reads the convention-based
436
- * memory file at `~/.copilot-bourdon/memory.md`. Port of `participants/copilot.py`.
437
- *
438
- * Copilot has no accessible local session index (its reasoning is cloud-side and
439
- * its native memory is not exposed on disk), so — like the Codex pre-distillation
440
- * fallback — this reader normalizes a user-maintained convention file into a
441
- * Bourdon L5 manifest. The file is YAML front-matter (structured `entities:` /
442
- * `sessions:`) followed by an optional freeform markdown body that Copilot Chat
443
- * reads as plain context but this reader ignores.
444
- *
445
- * NOT the cloud GitHub-Copilot network adapter ({@link GitHubCopilotParticipant})
446
- * and NOT the Copilot CLI SQLite reader.
447
- *
448
- * Paths checked (in order):
449
- * 1. `COPILOT_BOURDON_HOME` env-var override
450
- * 2. `~/.copilot-bourdon/` (default convention path)
451
- *
452
- * Defensive throughout: a missing convention directory raises
453
- * {@link ParticipantDiscoveryError} from `discover()`; malformed YAML degrades to
454
- * an empty manifest rather than raising; `healthCheck` never throws.
455
- */
456
-
457
- /**
458
- * External participant for GitHub Copilot via `~/.copilot-bourdon/memory.md`.
459
- * Implements {@link BourdonParticipant} structurally.
460
- */
461
- declare class CopilotParticipant implements BourdonParticipant {
462
- agentId: string;
463
- agentType: string;
464
- displayName: string;
465
- nativePath: string;
466
- /** Conventional `~/.copilot-bourdon` dir used by the setup wizard's detection. */
467
- static defaultNativePath(home?: string): string;
468
- private readonly copilotDir;
469
- constructor(copilotDir?: string | null);
470
- discover(): AgentStore;
471
- exportSessions(since?: Date, limit?: number): SessionModel[];
472
- exportL5(since?: Date): L5ManifestModel;
473
- healthCheck(): HealthStatus;
474
- private read;
475
- }
476
-
477
- /**
478
- * GitHub Copilot CLI participant — normalize the `copilot` terminal agent's
479
- * SQLite session store into L5. Port of `participants/copilot_cli.py`.
480
- *
481
- * Copilot CLI stores session history in a SQLite database at
482
- * `~/.copilot/session-store.db` (override `$COPILOT_CLI_HOME`). This is distinct
483
- * from:
484
- * - the VS Code Copilot Chat extension (`github-copilot` network reader)
485
- * - the `~/.copilot-bourdon/memory.md` convention-file participant (`copilot`)
486
- * - GitHub-embedded Copilot (no local state)
487
- *
488
- * The schema (schema_version 4) carries `sessions` / `turns` / `checkpoints`
489
- * plus `session_files` / `session_refs` / `dynamic_context_items`. The reader
490
- * opens the DB read-only (`mode=ro` via {@link tryOpenReadonly}) so a live
491
- * writer's lock can never block the export, probes each table defensively (a
492
- * missing table degrades to "no rows" rather than raising), redacts every native
493
- * string, applies the visibility filter BEFORE emission, and is deterministic.
494
- * `healthCheck` never throws.
495
- */
496
-
497
- /**
498
- * External participant for GitHub Copilot CLI (`~/.copilot/session-store.db`).
499
- * Reads the SQLite database read-only (never locks the live db).
500
- */
501
- declare class CopilotCliParticipant implements BourdonParticipant {
502
- agentId: string;
503
- agentType: string;
504
- displayName: string;
505
- nativePath: string;
506
- private readonly copilotDir;
507
- /** Conventional `~/.copilot` dir used by the setup wizard's detection. */
508
- static defaultNativePath(home?: string): string;
509
- constructor(copilotDir?: string);
510
- discover(): AgentStore;
511
- exportSessions(since?: Date, limit?: number): SessionModel[];
512
- exportL5(since?: Date): L5ManifestModel;
513
- healthCheck(): HealthStatus;
514
- private emptyManifest;
515
- }
516
-
517
- /**
518
- * Cascade (Windsurf) participant — convention-file reader. Port of
519
- * `participants/cascade.py`.
520
- *
521
- * Cascade's internal state is not exposed on the filesystem in a standardized
522
- * format (like cloud Copilot). Instead this participant uses a CONVENTION FILE:
523
- * Cascade maintains a structured memory file at `~/.cascade-bourdon/memory.md`
524
- * with YAML front-matter carrying `entities` + `sessions`. Cascade owns that
525
- * projection explicitly (it writes what it knows at session end); the
526
- * participant normalizes the front-matter into an L5 manifest for federation.
527
- *
528
- * Privacy: entity/session summaries pass through the redaction SSOT; the
529
- * visibility policy (private_tags) filters PRIVATE entities before emission.
530
- */
531
-
532
- /**
533
- * Convention-based Bourdon participant for Cascade (Windsurf). Reads structured
534
- * memory from `~/.cascade-bourdon/memory.md` and normalizes it into L5.
535
- */
536
- declare class CascadeParticipant implements BourdonParticipant {
537
- agentId: string;
538
- agentType: string;
539
- displayName: string;
540
- private readonly dir;
541
- private readonly policy;
542
- static defaultNativePath(home?: string): string;
543
- constructor(cascadeDir?: string, policy?: VisibilityPolicyModel);
544
- /** Path to the Cascade-Bourdon convention directory. */
545
- get nativePath(): string;
546
- private memoryPath;
547
- private readFrontmatter;
548
- discover(): AgentStore;
549
- exportL5(since?: Date): L5ManifestModel;
550
- exportSessions(since?: Date, limit?: number): SessionModel[];
551
- healthCheck(): HealthStatus;
552
- }
553
-
554
- /**
555
- * OpenClaw participant — network-shaped, QUARANTINED-CLASS. Port of
556
- * `participants/openclaw.py` (v0.9.0, spec R4/D9).
557
- *
558
- * OpenClaw is the highest-demand adapter target in the ecosystem and also its
559
- * highest-risk agent class: CVE-2026-25253 (one-click RCE, CVSS 8.8, first
560
- * patched in 2026.1.29), tens of thousands of internet-exposed instances (~93%
561
- * without authentication), ClawHub's malicious-skill problem, and auth disabled
562
- * by default on port 8080. Bourdon therefore treats OpenClaw differently from
563
- * every on-disk participant:
564
- *
565
- * 1. **Network-shaped** — state is read from the OpenClaw instance's local
566
- * HTTP API, not on-disk artifacts. Because the {@link BourdonParticipant}
567
- * contract is SYNCHRONOUS (`discover`/`exportL5` return values, not
568
- * Promises) and `fetch` is async, the reads go through a tiny synchronous
569
- * `curl` shell-out (the same idiom as the github-copilot reader).
570
- * 2. **Hard handshake gate** — {@link OpenClawParticipant.discover} refuses to
571
- * talk to an instance that is unpatched (< 2026.1.29) or has authentication
572
- * disabled. These are refusals with exact reasons AND fixes, not warnings,
573
- * and every read re-runs the gate.
574
- * 3. **Quarantined-class** — `quarantinedClass = true`: registering the agent
575
- * trusted requires `--i-understand-the-risk`, and exports stage for
576
- * operator review (spec D6: quarantine follows the content, not the
577
- * invoker). Its content federates under TEAM, never PUBLIC.
578
- *
579
- * We gate on instance hygiene (version, auth) — NOT on auditing the user's
580
- * installed skills; that's ClawSecure et al.'s job (spec non-goal 3).
581
- */
582
-
583
- /** First OpenClaw release that patches CVE-2026-25253 (one-click RCE). */
584
- declare const MIN_PATCHED_VERSION = "2026.1.29";
585
- /**
586
- * Hard handshake preconditions (spec D9). Returns the version on success.
587
- * Raises {@link ParticipantDiscoveryError} with the exact reason AND the fix —
588
- * these are refusals, not warnings.
589
- */
590
- declare function verifyInstance(status: Record<string, unknown>, url: string): string;
591
- /**
592
- * Minimal HTTP client for a local OpenClaw instance. Read-only: status,
593
- * sessions, memories. Failures raise {@link ParticipantDiscoveryError} with the
594
- * reason — the participant decides how to surface them.
595
- *
596
- * Error mapping (faithful to the Python `urllib` client): an HTTP >= 400
597
- * response -> "returned HTTP {code}"; a transport failure / timeout / non-JSON
598
- * body -> "instance unreachable at {url}".
599
- */
600
- declare class OpenClawApiClient {
601
- readonly url: string;
602
- private readonly token;
603
- readonly timeout: number;
604
- constructor(url: string, token?: string, timeout?: number);
605
- private get;
606
- status(): Record<string, unknown>;
607
- sessions(): Record<string, unknown>[];
608
- memories(): Record<string, unknown>[];
609
- /** Shared `sessions()`/`memories()` body: try/except-returns-[], unwrap the
610
- * `{ "<key>": [...] }` envelope, and keep only object rows. */
611
- private readCollection;
612
- }
613
- /** Bourdon participant for OpenClaw (quarantined class). */
614
- declare class OpenClawParticipant implements BourdonParticipant {
615
- agentId: string;
616
- agentType: string;
617
- displayName: string;
618
- /** Trust marker consumed by `bourdon agent add/set-tier` + export-all:
619
- * registering as trusted needs --i-understand-the-risk; exports stage. */
620
- quarantinedClass: boolean;
621
- readonly url: string;
622
- private readonly client;
623
- static defaultNativePath(home?: string): string;
624
- constructor(url?: string, token?: string, client?: OpenClawApiClient);
625
- get nativePath(): string;
626
- discover(): AgentStore;
627
- exportSessions(since?: Date, limit?: number): SessionModel[];
628
- exportL5(since?: Date): L5ManifestModel;
629
- healthCheck(): HealthStatus;
630
- }
631
-
632
- /**
633
- * Claude Code automations participant — publishes background-run memory as L5
634
- * evidence. Port of `participants/claude_code_automations.py`.
635
- *
636
- * Convention-file reader over the `~/.claude/automations/<id>/` tree:
637
- * automation.toml — id, name, status, schedule (rrule), kind, cwds
638
- * memory.md — dated bullet entries, one block per run
639
- *
640
- * Each `automation.toml` becomes a known Entity (`type: automation`); each dated
641
- * section of `memory.md` becomes a recent Session. Mirrors the Codex automation
642
- * publisher — it covers the federation gap that the interactive-only
643
- * `claude-code` participant leaves behind (automations whose work never touches
644
- * agent-brain / auto-memory / the MCP knowledge graph).
645
- *
646
- * Privacy: every native string routes through the redaction SSOT
647
- * (`redactText`, == the oracle's `_safe_native_memory_text`); the visibility
648
- * policy filters PRIVATE entities before emission. `healthCheck` never throws.
649
- */
650
-
651
- /** External participant for Claude Code automation memory artifacts. */
652
- declare class ClaudeCodeAutomationsParticipant implements BourdonParticipant {
653
- agentId: string;
654
- agentType: string;
655
- nativePath: string;
656
- private readonly automationsDir;
657
- private readonly policy;
658
- /**
659
- * Conventional Claude Code automations dir (`~/.claude/automations`). Provided
660
- * for protocol uniformity — the setup wizard wires the parent `claude-code`
661
- * participant and skips `-automations` sub-surfaces.
662
- */
663
- static defaultNativePath(home?: string): string;
664
- constructor(automationsDir?: string, claudeHome?: string);
665
- discover(): AgentStore;
666
- exportSessions(since?: Date, limit?: number): SessionModel[];
667
- exportL5(since?: Date): L5ManifestModel;
668
- healthCheck(): HealthStatus;
669
- private runs;
670
- }
671
-
672
- /**
673
- * Codex automations participant — publishes read-only Codex background/automation
674
- * run memory into Bourdon as L5 evidence. Port of
675
- * `participants/codex_automations.py`.
676
- *
677
- * Store convention (NOT SQLite, NOT network): a CONVENTION-FILE directory tree at
678
- * `~/.codex/automations/<id>/`, each holding an `automation.toml` config and an
679
- * optional `memory.md` run log. The reader parses the TOML config and extracts
680
- * dated "runs" from the markdown memory, normalizing them into L5 sessions +
681
- * entities (the automation itself, plus inferred projects and signal classes).
682
- *
683
- * Source-resolution order for the automations dir:
684
- * 1. explicit `automationsDir` constructor arg
685
- * 2. `codexHome` constructor arg → `<codexHome>/automations`
686
- * 3. `CODEX_HOME` env-var → `$CODEX_HOME/automations`
687
- * 4. `~/.codex/automations` (default convention path)
688
- *
689
- * Privacy: every native string routes through the redaction SSOT
690
- * (`redactText(v, 180)` == the oracle's `_safe_native_memory_text`); the
691
- * visibility policy filters PRIVATE entities before emission. Defensive
692
- * throughout — a missing dir raises {@link ParticipantDiscoveryError} from
693
- * `discover()`, malformed TOML/markdown degrades to empty rather than raising,
694
- * and `healthCheck` never throws.
695
- *
696
- * NOTE: does NOT depend on the full codex reader — only the redaction helper it
697
- * imports (`_safe_native_memory_text`, reproduced inline as {@link safeNativeMemoryText}).
698
- */
699
-
700
- /**
701
- * External participant for Codex automation memory artifacts. Reads
702
- * `~/.codex/automations/<id>/{automation.toml,memory.md}` and normalizes dated
703
- * runs into an L5 manifest.
704
- */
705
- declare class CodexAutomationsParticipant implements BourdonParticipant {
706
- agentId: string;
707
- agentType: string;
708
- private readonly automationsDir;
709
- private readonly policy;
710
- /**
711
- * Conventional Codex automations dir (`~/.codex/automations`). Provided for
712
- * protocol uniformity — the setup wizard wires the parent `codex` participant
713
- * and skips `-automations` sub-surfaces rather than detecting this one.
714
- */
715
- static defaultNativePath(home?: string): string;
716
- constructor(automationsDir?: string, codexHome?: string);
717
- get nativePath(): string;
718
- discover(): AgentStore;
719
- exportSessions(since?: Date, limit?: number): SessionModel[];
720
- exportL5(since?: Date): L5ManifestModel;
721
- healthCheck(): HealthStatus;
722
- private runs;
723
- }
724
-
725
- /**
726
- * GitHub Copilot · Automations participant — convention-file reader. Port of
727
- * `participants/copilot_automations.py`.
728
- *
729
- * GitHub Copilot can be triggered by GitHub Actions workflows, scheduled tasks,
730
- * and event-driven automations (issue triage, PR review, etc.). These run on a
731
- * separate memory surface from both the CLI agent and the VS Code extension.
732
- * Copilot automations have no standardized local state dump, so — mirroring the
733
- * codex-automations reader — this participant uses a CONVENTION directory:
734
- *
735
- * ~/.copilot-bourdon/automations/<automation-id>/
736
- * automation.toml — id, name, status, trigger, kind, repos
737
- * memory.md — dated bullet entries, one block per run
738
- *
739
- * Each `automation.toml` describes a recurring automation; each dated section of
740
- * `memory.md` captures what happened in that run. Users or CI scripts maintain
741
- * these files.
742
- *
743
- * Path resolution (matches the oracle):
744
- * 1. `COPILOT_AUTOMATIONS_HOME` env-var override (verbatim, → /automations skipped:
745
- * the override IS the automations dir).
746
- * 2. `~/.copilot-bourdon/automations/` (default convention path).
747
- *
748
- * Defensive throughout: a missing automations directory raises
749
- * {@link ParticipantDiscoveryError} from `discover()`; a malformed
750
- * `automation.toml` or unreadable `memory.md` is logged and skipped rather than
751
- * raising; `healthCheck` never throws.
752
- */
753
-
754
- /**
755
- * Convention-based Bourdon participant for Copilot automation memory artifacts.
756
- * Users or CI scripts maintain `automation.toml` + `memory.md` files at
757
- * `~/.copilot-bourdon/automations/<id>/`.
758
- */
759
- declare class CopilotAutomationsParticipant implements BourdonParticipant {
760
- agentId: string;
761
- agentType: string;
762
- displayName: string;
763
- private readonly automationsDir;
764
- private readonly policy;
765
- /** Conventional automations dir (`~/.copilot-bourdon/automations`). Does NOT
766
- * consult `COPILOT_AUTOMATIONS_HOME` (matches Python `default_native_path`). */
767
- static defaultNativePath(home?: string): string;
768
- constructor(automationsDir?: string | null);
769
- get nativePath(): string;
770
- discover(): AgentStore;
771
- exportSessions(since?: Date, limit?: number): SessionModel[];
772
- exportL5(since?: Date): L5ManifestModel;
773
- healthCheck(): HealthStatus;
774
- private runs;
775
- }
776
-
777
- /**
778
- * Cursor automations participant — publish background agent run memory as L5
779
- * evidence. Port of `participants/cursor_automations.py`.
780
- *
781
- * Reads the `~/.cursor/automations/<id>/` CONVENTION (file-based, no SQLite):
782
- *
783
- * automation.toml — id, name, status, schedule (rrule), kind, cwds
784
- * memory.md — dated bullet entries, one block per run
785
- *
786
- * Each `automation.toml` becomes a known Entity; each dated section of
787
- * `memory.md` becomes a recent Session. This covers the federation gap the
788
- * interactive-only `cursor` participant leaves behind: Cursor Cloud Agent
789
- * background tasks whose work never touches the interactive SQLite state.
790
- *
791
- * Path resolution (default dir):
792
- * 1. explicit `cursorHome` ctor arg → `<cursorHome>/automations`
793
- * 2. `CURSOR_DIR` or `CURSOR_HOME` env → `<env>/automations`
794
- * 3. `~/.cursor/automations`
795
- *
796
- * Redaction: every native action string passes through the redaction SSOT
797
- * (`redactText(v, 180)` == Python `_safe_native_memory_text`). Visibility policy
798
- * filters PRIVATE entities BEFORE emission. `healthCheck` never throws.
799
- */
800
-
801
- /** External participant for Cursor Cloud Agent automation memory artifacts. */
802
- declare class CursorAutomationsParticipant implements BourdonParticipant {
803
- agentId: string;
804
- agentType: string;
805
- private readonly automationsDir;
806
- private readonly policy;
807
- constructor(automationsDir?: string | null, cursorHome?: string | null);
808
- get nativePath(): string;
809
- discover(): AgentStore;
810
- exportSessions(since?: Date, limit?: number): SessionModel[];
811
- exportL5(since?: Date): L5ManifestModel;
812
- healthCheck(): HealthStatus;
813
- private runs;
814
- }
815
-
816
- /**
817
- * Claude Desktop · Code participant — the Claude desktop app's GUI "Claude Code"
818
- * surface. Port of `participants/claude_desktop_code.py` (+ the shared
819
- * `participants/_claude_desktop.py` helpers it needs).
820
- *
821
- * The desktop GUI's Claude Code keeps **metadata-only** state on disk — there is
822
- * no transcript. State files live at:
823
- *
824
- * <desktop>/claude-code-sessions/<accountUUID>/<orgUUID>/local_<id>.json
825
- *
826
- * This participant emits **recognition metadata only** and routes every emitted
827
- * string through the shared redactor + a length cap (defense in depth): title,
828
- * cwd→project, model, effort, `enabledMcpTools` *count*, timestamps. It never
829
- * emits `planPath` contents or any free-form text beyond the redacted title.
830
- *
831
- * Distinct from the interactive-CLI {@link ClaudeCodeParticipant} and the richer
832
- * Co-Work surface. Convention: file/JSON reader (no SQLite, no network).
833
- */
834
-
835
- /**
836
- * External participant for the Claude desktop app's GUI Claude Code surface.
837
- * File/JSON reader — metadata-only, no transcript, no SQLite, no network.
838
- */
839
- declare class ClaudeDesktopCodeParticipant implements BourdonParticipant {
840
- agentId: string;
841
- agentType: string;
842
- displayName: string;
843
- private readonly storeDir;
844
- private readonly policy;
845
- /**
846
- * The Claude Code sub-store dir the setup wizard probes for presence. Resolves
847
- * to `<desktop>/claude-code-sessions`. Falls back to a non-existent sentinel
848
- * under `home` on an unrecognized platform so the wizard reports "not found".
849
- */
850
- static defaultNativePath(home?: string): string;
851
- constructor(storeDir?: string, home?: string);
852
- get nativePath(): string;
853
- discover(): AgentStore;
854
- exportSessions(since?: Date, limit?: number): SessionModel[];
855
- exportL5(since?: Date): L5ManifestModel;
856
- healthCheck(): HealthStatus;
857
- private collectConversations;
858
- private conversations;
859
- }
860
-
861
- /**
862
- * Claude Desktop · Co-Work participant — the richest of the two Claude-desktop
863
- * surfaces. Port of `participants/claude_desktop_cowork.py` (+ the shared
864
- * `participants/_claude_desktop.py` extraction helpers, inlined here).
865
- *
866
- * The desktop app stores each Co-Work / local-agent run as a state file plus a
867
- * sibling audit transcript:
868
- *
869
- * <desktop>/local-agent-mode-sessions/<acct>/<org>/local_<id>.json (state)
870
- * <desktop>/local-agent-mode-sessions/<acct>/<org>/local_<id>/audit.jsonl
871
- *
872
- * This participant emits **recognition metadata only**. From the state file it
873
- * reads surface scalars (title, cwd, model, permission mode, timestamps,
874
- * `enabledMcpTools` *count*, `userSelectedFolders` *basenames*). From the
875
- * sibling `audit.jsonl` it reads ONLY the `system`/`init` capability *counts*
876
- * and the `result` safe scalars (cost, turns, error flag). It NEVER reads
877
- * conversation content. Every emitted string passes through the redaction SSOT
878
- * + a length cap, and TEAM entities are visibility-filtered before emission.
879
- *
880
- * Storage kind: file/convention (glob + JSON + JSONL), so this reads like the
881
- * claude-code / cascade file readers — no SQLite, no network.
882
- */
883
-
884
- /** External participant for the Claude desktop app's Co-Work surface. */
885
- declare class ClaudeDesktopCoworkParticipant implements BourdonParticipant {
886
- agentId: string;
887
- agentType: string;
888
- displayName: string;
889
- private readonly storeDir;
890
- private readonly policy;
891
- /**
892
- * The Co-Work sub-store dir the setup wizard probes for presence. Resolves to
893
- * `<desktop>/local-agent-mode-sessions`. When the desktop dir cannot be
894
- * resolved on this platform, falls back to a non-existent sentinel under
895
- * `home` so the wizard reports "not found" rather than crashing.
896
- */
897
- static defaultNativePath(home?: string): string;
898
- constructor(storeDir?: string, home?: string);
899
- get nativePath(): string;
900
- discover(): AgentStore;
901
- exportSessions(since?: Date, limit?: number): SessionModel[];
902
- exportL5(since?: Date): L5ManifestModel;
903
- healthCheck(): HealthStatus;
904
- private collectRuns;
905
- private runs;
906
- }
907
-
908
- /**
909
- * GitHub Copilot · VS Code participant — reads the GUI Copilot Chat extension's
910
- * per-workspace transcripts + repo-scoped memory. Port of
911
- * `participants/copilot_vscode.py`.
912
- *
913
- * VS Code's Copilot Chat extension stores per-workspace data at
914
- * `<workspaceStorage>/<hash>/GitHub.copilot-chat/`:
915
- * - `transcripts/<session-uuid>.jsonl` — event stream per chat session
916
- * - `memory-tool/memories/**\/*.md` — per-repo memory (markdown bullets)
917
- *
918
- * This is a FILE/CONVENTION reader (not SQLite, not network): it walks the
919
- * workspaceStorage tree read-only, parses JSONL transcripts + markdown memory
920
- * files, aggregates across every workspace hash, redacts every native string,
921
- * applies the visibility filter BEFORE emission, and is deterministic.
922
- * `healthCheck` never throws.
923
- *
924
- * Distinct from:
925
- * - `copilot` (convention-file at `~/.copilot-bourdon/memory.md`)
926
- * - `copilot-cli` (terminal agent, `~/.copilot/session-store.db`, SQLite)
927
- * - `github-copilot` (network reader — GitHub-embedded Copilot)
928
- */
929
-
930
- /**
931
- * External participant for GitHub Copilot in VS Code. Reads transcripts and
932
- * memory-tool files from VS Code's workspaceStorage read-only, aggregating
933
- * across all workspace hashes.
934
- */
935
- declare class CopilotVscodeParticipant implements BourdonParticipant {
936
- agentId: string;
937
- agentType: string;
938
- displayName: string;
939
- private readonly workspaceStorage;
940
- /** The workspaceStorage dir the setup wizard probes for presence. */
941
- static defaultNativePath(home?: string): string;
942
- constructor(workspaceStorage?: string);
943
- get nativePath(): string;
944
- private resolveWs;
945
- discover(): AgentStore;
946
- exportSessions(since?: Date, limit?: number): SessionModel[];
947
- exportL5(since?: Date): L5ManifestModel;
948
- healthCheck(): HealthStatus;
949
- /** Collect and parse all transcripts across all workspaces. */
950
- private allTranscripts;
951
- /** Collect all memory-tool files across all workspaces. */
952
- private allMemories;
953
- }
954
-
955
- /**
956
- * Codex session-index title lookup — narrow port of the three
957
- * `session_thread_titles` helpers in `participants/codex.py`.
958
- *
959
- * SCOPE (deliberately tiny): this is NOT the Codex participant/reader (the
960
- * ~2.6k-line turn-compiler still lands in a follow-on slice). It ports ONLY the
961
- * surface the tray/presence join needs — a `session_id -> human thread title`
962
- * map read from `~/.codex/session_index.jsonl`.
963
- *
964
- * Why only the index: `session_thread_titles()` runs on EVERY tray refresh, so
965
- * it must never touch rollout files. One small JSONL read, newest-first, done.
966
- * It covers Codex CLI sessions AND ChatGPT-app threads — the app's Work and
967
- * Codex modes share `~/.codex`, so `thread_name` is the human title for both.
968
- *
969
- * PRIVACY: titles are raw user text. Callers that EXPORT them MUST route them
970
- * through the audited redaction pipeline (`redactField` in
971
- * `mcp-server/src/agents-export.ts`, == Python's `_redact_field`), exactly like
972
- * every other emitted string. This module deliberately does NOT redact — the
973
- * redaction happens at the single audited egress point so it can't be
974
- * double-applied or silently skipped.
975
- *
976
- * Best-effort by construction: a missing dir, an unreadable file, or a corrupt
977
- * line degrades to fewer/no titles. Nothing here throws.
978
- */
979
- /** Default number of index records considered (newest-first). */
980
- declare const DEFAULT_TITLE_LIMIT = 200;
981
- /** Default number of threads on the tray codex card (newest-first). */
982
- declare const DEFAULT_RECENT_THREAD_LIMIT = 5;
983
- /**
984
- * Locate `~/.codex/` (the primary Codex store), or null.
985
- *
986
- * Resolution order, mirroring `_resolve_codex_home()` exactly:
987
- * 1. `$CODEX_HOME` — **only if that directory already exists**
988
- * 2. `~/.codex` — only if it exists
989
- * 3. `null`
990
- *
991
- * ⚠ FOOTGUN (preserved for parity, do not "fix" without changing Python too):
992
- * step 1 is a silent fallback, not a pin. If `$CODEX_HOME` points at a path that
993
- * does not exist yet, the env var is IGNORED and this returns the developer's
994
- * REAL `~/.codex`. A sandbox/test that sets `CODEX_HOME` to a temp path without
995
- * `mkdir`-ing it first looks isolated but reads live data. Always create the
996
- * directory before setting the variable.
997
- */
998
- declare function resolveCodexHome(baseHome?: string | null): string | null;
999
- /**
1000
- * Read `session_index.jsonl`, newest-first by `updated_at`.
1001
- *
1002
- * Port of `_parse_session_index()`. Per-line JSON parse: a malformed line is
1003
- * WARNED and SKIPPED — it never aborts the scan (one bad append must not blind
1004
- * the tray to every other session). An unreadable file warns and yields `[]`.
1005
- * Only records that are objects with a string `id` are kept.
1006
- */
1007
- declare function parseSessionIndex(path: string, limit?: number | null): Record<string, unknown>[];
1008
- /**
1009
- * Map full Codex session id → human thread title, newest-first.
1010
- *
1011
- * Port of `session_thread_titles()`. Reads ONLY `session_index.jsonl` — no
1012
- * rollout I/O, because this runs on every tray refresh. A missing/malformed
1013
- * index yields `{}`.
1014
- *
1015
- * NEWEST WINS: entries are already sorted newest-first and the insert is a
1016
- * `setdefault` equivalent, so the freshest `thread_name` for a repeated id is
1017
- * the one kept.
1018
- *
1019
- * Titles are RAW USER TEXT — see the module note; the exporter redacts.
1020
- */
1021
- declare function sessionThreadTitles(codexHome?: string | null, opts?: {
1022
- limit?: number;
1023
- }): Record<string, string>;
1024
- /** One row of the tray codex card. NOTE: `instance`, never a full session id. */
1025
- interface RecentThread {
1026
- instance: string;
1027
- title: string | null;
1028
- updated_at: string | null;
1029
- }
1030
- /**
1031
- * Newest-first `[{instance, title, updated_at}]` for the tray codex card.
1032
- *
1033
- * Port of `recent_session_threads()`. Independent of PRESENCE: ChatGPT-app
1034
- * threads fire no presence hooks, so this is the only way they surface.
1035
- *
1036
- * Emits only the 8-char `instance` prefix — parity with `presence.summarize`:
1037
- * a full session id never leaves the local read path. Titles are RAW USER TEXT;
1038
- * the exporter redacts them (see `sessionThreadTitles`).
1039
- */
1040
- declare function recentSessionThreads(codexHome?: string | null, opts?: {
1041
- limit?: number;
1042
- }): RecentThread[];
1043
-
1044
- /**
1045
- * Participant discovery — a STATIC TS registry replacing Python's `pkgutil`
1046
- * package scan + entry-point duck-type (`participants/__init__.py`).
1047
- *
1048
- * Python scans the `participants/` package at runtime and duck-types each class
1049
- * by `_PARTICIPANT_MARKER_ATTRS`. A filesystem package scan does not survive
1050
- * bundling (`npx bourdon` is a single file), so the JS side declares an explicit
1051
- * {@link FIRST_PARTY} array. The three preserved invariants:
1052
- * - output sorted by `agentId`
1053
- * - first-wins dedupe on `agentId`
1054
- * - log-and-skip a participant that throws on construction (one broken reader
1055
- * must NOT abort discovery / crash the CLI)
1056
- *
1057
- * The marker-attr duck-typing collapses into the {@link BourdonParticipant}
1058
- * interface conformance (checked structurally via {@link isParticipant}).
1059
- */
1060
-
1061
- /** A zero-arg-constructible participant class. */
1062
- type ParticipantCtor = new () => BourdonParticipant;
1063
- /**
1064
- * The first-party reader registry. Order here is irrelevant — discovery sorts by
1065
- * `agentId`. Covers the base agents, their background-run "automations" variants,
1066
- * the Claude-desktop surfaces, and the quarantined-class openclaw network reader.
1067
- * codex — the ~2.6k-line turn-compiler reader — is the only one still deferred.
1068
- */
1069
- declare const FIRST_PARTY: ParticipantCtor[];
1070
- /**
1071
- * Instantiate each registered participant, duck-type the contract, sort by
1072
- * `agentId`, and first-wins dedupe. A class that throws on construction is
1073
- * logged and skipped — never propagated.
1074
- */
1075
- declare function discoverParticipants(ctors?: ParticipantCtor[]): BourdonParticipant[];
1076
- /**
1077
- * Optional Layer 2: third-party plugins declared via a `package.json`
1078
- * `"bourdon": { participants: { ... } }` field. Gated behind `BOURDON_PLUGINS=1`
1079
- * and a no-op today (no external participant exists yet) — the resolver ships so
1080
- * the seam is wired, defaulted off so `npx bourdon` stays predictable.
1081
- */
1082
- declare function resolvePluginParticipants(): ParticipantCtor[];
1083
-
1084
- export { type AgentStore, type AuthProvider, type BourdonParticipant, CONTRACT_VERSION, CacheEntry, CascadeParticipant, ClaudeCodeAutomationsParticipant, ClaudeCodeParticipant, ClaudeDesktopCodeParticipant, ClaudeDesktopCoworkParticipant, CodexAutomationsParticipant, CopilotAutomationsParticipant, CopilotCliParticipant, CopilotParticipant, CopilotVscodeParticipant, CursorAutomationsParticipant, CursorParticipant, DEFAULT_CACHE_TTL_SECONDS, DEFAULT_RECENT_THREAD_LIMIT, DEFAULT_TITLE_LIMIT, FIRST_PARTY, GitHubCopilotParticipant, type HealthStatus, HermesParticipant, MIN_PATCHED_VERSION, NETWORK_CONTRACT_VERSION, NetworkParticipant, type NetworkParticipantOptions, NetworkUnavailable, OpenClawApiClient, OpenClawParticipant, type OpenReadonlyOptions, PROJECT_HINTS_ENV, ParticipantAuthError, type ParticipantCtor, ParticipantDiscoveryError, ParticipantError, ParticipantExportError, ParticipantVersionMismatchError, PayloadCache, type RecentThread, SPEC_VERSION, type SqliteDatabase, defaultCacheRoot, discoverParticipants, envAuthProvider, epochToIsoDate, epochToIsoDatetime, friendlyLabel, ghTokenProvider, isParticipant, loadProjectHints, openReadonly, parseSessionIndex, projectKeyFromCwd, recentSessionThreads, resolveCodexHome, resolvePluginParticipants, sessionThreadTitles, sqliteAvailable, tableColumns, tableExists, tryOpenReadonly, verifyInstance };
2
+ * @getbourdon/participants — the external-agent → L5 reader layer (BUSL-1.1).
3
+ *
4
+ * Each participant normalizes a foreign agent's native memory store into a
5
+ * visibility-filtered, redacted L5 manifest. Reader categories:
6
+ * - SQLite (read-only, better-sqlite3 mode=ro): {@link HermesParticipant},
7
+ * {@link CursorParticipant}, {@link CopilotCliParticipant}
8
+ * - file / convention: {@link ClaudeCodeParticipant},
9
+ * {@link CopilotParticipant}, {@link CascadeParticipant}
10
+ * - network (TTL cache + lazy AuthProvider): {@link GitHubCopilotParticipant}
11
+ * - network + quarantined-class (handshake gate): {@link OpenClawParticipant}
12
+ *
13
+ * Four invariants enforced in code, not by trust: visibility-filter-before-
14
+ * emission, deterministic exportL5, healthCheck never throws, redact every
15
+ * native string. Discovery is a static registry ({@link discoverParticipants}).
16
+ *
17
+ * Python (`pip install bourdon`) is the oracle; this mirror asserts against the
18
+ * @getbourdon/conformance `native_stores` fixtures (output shape only).
19
+ * Still deferred: codex (the ~2.6k-line turn-compiler reader) lands in a
20
+ * follow-on slice.
21
+ */
22
+ export { CONTRACT_VERSION, SPEC_VERSION, ParticipantError, ParticipantDiscoveryError, ParticipantExportError, ParticipantVersionMismatchError, isParticipant, loadProjectHints, PROJECT_HINTS_ENV, type AgentStore, type BourdonParticipant, type HealthStatus, } from "./base.js";
23
+ export { sqliteAvailable, openReadonly, tryOpenReadonly, tableExists, tableColumns, epochToIsoDate, epochToIsoDatetime, projectKeyFromCwd, friendlyLabel, type OpenReadonlyOptions, type SqliteDatabase, } from "./sqlite-base.js";
24
+ export { NETWORK_CONTRACT_VERSION, DEFAULT_CACHE_TTL_SECONDS, NetworkUnavailable, ParticipantAuthError, NetworkParticipant, PayloadCache, CacheEntry, envAuthProvider, defaultCacheRoot, type AuthProvider, type NetworkParticipantOptions, } from "./network-base.js";
25
+ export { HermesParticipant } from "./readers/hermes.js";
26
+ export { ClaudeCodeParticipant } from "./readers/claude-code.js";
27
+ export { GitHubCopilotParticipant, ghTokenProvider } from "./readers/github-copilot.js";
28
+ export { CursorParticipant } from "./readers/cursor.js";
29
+ export { CopilotParticipant } from "./readers/copilot.js";
30
+ export { CopilotCliParticipant } from "./readers/copilot-cli.js";
31
+ export { CascadeParticipant } from "./readers/cascade.js";
32
+ export { OpenClawParticipant, OpenClawApiClient, verifyInstance, MIN_PATCHED_VERSION, } from "./readers/openclaw.js";
33
+ export { ClaudeCodeAutomationsParticipant } from "./readers/claude-code-automations.js";
34
+ export { CodexAutomationsParticipant } from "./readers/codex-automations.js";
35
+ export { CopilotAutomationsParticipant } from "./readers/copilot-automations.js";
36
+ export { CursorAutomationsParticipant } from "./readers/cursor-automations.js";
37
+ export { ClaudeDesktopCodeParticipant } from "./readers/claude-desktop-code.js";
38
+ export { ClaudeDesktopCoworkParticipant } from "./readers/claude-desktop-cowork.js";
39
+ export { CopilotVscodeParticipant } from "./readers/copilot-vscode.js";
40
+ export { DEFAULT_RECENT_THREAD_LIMIT, DEFAULT_TITLE_LIMIT, parseSessionIndex, recentSessionThreads, resolveCodexHome, sessionThreadTitles, } from "./readers/codex-sessions.js";
41
+ export type { RecentThread } from "./readers/codex-sessions.js";
42
+ export { FIRST_PARTY, discoverParticipants, resolvePluginParticipants, type ParticipantCtor, } from "./registry.js";
43
+ export { Visibility, applyVisibility, filterForFederation, toDict, validateManifest, type EntityModel, type L5ManifestModel, type SessionModel, type VisibilityPolicyModel, } from "@getbourdon/l5";