@inetafrica/open-claudia 3.4.2 → 3.4.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/CHANGELOG.md +18 -0
- package/channels/kazee/adapter.js +27 -0
- package/core/handlers.js +8 -5
- package/core/run-context.js +9 -1
- package/core/runner.js +13 -1
- package/core/state.js +37 -2
- package/package.json +3 -3
- package/test-provider-gateway.js +3 -0
- package/test-provider-language.js +27 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v3.4.4 — The room's model was saved, shown, and never once used
|
|
4
|
+
|
|
5
|
+
- **A model pinned in a room was silently ignored by every turn in it.** `/model` wrote the choice to the room, `/status` read it back from the room, and the picker highlighted it — all three already room-aware. Only the code that actually launches the provider was not: `captureRunContext` read `state.providerSettings[provider]`, the *speaker's* own bucket, so the room's pinned model was never consulted. The setting looked applied everywhere a human could look while every turn ran the personal default.
|
|
6
|
+
- **This was a v3.4.0 regression, not a long-standing bug.** `run-context.js` dates from 10 Jul, when the speaker's bucket was the only scope that existed and reading it directly was correct. v3.4.0 introduced rooms and the room-aware resolver but never revisited that read. Channels without a room are unaffected — the resolver returns the same personal bucket there.
|
|
7
|
+
- **Three more call sites had the same shape.** `applyProviderSetting` wrote `/effort`, `/budget`, `/plan` and `/worktree` to the speaker instead of the room; the provider-switch payload reported the speaker's bucket; and usage records attributed the wrong model, so cost accounting named a model the turn never ran on.
|
|
8
|
+
- **`getProviderSettings` was not identity-stable.** It rebuilt the bucket (`{ ...defaults, ...bucket }`) and assigned it back on every call, so any caller holding the previous reference wrote into a detached copy that was then discarded. Nothing depended on the rebuild; it now backfills missing defaults in place.
|
|
9
|
+
- **Reads must not mutate.** Routing the run-context read through `getProviderSettings` made merely capturing a turn seed room buckets into `savedState` — side-chat execution began mutating main state. Reads now go through a new pure `resolveProviderSettings`, which creates nothing; the mutating accessor is reserved for the setter that genuinely needs the live object.
|
|
10
|
+
- `test-room-provider-settings.js` pins the behaviour and was verified to FAIL against unmodified code with exactly the reported symptom — `got "personal-default-model", expected "room-pinned-model"` — and also pins that an unpinned room does not inherit another room's choice.
|
|
11
|
+
|
|
12
|
+
- **Kazee replied to everything twice.** chat-central fans `message:new` out to both `chatId` and each participant's `user:<id>` room so delivery survives a failed join. The bot only ever sat in its own user room until v3.4.2 joined chat rooms for the typing indicator — which put it in both, so every inbound message was handled twice and `/model` answered with two identical pickers. The join is correct; the missing half was the id-dedupe every other client already does. Inbound ids are now remembered (bounded, oldest evicted); an id-less message is still let through rather than silently swallowed.
|
|
13
|
+
|
|
14
|
+
## v3.4.3 — The chip knew it had started typing; nobody asked it in time
|
|
15
|
+
|
|
16
|
+
- **v3.4.2 restored the indicator and immediately exposed a second bug underneath it.** With delivery fixed, the chip reached the client — and then sat on "thinking" for the whole turn and stopped, never showing "typing". Same symptom, different layer: 3.4.2 was DELIVERY, this is CONTENT.
|
|
17
|
+
- **The phase was pushed by events but only read by a timer.** `onEvent` flips `state.thinkingPhase` correctly (`text_delta` → typing, `tool_start` → thinking), but `startTypingHeartbeat` re-read that flag on a 4s interval. An agentic turn spends nearly all of its time in tool calls, then streams its final answer and finishes — routinely inside one interval. So no tick ever sampled the flag while it was false, and the one state the user was waiting to see was the one state never transmitted. A slow, chatty turn would show it; the common case never did.
|
|
18
|
+
- **Transitions now push.** `state.typingTick` fires on an actual phase change, guarded so a long stream emits one frame rather than one per delta, and the stopper clears the pusher so a stale tick cannot outlive its turn (the same ownership discipline the heartbeat's stopper already used).
|
|
19
|
+
- `test-typing-phase-push.js` pins the sequence and was verified to FAIL against unmodified code with precisely the reported symptom — `["thinking"]` where `["thinking", "typing"]` was expected — rather than merely passing against the fix.
|
|
20
|
+
|
|
3
21
|
## v3.4.2 — The bot was typing into a room it had never joined
|
|
4
22
|
|
|
5
23
|
- **The typing and thinking indicators had been dead since 2026-08-23, and nothing said so.** chat-central `7aa9276` ("authorize typing") made `handleTypingStart` return early unless the sending socket had joined that chat's Socket.IO room — a correct fix, since `socket.to(chatId)` addresses a room by name and would otherwise let any authenticated user inject an indicator into any chat whose id they knew. But the Kazee adapter only ever joined the bot's own user room, which is how `message:new` reaches it. So messages kept flowing while every `typing:start` was discarded server-side, which is exactly why this read as a rendering bug in the web client.
|
|
@@ -24,6 +24,15 @@ const kazeeState = require("./state");
|
|
|
24
24
|
// late is worth less than the next heartbeat tick, which retries the join.
|
|
25
25
|
const KAZEE_JOIN_ACK_TIMEOUT_MS = 5000;
|
|
26
26
|
|
|
27
|
+
// chat-central deliberately fans message:new out TWICE to anyone in the chat
|
|
28
|
+
// room: once via to(chatId) and again via to(`user:<id>`) per participant, so
|
|
29
|
+
// delivery survives a failed room join (see broadcastBridge). Ordinary clients
|
|
30
|
+
// dedupe by message id; the bot never had to, because until it joined chat
|
|
31
|
+
// rooms for the typing indicator it only ever sat in its own user room. How
|
|
32
|
+
// many ids to remember: large enough to cover a burst, small enough to stay
|
|
33
|
+
// trivial to scan.
|
|
34
|
+
const INBOUND_DEDUP_MEMORY = 500;
|
|
35
|
+
|
|
27
36
|
const CONTEXT_MAX_MESSAGES = 40;
|
|
28
37
|
const CONTEXT_BODY_LIMIT = 280;
|
|
29
38
|
const COLD_START_WINDOW = 15;
|
|
@@ -71,6 +80,8 @@ class KazeeAdapter {
|
|
|
71
80
|
// on every (re)connect.
|
|
72
81
|
this._joinedRooms = new Set();
|
|
73
82
|
this._joinPending = new Map();
|
|
83
|
+
// Insertion-ordered, so the oldest id is always the first key.
|
|
84
|
+
this._seenMessageIds = new Set();
|
|
74
85
|
this._callManager = new KazeeCallManager({ adapter: this });
|
|
75
86
|
}
|
|
76
87
|
|
|
@@ -186,8 +197,24 @@ class KazeeAdapter {
|
|
|
186
197
|
});
|
|
187
198
|
}
|
|
188
199
|
|
|
200
|
+
// True the SECOND time a message id is seen. An id-less message is always
|
|
201
|
+
// let through: dropping every one of them would silently swallow real
|
|
202
|
+
// traffic, and the duplicate pair we are guarding against always carries an
|
|
203
|
+
// id (it is the same persisted document emitted down two paths).
|
|
204
|
+
_isDuplicateInbound(msg) {
|
|
205
|
+
const id = String(msg._id || msg.id || "");
|
|
206
|
+
if (!id) return false;
|
|
207
|
+
if (this._seenMessageIds.has(id)) return true;
|
|
208
|
+
this._seenMessageIds.add(id);
|
|
209
|
+
if (this._seenMessageIds.size > INBOUND_DEDUP_MEMORY) {
|
|
210
|
+
this._seenMessageIds.delete(this._seenMessageIds.values().next().value);
|
|
211
|
+
}
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
|
|
189
215
|
async _handleInboundMessage(msg) {
|
|
190
216
|
if (!msg) return;
|
|
217
|
+
if (this._isDuplicateInbound(msg)) return;
|
|
191
218
|
const senderId = String(msg.sender?._id || msg.sender?.id || msg.senderId || "");
|
|
192
219
|
if (this.botUserId && senderId === String(this.botUserId)) return; // ignore our own echoes
|
|
193
220
|
const chatField = msg.chat;
|
package/core/handlers.js
CHANGED
|
@@ -17,7 +17,7 @@ const { currentAdapter, currentChannelId } = require("./context");
|
|
|
17
17
|
const {
|
|
18
18
|
currentState, saveState, rootSession,
|
|
19
19
|
freshUsage, getActiveProvider, getProjectKey, getProviderSession, setProviderSession, clearProviderSession,
|
|
20
|
-
getProviderSettings,
|
|
20
|
+
getProviderSettings, resolveProviderSettings,
|
|
21
21
|
getProjectSessions, getLastProjectSession, userOwnsProviderSession,
|
|
22
22
|
createSessionCallbackToken, linkIdentity,
|
|
23
23
|
roomSettingsFor, setRoomSetting,
|
|
@@ -176,7 +176,10 @@ function applyProviderSetting(state, providerId, setting, value, options = {}) {
|
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
|
|
179
|
+
// Room-aware: a setting changed inside a room lands on the room, so every
|
|
180
|
+
// speaker there gets the same assistant. Preferring the raw personal bucket
|
|
181
|
+
// here wrote /effort, /budget and /plan to the speaker instead.
|
|
182
|
+
const settings = getProviderSettings(state, provider.id);
|
|
180
183
|
const previous = settings[setting];
|
|
181
184
|
settings[setting] = normalized;
|
|
182
185
|
if (options.persist) {
|
|
@@ -232,7 +235,7 @@ function switchProviderState(providerId, options = {}) {
|
|
|
232
235
|
state.isFirstMessage = previous.isFirstMessage;
|
|
233
236
|
});
|
|
234
237
|
return persisted.ok
|
|
235
|
-
? { ok: true, provider, sessionId: getProviderSession(state, provider, project), settings: state
|
|
238
|
+
? { ok: true, provider, sessionId: getProviderSession(state, provider, project), settings: resolveProviderSettings(state, provider) }
|
|
236
239
|
: persisted;
|
|
237
240
|
}
|
|
238
241
|
|
|
@@ -1622,7 +1625,7 @@ register({
|
|
|
1622
1625
|
if (state.streamInterval) { clearTimeout(state.streamInterval); state.streamInterval = null; }
|
|
1623
1626
|
// Clearing the interval here orphans the run's own stopper (ownership
|
|
1624
1627
|
// check makes it a no-op), so the explicit typing:stop must go out now.
|
|
1625
|
-
if (state.typingHeartbeat) { clearInterval(state.typingHeartbeat); state.typingHeartbeat = null; state.thinkingPhase = false; }
|
|
1628
|
+
if (state.typingHeartbeat) { clearInterval(state.typingHeartbeat); state.typingHeartbeat = null; state.thinkingPhase = false; state.typingTick = null; }
|
|
1626
1629
|
try { currentAdapter()?.typingStop?.(currentChannelId()); } catch (_) {}
|
|
1627
1630
|
await sideCancellation;
|
|
1628
1631
|
await send(`Cancelled.${queuedNote()}`);
|
|
@@ -1630,7 +1633,7 @@ register({
|
|
|
1630
1633
|
// Turn is mid-recall/prompt-build — no process to kill yet. Flag it so
|
|
1631
1634
|
// the runner's pre-spawn shouldAbort checkpoint bails before spawning.
|
|
1632
1635
|
state.cancelRequested = true;
|
|
1633
|
-
if (state.typingHeartbeat) { clearInterval(state.typingHeartbeat); state.typingHeartbeat = null; state.thinkingPhase = false; }
|
|
1636
|
+
if (state.typingHeartbeat) { clearInterval(state.typingHeartbeat); state.typingHeartbeat = null; state.thinkingPhase = false; state.typingTick = null; }
|
|
1634
1637
|
try { currentAdapter()?.typingStop?.(currentChannelId()); } catch (_) {}
|
|
1635
1638
|
await sideCancellation;
|
|
1636
1639
|
await send(`Cancelled.${queuedNote()}`);
|
package/core/run-context.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const crypto = require("crypto");
|
|
4
4
|
const path = require("path");
|
|
5
5
|
const { currentConversationKey } = require("./context");
|
|
6
|
+
const { resolveProviderSettings } = require("./state");
|
|
6
7
|
|
|
7
8
|
function cloneSerializable(value, label = "run context value") {
|
|
8
9
|
if (value === undefined) return undefined;
|
|
@@ -109,8 +110,15 @@ function captureRunContext({
|
|
|
109
110
|
const resolvedChannelId = channelId != null
|
|
110
111
|
? String(channelId)
|
|
111
112
|
: (origin.channelId || (state.channelId != null ? String(state.channelId) : null));
|
|
113
|
+
// Inside a room the model/effort/budget belong to the room, not to whoever
|
|
114
|
+
// happens to be speaking, so this must go through the room-aware resolver.
|
|
115
|
+
// Reading `state.providerSettings[provider]` directly took the speaker's own
|
|
116
|
+
// bucket and silently ignored a room's pinned model: the picker saved it and
|
|
117
|
+
// /status reported it (both already room-aware) while every turn still ran
|
|
118
|
+
// the personal default. Outside a room the resolver returns that same
|
|
119
|
+
// personal bucket, so non-room channels are unaffected.
|
|
112
120
|
const providerSettings = cloneSerializable({
|
|
113
|
-
...(state
|
|
121
|
+
...(resolveProviderSettings(state, provider) || {}),
|
|
114
122
|
...(opts.providerSettings || {}),
|
|
115
123
|
}, "provider settings");
|
|
116
124
|
delete providerSettings.backend;
|
package/core/runner.js
CHANGED
|
@@ -15,6 +15,7 @@ const {
|
|
|
15
15
|
currentState, saveState, recordSession,
|
|
16
16
|
resetSessionUsage, acquireRunLock, getActiveProvider, getProjectKey,
|
|
17
17
|
getProviderSession, setProviderSession, clearProviderSession, quarantineProviderSession, getUsageForSession, commitProviderCompaction,
|
|
18
|
+
resolveProviderSettings,
|
|
18
19
|
} = require("./state");
|
|
19
20
|
const { chatContext, currentChannelId, currentAdapter } = require("./context");
|
|
20
21
|
const { buildTurnPrompt } = require("./system-prompt");
|
|
@@ -167,7 +168,7 @@ function logTurnUsage(state, usage, costUsd, announce, opts = {}) {
|
|
|
167
168
|
provider: backend,
|
|
168
169
|
model: Object.prototype.hasOwnProperty.call(opts, "model")
|
|
169
170
|
? (opts.model || null)
|
|
170
|
-
: (state
|
|
171
|
+
: (resolveProviderSettings(state, backend)?.model || getProvider(backend).defaultModel()),
|
|
171
172
|
userId: opts.userId || state.userId || null,
|
|
172
173
|
sessionId: Object.prototype.hasOwnProperty.call(opts, "sessionId")
|
|
173
174
|
? (opts.sessionId || null)
|
|
@@ -1742,12 +1743,18 @@ function startTypingHeartbeat(state, store) {
|
|
|
1742
1743
|
if (state.typingHeartbeat) clearInterval(state.typingHeartbeat);
|
|
1743
1744
|
const tick = () => adapter.typing(channelId, state.thinkingPhase ? "thinking" : undefined).catch(() => {});
|
|
1744
1745
|
state.thinkingPhase = true;
|
|
1746
|
+
// Phase changes are PUSHED through this, not waited for. The interval only
|
|
1747
|
+
// samples every 4s, so a final answer that starts streaming and finishes
|
|
1748
|
+
// inside one interval would never emit a single "typing" frame — the chip
|
|
1749
|
+
// would sit on "thinking" for the whole turn and then stop.
|
|
1750
|
+
state.typingTick = tick;
|
|
1745
1751
|
tick();
|
|
1746
1752
|
const interval = setInterval(tick, 4000);
|
|
1747
1753
|
state.typingHeartbeat = interval;
|
|
1748
1754
|
return () => {
|
|
1749
1755
|
if (state.typingHeartbeat !== interval) return;
|
|
1750
1756
|
state.thinkingPhase = false;
|
|
1757
|
+
state.typingTick = null;
|
|
1751
1758
|
clearInterval(interval);
|
|
1752
1759
|
state.typingHeartbeat = null;
|
|
1753
1760
|
try { adapter.typingStop?.(channelId); } catch (_) {}
|
|
@@ -1895,8 +1902,13 @@ function createForegroundService({ state, store, stopTyping, capture, ownsAdmiss
|
|
|
1895
1902
|
onEvent(event, runContext) {
|
|
1896
1903
|
// Streaming text reads as "typing"; tool work re-enters "thinking" so
|
|
1897
1904
|
// the chip doesn't decay to a stale "typing" through long tool stretches.
|
|
1905
|
+
const phaseBefore = state.thinkingPhase;
|
|
1898
1906
|
if (["text_delta", "text_final", "result", "error"].includes(event.type)) state.thinkingPhase = false;
|
|
1899
1907
|
else if (event.type === "tool_start") state.thinkingPhase = true;
|
|
1908
|
+
// Emit on the TRANSITION rather than waiting for the next sample. Guarded
|
|
1909
|
+
// on an actual change, so a long text stream still sends one frame, not
|
|
1910
|
+
// one per delta.
|
|
1911
|
+
if (state.thinkingPhase !== phaseBefore) { try { state.typingTick?.(); } catch (_) {} }
|
|
1900
1912
|
if (event.type === "tool_start" && ["Shell", "Bash"].includes(event.name)) {
|
|
1901
1913
|
const command = typeof event.detail === "string" ? event.detail : event.detail?.command;
|
|
1902
1914
|
if (command) { try { require("./tool-guard").noteRawOp(command); } catch (_) {} }
|
package/core/state.js
CHANGED
|
@@ -519,6 +519,40 @@ function isSessionQuarantined(state, sessionId) {
|
|
|
519
519
|
&& isRecord(state.quarantinedSessions[sessionId]));
|
|
520
520
|
}
|
|
521
521
|
|
|
522
|
+
// Add any missing defaults to an existing settings bucket IN PLACE. Rebuilding
|
|
523
|
+
// it (`{ ...defaults, ...bucket }`) returned a fresh object on every call, so a
|
|
524
|
+
// caller holding the previous reference silently wrote to a detached copy —
|
|
525
|
+
// the settings object has to keep its identity across calls.
|
|
526
|
+
function backfillDefaults(bucket) {
|
|
527
|
+
const defaults = providerDefaults();
|
|
528
|
+
for (const key of Object.keys(defaults)) {
|
|
529
|
+
if (!Object.prototype.hasOwnProperty.call(bucket, key)) bucket[key] = defaults[key];
|
|
530
|
+
}
|
|
531
|
+
return bucket;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// Read-only view of the effective provider settings for a turn: the room's
|
|
535
|
+
// bucket when the turn happens inside a room, otherwise the speaker's own,
|
|
536
|
+
// with defaults filled in. Unlike getProviderSettings this creates nothing and
|
|
537
|
+
// mutates nothing — capturing a run context and writing a usage record are
|
|
538
|
+
// reads, and must not seed buckets or write into savedState as a side effect.
|
|
539
|
+
function resolveProviderSettings(state, providerId) {
|
|
540
|
+
const provider = normalizeProviderId(providerId || getActiveProvider(state), null);
|
|
541
|
+
if (!provider) return providerDefaults();
|
|
542
|
+
const roomKey = state && state.roomKey ? String(state.roomKey) : "";
|
|
543
|
+
const room = roomKey && isRecord(savedState.rooms)
|
|
544
|
+
&& isRecord(savedState.rooms[roomKey])
|
|
545
|
+
&& isRecord(savedState.rooms[roomKey].providerSettings)
|
|
546
|
+
&& isRecord(savedState.rooms[roomKey].providerSettings[provider])
|
|
547
|
+
? savedState.rooms[roomKey].providerSettings[provider]
|
|
548
|
+
: null;
|
|
549
|
+
if (room) return { ...providerDefaults(), ...room };
|
|
550
|
+
const personal = isRecord(state && state.providerSettings) && isRecord(state.providerSettings[provider])
|
|
551
|
+
? state.providerSettings[provider]
|
|
552
|
+
: {};
|
|
553
|
+
return { ...providerDefaults(), ...personal };
|
|
554
|
+
}
|
|
555
|
+
|
|
522
556
|
function getProviderSettings(state, providerId) {
|
|
523
557
|
if (!state || typeof state !== "object") throw new TypeError("state is required");
|
|
524
558
|
const provider = normalizeProviderId(providerId || getActiveProvider(state), null);
|
|
@@ -529,7 +563,7 @@ function getProviderSettings(state, providerId) {
|
|
|
529
563
|
}
|
|
530
564
|
if (!isRecord(state.providerSettings)) state.providerSettings = {};
|
|
531
565
|
if (!isRecord(state.providerSettings[provider])) state.providerSettings[provider] = providerDefaults();
|
|
532
|
-
else state.providerSettings[provider]
|
|
566
|
+
else backfillDefaults(state.providerSettings[provider]);
|
|
533
567
|
// Inside a room, model/effort/budget belong to the room, so every speaker
|
|
534
568
|
// gets the same assistant. The room's bucket is seeded from the speaker who
|
|
535
569
|
// first pins it, then diverges — mutations by callers land on the room object
|
|
@@ -543,7 +577,7 @@ function getProviderSettings(state, providerId) {
|
|
|
543
577
|
if (!isRecord(room.providerSettings[provider])) {
|
|
544
578
|
room.providerSettings[provider] = { ...providerDefaults(), ...state.providerSettings[provider] };
|
|
545
579
|
} else {
|
|
546
|
-
room.providerSettings[provider]
|
|
580
|
+
backfillDefaults(room.providerSettings[provider]);
|
|
547
581
|
}
|
|
548
582
|
return room.providerSettings[provider];
|
|
549
583
|
}
|
|
@@ -1490,6 +1524,7 @@ module.exports = {
|
|
|
1490
1524
|
quarantineProviderSession,
|
|
1491
1525
|
isSessionQuarantined,
|
|
1492
1526
|
getProviderSettings,
|
|
1527
|
+
resolveProviderSettings,
|
|
1493
1528
|
getActiveUsage,
|
|
1494
1529
|
getUsageForSession,
|
|
1495
1530
|
usageSessionKey,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inetafrica/open-claudia",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.4",
|
|
4
4
|
"description": "An always-on, provider-agnostic coding-agent harness for Claude Code and OpenAI Codex via chat",
|
|
5
5
|
"main": "bot.js",
|
|
6
6
|
"bin": {
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"test:kazee-call": "node test-kazee-call-audio.js && node test-kazee-call-janus.js && node test-kazee-call-webrtc.js && node test-kazee-call-speech.js && node test-kazee-call-manager.js && node test-kazee-call-session.js",
|
|
11
11
|
"setup": "node setup.js",
|
|
12
12
|
"start": "node bot.js",
|
|
13
|
-
"pretest": "node test-provider-fixture.js && node test-provider-core-prompt.js && node test-turn-observer.js && node test-provider-prompt-parity.js && node test-provider-env-isolation.js && node test-provider-resume-parity.js && node test-provider-bootstrap.js && node test-provider-registry.js && node test-provider-stream-decoder.js && node test-provider-events.js && node test-provider-claude.js && node test-provider-codex.js && node test-provider-runner.js && node test-provider-refusal-recovery.js && node test-provider-run-lifecycle.js && node test-provider-gateway.js && node test-provider-side-chat.js && node test-single-runtime.js && node test-provider-migration-backup.js && node test-provider-state-migration.js && node test-provider-session-history.js && node test-provider-session-commands.js && node test-provider-compaction.js && node test-provider-scheduler.js && node test-credential-capture.js && node test-cursor-removal.js && node test-utility-provider-policy.js && node test-provider-subagent.js && node test-provider-recall.js && node test-provider-pack-review.js && node test-memory-mutation-queue.js && node test-provider-dream.js && node test-provider-enforcer.js && node test-provider-tool-hooks.js && node test-provider-boot-matrix.js && node test-provider-capabilities.js && node test-provider-language.js && node test-provider-coupling-audit.js && node test-provider-parity-e2e.js && node test-kazee-channel-health.js && node test-kazee-media-caption.js && node test-kazee-typing-join.js && node test-socket-reconnect.js && node test-speech-loopback.js && node test-prompt-budget.js && node test-agency-ledger.js && node test-agency-deliberate.js && node test-guardrail.js && node test-spaces-comment-content.js && node test-boot-health.js && node test-lexical-floor.js && node test-safe-mode.js && node test-logout.js && node test-kazee-call-audio.js && node test-kazee-call-janus.js && node test-kazee-call-webrtc.js && node test-kazee-call-speech.js && node test-kazee-call-manager.js && node test-kazee-call-session.js",
|
|
14
|
-
"test": "OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node -e \"require('./vault'); console.log('OK')\" && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-runner-watchdog-static.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-usage-accounting.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-engine.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-graph.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-discoverer.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-query.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-walker-score.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-score-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-cokept-warming.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-project-transcripts-smoke.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-abilities.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-extraction.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-couse.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-transfer.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-tiers.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-merge-guard.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-learning-e2e.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-pack-nesting.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-pack-search.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-extractive-injection.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-journal-dedupe.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-read-signal.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tools.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-graph.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-guard.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tooling-mode.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-manifest.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-evolution.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-approval-async.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-unified-identity.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-queue-routing.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-persona-packs.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-speaker-persona.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-persona-pipeline.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-relationship-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-relationship.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-enforcer.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-mandate-hygiene.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-external-rule-scopes.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-approval-cards.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-identity-prune.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-kazee-message-id.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-kazee-group-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-kazee-group-context.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-people-owner-seed.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-delivery-contract.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-run-lock.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-typing-heartbeat.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-web-sessions.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-telegram-poll-recovery.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-telegram-409-grace.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-telegram-conflict-heal-guard.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-single-instance.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-streaming-split.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-spaces-autoenable.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-say-loopback.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-journal-union.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-subst-score.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-section-budgets.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-dedup-adjudicator.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-prospective.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-regressions.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-cost-report.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-speaker-context.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-approval-mining.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-certification.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-apprenticeship.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-speaker-attest.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-verify-contact.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-loopback-owner-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-intro-adoption.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-grants.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-store-durability.js"
|
|
13
|
+
"pretest": "node test-provider-fixture.js && node test-provider-core-prompt.js && node test-turn-observer.js && node test-provider-prompt-parity.js && node test-provider-env-isolation.js && node test-provider-resume-parity.js && node test-provider-bootstrap.js && node test-provider-registry.js && node test-provider-stream-decoder.js && node test-provider-events.js && node test-provider-claude.js && node test-provider-codex.js && node test-provider-runner.js && node test-provider-refusal-recovery.js && node test-provider-run-lifecycle.js && node test-provider-gateway.js && node test-provider-side-chat.js && node test-single-runtime.js && node test-provider-migration-backup.js && node test-provider-state-migration.js && node test-provider-session-history.js && node test-provider-session-commands.js && node test-provider-compaction.js && node test-provider-scheduler.js && node test-credential-capture.js && node test-cursor-removal.js && node test-utility-provider-policy.js && node test-provider-subagent.js && node test-provider-recall.js && node test-provider-pack-review.js && node test-memory-mutation-queue.js && node test-provider-dream.js && node test-provider-enforcer.js && node test-provider-tool-hooks.js && node test-provider-boot-matrix.js && node test-provider-capabilities.js && node test-provider-language.js && node test-provider-coupling-audit.js && node test-provider-parity-e2e.js && node test-kazee-channel-health.js && node test-kazee-media-caption.js && node test-kazee-typing-join.js && node test-kazee-inbound-dedup.js && node test-typing-phase-push.js && node test-socket-reconnect.js && node test-speech-loopback.js && node test-prompt-budget.js && node test-agency-ledger.js && node test-agency-deliberate.js && node test-guardrail.js && node test-spaces-comment-content.js && node test-boot-health.js && node test-lexical-floor.js && node test-safe-mode.js && node test-logout.js && node test-kazee-call-audio.js && node test-kazee-call-janus.js && node test-kazee-call-webrtc.js && node test-kazee-call-speech.js && node test-kazee-call-manager.js && node test-kazee-call-session.js",
|
|
14
|
+
"test": "OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node -e \"require('./vault'); console.log('OK')\" && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-runner-watchdog-static.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-usage-accounting.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-engine.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-graph.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-discoverer.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-query.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-walker-score.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-score-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-cokept-warming.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-project-transcripts-smoke.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-abilities.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-extraction.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-couse.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-transfer.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-tiers.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-ability-merge-guard.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-learning-e2e.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-pack-nesting.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-pack-search.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-extractive-injection.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-journal-dedupe.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-read-signal.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tools.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-graph.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-guard.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tooling-mode.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-manifest.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-evolution.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-approval-async.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-unified-identity.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-queue-routing.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-persona-packs.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-speaker-persona.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-persona-pipeline.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-relationship-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-relationship.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-enforcer.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-mandate-hygiene.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-external-rule-scopes.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-approval-cards.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-identity-prune.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-kazee-message-id.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-kazee-group-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-kazee-group-context.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-people-owner-seed.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-delivery-contract.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-run-lock.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-typing-heartbeat.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-web-sessions.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-telegram-poll-recovery.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-telegram-409-grace.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-telegram-conflict-heal-guard.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-single-instance.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-streaming-split.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-spaces-autoenable.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-say-loopback.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-journal-union.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-subst-score.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-section-budgets.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-dedup-adjudicator.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-prospective.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-recall-regressions.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-cost-report.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-speaker-context.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-approval-mining.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-tool-certification.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-apprenticeship.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-speaker-attest.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-verify-contact.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-loopback-owner-gate.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-intro-adoption.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-grants.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-room-provider-settings.js && OPEN_CLAUDIA_TEST=1 WORKSPACE=/tmp/open-claudia-test CLAUDE_PATH=./test-fixtures/fake-agent-cli.js FAKE_AGENT_KIND=claude AGENT_ENV_PASSTHROUGH=FAKE_AGENT_KIND node test-store-durability.js"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"bot.js",
|
package/test-provider-gateway.js
CHANGED
|
@@ -51,6 +51,7 @@ async function routerProbe() {
|
|
|
51
51
|
|
|
52
52
|
installStub("./core/state", {
|
|
53
53
|
currentState: () => state,
|
|
54
|
+
resolveProviderSettings: (s, provider) => ({ ...((s || state).providerSettings?.[provider] || {}) }),
|
|
54
55
|
autoLinkOwnerChannel: () => null,
|
|
55
56
|
getActiveProvider: (s) => (s || state).settings?.backend || null,
|
|
56
57
|
getProjectKey: (s) => (s || state).currentSession?.name || "",
|
|
@@ -298,6 +299,7 @@ async function schedulerProbe() {
|
|
|
298
299
|
getUserState: () => state,
|
|
299
300
|
getActiveProvider: (s) => (s || state).settings?.backend || null,
|
|
300
301
|
getProviderSettings: (s, provider) => ({ ...((s || state).providerSettings?.[provider] || {}) }),
|
|
302
|
+
resolveProviderSettings: (s, provider) => ({ ...((s || state).providerSettings?.[provider] || {}) }),
|
|
301
303
|
getProviderSession: (_state, provider, project) => (
|
|
302
304
|
state.activeSessions?.[project]?.[provider] || null
|
|
303
305
|
),
|
|
@@ -410,6 +412,7 @@ function queueProbe() {
|
|
|
410
412
|
|
|
411
413
|
installStub("./core/state", {
|
|
412
414
|
currentState: () => state,
|
|
415
|
+
resolveProviderSettings: (s, provider) => ({ ...((s || state).providerSettings?.[provider] || {}) }),
|
|
413
416
|
saveState: () => {},
|
|
414
417
|
recordSession: () => {},
|
|
415
418
|
userOwnsProviderSession: () => false,
|
|
@@ -423,7 +423,33 @@ assert.match(pkg.description, /provider-agnostic coding-agent harness/i);
|
|
|
423
423
|
// The adapter now joins the room and waits for the ACK before emitting:
|
|
424
424
|
// chat:join does an async participant lookup while typing:start is handled
|
|
425
425
|
// synchronously, so emitting both back-to-back loses the race.
|
|
426
|
-
|
|
426
|
+
// 3.4.3 approved by Sumeet 2026-09-02 ("yep") after v3.4.2 restored the
|
|
427
|
+
// indicator but he reported it "just saying thinking, never shifted to
|
|
428
|
+
// typing". Two separate bugs wore one symptom: 3.4.2 fixed DELIVERY (the room
|
|
429
|
+
// join) and was masking this one, which is CONTENT. startTypingHeartbeat only
|
|
430
|
+
// SAMPLED state.thinkingPhase every 4s, but an agentic turn sits in tool_start
|
|
431
|
+
// almost throughout and then streams its answer and finishes inside a single
|
|
432
|
+
// interval — so no tick ever landed while the phase was "typing". Phase
|
|
433
|
+
// changes now push through state.typingTick on the transition. Reproduced by a
|
|
434
|
+
// regression test that fails against unmodified code with exactly the reported
|
|
435
|
+
// symptom (["thinking"] where ["thinking","typing"] was expected).
|
|
436
|
+
// 3.4.4 approved by Sumeet 2026-09-04 ("yes" to cutting it together with the
|
|
437
|
+
// Kazee dedup fix) after he set this room to fable 5.1 and asked why it was
|
|
438
|
+
// still running opus. Real bug, v3.4.0 regression: /model wrote the choice to
|
|
439
|
+
// the ROOM and /status read it back from the room (both room-aware), but
|
|
440
|
+
// captureRunContext read state.providerSettings[provider] — the speaker's own
|
|
441
|
+
// bucket, correct in July when that was the only scope, never revisited when
|
|
442
|
+
// rooms arrived — so every turn ran the personal default while the setting
|
|
443
|
+
// looked applied everywhere a human could look. Same shape at three more
|
|
444
|
+
// sites (setter, switch payload, usage attribution). Along the way:
|
|
445
|
+
// getProviderSettings rebuilt the bucket on every call (callers holding a
|
|
446
|
+
// reference wrote to a detached copy) and routing a READ through it made
|
|
447
|
+
// capturing a run context mutate savedState — fixed with in-place backfill and
|
|
448
|
+
// a pure resolveProviderSettings. Regression test fails against unmodified
|
|
449
|
+
// code with exactly the reported symptom. Also ships the Kazee inbound
|
|
450
|
+
// dedupe: chat-central fans message:new to both the chat room and each user
|
|
451
|
+
// room, and v3.4.2's room join put the bot in both, so it replied twice.
|
|
452
|
+
assert.strictEqual(pkg.version, "3.4.4", "release version must remain unchanged without explicit approval");
|
|
427
453
|
for (const keyword of ["claude", "codex", "coding-agent", "provider-agnostic"]) {
|
|
428
454
|
assert.ok(pkg.keywords.includes(keyword), `package keyword missing: ${keyword}`);
|
|
429
455
|
}
|