@getbourdon/participants 0.2.2 → 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.
- package/README.md +7 -1
- package/dist/base.d.ts +109 -0
- package/dist/base.js +88 -0
- package/dist/index.cjs +171 -82
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +117 -4
- package/dist/index.d.ts +42 -970
- package/dist/index.js +53 -6509
- package/dist/index.js.map +1 -1
- package/dist/network-base.d.ts +108 -0
- package/dist/network-base.js +248 -0
- package/dist/readers/cascade.d.ts +49 -0
- package/dist/readers/cascade.js +428 -0
- package/dist/readers/claude-code-automations.d.ts +62 -0
- package/dist/readers/claude-code-automations.js +693 -0
- package/dist/readers/claude-code.d.ts +50 -0
- package/dist/readers/claude-code.js +583 -0
- package/dist/readers/claude-desktop-code.d.ts +54 -0
- package/dist/readers/claude-desktop-code.js +526 -0
- package/dist/readers/claude-desktop-cowork.d.ts +47 -0
- package/dist/readers/claude-desktop-cowork.js +659 -0
- package/dist/readers/codex-automations.d.ts +55 -0
- package/dist/readers/codex-automations.js +519 -0
- package/dist/readers/codex-sessions.d.ts +88 -0
- package/dist/readers/codex-sessions.js +194 -0
- package/dist/readers/copilot-automations.d.ts +64 -0
- package/dist/readers/copilot-automations.js +530 -0
- package/dist/readers/copilot-cli.d.ts +45 -0
- package/dist/readers/copilot-cli.js +416 -0
- package/dist/readers/copilot-vscode.d.ts +54 -0
- package/dist/readers/copilot-vscode.js +553 -0
- package/dist/readers/copilot.d.ts +59 -0
- package/dist/readers/copilot.js +413 -0
- package/dist/readers/cursor-automations.d.ts +57 -0
- package/dist/readers/cursor-automations.js +685 -0
- package/dist/readers/cursor.d.ts +50 -0
- package/dist/readers/cursor.js +670 -0
- package/dist/readers/github-copilot.d.ts +34 -0
- package/dist/readers/github-copilot.js +242 -0
- package/dist/readers/hermes.d.ts +37 -0
- package/dist/readers/hermes.js +426 -0
- package/dist/readers/openclaw.d.ts +78 -0
- package/dist/readers/openclaw.js +386 -0
- package/dist/registry.d.ts +39 -0
- package/dist/registry.js +98 -0
- package/dist/sqlite-base.d.ts +65 -0
- package/dist/sqlite-base.js +163 -0
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -14,12 +14,18 @@ Python (`pip install bourdon`) is the oracle; this TS mirror asserts against the
|
|
|
14
14
|
| Reader | Category | Native store |
|
|
15
15
|
|---|---|---|
|
|
16
16
|
| `HermesParticipant` | SQLite (read-only) | `~/.hermes/` — `state.db` sessions + `memories/*.md` |
|
|
17
|
-
| `ClaudeCodeParticipant` | file / convention |
|
|
17
|
+
| `ClaudeCodeParticipant` | file / convention | `~/agent-brain/` + `~/.claude/projects/*/memory/` + KG JSONL |
|
|
18
18
|
| `GitHubCopilotParticipant` | network (TTL cache) | `api.github.com` PR activity → `~/.cache/bourdon/github-copilot/` |
|
|
19
19
|
|
|
20
20
|
The heavier SQLite readers (`cursor`, `codex`, `copilot_cli`) are **deferred to
|
|
21
21
|
the follow-on slice**; `openclaw` ships as the `@getbourdon/openclaw` plugin.
|
|
22
22
|
|
|
23
|
+
`ClaudeCodeParticipant` resolves its knowledge repo in this order: the
|
|
24
|
+
`AGENT_BRAIN` env var, then `$HOME/agent-brain/`, then `./agent-brain/`. The
|
|
25
|
+
pre-rename env var (`CLAUDE_BRAIN`) and the pre-rename directory name are still
|
|
26
|
+
accepted as **legacy aliases** at each tier, so a checkout that predates the
|
|
27
|
+
rename keeps resolving with no operator action.
|
|
28
|
+
|
|
23
29
|
## The four invariants (enforced in code, not by trust)
|
|
24
30
|
|
|
25
31
|
1. **Visibility filter BEFORE emission** — every entity passes
|
package/dist/base.d.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bourdon participant base — the Protocol → TS interface, errors, and the
|
|
3
|
+
* AgentStore / HealthStatus types. Faithful port of `participants/base.py`.
|
|
4
|
+
*
|
|
5
|
+
* The L5 dataclass model (AgentInfo/Entity/Session/VisibilityPolicy/L5Manifest),
|
|
6
|
+
* the `toDict` omission rules, and the visibility helpers all live in
|
|
7
|
+
* `@getbourdon/l5` and are reused verbatim — only THAT output shape is the parity
|
|
8
|
+
* contract. This module owns the participant CONTRACT surface around them.
|
|
9
|
+
*
|
|
10
|
+
* Contract semantics (enforced by every reader, asserted by the conformance
|
|
11
|
+
* fixtures, never by trust):
|
|
12
|
+
* 1. visibility filter BEFORE emission (`filterForFederation`) — private wins.
|
|
13
|
+
* 2. deterministic / idempotent `exportL5` — same store → identical `toDict`.
|
|
14
|
+
* 3. `healthCheck` NEVER throws — catch-all → degraded/blocked.
|
|
15
|
+
* 4. every native string through `@getbourdon/redaction` before it enters L5.
|
|
16
|
+
*/
|
|
17
|
+
import type { L5ManifestModel, SessionModel } from "@getbourdon/l5";
|
|
18
|
+
/** Tied to Bourdon spec v0.1 — same literals as the Python oracle. */
|
|
19
|
+
export declare const CONTRACT_VERSION = "0.1";
|
|
20
|
+
export declare const SPEC_VERSION = "0.1";
|
|
21
|
+
/** Base class for participant errors. */
|
|
22
|
+
export declare class ParticipantError extends Error {
|
|
23
|
+
constructor(message?: string);
|
|
24
|
+
}
|
|
25
|
+
/** Raised by `discover()` when the native store cannot be found or read.
|
|
26
|
+
* Non-fatal: L6 skips this agent rather than aborting the whole export. */
|
|
27
|
+
export declare class ParticipantDiscoveryError extends ParticipantError {
|
|
28
|
+
}
|
|
29
|
+
/** Raised by `exportL5()` / `exportSessions()` when an export fails mid-op
|
|
30
|
+
* (the store WAS present — distinct from a discovery miss). */
|
|
31
|
+
export declare class ParticipantExportError extends ParticipantError {
|
|
32
|
+
}
|
|
33
|
+
/** Raised when the native store's version is outside the supported range.
|
|
34
|
+
* Subtype of discovery error (a version mismatch is a discovery-time miss). */
|
|
35
|
+
export declare class ParticipantVersionMismatchError extends ParticipantDiscoveryError {
|
|
36
|
+
}
|
|
37
|
+
/** Metadata describing the native agent store. Returned by `discover()`. */
|
|
38
|
+
export interface AgentStore {
|
|
39
|
+
path: string;
|
|
40
|
+
version: string;
|
|
41
|
+
metadata: Record<string, unknown>;
|
|
42
|
+
}
|
|
43
|
+
/** Returned by `healthCheck()`. Consumed by the `bourdon doctor` CLI. */
|
|
44
|
+
export interface HealthStatus {
|
|
45
|
+
status: "ok" | "degraded" | "blocked";
|
|
46
|
+
reason?: string;
|
|
47
|
+
details: Record<string, unknown>;
|
|
48
|
+
/** A human-runnable command to remedy a non-ok status. */
|
|
49
|
+
proposedFix?: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Structural interface every participant must satisfy (the Python
|
|
53
|
+
* `@runtime_checkable Protocol`). Duck-typed at registration: a class is a
|
|
54
|
+
* participant iff it has `agentId` + `agentType` + `exportL5` + `healthCheck`.
|
|
55
|
+
*
|
|
56
|
+
* Optional members (`displayName`, a `defaultNativePath` static) are documented
|
|
57
|
+
* here as in the Python Protocol; discovery + the setup wizard fall back to
|
|
58
|
+
* sensible defaults when absent.
|
|
59
|
+
*/
|
|
60
|
+
export interface BourdonParticipant {
|
|
61
|
+
agentId: string;
|
|
62
|
+
agentType: string;
|
|
63
|
+
nativePath: string;
|
|
64
|
+
/** Human-friendly label (e.g. "GitHub Copilot"). Optional. */
|
|
65
|
+
displayName?: string;
|
|
66
|
+
/** Quarantined-class marker (Python `QUARANTINED_CLASS`). When true, the CLI
|
|
67
|
+
* requires `--i-understand-the-risk` to register the agent trusted, and its
|
|
68
|
+
* exports are staged for operator review rather than written to the live
|
|
69
|
+
* store (spec D6: quarantine follows the content, not the invoker). Absent =
|
|
70
|
+
* a normal, non-quarantined participant. Read by `bourdon agent add/set-tier`
|
|
71
|
+
* (cli/src/commands/federation.ts). */
|
|
72
|
+
quarantinedClass?: boolean;
|
|
73
|
+
/** Confirm the native store exists; return metadata. Throws
|
|
74
|
+
* {@link ParticipantDiscoveryError} when missing/unreadable. */
|
|
75
|
+
discover(): AgentStore;
|
|
76
|
+
/** Build the L5 manifest from native memory, applying the visibility filter
|
|
77
|
+
* BEFORE return. Deterministic — same store yields the same manifest. */
|
|
78
|
+
exportL5(since?: Date): L5ManifestModel;
|
|
79
|
+
/** Export recent sessions in normalized schema. */
|
|
80
|
+
exportSessions(since?: Date, limit?: number): SessionModel[];
|
|
81
|
+
/** Return ok / degraded / blocked with a reason. MUST NOT throw. */
|
|
82
|
+
healthCheck(): HealthStatus;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Tiny structural guard mirroring Python's `_PARTICIPANT_MARKER_ATTRS`
|
|
86
|
+
* duck-type: a value is a participant iff it carries the four marker members.
|
|
87
|
+
*/
|
|
88
|
+
export declare function isParticipant(obj: unknown): obj is BourdonParticipant;
|
|
89
|
+
/**
|
|
90
|
+
* Environment variable holding the deployment's own project-name recognition
|
|
91
|
+
* vocabulary, as a comma-separated list (e.g.
|
|
92
|
+
* `BOURDON_PROJECT_HINTS="Acme Portal,Widget API,internal-tools"`).
|
|
93
|
+
*/
|
|
94
|
+
export declare const PROJECT_HINTS_ENV = "BOURDON_PROJECT_HINTS";
|
|
95
|
+
/**
|
|
96
|
+
* Project-name hints used to tag sessions with a project focus.
|
|
97
|
+
*
|
|
98
|
+
* Bourdon ships **no** project roster of its own — the `defaults` a reader
|
|
99
|
+
* passes are limited to product-neutral names (this product, plus the agent
|
|
100
|
+
* surfaces it federates). A deployment that wants its own projects recognized
|
|
101
|
+
* sets {@link PROJECT_HINTS_ENV}; those entries are appended to `defaults`.
|
|
102
|
+
*
|
|
103
|
+
* Matching downstream is case-insensitive substring matching, so entries are
|
|
104
|
+
* de-duplicated case-insensitively here while preserving first-seen order and
|
|
105
|
+
* the original casing (which is what gets emitted as the project name).
|
|
106
|
+
*
|
|
107
|
+
* Mirrors Python `participants.base.load_project_hints`.
|
|
108
|
+
*/
|
|
109
|
+
export declare function loadProjectHints(defaults?: readonly string[]): readonly string[];
|
package/dist/base.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bourdon participant base — the Protocol → TS interface, errors, and the
|
|
3
|
+
* AgentStore / HealthStatus types. Faithful port of `participants/base.py`.
|
|
4
|
+
*
|
|
5
|
+
* The L5 dataclass model (AgentInfo/Entity/Session/VisibilityPolicy/L5Manifest),
|
|
6
|
+
* the `toDict` omission rules, and the visibility helpers all live in
|
|
7
|
+
* `@getbourdon/l5` and are reused verbatim — only THAT output shape is the parity
|
|
8
|
+
* contract. This module owns the participant CONTRACT surface around them.
|
|
9
|
+
*
|
|
10
|
+
* Contract semantics (enforced by every reader, asserted by the conformance
|
|
11
|
+
* fixtures, never by trust):
|
|
12
|
+
* 1. visibility filter BEFORE emission (`filterForFederation`) — private wins.
|
|
13
|
+
* 2. deterministic / idempotent `exportL5` — same store → identical `toDict`.
|
|
14
|
+
* 3. `healthCheck` NEVER throws — catch-all → degraded/blocked.
|
|
15
|
+
* 4. every native string through `@getbourdon/redaction` before it enters L5.
|
|
16
|
+
*/
|
|
17
|
+
/** Tied to Bourdon spec v0.1 — same literals as the Python oracle. */
|
|
18
|
+
export const CONTRACT_VERSION = "0.1";
|
|
19
|
+
export const SPEC_VERSION = "0.1";
|
|
20
|
+
// -- Errors -------------------------------------------------------------------
|
|
21
|
+
/** Base class for participant errors. */
|
|
22
|
+
export class ParticipantError extends Error {
|
|
23
|
+
constructor(message) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = new.target.name;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** Raised by `discover()` when the native store cannot be found or read.
|
|
29
|
+
* Non-fatal: L6 skips this agent rather than aborting the whole export. */
|
|
30
|
+
export class ParticipantDiscoveryError extends ParticipantError {
|
|
31
|
+
}
|
|
32
|
+
/** Raised by `exportL5()` / `exportSessions()` when an export fails mid-op
|
|
33
|
+
* (the store WAS present — distinct from a discovery miss). */
|
|
34
|
+
export class ParticipantExportError extends ParticipantError {
|
|
35
|
+
}
|
|
36
|
+
/** Raised when the native store's version is outside the supported range.
|
|
37
|
+
* Subtype of discovery error (a version mismatch is a discovery-time miss). */
|
|
38
|
+
export class ParticipantVersionMismatchError extends ParticipantDiscoveryError {
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Tiny structural guard mirroring Python's `_PARTICIPANT_MARKER_ATTRS`
|
|
42
|
+
* duck-type: a value is a participant iff it carries the four marker members.
|
|
43
|
+
*/
|
|
44
|
+
export function isParticipant(obj) {
|
|
45
|
+
if (obj === null || typeof obj !== "object")
|
|
46
|
+
return false;
|
|
47
|
+
const o = obj;
|
|
48
|
+
return (typeof o["agentId"] === "string" &&
|
|
49
|
+
typeof o["agentType"] === "string" &&
|
|
50
|
+
typeof o["exportL5"] === "function" &&
|
|
51
|
+
typeof o["healthCheck"] === "function");
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Environment variable holding the deployment's own project-name recognition
|
|
55
|
+
* vocabulary, as a comma-separated list (e.g.
|
|
56
|
+
* `BOURDON_PROJECT_HINTS="Acme Portal,Widget API,internal-tools"`).
|
|
57
|
+
*/
|
|
58
|
+
export const PROJECT_HINTS_ENV = "BOURDON_PROJECT_HINTS";
|
|
59
|
+
/**
|
|
60
|
+
* Project-name hints used to tag sessions with a project focus.
|
|
61
|
+
*
|
|
62
|
+
* Bourdon ships **no** project roster of its own — the `defaults` a reader
|
|
63
|
+
* passes are limited to product-neutral names (this product, plus the agent
|
|
64
|
+
* surfaces it federates). A deployment that wants its own projects recognized
|
|
65
|
+
* sets {@link PROJECT_HINTS_ENV}; those entries are appended to `defaults`.
|
|
66
|
+
*
|
|
67
|
+
* Matching downstream is case-insensitive substring matching, so entries are
|
|
68
|
+
* de-duplicated case-insensitively here while preserving first-seen order and
|
|
69
|
+
* the original casing (which is what gets emitted as the project name).
|
|
70
|
+
*
|
|
71
|
+
* Mirrors Python `participants.base.load_project_hints`.
|
|
72
|
+
*/
|
|
73
|
+
export function loadProjectHints(defaults = []) {
|
|
74
|
+
const hints = [];
|
|
75
|
+
const seen = new Set();
|
|
76
|
+
const raw = process.env[PROJECT_HINTS_ENV] ?? "";
|
|
77
|
+
for (const candidate of [...defaults, ...raw.split(",")]) {
|
|
78
|
+
const name = candidate.trim();
|
|
79
|
+
if (!name)
|
|
80
|
+
continue;
|
|
81
|
+
const key = name.toLowerCase();
|
|
82
|
+
if (seen.has(key))
|
|
83
|
+
continue;
|
|
84
|
+
seen.add(key);
|
|
85
|
+
hints.push(name);
|
|
86
|
+
}
|
|
87
|
+
return hints;
|
|
88
|
+
}
|
package/dist/index.cjs
CHANGED
|
@@ -35,6 +35,8 @@ __export(index_exports, {
|
|
|
35
35
|
CursorAutomationsParticipant: () => CursorAutomationsParticipant,
|
|
36
36
|
CursorParticipant: () => CursorParticipant,
|
|
37
37
|
DEFAULT_CACHE_TTL_SECONDS: () => DEFAULT_CACHE_TTL_SECONDS,
|
|
38
|
+
DEFAULT_RECENT_THREAD_LIMIT: () => DEFAULT_RECENT_THREAD_LIMIT,
|
|
39
|
+
DEFAULT_TITLE_LIMIT: () => DEFAULT_TITLE_LIMIT,
|
|
38
40
|
FIRST_PARTY: () => FIRST_PARTY,
|
|
39
41
|
GitHubCopilotParticipant: () => GitHubCopilotParticipant,
|
|
40
42
|
HermesParticipant: () => HermesParticipant,
|
|
@@ -44,6 +46,7 @@ __export(index_exports, {
|
|
|
44
46
|
NetworkUnavailable: () => NetworkUnavailable,
|
|
45
47
|
OpenClawApiClient: () => OpenClawApiClient,
|
|
46
48
|
OpenClawParticipant: () => OpenClawParticipant,
|
|
49
|
+
PROJECT_HINTS_ENV: () => PROJECT_HINTS_ENV,
|
|
47
50
|
ParticipantAuthError: () => ParticipantAuthError,
|
|
48
51
|
ParticipantDiscoveryError: () => ParticipantDiscoveryError,
|
|
49
52
|
ParticipantError: () => ParticipantError,
|
|
@@ -62,9 +65,14 @@ __export(index_exports, {
|
|
|
62
65
|
friendlyLabel: () => friendlyLabel,
|
|
63
66
|
ghTokenProvider: () => ghTokenProvider,
|
|
64
67
|
isParticipant: () => isParticipant,
|
|
68
|
+
loadProjectHints: () => loadProjectHints,
|
|
65
69
|
openReadonly: () => openReadonly,
|
|
70
|
+
parseSessionIndex: () => parseSessionIndex,
|
|
66
71
|
projectKeyFromCwd: () => projectKeyFromCwd,
|
|
72
|
+
recentSessionThreads: () => recentSessionThreads,
|
|
73
|
+
resolveCodexHome: () => resolveCodexHome,
|
|
67
74
|
resolvePluginParticipants: () => resolvePluginParticipants,
|
|
75
|
+
sessionThreadTitles: () => sessionThreadTitles,
|
|
68
76
|
sqliteAvailable: () => sqliteAvailable,
|
|
69
77
|
tableColumns: () => tableColumns,
|
|
70
78
|
tableExists: () => tableExists,
|
|
@@ -95,6 +103,21 @@ function isParticipant(obj) {
|
|
|
95
103
|
const o = obj;
|
|
96
104
|
return typeof o["agentId"] === "string" && typeof o["agentType"] === "string" && typeof o["exportL5"] === "function" && typeof o["healthCheck"] === "function";
|
|
97
105
|
}
|
|
106
|
+
var PROJECT_HINTS_ENV = "BOURDON_PROJECT_HINTS";
|
|
107
|
+
function loadProjectHints(defaults = []) {
|
|
108
|
+
const hints = [];
|
|
109
|
+
const seen = /* @__PURE__ */ new Set();
|
|
110
|
+
const raw = process.env[PROJECT_HINTS_ENV] ?? "";
|
|
111
|
+
for (const candidate of [...defaults, ...raw.split(",")]) {
|
|
112
|
+
const name = candidate.trim();
|
|
113
|
+
if (!name) continue;
|
|
114
|
+
const key = name.toLowerCase();
|
|
115
|
+
if (seen.has(key)) continue;
|
|
116
|
+
seen.add(key);
|
|
117
|
+
hints.push(name);
|
|
118
|
+
}
|
|
119
|
+
return hints;
|
|
120
|
+
}
|
|
98
121
|
|
|
99
122
|
// src/sqlite-base.ts
|
|
100
123
|
var import_node_fs = require("fs");
|
|
@@ -749,7 +772,7 @@ var import_l52 = require("@getbourdon/l5");
|
|
|
749
772
|
var import_redaction2 = require("@getbourdon/redaction");
|
|
750
773
|
var AGENT_ID2 = "claude-code";
|
|
751
774
|
var AGENT_TYPE2 = "code-assistant";
|
|
752
|
-
var ROLE_NARRATIVE2 = "Agentic manager and code-assistant. Coordinates the
|
|
775
|
+
var ROLE_NARRATIVE2 = "Agentic manager and code-assistant. Coordinates the agent fleet, reviews PRs, and consults on architectural decisions. Capable of authoring code but typically reviews + delegates to specialised code-assistants like Codex for prime-code execution.";
|
|
753
776
|
var DEFAULT_POLICY2 = (0, import_l52.makeVisibilityPolicy)({
|
|
754
777
|
default: import_l52.Visibility.PUBLIC,
|
|
755
778
|
private_tags: ["personal", "financial", "credential", "health", "family", "legal"],
|
|
@@ -779,13 +802,22 @@ function isFile2(p) {
|
|
|
779
802
|
return false;
|
|
780
803
|
}
|
|
781
804
|
}
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
805
|
+
var BRAIN_DIR_NAMES = [
|
|
806
|
+
"agent-brain",
|
|
807
|
+
["c", "laude-brain"].join("")
|
|
808
|
+
];
|
|
809
|
+
var BRAIN_ENV_VARS = ["AGENT_BRAIN", "CLAUDE_BRAIN"];
|
|
810
|
+
function resolveBrainPath() {
|
|
811
|
+
for (const varName of BRAIN_ENV_VARS) {
|
|
812
|
+
const envOverride = process.env[varName];
|
|
813
|
+
if (envOverride && isDir2(envOverride)) return envOverride;
|
|
814
|
+
}
|
|
815
|
+
for (const base of [homeDir(), process.cwd()]) {
|
|
816
|
+
for (const name of BRAIN_DIR_NAMES) {
|
|
817
|
+
const candidate = (0, import_node_path3.join)(base, name);
|
|
818
|
+
if (isDir2(candidate)) return candidate;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
789
821
|
return null;
|
|
790
822
|
}
|
|
791
823
|
function homeDir() {
|
|
@@ -1110,8 +1142,8 @@ var ClaudeCodeParticipant = class {
|
|
|
1110
1142
|
return (0, import_node_path3.join)(home ?? homeDir(), ".claude");
|
|
1111
1143
|
}
|
|
1112
1144
|
constructor() {
|
|
1113
|
-
this.nativePath = (0, import_node_path3.join)(homeDir(),
|
|
1114
|
-
this.brainPath =
|
|
1145
|
+
this.nativePath = (0, import_node_path3.join)(homeDir(), BRAIN_DIR_NAMES[0]);
|
|
1146
|
+
this.brainPath = resolveBrainPath();
|
|
1115
1147
|
this.autoMemoryPath = resolveAutoMemoryPath();
|
|
1116
1148
|
this.knowledgeGraphPath = resolveKnowledgeGraphPath();
|
|
1117
1149
|
}
|
|
@@ -1123,7 +1155,7 @@ var ClaudeCodeParticipant = class {
|
|
|
1123
1155
|
};
|
|
1124
1156
|
if (!Object.values(sources).some((v) => v)) {
|
|
1125
1157
|
throw new ParticipantDiscoveryError(
|
|
1126
|
-
"No Claude Code memory sources found. Expected one of: ~/
|
|
1158
|
+
"No Claude Code memory sources found. Expected one of: ~/agent-brain/, ~/.claude/projects/*/memory/, ~/claude-memory/memory.jsonl."
|
|
1127
1159
|
);
|
|
1128
1160
|
}
|
|
1129
1161
|
return {
|
|
@@ -1185,7 +1217,7 @@ var ClaudeCodeParticipant = class {
|
|
|
1185
1217
|
status: "degraded",
|
|
1186
1218
|
reason: `${present}/3 Claude Code memory sources found`,
|
|
1187
1219
|
details,
|
|
1188
|
-
proposedFix: "Run `bourdon setup` to (re-)wire missing sources, or set the
|
|
1220
|
+
proposedFix: "Run `bourdon setup` to (re-)wire missing sources, or set the AGENT_BRAIN env var to point at your agent-brain checkout."
|
|
1189
1221
|
};
|
|
1190
1222
|
} catch (err) {
|
|
1191
1223
|
return {
|
|
@@ -3229,24 +3261,15 @@ var MAX_KEY_ACTIONS_PER_RUN = 6;
|
|
|
3229
3261
|
var MAX_KEY_ACTION_CHARS2 = 280;
|
|
3230
3262
|
var RUN_HEADER_RE = /^(\d{4}-\d{2}-\d{2})(?:\b|$)(.*)$/;
|
|
3231
3263
|
var HEADER_SUFFIX_STRIP = " -:\u2014";
|
|
3232
|
-
var
|
|
3233
|
-
"ShipStable",
|
|
3234
|
-
"ILTT",
|
|
3235
|
-
"Prun",
|
|
3236
|
-
"PRUN",
|
|
3237
|
-
"OMNIvour",
|
|
3238
|
-
"Castmore",
|
|
3264
|
+
var DEFAULT_PROJECT_HINTS = [
|
|
3239
3265
|
"Bourdon",
|
|
3240
|
-
"RADLAB",
|
|
3241
|
-
"CHIP",
|
|
3242
|
-
"Claude Brain",
|
|
3243
3266
|
"Cursor",
|
|
3244
3267
|
"Copilot",
|
|
3245
3268
|
"Codex",
|
|
3246
3269
|
"Cascade"
|
|
3247
3270
|
];
|
|
3248
3271
|
var SIGNAL_PATTERNS = [
|
|
3249
|
-
["human-dashboard-action", /\b(human|
|
|
3272
|
+
["human-dashboard-action", /\b(human|dashboard|manual)\b/i],
|
|
3250
3273
|
["release-gate", /\b(release|store|app review|play console|testflight)\b/i],
|
|
3251
3274
|
["billing-drift", /\b(billing|stripe|revenuecat|iap|subscription)\b/i],
|
|
3252
3275
|
["memory-coverage-gap", /\b(memory|l5|manifest|federated|bourdon)\b/i],
|
|
@@ -3470,7 +3493,7 @@ function inferProjects(text) {
|
|
|
3470
3493
|
const projects = [];
|
|
3471
3494
|
const lowered = text.toLowerCase();
|
|
3472
3495
|
const seen = /* @__PURE__ */ new Set();
|
|
3473
|
-
for (const project of
|
|
3496
|
+
for (const project of loadProjectHints(DEFAULT_PROJECT_HINTS)) {
|
|
3474
3497
|
const key = project.toLowerCase();
|
|
3475
3498
|
if (lowered.includes(key) && !seen.has(key)) {
|
|
3476
3499
|
projects.push(project);
|
|
@@ -3701,22 +3724,9 @@ var MAX_MEMORY_CHARS2 = 16e4;
|
|
|
3701
3724
|
var MAX_KEY_ACTIONS_PER_RUN2 = 6;
|
|
3702
3725
|
var MAX_KEY_ACTION_CHARS3 = 280;
|
|
3703
3726
|
var RUN_HEADER_RE2 = /^(\d{4}-\d{2}-\d{2})(?:\b|$)(.*)$/;
|
|
3704
|
-
var
|
|
3705
|
-
"ShipStable",
|
|
3706
|
-
"ILTT",
|
|
3707
|
-
"Prun",
|
|
3708
|
-
"PRUN",
|
|
3709
|
-
"OMNIvour",
|
|
3710
|
-
"Castmore",
|
|
3711
|
-
"Bourdon",
|
|
3712
|
-
"RADLAB",
|
|
3713
|
-
"CHIP",
|
|
3714
|
-
"Claude Brain",
|
|
3715
|
-
"Cursor",
|
|
3716
|
-
"Copilot"
|
|
3717
|
-
];
|
|
3727
|
+
var DEFAULT_PROJECT_HINTS2 = ["Bourdon", "Cursor", "Copilot"];
|
|
3718
3728
|
var SIGNAL_PATTERNS2 = [
|
|
3719
|
-
["human-dashboard-action", /\b(human|
|
|
3729
|
+
["human-dashboard-action", /\b(human|dashboard|manual)\b/i],
|
|
3720
3730
|
["release-gate", /\b(release|store|app review|play console|testflight)\b/i],
|
|
3721
3731
|
["billing-drift", /\b(billing|stripe|revenuecat|iap|subscription)\b/i],
|
|
3722
3732
|
["memory-coverage-gap", /\b(memory|l5|manifest|federated|bourdon)\b/i],
|
|
@@ -3834,7 +3844,7 @@ function readMemoryText2(path) {
|
|
|
3834
3844
|
return text.length > MAX_MEMORY_CHARS2 ? text.slice(-MAX_MEMORY_CHARS2) : text;
|
|
3835
3845
|
}
|
|
3836
3846
|
function splitLines2(text) {
|
|
3837
|
-
return text.split(/\r\n|[\n\r\
|
|
3847
|
+
return text.split(/\r\n|[\n\r\u000B\u000C\u001C\u001D\u001E\u0085\u2028\u2029]/u);
|
|
3838
3848
|
}
|
|
3839
3849
|
function rstrip2(s) {
|
|
3840
3850
|
return s.replace(/\s+$/, "");
|
|
@@ -3874,7 +3884,7 @@ function inferProjects2(text) {
|
|
|
3874
3884
|
const projects = [];
|
|
3875
3885
|
const lowered = text.toLowerCase();
|
|
3876
3886
|
const seen = /* @__PURE__ */ new Set();
|
|
3877
|
-
for (const project of
|
|
3887
|
+
for (const project of loadProjectHints(DEFAULT_PROJECT_HINTS2)) {
|
|
3878
3888
|
const key = project.toLowerCase();
|
|
3879
3889
|
if (lowered.includes(key) && !seen.has(key)) {
|
|
3880
3890
|
projects.push(project);
|
|
@@ -4213,9 +4223,7 @@ function buildConfig3(tomlPath) {
|
|
|
4213
4223
|
const kind = pyStr2(pyTruthy(raw["kind"]) ? raw["kind"] : "").trim();
|
|
4214
4224
|
const reposRaw = pyTruthy(raw["repos"]) ? raw["repos"] : [];
|
|
4215
4225
|
const reposIter = Array.isArray(reposRaw) ? reposRaw : typeof reposRaw === "string" ? Array.from(reposRaw) : [];
|
|
4216
|
-
const repos = reposIter.filter(
|
|
4217
|
-
(r) => typeof r === "string" && r.trim() !== ""
|
|
4218
|
-
);
|
|
4226
|
+
const repos = reposIter.filter((r) => typeof r === "string" && r.trim() !== "");
|
|
4219
4227
|
const memoryPath = (0, import_node_path11.join)(parentDir, MEMORY_MD3);
|
|
4220
4228
|
return {
|
|
4221
4229
|
automationId,
|
|
@@ -4251,7 +4259,10 @@ function iterConfigs3(automationsDir) {
|
|
|
4251
4259
|
}
|
|
4252
4260
|
function splitLines3(text) {
|
|
4253
4261
|
if (text.length === 0) return [];
|
|
4254
|
-
return text.split(
|
|
4262
|
+
return text.split(
|
|
4263
|
+
// eslint-disable-next-line no-control-regex
|
|
4264
|
+
/\r\n|\r|\n|\u000B|\u000C|\u001C|\u001D|\u001E|\u0085|\u2028|\u2029/u
|
|
4265
|
+
);
|
|
4255
4266
|
}
|
|
4256
4267
|
function rstrip3(s) {
|
|
4257
4268
|
return s.replace(/\s+$/u, "");
|
|
@@ -4269,9 +4280,7 @@ function extractMemoryRuns3(config) {
|
|
|
4269
4280
|
try {
|
|
4270
4281
|
text = (0, import_node_fs11.readFileSync)(config.memoryPath, "utf8");
|
|
4271
4282
|
} catch (exc) {
|
|
4272
|
-
logger5.warn(
|
|
4273
|
-
`CopilotAutomationsParticipant: cannot read ${config.memoryPath}: ${String(exc)}`
|
|
4274
|
-
);
|
|
4283
|
+
logger5.warn(`CopilotAutomationsParticipant: cannot read ${config.memoryPath}: ${String(exc)}`);
|
|
4275
4284
|
return [];
|
|
4276
4285
|
}
|
|
4277
4286
|
text = text.slice(-MAX_MEMORY_CHARS3);
|
|
@@ -4521,24 +4530,15 @@ var MAX_KEY_ACTIONS_PER_RUN4 = 6;
|
|
|
4521
4530
|
var MAX_KEY_ACTION_CHARS5 = 280;
|
|
4522
4531
|
var RUN_HEADER_RE4 = /^(\d{4}-\d{2}-\d{2})(?:\b|$)(.*)$/;
|
|
4523
4532
|
var HEADER_SUFFIX_STRIP2 = " -:\u2014";
|
|
4524
|
-
var
|
|
4525
|
-
"ShipStable",
|
|
4526
|
-
"ILTT",
|
|
4527
|
-
"Prun",
|
|
4528
|
-
"PRUN",
|
|
4529
|
-
"OMNIvour",
|
|
4530
|
-
"Castmore",
|
|
4533
|
+
var DEFAULT_PROJECT_HINTS3 = [
|
|
4531
4534
|
"Bourdon",
|
|
4532
|
-
"RADLAB",
|
|
4533
|
-
"CHIP",
|
|
4534
|
-
"Claude Brain",
|
|
4535
4535
|
"Cursor",
|
|
4536
4536
|
"Copilot",
|
|
4537
4537
|
"Codex",
|
|
4538
4538
|
"Cascade"
|
|
4539
4539
|
];
|
|
4540
4540
|
var SIGNAL_PATTERNS3 = [
|
|
4541
|
-
["human-dashboard-action", /\b(human|
|
|
4541
|
+
["human-dashboard-action", /\b(human|dashboard|manual)\b/i],
|
|
4542
4542
|
["release-gate", /\b(release|store|app review|play console|testflight)\b/i],
|
|
4543
4543
|
["billing-drift", /\b(billing|stripe|revenuecat|iap|subscription)\b/i],
|
|
4544
4544
|
["memory-coverage-gap", /\b(memory|l5|manifest|federated|bourdon)\b/i],
|
|
@@ -4751,7 +4751,7 @@ function inferProjects3(text) {
|
|
|
4751
4751
|
const projects = [];
|
|
4752
4752
|
const lowered = text.toLowerCase();
|
|
4753
4753
|
const seen = /* @__PURE__ */ new Set();
|
|
4754
|
-
for (const project of
|
|
4754
|
+
for (const project of loadProjectHints(DEFAULT_PROJECT_HINTS3)) {
|
|
4755
4755
|
const key = project.toLowerCase();
|
|
4756
4756
|
if (lowered.includes(key) && !seen.has(key)) {
|
|
4757
4757
|
projects.push(project);
|
|
@@ -4962,17 +4962,8 @@ var STATE_FILE_RE = /^local_.*\.json$/;
|
|
|
4962
4962
|
var MAX_KEY_ACTION_CHARS6 = 280;
|
|
4963
4963
|
var MAX_PROJECTS = 6;
|
|
4964
4964
|
var MAX_KEY_ACTIONS2 = 6;
|
|
4965
|
-
var
|
|
4966
|
-
"ShipStable",
|
|
4967
|
-
"ILTT",
|
|
4968
|
-
"Prun",
|
|
4969
|
-
"PRUN",
|
|
4970
|
-
"OMNIvour",
|
|
4971
|
-
"Castmore",
|
|
4965
|
+
var DEFAULT_PROJECT_HINTS4 = [
|
|
4972
4966
|
"Bourdon",
|
|
4973
|
-
"RADLAB",
|
|
4974
|
-
"CHIP",
|
|
4975
|
-
"Claude Brain",
|
|
4976
4967
|
"Cursor",
|
|
4977
4968
|
"Copilot",
|
|
4978
4969
|
"Codex",
|
|
@@ -5142,7 +5133,7 @@ function inferProjects4(state) {
|
|
|
5142
5133
|
if (base) add(base);
|
|
5143
5134
|
}
|
|
5144
5135
|
const haystack = pathStrings.join(" ").toLowerCase();
|
|
5145
|
-
for (const hint of
|
|
5136
|
+
for (const hint of loadProjectHints(DEFAULT_PROJECT_HINTS4)) {
|
|
5146
5137
|
if (haystack.includes(hint.toLowerCase())) add(hint);
|
|
5147
5138
|
}
|
|
5148
5139
|
return projects.slice(0, MAX_PROJECTS);
|
|
@@ -5389,17 +5380,8 @@ var STATE_PREFIX2 = "local_";
|
|
|
5389
5380
|
var MAX_PROJECTS2 = 6;
|
|
5390
5381
|
var MAX_KEY_ACTIONS3 = 8;
|
|
5391
5382
|
var MAX_AUDIT_LINES = 5e4;
|
|
5392
|
-
var
|
|
5393
|
-
"ShipStable",
|
|
5394
|
-
"ILTT",
|
|
5395
|
-
"Prun",
|
|
5396
|
-
"PRUN",
|
|
5397
|
-
"OMNIvour",
|
|
5398
|
-
"Castmore",
|
|
5383
|
+
var DEFAULT_PROJECT_HINTS5 = [
|
|
5399
5384
|
"Bourdon",
|
|
5400
|
-
"RADLAB",
|
|
5401
|
-
"CHIP",
|
|
5402
|
-
"Claude Brain",
|
|
5403
5385
|
"Cursor",
|
|
5404
5386
|
"Copilot",
|
|
5405
5387
|
"Codex",
|
|
@@ -5579,7 +5561,7 @@ function inferProjects5(state) {
|
|
|
5579
5561
|
if (base) add(base);
|
|
5580
5562
|
}
|
|
5581
5563
|
const haystack = pathStrings.join(" ").toLowerCase();
|
|
5582
|
-
for (const hint of
|
|
5564
|
+
for (const hint of loadProjectHints(DEFAULT_PROJECT_HINTS5)) {
|
|
5583
5565
|
if (haystack.includes(hint.toLowerCase())) add(hint);
|
|
5584
5566
|
}
|
|
5585
5567
|
return projects.slice(0, MAX_PROJECTS2);
|
|
@@ -6350,6 +6332,105 @@ var CopilotVscodeParticipant = class {
|
|
|
6350
6332
|
}
|
|
6351
6333
|
};
|
|
6352
6334
|
|
|
6335
|
+
// src/readers/codex-sessions.ts
|
|
6336
|
+
var import_node_fs16 = require("fs");
|
|
6337
|
+
var import_node_os16 = require("os");
|
|
6338
|
+
var import_node_path16 = require("path");
|
|
6339
|
+
var DEFAULT_TITLE_LIMIT = 200;
|
|
6340
|
+
var DEFAULT_RECENT_THREAD_LIMIT = 5;
|
|
6341
|
+
function normalizeText(value) {
|
|
6342
|
+
return value.trim().replace(/\s+/g, " ");
|
|
6343
|
+
}
|
|
6344
|
+
function isDir14(path) {
|
|
6345
|
+
try {
|
|
6346
|
+
return (0, import_node_fs16.statSync)(path).isDirectory();
|
|
6347
|
+
} catch {
|
|
6348
|
+
return false;
|
|
6349
|
+
}
|
|
6350
|
+
}
|
|
6351
|
+
function resolveCodexHome(baseHome) {
|
|
6352
|
+
const env = process.env.CODEX_HOME;
|
|
6353
|
+
if (env) {
|
|
6354
|
+
if (isDir14(env)) return env;
|
|
6355
|
+
}
|
|
6356
|
+
const home = baseHome ? baseHome : (0, import_node_os16.homedir)();
|
|
6357
|
+
const candidate = (0, import_node_path16.join)(home, ".codex");
|
|
6358
|
+
return isDir14(candidate) ? candidate : null;
|
|
6359
|
+
}
|
|
6360
|
+
function parseSessionIndex(path, limit) {
|
|
6361
|
+
let text;
|
|
6362
|
+
try {
|
|
6363
|
+
if (!(0, import_node_fs16.statSync)(path).isFile()) return [];
|
|
6364
|
+
text = (0, import_node_fs16.readFileSync)(path, "utf8");
|
|
6365
|
+
} catch (exc) {
|
|
6366
|
+
if (existsQuiet(path)) console.warn(`Failed to read ${path}: ${String(exc)}`);
|
|
6367
|
+
return [];
|
|
6368
|
+
}
|
|
6369
|
+
const entries = [];
|
|
6370
|
+
const lines = text.split(/\r?\n/);
|
|
6371
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
6372
|
+
const line = lines[i].trim();
|
|
6373
|
+
if (!line) continue;
|
|
6374
|
+
let record;
|
|
6375
|
+
try {
|
|
6376
|
+
record = JSON.parse(line);
|
|
6377
|
+
} catch (exc) {
|
|
6378
|
+
console.warn(`Skipping malformed JSONL in ${path}:${i + 1} -- ${String(exc)}`);
|
|
6379
|
+
continue;
|
|
6380
|
+
}
|
|
6381
|
+
if (record !== null && typeof record === "object" && !Array.isArray(record) && typeof record.id === "string") {
|
|
6382
|
+
entries.push(record);
|
|
6383
|
+
}
|
|
6384
|
+
}
|
|
6385
|
+
entries.sort((a, b) => {
|
|
6386
|
+
const ua = String(a.updated_at ?? "");
|
|
6387
|
+
const ub = String(b.updated_at ?? "");
|
|
6388
|
+
return ua < ub ? 1 : ua > ub ? -1 : 0;
|
|
6389
|
+
});
|
|
6390
|
+
return limit !== void 0 && limit !== null ? entries.slice(0, limit) : entries;
|
|
6391
|
+
}
|
|
6392
|
+
function existsQuiet(path) {
|
|
6393
|
+
try {
|
|
6394
|
+
(0, import_node_fs16.statSync)(path);
|
|
6395
|
+
return true;
|
|
6396
|
+
} catch {
|
|
6397
|
+
return false;
|
|
6398
|
+
}
|
|
6399
|
+
}
|
|
6400
|
+
function sessionThreadTitles(codexHome, opts = {}) {
|
|
6401
|
+
const limit = opts.limit ?? DEFAULT_TITLE_LIMIT;
|
|
6402
|
+
const home = codexHome === void 0 || codexHome === null ? resolveCodexHome() : codexHome;
|
|
6403
|
+
if (home === null) return {};
|
|
6404
|
+
const titles = {};
|
|
6405
|
+
for (const entry of parseSessionIndex((0, import_node_path16.join)(home, "session_index.jsonl"), limit)) {
|
|
6406
|
+
const sid = entry.id;
|
|
6407
|
+
const name = entry.thread_name;
|
|
6408
|
+
if (typeof sid === "string" && sid && typeof name === "string" && name.trim() && !(sid in titles)) {
|
|
6409
|
+
titles[sid] = normalizeText(name);
|
|
6410
|
+
}
|
|
6411
|
+
}
|
|
6412
|
+
return titles;
|
|
6413
|
+
}
|
|
6414
|
+
function recentSessionThreads(codexHome, opts = {}) {
|
|
6415
|
+
const limit = opts.limit ?? DEFAULT_RECENT_THREAD_LIMIT;
|
|
6416
|
+
const home = codexHome === void 0 || codexHome === null ? resolveCodexHome() : codexHome;
|
|
6417
|
+
if (home === null) return [];
|
|
6418
|
+
const threads = [];
|
|
6419
|
+
for (const entry of parseSessionIndex((0, import_node_path16.join)(home, "session_index.jsonl"), limit)) {
|
|
6420
|
+
const sid = entry.id;
|
|
6421
|
+
if (typeof sid !== "string" || !sid) continue;
|
|
6422
|
+
const name = entry.thread_name;
|
|
6423
|
+
const title = typeof name === "string" && name.trim() ? normalizeText(name) : null;
|
|
6424
|
+
const updated = String(entry.updated_at ?? "");
|
|
6425
|
+
threads.push({
|
|
6426
|
+
instance: sid.slice(0, 8),
|
|
6427
|
+
title,
|
|
6428
|
+
updated_at: updated || null
|
|
6429
|
+
});
|
|
6430
|
+
}
|
|
6431
|
+
return threads;
|
|
6432
|
+
}
|
|
6433
|
+
|
|
6353
6434
|
// src/registry.ts
|
|
6354
6435
|
var FIRST_PARTY = [
|
|
6355
6436
|
CascadeParticipant,
|
|
@@ -6416,6 +6497,8 @@ var import_l516 = require("@getbourdon/l5");
|
|
|
6416
6497
|
CursorAutomationsParticipant,
|
|
6417
6498
|
CursorParticipant,
|
|
6418
6499
|
DEFAULT_CACHE_TTL_SECONDS,
|
|
6500
|
+
DEFAULT_RECENT_THREAD_LIMIT,
|
|
6501
|
+
DEFAULT_TITLE_LIMIT,
|
|
6419
6502
|
FIRST_PARTY,
|
|
6420
6503
|
GitHubCopilotParticipant,
|
|
6421
6504
|
HermesParticipant,
|
|
@@ -6425,6 +6508,7 @@ var import_l516 = require("@getbourdon/l5");
|
|
|
6425
6508
|
NetworkUnavailable,
|
|
6426
6509
|
OpenClawApiClient,
|
|
6427
6510
|
OpenClawParticipant,
|
|
6511
|
+
PROJECT_HINTS_ENV,
|
|
6428
6512
|
ParticipantAuthError,
|
|
6429
6513
|
ParticipantDiscoveryError,
|
|
6430
6514
|
ParticipantError,
|
|
@@ -6443,9 +6527,14 @@ var import_l516 = require("@getbourdon/l5");
|
|
|
6443
6527
|
friendlyLabel,
|
|
6444
6528
|
ghTokenProvider,
|
|
6445
6529
|
isParticipant,
|
|
6530
|
+
loadProjectHints,
|
|
6446
6531
|
openReadonly,
|
|
6532
|
+
parseSessionIndex,
|
|
6447
6533
|
projectKeyFromCwd,
|
|
6534
|
+
recentSessionThreads,
|
|
6535
|
+
resolveCodexHome,
|
|
6448
6536
|
resolvePluginParticipants,
|
|
6537
|
+
sessionThreadTitles,
|
|
6449
6538
|
sqliteAvailable,
|
|
6450
6539
|
tableColumns,
|
|
6451
6540
|
tableExists,
|