@getbourdon/participants 0.2.2 → 0.2.3

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.
package/dist/index.d.cts CHANGED
@@ -90,6 +90,27 @@ interface BourdonParticipant {
90
90
  * duck-type: a value is a participant iff it carries the four marker members.
91
91
  */
92
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[];
93
114
 
94
115
  /**
95
116
  * Shared read-only SQLite + normalization helpers — port of
@@ -298,14 +319,17 @@ declare class HermesParticipant implements BourdonParticipant {
298
319
  }
299
320
 
300
321
  /**
301
- * Claude Code participant — reads claude-brain + auto-memory + MCP knowledge
322
+ * Claude Code participant — reads agent-brain + auto-memory + MCP knowledge
302
323
  * graph. Port of `participants/claude_code.py`.
303
324
  *
304
325
  * Three optional sources (the participant degrades gracefully):
305
- * 1. claude-brain/ — git-synced markdown records
326
+ * 1. agent-brain/ — git-synced markdown records
306
327
  * 2. ~/.claude/projects/<ws>/memory/ — per-machine auto-memory frontmatter
307
328
  * 3. ~/claude-memory/memory.jsonl — MCP knowledge-graph JSONL
308
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
+ *
309
333
  * Privacy: entities typed `person` (+ family/contact variants) and observations
310
334
  * containing credential-like strings default to PRIVATE and are filtered before
311
335
  * federation. Entities are deduped by case-insensitive name and sorted
@@ -617,7 +641,7 @@ declare class OpenClawParticipant implements BourdonParticipant {
617
641
  * section of `memory.md` becomes a recent Session. Mirrors the Codex automation
618
642
  * publisher — it covers the federation gap that the interactive-only
619
643
  * `claude-code` participant leaves behind (automations whose work never touches
620
- * claude-brain / auto-memory / the MCP knowledge graph).
644
+ * agent-brain / auto-memory / the MCP knowledge graph).
621
645
  *
622
646
  * Privacy: every native string routes through the redaction SSOT
623
647
  * (`redactText`, == the oracle's `_safe_native_memory_text`); the visibility
@@ -928,6 +952,95 @@ declare class CopilotVscodeParticipant implements BourdonParticipant {
928
952
  private allMemories;
929
953
  }
930
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
+
931
1044
  /**
932
1045
  * Participant discovery — a STATIC TS registry replacing Python's `pkgutil`
933
1046
  * package scan + entry-point duck-type (`participants/__init__.py`).
@@ -968,4 +1081,4 @@ declare function discoverParticipants(ctors?: ParticipantCtor[]): BourdonPartici
968
1081
  */
969
1082
  declare function resolvePluginParticipants(): ParticipantCtor[];
970
1083
 
971
- 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, FIRST_PARTY, GitHubCopilotParticipant, type HealthStatus, HermesParticipant, MIN_PATCHED_VERSION, NETWORK_CONTRACT_VERSION, NetworkParticipant, type NetworkParticipantOptions, NetworkUnavailable, OpenClawApiClient, OpenClawParticipant, type OpenReadonlyOptions, ParticipantAuthError, type ParticipantCtor, ParticipantDiscoveryError, ParticipantError, ParticipantExportError, ParticipantVersionMismatchError, PayloadCache, SPEC_VERSION, type SqliteDatabase, defaultCacheRoot, discoverParticipants, envAuthProvider, epochToIsoDate, epochToIsoDatetime, friendlyLabel, ghTokenProvider, isParticipant, openReadonly, projectKeyFromCwd, resolvePluginParticipants, sqliteAvailable, tableColumns, tableExists, tryOpenReadonly, verifyInstance };
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 };
package/dist/index.d.ts CHANGED
@@ -90,6 +90,27 @@ interface BourdonParticipant {
90
90
  * duck-type: a value is a participant iff it carries the four marker members.
91
91
  */
92
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[];
93
114
 
94
115
  /**
95
116
  * Shared read-only SQLite + normalization helpers — port of
@@ -298,14 +319,17 @@ declare class HermesParticipant implements BourdonParticipant {
298
319
  }
299
320
 
300
321
  /**
301
- * Claude Code participant — reads claude-brain + auto-memory + MCP knowledge
322
+ * Claude Code participant — reads agent-brain + auto-memory + MCP knowledge
302
323
  * graph. Port of `participants/claude_code.py`.
303
324
  *
304
325
  * Three optional sources (the participant degrades gracefully):
305
- * 1. claude-brain/ — git-synced markdown records
326
+ * 1. agent-brain/ — git-synced markdown records
306
327
  * 2. ~/.claude/projects/<ws>/memory/ — per-machine auto-memory frontmatter
307
328
  * 3. ~/claude-memory/memory.jsonl — MCP knowledge-graph JSONL
308
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
+ *
309
333
  * Privacy: entities typed `person` (+ family/contact variants) and observations
310
334
  * containing credential-like strings default to PRIVATE and are filtered before
311
335
  * federation. Entities are deduped by case-insensitive name and sorted
@@ -617,7 +641,7 @@ declare class OpenClawParticipant implements BourdonParticipant {
617
641
  * section of `memory.md` becomes a recent Session. Mirrors the Codex automation
618
642
  * publisher — it covers the federation gap that the interactive-only
619
643
  * `claude-code` participant leaves behind (automations whose work never touches
620
- * claude-brain / auto-memory / the MCP knowledge graph).
644
+ * agent-brain / auto-memory / the MCP knowledge graph).
621
645
  *
622
646
  * Privacy: every native string routes through the redaction SSOT
623
647
  * (`redactText`, == the oracle's `_safe_native_memory_text`); the visibility
@@ -928,6 +952,95 @@ declare class CopilotVscodeParticipant implements BourdonParticipant {
928
952
  private allMemories;
929
953
  }
930
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
+
931
1044
  /**
932
1045
  * Participant discovery — a STATIC TS registry replacing Python's `pkgutil`
933
1046
  * package scan + entry-point duck-type (`participants/__init__.py`).
@@ -968,4 +1081,4 @@ declare function discoverParticipants(ctors?: ParticipantCtor[]): BourdonPartici
968
1081
  */
969
1082
  declare function resolvePluginParticipants(): ParticipantCtor[];
970
1083
 
971
- 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, FIRST_PARTY, GitHubCopilotParticipant, type HealthStatus, HermesParticipant, MIN_PATCHED_VERSION, NETWORK_CONTRACT_VERSION, NetworkParticipant, type NetworkParticipantOptions, NetworkUnavailable, OpenClawApiClient, OpenClawParticipant, type OpenReadonlyOptions, ParticipantAuthError, type ParticipantCtor, ParticipantDiscoveryError, ParticipantError, ParticipantExportError, ParticipantVersionMismatchError, PayloadCache, SPEC_VERSION, type SqliteDatabase, defaultCacheRoot, discoverParticipants, envAuthProvider, epochToIsoDate, epochToIsoDatetime, friendlyLabel, ghTokenProvider, isParticipant, openReadonly, projectKeyFromCwd, resolvePluginParticipants, sqliteAvailable, tableColumns, tableExists, tryOpenReadonly, verifyInstance };
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 };