mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 14:01:24 +08:00
docs: document agent identity tests
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
// Verifies when heartbeat guidance is injected into the default agent prompt.
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveHeartbeatPromptForSystemPrompt } from "./heartbeat-system-prompt.js";
|
||||
|
||||
@@ -65,6 +66,8 @@ describe("resolveHeartbeatPromptForSystemPrompt", () => {
|
||||
});
|
||||
|
||||
it("omits the heartbeat section when only a non-default agent has explicit heartbeat config", () => {
|
||||
// The system prompt section is only for the default active agent; sibling
|
||||
// agent heartbeat settings should not leak into the default prompt.
|
||||
expect(
|
||||
resolveHeartbeatPromptForSystemPrompt({
|
||||
config: {
|
||||
@@ -87,6 +90,8 @@ describe("resolveHeartbeatPromptForSystemPrompt", () => {
|
||||
});
|
||||
|
||||
it("honors default-agent overrides for the prompt text", () => {
|
||||
// Defaults establish cadence/shape, but the default agent can override the
|
||||
// final visible prompt text.
|
||||
expect(
|
||||
resolveHeartbeatPromptForSystemPrompt({
|
||||
config: {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
// Covers attribution boundaries around plugin-injected system context.
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { wrapPluginSystemContextSection } from "./hook-system-context-boundary.js";
|
||||
|
||||
function wrappedPluginSystemContext(text: string): string {
|
||||
// The boundary text makes injected context explicit to the model so plugin
|
||||
// instructions are not mistaken for workspace file content.
|
||||
return `---\n\nOpenClaw plugin-injected system context. This block is not workspace file content.\n\n${text}\n\n---`;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Exercises agent avatar resolution, workspace containment, and public redaction.
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
@@ -17,6 +18,8 @@ async function expectLocalAvatarPath(
|
||||
expectedRelativePath: string,
|
||||
opts?: Parameters<typeof resolveAgentAvatar>[2],
|
||||
) {
|
||||
// Compare realpaths so symlinks or temp-dir normalization cannot hide an
|
||||
// avatar escaping the configured workspace.
|
||||
const workspaceReal = await fs.realpath(workspace);
|
||||
const resolved = resolveAgentAvatar(cfg, "main", opts);
|
||||
expect(resolved.kind).toBe("local");
|
||||
@@ -161,6 +164,8 @@ describe("resolveAgentAvatar", () => {
|
||||
expect(absolute.kind).toBe("none");
|
||||
expect(resolvePublicAgentAvatarSource(absolute)).toBeUndefined();
|
||||
|
||||
// Public status/UI surfaces may report remote/data origins, but local
|
||||
// absolute paths and traversal attempts stay hidden.
|
||||
expect(
|
||||
resolvePublicAgentAvatarSource({
|
||||
kind: "remote",
|
||||
@@ -247,7 +252,8 @@ describe("resolveAgentAvatar", () => {
|
||||
it("ui.assistant.avatar ignored without includeUiOverride (outbound callers)", async () => {
|
||||
const { cfg, workspace } = await setupUiAndConfigAvatarWorkspace();
|
||||
|
||||
// Without the opt-in, outbound callers get the per-agent identity avatar, not the UI override.
|
||||
// Without the opt-in, outbound callers get the per-agent identity avatar,
|
||||
// not the UI override.
|
||||
await expectLocalAvatarPath(cfg, workspace, "cfg-avatar.png");
|
||||
});
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Covers human-delay identity config inheritance.
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { resolveHumanDelayConfig } from "./identity.js";
|
||||
@@ -9,6 +10,8 @@ describe("resolveHumanDelayConfig", () => {
|
||||
});
|
||||
|
||||
it("merges defaults with per-agent overrides", () => {
|
||||
// Partial agent overrides should preserve unspecified timing bounds from
|
||||
// defaults while replacing the fields the agent owns.
|
||||
const cfg: OpenClawConfig = {
|
||||
agents: {
|
||||
defaults: {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Documents response-prefix cascade across global, channel, and account scopes.
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { resolveResponsePrefix, resolveEffectiveMessagesConfig } from "./identity.js";
|
||||
@@ -38,6 +39,7 @@ describe("resolveResponsePrefix with per-channel override", () => {
|
||||
|
||||
describe("channel-level prefix", () => {
|
||||
it("returns channel prefix when set, ignoring global", () => {
|
||||
// Channel scope is more specific than the global messages default.
|
||||
const cfg = makeConfig({
|
||||
messages: { responsePrefix: "[Global] " },
|
||||
channels: {
|
||||
@@ -58,6 +60,7 @@ describe("resolveResponsePrefix with per-channel override", () => {
|
||||
});
|
||||
|
||||
it("channel empty string stops cascade (no global prefix applied)", () => {
|
||||
// Empty string is an explicit operator choice, not an unset value.
|
||||
const cfg = makeConfig({
|
||||
messages: { responsePrefix: "[Global] " },
|
||||
channels: {
|
||||
@@ -229,6 +232,8 @@ describe("resolveResponsePrefix with per-channel override", () => {
|
||||
// ─── Full cascade ─────────────────────────────────────────────────
|
||||
|
||||
describe("full 4-level cascade", () => {
|
||||
// Specificity order: account, channel, agent/global identity fallback,
|
||||
// then global messages config.
|
||||
const fullCfg = makeConfig({
|
||||
agents: {
|
||||
list: [{ id: "main", identity: { name: "TestBot" } }],
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Verifies image-generation task lookup, duplicate guards, and prompt status text.
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
buildActiveImageGenerationTaskPromptContextForSession,
|
||||
@@ -32,6 +33,7 @@ vi.mock("../tasks/runtime-internal.js", () => taskRuntimeInternalMocks);
|
||||
function expectActiveImageGenerationTask(
|
||||
task: ReturnType<typeof findActiveImageGenerationTaskForSession>,
|
||||
): NonNullable<ReturnType<typeof findActiveImageGenerationTaskForSession>> {
|
||||
// Narrows optional lookups in tests that need provider/status helper calls.
|
||||
if (task == null) {
|
||||
throw new Error("Expected active image generation task");
|
||||
}
|
||||
@@ -180,6 +182,8 @@ describe("image generation task status", () => {
|
||||
});
|
||||
|
||||
it("uses a matching recent-start request key as a succeeded duplicate guard", () => {
|
||||
// The request key ties a tool call to its persisted completion so the
|
||||
// model gets status guidance instead of starting the same image twice.
|
||||
const now = Date.now();
|
||||
recordRecentMediaGenerationTaskStartForSession({
|
||||
sessionKey: "agent:main",
|
||||
@@ -228,6 +232,8 @@ describe("image generation task status", () => {
|
||||
});
|
||||
|
||||
it("does not use a delivery-blocked image task as a succeeded duplicate guard", () => {
|
||||
// If completion delivery failed, suppressing a retry would strand the
|
||||
// requester without an image even though the provider task succeeded.
|
||||
const now = Date.now();
|
||||
recordRecentMediaGenerationTaskStartForSession({
|
||||
sessionKey: "agent:main",
|
||||
@@ -312,6 +318,8 @@ describe("image generation task status", () => {
|
||||
});
|
||||
|
||||
it("preserves earlier recent request keys when another image request starts", () => {
|
||||
// Multiple image requests can be active/recent in the same session; a new
|
||||
// request must not erase an older request key that can still match status.
|
||||
const now = Date.now();
|
||||
recordRecentMediaGenerationTaskStartForSession({
|
||||
sessionKey: "agent:main",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Covers agent image-sanitization limit config normalization.
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { resolveImageSanitizationLimits } from "./image-sanitization.js";
|
||||
|
||||
Reference in New Issue
Block a user