@securecoms/agent-bridge 0.33.1 → 0.35.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.
@@ -0,0 +1,42 @@
1
+ export declare const VAULT_OUTBOX_DIRNAME = "vault-outbox";
2
+ export declare class PathOutsideOutboxError extends Error {
3
+ constructor();
4
+ }
5
+ /** The outbox as observed at start(); every read must still see exactly this directory. */
6
+ export interface OutboxPin {
7
+ /** The configured path (what the authenticated GET /v1/vault-outbox reports). */
8
+ readonly dir: string;
9
+ /** realpath of the outbox at pin time; the open path is built from this. */
10
+ readonly real: string;
11
+ readonly dev: number;
12
+ readonly ino: number;
13
+ }
14
+ /** A file read from the outbox; `consumeOutboxFile` deletes exactly this inode. */
15
+ export interface OutboxRead {
16
+ readonly bytes: Uint8Array;
17
+ readonly path: string;
18
+ readonly dev: number;
19
+ readonly ino: number;
20
+ }
21
+ /**
22
+ * Create the outbox 0700 if missing and pin it. An existing outbox owned by
23
+ * this uid is tightened to 0700; one that is a symlink, not a directory, or
24
+ * owned by another uid is refused.
25
+ */
26
+ export declare function ensureOutbox(dir: string): OutboxPin;
27
+ /**
28
+ * Read `callerPath` iff it is a regular file directly inside the pinned
29
+ * outbox. A relative `callerPath` resolves against the outbox. A null pin
30
+ * (no data dir, or the outbox could not be created at start) refuses every
31
+ * path: fail closed.
32
+ */
33
+ export declare function readOutboxFile(pin: OutboxPin | null, callerPath: string): Promise<OutboxRead>;
34
+ /**
35
+ * Delete an uploaded file from the outbox, but only if the outbox is still
36
+ * the pinned directory (same checks as a read) and the name still holds the
37
+ * inode that was read (a file swapped in after the read is left alone). The
38
+ * unlink goes through the pinned realpath. A window remains between these
39
+ * lstats and the unlink (Node has no unlinkat): narrowed, not closed.
40
+ * Returns whether it was deleted; never throws (the upload already happened).
41
+ */
42
+ export declare function consumeOutboxFile(pin: OutboxPin, read: OutboxRead): Promise<boolean>;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The reply credit (weather/currency architect ruling OQ-P1, 2026-10-29; plan Task 17).
3
+ *
4
+ * A runtime that called weather_forecast flags its `send` frame with `credit: "weatherapi"`. The BRIDGE appends the
5
+ * WeatherAPI.com credit line (U-25, approved by Eric 2026-10-18) to the published text and records the UN-credited text
6
+ * to history, unified memory and the call buffer, so the line never feeds the next turn's context (P-1). The bridge
7
+ * declares REPLY_CREDIT_FEATURE in its hello; the runtime offers weather_forecast only behind a bridge that did.
8
+ * The bridge keeps its own copy of the line; capability-parity.test.ts pins it to the runtime's.
9
+ */
10
+ export declare const REPLY_CREDIT_FEATURE = "reply_credit_v1";
11
+ export declare const WEATHER_CREDIT_LINE = "Weather data: WeatherAPI.com. For general information only.";
12
+ export type ReplyCredit = "weatherapi";
13
+ /** The exact suffix a credited reply's published text carries. */
14
+ export declare const WEATHER_CREDIT_SUFFIX = "\n\nWeather data: WeatherAPI.com. For general information only.";
15
+ /** The closed set: anything else is not a credit (and a frame carrying it is refused). */
16
+ export declare function isReplyCredit(v: unknown): v is ReplyCredit;
17
+ /**
18
+ * Code review Q2: the exact credit suffix removed from the END of a text, once; anything else unchanged. Used where
19
+ * the agent's OWN published reply comes back as an inbound (another device of the same identity), so the credit line
20
+ * never enters history from that path either.
21
+ */
22
+ export declare function stripCreditSuffix(text: string): string;
@@ -1,3 +1,4 @@
1
+ import type { ReplyCredit } from "./reply-credit.js";
1
2
  /** The body of one reply part, as the intent stores it (sealed at rest). */
