@essentialai/cogent-bridge 3.1.11 → 3.3.0

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 (55) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/README.md +13 -2
  3. package/dist/backend/file-backend.d.ts +2 -2
  4. package/dist/backend/file-backend.d.ts.map +1 -1
  5. package/dist/backend/file-backend.js +6 -4
  6. package/dist/backend/file-backend.js.map +1 -1
  7. package/dist/backend/http-backend.d.ts +14 -3
  8. package/dist/backend/http-backend.d.ts.map +1 -1
  9. package/dist/backend/http-backend.js +44 -4
  10. package/dist/backend/http-backend.js.map +1 -1
  11. package/dist/backend/relay-version-cache.d.ts +17 -0
  12. package/dist/backend/relay-version-cache.d.ts.map +1 -0
  13. package/dist/backend/relay-version-cache.js +65 -0
  14. package/dist/backend/relay-version-cache.js.map +1 -0
  15. package/dist/backend/storage-backend.d.ts +24 -4
  16. package/dist/backend/storage-backend.d.ts.map +1 -1
  17. package/dist/cli.js +0 -0
  18. package/dist/config.d.ts +3 -0
  19. package/dist/config.d.ts.map +1 -1
  20. package/dist/config.js +3 -0
  21. package/dist/config.js.map +1 -1
  22. package/dist/services/auto-relay.d.ts +36 -1
  23. package/dist/services/auto-relay.d.ts.map +1 -1
  24. package/dist/services/auto-relay.js +58 -2
  25. package/dist/services/auto-relay.js.map +1 -1
  26. package/dist/services/health-check.d.ts +8 -1
  27. package/dist/services/health-check.d.ts.map +1 -1
  28. package/dist/services/health-check.js +1 -1
  29. package/dist/services/health-check.js.map +1 -1
  30. package/dist/services/peer-registry.d.ts +2 -2
  31. package/dist/services/peer-registry.d.ts.map +1 -1
  32. package/dist/services/peer-registry.js +30 -3
  33. package/dist/services/peer-registry.js.map +1 -1
  34. package/dist/startup.d.ts.map +1 -1
  35. package/dist/startup.js +7 -4
  36. package/dist/startup.js.map +1 -1
  37. package/dist/tools/get-history.d.ts.map +1 -1
  38. package/dist/tools/get-history.js +19 -2
  39. package/dist/tools/get-history.js.map +1 -1
  40. package/dist/tools/health-check.d.ts.map +1 -1
  41. package/dist/tools/health-check.js +44 -5
  42. package/dist/tools/health-check.js.map +1 -1
  43. package/dist/tools/list-peers.d.ts.map +1 -1
  44. package/dist/tools/list-peers.js +5 -0
  45. package/dist/tools/list-peers.js.map +1 -1
  46. package/dist/tools/register-peer.d.ts.map +1 -1
  47. package/dist/tools/register-peer.js +12 -3
  48. package/dist/tools/register-peer.js.map +1 -1
  49. package/dist/tools/send-message.d.ts.map +1 -1
  50. package/dist/tools/send-message.js +28 -12
  51. package/dist/tools/send-message.js.map +1 -1
  52. package/dist/types.d.ts +12 -0
  53. package/dist/types.d.ts.map +1 -1
  54. package/package.json +1 -1
  55. package/server.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,88 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.3.0 — Multi-Provider: OpenAI Codex (2026-05-25)
