diff --git a/README.md b/README.md index bc6a87d..9da5d18 100644 --- a/README.md +++ b/README.md @@ -204,6 +204,20 @@ Your task is to transform the character concept into a JSON object
(click to expand) +### 1.0.3 +- Added config "Automatic disable for cache enabled models" +- Lets players disable Inner Self automatically if a cache-enabled model is detected +- Added config "Additional model block list" +- Lets players decided if they want to disable certain models automatically if they are detected +- Added config "Enable Model Warning Messages" +- Added config "Notification Cached Model" +- Added config "Notification blocked story model" +- These changes let players enable or disable and customise a one-time per model warning message if a cached-model or block story model is detected. +- Added config "Turn delay for Inner Self start" +- This change prevents Inner Self from impacting turn one output +- Adjusted AI prompts for Inner Self to reduce duplicate brain entries and reinforce story continuation +- Pull request by [Fly3-r](https://github.com/Fly3-r) + ### 1.0.2 - Added config "Brain card notes store brains as JSON" - When disabled, brain card notes use a simpler colon + newline delimited format instead of JSON @@ -229,6 +243,7 @@ Your task is to transform the character concept into a JSON object
(click to expand) +- v1.0.2 → v1.0.3 by [Fly3-r](https://github.com/Fly3-r) - v1.0.1 → v1.0.2 by [dirtymined13](https://github.com/dirtymined13) - v1.0.0 → v1.0.1 by [-Vinny-](https://play.aidungeon.com/profile/-Vinny-) diff --git a/src/library.js b/src/library.js index fc7ca5b..4c10c35 100644 --- a/src/library.js +++ b/src/library.js @@ -11,7 +11,7 @@ globalThis.MainSettings = (class MainSettings { //————————————————————————————————————————————————————————————————————————————————— /** - * Inner Self v1.0.2 + * Inner Self v1.0.3 * Made by LewdLeah on January 3, 2026 * Gives story characters the ability to learn, plan, and adapt over time * Inner Self is free and open-source for anyone! ❤️ @@ -67,6 +67,30 @@ globalThis.MainSettings = (class MainSettings { IS_CONFIG_CARD_PINNED_BY_DEFAULT: false // (true or false) , + // Should Inner Self remain active on cached model turns? + ALLOW_CACHED_MODELS: false + // (true or false) + , + // Minimum turn count required before Inner Self can activate. + MINIMUM_HISTORY_LENGTH_BEFORE_ENABLE: 2 + // (0 to 9999) + , + // Should one-time warning messages be shown when model rules disable Inner Self? + ENABLE_MODEL_WARNING_MESSAGES: false + // (true or false) + , + // Message shown once per model when Inner Self is disabled on a cached turn. + NOTIFICATION_CACHED_MODEL: "Inner Self is disabled on cached turns for %{model}." + // (any text inside the ""; use %{model} to include the model name) + , + // Message shown once per model when Inner Self is disabled by the blocked models list. + NOTIFICATION_BLOCKED_STORY_MODEL: "Inner Self is disabled on blocked story model %{model}." + // (any text inside the ""; use %{model} to include the model name) + , + // Which story models should block Inner Self? Leave empty to block none. Ex: Wayfarer Large,Wayfarer Small 2 + BLOCKED_STORY_MODELS: "" + // (write a comma separated list of exact model names inside the "" or leave empty) + , // Is AC already enabled when the adventure begins? IS_AC_ENABLED_BY_DEFAULT: false // (true or false) @@ -278,6 +302,30 @@ function InnerSelf(hook) { IS_CONFIG_CARD_PINNED_BY_DEFAULT: false // (true or false) , + // Should Inner Self remain active on cached model turns? + ALLOW_CACHED_MODELS: true + // (true or false) + , + // Minimum turn count required before Inner Self can activate. + MINIMUM_HISTORY_LENGTH_BEFORE_ENABLE: 1 + // (0 to 9999) + , + // Should one-time warning messages be shown when model rules disable Inner Self? + ENABLE_MODEL_WARNING_MESSAGES: true + // (true or false) + , + // Message shown once per model when Inner Self is disabled on a cached turn. + NOTIFICATION_CACHED_MODEL: "Inner Self is disabled on cached turns for %{model}." + // (any text inside the ""; use %{model} to include the model name) + , + // Message shown once per model when Inner Self is disabled by the blocked models list. + NOTIFICATION_BLOCKED_STORY_MODEL: "Inner Self is disabled on blocked story model %{model}." + // (any text inside the ""; use %{model} to include the model name) + , + // Which story models should block Inner Self? Leave empty to block none. + BLOCKED_STORY_MODELS: "" + // (write a comma separated list of exact model names inside the "" or leave empty) + , // Is AC already enabled when the adventure begins? IS_AC_ENABLED_BY_DEFAULT: false // (true or false) @@ -339,6 +387,16 @@ function InnerSelf(hook) { label: 0, // Hash of recent history to detect retry or erase + continue turns hash: "", + // Most recent actionCount value observed from info + lastKnownActionCount: 0, + // Models from the blocked list which have actually been encountered + detectedBlockedModels: [], + // Blocked models already shown to the user + warnedBlockedModels: [], + // Cached models already shown to the user + warnedCachedModels: [], + // One-time output notice queued for the current turn + pendingUserNotice: "", // Total number of brain operations performed across all agents ops: 0, // Auto-Cards integration state @@ -381,6 +439,128 @@ function InnerSelf(hook) { } return n.toString(16); }; + const normalizeWhitespace = (value = "") => ( + ((typeof value === "string") || (typeof value === "number")) + ? String(value).replace(/\s+/g, " ").trim() + : "" + ); + const normalizeModelValue = (value = "") => String(value).trim().replace(/\s+/g, " ").toLowerCase(); + const splitModelList = (value = "") => [...new Set(String(value) + .split(/[,\n]/) + .map(model => normalizeModelValue(model)) + .filter(model => (model !== "")) + )]; + const pushUnique = (list = [], value = "") => { + value = normalizeWhitespace(value); + if ((value === "") || !Array.isArray(list) || list.includes(value)) { + return false; + } + list.push(value); + return true; + }; + const readInfoActionCount = () => ( + Number.isInteger(info?.actionCount) + ? Math.abs(info.actionCount) + : null + ); + const rememberInfoActionCount = () => { + const current = readInfoActionCount(); + if (current !== null) { + IS.lastKnownActionCount = current; + return current; + } else if (Number.isInteger(IS.lastKnownActionCount)) { + return IS.lastKnownActionCount; + } + return 0; + }; + rememberInfoActionCount(); + const getStoryModelDisplayName = () => { + for (const candidate of [ + info?.storyModel?.name, + info?.storyModel?.id, + info?.storyModel?.slug, + info?.storyModel, + info?.model?.name, + info?.model?.id, + info?.model?.slug, + info?.modelName, + info?.model + ]) { + const model = normalizeWhitespace(candidate); + if (model !== "") { + return model; + } + } + return "unknown"; + }; + const getStoryModelName = () => normalizeModelValue(getStoryModelDisplayName()); + const isCacheEfficientTurn = () => (info?.useCacheEfficient === true); + const getInnerSelfActivationCount = () => rememberInfoActionCount(); + const isInnerSelfHistoryAllowed = (config = {}) => ( + getInnerSelfActivationCount() >= ( + Number.isInteger(config.minimumHistoryLength) + ? config.minimumHistoryLength + : 0 + ) + ); + const getInnerSelfModelStatus = (config = {}) => { + const modelName = getStoryModelName(); + const modelLabel = getStoryModelDisplayName(); + if (!config.allowCachedModels && isCacheEfficientTurn()) { + return { allowed: false, reason: "cached", modelName, modelLabel }; + } else if (Array.isArray(config.blockedModels) && (config.blockedModels.length !== 0)) { + if ((modelName !== "") && (modelName !== "unknown") && config.blockedModels.includes(modelName)) { + return { allowed: false, reason: "blocked", modelName, modelLabel }; + } + } + return { allowed: true, reason: "", modelName, modelLabel }; + }; + const formatModelWarning = (template = "", modelLabel = "") => normalizeWhitespace( + String(template || "").replace(/%\{model\}/g, modelLabel || "unknown") + ); + const queueModelWarning = (modelStatus = {}, config = {}) => { + const modelKey = normalizeModelValue(modelStatus.modelName || ""); + const modelLabel = normalizeWhitespace(modelStatus.modelLabel || modelKey || "unknown"); + if (modelStatus.reason === "blocked") { + pushUnique(IS.detectedBlockedModels, modelKey || modelLabel); + } + if (!config.enableModelWarningMessages) { + return; + } + const warnedList = + (modelStatus.reason === "blocked") + ? IS.warnedBlockedModels + : (modelStatus.reason === "cached") + ? IS.warnedCachedModels + : null; + if (!warnedList || !pushUnique(warnedList, modelKey || modelLabel)) { + return; + } + IS.pendingUserNotice = formatModelWarning( + (modelStatus.reason === "blocked") + ? config.notificationBlockedStoryModel + : config.notificationCachedModel, + modelLabel + ); + }; + const consumePendingUserNotice = () => { + const pending = normalizeWhitespace(IS.pendingUserNotice || ""); + IS.pendingUserNotice = ""; + return pending; + }; + const buildUserNoticeBlock = (message = "") => { + message = normalizeWhitespace(message); + return (message === "") ? "" : `>>> Inner Self:\n${message}\n<<<`; + }; + const applyUserNoticeToOutput = (output = "") => { + const notice = buildUserNoticeBlock(consumePendingUserNotice()); + if (notice === "") { + return output; + } else if ((typeof output !== "string") || (output === "") || (output === "\u200B")) { + return notice; + } + return `${notice}\n\n${String(output).trimStart()}`; + }; /** * Safely parses a JSON string into an object * Optionally attempts to repair malformed JSON by extracting quoted content @@ -427,7 +607,13 @@ function InnerSelf(hook) { * @property {boolean} json - Is raw JSON syntax used to serialize NPC brains in their card notes? * @property {boolean} debug - Is debug mode enabled for inline task output visibility? * @property {boolean} pin - Is the config card pinned near the top of the list? + * @property {boolean} allowCachedModels - Should cached model turns run Inner Self? + * @property {number} minimumHistoryLength - Minimum turn count before Inner Self activates + * @property {boolean} enableModelWarningMessages - Show one-time model warning messages in output + * @property {string} notificationCachedModel - Cached-model warning message template + * @property {string} notificationBlockedStoryModel - Blocked-model warning message template * @property {boolean} auto - Is Auto-Cards enabled? + * @property {string[]} blockedModels - Story model names which disable Inner Self * @property {string[]} agents - All agent names, ordered from highest to lowest trigger priority */ /** @@ -466,7 +652,14 @@ function InnerSelf(hook) { json: false, debug: false, pin: false, + allowCachedModels: true, + minimumHistoryLength: 1, + enableModelWarningMessages: true, + notificationCachedModel: "Inner Self is disabled on cached turns for %{model}.", + notificationBlockedStoryModel: + "Inner Self is disabled on blocked story model %{model}.", auto: false, + blockedModels: [], agents: [] }); /** @type {config} */ @@ -625,6 +818,51 @@ function InnerSelf(hook) { { message: "Pin this config card near the top:", ...factory( "pin", S.IS_CONFIG_CARD_PINNED_BY_DEFAULT ) }, + { message: "Allow cached models:", ...factory( + "allowCachedModels", S.ALLOW_CACHED_MODELS + ) }, + { message: "Minimum turn count before activation:", ...factory( + "minimumHistoryLength", S.MINIMUM_HISTORY_LENGTH_BEFORE_ENABLE, + { lower: 0, upper: 9999 } + ) }, + { message: "Enable model warning messages:", ...factory( + "enableModelWarningMessages", S.ENABLE_MODEL_WARNING_MESSAGES + ) }, + { + message: "Cached model warning message:", + builder: (cfg = {}) => ` "${( + config.notificationCachedModel + ?? cfg.setter?.(S.NOTIFICATION_CACHED_MODEL) + )}"`, + setter: (value = null, fallible = false) => { + if (typeof value === "string") { + config.notificationCachedModel = value.replaceAll("\"", "").trim(); + } else if (fallible) { + return; + } else { + config.notificationCachedModel = fallback.notificationCachedModel; + } + return config.notificationCachedModel; + } + }, + { + message: "Blocked story model warning message:", + builder: (cfg = {}) => ` "${( + config.notificationBlockedStoryModel + ?? cfg.setter?.(S.NOTIFICATION_BLOCKED_STORY_MODEL) + )}"`, + setter: (value = null, fallible = false) => { + if (typeof value === "string") { + config.notificationBlockedStoryModel = value.replaceAll("\"", "").trim(); + } else if (fallible) { + return; + } else { + config.notificationBlockedStoryModel = + fallback.notificationBlockedStoryModel; + } + return config.notificationBlockedStoryModel; + } + }, { message: "Install Auto-Cards:", ...factory( "auto", S.IS_AC_ENABLED_BY_DEFAULT ) }, @@ -640,6 +878,24 @@ function InnerSelf(hook) { { message: `Inner Self ${version} is an open-source and general-purpose AI Dungeon mod by LewdLeah. You have my full permission to use it with any scenario!` }, + { + message: "Block Inner Self on these story models (leave empty to block none):", + builder: (cfg = {}) => ["", "", ...( + config.blockedModels ?? cfg.setter?.(S.BLOCKED_STORY_MODELS) + ), ""].join("\n"), + setter: (value = null, fallible = false) => { + if (typeof value === "string") { + config.blockedModels = splitModelList(value); + } else if (Array.isArray(value)) { + config.blockedModels = splitModelList(value.join("\n")); + } else if (fallible) { + return; + } else { + return (config.blockedModels = [...fallback.blockedModels]); + } + return config.blockedModels; + } + }, { // This is where players list their NPCs message: "Write the first name of every intelligent story character on separate lines below, listed from highest to lowest trigger priority:", @@ -1064,6 +1320,15 @@ function InnerSelf(hook) { IS.agent = ""; /** @type {config} */ const config = Config.get(); + const modelStatus = getInnerSelfModelStatus(config); + if (!modelStatus.allowed) { + queueModelWarning(modelStatus, config); + } + const innerSelfEnabled = ( + config.allow + && isInnerSelfHistoryAllowed(config) + && modelStatus.allowed + ); if (config.pin) { // Move config card to top of list if pinning is enabled const index = storyCards.indexOf(config.card); @@ -1098,7 +1363,7 @@ function InnerSelf(hook) { IS.AC.enabled = true; if (IS.AC.event || (stop === true)) { // If AC triggered an event or stop, we're done here - config.allow ? unzero() : ((IS.encoding = ""), (text ||= " ")); + innerSelfEnabled ? unzero() : ((IS.encoding = ""), (text ||= " ")); return; } } else if (IS.AC.enabled) { @@ -1130,12 +1395,6 @@ function InnerSelf(hook) { } } } - if (!config.allow) { - // Early exit if Inner Self is disabled - IS.encoding = ""; - text ||= " "; - return; - } /** * Removes visual indicators from all story cards * Called when no agent is triggered or Inner Self is disabled @@ -1147,6 +1406,14 @@ function InnerSelf(hook) { } return; }; + if (!innerSelfEnabled) { + // Early exit if Inner Self is disabled + deindicateAll(); + IS.agent = ""; + IS.encoding = ""; + text ||= " "; + return; + } if (config.agents.length === 0) { // No agents are configured deindicateAll(); @@ -1515,7 +1782,7 @@ You must output one short parenthetical task followed by the story continuation. ## STORY CONTINUATION (REQUIRED) - After the closing parenthesis, write **one space** and then continue the story - Written from ${ownership(config.player)} **first person present tense** PoV -- The story continues where it previously left off, with many lines or sentences of new prose +- The story continues EXACTLY where it previously left off, with many lines or sentences of new prose, without reiterating information or content ## EXACT SHAPE (delete unwanted_key) Story continues from ${ownership(config.player)} perspective, using first person present tense prose... @@ -1536,7 +1803,7 @@ You must output one short parenthetical task followed by the story continuation. ## STORY CONTINUATION (REQUIRED) - After the closing parenthesis, write **one space** and then continue the story - Written from ${ownership(config.player)} **second person present tense** ("you") PoV -- The story continues where it previously left off, with many lines or sentences of new prose +- The story continues EXACTLY where it previously left off, with many lines or sentences of new prose, without reiterating information or content ## EXACT SHAPE (delete unwanted_key) Story continues from ${ownership(config.player)} second person perspective... @@ -1557,7 +1824,7 @@ You must output one short parenthetical task followed by the story continuation. ## STORY CONTINUATION (REQUIRED) - After the closing parenthesis, write **one space** and then continue the story - Written from ${ownership(config.player)} **third person** PoV -- The story continues where it previously left off, with many lines or sentences of new prose +- The story continues EXACTLY where it previously left off, with many lines or sentences of new prose, without reiterating information or content ## EXACT SHAPE (delete unwanted_key) Story continues with third person prose... @@ -1587,7 +1854,9 @@ Inside the parentheses: - Written from ${ownership(agent.name)} **first person** PoV${refocus(false)} - Avoid using pronouns or the word "you", instead ${agent.name} refers to other characters directly by name - Never repeat, novelty and uniqueness are top priorities + - Never repeat former identical thoughts of ${ownership(agent.name)} - ${ownership(agent.name)} thought must be one single sentence only + - Only use facts what ${ownership(agent.name)} logically has information on - Never hallucinate facts - End the sentence with a period and backtick inside the parentheses; close with ".\`)" @@ -1596,7 +1865,7 @@ This creates or overwrites the thought associated with that key. ## STORY CONTINUATION (REQUIRED) - After the closing parenthesis, write **one space** and then continue the story - Written from ${ownership(config.player)} **first person present tense** PoV -- The story continues where it previously left off, with many lines or sentences of new prose +- The story continues EXACTLY where it previously left off, with many lines or sentences of new prose, without reiterating information or content ## EXACT SHAPE (example_key = \`${ownership(agent.name)} own short 1-sentence thought in first person.\`) Story continues from ${ownership(config.player)} perspective, using first person present tense prose... @@ -1623,7 +1892,9 @@ Inside the parentheses: - Written from ${ownership(agent.name)} **first person** PoV${refocus(false)} - Avoid using pronouns or the word "you", instead ${agent.name} refers to other characters directly by name - Never repeat, novelty and uniqueness are top priorities + - Never repeat former identical thoughts of ${ownership(agent.name)} - ${ownership(agent.name)} thought must be one single sentence only + - Only use facts what ${ownership(agent.name)} logically has information on - Never hallucinate facts - End the sentence with a period and backtick inside the parentheses; close with ".\`)" @@ -1632,7 +1903,7 @@ This creates or overwrites the thought associated with that key. ## STORY CONTINUATION (REQUIRED) - After the closing parenthesis, write **one space** and then continue the story - Written from ${ownership(config.player)} **second person present tense** ("you") PoV -- The story continues where it previously left off, with many lines or sentences of new prose +- The story continues EXACTLY where it previously left off, with many lines or sentences of new prose, without reiterating information or content ## EXACT SHAPE (example_key = \`${ownership(agent.name)} own short 1-sentence thought in first person.\`) Story continues from ${ownership(config.player)} second person perspective... @@ -1659,7 +1930,9 @@ Inside the parentheses: - Written from ${ownership(agent.name)} **first person** PoV${refocus(false)} - Avoid using pronouns or the word "you", instead ${agent.name} refers to other characters directly by name - Never repeat, novelty and uniqueness are top priorities + - Never repeat former identical thoughts of ${ownership(agent.name)} - ${ownership(agent.name)} thought must be one single sentence only + - Only use facts what ${ownership(agent.name)} logically has information on - Never hallucinate facts - End the sentence with a period and backtick inside the parentheses; close with ".\`)" @@ -1668,7 +1941,7 @@ This creates or overwrites the thought associated with that key. ## STORY CONTINUATION (REQUIRED) - After the closing parenthesis, write **one space** and then continue the story - Written from ${ownership(config.player)} **third person** PoV -- The story continues where it previously left off, with many lines or sentences of new prose +- The story continues EXACTLY where it previously left off, with many lines or sentences of new prose, without reiterating information or content ## EXACT SHAPE (example_key = \`${ownership(agent.name)} own short 1-sentence thought in first person.\`) Story continues with third person prose... @@ -1715,7 +1988,9 @@ Inside the parentheses: - Only refer to other characters directly by name in the thought sentence. - Avoid using pronouns or the word "you" which is too vague. Use specific names instead. - Never repeat, novelty and uniqueness are top priorities. + - Never repeat former identical thoughts of ${ownership(agent.name)}. - ${ownership(agent.name)} thought must be short. + - Only use facts what ${ownership(agent.name)} logically has information on. - Never hallucinate facts. - End the sentence with a period and backtick **inside** the parentheses; close with ".\`)". @@ -1755,7 +2030,7 @@ Rules: 4. Do **NOT** write extra parentheses. 5. Do **NOT** use more than one operation per turn. 6. Do **NOT** invent new structures or mix formats. -7. The story continues where it previously left off, with many sentences of brand new prose. +7. The story continues EXACTLY where it previously left off, with many sentences of brand new prose, without reiterating information or content. --- @@ -1765,7 +2040,7 @@ Rules: - **If ${agent.name} reuses an already existing key, the new thought REPLACES / OVERRIDES the older thought stored under that key.** - This means: - Reusing an old key: **Overwrite an old thought with a new thought.** Useful for extending or maintaining existing information stored in ${ownership(agent.name)} brain. - - Using a new key: **Create a new thought.** Useful for storing ${ownership(agent.name)} memories, self-modifying ${ownership(agent.name)} own personality, tracking ${ownership(agent.name)} goals, or making plans for ${agent.name} to follow. + - Using a new key: **Create a new thought.** Useful for storing ${ownership(agent.name)} memories, self-modifying ${ownership(agent.name)} own personality, tracking ${ownership(agent.name)} goals with, demonstration slow-burn gain or loss of ${ownership(agent.name)}'s relationship with ${agent.name} or making plans for ${agent.name} to follow. - **Renaming a key moves the thought to a new name.** Useful for reorganizing ${ownership(agent.name)} brain. - **Deleting a key removes the thought permanently.** Helps ${agent.name} forget outdated, superfluous, or irrelevant information. - Choose keys carefully so ${agent.name} can easily recall, update, overwrite, rename, or delete thoughts as required for self-improvement. @@ -1824,6 +2099,8 @@ Inside the parentheses: - Only refer to other characters directly by name in the thought sentence. - Avoid using pronouns or the word "you" which is too vague. Use specific names instead. - Never repeat, novelty and uniqueness are top priorities. + - Never repeat former identical thoughts of ${ownership(agent.name)}. + - Only use facts what ${ownership(agent.name)} logically has information on. - ${ownership(agent.name)} thought must be short. - Never hallucinate facts. - End the sentence with a period and backtick **inside** the parentheses; close with ".\`)". @@ -1864,7 +2141,7 @@ Rules: 4. Do **NOT** write extra parentheses. 5. Do **NOT** use more than one operation per turn. 6. Do **NOT** invent new structures or mix formats. -7. The story continues where it previously left off, with many sentences of brand new prose. +7. The story continues EXACTLY where it previously left off, with many sentences of brand new prose, without reiterating information or content. --- @@ -1874,7 +2151,7 @@ Rules: - **If ${agent.name} reuses an already existing key, the new thought REPLACES / OVERRIDES the older thought stored under that key.** - This means: - Reusing an old key: **Overwrite an old thought with a new thought.** Useful for extending or maintaining existing information stored in ${ownership(agent.name)} brain. - - Using a new key: **Create a new thought.** Useful for storing ${ownership(agent.name)} memories, self-modifying ${ownership(agent.name)} own personality, tracking ${ownership(agent.name)} goals, or making plans for ${agent.name} to follow. + - Using a new key: **Create a new thought.** Useful for storing ${ownership(agent.name)} memories, self-modifying ${ownership(agent.name)} own personality, tracking ${ownership(agent.name)} goals with, demonstration slow-burn gain or loss of ${ownership(agent.name)}'s relationship with ${agent.name} or making plans for ${agent.name} to follow. - **Renaming a key moves the thought to a new name.** Useful for reorganizing ${ownership(agent.name)} brain. - **Deleting a key removes the thought permanently.** Helps ${agent.name} forget outdated, superfluous, or irrelevant information. - Choose keys carefully so ${agent.name} can easily recall, update, overwrite, rename, or delete thoughts as required for self-improvement. @@ -1933,6 +2210,8 @@ Inside the parentheses: - Only refer to other characters directly by name in the thought sentence. - Avoid using pronouns or the word "you" which is too vague. Use specific names instead. - Never repeat, novelty and uniqueness are top priorities. + - Never repeat former identical thoughts of ${ownership(agent.name)}. + - Only use facts what ${ownership(agent.name)} logically has information on. - ${ownership(agent.name)} thought must be short. - Never hallucinate facts. - End the sentence with a period and backtick **inside** the parentheses; close with ".\`)". @@ -1973,7 +2252,7 @@ Rules: 4. Do **NOT** write extra parentheses. 5. Do **NOT** use more than one operation per turn. 6. Do **NOT** invent new structures or mix formats. -7. The story continues where it previously left off, with many sentences of brand new prose. +7. The story continues EXACTLY where it previously left off, with many sentences of brand new prose, without reiterating information or content. --- @@ -1983,7 +2262,7 @@ Rules: - **If ${agent.name} reuses an already existing key, the new thought REPLACES / OVERRIDES the older thought stored under that key.** - This means: - Reusing an old key: **Overwrite an old thought with a new thought.** Useful for extending or maintaining existing information stored in ${ownership(agent.name)} brain. - - Using a new key: **Create a new thought.** Useful for storing ${ownership(agent.name)} memories, self-modifying ${ownership(agent.name)} own personality, tracking ${ownership(agent.name)} goals, or making plans for ${agent.name} to follow. + - Using a new key: **Create a new thought.** Useful for storing ${ownership(agent.name)} memories, self-modifying ${ownership(agent.name)} own personality, tracking ${ownership(agent.name)} goals with, demonstration slow-burn gain or loss of ${ownership(agent.name)}'s relationship with ${agent.name} or making plans for ${agent.name} to follow. - **Renaming a key moves the thought to a new name.** Useful for reorganizing ${ownership(agent.name)} brain. - **Deleting a key removes the thought permanently.** Helps ${agent.name} forget outdated, superfluous, or irrelevant information. - Choose keys carefully so ${agent.name} can easily recall, update, overwrite, rename, or delete thoughts as required for self-improvement. @@ -2125,6 +2404,15 @@ Follow the format **perfectly**. // Process model output and implement brain operations /** @type {config} */ const config = Config.get(); + const modelStatus = getInnerSelfModelStatus(config); + if (!modelStatus.allowed) { + queueModelWarning(modelStatus, config); + } + const innerSelfEnabled = ( + config.allow + && isInnerSelfHistoryAllowed(config) + && modelStatus.allowed + ); /** * Ensures clean visual separation between actions * Only applies after "continue" or "story" actions @@ -2258,9 +2546,10 @@ I hope you will have lots of fun! prespace(); IS.agent = ""; return; - } else if (!config.allow) { + } else if (!innerSelfEnabled) { // Early exit if Inner Self is disabled text ||= "\u200B"; + text = applyUserNoticeToOutput(text); IS.agent = ""; return; } @@ -2754,6 +3043,7 @@ I hope you will have lots of fun! agent.card.entry = `${agent.card.entry}\n\n// operation ${IS.ops}\n${operation()}`.trimStart(); } text ||= "\u200B"; + text = applyUserNoticeToOutput(text); // Keep the operation log from growing unbounded // Limit to approximately 2000 chars to satisfy AID's soft entry limit agent.card.entry = agent.card.entry.split(/\n\n/).slice(-2000).reduceRight((out, op) => (