Skip to content

宏与变量

注册自定义宏、对文本求值宏、读写聊天作用域或全局变量的相关 API。

Luker 通过 macros 命名空间提供宏系统,同时为向后兼容保留了 MacrosParser{{user}}{{char}}{{lastMessage}}{{getvar::name}} 等内置宏由核心注册;插件可以通过 macros.register() 添加自己的宏。

macros.register

ts
macros.register(name: string, options: {
    handler: (ctx: MacroExecutionContext) => string,
    aliases?: { alias: string, visible?: boolean }[],
    category?: string,
    unnamedArgs?: number | UnnamedArgDef[],
    list?: boolean | { min: number, max?: number },
    strictArgs?: boolean,
    description?: string,
    returns?: string,
    returnType?: 'string' | 'integer' | 'number' | 'boolean',
    displayOverride?: string,
    exampleUsage?: string | string[],
    delayArgResolution?: boolean,
}): MacroDefinition | null

注册宏。返回注册成功的定义;校验失败则返回 null

选项说明
handler宏主体。接收带解析后参数的执行上下文
aliases备用名。每个 { alias, visible } 注册同一处理器
category自动补全里的分组(如 'utility''character''time'
unnamedArgs数量(全部必填)或参数定义数组
list是否接受可变长度的参数列表
strictArgsfalse 时,arity / 类型不匹配只 log 警告而不抛错
delayArgResolutiontrue 时,参数中的嵌套宏会被预先解析——处理器必须自己调用 ctx.resolve(text)。仅用于控制流式宏

处理器上下文

处理器收到 MacroExecutionContext,包含:

字段说明
name调用时使用的宏名
args命名参数的值
unnamedArgs非命名位置参数
list可变长度的列表参数
env宏求值环境(聊天、角色、persona 等)
normalize(value)把值强制为该宏的返回类型
trimContent(content, opts?)修剪多行块
resolve(text, opts?)解析 text 中的嵌套宏
warn(message, error?)记录归属于此宏的警告
js
const ctx = Luker.getContext();

ctx.macros.register('myStatus', {
    description: 'Returns the plugin status string.',
    category: 'utility',
    handler: () => 'My plugin is active.',
});

ctx.macros.register('greet', {
    description: 'Greets a name.',
    unnamedArgs: [
        { name: 'name', optional: false, type: 'string', description: 'Person to greet' },
    ],
    handler: (mctx) => `Hello, ${mctx.unnamedArgs[0]}!`,
});

注册后,{{myStatus}}{{greet::Bob}} 都能工作。

macros.registry

底层的注册表。可用于反注册和检视:

js
ctx.macros.registry.unregisterMacro('myStatus');
ctx.macros.registry.hasMacro('greet');
const def = ctx.macros.registry.getMacro('greet');

内置宏参考

下面是核心注册的宏的非穷尽列表。完整覆盖请见 public/scripts/macros/definitions/ 下的源码。

返回
{{user}}当前用户 / persona 名
{{char}}当前角色名
{{persona}}当前 persona 描述
{{charDescription}} / {{charPersonality}} / {{charScenario}}卡片字段
{{charDepthPrompt}} / {{charCreatorNotes}} / {{charFirstMessage}} / {{charVersion}}卡片字段
{{mesExamples}} / {{mesExamplesRaw}}对话示例
{{group}} / {{groupNotMuted}}群组成员名
{{lastMessage}} / {{lastMessageId}} / {{lastUserMessage}} / {{lastCharMessage}}最近聊天内容
{{firstIncludedMessageId}} / {{firstDisplayedMessageId}}可见性窗口
{{lastSwipeId}} / {{currentSwipeId}}swipe 状态
{{model}}当前模型标识
{{maxPrompt}} / {{maxContext}} / {{maxResponse}}token 预算
{{time}} / {{date}} / {{weekday}} / {{isotime}} / {{isodate}}本地时钟
{{datetimeformat::FORMAT}}moment.format(FORMAT)
{{idleDuration}} / {{timeDiff}}时间差
{{getvar::name}} / {{setvar::name::value}} / {{addvar::name::value}}本地变量
{{incvar::name}} / {{decvar::name}} / {{hasvar::name}} / {{deletevar::name}}本地变量
{{getglobalvar::name}} / {{setglobalvar::name::value}} / ...全局变量
{{if::cond::then::else}} / {{else::...}} / {{each::...}}控制流
{{trim}} / {{newline}} / {{space}} / {{noop}}空白辅助
{{roll::XdY}} / {{random::a,b,c}} / {{pick::a,b,c}}随机
{{//comment}}注释(输出忽略)
{{outlet::name}}自定义 WI outlet 内容
{{isMobile}} / {{hasExtension::name}}环境检查
{{lastGenerationType}} / {{systemPrompt}}流水线状态

MacrosParser(已弃用)

ts
MacrosParser.registerMacro(key: string, value: string | (nonce) => string, description?: string): void
MacrosParser.unregisterMacro(key: string): void

旧版的简单字符串替换宏注册 API。会记录弃用警告。请迁移到 macros.register({ handler }) 以获得完整能力,或在一次性调用中给 substituteParamsdynamicMacros

substituteParams

ts
substituteParams(content: string, options?: {
    name1Override?: string,
    name2Override?: string,
    original?: string,
    groupOverride?: string,
    replaceCharacterCard?: boolean,
    dynamicMacros?: Record<string, string | (() => string)>,
    postProcessFn?: (text: string) => string,
}): string

解析 content 中的所有宏。dynamicMacros 可以为单次调用注入临时的零参数宏:

js
const result = ctx.substituteParams('Hello, {{user}}! Today is {{date}}.');

substituteParamsExtended

ts
substituteParamsExtended(
    content: string,
    additionalMacros?: Record<string, string | (() => string)>,
    postProcessFn?: (text: string) => string,
): string

substituteParams 的便捷封装,仅为本次调用添加 additionalMacros

js
const result = ctx.substituteParamsExtended(
    'Query: {{queryText}}',
    { queryText: userInput },
);

additionalMacros 不会被全局注册——它们只对这一次替换有效。

变量

有两种作用域可用:本地(按聊天,持久化在 chat_metadata.variables)和全局(跨聊天,持久化在 extension_settings.variables.global)。

本地变量

ts
context.variables.local.get(name: string, args?: object): string | number
context.variables.local.set(name: string, value: any, args?: object): any
context.variables.local.add(name: string, value: any): any
context.variables.local.inc(name: string): any
context.variables.local.dec(name: string): any
context.variables.local.del(name: string): ''
context.variables.local.has(name: string): boolean
方法说明
get读取变量。数字字符串自动强制为数字。不存在时返回 ''
set写入变量。返回值
add两者都是数字时执行加法。已有值是 JSON 数组时 push。否则按字符串拼接
inc / decadd(name, ±1) 的快捷方式
del删除变量。返回 ''
has布尔型存在性检查

get / set 上的可选 args 参数支持:

  • args.key——备用变量名(覆盖 name
  • args.index——存在变量里的 JSON 列表 / 字典的索引 / key
  • args.as(仅 set)——为索引写入将值强制为 'string' / 'number' / 'boolean'

全局变量

ts
context.variables.global.get / set / add / inc / dec / del / has

接口与本地相同。跨聊天持久化。

使用示例

js
const ctx = Luker.getContext();

// 读本地变量并给默认值
const turns = Number(ctx.variables.local.get('turns_taken')) || 0;

// 自增
ctx.variables.local.inc('turns_taken');

// 检查并初始化全局配置变量
if (!ctx.variables.global.has('api_endpoint')) {
    ctx.variables.global.set('api_endpoint', 'https://api.example.com');
}
const endpoint = ctx.variables.global.get('api_endpoint');

// 索引写入:往本地变量里的 JSON 列表的某个位置写
ctx.variables.local.set('inventory', 'sword', { index: 0, as: 'string' });
ctx.variables.local.set('inventory', 'shield', { index: 1, as: 'string' });

本地 vs 全局

本地全局
作用域单个聊天所有聊天
存储chat_metadata.variablesextension_settings.variables.global
保存触发saveMetadataDebouncedsaveSettingsDebounced
适用场景聊天专属计数器、阶段性状态插件配置、跨聊天数据

基于 SillyTavern 构建