4
+
5
+ ### Added
6
+ - **Codex as first-class platform**: `platform: "codex"` in shared types, peer
7
+ registration, and message origin tracking
8
+ - **`COGENT_PLATFORM` env var**: clients identify their platform (default `"cc"`;
9
+ Codex sets `codex`). Replaces the hardcoded `platform: "cc"` in HttpBackend
10
+ - **Platform-segmented admin stats**: live agents-by-platform counts + cumulative
11
+ historical totals (persisted to `platform-stats.json`)
12
+ - **Admin UI badges**: Platform and Mode columns in peer table (color-coded);
13
+ platform breakdown in session list; agent-count cards on dashboard
14
+ - **Codex install instructions**: landing page, FAQ, README, docs/installation.md
15
+ - **Supported Platforms section** on landing page (Claude Code, Codex, Slack)
16
+ - **FAQ entries**: Codex setup, cross-platform messaging, model config, auto-relay status
17
+
18
+ ### Changed
19
+ - All user-facing copy updated from "Claude Code" to platform-inclusive language
20
+ - `@essentialai/cogent` bumped to 3.1.0 (additive enum extension)
21
+ - Server package bumped from 3.2.1 to 3.3.0
22
+
23
+ ### Not included (v3.4)
24
+ - Codex auto-relay adapter (`codex exec resume` subprocess dispatch)
25
+
26
+ ## [3.2.2] - 2026-05-19
27
+
28
+ Surfaced by ~4-day clone-detector channel observer watch (tick 89 mass re-register event at 2026-05-18T00:30:26Z). Two client-side polish fixes plus a long-deferred marketplace + plugin version sync. No emergency — bridge transport is otherwise operationally fine.
29
+
30
+ ### Fixed
31
+ - **FIX-LABEL-PRESERVE: preserve operator-supplied label + mode on auto-reconnect.** `AutoRelayService` now captures `label` and `mode` at `setLocalPeer()` time and surfaces both via `getLocalPeer()`. `triggerReRegistration()` in `src/startup.ts` passes the captured `label` (not `peerId`) and `mode` (not implicit `"agent"`) to `backend.registerPeer()` on auto-reconnect. Pre-3.2.2, the re-register call substituted `peerId` for `label` (silently normalizing `"Cogent_Master"` -> `"cogent-master"` after a WS-cycle mass-reregister) and dropped `mode` (silently flipping observer peers back to agent mode). See `src/services/auto-relay.ts`, `src/tools/register-peer.ts`, `src/startup.ts`.
32
+ - **FIX-WSHEALTH-RECONNECTING: new transient "reconnecting" state on health-check.** `transport.wsHealth` now has a fourth value, `"reconnecting"`, returned when `wsConnected=false` BUT the last frame was received within `COGENT_WS_STALE_MS` (default 90s). Pre-3.2.2 reported `"disconnected"` during the 1-4s window each ~5-20min keepalive cycle takes — alarming on a healthy idle channel. Only sustained socket-down beyond the threshold (or null last-frame) is now reported as `"disconnected"`. See `src/tools/health-check.ts`.
33
+
34
+ ### Changed
35
+ - **`AutoRelayService.setLocalPeer()` signature** gained a 5th optional `label?: string` parameter (defaults to `peerId` for back-compat). `getLocalPeer()` return type widened to include `label: string` and `mode: "observer" | "agent"` so re-registration can replay the original registration payload exactly.
36
+
37
+ ### Marketplace + manifests
38
+ - **`server.json` bumped 3.1.11 -> 3.2.2.** Top-level `version` + `packages[].version`. Was 4 minor-releases behind the npm package after Phase 17 / Phase 18 light shipped without a marketplace sync — operators installing via the MCP registry could not consume `metadataOnly` history or `dedupInferredEchoes` because the registry advertised pre-feature versions.
39
+ - **`plugin/.claude-plugin/plugin.json` bumped 3.1.8 -> 3.2.2.** Same story for the Claude Code plugin marketplace at `eaisdevelopment/cogent` — was 6 minor-releases behind. Plugin sync will land in the marketplace repo as part of this release deploy.
40
+
41
+ ### Internal
42
+ - 5 new tests under `src/services/auto-relay.test.ts` covering label preservation, peerId-fallback for pre-3.2.2 callers, observer-mode preservation, and `stop()` clearing `localLabel`.
43
+ - 2 new tests under `src/tools/health-check.test.ts` covering the new `"reconnecting"` state (recent frame, socket down) and the boundary case where an old frame plus socket-down still resolves to `"disconnected"`.
44
+ - Existing `src/startup.test.ts triggerReRegistration` test updated to assert the new 6-arg `registerPeer` call (peerId, sessionId, cwd, label, clientVersion, mode); added one new test for observer-mode preservation through the re-register path.
45
+
46
+ Observability backstory: `temp/watch/cogent-watch-state.json` ticks 70-94 (4-day continuous watch as cogent-master; mass-reregister event at tick 89 surfaced both the label-strip regression and the wsHealth UX issue).
47
+
48
+ ## [3.2.1] - 2026-05-17
49
+
50
+ Surfaced by 51-tick clone-detector channel watch (20 confirmed sender-side 180s timeouts, 9 confirmed untagged-echo phantoms across the session's 899-message history). Neither is a relay drop — both are receipt-side UX bugs that misled the LLM reading the bridge output.
51
+
52
+ ### Fixed
53
+ - **FIX-TIMEOUT-UX: cloud-mode send-message timeout result shape.** Both timeout paths (`DELIVERY_NO_ACK` after 15s ack-wait, `RESPONSE_TIMEOUT` after `COGENT_TIMEOUT_MS` response-wait) now return `{success: false, timedOut: true, error: "DELIVERY_NO_ACK" | "RESPONSE_TIMEOUT", message: <stub-text>, response: null, durationMs}` instead of the prior `{success: true, response: <stub-text>}`. The LLM no longer mistakes the bridge's "Delivered to X but no synchronous response within 180s" stub for the recipient's actual reply. The history record's `response` field is also written as `null` on timeout (was the stub text), so later inspection cleanly distinguishes "no reply received" from "real reply received." See `src/tools/send-message.ts`.
54
+ - **FIX-INFERRED-ECHO: server-side dedup of untagged auto-relay echoes (Phase 18 light).** New optional GET param on `/api/sessions/:id/messages` — `dedupInferredEchoes` (default `false`). When `true`, suppresses M[i] when `M[i].message === M[i-1].response`, `M[i].fromPeerId === M[i-1].toPeerId`, `M[i].toPeerId === M[i-1].fromPeerId`, AND `Δt < 120s`. Catches the ~13% of echo records that bypass the `isRelayEcho` tag (peer-driven `cogent_send_message` re-broadcasts after autoRelay's execClaude returns). Opt-in to avoid surprise behavior change. Plumbed through `cogent_get_history` (new `dedupInferredEchoes: boolean` param) → `StorageBackend.getHistory(..., dedupInferredEchoes?)` → `HttpBackend` (sends `?dedupInferredEchoes=true` to server). `FileBackend` ignores the flag (local mode doesn't synthesize untagged echoes). See `server/src/routes/messages.ts`, `src/tools/get-history.ts`, `src/backend/*.ts`.
55
+
56
+ ### Changed
57
+ - **`StorageBackend.updateMessageResponse(messageId, response, durationMs)`** signature: `response: string` → `response: string | null`. Server PATCH route mirrors with `z.string().nullable()`. Lets cloud clients explicitly mark timed-out sends with `null` response (was previously a misleading stub string).
58
+
59
+ ### Internal
60
+ - 2 new tests under `src/tools/send-message.test.ts` `describe("cloud-mode timeout result shape (v3.2.1)")` — assert `success:false`, `timedOut:true`, `error: "DELIVERY_NO_ACK" | "RESPONSE_TIMEOUT"`, `response: null`, and that explanatory text lives in `message` not `response`. Spies on `isCloudMode` + `autoRelay.waitForDeliveryAck` / `waitForResponse` to drive the cloud path without booting `HttpBackend`.
61
+ - 5 new tests under `server/src/__tests__/routes/messages.test.ts` `describe("dedupInferredEchoes (FIX-INFERRED-ECHO, 3.2.1)")` — happy-path suppression, default-off backward compat, content-mismatch no-op, direction-mismatch no-op, string `"true"` preprocess coercion.
62
+
63
+ Observability backstory: `.planning/notes/` (`temp/watch/cogent-watch-state.json` raw evidence).
64
+
65
+ ## [3.2.0] - 2026-05-12
66
+
67
+ ### Added
68
+ - **Observer-mode peer registration (OBS-01).** `cogent_register_peer` accepts optional `mode: "observer" | "agent"` (default `"agent"`). Observer peers register normally and remain visible/targetable but skip the auto-relay subprocess. See `src/tools/register-peer.ts`, `src/services/auto-relay.ts`.
69
+ - **Observer mode surfaced via list-peers (OBS-02).** `cogent_list_peers` passes through the `mode` field via the existing `PeerInfo` spread. Operators can identify observer peers in the topology before sending. See `src/tools/list-peers.ts`, `src/types.ts`.
70
+ - **Auto-relay observer short-circuit (OBS-03).** `AutoRelayService.handleIncoming` short-circuits AFTER delivery-ack and waiter resolution, BEFORE `_processMessage` — observers ack frames and resolve their own outbound waiters, but never spawn `execClaude`. Extracted as `_shouldSkipAutoRelay()` for Phase 20 presence/DND reuse. See `src/services/auto-relay.ts`.
71
+ - **Metadata-only history schema (HIST-01).** `cogent_get_history` accepts optional `metadataOnly: boolean` (default `false`). Plumbs through `StorageBackend.getHistory(..., metadataOnly?)` to both `FileBackend` (client-side projection) and `HttpBackend` (server-side projection via `?metadataOnly=true` query param). See `src/tools/get-history.ts`, `src/backend/*.ts`.
72
+ - **Metadata-only 7-key projection (HIST-02).** When `metadataOnly: true`, each record is exactly `{id, fromPeerId, toPeerId, timestamp, durationMs, isRelayEcho, success}` — `message` and `response` keys are physically absent (object-literal projection, not delete-on-clone). Measured 94.4% payload reduction for a 30-record window (5.6% ratio vs ≤10% target). See `src/services/peer-registry.ts`, `server/src/routes/messages.ts`.
73
+ - **`transport.relayVersion` on health-check (VER-02).** Cloud mode populates `transport.relayVersion` from a lazy `GET /api/health` fetch behind a 60s module-scoped TTL cache (`src/backend/relay-version-cache.ts`). Relay upgrades become client-visible within 60s without a client restart. Returns `null` on fetch failure (rest of payload intact); key omitted entirely in local mode. See `src/tools/health-check.ts`, `src/backend/http-backend.ts`.
74
+
75
+ ### Changed
76
+ - **Hard rename: `serverVersion` → `mcpServerVersion` (VER-01).** Top-level field on `cogent_health_check` renamed without a backward-compat alias. This is the local cogent-bridge npm package version (NOT the upstream relay; the relay's version is now in `transport.relayVersion`). **Breaking by omission:** mixed-version 3.1.x clients reading the old name will see `undefined` — intentional per the coordinated 3.2.0 bump. See `src/services/health-check.ts`, `src/backend/http-backend.ts`, `src/tools/health-check.ts`.
77
+
78
+ ### Internal
79
+ - New module `src/backend/relay-version-cache.ts` with injectable `nowFn` clock seam and `__resetCacheForTest()` helper for deterministic TTL tests. Module-scoped `TTL_MS = 60_000` constant.
80
+ - 10 new tests under `src/services/auto-relay.test.ts` `describe("observer mode (OBS-03)")` and 6 new tests under `src/tools/health-check.test.ts` `describe("version field hygiene (VER-01 / VER-02)")`.
81
+ - 4 new tests under `src/tools/get-history.test.ts` `describe("metadataOnly (HIST-02)")` including a backend-layer size-ratio assertion (`≤0.10`).
82
+ - 5 new tests under `src/backend/relay-version-cache.test.ts` covering cold fetch, warm fetch, TTL expiry, fetch-error no-cache, and malformed-payload no-cache.
83
+
84
+ Planning: `.planning/phases/17-observer-mode-and-history-hygiene/`
85
+
3
86
  ## [3.1.5] - 2026-05-05
4
87
 
5
88
  ### Fixed
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![license](https://img.shields.io/npm/l/@essentialai/cogent-bridge)](https://www.npmjs.com/package/@essentialai/cogent-bridge)
5
5
  [![downloads](https://img.shields.io/npm/dm/@essentialai/cogent-bridge)](https://www.npmjs.com/package/@essentialai/cogent-bridge)
6
6
 
7
- MCP server for inter-Claude-Code session communication. Two Claude Code instances can exchange messages while staying fully isolated in their own repositories -- locally via shared files or across machines via [cogent.tools](https://cogent.tools) cloud relay.
7
+ MCP server for inter-agent communication between Claude Code, OpenAI Codex, and Slack. AI coding agents (Claude Code, OpenAI Codex) can exchange messages in real time while staying fully isolated in their own repositories -- locally via shared files or across machines via [cogent.tools](https://cogent.tools) cloud relay.
8
8
 
9
9
  ## Quick Start
10
10
 
@@ -41,11 +41,22 @@ claude mcp add --transport stdio cogent -- npx -y @essentialai/cogent-bridge
41
41
 
42
42
  Restart Claude Code in both repos. The bridge tools are now available.
43
43
 
44
+ ### OpenAI Codex
45
+
46
+ ```bash
47
+ codex mcp add cogent \
48
+ --env COGENT_ENDPOINT=https://cogent.tools \
49
+ --env COGENT_PLATFORM=codex \
50
+ -- npx -y @essentialai/cogent-bridge
51
+ ```
52
+
53
+ Set `model = "gpt-5.4"` in `~/.codex/config.toml` if using a ChatGPT account.
54
+
44
55
  > See [docs/installation.md](docs/installation.md) for all installation options, configuration, and troubleshooting.
45
56
 
46
57
  ## What It Does
47
58
 
48
- Two Claude Code instances -- one working on a backend repo, another on a frontend repo -- need to negotiate testing scenarios and debug collaboratively in real-time without mixing their accumulated project context.
59
+ Two AI agents Claude Code on backend, Codex on frontend, or any combination — need to negotiate testing scenarios and debug collaboratively in real-time without mixing their accumulated project context.
49
60
 
50
61
  ```
51
62
  Cogent_Backend Cogent_Frontend
@@ -8,13 +8,13 @@ import { StorageBackend } from "./storage-backend.js";
8
8
  * cc-cli.ts, and health-check.ts. No added logic, logging, or transformation.
9
9
  */
10
10
  export declare class FileBackend implements StorageBackend {
11
- registerPeer(peerId: string, sessionId: string, cwd: string, label: string, clientVersion?: string): Promise<PeerInfo>;
11
+ registerPeer(peerId: string, sessionId: string, cwd: string, label: string, clientVersion?: string, mode?: "observer" | "agent"): Promise<PeerInfo>;
12
12
  deregisterPeer(peerId: string): Promise<boolean>;
13
13
  getPeer(peerId: string): Promise<PeerInfo | undefined>;
14
14
  listPeers(): Promise<PeerInfo[]>;
15
15
  updateLastSeen(peerId: string): Promise<void>;
16
16
  recordMessage(record: Omit<MessageRecord, "id" | "timestamp">): Promise<MessageRecord>;
17
- getHistory(peerId?: string, limit?: number, includeRelayEchoes?: boolean): Promise<MessageRecord[]>;
17
+ getHistory(peerId?: string, limit?: number, includeRelayEchoes?: boolean, metadataOnly?: boolean, _dedupInferredEchoes?: boolean): Promise<MessageRecord[]>;
18
18
  validateSession(sessionId: string, cwd: string): Promise<boolean>;
19
19
  execClaude(sessionId: string, message: string, cwd: string, timeoutMs?: number): Promise<CliExecResult>;
20
20
  checkHealth(): Promise<HealthCheckResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"file-backend.d.ts","sourceRoot":"","sources":["../../src/backend/file-backend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAKtD;;;;;GAKG;AACH,qBAAa,WAAY,YAAW,cAAc;IAGhD,YAAY,CACV,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,QAAQ,CAAC;IAIpB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIhD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAItD,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAIhC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM7C,aAAa,CACX,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,WAAW,CAAC,GAC9C,OAAO,CAAC,aAAa,CAAC;IAIzB,UAAU,CACR,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,EACd,kBAAkB,CAAC,EAAE,OAAO,GAC3B,OAAO,CAAC,aAAa,EAAE,CAAC;IAM3B,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIjE,UAAU,CACR,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,CAAC;IAMzB,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC;CAG1C"}
1
+ {"version":3,"file":"file-backend.d.ts","sourceRoot":"","sources":["../../src/backend/file-backend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAKtD;;;;;GAKG;AACH,qBAAa,WAAY,YAAW,cAAc;IAGhD,YAAY,CACV,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,aAAa,CAAC,EAAE,MAAM,EACtB,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,GAC1B,OAAO,CAAC,QAAQ,CAAC;IAWpB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIhD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAItD,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAIhC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM7C,aAAa,CACX,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,WAAW,CAAC,GAC9C,OAAO,CAAC,aAAa,CAAC;IAIzB,UAAU,CACR,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,EACd,kBAAkB,CAAC,EAAE,OAAO,EAC5B,YAAY,CAAC,EAAE,OAAO,EACtB,oBAAoB,CAAC,EAAE,OAAO,GAC7B,OAAO,CAAC,aAAa,EAAE,CAAC;IAQ3B,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIjE,UAAU,CACR,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,CAAC;IAMzB,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC;CAG1C"}
@@ -9,8 +9,8 @@ import * as health from "../services/health-check.js";
9
9
  */
10
10
  export class FileBackend {
11
11
  // --- Peer management ---
12
- registerPeer(peerId, sessionId, cwd, label, clientVersion) {
13
- return registry.registerPeer(peerId, sessionId, cwd, label, clientVersion);
12
+ registerPeer(peerId, sessionId, cwd, label, clientVersion, mode) {
13
+ return registry.registerPeer(peerId, sessionId, cwd, label, clientVersion, mode);
14
14
  }
15
15
  deregisterPeer(peerId) {
16
16
  return registry.deregisterPeer(peerId);
@@ -28,8 +28,10 @@ export class FileBackend {
28
28
  recordMessage(record) {
29
29
  return registry.recordMessage(record);
30
30
  }
31
- getHistory(peerId, limit, includeRelayEchoes) {
32
- return registry.getHistory(peerId, limit, includeRelayEchoes);
31
+ getHistory(peerId, limit, includeRelayEchoes, metadataOnly, _dedupInferredEchoes) {
32
+ // Local FileBackend doesn't synthesize untagged echoes (no autoRelay
33
+ // re-broadcast pattern), so dedupInferredEchoes is a no-op here.
34
+ return registry.getHistory(peerId, limit, includeRelayEchoes, metadataOnly);
33
35
  }
34
36
  // --- Message relay ---
35
37
  validateSession(sessionId, cwd) {
@@ -1 +1 @@
1
- {"version":3,"file":"file-backend.js","sourceRoot":"","sources":["../../src/backend/file-backend.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,QAAQ,MAAM,8BAA8B,CAAC;AACzD,OAAO,KAAK,GAAG,MAAM,uBAAuB,CAAC;AAC7C,OAAO,KAAK,MAAM,MAAM,6BAA6B,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,OAAO,WAAW;IACtB,0BAA0B;IAE1B,YAAY,CACV,MAAc,EACd,SAAiB,EACjB,GAAW,EACX,KAAa,EACb,aAAsB;QAEtB,OAAO,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;IAC7E,CAAC;IAED,cAAc,CAAC,MAAc;QAC3B,OAAO,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,CAAC,MAAc;QACpB,OAAO,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,SAAS;QACP,OAAO,QAAQ,CAAC,SAAS,EAAE,CAAC;IAC9B,CAAC;IAED,cAAc,CAAC,MAAc;QAC3B,OAAO,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAED,wBAAwB;IAExB,aAAa,CACX,MAA+C;QAE/C,OAAO,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IAED,UAAU,CACR,MAAe,EACf,KAAc,EACd,kBAA4B;QAE5B,OAAO,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,kBAAkB,CAAC,CAAC;IAChE,CAAC;IAED,wBAAwB;IAExB,eAAe,CAAC,SAAiB,EAAE,GAAW;QAC5C,OAAO,GAAG,CAAC,eAAe,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED,UAAU,CACR,SAAiB,EACjB,OAAe,EACf,GAAW,EACX,SAAkB;QAElB,OAAO,GAAG,CAAC,UAAU,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;IAC5D,CAAC;IAED,iBAAiB;IAEjB,WAAW;QACT,OAAO,MAAM,CAAC,WAAW,EAAE,CAAC;IAC9B,CAAC;CACF"}
1
+ {"version":3,"file":"file-backend.js","sourceRoot":"","sources":["../../src/backend/file-backend.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,QAAQ,MAAM,8BAA8B,CAAC;AACzD,OAAO,KAAK,GAAG,MAAM,uBAAuB,CAAC;AAC7C,OAAO,KAAK,MAAM,MAAM,6BAA6B,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,OAAO,WAAW;IACtB,0BAA0B;IAE1B,YAAY,CACV,MAAc,EACd,SAAiB,EACjB,GAAW,EACX,KAAa,EACb,aAAsB,EACtB,IAA2B;QAE3B,OAAO,QAAQ,CAAC,YAAY,CAC1B,MAAM,EACN,SAAS,EACT,GAAG,EACH,KAAK,EACL,aAAa,EACb,IAAI,CACL,CAAC;IACJ,CAAC;IAED,cAAc,CAAC,MAAc;QAC3B,OAAO,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,CAAC,MAAc;QACpB,OAAO,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,SAAS;QACP,OAAO,QAAQ,CAAC,SAAS,EAAE,CAAC;IAC9B,CAAC;IAED,cAAc,CAAC,MAAc;QAC3B,OAAO,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAED,wBAAwB;IAExB,aAAa,CACX,MAA+C;QAE/C,OAAO,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IAED,UAAU,CACR,MAAe,EACf,KAAc,EACd,kBAA4B,EAC5B,YAAsB,EACtB,oBAA8B;QAE9B,qEAAqE;QACrE,iEAAiE;QACjE,OAAO,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,kBAAkB,EAAE,YAAY,CAAC,CAAC;IAC9E,CAAC;IAED,wBAAwB;IAExB,eAAe,CAAC,SAAiB,EAAE,GAAW;QAC5C,OAAO,GAAG,CAAC,eAAe,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED,UAAU,CACR,SAAiB,EACjB,OAAe,EACf,GAAW,EACX,SAAkB;QAElB,OAAO,GAAG,CAAC,UAAU,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;IAC5D,CAAC;IAED,iBAAiB;IAEjB,WAAW;QACT,OAAO,MAAM,CAAC,WAAW,EAAE,CAAC;IAC9B,CAAC;CACF"}
@@ -26,7 +26,7 @@ export declare class HttpBackend implements StorageBackend {
26
26
  * The sessionId parameter from StorageBackend is the local CC sessionId;
27
27
  * in cloud mode we ignore it and use this.sessionId (the cloud session).
28
28
  */
29
- registerPeer(peerId: string, _sessionId: string, cwd: string, label: string, clientVersion?: string): Promise<PeerInfo>;
29
+ registerPeer(peerId: string, _sessionId: string, cwd: string, label: string, clientVersion?: string, mode?: "observer" | "agent"): Promise<PeerInfo>;
30
30
  /**
31
31
  * Deregister a peer from the cloud session.
32
32
  * DELETE /api/sessions/:sessionId/peers/:peerId
@@ -65,7 +65,7 @@ export declare class HttpBackend implements StorageBackend {
65
65
  *
66
66
  * Supports optional peerId filter and limit (default 300).
67
67
  */
68
- getHistory(peerId?: string, limit?: number, includeRelayEchoes?: boolean): Promise<MessageRecord[]>;
68
+ getHistory(peerId?: string, limit?: number, includeRelayEchoes?: boolean, metadataOnly?: boolean, dedupInferredEchoes?: boolean): Promise<MessageRecord[]>;
69
69
  /**
70
70
  * Update an existing message record's response field on the server.
71
71
  * PATCH /api/sessions/:sessionId/messages/:messageId
@@ -73,7 +73,7 @@ export declare class HttpBackend implements StorageBackend {
73
73
  * Called by send-message after receiving the async cloud response,
74
74
  * so that get-history shows the actual response (not null).
75
75
  */
76
- updateMessageResponse(messageId: string, response: string, durationMs: number): Promise<void>;
76
+ updateMessageResponse(messageId: string, response: string | null, durationMs: number): Promise<void>;
77
77
  /**
78
78
  * Validate a session.
79
79
  * In cloud mode, the server validates session authenticity on every
@@ -97,5 +97,16 @@ export declare class HttpBackend implements StorageBackend {
97
97
  * format with cloud-mode-specific diagnostics.
98
98
  */
99
99
  checkHealth(): Promise<HealthCheckResult>;
100
+ /**
101
+ * Lazy lookup of the upstream relay's `version` field via GET /api/health,
102
+ * memoized for 60s. Returns null on fetch failure or malformed payload.
103
+ * Never throws — the caller (health-check tool) treats null as "unknown"
104
+ * and keeps the rest of the response intact.
105
+ *
106
+ * Delegates to the module-scoped cache in `relay-version-cache.ts` so the
107
+ * TTL is shared across all callers and tests can reset state via
108
+ * `__resetCacheForTest()`. VER-02 (3.2).
109
+ */
110
+ getRelayVersion(): Promise<string | null>;
100
111
  }
101
112
  //# sourceMappingURL=http-backend.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"http-backend.d.ts","sourceRoot":"","sources":["../../src/backend/http-backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAgB1D;;;;;;;;;;;;GAYG;AACH,qBAAa,WAAY,YAAW,cAAc;IAE9C,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM;IAGpC;;;;;;OAMG;IACG,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,QAAQ,CAAC;IAmBpB;;;;;OAKG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAatD;;;;OAIG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAK5D;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAMtC;;;OAGG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKnD;;;;;;;OAOG;IACG,aAAa,CACjB,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,WAAW,CAAC,GAC9C,OAAO,CAAC,aAAa,CAAC;IA2BzB;;;;;OAKG;IACG,UAAU,CACd,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,EACd,kBAAkB,CAAC,EAAE,OAAO,GAC3B,OAAO,CAAC,aAAa,EAAE,CAAC;IAsB3B;;;;;;OAMG;IACG,qBAAqB,CACzB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;IAOhB;;;;OAIG;IACG,eAAe,CACnB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,CAAC;IAInB;;;;;;;OAOG;IACG,UAAU,CACd,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,aAAa,CAAC;IAQzB;;;;;;OAMG;IACG,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC;CAoChD"}
1
+ {"version":3,"file":"http-backend.d.ts","sourceRoot":"","sources":["../../src/backend/http-backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAkB1D;;;;;;;;;;;;GAYG;AACH,qBAAa,WAAY,YAAW,cAAc;IAE9C,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM;IAGpC;;;;;;OAMG;IACG,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,aAAa,CAAC,EAAE,MAAM,EACtB,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,GAC1B,OAAO,CAAC,QAAQ,CAAC;IA2BpB;;;;;OAKG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAatD;;;;OAIG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAK5D;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAMtC;;;OAGG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKnD;;;;;;;OAOG;IACG,aAAa,CACjB,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,WAAW,CAAC,GAC9C,OAAO,CAAC,aAAa,CAAC;IA2BzB;;;;;OAKG;IACG,UAAU,CACd,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,EACd,kBAAkB,CAAC,EAAE,OAAO,EAC5B,YAAY,CAAC,EAAE,OAAO,EACtB,mBAAmB,CAAC,EAAE,OAAO,GAC5B,OAAO,CAAC,aAAa,EAAE,CAAC;IAmC3B;;;;;;OAMG;IACG,qBAAqB,CACzB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;IAOhB;;;;OAIG;IACG,eAAe,CACnB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,CAAC;IAInB;;;;;;;OAOG;IACG,UAAU,CACd,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,aAAa,CAAC;IAQzB;;;;;;OAMG;IACG,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAyC/C;;;;;;;;;OASG;IACG,eAAe,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAGhD"}
@@ -1,4 +1,6 @@
1
1
  import { SERVER_VERSION } from "../constants.js";
2
+ import { getConfig } from "../config.js";
3
+ import { getRelayVersion } from "./relay-version-cache.js";
2
4
  /**
3
5
  * API path patterns matching @essentialai/cogent PATHS constants.
4
6
  * Defined locally because cogent is not a dependency of the main package.
@@ -38,7 +40,7 @@ export class HttpBackend {
38
40
  * The sessionId parameter from StorageBackend is the local CC sessionId;
39
41
  * in cloud mode we ignore it and use this.sessionId (the cloud session).
40
42
  */
41
- async registerPeer(peerId, _sessionId, cwd, label, clientVersion) {
43
+ async registerPeer(peerId, _sessionId, cwd, label, clientVersion, mode) {
42
44
  const path = PATHS.peers.replace(":sessionId", this.sessionId);
43
45
  // Build body conditionally: omit clientVersion entirely for older clients
44
46
  // / undefined inputs so the wire payload stays clean (no JSON null) and
@@ -47,13 +49,21 @@ export class HttpBackend {
47
49
  peerId,
48
50
  cwd,
49
51
  label,
50
- platform: "cc",
52
+ platform: getConfig().COGENT_PLATFORM,
51
53
  type: "agent",
52
54
  transport: "ws",
53
55
  };
54
56
  if (clientVersion !== undefined) {
55
57
  body.clientVersion = clientVersion;
56
58
  }
59
+ // Same omit-when-undefined pattern for the 3.2.0 mode field (Phase 17
60
+ // OBS-01). Older servers that don't know the field will ignore it (it
61
+ // arrives via the .strict() body schema, so a pre-3.2.0 server WOULD
62
+ // reject the request — guarded by the optional field on the server
63
+ // mirror being shipped in lockstep with the client).
64
+ if (mode !== undefined) {
65
+ body.mode = mode;
66
+ }
57
67
  return this.http.post(path, body);
58
68
  }
59
69
  /**
@@ -136,7 +146,7 @@ export class HttpBackend {
136
146
  *
137
147
  * Supports optional peerId filter and limit (default 300).
138
148
  */
139
- async getHistory(peerId, limit, includeRelayEchoes) {
149
+ async getHistory(peerId, limit, includeRelayEchoes, metadataOnly, dedupInferredEchoes) {
140
150
  const path = PATHS.messages.replace(":sessionId", this.sessionId);
141
151
  const query = {};
142
152
  if (peerId) {
@@ -150,6 +160,19 @@ export class HttpBackend {
150
160
  if (includeRelayEchoes) {
151
161
  query.includeRelayEchoes = "true";
152
162
  }
163
+ // HIST-02 (3.2): server projects the 7-key shape when this is set.
164
+ // Same omit-when-falsy pattern — pre-3.2 servers ignore the unknown
165
+ // key and return full records, so client-side parsers must not assume
166
+ // the projection is enforced.
167
+ if (metadataOnly) {
168
+ query.metadataOnly = "true";
169
+ }
170
+ // FIX-INFERRED-ECHO (3.2.1): server filters untagged auto-relay echoes
171
+ // via content-and-direction heuristic when this is set. Older servers
172
+ // (pre-3.2.1) ignore the unknown key.
173
+ if (dedupInferredEchoes) {
174
+ query.dedupInferredEchoes = "true";
175
+ }
153
176
  const result = await this.http.get(path, query);
154
177
  return result.messages;
155
178
  }
@@ -200,7 +223,11 @@ export class HttpBackend {
200
223
  const resp = await this.http.get(PATHS.health);
201
224
  return {
202
225
  healthy: resp.status === "ok",
203
- serverVersion: SERVER_VERSION,
226
+ // VER-01 (3.2): the SERVER_VERSION constant still identifies the local
227
+ // cogent-bridge npm package — this property name makes its role
228
+ // unambiguous now that transport.relayVersion carries the upstream
229
+ // relay's version. Hard rename, no backward-compat alias.
230
+ mcpServerVersion: SERVER_VERSION,
204
231
  statePath: "cloud:" + this.sessionId,
205
232
  claudePath: "N/A (cloud mode)",
206
233
  checks: {
@@ -225,5 +252,18 @@ export class HttpBackend {
225
252
  serverUptime: resp.uptime,
226
253
  };
227
254
  }
255
+ /**
256
+ * Lazy lookup of the upstream relay's `version` field via GET /api/health,
257
+ * memoized for 60s. Returns null on fetch failure or malformed payload.
258
+ * Never throws — the caller (health-check tool) treats null as "unknown"
259
+ * and keeps the rest of the response intact.
260
+ *
261
+ * Delegates to the module-scoped cache in `relay-version-cache.ts` so the
262
+ * TTL is shared across all callers and tests can reset state via
263
+ * `__resetCacheForTest()`. VER-02 (3.2).
264
+ */
265
+ async getRelayVersion() {
266
+ return getRelayVersion(this.http);
267
+ }
228
268
  }
229
269
  //# sourceMappingURL=http-backend.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"http-backend.js","sourceRoot":"","sources":["../../src/backend/http-backend.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http-backend.js","sourceRoot":"","sources":["../../src/backend/http-backend.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { HttpClient } from "../cloud/http-client.js";
2
+ /**
3
+ * Get the relay's version, using a 60s TTL cache. Returns null on fetch
4
+ * failure or malformed response. Does not throw.
5
+ *
6
+ * @param http Authenticated HttpClient (typically `HttpBackend.http`).
7
+ * @param nowFn Override for `Date.now()` (test seam). Defaults to `Date.now`.
8
+ */
9
+ export declare function getRelayVersion(http: HttpClient, nowFn?: () => number): Promise<string | null>;
10
+ /**
11
+ * Test-only helper to clear the module-scoped cache. Call from beforeEach
12
+ * in test suites that exercise the cache.
13
+ *
14
+ * @internal
15
+ */
16
+ export declare function __resetCacheForTest(): void;
17
+ //# sourceMappingURL=relay-version-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relay-version-cache.d.ts","sourceRoot":"","sources":["../../src/backend/relay-version-cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAmC1D;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,UAAU,EAChB,KAAK,GAAE,MAAM,MAAiB,GAC7B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAyBxB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C"}
@@ -0,0 +1,65 @@
1
+ import { logger } from "../logger.js";
2
+ /**
3
+ * Module-scoped cache for the relay's `version` field (from GET /api/health).
4
+ *
5
+ * Rationale (VER-02, plan 17-03):
6
+ * - Operators need to see "is my relay current?" at a glance via cogent_health_check.
7
+ * - A hot-path HTTP call on every health_check is too expensive.
8
+ * - A 60s TTL bounds staleness: relay upgrades become visible to the client
9
+ * within 60s without a client restart, but the fetch is amortized across
10
+ * N calls within the window.
11
+ *
12
+ * Failure semantics:
13
+ * - On HTTP error: return null, DO NOT cache. Next call retries.
14
+ * - On malformed payload (no `version` string): return null, DO NOT cache.
15
+ * - Caller (health-check tool) treats null as "unknown" — does NOT propagate
16
+ * the fetch failure upward; the rest of the health_check response is intact.
17
+ *
18
+ * Test seam:
19
+ * - `nowFn` parameter (default `Date.now`) lets tests advance the clock
20
+ * deterministically without coupling to vitest fake-timer state shared
21
+ * across other suites.
22
+ * - `__resetCacheForTest()` clears module state between tests.
23
+ */
24
+ const TTL_MS = 60_000;
25
+ let cached = null;
26
+ /**
27
+ * Get the relay's version, using a 60s TTL cache. Returns null on fetch
28
+ * failure or malformed response. Does not throw.
29
+ *
30
+ * @param http Authenticated HttpClient (typically `HttpBackend.http`).
31
+ * @param nowFn Override for `Date.now()` (test seam). Defaults to `Date.now`.
32
+ */
33
+ export async function getRelayVersion(http, nowFn = Date.now) {
34
+ const now = nowFn();
35
+ if (cached !== null && now - cached.fetchedAt < TTL_MS) {
36
+ return cached.version;
37
+ }
38
+ try {
39
+ const resp = await http.get("/api/health");
40
+ const version = resp?.version;
41
+ if (typeof version !== "string" || version.length === 0) {
42
+ // Malformed response shape — treat as fetch failure. Do not cache.
43
+ logger.debug(`relay-version-cache: /api/health response missing string 'version' field`);
44
+ return null;
45
+ }
46
+ cached = { version, fetchedAt: now };
47
+ return version;
48
+ }
49
+ catch (err) {
50
+ const msg = err instanceof Error ? err.message : String(err);
51
+ logger.debug(`relay-version-cache: /api/health fetch failed: ${msg}`);
52
+ // Do NOT update `cached` — next call retries.
53
+ return null;
54
+ }
55
+ }
56
+ /**
57
+ * Test-only helper to clear the module-scoped cache. Call from beforeEach
58
+ * in test suites that exercise the cache.
59
+ *
60
+ * @internal
61
+ */
62
+ export function __resetCacheForTest() {
63
+ cached = null;
64
+ }
65
+ //# sourceMappingURL=relay-version-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relay-version-cache.js","sourceRoot":"","sources":["../../src/backend/relay-version-cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,MAAM,GAAG,MAAM,CAAC;AAOtB,IAAI,MAAM,GAAsB,IAAI,CAAC;AAErC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAgB,EAChB,QAAsB,IAAI,CAAC,GAAG;IAE9B,MAAM,GAAG,GAAG,KAAK,EAAE,CAAC;IAEpB,IAAI,MAAM,KAAK,IAAI,IAAI,GAAG,GAAG,MAAM,CAAC,SAAS,GAAG,MAAM,EAAE,CAAC;QACvD,OAAO,MAAM,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAwB,aAAa,CAAC,CAAC;QAClE,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,CAAC;QAC9B,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxD,mEAAmE;YACnE,MAAM,CAAC,KAAK,CACV,0EAA0E,CAC3E,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;QACrC,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,MAAM,CAAC,KAAK,CAAC,kDAAkD,GAAG,EAAE,CAAC,CAAC;QACtE,8CAA8C;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,GAAG,IAAI,CAAC;AAChB,CAAC"}
@@ -10,7 +10,9 @@ import { HealthCheckResult } from "../services/health-check.js";
10
10
  export interface StorageBackend {
11
11
  registerPeer(peerId: string, sessionId: string, cwd: string, label: string,
12
12
  /** cogent-bridge client version sent by the registering process (3.1.6+). */
13
- clientVersion?: string): Promise<PeerInfo>;
13
+ clientVersion?: string,
14
+ /** Observer peers receive frames but never auto-respond, added in 3.2 (Phase 17 OBS-01). */
15
+ mode?: "observer" | "agent"): Promise<PeerInfo>;
14
16
  deregisterPeer(peerId: string): Promise<boolean>;
15
17
  getPeer(peerId: string): Promise<PeerInfo | undefined>;
16
18
  listPeers(): Promise<PeerInfo[]>;
@@ -23,12 +25,30 @@ export interface StorageBackend {
23
25
  * (FE->BE response mirrors). Defaults to false in implementations -- the
24
26
  * common case is a "clean" history with one record per directed exchange.
25
27
  * Added in 3.1.11 (260511-o3p).
28
+ * @param metadataOnly When true, records are returned with body fields
29
+ * (message, response) omitted — only id, fromPeerId, toPeerId, timestamp,
30
+ * durationMs, isRelayEcho, success kept. Added in 3.2 (HIST-02).
31
+ * @param dedupInferredEchoes When true, suppress untagged auto-relay echoes
32
+ * via content-and-direction heuristic. Cloud-backend-only; FileBackend
33
+ * ignores the flag. Added in 3.2.1 (FIX-INFERRED-ECHO).
26
34
  */
27
- getHistory(peerId?: string, limit?: number, includeRelayEchoes?: boolean): Promise<MessageRecord[]>;
35
+ getHistory(peerId?: string, limit?: number, includeRelayEchoes?: boolean, metadataOnly?: boolean, dedupInferredEchoes?: boolean): Promise<MessageRecord[]>;
28
36
  validateSession(sessionId: string, cwd: string): Promise<boolean>;
29
37
  execClaude(sessionId: string, message: string, cwd: string, timeoutMs?: number): Promise<CliExecResult>;
30
- /** Update an existing message record's response field. Optional -- only HttpBackend implements this. */
31
- updateMessageResponse?(messageId: string, response: string, durationMs: number): Promise<void>;
38
+ /**
39
+ * Update an existing message record's response field. Optional -- only
40
+ * HttpBackend implements this. Pass `null` to mark a timed-out send so
41
+ * the record's response is not mistaken for the recipient's actual reply
42
+ * (v3.2.1, FIX-TIMEOUT-UX).
43
+ */
44
+ updateMessageResponse?(messageId: string, response: string | null, durationMs: number): Promise<void>;
32
45
  checkHealth(): Promise<HealthCheckResult>;
46
+ /**
47
+ * Lazy lookup of the upstream relay's `version` field, memoized for 60s
48
+ * by the implementing backend. Returns null in local mode or on fetch
49
+ * failure. Optional — only HttpBackend implements this; FileBackend omits.
50
+ * Added in 3.2 (VER-02). Consumers must use optional chaining.
51
+ */
52
+ getRelayVersion?(): Promise<string | null>;
33
53
  }
34
54
  //# sourceMappingURL=storage-backend.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"storage-backend.d.ts","sourceRoot":"","sources":["../../src/backend/storage-backend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAEhE;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAE7B,YAAY,CACV,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM;IACb,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,QAAQ,CAAC,CAAC;IAErB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEjD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IAEvD,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAEjC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAG9C,aAAa,CACX,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,WAAW,CAAC,GAC9C,OAAO,CAAC,aAAa,CAAC,CAAC;IAE1B;;;;;;;OAOG;IACH,UAAU,CACR,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,EACd,kBAAkB,CAAC,EAAE,OAAO,GAC3B,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAG5B,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAElE,UAAU,CACR,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,CAAC,CAAC;IAG1B,wGAAwG;IACxG,qBAAqB,CAAC,CACpB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAAC;IAGjB,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC3C"}
1
+ {"version":3,"file":"storage-backend.d.ts","sourceRoot":"","sources":["../../src/backend/storage-backend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAEhE;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAE7B,YAAY,CACV,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM;IACb,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM;IACtB,4FAA4F;IAC5F,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,GAC1B,OAAO,CAAC,QAAQ,CAAC,CAAC;IAErB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEjD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IAEvD,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAEjC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAG9C,aAAa,CACX,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,WAAW,CAAC,GAC9C,OAAO,CAAC,aAAa,CAAC,CAAC;IAE1B;;;;;;;;;;;;;OAaG;IACH,UAAU,CACR,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,EACd,kBAAkB,CAAC,EAAE,OAAO,EAC5B,YAAY,CAAC,EAAE,OAAO,EACtB,mBAAmB,CAAC,EAAE,OAAO,GAC5B,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAG5B,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAElE,UAAU,CACR,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,CAAC,CAAC;IAG1B;;;;;OAKG;IACH,qBAAqB,CAAC,CACpB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAAC;IAGjB,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAE1C;;;;;OAKG;IACH,eAAe,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC5C"}
package/dist/cli.js CHANGED
File without changes
package/dist/config.d.ts CHANGED
@@ -12,6 +12,7 @@ export declare const configSchema: z.ZodObject<{
12
12
  COGENT_STALE_TIMEOUT_MS: z.ZodDefault<z.ZodNumber>;
13
13
  COGENT_HEARTBEAT_INTERVAL_MS: z.ZodDefault<z.ZodNumber>;
14
14
  COGENT_WS_STALE_MS: z.ZodDefault<z.ZodNumber>;
15
+ COGENT_PLATFORM: z.ZodDefault<z.ZodEnum<["cc", "codex", "slack", "gchat", "web"]>>;
15
16
  }, "strip", z.ZodTypeAny, {
16
17
  COGENT_STATE_PATH: string;
17
18
  COGENT_POLL_INTERVAL_MS: number;
@@ -22,6 +23,7 @@ export declare const configSchema: z.ZodObject<{
22
23
  COGENT_STALE_TIMEOUT_MS: number;
23
24
  COGENT_HEARTBEAT_INTERVAL_MS: number;
24
25
  COGENT_WS_STALE_MS: number;
26
+ COGENT_PLATFORM: "cc" | "codex" | "slack" | "gchat" | "web";
25
27
  COGENT_ENDPOINT?: string | undefined;
26
28
  COGENT_SESSION_ID?: string | undefined;
27
29
  COGENT_SECRET?: string | undefined;
@@ -38,6 +40,7 @@ export declare const configSchema: z.ZodObject<{
38
40
  COGENT_STALE_TIMEOUT_MS?: number | undefined;
39
41
  COGENT_HEARTBEAT_INTERVAL_MS?: number | undefined;
40
42
  COGENT_WS_STALE_MS?: number | undefined;
43
+ COGENT_PLATFORM?: "cc" | "codex" | "slack" | "gchat" | "web" | undefined;
41
44
  }>;
42
45
  export type Config = z.infer<typeof configSchema>;
43
46
  export declare function loadConfig(env?: Record<string, string | undefined>): Config;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAevB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAIlD,wBAAgB,UAAU,CACxB,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GACpD,MAAM,CAUR;AAED,wBAAgB,SAAS,IAAI,MAAM,CAGlC;AAED,wBAAgB,WAAW,IAAI,IAAI,CAElC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBvB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAIlD,wBAAgB,UAAU,CACxB,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GACpD,MAAM,CAUR;AAED,wBAAgB,SAAS,IAAI,MAAM,CAGlC;AAED,wBAAgB,WAAW,IAAI,IAAI,CAElC"}
package/dist/config.js CHANGED
@@ -17,6 +17,9 @@ export const configSchema = z.object({
17
17
  COGENT_STALE_TIMEOUT_MS: z.coerce.number().int().min(0).default(1_800_000),
18
18
  COGENT_HEARTBEAT_INTERVAL_MS: z.coerce.number().int().min(0).default(60_000),
19
19
  COGENT_WS_STALE_MS: z.coerce.number().int().positive().default(90_000),
20
+ COGENT_PLATFORM: z
21
+ .enum(["cc", "codex", "slack", "gchat", "web"])
22
+ .default("cc"),
20
23
  });
21
24
  let _config = null;
22
25
  export function loadConfig(env = process.env) {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}