UNPKG

@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.

108 lines • 5.42 kB
import { z } from "zod"; import { getBackend, isCloudDeferred } from "../backend/index.js"; import { getConfig } from "../config.js"; import { successResult, errorResult } from "../errors.js"; import { logger } from "../logger.js"; /** * Maximum total character count for the tool response. * Keeps the result safely below Claude Code's MCP result size limit. * Older messages are dropped first when the budget is exceeded. */ const MAX_RESULT_CHARS = 50_000; export function registerGetHistoryTool(server) { server.registerTool("cogent_get_history", { title: "Get Message History", description: "Retrieve the message history for the bridge. " + "Optionally filter by a specific peer ID. " + "Returns the most recent messages that fit within a 50,000-character response budget — " + "older messages are omitted when AI responses are large (code blocks, long explanations). " + "Use peerId to filter to a specific conversation thread for focused context. " + "Returns messages in chronological order, most recent last.", inputSchema: { peerId: z .string() .optional() .describe("Optional peer ID to filter history for"), limit: z .number() .optional() .default(30) .describe("Maximum number of messages to fetch. Defaults to 30. " + "Increase if you need more history context."), includeRelayEchoes: z .boolean() .optional() .default(false) .describe("Include auto-relay echo records that mirror the recipient's reply. " + "Off by default to keep history readable; turn on for debugging the " + "relay pipeline (260511-o3p, requires server 3.1.6+)."), metadataOnly: z.boolean() .optional() .default(false) .describe("Return records as metadata only — keys limited to " + "{id, fromPeerId, toPeerId, timestamp, durationMs, isRelayEcho, success, " + "attachmentCount}. " + "message and response bodies are omitted entirely. " + "Target: ≥90% payload reduction for cheap \"did head move?\" polling. " + "Added in 3.2 (HIST-02); attachmentCount added by Cogent Mail M2.5."), dedupInferredEchoes: z.boolean() .optional() .default(false) .describe("Suppress untagged auto-relay echo records via content-and-direction " + "heuristic: drop M[i] when M[i].message === M[i-1].response AND " + "fromPeerId/toPeerId are swapped AND Δt < 120s. Catches the ~13% of " + "echoes that bypass the isRelayEcho tag (peer-driven re-broadcasts). " + "Requires server 3.2.1+; older servers ignore the param. " + "Added in 3.2.1 (FIX-INFERRED-ECHO, Phase 18 light)."), }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false, }, }, async ({ peerId, limit, includeRelayEchoes, metadataOnly, dedupInferredEchoes }) => { try { // SECURITY: a cloud-configured agent that has not joined a channel yet // runs on the local FileBackend placeholder over the host-global // ~/.cogent/cogent-state.json, which can hold OTHER agents' local // history. It belongs to no channel, so return empty rather than // disclose another channel's content. See backend/isCloudDeferred. if (isCloudDeferred(getConfig().COGENT_ENDPOINT)) { return successResult({ messages: [], count: 0, truncated: false, totalAvailable: 0, notJoined: true, hint: "Not connected to a channel yet — call cogent_join_session (or cogent_register_peer) first. Local history is withheld to prevent cross-channel disclosure.", }); } const backend = getBackend(); const messages = await backend.getHistory(peerId, limit, includeRelayEchoes, metadataOnly, dedupInferredEchoes); // Apply response budget: keep the newest messages that fit within // MAX_RESULT_CHARS to avoid exceeding Claude Code's MCP result size limit. const trimmed = []; let chars = 0; for (let i = messages.length - 1; i >= 0; i--) { const size = JSON.stringify(messages[i]).length; if (chars + size > MAX_RESULT_CHARS) break; trimmed.unshift(messages[i]); chars += size; } const truncated = trimmed.length < messages.length; return successResult({ messages: trimmed, count: trimmed.length, truncated, totalAvailable: messages.length, }); } catch (err) { logger.error("get-history failed", { error: err }); return errorResult(err); } }); } //# sourceMappingURL=get-history.js.map