@securecoms/agent-bridge 0.26.6 → 0.27.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.
package/README.md CHANGED
@@ -705,6 +705,84 @@ including its key). Each proxied call is metered server-side
705
705
 
706
706
  ---
707
707
 
708
+ ## Markdown notes (0.27.0)
709
+
710
+ SecureComs-runtime agents keep short notes of what the owner asks them to
711
+ remember, in the owner's private chat only. The runtime saves a note with the
712
+ `memory_note` tool, and the bridge stores only a quote of the owner's own
713
+ current message. Each note is sealed per row in `bridge-state.db` (schema
714
+ v10) and is delivered only to the runtime's `/v1/ws` socket, never to a
715
+ harness, HTTP, SSE, a room, another chat or the voice fast path.
716
+
717
+ **Compatibility.**
718
+
719
+ - Install `@securecoms/agent-runtime` 0.10.0 together with the bridge and
720
+ restart both (`launchctl bootout` then `bootstrap`, never `kickstart`). The
721
+ bridge moves legacy owner-DM facts into notes, and reports
722
+ `memory_notes: true`, only after a runtime whose hello declares
723
+ `memory_notes` has connected in that bridge process. A 0.9.x runtime's
724
+ hello does not, so a 0.27 bridge with a 0.9.x runtime keeps today's facts
725
+ and recall, but it is not a supported pairing.
726
+ - Harness daemons (Hermes, OpenClaw) must name `memory.provider` in their
727
+ credential file. A daemon whose file omits it is treated as `securecoms`;
728
+ its harness socket still never receives notes and never turns on the import
729
+ or the report, so naming the provider is defence in depth. A global
730
+ `npm install -g --prefix ~/.local` reaches every daemon whose plist points
731
+ at the global `dist/bin.js`, at its next restart; check each credential file
732
+ (`jq .memory.provider <credential-file>`) before installing.
733
+ - A `/v1/ws` consumer that sends no hello waits about 2 seconds for its first
734
+ delivery.
735
+ - Notes are off in a freshly started bridge until a runtime-config refetch
736
+ succeeds. A bridge restarted while the backend is unreachable serves no
737
+ notes and accepts no writes until the backend answers.
738
+
739
+ **Known limitations.**
740
+
741
+ - Text the owner pastes counts as the owner's own words, up to the
742
+ 600-unit short-message bound.
743
+ - A quote can drop a condition or a negation ("Never cc X" can be saved as
744
+ "cc X"). Ask the agent what it saved.
745
+ - Short notes in CJK or Thai (fewer than 2 space-separated tokens) are
746
+ refused.
747
+ - UUIDs and long letter-and-digit tokens are refused as possible secrets.
748
+ - Forget and clear are logical deletes: sealed bytes can stay in free
749
+ database pages until they are overwritten, and they still open under the
750
+ device key.
751
+ - "Clear all notes" does not delete chat history or legacy facts. Legacy facts
752
+ that did not fit before can become notes after a clear.
753
+ - The voice fast path still sends the last 10 DM messages through the
754
+ backend proxy.
755
+
756
+ **Off switches.** There are three. Use the narrowest that fits.
757
+
758
+ - `memory.provider: "none"` in the credential file, then a daemon restart.
759
+ This turns notes off, and it also drops the recent history.
760
+ - `SECURECOMS_OWNER_DM_DEFAULT_GRANTS=off` in the bridge service environment.
761
+ This also drops the owner-DM tools, not only `memory_note`.
762
+ - `SECURECOMS_TOOL_DENY=memory_note` removes only the note tool.
763
+
764
+ **Log events.** All are content-free: counts and classes only, never note text.
765
+ `memory.note_written` (`op`, `notes_count`, `doc_chars`),
766
+ `memory.note_refused` (`reason_class`), `memory.notes_cache_miss`,
767
+ `memory.note_open_failed`, `memory.import_partial` (`remaining`),
768
+ `memory.config_unrecognized`, `memory.clear_generation_regressed`,
769
+ `memory.clear_failed`, `memory.applied_generation_out_of_range`,
770
+ `memory.notes_fill_failed`, `memory.import_failed`,
771
+ `memory.note_write_failed` (error class only), and `ws.hello_timeout` (no
772
+ fields: a `/v1/ws` socket sent no hello and delivery opened after the wait).
773
+
774
+ **Upgrade order.** Upgrade and restart the bridge and the runtime together.
775
+ First check `memory.provider` in the credential file of every daemon that a
776
+ global install reaches (`jq .memory.provider <credential-file>`).
777
+
778
+ **Rollback.** A 0.26.x bridge leaves the notes sealed on disk and reads
779
+ neither the notes nor the legacy facts already moved into them, until it is
780
+ upgraded again; the same holds for a 0.9.x runtime. Roll back the runtime and
781
+ the bridge together, and restart both: the bridge decides once per process
782
+ that a notes-reading runtime is present.
783
+
784
+ ---
785
+
708
786
  ## Flags and environment
709
787
 
710
788
  | Flag | Env var | Default | Description |
package/dist/bin.d.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import { BridgeAgent } from "./bridge-agent.js";
3
+ import { createHttpServer } from "./http-server.js";
4
+ import { attachAgentWebSocket } from "./ws-server.js";
2
5
  import { type ResolveNodeDeps } from "./service/resolve-node.js";
3
6
  import { type Harness } from "./service/wire.js";
4
7
  export declare function nodeMajorOk(version: string): boolean;
@@ -12,3 +15,23 @@ export declare function parseVerb(argv: string[]): "install" | "uninstall" | "st
12
15
  export declare function slugFromCredentialPath(credentialPath: string): string;
13
16
  export declare function chooseInstallExecPath(runningExecPath: string, override: string | undefined, deps: ResolveNodeDeps): string;
14
17
  export declare function realCopyConnector(srcDir: string, dstDir: string, harness: Harness): void;
18
+ /**
19
+ * Markdown memory 7a, N-L5: start the agent, THEN create the HTTP server and
20
+ * attach /v1/ws. start() applies the runtime config (and any clear issued
21
+ * while the machine was offline) and warms the restored turns before it
22
+ * resolves, so no route or socket exists while a stale note could be served.
23
+ * main() can listen only on the server this returns. `readTls` runs after
24
+ * start(), as the inline read did.
25
+ */
26
+ export declare function startThenServe(agent: BridgeAgent, opts: {
27
+ token: string;
28
+ allowOrigins: string[];
29
+ readTls: () => {
30
+ cert: string;
31
+ key: string;
32
+ } | undefined;
33
+ }): Promise<{
34
+ server: ReturnType<typeof createHttpServer>["server"];
35
+ closeAllSseStreams: () => void;
36
+ agentWs: ReturnType<typeof attachAgentWebSocket>;
37
+ }>;