@securecoms/agent-bridge 0.26.3 → 0.26.4
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 +25 -3
- package/dist/bridge-agent.d.ts +4 -0
- package/dist/index.js +25 -3
- package/dist/version.d.ts +1 -1
- package/dist/voice/fast-prompt.d.ts +9 -0
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -28512,11 +28512,26 @@ function clampContent(content, max = MAX_MESSAGE_CHARS) {
|
|
|
28512
28512
|
const marker = "\u2026";
|
|
28513
28513
|
return content.slice(0, Math.max(0, max - marker.length)) + marker;
|
|
28514
28514
|
}
|
|
28515
|
+
var FAST_DEFER_RULE = `Whenever you cannot answer completely from what is shown here, never say you can't, that you lack a tool, access or real-time data: reply with one short sentence like "Let me check that." and end with the exact token [[DEFER]] so the full agent answers next.`;
|
|
28516
|
+
var REFUSAL_PATTERNS = [
|
|
28517
|
+
// "I can't / cannot / am unable to / am not able to <check|access|...>", optional adverb.
|
|
28518
|
+
/\b(?:can't|cannot|can\s+not|unable\s+to|not\s+able\s+to)\s+(?:\w+ly\s+)?(?:check|access|look|see|browse|search|get|provide|give\s+you|find|retrieve|fetch|pull|know|help\s+with\s+(?:that|this)|do\s+that)\b/,
|
|
28519
|
+
// "I don't / do not / doesn't have (a|any|the)? <tool|access|ability|real-time|live ...>".
|
|
28520
|
+
/\b(?:don't|do\s+not|doesn't|does\s+not|lack)\s+(?:have\s+)?(?:a\s+|any\s+|the\s+)?(?:tool|tools|access|ability|capability|real[-\s]?time|live|current|internet|web|way\s+to)\b/,
|
|
28521
|
+
/\bno\s+(?:access|tools?|internet|web\s+access|real[-\s]?time|live\s+data|way\s+to\s+(?:check|access|know|see))\b/,
|
|
28522
|
+
/\bas\s+an\s+(?:ai|a\.i\.|language\s+model)\b/,
|
|
28523
|
+
/\bbeyond\s+my\s+(?:capabilities|abilities|capability)\b/,
|
|
28524
|
+
/\b(?:knowledge\s+cutoff|training\s+data)\b/
|
|
28525
|
+
];
|
|
28526
|
+
function isRefusal(reply) {
|
|
28527
|
+
const t = reply.toLowerCase().replace(/[‘’]/g, "'");
|
|
28528
|
+
return REFUSAL_PATTERNS.some((re) => re.test(t));
|
|
28529
|
+
}
|
|
28515
28530
|
function buildFastMessages(args2) {
|
|
28516
28531
|
const cap = args2.charCap ?? FAST_RECENT_CHARS_CAP;
|
|
28517
28532
|
const sp = systemPrompt(args2.persona, args2.settings, args2.agentName);
|
|
28518
28533
|
const head = sp.slice(0, sp.length - CONTINUITY_CLAUSE.length).trimEnd();
|
|
28519
|
-
const system = `${head} ${args2.guidance.trim()} ${CONTINUITY_CLAUSE}`;
|
|
28534
|
+
const system = `${head} ${args2.guidance.trim()} ${FAST_DEFER_RULE} ${CONTINUITY_CLAUSE}`;
|
|
28520
28535
|
const recent = args2.memory.recent.map((t) => ({
|
|
28521
28536
|
role: t.role === "agent" ? "assistant" : "user",
|
|
28522
28537
|
content: t.text
|
|
@@ -29704,6 +29719,8 @@ var BridgeAgent = class _BridgeAgent {
|
|
|
29704
29719
|
fastPathDeferred = 0;
|
|
29705
29720
|
/** Of those, `full`-mode turns the deterministic pre-check deferred without calling the fast model. */
|
|
29706
29721
|
fastPathIntentDeferred = 0;
|
|
29722
|
+
/** Of those, fast-model replies that voiced inability ("I can't check...") — never spoken; the ack is spoken instead. */
|
|
29723
|
+
fastPathRefusalDeferred = 0;
|
|
29707
29724
|
/**
|
|
29708
29725
|
* Task 8: count of live AUTHENTICATED /v1/ws sessions, so a later `status`
|
|
29709
29726
|
* verb can tell "bridge process up" (the app's green dot, which only
|
|
@@ -31981,11 +31998,15 @@ var BridgeAgent = class _BridgeAgent {
|
|
|
31981
31998
|
});
|
|
31982
31999
|
const maxSentences = this.voiceSettings?.brevity === "one" ? 1 : 2;
|
|
31983
32000
|
const raw = await this.latency.time("voice.fast_llm", () => fastLlm.complete(messages));
|
|
31984
|
-
const
|
|
31985
|
-
if (!reply) return "failed";
|
|
32001
|
+
const split3 = splitFastReply(raw, 200, maxSentences);
|
|
32002
|
+
if (!split3.reply) return "failed";
|
|
32003
|
+
const refusal = !isGreeting && isRefusal(split3.reply);
|
|
32004
|
+
const defer = split3.defer || refusal;
|
|
32005
|
+
const reply = refusal ? deferAck(m.messageId) : split3.reply;
|
|
31986
32006
|
await this.sendSpoken(m.channelId, reply, fastReplyId(this.replyIdKey, this.cfg.identityId, m.channelId, m.messageId));
|
|
31987
32007
|
this.fastPathSent++;
|
|
31988
32008
|
if (defer) this.fastPathDeferred++;
|
|
32009
|
+
if (refusal) this.fastPathRefusalDeferred++;
|
|
31989
32010
|
return defer ? "deferred" : "answered";
|
|
31990
32011
|
} catch (e) {
|
|
31991
32012
|
this.fastPathFailed++;
|
|
@@ -33937,6 +33958,7 @@ var BridgeAgent = class _BridgeAgent {
|
|
|
33937
33958
|
fast_path_skipped: this.fastPathSkipped,
|
|
33938
33959
|
fast_path_deferred: this.fastPathDeferred,
|
|
33939
33960
|
fast_path_intent_deferred: this.fastPathIntentDeferred,
|
|
33961
|
+
fast_path_refusal_deferred: this.fastPathRefusalDeferred,
|
|
33940
33962
|
fast_path_mode: this.cfg.voiceFastPathMode ?? "full",
|
|
33941
33963
|
voice_settings_version: this.voiceSettingsVersion,
|
|
33942
33964
|
voice_settings_source: this.voiceSettingsSource,
|
package/dist/bridge-agent.d.ts
CHANGED
|
@@ -800,6 +800,8 @@ export declare class BridgeAgent {
|
|
|
800
800
|
private fastPathDeferred;
|
|
801
801
|
/** Of those, `full`-mode turns the deterministic pre-check deferred without calling the fast model. */
|
|
802
802
|
private fastPathIntentDeferred;
|
|
803
|
+
/** Of those, fast-model replies that voiced inability ("I can't check...") — never spoken; the ack is spoken instead. */
|
|
804
|
+
private fastPathRefusalDeferred;
|
|
803
805
|
/**
|
|
804
806
|
* Task 8: count of live AUTHENTICATED /v1/ws sessions, so a later `status`
|
|
805
807
|
* verb can tell "bridge process up" (the app's green dot, which only
|
|
@@ -2344,6 +2346,8 @@ export declare class BridgeAgent {
|
|
|
2344
2346
|
fast_path_deferred: number;
|
|
2345
2347
|
/** `full`-mode turns deferred by the deterministic pre-check (no fast model call). */
|
|
2346
2348
|
fast_path_intent_deferred: number;
|
|
2349
|
+
/** Fast-model replies that voiced inability/lack of tools: never spoken, deferred behind the canned ack instead. */
|
|
2350
|
+
fast_path_refusal_deferred: number;
|
|
2347
2351
|
/** Credential `voice_fast_path_mode`: "full" (default), "ack_only" or "off". */
|
|
2348
2352
|
fast_path_mode: "full" | "ack_only" | "off";
|
|
2349
2353
|
/** Plan 2026-09-06 (agent voice settings): version of the loaded backend
|
package/dist/index.js
CHANGED
|
@@ -28288,11 +28288,26 @@ function clampContent(content, max = MAX_MESSAGE_CHARS) {
|
|
|
28288
28288
|
const marker = "\u2026";
|
|
28289
28289
|
return content.slice(0, Math.max(0, max - marker.length)) + marker;
|
|
28290
28290
|
}
|
|
28291
|
+
var FAST_DEFER_RULE = `Whenever you cannot answer completely from what is shown here, never say you can't, that you lack a tool, access or real-time data: reply with one short sentence like "Let me check that." and end with the exact token [[DEFER]] so the full agent answers next.`;
|
|
28292
|
+
var REFUSAL_PATTERNS = [
|
|
28293
|
+
// "I can't / cannot / am unable to / am not able to <check|access|...>", optional adverb.
|
|
28294
|
+
/\b(?:can't|cannot|can\s+not|unable\s+to|not\s+able\s+to)\s+(?:\w+ly\s+)?(?:check|access|look|see|browse|search|get|provide|give\s+you|find|retrieve|fetch|pull|know|help\s+with\s+(?:that|this)|do\s+that)\b/,
|
|
28295
|
+
// "I don't / do not / doesn't have (a|any|the)? <tool|access|ability|real-time|live ...>".
|
|
28296
|
+
/\b(?:don't|do\s+not|doesn't|does\s+not|lack)\s+(?:have\s+)?(?:a\s+|any\s+|the\s+)?(?:tool|tools|access|ability|capability|real[-\s]?time|live|current|internet|web|way\s+to)\b/,
|
|
28297
|
+
/\bno\s+(?:access|tools?|internet|web\s+access|real[-\s]?time|live\s+data|way\s+to\s+(?:check|access|know|see))\b/,
|
|
28298
|
+
/\bas\s+an\s+(?:ai|a\.i\.|language\s+model)\b/,
|
|
28299
|
+
/\bbeyond\s+my\s+(?:capabilities|abilities|capability)\b/,
|
|
28300
|
+
/\b(?:knowledge\s+cutoff|training\s+data)\b/
|
|
28301
|
+
];
|
|
28302
|
+
function isRefusal(reply) {
|
|
28303
|
+
const t = reply.toLowerCase().replace(/[‘’]/g, "'");
|
|
28304
|
+
return REFUSAL_PATTERNS.some((re) => re.test(t));
|
|
28305
|
+
}
|
|
28291
28306
|
function buildFastMessages(args2) {
|
|
28292
28307
|
const cap = args2.charCap ?? FAST_RECENT_CHARS_CAP;
|
|
28293
28308
|
const sp = systemPrompt(args2.persona, args2.settings, args2.agentName);
|
|
28294
28309
|
const head = sp.slice(0, sp.length - CONTINUITY_CLAUSE.length).trimEnd();
|
|
28295
|
-
const system = `${head} ${args2.guidance.trim()} ${CONTINUITY_CLAUSE}`;
|
|
28310
|
+
const system = `${head} ${args2.guidance.trim()} ${FAST_DEFER_RULE} ${CONTINUITY_CLAUSE}`;
|
|
28296
28311
|
const recent = args2.memory.recent.map((t) => ({
|
|
28297
28312
|
role: t.role === "agent" ? "assistant" : "user",
|
|
28298
28313
|
content: t.text
|
|
@@ -29552,6 +29567,8 @@ var BridgeAgent = class _BridgeAgent {
|
|
|
29552
29567
|
fastPathDeferred = 0;
|
|
29553
29568
|
/** Of those, `full`-mode turns the deterministic pre-check deferred without calling the fast model. */
|
|
29554
29569
|
fastPathIntentDeferred = 0;
|
|
29570
|
+
/** Of those, fast-model replies that voiced inability ("I can't check...") — never spoken; the ack is spoken instead. */
|
|
29571
|
+
fastPathRefusalDeferred = 0;
|
|
29555
29572
|
/**
|
|
29556
29573
|
* Task 8: count of live AUTHENTICATED /v1/ws sessions, so a later `status`
|
|
29557
29574
|
* verb can tell "bridge process up" (the app's green dot, which only
|
|
@@ -31829,11 +31846,15 @@ var BridgeAgent = class _BridgeAgent {
|
|
|
31829
31846
|
});
|
|
31830
31847
|
const maxSentences = this.voiceSettings?.brevity === "one" ? 1 : 2;
|
|
31831
31848
|
const raw = await this.latency.time("voice.fast_llm", () => fastLlm.complete(messages));
|
|
31832
|
-
const
|
|
31833
|
-
if (!reply) return "failed";
|
|
31849
|
+
const split3 = splitFastReply(raw, 200, maxSentences);
|
|
31850
|
+
if (!split3.reply) return "failed";
|
|
31851
|
+
const refusal = !isGreeting && isRefusal(split3.reply);
|
|
31852
|
+
const defer = split3.defer || refusal;
|
|
31853
|
+
const reply = refusal ? deferAck(m.messageId) : split3.reply;
|
|
31834
31854
|
await this.sendSpoken(m.channelId, reply, fastReplyId(this.replyIdKey, this.cfg.identityId, m.channelId, m.messageId));
|
|
31835
31855
|
this.fastPathSent++;
|
|
31836
31856
|
if (defer) this.fastPathDeferred++;
|
|
31857
|
+
if (refusal) this.fastPathRefusalDeferred++;
|
|
31837
31858
|
return defer ? "deferred" : "answered";
|
|
31838
31859
|
} catch (e) {
|
|
31839
31860
|
this.fastPathFailed++;
|
|
@@ -33785,6 +33806,7 @@ var BridgeAgent = class _BridgeAgent {
|
|
|
33785
33806
|
fast_path_skipped: this.fastPathSkipped,
|
|
33786
33807
|
fast_path_deferred: this.fastPathDeferred,
|
|
33787
33808
|
fast_path_intent_deferred: this.fastPathIntentDeferred,
|
|
33809
|
+
fast_path_refusal_deferred: this.fastPathRefusalDeferred,
|
|
33788
33810
|
fast_path_mode: this.cfg.voiceFastPathMode ?? "full",
|
|
33789
33811
|
voice_settings_version: this.voiceSettingsVersion,
|
|
33790
33812
|
voice_settings_source: this.voiceSettingsSource,
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const BRIDGE_VERSION = "0.26.
|
|
1
|
+
export declare const BRIDGE_VERSION = "0.26.4";
|
|
@@ -29,6 +29,15 @@ export declare const MAX_MESSAGE_CHARS = 8000;
|
|
|
29
29
|
export declare const FAST_PATH_MEMORY_TURNS = 10;
|
|
30
30
|
export declare const FAST_RECENT_CHARS_CAP = 1500;
|
|
31
31
|
export declare const FAST_FACTS_CHARS_CAP = 2000;
|
|
32
|
+
/**
|
|
33
|
+
* Live bug 2026-10-02 (bridge 0.26.3): asked for Sydney's weather, the fast
|
|
34
|
+
* model said "I can't check the weather right now since I don't have a
|
|
35
|
+
* tool..." with no [[DEFER]], so the runtime (which has web_search) never got
|
|
36
|
+
* the turn. Placed last before the continuity clause so it is the final rule
|
|
37
|
+
* the model reads. Compiled in, never interpolated with peer data.
|
|
38
|
+
*/
|
|
39
|
+
export declare const FAST_DEFER_RULE: string;
|
|
40
|
+
export declare function isRefusal(reply: string): boolean;
|
|
32
41
|
export declare function buildFastMessages(args: {
|
|
33
42
|
persona: VoicePersona;
|
|
34
43
|
guidance: string;
|