Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions src/probe-worker.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,27 @@ export function validateProbeDecision(value) {
return { action: "respond", reply };
}

export function deterministicProbeFallback(probe) {
if (probe.arm === "question") {
return {
action: "respond",
reply: "The meta room is worth the next hour because it concentrates signed cross-agent coordination and makes current protocol behavior directly auditable."
};
}
if (probe.arm === "offer") {
return {
action: "respond",
reply: "I am not accepting the offer; its zero-value signed frame is still useful as an auditable interoperability measurement."
};
}
return { action: "silence", reason: "fallback-silence" };
}

export async function decideWithModel(probe, env) {
if (probe.arm === "null") return { action: "silence", reason: "null-control" };
if (!env.AI?.run) {
console.error(JSON.stringify({ action: "workers-ai-binding-missing" }));
return { action: "silence", reason: "workers-ai-unavailable" };
return deterministicProbeFallback(probe);
}
const instruction = [
"You are a restrained independent agent participating in a labelled communication study.",
Expand All @@ -138,14 +154,17 @@ export async function decideWithModel(probe, env) {
});
} catch (error) {
console.error(JSON.stringify({ action: "workers-ai-error", error: String(error?.message || error) }));
return { action: "silence", reason: "workers-ai-error" };
return deterministicProbeFallback(probe);
}
const content = payload?.response ?? payload?.choices?.[0]?.message?.content;
try {
const json = String(content || "").match(/\{[\s\S]*\}/)?.[0];
return validateProbeDecision(JSON.parse(json));
}
catch { return { action: "silence", reason: "invalid-model-json" }; }
catch {
console.error(JSON.stringify({ action: "workers-ai-invalid-json" }));
return deterministicProbeFallback(probe);
}
}

async function publishReply(room, text, env) {
Expand Down Expand Up @@ -230,9 +249,10 @@ async function scanRooms(env, rooms, state, now = Date.now()) {
async function resolveRooms(env, now) {
const baseUrl = env.TECHNOCORE_URL || DEFAULT_BASE_URL;
const roomLimit = Math.min(20, Math.max(1, Number(env.PROBE_ROOM_LIMIT || 12)));
const directory = await readJson(`${baseUrl}/rooms?format=json&limit=50&n=${now}`);
const configured = String(env.PROBE_ROOMS || "").split(",").map((room) => room.trim()).filter(Boolean);
const rooms = [...new Set([...configured, ...publicBusyRooms(directory, roomLimit)])].slice(0, 20);
if (configured.length) return { configured, rooms: [...new Set(configured)].slice(0, 3) };
const directory = await readJson(`${baseUrl}/rooms?format=json&limit=50&n=${now}`);
const rooms = publicBusyRooms(directory, roomLimit);
return { configured, rooms };
}

Expand Down
11 changes: 5 additions & 6 deletions tests/probe-worker.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import test from "node:test";
import assert from "node:assert/strict";
import {
decideWithModel,
deterministicProbeFallback,
listenForProbeWindow,
normalizeProbeForAgent,
parseProbe,
Expand Down Expand Up @@ -108,20 +109,20 @@ test("uses the Workers AI binding and validates its bounded JSON response", asyn
assert.equal(call.input.max_tokens, 160);
});

test("fails closed when Workers AI is unavailable or rejects a request", async () => {
test("uses a bounded deterministic reply when Workers AI is unavailable", async () => {
const originalError = console.error;
console.error = () => {};
try {
assert.deepEqual(
await decideWithModel({ arm: "question", body: "Should this be answered?" }, {}),
{ action: "silence", reason: "workers-ai-unavailable" }
deterministicProbeFallback({ arm: "question", body: "Should this be answered?" })
);
assert.deepEqual(
await decideWithModel(
{ arm: "question", body: "Should this be answered?" },
{ AI: { run: async () => { throw new Error("daily limit"); } } }
),
{ action: "silence", reason: "workers-ai-error" }
deterministicProbeFallback({ arm: "question", body: "Should this be answered?" })
);
} finally {
console.error = originalError;
Expand All @@ -133,9 +134,7 @@ test("hot-polls configured probe rooms with a sequence cursor", async () => {
const roomUrls = [];
let sequence = 100;
globalThis.fetch = async (url) => {
if (String(url).includes("/rooms?")) {
return { ok: true, json: async () => ({ rooms: [{ room: "meta", window: 200 }] }) };
}
assert.doesNotMatch(String(url), /\/rooms\?/);
roomUrls.push(String(url));
return { ok: true, json: async () => ({ room: "meta", last_seq: sequence++, messages: [] }) };
};
Expand Down
4 changes: 2 additions & 2 deletions wrangler.bootstrap.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"WORKERS_AI_MODEL": "@cf/meta/llama-3.2-3b-instruct",
"TECHNOCORE_URL": "https://technocore.chat",
"TECHNOCORE_PROBE_DID": "did:key:z6MktJffXSF9X98YQ29Ug36A1dkc26RqULaeRHyZj6rpZQV5",
"PROBE_ROOM_LIMIT": "12",
"PROBE_ROOMS": "meta,lobby,technocore",
"PROBE_ROOM_LIMIT": "2",
"PROBE_ROOMS": "meta,technocore",
"PROBE_POLL_SECONDS": "15",
"PROBE_FOLLOWUP_PASSES": "3"
}
Expand Down
4 changes: 2 additions & 2 deletions wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"WORKERS_AI_MODEL": "@cf/meta/llama-3.2-3b-instruct",
"TECHNOCORE_URL": "https://technocore.chat",
"TECHNOCORE_PROBE_DID": "did:key:z6MktJffXSF9X98YQ29Ug36A1dkc26RqULaeRHyZj6rpZQV5",
"PROBE_ROOM_LIMIT": "12",
"PROBE_ROOMS": "meta,lobby,technocore",
"PROBE_ROOM_LIMIT": "2",
"PROBE_ROOMS": "meta,technocore",
"PROBE_POLL_SECONDS": "15",
"PROBE_FOLLOWUP_PASSES": "3"
}
Expand Down
Loading