mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-07 18:42:25 +00:00
chore(deadcode): remove stale proof scripts
This commit is contained in:
@@ -1,193 +0,0 @@
|
||||
/**
|
||||
* Real-runtime behavior proof for #73706.
|
||||
*
|
||||
* This script does NOT use vitest mocks. It wires up the production
|
||||
* `deliverOutboundPayloads` path against:
|
||||
* - a real `PluginRegistry` populated with one real channel plugin and
|
||||
* two real plugin hooks (`message_sending`, `message_sent`)
|
||||
* - the real `getGlobalHookRunner()` / `initializeGlobalHookRunner()`
|
||||
* singleton path (no fake hook runner)
|
||||
* - the real `setActivePluginRegistry` channel resolution path (no
|
||||
* fake channel adapter)
|
||||
*
|
||||
* It then exercises three scenarios:
|
||||
*
|
||||
* 1. Direct outbound delivery with `session.key` set: confirms the
|
||||
* `message_sending` and `message_sent` hook contexts both receive
|
||||
* the canonical `sessionKey`.
|
||||
*
|
||||
* 2. Direct outbound delivery with NO session: confirms `sessionKey`
|
||||
* is absent from both hook contexts (the "narrowed" docs branch).
|
||||
*
|
||||
* 3. Native-redirect simulation: outbound delivery whose `session.key`
|
||||
* is set to the redirect TARGET session (i.e., what the agent
|
||||
* runtime resolves as `params.sessionKey` when
|
||||
* `CommandTargetSessionKey` is set and `CommandSource === "native"`,
|
||||
* and what `dispatch-from-config.ts` now passes through to
|
||||
* `routeReply`). Confirms `message_sending` / `message_sent`
|
||||
* observe the redirect-target session, NOT the inbound session.
|
||||
* This is the runtime invariant Clawsweeper asked us to pin
|
||||
* with a regression test.
|
||||
*
|
||||
* Run with:
|
||||
* pnpm tsx scripts/proof-73706-message-sending-session-key.ts
|
||||
*/
|
||||
|
||||
import { deliverOutboundPayloads } from "../src/infra/outbound/deliver.js";
|
||||
import type {
|
||||
PluginHookMessageContext,
|
||||
PluginHookMessageReceivedEvent,
|
||||
} from "../src/plugins/hook-message.types.js";
|
||||
import { initializeGlobalHookRunner } from "../src/plugins/hook-runner-global.js";
|
||||
import { addTestHook, createMockPluginRegistry } from "../src/plugins/hooks.test-helpers.js";
|
||||
import type { PluginRegistry } from "../src/plugins/registry.js";
|
||||
import { setActivePluginRegistry } from "../src/plugins/runtime.js";
|
||||
import { createOutboundTestPlugin, createTestRegistry } from "../src/test-utils/channel-plugins.js";
|
||||
|
||||
type CapturedContext = {
|
||||
hook: "message_sending" | "message_sent";
|
||||
ctx: PluginHookMessageContext;
|
||||
event: PluginHookMessageReceivedEvent;
|
||||
};
|
||||
|
||||
function buildRegistry(captured: CapturedContext[], channelId: "matrix"): PluginRegistry {
|
||||
// Real outbound channel plugin: returns a synthetic delivery result
|
||||
// without touching any network. This drives `deliverOutboundPayloads`
|
||||
// through its real channel-resolution + sendText path.
|
||||
const sendText = async () => ({
|
||||
channel: channelId,
|
||||
messageId: `mx-${Date.now()}`,
|
||||
roomId: "!room:example",
|
||||
});
|
||||
|
||||
const channelRegistry = createTestRegistry([
|
||||
{
|
||||
pluginId: channelId,
|
||||
source: "proof",
|
||||
plugin: createOutboundTestPlugin({
|
||||
id: channelId,
|
||||
outbound: { deliveryMode: "direct", sendText },
|
||||
}),
|
||||
},
|
||||
]);
|
||||
|
||||
// Real hook handlers: capture exactly what delivery hands to plugins.
|
||||
const hookRegistry = createMockPluginRegistry([]);
|
||||
addTestHook({
|
||||
registry: hookRegistry,
|
||||
pluginId: "proof-message-sending",
|
||||
hookName: "message_sending",
|
||||
handler: async (event: unknown, ctx: unknown) => {
|
||||
captured.push({
|
||||
hook: "message_sending",
|
||||
ctx: ctx as PluginHookMessageContext,
|
||||
event: event as PluginHookMessageReceivedEvent,
|
||||
});
|
||||
// Returning undefined means "do not modify or cancel".
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
addTestHook({
|
||||
registry: hookRegistry,
|
||||
pluginId: "proof-message-sent",
|
||||
hookName: "message_sent",
|
||||
handler: async (event: unknown, ctx: unknown) => {
|
||||
captured.push({
|
||||
hook: "message_sent",
|
||||
ctx: ctx as PluginHookMessageContext,
|
||||
event: event as PluginHookMessageReceivedEvent,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
...channelRegistry,
|
||||
hooks: hookRegistry.hooks,
|
||||
typedHooks: hookRegistry.typedHooks,
|
||||
plugins: hookRegistry.plugins,
|
||||
};
|
||||
}
|
||||
|
||||
async function runScenario(
|
||||
label: string,
|
||||
opts: { sessionKey?: string },
|
||||
): Promise<CapturedContext[]> {
|
||||
const captured: CapturedContext[] = [];
|
||||
const registry = buildRegistry(captured, "matrix");
|
||||
setActivePluginRegistry(registry);
|
||||
initializeGlobalHookRunner(registry);
|
||||
|
||||
const result = await deliverOutboundPayloads({
|
||||
cfg: {},
|
||||
channel: "matrix",
|
||||
to: "!room:example",
|
||||
payloads: [{ text: `proof: ${label}` }],
|
||||
skipQueue: true,
|
||||
...(opts.sessionKey ? { session: { key: opts.sessionKey } } : {}),
|
||||
});
|
||||
|
||||
console.log(`\n=== Scenario: ${label} ===`);
|
||||
console.log(`deliverOutboundPayloads result:`, JSON.stringify(result));
|
||||
for (const entry of captured) {
|
||||
console.log(
|
||||
`[${entry.hook}] ctx.sessionKey = ${
|
||||
entry.ctx.sessionKey === undefined ? "(undefined)" : JSON.stringify(entry.ctx.sessionKey)
|
||||
}`,
|
||||
);
|
||||
console.log(`[${entry.hook}] full ctx = ${JSON.stringify(entry.ctx)}`);
|
||||
}
|
||||
|
||||
return captured;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log("[proof-73706] Real-runtime behavior proof for outbound session-key threading.");
|
||||
console.log(
|
||||
"[proof-73706] Production code paths: deliverOutboundPayloads + getGlobalHookRunner.",
|
||||
);
|
||||
|
||||
const scenario1 = await runScenario(
|
||||
"outbound delivery WITH session.key (canonical key from agent runtime)",
|
||||
{ sessionKey: "agent:tank:slack:channel:CHAN1" },
|
||||
);
|
||||
const scenario2 = await runScenario(
|
||||
"outbound delivery WITHOUT session (narrowed docs branch)",
|
||||
{},
|
||||
);
|
||||
const scenario3 = await runScenario(
|
||||
"native-redirect: session.key = CommandTargetSessionKey (what dispatch-from-config.ts now passes)",
|
||||
{ sessionKey: "agent:tank:telegram:direct:999" },
|
||||
);
|
||||
|
||||
// Assertions — make the proof self-checking so the captured output is
|
||||
// not silently green when the runtime regresses.
|
||||
const expectFromHook = (
|
||||
captured: CapturedContext[],
|
||||
hook: "message_sending" | "message_sent",
|
||||
expected: string | undefined,
|
||||
): void => {
|
||||
const entry = captured.find((c) => c.hook === hook);
|
||||
if (!entry) {
|
||||
throw new Error(`[proof-73706] No ${hook} hook fired.`);
|
||||
}
|
||||
if (entry.ctx.sessionKey !== expected) {
|
||||
throw new Error(
|
||||
`[proof-73706] ${hook} sessionKey mismatch: expected ${JSON.stringify(expected)} got ${JSON.stringify(entry.ctx.sessionKey)}`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
expectFromHook(scenario1, "message_sending", "agent:tank:slack:channel:CHAN1");
|
||||
expectFromHook(scenario1, "message_sent", "agent:tank:slack:channel:CHAN1");
|
||||
expectFromHook(scenario2, "message_sending", undefined);
|
||||
expectFromHook(scenario2, "message_sent", undefined);
|
||||
expectFromHook(scenario3, "message_sending", "agent:tank:telegram:direct:999");
|
||||
expectFromHook(scenario3, "message_sent", "agent:tank:telegram:direct:999");
|
||||
|
||||
console.log("\n[proof-73706] All runtime assertions passed.");
|
||||
}
|
||||
|
||||
main().catch((err: unknown) => {
|
||||
console.error("[proof-73706] FAILED:", err);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
@@ -1,142 +0,0 @@
|
||||
// Live-proof harness for PR #83738 (cron wake origin capture).
|
||||
//
|
||||
// Drives the patched gateway wake handler (validateWakeParams + isSubagentSessionKey
|
||||
// guard) into the patched cron service wake() (wake.ts) with deps wired to LOG
|
||||
// every enqueueSystemEvent / requestHeartbeat call. Captures stdout that
|
||||
// demonstrates a non-main cron wake routing to the originating session/agent
|
||||
// rather than the heartbeat/main default.
|
||||
//
|
||||
// Run: pnpm exec tsx scripts/proof-cron-wake-origin.mts
|
||||
//
|
||||
// All identifiers in this script are synthetic. Real Telegram chat ids /
|
||||
// session keys are not used.
|
||||
|
||||
import { cronHandlers } from "../src/gateway/server-methods/cron.js";
|
||||
import { wake as cronServiceWake } from "../src/cron/service/wake.js";
|
||||
import type { CronServiceState } from "../src/cron/service/state.js";
|
||||
|
||||
type EnqueueArgs = [string, { sessionKey?: string; agentId?: string } | undefined];
|
||||
type HeartbeatArgs = [
|
||||
{ source: string; intent: string; reason: string; sessionKey?: string; agentId?: string },
|
||||
];
|
||||
|
||||
const log = (...parts: unknown[]) => {
|
||||
console.log(...parts);
|
||||
};
|
||||
|
||||
function makeShimmedState(): {
|
||||
state: CronServiceState;
|
||||
recorder: { enqueue: EnqueueArgs[]; heartbeat: HeartbeatArgs[] };
|
||||
} {
|
||||
const recorder = { enqueue: [] as EnqueueArgs[], heartbeat: [] as HeartbeatArgs[] };
|
||||
const state = {
|
||||
deps: {
|
||||
enqueueSystemEvent: (...args: EnqueueArgs) => {
|
||||
recorder.enqueue.push(args);
|
||||
const [text, opts] = args;
|
||||
log(
|
||||
`[gateway/cron] enqueueSystemEvent text=${JSON.stringify(text)} opts=${JSON.stringify(opts)}`,
|
||||
);
|
||||
},
|
||||
requestHeartbeat: (...args: HeartbeatArgs) => {
|
||||
recorder.heartbeat.push(args);
|
||||
log(`[gateway/heartbeat] requestHeartbeat ${JSON.stringify(args[0])}`);
|
||||
},
|
||||
},
|
||||
} as unknown as CronServiceState;
|
||||
return { state, recorder };
|
||||
}
|
||||
|
||||
type ScenarioResult = { ok: boolean; payload?: unknown; error?: unknown };
|
||||
|
||||
async function drive(label: string, params: unknown): Promise<ScenarioResult> {
|
||||
log("");
|
||||
log(`=== ${label} ===`);
|
||||
log(`> wake params: ${JSON.stringify(params)}`);
|
||||
const { state } = makeShimmedState();
|
||||
let response: ScenarioResult = { ok: false };
|
||||
const respond = (ok: boolean, payload: unknown, error: unknown) => {
|
||||
response = { ok, payload, error };
|
||||
};
|
||||
const context = {
|
||||
cron: {
|
||||
wake: (
|
||||
opts: {
|
||||
mode: "now" | "next-heartbeat";
|
||||
text: string;
|
||||
sessionKey?: string;
|
||||
agentId?: string;
|
||||
},
|
||||
) => cronServiceWake(state, opts),
|
||||
},
|
||||
} as unknown as Parameters<typeof cronHandlers.wake>[0]["context"];
|
||||
|
||||
// cronHandlers.wake is sync (calls respond synchronously) but typed as
|
||||
// returning void; await on a Promise wrapper to flush console.log ordering.
|
||||
await Promise.resolve(
|
||||
cronHandlers.wake({
|
||||
params,
|
||||
respond,
|
||||
context,
|
||||
request: {} as never,
|
||||
requestId: 1 as never,
|
||||
logger: undefined as never,
|
||||
} as never),
|
||||
);
|
||||
log(`< wake result: ok=${response.ok} payload=${JSON.stringify(response.payload)}`);
|
||||
if (response.error) {
|
||||
log(`< wake error: ${JSON.stringify(response.error)}`);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
log("=== PR #83738 cron wake origin-capture: live-proof harness ===");
|
||||
log("Driving the patched gateway wake handler through cron.wake() with");
|
||||
log("logging deps. All ids below are synthetic.");
|
||||
|
||||
// Scenario 1: real-world bug-reproduction case — a wake fired from inside
|
||||
// a non-main Telegram topic session for a non-default agent.
|
||||
await drive("non-main session + non-default agent (the bug-fix case)", {
|
||||
mode: "now",
|
||||
text: "follow up on report",
|
||||
sessionKey: "agent:coding:telegram:<chat-id-redacted>:topic:<topic-id-redacted>",
|
||||
agentId: "coding",
|
||||
});
|
||||
|
||||
// Scenario 2: backwards-compatible — no origin → default routing.
|
||||
await drive("no origin (backwards-compatible default routing)", {
|
||||
mode: "now",
|
||||
text: "ping",
|
||||
});
|
||||
|
||||
// Scenario 3: next-heartbeat + sessionKey collapses to a targeted-immediate
|
||||
// heartbeat because the regularly-scheduled heartbeat fires for the
|
||||
// agent's main session, never peeking the targeted lane's queue.
|
||||
await drive("next-heartbeat + sessionKey collapses to targeted-immediate", {
|
||||
mode: "next-heartbeat",
|
||||
text: "check the queue",
|
||||
sessionKey: "agent:coding:discord:<thread-redacted>",
|
||||
agentId: "coding",
|
||||
});
|
||||
|
||||
// Scenario 4: subagent sessionKey rejected at the gateway handler.
|
||||
await drive("subagent sessionKey rejected by gateway handler guard", {
|
||||
mode: "now",
|
||||
text: "wake my subagent",
|
||||
sessionKey: "subagent:scratch:<id-redacted>",
|
||||
});
|
||||
|
||||
// Scenario 5: whitespace-only origin falls through to default routing.
|
||||
await drive("whitespace-only origin falls through (defence-in-depth)", {
|
||||
mode: "now",
|
||||
text: "x",
|
||||
sessionKey: " ",
|
||||
agentId: "\t",
|
||||
});
|
||||
|
||||
log("");
|
||||
log("=== Done. ===");
|
||||
}
|
||||
|
||||
void main();
|
||||
@@ -1,42 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Live repro for CLI infer web search SecretRef resolution (PR #82699).
|
||||
* Run: TAVILY_API_KEY=resolved-live-proof pnpm exec tsx scripts/repro/cli-web-search-secret-refs-live-proof.mjs
|
||||
*/
|
||||
import { resolveCommandConfigWithSecrets } from "../../src/cli/command-config-resolution.js";
|
||||
import { getCapabilityWebSearchCommandSecretTargetIds } from "../../src/cli/command-secret-targets.js";
|
||||
|
||||
const unresolvedConfig = {
|
||||
tools: { web: { search: { provider: "tavily", enabled: true } } },
|
||||
plugins: {
|
||||
entries: {
|
||||
tavily: {
|
||||
config: {
|
||||
webSearch: {
|
||||
apiKey: { source: "env", provider: "default", id: "TAVILY_API_KEY" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
process.env.TAVILY_API_KEY = process.env.TAVILY_API_KEY ?? "resolved-live-proof";
|
||||
|
||||
const { effectiveConfig, diagnostics } = await resolveCommandConfigWithSecrets({
|
||||
config: unresolvedConfig,
|
||||
commandName: "infer web search",
|
||||
targetIds: getCapabilityWebSearchCommandSecretTargetIds(),
|
||||
autoEnable: true,
|
||||
});
|
||||
|
||||
const apiKey = effectiveConfig.plugins?.entries?.tavily?.config?.webSearch?.apiKey;
|
||||
const unresolved = unresolvedConfig.plugins.entries.tavily.config.webSearch.apiKey;
|
||||
|
||||
console.log("unresolved apiKey is SecretRef object =", typeof unresolved === "object");
|
||||
console.log(
|
||||
"resolveCommandConfigWithSecrets apiKey is string =",
|
||||
typeof apiKey === "string" && apiKey.length > 0,
|
||||
);
|
||||
console.log("resolved apiKey remains redacted =", typeof apiKey === "string");
|
||||
console.log("diagnostics count =", diagnostics.length);
|
||||
@@ -1,94 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Live repro for implicit session_status + runSessionKey (#82669 / PR #82696).
|
||||
* Run: pnpm exec tsx scripts/repro/session-status-run-session-key-live-proof.mjs
|
||||
*/
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
|
||||
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-session-status-proof-"));
|
||||
const configPath = path.join(tmpRoot, "openclaw.json");
|
||||
const storePath = path.join(tmpRoot, "sessions.json");
|
||||
const store = {
|
||||
"agent:main:telegram:default:direct:1234": {
|
||||
sessionId: "s-tg-direct",
|
||||
updatedAt: 5,
|
||||
status: "done",
|
||||
thinkingLevel: "off",
|
||||
},
|
||||
"agent:main:main": {
|
||||
sessionId: "s-main",
|
||||
updatedAt: 10,
|
||||
status: "running",
|
||||
thinkingLevel: "high",
|
||||
},
|
||||
};
|
||||
fs.writeFileSync(configPath, "{}\n");
|
||||
fs.writeFileSync(storePath, `${JSON.stringify(store, null, 2)}\n`);
|
||||
process.env.OPENCLAW_CONFIG_PATH = configPath;
|
||||
process.env.OPENCLAW_DISABLE_BUNDLED_PLUGINS = "1";
|
||||
|
||||
const originalStderrWrite = process.stderr.write.bind(process.stderr);
|
||||
process.stderr.write = (chunk, encoding, callback) => {
|
||||
const text = String(chunk);
|
||||
if (text.includes("gateway connect failed:")) {
|
||||
if (typeof encoding === "function") {
|
||||
encoding();
|
||||
} else if (typeof callback === "function") {
|
||||
callback();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return originalStderrWrite(chunk, encoding, callback);
|
||||
};
|
||||
|
||||
const { createSessionStatusTool } = await import("../../src/agents/tools/session-status-tool.ts");
|
||||
|
||||
const config = {
|
||||
session: { mainKey: "main", scope: "per-sender", store: storePath },
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "proof/gpt-5.4" },
|
||||
models: {},
|
||||
},
|
||||
},
|
||||
tools: {
|
||||
agentToAgent: { enabled: false },
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
const tool = createSessionStatusTool({
|
||||
agentSessionKey: "agent:main:telegram:default:direct:1234",
|
||||
runSessionKey: "agent:main:main",
|
||||
config,
|
||||
});
|
||||
|
||||
const result = await tool.execute("live-proof-implicit-run-session", {});
|
||||
const text =
|
||||
typeof result === "string"
|
||||
? result
|
||||
: (result.content.find((item) => item.type === "text")?.text ?? result.details.statusText);
|
||||
const thinkingMatch = text.match(/\bThink:\s+(\w+)/i);
|
||||
const sessionKey = typeof result === "string" ? undefined : result.details.sessionKey;
|
||||
|
||||
if (sessionKey !== "agent:main:main") {
|
||||
throw new Error(`expected details.sessionKey agent:main:main, got ${String(sessionKey)}`);
|
||||
}
|
||||
if (thinkingMatch?.[1] !== "high") {
|
||||
throw new Error(`expected status text to mention Think: high, got ${thinkingMatch?.[1]}`);
|
||||
}
|
||||
|
||||
console.log(
|
||||
"implicit session_status resolved thinkingLevel from store =",
|
||||
store["agent:main:main"].thinkingLevel,
|
||||
);
|
||||
console.log("status text mentions thinking:", thinkingMatch[1]);
|
||||
console.log("details.sessionKey =", sessionKey);
|
||||
console.log("--- status excerpt ---");
|
||||
console.log(text.split("\n").slice(0, 8).join("\n"));
|
||||
} finally {
|
||||
process.stderr.write = originalStderrWrite;
|
||||
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
||||
}
|
||||
Reference in New Issue
Block a user