@inetafrica/open-claudia 3.0.14 → 3.0.15
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v3.0.15 — the owner keeps their memory on Kazee
|
|
4
|
+
|
|
5
|
+
- **Episodic recall no longer goes dark on Kazee / group chats.** Cross-conversation episodic memory (relevant snippets from the owner's past transcripts) is deliberately owner-only. The gate that decides "is this speaker the owner?" resolved the person by `findByHandle(adapter, channelId)` — but on Kazee the `channelId` is the *chat/room id*, while the owner's stored handle is their Kazee *user id*, so the lookup missed and fail-closed suppressed episodes. The owner's canonical brain, settings, and session were shared via identity unification, but this one recall layer silently went quiet — which read as "less context on Kazee." The gate now resolves the speaker by the envelope's **canonical user id** first (derived from the authenticated sender and unified across a person's linked channels), falling back to the channelId handle lookup when no canonical is in context. Fail-closed semantics for non-owners are preserved: a non-owner's canonical never matches an owner record. Regression pinned in `test-recall-relationship-gate.js` (owner recognised via canonical on a room-id channel; external still blocked).
|
|
6
|
+
- **Agent-space / OpenClaw:** no new deps, no new env, no schema change; Docker image builds identically (FROM the pre-baked `:base`). Existing pods pick this up on their next approved upgrade.
|
|
7
|
+
|
|
3
8
|
## v3.0.14 — the Telegram poll stops wedging, and every reboot says why
|
|
4
9
|
|
|
5
10
|
- **Root-cause fix for the restart flap.** In the cluster, DNS hands back a dead IPv6 address for `api.telegram.org` first and IPv6 egress is unreachable; under Node's default `verbatim` resolution the long-poll dials the dead address first (a latency penalty always, and a hard wedge on any AAAA-only window). `bot.js` now sets `dns.setDefaultResultOrder("ipv4first")` before any socket opens, eliminating that path for every request the process makes.
|
|
@@ -109,12 +109,21 @@ const EXCERPT_CHARS = 600;
|
|
|
109
109
|
// e.g. CLI/tests) may pull them. Same-conversation packs/entities are unaffected.
|
|
110
110
|
function episodesAllowedForSpeaker() {
|
|
111
111
|
try {
|
|
112
|
-
const { currentAdapter, currentChannelId } = require("../context");
|
|
112
|
+
const { currentAdapter, currentChannelId, currentCanonicalUserId } = require("../context");
|
|
113
113
|
const adapter = currentAdapter();
|
|
114
114
|
const channelId = currentChannelId();
|
|
115
115
|
if (!adapter || !channelId) return true; // no speaker context (CLI/tests) → ungated
|
|
116
116
|
const people = require("../people");
|
|
117
|
-
|
|
117
|
+
// Resolve the speaker by canonical user id first. On transports where the
|
|
118
|
+
// channelId is a room/chat id rather than the sender's user id (Kazee, group
|
|
119
|
+
// chats), a handle lookup keyed on channelId misses the owner and fails
|
|
120
|
+
// closed — silently starving them of episodic recall. The canonical id is
|
|
121
|
+
// derived from the authenticated sender and is unified across a person's
|
|
122
|
+
// linked channels, so it recognises the owner on every transport. Falls back
|
|
123
|
+
// to the channelId handle lookup when no canonical is in context.
|
|
124
|
+
const canonical = currentCanonicalUserId();
|
|
125
|
+
const speaker = (canonical && people.findByCanonicalUserId(canonical))
|
|
126
|
+
|| people.findByHandle(adapter.type, channelId);
|
|
118
127
|
return !!(speaker && speaker.isOwner); // unknown/non-owner → gated
|
|
119
128
|
} catch (e) {
|
|
120
129
|
return false; // resolution error → fail closed
|
package/package.json
CHANGED
|
@@ -32,12 +32,11 @@ assert.doesNotMatch(setup, /Your Claude Code bot is connected|Description=Claude
|
|
|
32
32
|
|
|
33
33
|
const pkg = JSON.parse(read("package.json"));
|
|
34
34
|
assert.match(pkg.description, /provider-agnostic coding-agent harness/i);
|
|
35
|
-
// 3.0.
|
|
36
|
-
//
|
|
37
|
-
// the
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
assert.strictEqual(pkg.version, "3.0.14", "release version must remain unchanged without explicit approval");
|
|
35
|
+
// 3.0.15 approved by Sumeet 2026-07-14 ("Yes fix and push"): episodic-recall
|
|
36
|
+
// owner gate now resolves the speaker by canonical user id (not raw channelId),
|
|
37
|
+
// so the owner keeps cross-conversation episodic memory on Kazee / group chats
|
|
38
|
+
// where channelId is a room id that never matches the stored user-id handle.
|
|
39
|
+
assert.strictEqual(pkg.version, "3.0.15", "release version must remain unchanged without explicit approval");
|
|
41
40
|
for (const keyword of ["claude", "codex", "coding-agent", "provider-agnostic"]) {
|
|
42
41
|
assert.ok(pkg.keywords.includes(keyword), `package keyword missing: ${keyword}`);
|
|
43
42
|
}
|
|
@@ -39,4 +39,25 @@ assert.strictEqual(inChat("222", () => episodesAllowedForSpeaker()), false, "ext
|
|
|
39
39
|
// Unknown channel (no person record) → fail closed.
|
|
40
40
|
assert.strictEqual(inChat("999", () => episodesAllowedForSpeaker()), false, "unknown speaker → episodes blocked");
|
|
41
41
|
|
|
42
|
+
// Kazee / group case: the channelId is a room/chat id that does NOT match the
|
|
43
|
+
// owner's stored handle, but the envelope carries the owner's unified canonical
|
|
44
|
+
// id. Resolving by canonical must recognise the owner even though a handle
|
|
45
|
+
// lookup on the room id misses — otherwise the owner silently loses episodic
|
|
46
|
+
// recall on those transports (the Kazee "less context" regression).
|
|
47
|
+
const withCanon = (channelId, canonicalUserId, fn) =>
|
|
48
|
+
runInChat({ adapter, channelId, canonicalUserId, transport: "telegram" }, fn);
|
|
49
|
+
const ownerCanon = people.findById(owner.id).handles[0].canonicalUserId;
|
|
50
|
+
assert.strictEqual(
|
|
51
|
+
withCanon("room-xyz", ownerCanon, () => episodesAllowedForSpeaker()),
|
|
52
|
+
true,
|
|
53
|
+
"owner via canonical on a room-id channel → episodes allowed (Kazee/group regression)",
|
|
54
|
+
);
|
|
55
|
+
// A non-owner on a room-id channel with their own canonical stays blocked.
|
|
56
|
+
const extCanon = people.findById(ext.id).handles[0].canonicalUserId;
|
|
57
|
+
assert.strictEqual(
|
|
58
|
+
withCanon("room-abc", extCanon, () => episodesAllowedForSpeaker()),
|
|
59
|
+
false,
|
|
60
|
+
"external via canonical → episodes still blocked",
|
|
61
|
+
);
|
|
62
|
+
|
|
42
63
|
console.log("recall relationship gate OK");
|