mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-06-14 02:40:45 +08:00
refactor(extraction): remove legacy extract prompt path
This commit is contained in:
@@ -109,12 +109,11 @@ assert.equal(defaultSettings.loadNativeHydrateThresholdRecords, 30000);
|
||||
assert.equal(defaultSettings.nativeRolloutVersion, 2);
|
||||
assert.equal(defaultSettings.nativeEngineFailOpen, true);
|
||||
assert.equal(defaultSettings.graphNativeForceDisable, false);
|
||||
assert.equal(defaultSettings.extractPipelineVersion, "split-v1");
|
||||
assert.equal(defaultSettings.taskProfilesVersion, 3);
|
||||
assert.equal(defaultSettings.extractObjectivePrompt, "");
|
||||
assert.equal(defaultSettings.extractSubjectivePrompt, "");
|
||||
assert.ok(defaultSettings.taskProfiles);
|
||||
assert.ok(defaultSettings.taskProfiles.extract);
|
||||
assert.equal(defaultSettings.taskProfiles.extract, undefined);
|
||||
assert.ok(defaultSettings.taskProfiles.extract_objective);
|
||||
assert.ok(defaultSettings.taskProfiles.extract_subjective);
|
||||
assert.ok(defaultSettings.taskProfiles.recall);
|
||||
|
||||
@@ -194,13 +194,14 @@ function characterKnowledgeEntries(graph) {
|
||||
async function captureTaskTypesForExtract(settings, options = {}) {
|
||||
const graph = createGraphWithCharacter();
|
||||
const capturedTaskTypes = [];
|
||||
const capturedPayloads = [];
|
||||
const restore = setTestOverrides({
|
||||
llm: {
|
||||
async callLLMForJSON(payload = {}) {
|
||||
capturedTaskTypes.push(payload.taskType);
|
||||
capturedPayloads.push(payload);
|
||||
if (payload.taskType === "extract_objective") return objectivePayload();
|
||||
if (payload.taskType === "extract_subjective") return subjectivePayload();
|
||||
if (payload.taskType === "extract") return { operations: [], cognitionUpdates: [], regionUpdates: {} };
|
||||
return { operations: [], cognitionUpdates: [], regionUpdates: {} };
|
||||
},
|
||||
},
|
||||
@@ -215,53 +216,12 @@ async function captureTaskTypesForExtract(settings, options = {}) {
|
||||
params.settings = settings;
|
||||
}
|
||||
const result = await extractMemories(params);
|
||||
return { graph, result, capturedTaskTypes };
|
||||
return { graph, result, capturedTaskTypes, capturedPayloads };
|
||||
} finally {
|
||||
restore();
|
||||
}
|
||||
}
|
||||
|
||||
function cloneJson(value) {
|
||||
return JSON.parse(JSON.stringify(value));
|
||||
}
|
||||
|
||||
function createCustomizedLegacyExtractProfileSettings() {
|
||||
const taskProfiles = cloneJson(defaultSettings.taskProfiles);
|
||||
const baseProfile = taskProfiles.extract.profiles[0];
|
||||
const customProfile = {
|
||||
...baseProfile,
|
||||
id: "custom-legacy-extract-profile",
|
||||
name: "Custom legacy extract profile",
|
||||
builtin: false,
|
||||
blocks: (Array.isArray(baseProfile.blocks) ? baseProfile.blocks : []).map((block, index) =>
|
||||
index === 0
|
||||
? { ...block, content: `${String(block.content || "")}\nCUSTOM_LEGACY_EXTRACT_SENTINEL` }
|
||||
: { ...block },
|
||||
),
|
||||
};
|
||||
taskProfiles.extract = {
|
||||
activeProfileId: customProfile.id,
|
||||
profiles: [baseProfile, customProfile],
|
||||
};
|
||||
return {
|
||||
...defaultSettings,
|
||||
extractPipelineVersion: "split-v1",
|
||||
taskProfiles,
|
||||
};
|
||||
}
|
||||
|
||||
function createDefaultExtractProfileSettings(mutator) {
|
||||
const taskProfiles = cloneJson(defaultSettings.taskProfiles);
|
||||
const extractProfiles = taskProfiles.extract.profiles || [];
|
||||
const defaultProfile = extractProfiles.find((profile) => profile.id === "default") || extractProfiles[0];
|
||||
mutator?.(defaultProfile, taskProfiles.extract);
|
||||
return {
|
||||
...defaultSettings,
|
||||
extractPipelineVersion: "split-v1",
|
||||
taskProfiles,
|
||||
};
|
||||
}
|
||||
|
||||
// Phase 4 default switch: omitting settings should use the split pipeline by default.
|
||||
{
|
||||
const { result, capturedTaskTypes } = await captureTaskTypesForExtract(undefined, {
|
||||
@@ -276,19 +236,68 @@ function createDefaultExtractProfileSettings(mutator) {
|
||||
);
|
||||
}
|
||||
|
||||
// Phase 4 default switch: the default settings object should request split-v1.
|
||||
// The default settings object should always use objective+subjective split extraction.
|
||||
{
|
||||
const { result, capturedTaskTypes } = await captureTaskTypesForExtract({
|
||||
const { result, capturedTaskTypes, capturedPayloads } = await captureTaskTypesForExtract({
|
||||
...defaultSettings,
|
||||
});
|
||||
|
||||
assert.equal(result.success, true);
|
||||
assert.equal(defaultSettings.extractPipelineVersion, "split-v1");
|
||||
assert.deepEqual(
|
||||
capturedTaskTypes,
|
||||
["extract_objective", "extract_subjective"],
|
||||
"defaultSettings should call split objective+subjective extraction",
|
||||
);
|
||||
const subjectivePayloadText = JSON.stringify(
|
||||
capturedPayloads.find((payload) => payload.taskType === "extract_subjective") || {},
|
||||
);
|
||||
const subjectivePayload = capturedPayloads.find(
|
||||
(payload) => payload.taskType === "extract_subjective",
|
||||
);
|
||||
const objectiveRefMapBlock = subjectivePayload?.promptMessages?.find(
|
||||
(message) => message.sourceKey === "objectiveRefMap",
|
||||
);
|
||||
assert.match(
|
||||
subjectivePayloadText,
|
||||
/evt-clock/,
|
||||
"subjective extraction prompt should receive objective draft/ref context",
|
||||
);
|
||||
assert.match(
|
||||
String(objectiveRefMapBlock?.content || ""),
|
||||
/evt-clock/,
|
||||
"subjective extraction prompt should render objectiveRefMap with objective refs",
|
||||
);
|
||||
}
|
||||
|
||||
// Removed legacy knobs are ignored and must not revive the old single extract task.
|
||||
for (const legacyPatch of [
|
||||
{ extractPrompt: "CUSTOM LEGACY EXTRACT PROMPT" },
|
||||
{ extractPipelineVersion: "legacy-single" },
|
||||
{
|
||||
taskProfiles: {
|
||||
...defaultSettings.taskProfiles,
|
||||
extract: {
|
||||
activeProfileId: "legacy-custom",
|
||||
profiles: [
|
||||
{
|
||||
id: "legacy-custom",
|
||||
taskType: "extract",
|
||||
builtin: false,
|
||||
blocks: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
]) {
|
||||
const { result, capturedTaskTypes } = await captureTaskTypesForExtract({
|
||||
...defaultSettings,
|
||||
...legacyPatch,
|
||||
});
|
||||
|
||||
assert.equal(result.success, true);
|
||||
assert.deepEqual(capturedTaskTypes, ["extract_objective", "extract_subjective"]);
|
||||
assert.equal(capturedTaskTypes.includes("extract"), false);
|
||||
}
|
||||
|
||||
// split-v1 calls objective then subjective, merges both stage outputs, and commits once.
|
||||
@@ -310,7 +319,7 @@ function createDefaultExtractProfileSettings(mutator) {
|
||||
const result = await extractMemories({
|
||||
graph,
|
||||
...baseExtractParams,
|
||||
settings: { extractPipelineVersion: "split-v1" },
|
||||
settings: defaultSettings,
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
@@ -366,7 +375,7 @@ function createDefaultExtractProfileSettings(mutator) {
|
||||
const result = await extractMemories({
|
||||
graph,
|
||||
...baseExtractParams,
|
||||
settings: { extractPipelineVersion: "split-v1" },
|
||||
settings: defaultSettings,
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
@@ -383,92 +392,4 @@ function createDefaultExtractProfileSettings(mutator) {
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy guard: a non-empty legacy extractPrompt should force the single extract taskType path.
|
||||
{
|
||||
const { result, capturedTaskTypes } = await captureTaskTypesForExtract({
|
||||
...defaultSettings,
|
||||
extractPipelineVersion: "split-v1",
|
||||
extractPrompt: "CUSTOM LEGACY EXTRACT PROMPT",
|
||||
});
|
||||
|
||||
assert.equal(result.success, true);
|
||||
assert.deepEqual(
|
||||
capturedTaskTypes,
|
||||
["extract"],
|
||||
"non-empty extractPrompt should guard back to legacy taskType extract",
|
||||
);
|
||||
}
|
||||
|
||||
// Legacy guard: an active customized legacy extract task profile should force the single extract path.
|
||||
{
|
||||
const { result, capturedTaskTypes } = await captureTaskTypesForExtract(
|
||||
createCustomizedLegacyExtractProfileSettings(),
|
||||
);
|
||||
|
||||
assert.equal(result.success, true);
|
||||
assert.deepEqual(
|
||||
capturedTaskTypes,
|
||||
["extract"],
|
||||
"customized active taskProfiles.extract profile should guard back to legacy taskType extract",
|
||||
);
|
||||
}
|
||||
|
||||
// Legacy guard: an explicit legacy override should always keep the single extract path.
|
||||
{
|
||||
const { result, capturedTaskTypes } = await captureTaskTypesForExtract({
|
||||
...defaultSettings,
|
||||
extractPipelineVersion: "legacy-single",
|
||||
});
|
||||
|
||||
assert.equal(result.success, true);
|
||||
assert.deepEqual(capturedTaskTypes, ["extract"]);
|
||||
}
|
||||
|
||||
// Legacy guard: migrated legacy default-looking profiles are conservative legacy.
|
||||
{
|
||||
const { result, capturedTaskTypes } = await captureTaskTypesForExtract(
|
||||
createDefaultExtractProfileSettings((profile) => {
|
||||
profile.metadata = {
|
||||
...(profile.metadata || {}),
|
||||
migratedFromLegacy: true,
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
assert.equal(result.success, true);
|
||||
assert.deepEqual(capturedTaskTypes, ["extract"]);
|
||||
}
|
||||
|
||||
// Legacy guard: stale default profile metadata is conservative legacy.
|
||||
{
|
||||
const { result, capturedTaskTypes } = await captureTaskTypesForExtract(
|
||||
createDefaultExtractProfileSettings((profile) => {
|
||||
profile.metadata = {
|
||||
...(profile.metadata || {}),
|
||||
defaultTemplateFingerprint: "stale-fingerprint",
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
assert.equal(result.success, true);
|
||||
assert.deepEqual(capturedTaskTypes, ["extract"]);
|
||||
}
|
||||
|
||||
// Legacy guard: modified default profile content is conservative legacy even if id/builtin remain default.
|
||||
{
|
||||
const { result, capturedTaskTypes } = await captureTaskTypesForExtract(
|
||||
createDefaultExtractProfileSettings((profile) => {
|
||||
profile.blocks = (profile.blocks || []).map((block, index) =>
|
||||
index === 0
|
||||
? { ...block, content: `${String(block.content || "")}
|
||||
CUSTOM_DEFAULT_PROFILE_SENTINEL` }
|
||||
: { ...block },
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
assert.equal(result.success, true);
|
||||
assert.deepEqual(capturedTaskTypes, ["extract"]);
|
||||
}
|
||||
|
||||
console.log("extractor-split-pipeline tests passed");
|
||||
|
||||
@@ -4,8 +4,8 @@ import { createDefaultTaskProfiles } from "../prompting/prompt-profiles.js";
|
||||
|
||||
function buildSettingsWithExtractGeneration(generation) {
|
||||
const taskProfiles = createDefaultTaskProfiles();
|
||||
taskProfiles.extract.profiles[0].generation = {
|
||||
...taskProfiles.extract.profiles[0].generation,
|
||||
taskProfiles.extract_objective.profiles[0].generation = {
|
||||
...taskProfiles.extract_objective.profiles[0].generation,
|
||||
...generation,
|
||||
};
|
||||
return {
|
||||
@@ -28,7 +28,7 @@ const openAiLikeSettings = buildSettingsWithExtractGeneration({
|
||||
|
||||
const openAiLike = resolveTaskGenerationOptions(
|
||||
openAiLikeSettings,
|
||||
"extract",
|
||||
"extract_objective",
|
||||
{ max_completion_tokens: 256 },
|
||||
{ mode: "dedicated-openai-compatible" },
|
||||
);
|
||||
@@ -50,7 +50,7 @@ assert.ok(
|
||||
|
||||
const conservative = resolveTaskGenerationOptions(
|
||||
openAiLikeSettings,
|
||||
"extract",
|
||||
"extract_objective",
|
||||
{ max_completion_tokens: 256 },
|
||||
{ mode: "sillytavern-current-model" },
|
||||
);
|
||||
@@ -74,7 +74,7 @@ const fallbackSettings = buildSettingsWithExtractGeneration({
|
||||
});
|
||||
const fallback = resolveTaskGenerationOptions(
|
||||
fallbackSettings,
|
||||
"extract",
|
||||
"extract_objective",
|
||||
{ max_completion_tokens: 300 },
|
||||
{ mode: "conservative" },
|
||||
);
|
||||
|
||||
@@ -85,8 +85,8 @@ if (originalSendOpenAIRequest === undefined) {
|
||||
|
||||
function buildStreamingSettings(generation = {}, overrides = {}) {
|
||||
const taskProfiles = createDefaultTaskProfiles();
|
||||
taskProfiles.extract.profiles[0].generation = {
|
||||
...taskProfiles.extract.profiles[0].generation,
|
||||
taskProfiles.extract_objective.profiles[0].generation = {
|
||||
...taskProfiles.extract_objective.profiles[0].generation,
|
||||
...generation,
|
||||
};
|
||||
return {
|
||||
@@ -122,7 +122,7 @@ function createSseResponse(events = [], status = 200) {
|
||||
);
|
||||
}
|
||||
|
||||
function getSnapshot(taskKey = "extract") {
|
||||
function getSnapshot(taskKey = "extract_objective") {
|
||||
return globalThis.__stBmeRuntimeDebugState?.taskLlmRequests?.[taskKey] || null;
|
||||
}
|
||||
|
||||
@@ -163,14 +163,14 @@ async function testDedicatedStreamingSuccess() {
|
||||
systemPrompt: "system",
|
||||
userPrompt: "user",
|
||||
maxRetries: 0,
|
||||
taskType: "extract",
|
||||
taskType: "extract_objective",
|
||||
requestSource: "test:stream-success",
|
||||
});
|
||||
|
||||
assert.deepEqual(result, { ok: true });
|
||||
assert.equal(fetchCount, 1);
|
||||
|
||||
const snapshot = getSnapshot("extract");
|
||||
const snapshot = getSnapshot("extract_objective");
|
||||
assert.ok(snapshot);
|
||||
assert.equal(snapshot.streamRequested ?? true, true);
|
||||
assert.equal(snapshot.streamActive ?? false, false);
|
||||
@@ -236,14 +236,14 @@ async function testDedicatedStreamingFallsBackToNonStream() {
|
||||
systemPrompt: "system",
|
||||
userPrompt: "user",
|
||||
maxRetries: 0,
|
||||
taskType: "extract",
|
||||
taskType: "extract_objective",
|
||||
requestSource: "test:stream-fallback",
|
||||
});
|
||||
|
||||
assert.deepEqual(result, { ok: true });
|
||||
assert.equal(fetchCount, 2);
|
||||
|
||||
const snapshot = getSnapshot("extract");
|
||||
const snapshot = getSnapshot("extract_objective");
|
||||
assert.ok(snapshot);
|
||||
assert.equal(snapshot.streamRequested ?? true, true);
|
||||
assert.equal(snapshot.streamCompleted ?? false, false);
|
||||
@@ -312,7 +312,7 @@ async function testDedicatedStreamingAbortDoesNotLeaveActiveState() {
|
||||
systemPrompt: "system",
|
||||
userPrompt: "user",
|
||||
maxRetries: 0,
|
||||
taskType: "extract",
|
||||
taskType: "extract_objective",
|
||||
requestSource: "test:stream-abort",
|
||||
signal: controller.signal,
|
||||
});
|
||||
@@ -325,7 +325,7 @@ async function testDedicatedStreamingAbortDoesNotLeaveActiveState() {
|
||||
(error) => error?.name === "AbortError",
|
||||
);
|
||||
|
||||
const snapshot = getSnapshot("extract");
|
||||
const snapshot = getSnapshot("extract_objective");
|
||||
assert.ok(snapshot);
|
||||
assert.equal(snapshot.streamRequested ?? true, true);
|
||||
assert.equal(snapshot.streamActive ?? false, false);
|
||||
@@ -397,14 +397,14 @@ async function testJsonRetryKeepsProfileCompletionTokens() {
|
||||
systemPrompt: "system",
|
||||
userPrompt: "user",
|
||||
maxRetries: 1,
|
||||
taskType: "extract",
|
||||
taskType: "extract_objective",
|
||||
requestSource: "test:json-retry-keeps-profile-tokens",
|
||||
});
|
||||
|
||||
assert.deepEqual(result, { ok: true });
|
||||
assert.equal(fetchCount, 2);
|
||||
|
||||
const snapshot = getSnapshot("extract");
|
||||
const snapshot = getSnapshot("extract_objective");
|
||||
assert.ok(snapshot);
|
||||
assert.equal(snapshot.requestBody?.maxTokens ?? 7777, 7777);
|
||||
assert.equal(
|
||||
@@ -456,7 +456,7 @@ async function testAnthropicRouteUsesReverseProxyAndDisablesStreaming() {
|
||||
systemPrompt: "system",
|
||||
userPrompt: "user",
|
||||
maxRetries: 0,
|
||||
taskType: "extract",
|
||||
taskType: "extract_objective",
|
||||
requestSource: "test:anthropic-route",
|
||||
});
|
||||
|
||||
@@ -467,7 +467,7 @@ async function testAnthropicRouteUsesReverseProxyAndDisablesStreaming() {
|
||||
assert.equal(requestBody?.stream, false);
|
||||
assert.ok(requestBody?.json_schema);
|
||||
|
||||
const snapshot = getSnapshot("extract");
|
||||
const snapshot = getSnapshot("extract_objective");
|
||||
assert.ok(snapshot);
|
||||
assert.equal(
|
||||
snapshot.route || snapshot.effectiveRoute || "dedicated-anthropic-claude",
|
||||
|
||||
@@ -160,7 +160,7 @@ try {
|
||||
systemPrompt: "system",
|
||||
userPrompt: "user",
|
||||
maxRetries: 0,
|
||||
taskType: "extract",
|
||||
taskType: "extract_objective",
|
||||
requestSource: "test:luker-route",
|
||||
});
|
||||
|
||||
@@ -190,7 +190,7 @@ try {
|
||||
systemPrompt: "system",
|
||||
userPrompt: "user",
|
||||
maxRetries: 0,
|
||||
taskType: "extract",
|
||||
taskType: "extract_objective",
|
||||
requestSource: "test:luker-global-stale",
|
||||
});
|
||||
|
||||
@@ -210,7 +210,7 @@ try {
|
||||
capturedFetchBody = null;
|
||||
sendOpenAIRequestCalls = 0;
|
||||
const taskProfiles = createDefaultTaskProfiles();
|
||||
taskProfiles.extract.profiles[0].generation.llm_preset = "luker-profile-alpha";
|
||||
taskProfiles.extract_objective.profiles[0].generation.llm_preset = "luker-profile-alpha";
|
||||
extensionsApi.extension_settings.st_bme = {
|
||||
llmApiUrl: "https://stale-generic-config.invalid/v1",
|
||||
llmApiKey: "sk-stale-generic",
|
||||
@@ -246,7 +246,7 @@ try {
|
||||
systemPrompt: "system",
|
||||
userPrompt: "user",
|
||||
maxRetries: 0,
|
||||
taskType: "extract",
|
||||
taskType: "extract_objective",
|
||||
requestSource: "test:luker-profile-route",
|
||||
});
|
||||
|
||||
|
||||
@@ -7777,12 +7777,12 @@ async function testLlmOutputRegexCleansResponseBeforeJsonParse() {
|
||||
delete globalThis.__stBmeRuntimeDebugState;
|
||||
|
||||
const taskProfiles = createDefaultTaskProfiles();
|
||||
taskProfiles.extract.profiles[0].regex = {
|
||||
...taskProfiles.extract.profiles[0].regex,
|
||||
taskProfiles.extract_objective.profiles[0].regex = {
|
||||
...taskProfiles.extract_objective.profiles[0].regex,
|
||||
enabled: true,
|
||||
inheritStRegex: false,
|
||||
stages: {
|
||||
...taskProfiles.extract.profiles[0].regex.stages,
|
||||
...taskProfiles.extract_objective.profiles[0].regex.stages,
|
||||
"output.rawResponse": true,
|
||||
"output.beforeParse": true,
|
||||
},
|
||||
@@ -7854,13 +7854,13 @@ async function testLlmOutputRegexCleansResponseBeforeJsonParse() {
|
||||
systemPrompt: "system",
|
||||
userPrompt: "user",
|
||||
maxRetries: 0,
|
||||
taskType: "extract",
|
||||
taskType: "extract_objective",
|
||||
requestSource: "test:output-regex",
|
||||
});
|
||||
assert.deepEqual(result, { ok: true });
|
||||
|
||||
const snapshot =
|
||||
globalThis.__stBmeRuntimeDebugState?.taskLlmRequests?.extract;
|
||||
globalThis.__stBmeRuntimeDebugState?.taskLlmRequests?.extract_objective;
|
||||
assert.ok(snapshot);
|
||||
assert.equal(snapshot.responseCleaning?.applied, true);
|
||||
assert.equal(snapshot.responseCleaning?.changed, true);
|
||||
|
||||
@@ -58,8 +58,13 @@ const settings = {
|
||||
taskProfiles: createDefaultTaskProfiles(),
|
||||
};
|
||||
|
||||
const extractPromptBuild = await buildTaskPrompt(settings, "extract", {
|
||||
taskName: "extract",
|
||||
await assert.rejects(
|
||||
() => buildTaskPrompt(settings, "extract", { taskName: "extract" }),
|
||||
/Unsupported task type: extract/,
|
||||
);
|
||||
|
||||
const extractPromptBuild = await buildTaskPrompt(settings, "extract_objective", {
|
||||
taskName: "extract_objective",
|
||||
charDescription: "角色描述",
|
||||
userPersona: "用户设定",
|
||||
recentMessages: "A: 你好\nB: 世界",
|
||||
@@ -88,11 +93,11 @@ const extractFormatBlock = extractPayload.promptMessages.find(
|
||||
const extractRulesBlock = extractPayload.promptMessages.find(
|
||||
(message) => message.blockName === "行为规则",
|
||||
);
|
||||
assert.match(String(extractFormatBlock?.content || ""), /cognitionUpdates/);
|
||||
assert.doesNotMatch(String(extractFormatBlock?.content || ""), /cognitionUpdates/);
|
||||
assert.match(String(extractFormatBlock?.content || ""), /regionUpdates/);
|
||||
assert.match(String(extractFormatBlock?.content || ""), /batchStoryTime/);
|
||||
assert.match(String(extractFormatBlock?.content || ""), /storyTime/);
|
||||
assert.match(String(extractRulesBlock?.content || ""), /涉及到的角色都尽量尝试补 cognitionUpdates/);
|
||||
assert.match(String(extractRulesBlock?.content || ""), /禁止输出/);
|
||||
assert.match(String(extractRulesBlock?.content || ""), /batchStoryTime/);
|
||||
assert.deepEqual(
|
||||
extractPayload.promptMessages
|
||||
@@ -203,8 +208,8 @@ initializeHostAdapter({
|
||||
},
|
||||
});
|
||||
|
||||
const regexAwarePromptBuild = await buildTaskPrompt(settings, "extract", {
|
||||
taskName: "extract",
|
||||
const regexAwarePromptBuild = await buildTaskPrompt(settings, "extract_objective", {
|
||||
taskName: "extract_objective",
|
||||
charDescription: "",
|
||||
userPersona: "",
|
||||
recentMessages: "这里会被 chatMessages 回填",
|
||||
@@ -260,29 +265,13 @@ initializeHostAdapter({});
|
||||
const splitContextTaskProfiles = createDefaultTaskProfiles();
|
||||
const subjectiveProfile = splitContextTaskProfiles.extract_subjective.profiles[0];
|
||||
subjectiveProfile.blocks = [
|
||||
createBuiltinPromptBlock("extract_subjective", "objectiveExtractionDraft", {
|
||||
name: "客观提取草稿",
|
||||
order: 0,
|
||||
}),
|
||||
createBuiltinPromptBlock("extract_subjective", "objectiveRefMap", {
|
||||
name: "客观引用映射",
|
||||
order: 1,
|
||||
}),
|
||||
createBuiltinPromptBlock("extract_subjective", "ownerContext", {
|
||||
name: "视角主体上下文",
|
||||
order: 2,
|
||||
}),
|
||||
createBuiltinPromptBlock("extract_subjective", "batchStoryTime", {
|
||||
name: "批次故事时间",
|
||||
order: 3,
|
||||
}),
|
||||
createBuiltinPromptBlock("extract_subjective", "relevantPovMemories", {
|
||||
name: "相关主观记忆",
|
||||
order: 4,
|
||||
order: 0,
|
||||
}),
|
||||
createBuiltinPromptBlock("extract_subjective", "cognitionStateDigest", {
|
||||
name: "认知状态摘要",
|
||||
order: 5,
|
||||
order: 1,
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -305,19 +294,22 @@ const splitContextPayload = buildTaskLlmPayload(
|
||||
splitContextPromptBuild,
|
||||
"fallback-user",
|
||||
);
|
||||
assert.deepEqual(
|
||||
splitContextPayload.promptMessages
|
||||
.map((message) => message.sourceKey)
|
||||
.filter(Boolean),
|
||||
[
|
||||
"objectiveExtractionDraft",
|
||||
"objectiveRefMap",
|
||||
"ownerContext",
|
||||
"batchStoryTime",
|
||||
"relevantPovMemories",
|
||||
"cognitionStateDigest",
|
||||
],
|
||||
);
|
||||
const splitContextSourceKeys = splitContextPayload.promptMessages
|
||||
.map((message) => message.sourceKey)
|
||||
.filter(Boolean);
|
||||
for (const sourceKey of [
|
||||
"objectiveExtractionDraft",
|
||||
"objectiveRefMap",
|
||||
"ownerContext",
|
||||
"batchStoryTime",
|
||||
"relevantPovMemories",
|
||||
"cognitionStateDigest",
|
||||
]) {
|
||||
assert.ok(
|
||||
splitContextSourceKeys.includes(sourceKey),
|
||||
`subjective prompt should include ${sourceKey}`,
|
||||
);
|
||||
}
|
||||
assert.match(
|
||||
String(
|
||||
splitContextPayload.promptMessages.find(
|
||||
|
||||
@@ -55,7 +55,7 @@ const settings = {
|
||||
taskProfilesVersion: 3,
|
||||
taskProfiles: createDefaultTaskProfiles(),
|
||||
};
|
||||
const extractProfile = settings.taskProfiles.extract.profiles[0];
|
||||
const extractProfile = settings.taskProfiles.extract_objective.profiles[0];
|
||||
extractProfile.regex = {
|
||||
...(extractProfile.regex || {}),
|
||||
enabled: true,
|
||||
@@ -105,8 +105,8 @@ extractProfile.regex = {
|
||||
],
|
||||
};
|
||||
|
||||
const promptBuild = await buildTaskPrompt(settings, "extract", {
|
||||
taskName: "extract",
|
||||
const promptBuild = await buildTaskPrompt(settings, "extract_objective", {
|
||||
taskName: "extract_objective",
|
||||
charDescription: "",
|
||||
userPersona: "",
|
||||
recentMessages: "这里会被 chatMessages 回填",
|
||||
|
||||
@@ -14,7 +14,8 @@ import {
|
||||
} from "../prompting/prompt-profiles.js";
|
||||
|
||||
const legacySettings = {
|
||||
extractPrompt: "旧提取提示",
|
||||
extractObjectivePrompt: "旧客观提取提示",
|
||||
extractSubjectivePrompt: "旧主观提取提示",
|
||||
recallPrompt: "旧召回提示",
|
||||
compressPrompt: "",
|
||||
synopsisPrompt: "",
|
||||
@@ -25,7 +26,7 @@ const legacySettings = {
|
||||
const migrated = migrateLegacyTaskProfiles(legacySettings);
|
||||
assert.equal(migrated.taskProfilesVersion, 3);
|
||||
assert.ok(migrated.taskProfiles);
|
||||
assert.ok(migrated.taskProfiles.extract);
|
||||
assert.ok(migrated.taskProfiles.extract_objective);
|
||||
assert.ok(migrated.taskProfiles.recall);
|
||||
assert.ok(migrated.taskProfiles.planner);
|
||||
|
||||
@@ -34,9 +35,9 @@ const extractProfile = getActiveTaskProfile(
|
||||
...legacySettings,
|
||||
taskProfiles: migrated.taskProfiles,
|
||||
},
|
||||
"extract",
|
||||
"extract_objective",
|
||||
);
|
||||
assert.equal(extractProfile.taskType, "extract");
|
||||
assert.equal(extractProfile.taskType, "extract_objective");
|
||||
assert.equal(extractProfile.id, "default");
|
||||
assert.ok(Array.isArray(extractProfile.blocks));
|
||||
assert.equal(extractProfile.blocks.length, 16);
|
||||
@@ -105,15 +106,17 @@ assert.deepEqual(
|
||||
);
|
||||
assert.equal(
|
||||
extractProfile.metadata.legacyPromptField,
|
||||
"extractPrompt",
|
||||
"extractObjectivePrompt",
|
||||
);
|
||||
assert.equal(
|
||||
extractProfile.metadata.legacyPromptSnapshot,
|
||||
"旧提取提示",
|
||||
"旧客观提取提示",
|
||||
);
|
||||
|
||||
const defaults = createDefaultTaskProfiles();
|
||||
assert.ok(defaults.extract.profiles.length > 0);
|
||||
assert.equal(defaults.extract, undefined);
|
||||
assert.ok(defaults.extract_objective.profiles.length > 0);
|
||||
assert.ok(defaults.extract_subjective.profiles.length > 0);
|
||||
assert.ok(defaults.recall.profiles.length > 0);
|
||||
assert.ok(defaults.compress.profiles.length > 0);
|
||||
assert.ok(defaults.synopsis.profiles.length > 0);
|
||||
@@ -406,7 +409,7 @@ const upgradedLegacyDefault = getActiveTaskProfile(
|
||||
profiles: [
|
||||
{
|
||||
id: "default",
|
||||
taskType: "extract",
|
||||
taskType: "extract_objective",
|
||||
builtin: true,
|
||||
blocks: [
|
||||
{
|
||||
@@ -471,14 +474,18 @@ const upgradedLegacyDefault = getActiveTaskProfile(
|
||||
},
|
||||
},
|
||||
},
|
||||
"extract",
|
||||
"extract_objective",
|
||||
);
|
||||
assert.equal(upgradedLegacyDefault.blocks.length, 16);
|
||||
assert.equal(upgradedLegacyDefault.blocks[0].name, "抬头");
|
||||
assert.match(upgradedLegacyDefault.blocks[0].content, /虚拟的世界/);
|
||||
assert.equal(upgradedLegacyDefault.blocks[0].role, "system");
|
||||
assert.equal(upgradedLegacyDefault.blocks[0].injectionMode, "relative");
|
||||
assert.equal(upgradedLegacyDefault.blocks[1].content, "保留我自己的角色定义");
|
||||
assert.match(
|
||||
upgradedLegacyDefault.blocks[1].content,
|
||||
/客观事实提取师/,
|
||||
"removed legacy extract profile should be replaced by the current objective extraction default",
|
||||
);
|
||||
const upgradedIdentityAck = upgradedLegacyDefault.blocks.find(
|
||||
(block) => block.id === "default-identity-ack",
|
||||
);
|
||||
@@ -497,18 +504,18 @@ assert.ok(
|
||||
assert.equal(upgradedInfoAck.role, "assistant");
|
||||
assert.equal(upgradedLegacyDefault.blocks[14].id, "default-format");
|
||||
assert.equal(upgradedLegacyDefault.blocks[15].id, "default-rules");
|
||||
assert.equal(upgradedLegacyDefault.blocks[14].content, "保留我自己的输出格式");
|
||||
assert.equal(upgradedLegacyDefault.blocks[15].content, "保留我自己的行为规则");
|
||||
assert.match(upgradedLegacyDefault.blocks[14].content, /batchStoryTime/);
|
||||
assert.match(upgradedLegacyDefault.blocks[15].content, /禁止输出/);
|
||||
assert.equal(upgradedLegacyDefault.blocks[14].role, "user");
|
||||
assert.equal(upgradedLegacyDefault.blocks[15].role, "user");
|
||||
|
||||
const currentDefaults = createDefaultTaskProfiles();
|
||||
const currentDefaultExtract = currentDefaults.extract.profiles[0];
|
||||
const currentDefaultExtract = currentDefaults.extract_objective.profiles[0];
|
||||
|
||||
const staleBuiltinDefaults = ensureTaskProfiles({
|
||||
taskProfilesVersion: 3,
|
||||
taskProfiles: {
|
||||
extract: {
|
||||
extract_objective: {
|
||||
activeProfileId: "default",
|
||||
profiles: [
|
||||
{
|
||||
@@ -528,7 +535,7 @@ const staleBuiltinDefaults = ensureTaskProfiles({
|
||||
},
|
||||
{
|
||||
id: "extract-custom-1",
|
||||
taskType: "extract",
|
||||
taskType: "extract_objective",
|
||||
builtin: false,
|
||||
name: "我的自定义预设",
|
||||
promptMode: "block-based",
|
||||
@@ -561,10 +568,10 @@ const staleBuiltinDefaults = ensureTaskProfiles({
|
||||
},
|
||||
},
|
||||
});
|
||||
const refreshedDefaultExtract = staleBuiltinDefaults.extract.profiles.find(
|
||||
const refreshedDefaultExtract = staleBuiltinDefaults.extract_objective.profiles.find(
|
||||
(profile) => profile.id === "default",
|
||||
);
|
||||
const preservedCustomExtract = staleBuiltinDefaults.extract.profiles.find(
|
||||
const preservedCustomExtract = staleBuiltinDefaults.extract_objective.profiles.find(
|
||||
(profile) => profile.id === "extract-custom-1",
|
||||
);
|
||||
|
||||
@@ -586,7 +593,7 @@ assert.equal(
|
||||
assert.match(
|
||||
refreshedDefaultExtract.blocks.find((block) => block.id === "default-format")
|
||||
?.content || "",
|
||||
/cognitionUpdates/,
|
||||
/regionUpdates/,
|
||||
);
|
||||
assert.ok(preservedCustomExtract);
|
||||
assert.equal(
|
||||
@@ -597,7 +604,7 @@ assert.equal(
|
||||
const sameStampBuiltinDefault = ensureTaskProfiles({
|
||||
taskProfilesVersion: 3,
|
||||
taskProfiles: {
|
||||
extract: {
|
||||
extract_objective: {
|
||||
activeProfileId: "default",
|
||||
profiles: [
|
||||
{
|
||||
@@ -615,7 +622,7 @@ const sameStampBuiltinDefault = ensureTaskProfiles({
|
||||
},
|
||||
},
|
||||
});
|
||||
const sameStampDefaultExtract = sameStampBuiltinDefault.extract.profiles.find(
|
||||
const sameStampDefaultExtract = sameStampBuiltinDefault.extract_objective.profiles.find(
|
||||
(profile) => profile.id === "default",
|
||||
);
|
||||
assert.equal(
|
||||
@@ -627,7 +634,7 @@ assert.equal(
|
||||
const sameTimestampButChangedTemplateDefaults = ensureTaskProfiles({
|
||||
taskProfilesVersion: 3,
|
||||
taskProfiles: {
|
||||
extract: {
|
||||
extract_objective: {
|
||||
activeProfileId: "default",
|
||||
profiles: [
|
||||
{
|
||||
@@ -647,7 +654,7 @@ const sameTimestampButChangedTemplateDefaults = ensureTaskProfiles({
|
||||
},
|
||||
});
|
||||
const fingerprintRefreshedDefault =
|
||||
sameTimestampButChangedTemplateDefaults.extract.profiles.find(
|
||||
sameTimestampButChangedTemplateDefaults.extract_objective.profiles.find(
|
||||
(profile) => profile.id === "default",
|
||||
);
|
||||
assert.equal(
|
||||
@@ -692,11 +699,11 @@ const legacyRegexSettings = {
|
||||
taskProfilesVersion: 3,
|
||||
taskProfiles: createDefaultTaskProfiles(),
|
||||
};
|
||||
legacyRegexSettings.taskProfiles.extract.activeProfileId = "default";
|
||||
legacyRegexSettings.taskProfiles.extract.profiles.push(
|
||||
normalizeTaskProfile("extract", {
|
||||
legacyRegexSettings.taskProfiles.extract_objective.activeProfileId = "default";
|
||||
legacyRegexSettings.taskProfiles.extract_objective.profiles.push(
|
||||
normalizeTaskProfile("extract_objective", {
|
||||
id: "extract-legacy-regex",
|
||||
taskType: "extract",
|
||||
taskType: "extract_objective",
|
||||
name: "旧正则副本",
|
||||
builtin: false,
|
||||
regex: {
|
||||
@@ -729,7 +736,7 @@ assert.deepEqual(
|
||||
],
|
||||
);
|
||||
assert.deepEqual(
|
||||
migratedLegacyRegex.settings.taskProfiles.extract.profiles.find(
|
||||
migratedLegacyRegex.settings.taskProfiles.extract_objective.profiles.find(
|
||||
(profile) => profile.id === "extract-legacy-regex",
|
||||
)?.regex?.localRules || [],
|
||||
[],
|
||||
@@ -761,10 +768,10 @@ const existingGlobalRegexSettings = {
|
||||
},
|
||||
taskProfiles: createDefaultTaskProfiles(),
|
||||
};
|
||||
existingGlobalRegexSettings.taskProfiles.extract.profiles.push(
|
||||
normalizeTaskProfile("extract", {
|
||||
existingGlobalRegexSettings.taskProfiles.extract_objective.profiles.push(
|
||||
normalizeTaskProfile("extract_objective", {
|
||||
id: "extract-legacy-extra",
|
||||
taskType: "extract",
|
||||
taskType: "extract_objective",
|
||||
name: "旧规则补充",
|
||||
builtin: false,
|
||||
regex: {
|
||||
@@ -807,7 +814,7 @@ const importedLegacyProfileMigration = migrateLegacyProfileRegexToGlobal(
|
||||
localRules: [],
|
||||
},
|
||||
{
|
||||
taskType: "extract",
|
||||
taskType: "extract_objective",
|
||||
regex: {
|
||||
enabled: false,
|
||||
inheritStRegex: false,
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
cloneTaskProfile,
|
||||
createBuiltinPromptBlock,
|
||||
createCustomPromptBlock,
|
||||
createDefaultTaskProfile,
|
||||
createDefaultTaskProfiles,
|
||||
createLocalRegexRule,
|
||||
exportTaskProfile,
|
||||
@@ -18,22 +19,22 @@ import {
|
||||
} from "../prompting/prompt-profiles.js";
|
||||
|
||||
const taskProfiles = createDefaultTaskProfiles();
|
||||
const baseProfile = taskProfiles.extract.profiles[0];
|
||||
const baseProfile = taskProfiles.extract_objective.profiles[0];
|
||||
assert.equal(baseProfile.generation.llm_preset, "");
|
||||
|
||||
const clonedProfile = cloneTaskProfile(baseProfile, {
|
||||
taskType: "extract",
|
||||
taskType: "extract_objective",
|
||||
name: "激进提取",
|
||||
});
|
||||
clonedProfile.generation.llm_preset = "Recall-API";
|
||||
clonedProfile.blocks = [
|
||||
...clonedProfile.blocks,
|
||||
createBuiltinPromptBlock("extract", "userMessage", {
|
||||
createBuiltinPromptBlock("extract_objective", "userMessage", {
|
||||
name: "用户消息块",
|
||||
injectionMode: "prepend",
|
||||
order: 1,
|
||||
}),
|
||||
createCustomPromptBlock("extract", {
|
||||
createCustomPromptBlock("extract_objective", {
|
||||
name: "补充说明",
|
||||
content: "请关注 {{userMessage}}",
|
||||
role: "user",
|
||||
@@ -41,20 +42,20 @@ clonedProfile.blocks = [
|
||||
}),
|
||||
];
|
||||
clonedProfile.regex.localRules = [
|
||||
createLocalRegexRule("extract", {
|
||||
createLocalRegexRule("extract_objective", {
|
||||
script_name: "裁边",
|
||||
find_regex: "/^foo/g",
|
||||
replace_string: "bar",
|
||||
}),
|
||||
];
|
||||
|
||||
const updatedProfiles = upsertTaskProfile(taskProfiles, "extract", clonedProfile, {
|
||||
const updatedProfiles = upsertTaskProfile(taskProfiles, "extract_objective", clonedProfile, {
|
||||
setActive: true,
|
||||
});
|
||||
|
||||
const activeProfile = getActiveTaskProfile(
|
||||
{ taskProfiles: updatedProfiles },
|
||||
"extract",
|
||||
"extract_objective",
|
||||
);
|
||||
assert.equal(activeProfile.name, "激进提取");
|
||||
assert.equal(activeProfile.blocks.length, 18);
|
||||
@@ -75,16 +76,16 @@ assert.equal(activeProfile.generation.llm_preset, "Recall-API");
|
||||
|
||||
const exported = exportTaskProfile(
|
||||
updatedProfiles,
|
||||
"extract",
|
||||
"extract_objective",
|
||||
clonedProfile.id,
|
||||
);
|
||||
assert.equal(exported.format, "st-bme-task-profile");
|
||||
assert.equal(exported.taskType, "extract");
|
||||
assert.equal(exported.taskType, "extract_objective");
|
||||
assert.equal(exported.profile.name, "激进提取");
|
||||
assert.equal(exported.profile.generation.llm_preset, "Recall-API");
|
||||
|
||||
const imported = importTaskProfile(updatedProfiles, JSON.stringify(exported));
|
||||
assert.equal(imported.taskType, "extract");
|
||||
assert.equal(imported.taskType, "extract_objective");
|
||||
assert.notEqual(imported.profile.id, clonedProfile.id);
|
||||
assert.equal(imported.profile.generation.llm_preset, "Recall-API");
|
||||
assert.ok(
|
||||
@@ -93,14 +94,29 @@ assert.ok(
|
||||
),
|
||||
);
|
||||
|
||||
const restoredProfiles = restoreDefaultTaskProfile(imported.taskProfiles, "extract");
|
||||
const restoredProfiles = restoreDefaultTaskProfile(imported.taskProfiles, "extract_objective");
|
||||
const restoredActive = getActiveTaskProfile(
|
||||
{ taskProfiles: restoredProfiles },
|
||||
"extract",
|
||||
"extract_objective",
|
||||
);
|
||||
assert.equal(restoredActive.id, "default");
|
||||
assert.equal(getLegacyPromptFieldForTask("extract"), "extractPrompt");
|
||||
assert.equal(getTaskTypeMeta("extract").label, "旧提取");
|
||||
assert.equal(getLegacyPromptFieldForTask("extract"), "");
|
||||
assert.equal(getTaskTypeMeta("extract").label, "extract");
|
||||
assert.equal(createDefaultTaskProfile("extract"), null);
|
||||
assert.equal(getActiveTaskProfile({ taskProfiles }, "extract"), null);
|
||||
assert.throws(
|
||||
() => importTaskProfile(taskProfiles, JSON.stringify({
|
||||
format: "st-bme-task-profile",
|
||||
taskType: "extract",
|
||||
profile: { id: "legacy-extract", taskType: "extract", blocks: [] },
|
||||
})),
|
||||
/Unsupported task type: extract/,
|
||||
);
|
||||
assert.equal(
|
||||
getTaskTypeOptions().some((option) => option.id === "extract"),
|
||||
false,
|
||||
);
|
||||
assert.equal(getTaskTypes().includes("extract"), false);
|
||||
|
||||
assert.ok(getTaskTypes().includes("extract_objective"));
|
||||
assert.ok(getTaskTypes().includes("extract_subjective"));
|
||||
|
||||
@@ -93,13 +93,13 @@ function createTavernRule(id, findRegex, replaceString, overrides = {}) {
|
||||
function buildSettings(regex = {}) {
|
||||
return {
|
||||
taskProfiles: {
|
||||
extract: {
|
||||
extract_objective: {
|
||||
activeProfileId: "default",
|
||||
profiles: [
|
||||
{
|
||||
id: "default",
|
||||
name: "Regex Test",
|
||||
taskType: "extract",
|
||||
taskType: "extract_objective",
|
||||
builtin: false,
|
||||
blocks: [],
|
||||
regex: {
|
||||
@@ -220,7 +220,7 @@ try {
|
||||
|
||||
const defaultProfiles = createDefaultTaskProfiles();
|
||||
const defaultExtractStages =
|
||||
defaultProfiles.extract?.profiles?.[0]?.regex?.stages || {};
|
||||
defaultProfiles.extract_objective?.profiles?.[0]?.regex?.stages || {};
|
||||
assert.equal(
|
||||
isTaskRegexStageEnabled(defaultExtractStages, "input.finalPrompt"),
|
||||
false,
|
||||
@@ -251,7 +251,7 @@ try {
|
||||
);
|
||||
|
||||
const normalizedLegacyOnlyProfile = normalizeTaskProfile(
|
||||
"extract",
|
||||
"extract_objective",
|
||||
{
|
||||
id: "legacy-only-profile",
|
||||
name: "legacy only",
|
||||
@@ -287,7 +287,7 @@ try {
|
||||
const coreBridgeDebug = { entries: [] };
|
||||
const coreBridgeOutput = applyHostRegexReuse(
|
||||
buildSettings(),
|
||||
"extract",
|
||||
"extract_objective",
|
||||
"Alpha Beta",
|
||||
{
|
||||
sourceType: "user_input",
|
||||
@@ -308,7 +308,7 @@ try {
|
||||
]);
|
||||
assert.equal(coreBridgeDebug.entries[0].executionMode, "host-real");
|
||||
assert.equal(
|
||||
inspectTaskRegexReuse(buildSettings(), "extract").host.bridgeTier,
|
||||
inspectTaskRegexReuse(buildSettings(), "extract_objective").host.bridgeTier,
|
||||
"core-real",
|
||||
);
|
||||
setCoreRegexedStringHandler(null);
|
||||
@@ -375,7 +375,7 @@ try {
|
||||
const fullBridgeDebug = { entries: [] };
|
||||
const fullBridgeOutput = applyHostRegexReuse(
|
||||
fullBridgeSettings,
|
||||
"extract",
|
||||
"extract_objective",
|
||||
"Alpha Beta",
|
||||
{
|
||||
sourceType: "user_input",
|
||||
@@ -407,13 +407,13 @@ try {
|
||||
["__host_formatter__"],
|
||||
);
|
||||
assert.equal(
|
||||
inspectTaskRegexReuse(fullBridgeSettings, "extract").host.bridgeTier,
|
||||
inspectTaskRegexReuse(fullBridgeSettings, "extract_objective").host.bridgeTier,
|
||||
"helper-bridge",
|
||||
);
|
||||
assert.equal(
|
||||
applyTaskRegex(
|
||||
fullBridgeSettings,
|
||||
"extract",
|
||||
"extract_objective",
|
||||
"input.finalPrompt",
|
||||
"Beta",
|
||||
{ entries: [] },
|
||||
@@ -460,7 +460,7 @@ try {
|
||||
const fallbackDebug = { entries: [] };
|
||||
const fallbackOutput = applyHostRegexReuse(
|
||||
buildSettings(),
|
||||
"extract",
|
||||
"extract_objective",
|
||||
"Gamma",
|
||||
{
|
||||
sourceType: "world_info",
|
||||
@@ -493,7 +493,7 @@ try {
|
||||
character: false,
|
||||
},
|
||||
}),
|
||||
"extract",
|
||||
"extract_objective",
|
||||
"Gamma",
|
||||
{
|
||||
sourceType: "world_info",
|
||||
@@ -512,7 +512,7 @@ try {
|
||||
character: false,
|
||||
},
|
||||
}),
|
||||
"extract",
|
||||
"extract_objective",
|
||||
"Gamma",
|
||||
{
|
||||
sourceType: "world_info",
|
||||
@@ -549,7 +549,7 @@ try {
|
||||
],
|
||||
});
|
||||
initializeFallbackHostAdapter();
|
||||
const fallbackInspect = inspectTaskRegexReuse(buildSettings(), "extract");
|
||||
const fallbackInspect = inspectTaskRegexReuse(buildSettings(), "extract_objective");
|
||||
assert.equal(fallbackInspect.activeRuleCount, 3);
|
||||
assert.deepEqual(
|
||||
fallbackInspect.activeRules.map((rule) => rule.id),
|
||||
@@ -601,7 +601,7 @@ try {
|
||||
|
||||
const disallowedOutput = applyHostRegexReuse(
|
||||
buildSettings(),
|
||||
"extract",
|
||||
"extract_objective",
|
||||
"Gamma",
|
||||
{
|
||||
sourceType: "world_info",
|
||||
@@ -611,7 +611,7 @@ try {
|
||||
);
|
||||
assert.equal(disallowedOutput.text, "G2");
|
||||
|
||||
const disallowedInspect = inspectTaskRegexReuse(buildSettings(), "extract");
|
||||
const disallowedInspect = inspectTaskRegexReuse(buildSettings(), "extract_objective");
|
||||
assert.equal(disallowedInspect.activeRuleCount, 1);
|
||||
assert.equal(
|
||||
disallowedInspect.sources.find((source) => source.type === "preset")
|
||||
@@ -663,7 +663,7 @@ try {
|
||||
|
||||
const userReuseResult = applyHostRegexReuse(
|
||||
tavernSemanticsSettings,
|
||||
"extract",
|
||||
"extract_objective",
|
||||
"Alpha",
|
||||
{
|
||||
sourceType: "user_input",
|
||||
@@ -676,7 +676,7 @@ try {
|
||||
assert.equal(userReuseResult.skippedDisplayOnlyRuleCount >= 1, true);
|
||||
const aiReuseResult = applyHostRegexReuse(
|
||||
tavernSemanticsSettings,
|
||||
"extract",
|
||||
"extract_objective",
|
||||
"Answer Lore",
|
||||
{
|
||||
sourceType: "ai_output",
|
||||
@@ -686,7 +686,7 @@ try {
|
||||
);
|
||||
assert.equal(aiReuseResult.text, "AI Lore");
|
||||
assert.equal(aiReuseResult.executionMode, "host-fallback");
|
||||
const markdownInspect = inspectTaskRegexReuse(tavernSemanticsSettings, "extract");
|
||||
const markdownInspect = inspectTaskRegexReuse(tavernSemanticsSettings, "extract_objective");
|
||||
const markdownRule = markdownInspect.activeRules.find(
|
||||
(rule) => rule.id === "markdown-only",
|
||||
);
|
||||
@@ -717,7 +717,7 @@ try {
|
||||
const markdownFinalDebug = { entries: [] };
|
||||
const markdownFallbackResult = applyHostRegexReuse(
|
||||
markdownOnlyFinalPromptSettings,
|
||||
"extract",
|
||||
"extract_objective",
|
||||
"Decor",
|
||||
{
|
||||
sourceType: "user_input",
|
||||
@@ -750,7 +750,7 @@ try {
|
||||
initializeFallbackHostAdapter();
|
||||
const beautifyFinalInspect = inspectTaskRegexReuse(
|
||||
beautifyFinalPromptSettings,
|
||||
"extract",
|
||||
"extract_objective",
|
||||
);
|
||||
const beautifyFinalRule = beautifyFinalInspect.activeRules.find(
|
||||
(rule) => rule.id === "beautify-final-strip",
|
||||
@@ -760,7 +760,7 @@ try {
|
||||
const beautifyFinalDebug = { entries: [] };
|
||||
const beautifyFallbackResult = applyHostRegexReuse(
|
||||
beautifyFinalPromptSettings,
|
||||
"extract",
|
||||
"extract_objective",
|
||||
"Decor",
|
||||
{
|
||||
sourceType: "user_input",
|
||||
@@ -785,7 +785,7 @@ try {
|
||||
});
|
||||
const beautifyStageOffInspect = inspectTaskRegexReuse(
|
||||
beautifyFinalPromptStageOffSettings,
|
||||
"extract",
|
||||
"extract_objective",
|
||||
);
|
||||
const beautifyStageOffRule = beautifyStageOffInspect.activeRules.find(
|
||||
(rule) => rule.id === "beautify-final-strip",
|
||||
@@ -835,7 +835,7 @@ try {
|
||||
const destinationDebug = { entries: [] };
|
||||
const destinationReuseResult = applyHostRegexReuse(
|
||||
destinationBeautifySettings,
|
||||
"extract",
|
||||
"extract_objective",
|
||||
"DecorPlain",
|
||||
{
|
||||
sourceType: "user_input",
|
||||
@@ -848,7 +848,7 @@ try {
|
||||
assert.deepEqual(destinationDebug.entries[0].appliedRules, []);
|
||||
const destinationInspect = inspectTaskRegexReuse(
|
||||
destinationBeautifySettings,
|
||||
"extract",
|
||||
"extract_objective",
|
||||
);
|
||||
const destinationBeautifyRule = destinationInspect.activeRules.find(
|
||||
(rule) => rule.id === "destination-display-only-beautify",
|
||||
@@ -892,7 +892,7 @@ try {
|
||||
initializeFallbackHostAdapter();
|
||||
const mixedReuseResult = applyHostRegexReuse(
|
||||
tavernSemanticsSettings,
|
||||
"extract",
|
||||
"extract_objective",
|
||||
"User Reply Lore",
|
||||
{
|
||||
sourceType: "ai_output",
|
||||
@@ -922,7 +922,7 @@ try {
|
||||
const outputGuardDebug = { entries: [] };
|
||||
const outputGuardResult = applyTaskRegex(
|
||||
outputGuardSettings,
|
||||
"extract",
|
||||
"extract_objective",
|
||||
"output.rawResponse",
|
||||
"JSON 美化",
|
||||
outputGuardDebug,
|
||||
@@ -952,7 +952,7 @@ try {
|
||||
taskProfiles: createDefaultTaskProfiles(),
|
||||
globalTaskRegex: createDefaultGlobalTaskRegex(),
|
||||
},
|
||||
"extract",
|
||||
"extract_objective",
|
||||
"input.recentMessages",
|
||||
[
|
||||
"前缀",
|
||||
@@ -1008,7 +1008,7 @@ try {
|
||||
localRules: [],
|
||||
},
|
||||
},
|
||||
"extract",
|
||||
"extract_objective",
|
||||
"input.recentMessages",
|
||||
"<choice>保留</choice><thinking>保留</thinking>",
|
||||
explicitEmptyGlobalDebug,
|
||||
|
||||
Reference in New Issue
Block a user