2
3
  export type ReplyBody = {
3
4
  kind: "text";
@@ -39,8 +40,12 @@ export declare function decodeReplyBody(bytes: Uint8Array): ReplyBody;
39
40
  * Keyed MAC binding a body to its reply id and channel. Compares retries
40
41
  * without storing a plain digest, and (PR #716 review LOW-6) makes a body moved
41
42
  * to another row, or a row whose channel was edited, fail verification.
43
+ *
44
+ * Weather/currency Task 17 (audit r2, adopted): an optional `credit` is bound too. Undefined keeps the MAC input
45
+ * byte-identical to the four-argument form, so every existing row and every uncredited reply verifies unchanged; a
46
+ * flipped or nulled reply_credit column, or a credited row read by an older bridge, fails verification.
42
47
  */
43
- export declare function replyBodyMac(key: Uint8Array, replyId: string, channelId: string, body: Uint8Array): string;
48
+ export declare function replyBodyMac(key: Uint8Array, replyId: string, channelId: string, body: Uint8Array, credit?: ReplyCredit): string;
44
49
  /** The ordinal of an unkeyed reply part (`p:<n>`), or null for a keyed part. */
45
50
  export declare function partOrdinal(part: string): number | null;
46
51
  /**
@@ -52,6 +52,8 @@ export interface LocalReport {
52
52
  has_llm_key: boolean;
53
53
  /** L-2 (spec §7.9): a readable key for an extract-capable provider. Only a real true counts; absent is false. */
54
54
  has_extract_provider: boolean;
55
+ /** Weather/currency L-1: a weather key the runtime's format check accepts. Only a real true counts; absent is false. */
56
+ has_weather_key: boolean;
55
57
  /** D39: the owner-DM daily search cap the runtime enforces; an integer in [0, 2000], otherwise undefined. */
56
58
  owner_dm_search_cap_effective?: number;
57
59
  legacy_memory: LegacyMemoryReport[];
@@ -81,6 +83,7 @@ export interface SecretPathsReport {
81
83
  postgres_url_file: number;
82
84
  search_key_file: number;
83
85
  sqlite?: number;
86
+ weather_key_file?: number;
84
87
  };
85
88
  }
86
89
  export type LegacyMemoryKind = "global-memory" | "conversation-history" | "captured-memory";
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const BRIDGE_VERSION = "0.33.1";
1
+ export declare const BRIDGE_VERSION = "0.35.0";
@@ -51,7 +51,7 @@ export declare const MEMORY_UNIFIED_FEATURE = "memory_unified";
51
51
  * fake against this list at run time (7b gate fix: a member added here without
52
52
  * a fake made three tests throw "is not a function").
53
53
  */
54
- export declare const WS_AGENT_MEMBERS: readonly ["ackRuntimeMessages", "action", "admitRuntimeDelivery", "applyMemoryNote", "clearHarnessReport", "clearManifestConsumer", "clearPerToolConsumer", "clearSearchProvidersSocket", "harnessGrantsWithheld", "signedSearchProvider", "isRuntimeMessageRetired", "noteConsumerCapability", "noteManifestConsumer", "noteRoomCapReached", "noteSearchProvidersSocket", "noteNotesConsumer", "notePerToolConsumer", "noteRecallConsumer", "noteUnifiedConsumer", "noteSessionClose", "noteSessionEvicted", "noteSessionOpen", "notesAppliedGeneration", "notesForDelivery", "recallForDelivery", "unifiedFeatureOn", "unifiedForDelivery", "recordHarnessReport", "recordRuntimeReply", "reportStatusGated", "requeueFailedRuntimeDeliveries", "requeueFront", "runtimeReplyReceipt", "send", "sendA2A", "subscribe", "takeDeliverable", "wakeListeners"];
54
+ export declare const WS_AGENT_MEMBERS: readonly ["ackRuntimeMessages", "action", "admitRuntimeDelivery", "applyMemoryNote", "clearHarnessReport", "clearManifestConsumer", "clearPerToolConsumer", "clearSearchProvidersSocket", "clearUtilityToolsSocket", "harnessGrantsWithheld", "signedSearchProvider", "isRuntimeMessageRetired", "noteConsumerCapability", "noteManifestConsumer", "noteRoomCapReached", "noteSearchProvidersSocket", "noteUtilityToolsSocket", "noteNotesConsumer", "notePerToolConsumer", "noteRecallConsumer", "noteUnifiedConsumer", "noteSessionClose", "noteSessionEvicted", "noteSessionOpen", "notesAppliedGeneration", "notesForDelivery", "recallForDelivery", "unifiedFeatureOn", "unifiedForDelivery", "recordHarnessReport", "recordRuntimeReply", "reportStatusGated", "requeueFailedRuntimeDeliveries", "requeueFront", "runtimeReplyReceipt", "send", "sendA2A", "subscribe", "takeDeliverable", "wakeListeners"];
55
55
  export type WsAgent = Pick<BridgeAgent, (typeof WS_AGENT_MEMBERS)[number]>;
56
56
  export declare function attachAgentWebSocket(server: HttpServer, agent: WsAgent, opts: AgentWebSocketOptions): {
57
57
  close(): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@securecoms/agent-bridge",
3
- "version": "0.33.1",
3
+ "version": "0.35.0",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=24"
@@ -50,7 +50,7 @@
50
50
  "ajv-formats": "^3.0.1",
51
51
  "libsodium-wrappers-sumo": "0.7.15",
52
52
  "ws": "^8.21.0",
53
- "zod": "^3.23.0"
53
+ "zod": "^4.6.7"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@agentvault/connect-core": "*",