Auto-refresh builtin default task profiles

This commit is contained in:
Youzini-afk
2026-04-05 19:29:18 +08:00
parent 28049d89bc
commit ef98161b4c
2 changed files with 182 additions and 1 deletions

View File

@@ -443,6 +443,19 @@ function getDefaultTaskProfileTemplate(taskType) {
return cloneJson(template); return cloneJson(template);
} }
function getDefaultTaskProfileTemplateStamp(taskType) {
const template = getDefaultTaskProfileTemplate(taskType);
return {
version: Number.isFinite(Number(template?.version))
? Number(template.version)
: DEFAULT_TASK_PROFILE_VERSION,
updatedAt:
typeof template?.updatedAt === "string" && template.updatedAt
? template.updatedAt
: "",
};
}
function buildDefaultTaskBlockTripletsFromTemplate(taskType) { function buildDefaultTaskBlockTripletsFromTemplate(taskType) {
const template = getDefaultTaskProfileTemplate(taskType); const template = getDefaultTaskProfileTemplate(taskType);
const blocks = Array.isArray(template?.blocks) ? template.blocks : []; const blocks = Array.isArray(template?.blocks) ? template.blocks : [];
@@ -775,8 +788,45 @@ function mergeDefaultTaskProfileBlocks(taskType, existingBlocks = []) {
return [...merged, ...extraBlocks]; return [...merged, ...extraBlocks];
} }
function shouldRefreshBuiltinDefaultProfile(taskType, profile = {}) {
if (String(profile?.id || "") !== DEFAULT_PROFILE_ID || profile?.builtin === false) {
return false;
}
const expectedStamp = getDefaultTaskProfileTemplateStamp(taskType);
const metadata = profile?.metadata || {};
const currentVersion = Number.isFinite(Number(metadata?.defaultTemplateVersion))
? Number(metadata.defaultTemplateVersion)
: Number.isFinite(Number(profile?.version))
? Number(profile.version)
: 0;
const currentUpdatedAt =
typeof metadata?.defaultTemplateUpdatedAt === "string"
? metadata.defaultTemplateUpdatedAt
: "";
if (currentVersion < expectedStamp.version) {
return true;
}
if (
expectedStamp.updatedAt &&
currentUpdatedAt &&
currentUpdatedAt !== expectedStamp.updatedAt
) {
return true;
}
if (expectedStamp.updatedAt && !currentUpdatedAt) {
return true;
}
return false;
}
function createFallbackDefaultTaskProfile(taskType) { function createFallbackDefaultTaskProfile(taskType) {
const legacyPromptField = LEGACY_PROMPT_FIELD_MAP[taskType]; const legacyPromptField = LEGACY_PROMPT_FIELD_MAP[taskType];
const templateStamp = getDefaultTaskProfileTemplateStamp(taskType);
return { return {
id: DEFAULT_PROFILE_ID, id: DEFAULT_PROFILE_ID,
name: "默认预设", name: "默认预设",
@@ -834,6 +884,8 @@ function createFallbackDefaultTaskProfile(taskType) {
metadata: { metadata: {
migratedFromLegacy: false, migratedFromLegacy: false,
legacyPromptField, legacyPromptField,
defaultTemplateVersion: templateStamp.version,
defaultTemplateUpdatedAt: templateStamp.updatedAt,
}, },
}; };
} }
@@ -846,6 +898,7 @@ export function createDefaultTaskProfile(taskType) {
const legacyPromptField = LEGACY_PROMPT_FIELD_MAP[taskType]; const legacyPromptField = LEGACY_PROMPT_FIELD_MAP[taskType];
const fallback = createFallbackDefaultTaskProfile(taskType); const fallback = createFallbackDefaultTaskProfile(taskType);
const templateStamp = getDefaultTaskProfileTemplateStamp(taskType);
return { return {
...fallback, ...fallback,
...template, ...template,
@@ -891,6 +944,8 @@ export function createDefaultTaskProfile(taskType) {
...(template?.metadata || {}), ...(template?.metadata || {}),
migratedFromLegacy: false, migratedFromLegacy: false,
legacyPromptField, legacyPromptField,
defaultTemplateVersion: templateStamp.version,
defaultTemplateUpdatedAt: templateStamp.updatedAt,
}, },
}; };
} }
@@ -985,13 +1040,25 @@ export function ensureTaskProfiles(settings = {}) {
for (const taskType of TASK_TYPES) { for (const taskType of TASK_TYPES) {
const current = existing[taskType] || {}; const current = existing[taskType] || {};
const defaultBucket = defaults[taskType]; const defaultBucket = defaults[taskType];
const profiles = let profiles =
Array.isArray(current.profiles) && current.profiles.length > 0 Array.isArray(current.profiles) && current.profiles.length > 0
? current.profiles.map((profile) => ? current.profiles.map((profile) =>
normalizeTaskProfile(taskType, profile, settings), normalizeTaskProfile(taskType, profile, settings),
) )
: defaultBucket.profiles; : defaultBucket.profiles;
const defaultIndex = profiles.findIndex(
(profile) => String(profile?.id || "") === DEFAULT_PROFILE_ID,
);
if (defaultIndex >= 0 && shouldRefreshBuiltinDefaultProfile(taskType, profiles[defaultIndex])) {
const refreshedDefault = createDefaultTaskProfile(taskType);
profiles = [
...profiles.slice(0, defaultIndex),
refreshedDefault,
...profiles.slice(defaultIndex + 1),
];
}
const activeProfileId = const activeProfileId =
typeof current.activeProfileId === "string" && typeof current.activeProfileId === "string" &&
profiles.some((profile) => profile.id === current.activeProfileId) profiles.some((profile) => profile.id === current.activeProfileId)

View File

@@ -1,6 +1,7 @@
import assert from "node:assert/strict"; import assert from "node:assert/strict";
import { import {
createDefaultTaskProfiles, createDefaultTaskProfiles,
ensureTaskProfiles,
getActiveTaskProfile, getActiveTaskProfile,
migrateLegacyTaskProfiles, migrateLegacyTaskProfiles,
} from "../prompt-profiles.js"; } from "../prompt-profiles.js";
@@ -218,6 +219,119 @@ assert.equal(upgradedLegacyDefault.blocks[10].content, "保留我自己的输出
assert.equal(upgradedLegacyDefault.blocks[11].content, "保留我自己的行为规则"); assert.equal(upgradedLegacyDefault.blocks[11].content, "保留我自己的行为规则");
assert.equal(upgradedLegacyDefault.blocks[10].role, "user"); assert.equal(upgradedLegacyDefault.blocks[10].role, "user");
assert.equal(upgradedLegacyDefault.blocks[11].role, "user"); assert.equal(upgradedLegacyDefault.blocks[11].role, "user");
const currentDefaults = createDefaultTaskProfiles();
const currentDefaultExtract = currentDefaults.extract.profiles[0];
const staleBuiltinDefaults = ensureTaskProfiles({
taskProfilesVersion: 3,
taskProfiles: {
extract: {
activeProfileId: "default",
profiles: [
{
...currentDefaultExtract,
updatedAt: "2000-01-01T00:00:00.000Z",
blocks: currentDefaultExtract.blocks.map((block) =>
block.id === "default-role"
? { ...block, content: "这是过期的默认角色定义" }
: block,
),
metadata: {
...(currentDefaultExtract.metadata || {}),
defaultTemplateVersion:
Number(currentDefaultExtract.metadata?.defaultTemplateVersion || 3),
defaultTemplateUpdatedAt: "2000-01-01T00:00:00.000Z",
},
},
{
id: "extract-custom-1",
taskType: "extract",
builtin: false,
name: "我的自定义预设",
promptMode: "block-based",
enabled: true,
updatedAt: "2026-04-05T00:00:00.000Z",
blocks: [
{
id: "custom-block-1",
name: "自定义块",
type: "custom",
enabled: true,
role: "system",
sourceKey: "",
sourceField: "",
content: "保留我的自定义内容",
injectionMode: "append",
order: 0,
},
],
generation: { ...(currentDefaultExtract.generation || {}) },
regex: {
...(currentDefaultExtract.regex || {}),
localRules: [],
},
metadata: {
note: "custom-profile-should-stay",
},
},
],
},
},
});
const refreshedDefaultExtract = staleBuiltinDefaults.extract.profiles.find(
(profile) => profile.id === "default",
);
const preservedCustomExtract = staleBuiltinDefaults.extract.profiles.find(
(profile) => profile.id === "extract-custom-1",
);
assert.ok(refreshedDefaultExtract);
assert.equal(
refreshedDefaultExtract.blocks.find((block) => block.id === "default-role")
?.content,
currentDefaultExtract.blocks.find((block) => block.id === "default-role")
?.content,
);
assert.equal(
refreshedDefaultExtract.metadata.defaultTemplateUpdatedAt,
currentDefaultExtract.metadata.defaultTemplateUpdatedAt,
);
assert.ok(preservedCustomExtract);
assert.equal(
preservedCustomExtract.blocks[0].content,
"保留我的自定义内容",
);
const sameStampBuiltinDefault = ensureTaskProfiles({
taskProfilesVersion: 3,
taskProfiles: {
extract: {
activeProfileId: "default",
profiles: [
{
...currentDefaultExtract,
blocks: currentDefaultExtract.blocks.map((block) =>
block.id === "default-role"
? { ...block, content: "同版本下保留我的默认预设修改" }
: block,
),
metadata: {
...(currentDefaultExtract.metadata || {}),
},
},
],
},
},
});
const sameStampDefaultExtract = sameStampBuiltinDefault.extract.profiles.find(
(profile) => profile.id === "default",
);
assert.equal(
sameStampDefaultExtract.blocks.find((block) => block.id === "default-role")
?.content,
"同版本下保留我的默认预设修改",
);
assert.deepEqual( assert.deepEqual(
upgradedLegacyDefault.blocks upgradedLegacyDefault.blocks
.slice(6, 10) .slice(6, 10)