@essentialai/cogent-plugin 3.20.3 → 3.20.5
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.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cogent",
|
|
3
|
-
"version": "3.20.
|
|
3
|
+
"version": "3.20.5",
|
|
4
4
|
"description": "Inter-session communication bridge for Claude Code with Slack integration. Enables CC agents and Slack team members to communicate in real time.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Essential AI Solutions",
|
package/bridge/cogent-bridge.mjs
CHANGED
|
@@ -26389,8 +26389,8 @@ var init_stdio2 = __esm({
|
|
|
26389
26389
|
// src/constants.ts
|
|
26390
26390
|
import { createRequire } from "node:module";
|
|
26391
26391
|
function resolveVersion() {
|
|
26392
|
-
if ("3.20.
|
|
26393
|
-
return "3.20.
|
|
26392
|
+
if ("3.20.5") {
|
|
26393
|
+
return "3.20.5";
|
|
26394
26394
|
}
|
|
26395
26395
|
try {
|
|
26396
26396
|
const require2 = createRequire(import.meta.url);
|
|
@@ -98,6 +98,21 @@ export function selectUnanswered({ messages, me, scope }) {
|
|
|
98
98
|
// My message (a reply or my own auto-relay echo) answers a pending item.
|
|
99
99
|
// A directed reply clears that sender's oldest; a broadcast reply clears
|
|
100
100
|
// only the oldest pending BROADCAST (never a directed message).
|
|
101
|
+
//
|
|
102
|
+
// COG-20: EXCEPT a meta-non-answer. When the real-time wake's capture fails, the agent
|
|
103
|
+
// sees its own (undelivered) answer plus this hook saying "unanswered", and resolves the
|
|
104
|
+
// contradiction by sending "Already answered… no duplicate sent." That is not an answer —
|
|
105
|
+
// but because this pairing used to clear on ANY outbound, it marked the message answered
|
|
106
|
+
// and silenced the alarm FOREVER, so the human only ever saw the meta-message. Skipping it
|
|
107
|
+
// here keeps the message pending until a real answer is sent.
|
|
108
|
+
//
|
|
109
|
+
// Same defect, second instance: rail B records its OWN failure notice ("Cogent could not
|
|
110
|
+
// capture a reply…" / "📨 Queued for …") as a message FROM me with success:false. Counting
|
|
111
|
+
// that as an answer would make C blind to exactly the miss C exists to catch. A record that
|
|
112
|
+
// is explicitly a failure is never an answer — check that first, it is stronger than any
|
|
113
|
+
// string match.
|
|
114
|
+
if (m.success === false || m.error) continue;
|
|
115
|
+
if (isMetaNonAnswer(m.message)) continue;
|
|
101
116
|
if (m.toPeerId === "*") dequeueOldestBroadcast();
|
|
102
117
|
else dequeueFrom(m.toPeerId);
|
|
103
118
|
continue;
|
|
@@ -113,6 +128,27 @@ export function selectUnanswered({ messages, me, scope }) {
|
|
|
113
128
|
return { items: items.map(({ _i, ...m }) => m) };
|
|
114
129
|
}
|
|
115
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Is this outbound of mine a "meta non-answer" — a note ABOUT answering rather than an answer?
|
|
133
|
+
* (COG-20)
|
|
134
|
+
*
|
|
135
|
+
* Real observed values that reached a human instead of the answer:
|
|
136
|
+
* "Already answered through the automatic Slack relay. No duplicate sent."
|
|
137
|
+
* "Already answered through the automatic Slack relay with live Jira and repository status. …"
|
|
138
|
+
*
|
|
139
|
+
* Deliberately CONSERVATIVE — it must not swallow a genuine answer that happens to contain the
|
|
140
|
+
* words "already answered". Two gates: the text must be SHORT (real answers carry substance; every
|
|
141
|
+
* observed meta-message was < 120 chars) AND match the pattern. A false negative just restores the
|
|
142
|
+
* old behaviour; a false positive would re-nag the agent into sending a duplicate, so short-only.
|
|
143
|
+
* An empty reply is always a non-answer.
|
|
144
|
+
*/
|
|
145
|
+
export function isMetaNonAnswer(text) {
|
|
146
|
+
const t = String(text ?? "").replace(/\s+/g, " ").trim().toLowerCase();
|
|
147
|
+
if (!t) return true;
|
|
148
|
+
if (t.length > 200) return false; // long enough to carry a real answer — never suppress it
|
|
149
|
+
return /already (answered|replied|responded|sent|handled)|no duplicate|duplicate (not )?sent|answered (already|via|through)|responded (already|via|through)/.test(t);
|
|
150
|
+
}
|
|
151
|
+
|
|
116
152
|
/** Build the { decision: "block" } reason string handed back to the agent. */
|
|
117
153
|
export function buildBlockReason(items, { firstUse }) {
|
|
118
154
|
const n = items.length;
|
|
@@ -120,11 +156,21 @@ export function buildBlockReason(items, { firstUse }) {
|
|
|
120
156
|
const snippet = String(m.message || "").replace(/\s+/g, " ").slice(0, 120);
|
|
121
157
|
return ` - from ${m.fromPeerId}${m.toPeerId === "*" ? " (channel)" : ""}: ${snippet}`;
|
|
122
158
|
});
|
|
159
|
+
// COG-20: the wording matters as much as the detection. The previous text ended with "Do not
|
|
160
|
+
// repeat work you already did this turn", which — combined with the real-time wake prompt telling
|
|
161
|
+
// the agent NOT to call cogent_send_message — pushed the agent to answer with a meta-message
|
|
162
|
+
// ("Already answered… no duplicate sent") instead of the substance. It had in fact answered; the
|
|
163
|
+
// capture just never delivered it. So: state plainly that nothing was delivered, and demand the
|
|
164
|
+
// answer itself.
|
|
123
165
|
let reason =
|
|
124
|
-
`You have ${n} unanswered Cogent message${n === 1 ? "" : "s"}
|
|
166
|
+
`You have ${n} unanswered Cogent message${n === 1 ? "" : "s"} — the channel has NO recorded reply ` +
|
|
167
|
+
`from you${n === 1 ? "" : " for these"}:\n` +
|
|
125
168
|
lines.join("\n") +
|
|
126
|
-
`\n\
|
|
127
|
-
`
|
|
169
|
+
`\n\nIf you already composed an answer this turn, it was NOT delivered — sending it again is ` +
|
|
170
|
+
`correct, not a duplicate. Read the channel with cogent_get_history if you need context, then ` +
|
|
171
|
+
`reply with the ANSWER ITSELF via cogent_send_message (or spawn a Task sub-agent) and continue. ` +
|
|
172
|
+
`NEVER reply with a note about having already answered (e.g. "already answered", "no duplicate ` +
|
|
173
|
+
`sent") — that is not an answer, and it is all the sender will ever see.`;
|
|
128
174
|
if (firstUse) {
|
|
129
175
|
reason +=
|
|
130
176
|
`\n\n(Cogent auto-check is on: it catches messages that arrive while you're busy. ` +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@essentialai/cogent-plugin",
|
|
3
|
-
"version": "3.20.
|
|
3
|
+
"version": "3.20.5",
|
|
4
4
|
"description": "Cogent — Claude Code plugin (skills + slash-commands + MCP server) for the cross-agent comms fabric.",
|
|
5
5
|
"author": { "name": "Essential AI Solutions Ltd.", "url": "https://essentialai.uk" },
|
|
6
6
|
"homepage": "https://cogent.tools",
|