@securecoms/agent-bridge 0.25.2 → 0.25.3

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/dist/bin.js CHANGED
@@ -7436,10 +7436,10 @@ var HANDOFF = {
7436
7436
  balanced: "If the message needs files, tools, memory lookups, current data, or any work you cannot do instantly, say in one sentence that you are checking and end your reply with the exact token [[DEFER]] so the full agent answers next. For greetings, small talk, and anything you can answer completely yourself, answer completely and do NOT add the token.",
7437
7437
  self: "Answer yourself whenever you reasonably can. Only when the message clearly needs files, tools, or current data you cannot see, say in one sentence that you are checking and end your reply with the exact token [[DEFER]]."
7438
7438
  };
7439
- function compileVoicePrompt(s) {
7439
+ function compileVoicePrompt(s, agentName) {
7440
7440
  const parts = [];
7441
7441
  const persona = s.persona.trim();
7442
- const displayName = s.displayName.trim();
7442
+ const displayName = (agentName ?? "").trim();
7443
7443
  if (displayName && !persona.toLowerCase().includes(displayName.toLowerCase())) {
7444
7444
  parts.push(`You are ${displayName}.`);
7445
7445
  }
@@ -7491,6 +7491,9 @@ var Row = z.object({
7491
7491
  voice_id: z.string().nullable().optional(),
7492
7492
  pace: z.enum(PACES).default("normal"),
7493
7493
  display_name: z.string().max(40).default(""),
7494
+ // Owner decision 2026-10-01 ("one name"). Lenient: a bad value is dropped
7495
+ // (see identityName below), never a reason to reject the whole row.
7496
+ identity_display_name: z.unknown().optional(),
7494
7497
  persona: z.string().max(600).default(""),
7495
7498
  warmth: z.enum(WARMTHS).default("friendly"),
7496
7499
  formality: z.enum(FORMALITIES).default("neutral"),
@@ -7501,8 +7504,14 @@ var Row = z.object({
7501
7504
  avoid_topics: z.array(z.string().max(80)).max(10).default([]),
7502
7505
  handoff: z.enum(HANDOFFS).default("balanced")
7503
7506
  }).passthrough();
7507
+ function identityName(v) {
7508
+ if (typeof v !== "string") return void 0;
7509
+ const name = v.trim();
7510
+ return name && name.length <= 200 ? name : void 0;
7511
+ }
7504
7512
  function parseVoiceSettings(raw) {
7505
7513
  const r = Row.parse(raw);
7514
+ const identityDisplayName = identityName(r.identity_display_name);
7506
7515
  return {
7507
7516
  version: r.version,
7508
7517
  voiceId: r.voice_id ?? null,
@@ -7516,7 +7525,8 @@ function parseVoiceSettings(raw) {
7516
7525
  quirks: r.quirks,
7517
7526
  greetingStyle: r.greeting_style,
7518
7527
  avoidTopics: r.avoid_topics,
7519
- handoff: r.handoff
7528
+ handoff: r.handoff,
7529
+ ...identityDisplayName ? { identityDisplayName } : {}
7520
7530
  };
7521
7531
  }
7522
7532
  function settingsToVoiceConfig(s, proxy) {
@@ -7577,10 +7587,11 @@ function parseVoiceConfig(raw, env) {
7577
7587
  }
7578
7588
  };
7579
7589
  }
7580
- function systemPrompt(p, settings) {
7590
+ function systemPrompt(p, settings, agentName) {
7581
7591
  const core = p.persona.trim().endsWith(CONTINUITY_CLAUSE) ? p.persona.trim().slice(0, -CONTINUITY_CLAUSE.length).trim() : p.persona.trim();
7582
7592
  return compileVoicePrompt(
7583
- settings ?? { ...DEFAULT_VOICE_SETTINGS, displayName: p.displayName ?? "", persona: core, quirks: p.quirks }
7593
+ settings ?? { ...DEFAULT_VOICE_SETTINGS, persona: core, quirks: p.quirks },
7594
+ agentName
7584
7595
  );
7585
7596
  }
7586
7597
 
@@ -28350,7 +28361,7 @@ function clampContent(content, max = MAX_MESSAGE_CHARS) {
28350
28361
  }
28351
28362
  function buildFastMessages(args2) {
28352
28363
  const cap = args2.charCap ?? 4e3;
28353
- const sp = systemPrompt(args2.persona, args2.settings);
28364
+ const sp = systemPrompt(args2.persona, args2.settings, args2.agentName);
28354
28365
  const head = sp.slice(0, sp.length - CONTINUITY_CLAUSE.length).trimEnd();
28355
28366
  const system = `${head} ${args2.guidance.trim()} ${CONTINUITY_CLAUSE}`;
28356
28367
  const recent = args2.memory.recent.map((t) => ({
@@ -29250,6 +29261,12 @@ var BridgeAgent = class _BridgeAgent {
29250
29261
  * `roomDisplayName`. Kept across a later failed refresh, so a transient
29251
29262
  * members-fetch error does not make the agent deaf to its own name; a
29252
29263
  * successful refresh after a rename replaces it.
29264
+ *
29265
+ * 2026-10-01 ("one name"): also the name the voice fast path speaks as
29266
+ * ("You are <name>."). A voice settings fetch that carries
29267
+ * `identity_display_name` writes it too (the backend pings
29268
+ * `voice_settings_changed` on a rename), so the latest observation from
29269
+ * either source wins; both read the same identity column.
29253
29270
  */
29254
29271
  lastOwnDisplayName;
29255
29272
  /**
@@ -29653,6 +29670,7 @@ var BridgeAgent = class _BridgeAgent {
29653
29670
  const res = await this.fetchBounded("voice_settings", "read", url, { headers: { authorization: `Bearer ${this.cfg.apiKey}` } });
29654
29671
  if (!res.ok) throw new Error(`voice-settings ${res.status}`);
29655
29672
  const s = parseVoiceSettings(await res.json());
29673
+ if (s.identityDisplayName) this.lastOwnDisplayName = s.identityDisplayName;
29656
29674
  const proxy = settingsToVoiceConfig(s, { baseUrl: this.cfg.apiBase, apiKey: this.cfg.apiKey });
29657
29675
  if (s.version === 0 && this.fileVoiceConfig) {
29658
29676
  const merged = {
@@ -31550,7 +31568,8 @@ var BridgeAgent = class _BridgeAgent {
31550
31568
  memory,
31551
31569
  speaker,
31552
31570
  text,
31553
- settings: this.voiceSettings ?? void 0
31571
+ settings: this.voiceSettings ?? void 0,
31572
+ agentName: this.voiceAgentName()
31554
31573
  });
31555
31574
  const maxSentences = this.voiceSettings?.brevity === "one" ? 1 : 2;
31556
31575
  const { reply, defer } = splitFastReply(await this.fastLlm.complete(messages), 200, maxSentences);
@@ -32857,6 +32876,16 @@ var BridgeAgent = class _BridgeAgent {
32857
32876
  ownRoomDisplayName() {
32858
32877
  return this.lastOwnDisplayName;
32859
32878
  }
32879
+ /**
32880
+ * 2026-10-01 (owner decision, "one name"): the name the voice prompt uses.
32881
+ * The agent's CURRENT identity display name (roster or voice settings
32882
+ * fetch, whichever saw it last); before either has, the credential's
32883
+ * agent_name (the same identity name as of credential issue). Never the
32884
+ * legacy voice settings `display_name` or the file `voice.persona.display_name`.
32885
+ */
32886
+ voiceAgentName() {
32887
+ return this.lastOwnDisplayName ?? this.cfg.agentName;
32888
+ }
32860
32889
  /** Phase 3 F3: the loop guard's view of the sender — server roster first. */
32861
32890
  loopSenderIsAgent(channelId, senderId, envelopeSaysAgent, relayedHumanTurn) {
32862
32891
  if (relayedHumanTurn) return false;
@@ -567,6 +567,12 @@ export declare class BridgeAgent {
567
567
  * `roomDisplayName`. Kept across a later failed refresh, so a transient
568
568
  * members-fetch error does not make the agent deaf to its own name; a
569
569
  * successful refresh after a rename replaces it.
570
+ *
571
+ * 2026-10-01 ("one name"): also the name the voice fast path speaks as
572
+ * ("You are <name>."). A voice settings fetch that carries
573
+ * `identity_display_name` writes it too (the backend pings
574
+ * `voice_settings_changed` on a rename), so the latest observation from
575
+ * either source wins; both read the same identity column.
570
576
  */
571
577
  private lastOwnDisplayName;
572
578
  /**
@@ -2001,6 +2007,14 @@ export declare class BridgeAgent {
2001
2007
  * the identity id.
2002
2008
  */
2003
2009
  private ownRoomDisplayName;
2010
+ /**
2011
+ * 2026-10-01 (owner decision, "one name"): the name the voice prompt uses.
2012
+ * The agent's CURRENT identity display name (roster or voice settings
2013
+ * fetch, whichever saw it last); before either has, the credential's
2014
+ * agent_name (the same identity name as of credential issue). Never the
2015
+ * legacy voice settings `display_name` or the file `voice.persona.display_name`.
2016
+ */
2017
+ private voiceAgentName;
2004
2018
  /** Phase 3 F3: the loop guard's view of the sender — server roster first. */
2005
2019
  private loopSenderIsAgent;
2006
2020
  private noteAgentTurnSuppressed;
package/dist/index.js CHANGED
@@ -28041,10 +28041,10 @@ var HANDOFF = {
28041
28041
  balanced: "If the message needs files, tools, memory lookups, current data, or any work you cannot do instantly, say in one sentence that you are checking and end your reply with the exact token [[DEFER]] so the full agent answers next. For greetings, small talk, and anything you can answer completely yourself, answer completely and do NOT add the token.",
28042
28042
  self: "Answer yourself whenever you reasonably can. Only when the message clearly needs files, tools, or current data you cannot see, say in one sentence that you are checking and end your reply with the exact token [[DEFER]]."
28043
28043
  };
28044
- function compileVoicePrompt(s) {
28044
+ function compileVoicePrompt(s, agentName) {
28045
28045
  const parts = [];
28046
28046
  const persona = s.persona.trim();
28047
- const displayName = s.displayName.trim();
28047
+ const displayName = (agentName ?? "").trim();
28048
28048
  if (displayName && !persona.toLowerCase().includes(displayName.toLowerCase())) {
28049
28049
  parts.push(`You are ${displayName}.`);
28050
28050
  }
@@ -28096,6 +28096,9 @@ var Row = z.object({
28096
28096
  voice_id: z.string().nullable().optional(),
28097
28097
  pace: z.enum(PACES).default("normal"),
28098
28098
  display_name: z.string().max(40).default(""),
28099
+ // Owner decision 2026-10-01 ("one name"). Lenient: a bad value is dropped
28100
+ // (see identityName below), never a reason to reject the whole row.
28101
+ identity_display_name: z.unknown().optional(),
28099
28102
  persona: z.string().max(600).default(""),
28100
28103
  warmth: z.enum(WARMTHS).default("friendly"),
28101
28104
  formality: z.enum(FORMALITIES).default("neutral"),
@@ -28106,8 +28109,14 @@ var Row = z.object({
28106
28109
  avoid_topics: z.array(z.string().max(80)).max(10).default([]),
28107
28110
  handoff: z.enum(HANDOFFS).default("balanced")
28108
28111
  }).passthrough();
28112
+ function identityName(v) {
28113
+ if (typeof v !== "string") return void 0;
28114
+ const name = v.trim();
28115
+ return name && name.length <= 200 ? name : void 0;
28116
+ }
28109
28117
  function parseVoiceSettings(raw) {
28110
28118
  const r = Row.parse(raw);
28119
+ const identityDisplayName = identityName(r.identity_display_name);
28111
28120
  return {
28112
28121
  version: r.version,
28113
28122
  voiceId: r.voice_id ?? null,
@@ -28121,7 +28130,8 @@ function parseVoiceSettings(raw) {
28121
28130
  quirks: r.quirks,
28122
28131
  greetingStyle: r.greeting_style,
28123
28132
  avoidTopics: r.avoid_topics,
28124
- handoff: r.handoff
28133
+ handoff: r.handoff,
28134
+ ...identityDisplayName ? { identityDisplayName } : {}
28125
28135
  };
28126
28136
  }
28127
28137
  function settingsToVoiceConfig(s, proxy) {
@@ -28182,10 +28192,11 @@ function parseVoiceConfig(raw, env) {
28182
28192
  }
28183
28193
  };
28184
28194
  }
28185
- function systemPrompt(p, settings) {
28195
+ function systemPrompt(p, settings, agentName) {
28186
28196
  const core = p.persona.trim().endsWith(CONTINUITY_CLAUSE) ? p.persona.trim().slice(0, -CONTINUITY_CLAUSE.length).trim() : p.persona.trim();
28187
28197
  return compileVoicePrompt(
28188
- settings ?? { ...DEFAULT_VOICE_SETTINGS, displayName: p.displayName ?? "", persona: core, quirks: p.quirks }
28198
+ settings ?? { ...DEFAULT_VOICE_SETTINGS, persona: core, quirks: p.quirks },
28199
+ agentName
28189
28200
  );
28190
28201
  }
28191
28202
 
@@ -28199,7 +28210,7 @@ function clampContent(content, max = MAX_MESSAGE_CHARS) {
28199
28210
  }
28200
28211
  function buildFastMessages(args2) {
28201
28212
  const cap = args2.charCap ?? 4e3;
28202
- const sp = systemPrompt(args2.persona, args2.settings);
28213
+ const sp = systemPrompt(args2.persona, args2.settings, args2.agentName);
28203
28214
  const head = sp.slice(0, sp.length - CONTINUITY_CLAUSE.length).trimEnd();
28204
28215
  const system = `${head} ${args2.guidance.trim()} ${CONTINUITY_CLAUSE}`;
28205
28216
  const recent = args2.memory.recent.map((t) => ({
@@ -29099,6 +29110,12 @@ var BridgeAgent = class _BridgeAgent {
29099
29110
  * `roomDisplayName`. Kept across a later failed refresh, so a transient
29100
29111
  * members-fetch error does not make the agent deaf to its own name; a
29101
29112
  * successful refresh after a rename replaces it.
29113
+ *
29114
+ * 2026-10-01 ("one name"): also the name the voice fast path speaks as
29115
+ * ("You are <name>."). A voice settings fetch that carries
29116
+ * `identity_display_name` writes it too (the backend pings
29117
+ * `voice_settings_changed` on a rename), so the latest observation from
29118
+ * either source wins; both read the same identity column.
29102
29119
  */
29103
29120
  lastOwnDisplayName;
29104
29121
  /**
@@ -29502,6 +29519,7 @@ var BridgeAgent = class _BridgeAgent {
29502
29519
  const res = await this.fetchBounded("voice_settings", "read", url, { headers: { authorization: `Bearer ${this.cfg.apiKey}` } });
29503
29520
  if (!res.ok) throw new Error(`voice-settings ${res.status}`);
29504
29521
  const s = parseVoiceSettings(await res.json());
29522
+ if (s.identityDisplayName) this.lastOwnDisplayName = s.identityDisplayName;
29505
29523
  const proxy = settingsToVoiceConfig(s, { baseUrl: this.cfg.apiBase, apiKey: this.cfg.apiKey });
29506
29524
  if (s.version === 0 && this.fileVoiceConfig) {
29507
29525
  const merged = {
@@ -31399,7 +31417,8 @@ var BridgeAgent = class _BridgeAgent {
31399
31417
  memory,
31400
31418
  speaker,
31401
31419
  text,
31402
- settings: this.voiceSettings ?? void 0
31420
+ settings: this.voiceSettings ?? void 0,
31421
+ agentName: this.voiceAgentName()
31403
31422
  });
31404
31423
  const maxSentences = this.voiceSettings?.brevity === "one" ? 1 : 2;
31405
31424
  const { reply, defer } = splitFastReply(await this.fastLlm.complete(messages), 200, maxSentences);
@@ -32706,6 +32725,16 @@ var BridgeAgent = class _BridgeAgent {
32706
32725
  ownRoomDisplayName() {
32707
32726
  return this.lastOwnDisplayName;
32708
32727
  }
32728
+ /**
32729
+ * 2026-10-01 (owner decision, "one name"): the name the voice prompt uses.
32730
+ * The agent's CURRENT identity display name (roster or voice settings
32731
+ * fetch, whichever saw it last); before either has, the credential's
32732
+ * agent_name (the same identity name as of credential issue). Never the
32733
+ * legacy voice settings `display_name` or the file `voice.persona.display_name`.
32734
+ */
32735
+ voiceAgentName() {
32736
+ return this.lastOwnDisplayName ?? this.cfg.agentName;
32737
+ }
32709
32738
  /** Phase 3 F3: the loop guard's view of the sender — server roster first. */
32710
32739
  loopSenderIsAgent(channelId, senderId, envelopeSaysAgent, relayedHumanTurn) {
32711
32740
  if (relayedHumanTurn) return false;
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const BRIDGE_VERSION = "0.25.2";
1
+ export declare const BRIDGE_VERSION = "0.25.3";
@@ -35,6 +35,9 @@ export declare function buildFastMessages(args: {
35
35
  * from these backend-loaded dials (compileVoicePrompt) instead of the
36
36
  * credential file's persona block. */
37
37
  settings?: VoiceSettings;
38
+ /** The agent's identity display name ("one name", 2026-10-01): the only
39
+ * source of the prompt's "You are <name>." line. */
40
+ agentName?: string;
38
41
  }): ChatMessage[];
39
42
  /** The fast model appends this when the full agent must answer next. */
40
43
  export declare const DEFER_TOKEN = "[[DEFER]]";
@@ -1,5 +1,11 @@
1
1
  import { type VoiceSettings } from "./settings.js";
2
2
  export declare const CONTINUITY_CLAUSE: string;
3
+ /**
4
+ * `displayName` is legacy (the credential file's `voice.persona.display_name`,
5
+ * or the backend's voice settings `display_name`). It is still parsed so old
6
+ * credentials and payloads load, but the prompt never reads it: the agent's
7
+ * name comes from its identity display name (owner decision 2026-10-01, "one name").
8
+ */
3
9
  export interface VoicePersona {
4
10
  displayName?: string;
5
11
  persona: string;
@@ -20,4 +26,4 @@ export interface VoiceConfig {
20
26
  settings?: VoiceSettings;
21
27
  }
22
28
  export declare function parseVoiceConfig(raw: unknown, env: Record<string, string | undefined>): VoiceConfig | undefined;
23
- export declare function systemPrompt(p: VoicePersona, settings?: VoiceSettings): string;
29
+ export declare function systemPrompt(p: VoicePersona, settings?: VoiceSettings, agentName?: string): string;
@@ -1,4 +1,11 @@
1
1
  import type { VoiceSettings } from "./settings.js";
2
- export declare function compileVoicePrompt(s: VoiceSettings): string;
2
+ /**
3
+ * `agentName` is the agent's identity display name (`ConnectIdentity.display_name`,
4
+ * the one name shown in rosters and the Directory). Owner decision 2026-10-01
5
+ * ("one name"): the voice settings `display_name` (`s.displayName`) is a legacy
6
+ * field that is still parsed for compatibility but never read here, so a
7
+ * rename reaches calls too.
8
+ */
9
+ export declare function compileVoicePrompt(s: VoiceSettings, agentName?: string): string;
3
10
  export declare const VOICE_CALL_START_MARKER = "[voice call started]";
4
11
  export declare function greetingTurnFor(s: VoiceSettings, callerName?: string): string;
@@ -10,7 +10,13 @@ export interface VoiceSettings {
10
10
  version: number;
11
11
  voiceId: string | null;
12
12
  pace: (typeof PACES)[number];
13
+ /** Legacy voice-only name (backend `display_name`). Parsed for compatibility
14
+ * with older backends/web clients, never used for the prompt ("one name",
15
+ * 2026-10-01). */
13
16
  displayName: string;
17
+ /** The agent's identity display name at fetch time (backend
18
+ * `identity_display_name`), when the backend sends it. */
19
+ identityDisplayName?: string;
14
20
  persona: string;
15
21
  warmth: (typeof WARMTHS)[number];
16
22
  formality: (typeof FORMALITIES)[number];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@securecoms/agent-bridge",
3
- "version": "0.25.2",
3
+ "version": "0.25.3",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=22.5.0"