项目文件夹

文件
wehub-resource-sync 426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

362 行
11 KiB
TypeScript

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
/**
* Deterministic-handler coverage for the slash-command actions (`/help`,
* `/status`, `/whoami`, runtime option setters). Exercises `runCommand` /
* `resolveCommand` against an in-memory runtime stub — no live model.
*/
import type { IAgentRuntime, Memory } from "@elizaos/core";
import { beforeEach, describe, expect, it } from "vitest";
import {
commandActions,
commandShortcuts,
dispatchCommandMessage,
explicitCommandShortcuts,
getCommandSettings,
naturalShortcuts,
resolveCommand,
} from "../src/actions";
import {
getEnabledCommandsForRuntime,
initForRuntime,
registerCommand,
useRuntime,
} from "../src/registry";
function makeRuntime(
agentId = "agent-1",
onGetCache?: (key: string) => void | Promise<void>,
overrides: Partial<IAgentRuntime> = {},
): IAgentRuntime {
const cache = new Map<string, unknown>();
let messages: Memory[] = [msg("first"), msg("second")];
return {
agentId,
character: { name: "Eliza", settings: {} },
actions: [],
getSetting: () => null,
setSetting: () => undefined,
getCache: async (key: string) => {
await onGetCache?.(key);
return cache.get(key);
},
setCache: async (key: string, value: unknown) => {
cache.set(key, value);
return true;
},
deleteCache: async (key: string) => cache.delete(key),
countMemories: async () => messages.length,
deleteAllMemories: async () => {
messages = [];
},
useModel: async () => "",
...overrides,
} as unknown as IAgentRuntime;
}
function msg(text: string, source = "client_chat"): Memory {
return {
id: "00000000-0000-0000-0000-000000000001",
entityId: "00000000-0000-0000-0000-0000000000aa",
roomId: "room-1",
content: { text, source },
} as unknown as Memory;
}
describe("runCommand / resolveCommand — deterministic handlers (#8790)", () => {
let runtime: IAgentRuntime;
beforeEach(() => {
initForRuntime("agent-1");
runtime = makeRuntime();
});
it("/help lists the registered commands deterministically", async () => {
const r = await resolveCommand(runtime, msg("/help"));
expect(r.handled).toBe(true);
expect(r.reply).toContain("Available commands");
expect(r.reply).toContain("/help");
});
it("/status reports real runtime state", async () => {
const r = await resolveCommand(runtime, msg("/status"));
expect(r.handled).toBe(true);
expect(r.reply).toContain("Agent: Eliza");
expect(r.reply).toContain("Commands enabled:");
});
it("/status keeps its runtime-scoped store across awaited settings reads", async () => {
initForRuntime("agent-a");
useRuntime("agent-a");
registerCommand({
key: "agent-a-only",
description: "Runtime-local command",
textAliases: ["/agent-a-only"],
scope: "both",
category: "skills",
});
initForRuntime("agent-b");
const agentACommandCount = getEnabledCommandsForRuntime("agent-a").length;
expect(agentACommandCount).toBe(
getEnabledCommandsForRuntime("agent-b").length + 1,
);
const runtimeA = makeRuntime("agent-a", async () => {
useRuntime("agent-b");
});
const r = await resolveCommand(runtimeA, msg("/status"));
expect(r.handled).toBe(true);
expect(r.reply).toContain(`Commands enabled: ${agentACommandCount}`);
});
it("/whoami reflects the sender context", async () => {
const r = await resolveCommand(runtime, msg("/whoami"), {
isAuthorized: true,
isElevated: true,
senderName: "Shaw",
});
expect(r.reply).toContain("You are Shaw");
expect(r.reply).toContain("Authorized: yes");
});
it("deterministically persists runtime option commands", async () => {
const cases = [
["/think high", "Thinking set to high."],
["/verbose on", "Verbose set to on."],
["/reasoning stream", "Reasoning set to stream."],
["/queue steer", "Queue mode set to steer."],
["/elevated on", "Elevated mode set to on."],
["/model Anthropic/Claude-Opus", "Model set to Anthropic/Claude-Opus."],
["/tts off", "TTS set to off."],
] as const;
for (const [text, expectedReply] of cases) {
const r = await resolveCommand(runtime, msg(text), {
isAuthorized: true,
isElevated: true,
});
expect(r.handled, text).toBe(true);
expect(r.reply).toBe(expectedReply);
}
expect(await getCommandSettings(runtime, "room-1")).toEqual({
thinking: "high",
verbose: "on",
reasoning: "stream",
queue: "steer",
elevated: "on",
model: "Anthropic/Claude-Opus",
tts: "off",
});
});
it("rejects invalid option values deterministically", async () => {
const r = await resolveCommand(runtime, msg("/think enormous"), {
isAuthorized: true,
});
expect(r.handled).toBe(true);
expect(r.reply).toContain("Invalid thinking value");
});
it("deterministically handles lifecycle commands (reset/new/compact)", async () => {
await resolveCommand(runtime, msg("/think high"), { isAuthorized: true });
const reset = await resolveCommand(runtime, msg("/reset"), {
isAuthorized: true,
});
expect(reset.handled).toBe(true);
expect(reset.reply).toContain("cleared command settings");
expect(reset.reply).toContain("2 message(s)");
expect(await getCommandSettings(runtime, "room-1")).toEqual({});
await resolveCommand(runtime, msg("/model gpt-5"));
const next = await resolveCommand(runtime, msg("/new"), {
isAuthorized: true,
});
expect(next.handled).toBe(true);
expect(next.reply).toBe(
"Started a new conversation context for this room.",
);
expect(await getCommandSettings(runtime, "room-1")).toEqual({});
const compactRuntime = makeRuntime("agent-1", undefined, {
actions: [
{
name: "COMPACT_CONVERSATION",
description: "Compact",
validate: async () => true,
handler: async () => ({
success: true,
text: "Compacted 4 older message(s); preserved the latest 2.",
}),
},
],
});
const compact = await resolveCommand(compactRuntime, msg("/compact"), {
isAuthorized: true,
});
expect(compact.handled).toBe(true);
expect(compact.reply).toContain("Compacted 4 older message(s)");
});
it("ignores non-command messages", async () => {
expect((await resolveCommand(runtime, msg("hello world"))).handled).toBe(
false,
);
});
it("dispatchCommandMessage fires the callback with the reply", async () => {
const calls: Array<{ text: string; source?: string }> = [];
const handled = await dispatchCommandMessage(
runtime,
msg("/help"),
(reply) => {
calls.push(reply);
return [];
},
);
expect(handled).toBe(true);
expect(calls).toHaveLength(1);
expect(calls[0]?.text).toContain("Available commands");
});
});
describe("command actions — slash-only validate (#8790)", () => {
let runtime: IAgentRuntime;
beforeEach(() => {
initForRuntime("agent-1");
runtime = makeRuntime();
});
it("registers one action per deterministic command", () => {
const names = new Set(commandActions.map((a) => a.name));
expect(names.has("HELP_COMMAND")).toBe(true);
expect(names.has("STATUS_COMMAND")).toBe(true);
expect(names.has("THINK_COMMAND")).toBe(true);
expect(names.has("MODEL_COMMAND")).toBe(true);
expect(names.has("TTS_COMMAND")).toBe(true);
expect(names.has("RESET_COMMAND")).toBe(true);
expect(names.has("NEW_COMMAND")).toBe(true);
expect(names.has("COMPACT_COMMAND")).toBe(true);
expect(names.has("STOP_COMMAND")).toBe(false);
expect(names.has("RESTART_COMMAND")).toBe(false);
});
it("validate() matches only its own slash command, never plain text", async () => {
const help = commandActions.find((a) => a.name === "HELP_COMMAND");
expect(help).toBeDefined();
expect(await help?.validate(runtime, msg("/help"))).toBe(true);
expect(await help?.validate(runtime, msg("/status"))).toBe(false);
expect(await help?.validate(runtime, msg("I need help please"))).toBe(
false,
);
});
it("handler produces the deterministic reply via the callback", async () => {
const status = commandActions.find((a) => a.name === "STATUS_COMMAND");
const replies: string[] = [];
const result = await status?.handler(
runtime,
msg("/status"),
undefined,
undefined,
async (content) => {
replies.push(String(content.text));
return [];
},
);
expect(result?.success).toBe(true);
expect(replies[0]).toContain("Agent: Eliza");
});
it("similes are slash-only (no natural language)", () => {
for (const action of commandActions) {
for (const simile of action.similes ?? []) {
expect(simile.startsWith("/")).toBe(true);
}
}
});
});
describe("command shortcuts ↔ actions linkage (#8790 × #8791)", () => {
it("every shortcut targets a registered command action", () => {
const actionNames = new Set(commandActions.map((a) => a.name));
expect(commandShortcuts.length).toBeGreaterThan(0);
// commandShortcuts = explicit slash shortcuts + narrow natural ones.
expect(commandShortcuts).toEqual([
...explicitCommandShortcuts,
...naturalShortcuts,
]);
for (const shortcut of commandShortcuts) {
expect(shortcut.target.kind).toBe("action");
if (shortcut.target.kind === "action") {
expect(actionNames.has(shortcut.target.name)).toBe(true);
}
}
});
it("explicit slash shortcuts are explicit-only with slash aliases", () => {
expect(explicitCommandShortcuts.length).toBeGreaterThan(0);
for (const shortcut of explicitCommandShortcuts) {
expect(shortcut.kind).toBe("explicit");
expect(shortcut.aliases && shortcut.aliases.length > 0).toBe(true);
for (const alias of shortcut.aliases ?? []) {
expect(alias.startsWith("/")).toBe(true);
}
}
});
it("natural shortcuts carry no slash aliases (anchored patterns)", () => {
for (const shortcut of naturalShortcuts) {
expect(shortcut.kind).toBe("natural");
expect(shortcut.aliases ?? []).toHaveLength(0);
expect(shortcut.patterns && shortcut.patterns.length > 0).toBe(true);
}
});
it("records every shortcut alias/action signature for the e2e coverage matrix", () => {
const signatures = commandShortcuts
.flatMap((shortcut) => {
const target =
shortcut.target.kind === "action"
? shortcut.target.name
: shortcut.target.kind;
return (shortcut.aliases ?? []).map(
(alias) => `${shortcut.id}:${alias}->${target}`,
);
})
.sort();
expect(signatures).toEqual([
"cmd:accounts:/accounts->ACCOUNTS_COMMAND",
"cmd:backend:/backend->BACKEND_COMMAND",
"cmd:commands:/cmds->COMMANDS_COMMAND",
"cmd:commands:/commands->COMMANDS_COMMAND",
"cmd:compact:/compact->COMPACT_COMMAND",
"cmd:context:/context->CONTEXT_COMMAND",
"cmd:context:/ctx->CONTEXT_COMMAND",
"cmd:elevated:/elev->ELEVATED_COMMAND",
"cmd:elevated:/elevated->ELEVATED_COMMAND",
"cmd:help:/?->HELP_COMMAND",
"cmd:help:/h->HELP_COMMAND",
"cmd:help:/help->HELP_COMMAND",
"cmd:model:/m->MODEL_COMMAND",
"cmd:model:/model->MODEL_COMMAND",
"cmd:new:/new->NEW_COMMAND",
"cmd:queue:/q->QUEUE_COMMAND",
"cmd:queue:/queue->QUEUE_COMMAND",
"cmd:reasoning:/reason->REASONING_COMMAND",
"cmd:reasoning:/reasoning->REASONING_COMMAND",
"cmd:reset:/reset->RESET_COMMAND",
"cmd:status:/s->STATUS_COMMAND",
"cmd:status:/status->STATUS_COMMAND",
"cmd:think:/t->THINK_COMMAND",
"cmd:think:/think->THINK_COMMAND",
"cmd:think:/thinking->THINK_COMMAND",
"cmd:tts:/tts->TTS_COMMAND",
"cmd:tts:/voice->TTS_COMMAND",
"cmd:usage:/usage->USAGE_COMMAND",
"cmd:verbose:/v->VERBOSE_COMMAND",
"cmd:verbose:/verbose->VERBOSE_COMMAND",
"cmd:whoami:/who->WHOAMI_COMMAND",
"cmd:whoami:/whoami->WHOAMI_COMMAND",
]);
});
});