@essentialai/cogent-bridge
Version:
Cogent Bridge — cross-agent comms for Claude Code, OpenAI Codex and Slack. Codex users: install with `curl -fsSL https://cogent.tools/install.sh | sh`, then start with `cogent-codex` for real-time peer wake.
90 lines • 4.65 kB
TypeScript
/**
* LEARNED AGENT SESSION RECORDS — "the agent told us where it lives".
*
* 🔴 WHY THIS EXISTS. Everything downstream of the wake rails used to DERIVE the
* location of an agent's session transcript:
*
* <config root> / projects / <cwd with non-alphanumerics turned into dashes>
*
* Both halves of that are guesses. The config root was `CLAUDE_CONFIG_DIR` or a
* hardcoded `~/.claude` — one guess, never verified. The cwd half assumed the
* caller passed the exact canonical spelling of the directory. Either guess being
* wrong produced the same dead end: zero candidates, wake refused, and a log line
* that never named the path it looked in.
*
* The agents already publish the truth. Claude Code hands every hook a payload
* containing `cwd`, `session_id` and `transcript_path` — an ABSOLUTE path to the
* live transcript, with no encoding to reverse and no root to guess. This module
* is where that fact is persisted so the resolver can prefer it over inference.
*
* Layering (see docs + session-resolver):
* 1. this record — authoritative, works with ANY relocated config dir
* 2. root discovery — inference, for agents running without our plugin
* 3. fail loud — name every path probed
*
* Storage mirrors the existing per-cwd convention exactly (credential-store.ts,
* wake-inflight.ts): `~/.cogent/<kind>/<sha256(path.resolve(cwd))[..16]>.json`,
* homedir-based on purpose so the bridge and the hook — two processes with
* different environments — always agree on the path.
*/
/** Platforms that keep a per-cwd session transcript we can learn. */
export type AgentPlatform = "cc" | "codex";
export interface AgentSessionRecord {
/** The cwd as the agent reported it (already resolved when written). */
cwd: string;
/** The agent's own session id — what `--resume` / `resume` takes. */
sessionId: string;
/** Absolute path to the transcript. The whole point: no derivation. */
transcriptPath: string;
/** Config root implied by transcriptPath, when it could be recovered. */
root?: string;
platform: AgentPlatform;
/** ISO timestamp of the last write. */
updatedAt: string;
}
/** MUST equal credential-store's hash and check-on-stop.lib.mjs credHashForCwd. */
export declare function hashCwd(cwd: string): string;
/** `~/.cogent/agent-sessions/` — the learned-record directory. */
export declare function agentSessionsDir(): string;
/**
* `~/.cogent/agent-sessions/<hash(cwd)>.<platform>.json`.
*
* Keyed by platform as well as cwd because one directory can host both a Claude
* Code and a Codex agent (that is the normal two-agent Cogent setup) and their
* transcripts live in completely different stores.
*/
export declare function agentSessionPath(cwd: string, platform: AgentPlatform): string;
/**
* Recover the config ROOT from an absolute transcript path.
*
* Claude Code lays transcripts out as `<root>/projects/<encoded-cwd>/<id>.jsonl`,
* so the root is whatever sits above the `projects` segment — recovered by
* structure, never by matching a known prefix, which is what lets a completely
* unknown custom location teach us its root.
*
* Returns null when the shape does not match (a Codex rollout, a temp file, an
* agent that changes its layout) — callers must treat the root as optional.
*/
export declare function rootFromTranscriptPath(transcriptPath: string): string | null;
/** Read the learned record for a cwd, or null. Never throws. */
export declare function readAgentSession(cwd: string, platform: AgentPlatform): Promise<AgentSessionRecord | null>;
/**
* Persist a learned record. Atomic (temp + rename) so a hook and the bridge
* writing concurrently can never leave a half-written file for the other to
* read — the same discipline peer-registry uses for shared state.
* Never throws: learning is an optimisation, never a reason to fail a wake.
*/
export declare function writeAgentSession(rec: Omit<AgentSessionRecord, "updatedAt" | "root"> & {
root?: string;
}): Promise<boolean>;
/**
* Every distinct config root this machine has ever taught us, newest first.
*
* This is what turns one lucky resolution into permanent knowledge: a user with
* `CLAUDE_CONFIG_DIR=/data/claude` teaches us that root once, and afterwards
* EVERY project on the machine resolves against it — including ones opened in a
* shell where the variable was never exported. Bounded work: one readdir plus a
* small number of tiny JSON reads.
*/
export declare function learnedRoots(platform: AgentPlatform): Promise<string[]>;
//# sourceMappingURL=agent-sessions.d.ts.map