Storvia

属性

SDK 的状态模块 —— 世界、玩家、角色、关系、物品、扩展属性、存档,以及完整状态读取

SDK 提供 7 个分模块 + 1 个全量读取接口(storvia.state),用于读写游戏中的各种数据。前 5 个模块的数据会自动注入 AI 提示词,AI 每轮回复时也会自动更新。custom 默认不注入 AI,可通过创作台开启「AI 追踪」选择性注入。save 完全独立、永不注入 AI,专供游戏运行状态持久化。

模块AI 感知数据结构
storvia.world自动注入扁平 KV 对象
storvia.player.state自动注入按分组的 KV
storvia.characters.state自动注入角色名 → 按分组的 KV
storvia.relationships自动注入关系数组
storvia.inventory自动注入分组 → 物品 Record(上限 100 件)
storvia.custom可选注入文本/数值(可分组,上限 100 字段)
storvia.save永不注入任意 JSON(独立配额,≤ 256KB)
storvia.memory自动注入AI 记忆文本
storvia.state一次性返回上述所有模块的合并快照

前 5 个模块的字段定义需要在创作台中配置(和深度创作一样),配置方法参考 深度创作。这里介绍的是如何通过 SDK 在游戏代码中读写数据

角色数量上限:每个会话最多 10 个角色处于活跃状态、可被 AI 看到。当超过上限时,系统会按 priority 从低到高把多余角色移入休眠区dormant)。休眠的角色不再注入 AI 提示词、AI 也不会更新它们的属性,但数据仍保留。可以通过 storvia.characters.setPriority() 调整排序,让某个角色重新进入活跃区。


storvia.world — 世界状态

存储全局环境信息。世界状态只有以下 5 个固定字段,由创作台按需启用,不支持自定义字段:

字段说明
time时间(如"晚上 21:00")
date日期(如"2024年3月15日")
location地点(如"秦照野的直播间")
region地区(如"江南水乡")
weather天气(如"小雨")

get() 返回当前存储的世界状态,update() 只接受上表中的 5 个字段,传入其他字段名会报错。

world.get()

获取当前世界状态。

const world = await storvia.world.get();
// { time: "晚上 21:00", location: "秦照野的直播间" }

world.update(data)

更新世界状态。传入的字段会与已有数据合并,未传入的字段保持不变。只传已启用的字段,传入未启用字段会被忽略。

await storvia.world.update({
    time: "深夜 23:30",
    location: "回到家中",
});

storvia.player — 玩家

player.get()

获取玩家基本信息(名称、性别、描述、头像)。

const player = await storvia.player.get();
// { name: "小明", gender: "male", description: "冒险者", avatar: "https://..." }

player.update(data)

更新用户人设。传入字段会合并到现有数据,未传入的字段保持不变。name + description 合计上限 5000 字符

await storvia.player.update({
    name: "小明",
    gender: "male",
    description: "22岁的新晋制作人",
    avatar: "https://example.com/player.png", // 可选
});

player.state.get()

获取玩家状态。不传参数返回全部分组,传分组名返回该组数据。

字段值为 RichFieldValue 对象,包含 value(当前值)、type(字段类型)以及可选的 min/max(数值范围)。可使用 SDK 导出的 extractFieldValue() 工具函数提取原始值。

作者在创作台配置初始属性值时,可以留空不填。留空的字段在游戏开局不会出现在 state 里,聊天页面也不会显示。等到 AI 在对话中首次赋值(或 SDK 调用 player.state.update())后才会开始展示。这种"渐进式揭示"适合做好感度、剧情开关等属性。

import { extractFieldValue } from "@storvia/sdk";

// 获取全部分组
const allState = await storvia.player.state.get();
// {
//   "经济": {
//     "花园币": { value: 500, type: "number", min: 0, max: 99999 },
//     "等级": { value: 3, type: "number", min: 1, max: 100 }
//   },
//   "数据": {
//     "粉丝": { value: 120, type: "number" }
//   }
// }

// 提取原始值
const coins = extractFieldValue(allState["经济"]["花园币"]); // 500

// 获取特定分组
const economy = await storvia.player.state.get("经济");

player.state.update(group, values)

更新指定分组的玩家状态。传入的字段与该组已有数据合并。只需传简单值,系统会自动保留字段的元数据(type/min/max)并做范围钳位。

await storvia.player.state.update("经济", {
    花园币: 450, // 扣了 50 币,系统自动钳位到 [0, 99999]
    经验: 180, // 加了 30 经验
});

分组名和字段名必须和创作台中配置的完全一致(包括中英文、空格等)。


storvia.characters — 角色

characters.list()

获取所有角色列表。预设角色的 description 为作者设定(对玩家可见),用户可通过 userDescription 补充。创作台里为预设角色上传的头像会随 avatar 字段返回完整可访问的 URL。

const chars = await storvia.characters.list();
// [{
//   name: "秦照野",                    // 角色名
//   avatar: "https://...",             // 头像
//   description: "",                   // 预设角色固定为空字符串(作者人设仅 AI 可见);自建角色为用户撰写
//   introduction: "对外介绍文本",      // 仅预设角色有意义,作者资产,SDK 只读
//   visibleAtStart: true,              // 开局是否出场,仅预设角色有意义,作者资产,SDK 只读
//   userDescription: "对我温柔一些",    // 用户补充人设
//   gender: "male",                   // "male" | "female" | "other";老数据可能没有
//   isPreset: true                    // 是否为作者预设角色
// }, ...]

characters.get(name)

获取单个角色 信息(含人设)。

const char = await storvia.characters.get("秦照野");
// { name, avatar, description, introduction, visibleAtStart, userDescription, gender, isPreset }

characters.add(character)

添加新 角色。gender 必填,取值 'male' | 'female' | 'other'

await storvia.characters.add({
    name: "新角色",
    description: "一个神秘的路人",
    gender: "other", // 必填
    avatar: "img/stranger.png", // 可选
});

characters.update(name, data)

更新 角色信息。规则:

  • 预设角色isPreset: true):description(作者设定)不可修改;userDescription(用户补充)、avatargender 可修改
  • 非预设角色descriptionuserDescriptionavatargender 均可修改
  • introduction / visibleAtStart 是作者预设资产,所有角色都不可通过 SDK 修改(仅创作台 + /sync 同步)
  • 所有非预设角色的 description + 所有角色的 userDescription 合计上限 10000 字符
// 为预设角色添加用户补充人设
await storvia.characters.update("秦照野", { userDescription: "对我温柔一些" });

// 非预设角色可改 description
await storvia.characters.update("路人甲", { description: "神秘的陌生人" });

// 改头像
await storvia.characters.update("秦照野", { avatar: "img/new-avatar.png" });

// 改性别
await storvia.characters.update("秦照野", { gender: "male" });

characters.remove(name)

删除角色。

await storvia.characters.remove("新角色");

characters.detail(name)

获取 角色完整信息(人设 + 属性状态)。属性值为 RichFieldValue 格式。

const detail = await storvia.characters.detail("秦照野");
// {
//   name: "秦照野",
//   avatar: "https://...",
//   description: "",                    // 预设角色固定为空;自建角色为用户撰写
//   introduction: "对外介绍文本",        // 仅预设角色有意义,只读
//   visibleAtStart: true,                // 仅预设角色有意义,只读
//   userDescription: "用户补充",
//   gender: "male",
//   isPreset: true,
//   state: {
//     "档案": {
//       "心情": { value: "happy", type: "text" },
//       "好感度": { value: 45, type: "number", min: 0, max: 100 }
//     }
//   }
// }

characters.state.get(name)

获取角色的属性状态。不传 group 返回全部分组,传 group 返回该组数据(与 player.state.get() 对称)。

// 获取全部分组
const all = await storvia.characters.state.get("秦照野");
// {
//   "档案": {
//     "心情": { value: "happy", type: "text" },
//     "好感度": { value: 45, type: "number", min: 0, max: 100 }
//   },
//   "身份": {
//     "粉丝牌": { value: "真爱粉", type: "text" }
//   }
// }

// 获取单个分组
const profile = await storvia.characters.state.get("秦照野", "档案");

characters.state.update(name, group, values)

更新角色指定分组下的字段。传入字段与该分组已有数据合并。只需传简单值,系统自动保留字段元数据(type/min/max)并钳位。

await storvia.characters.state.update("秦照野", "档案", {
    心情: "happy",
    好感度: 50, // 自动钳位到 [0, 100]
});

分组名和字段名必须和创作台中配置的完全一致(包括中英文、空格等)。

characters.setPriority(name, value)

调整 角色在场景中的重要程度。范围 0-100(超出自动钳位到 0 或 100),越高表示越不容易被挤出场景。

当会话中的角色 数量超过上限时,系统会把 priority 最低的角色移入休眠池。

预设角色的 priority 固定为 100,不可修改(调用会返回错误)。

// 让某个角色 变得重要
await storvia.characters.setPriority("路人甲", 80);

// 让 角色退居二线(下次触发上限裁剪时会被优先移除)
await storvia.characters.setPriority("过客", 10);

等价写法:storvia.characters.state.update('路人甲', { priority: 80 })setPriority 是这种用法的显式快捷方法,类型和错误提示更明确。


storvia.relationships — 关系

关系是两个角色之间的定向连接,由 from + to 唯一标识。每条关系可以有自定义字段(对应创作台配置的关系字段)。

from / to 涉及玩家时必须使用 "玩家",与你通过 storvia.player.update({ name: "..." }) 设置的实际玩家名无关。所有 relationships.list/get/add/update/remove 接口都遵循此约定,例如:

await storvia.relationships.update("玩家", "秦照野", { 好感度: 50 });

使用其它值无法定位到玩家相关的关系。

relationships.list()

获取所有关系。

const rels = await storvia.relationships.list();
// [
//   { from: "玩家", to: "秦照野", "好感度": 45, "关系阶段": "朋友" },
//   { from: "玩家", to: "宋亦", "好感度": 30, "关系阶段": "认识" },
// ]

relationships.get(from, to)

获取两个角色之间的关系。

const rel = await storvia.relationships.get("玩家", "秦照野");
// { from: "玩家", to: "秦照野", "好感度": 45, "关系阶段": "朋友" }

relationships.add(relationship)

添加新关系。

await storvia.relationships.add({
    from: "玩家",
    to: "新角色",
    好感度: 0,
    关系阶段: "陌生",
});

relationships.update(from, to, data)

更新关系字段。合并更新。

await storvia.relationships.update("玩家", "秦照野", {
    好感度: 50,
    关系阶段: "朋友",
});

relationships.remove(from, to)

删除关系。

await storvia.relationships.remove("玩家", "新角色");

关系是单向的:from:"玩家" to:"秦照野"from:"秦照野" to:"玩家" 是两条不同的关系。如果需要双向关系,需要分别创建和更新。


storvia.inventory — 物品栏

数据结构Record<分组名, Record<物品名, { count, desc?, iconUrl? }>>

创作台里配置的分组在运行时始终保留(即使清空所有物品也不会消失),和 player.state / characters.state 的行为一致。

物品总数上限 20 件,达到上限后新增会被拒绝(SDK 和 AI 都一样),需先 remove 释放空间。

inventory.list()

获取整个物品栏,或指定分组下的物品。创作台里为预设物品配置的图标会随 iconUrl 字段返回完整 URL;没配置图标的物品缺省 iconUrl

// 全部
const all = await storvia.inventory.list();
// {
//   "礼物": { "玫瑰花": { count: 3, desc: "送给主播的礼物", iconUrl: "https://.../rose.png" } },
//   "装备": {},               // 空分组也会保留
//   "仓库": { "宝箱": { count: 1, iconUrl: "https://.../chest.png" } }
// }

// 单个分组
const gifts = await storvia.inventory.list("礼物");
// { "玫瑰花": { count: 3, desc: "...", iconUrl: "https://.../rose.png" } }

创作台里为预设物品配置的图标会在首次同步时写入存档,list() 会直接返回带 iconUrl 的数据。如果没有配置图标,字段为 undefined

inventory.add(options)

参数:{ group, name, count?, desc?, iconUrl? }

新增物品。group 必须是已存在的分组(创作时定义,或先用 ensureGroup 创建);同分组下 name 唯一。iconUrl 支持 http/https 图片地址或 Storvia 的 storage:// 路径。

await storvia.inventory.add({
    group: "礼物",
    name: "玫瑰花",
    count: 5,
    desc: "送给主播的礼物",
    iconUrl: "https://example.com/rose.png", // 可选
});

inventory.update(options)

参数:{ group, name, count?, desc?, iconUrl? }

更新物品字段。groupname 是必填(用于定位物品),其余字段(count / desc / iconUrl)按需传入,合并更新,未传的保持不变。传空字符串不会清除 iconUrl,现阶段要"去掉图标"需要先 removeadd

// 同时更新多个字段
await storvia.inventory.update({
    group: "礼物",
    name: "玫瑰花",
    count: 10,
    desc: "新描述",
    iconUrl: "https://example.com/rose-v2.png",
});

inventory.remove(options)

参数:{ group, name }

删除单个物品。分组本身保留,即使变空也不会消失。

await storvia.inventory.remove({ group: "礼物", name: "玫瑰花" });

inventory.move(options)

参数:{ fromGroup, toGroup, name, newName? }

在分组间移动物品,可选择同时改名。事务完成,不会因中途失败导致物品丢失。

// 把随身的药水移到仓库
await storvia.inventory.move({
    fromGroup: "随身",
    toGroup: "仓库",
    name: "生命药水",
});

inventory.ensureGroup(group)

幂等地确保分组存在。用于运行时动态创建创作时未定义的分组。

await storvia.inventory.ensureGroup("临时物品栏");

inventory.removeGroup(group, options?)

第二参数:{ cascade?: boolean }

显式删除整个分组。默认非空分组会报错;传 cascade: true 连带物品一起删。

await storvia.inventory.removeGroup("临时物品栏"); // 仅空分组
await storvia.inventory.removeGroup("临时物品栏", { cascade: true }); // 强制删除

从 SDK v0.2.0 起,物品栏的数据结构从"扁平数组 + group 字段"改为"分组 → 物品名 Record"。创作时定义的分组现在会永久保留,不再因为物品清空而消失。如果你从旧版本升级,需要更新调用方式(所有方法都改为对象参数)。


storvia.custom — 扩展属性

扩展属性存储游戏中的额外变量。字段类型只支持 文本 / 数值,可选分组(分组的子字段也只能是文本/数值)。支持两种用法:

  • 纯 SDK 数据 — 不注入 AI,仅游戏代码读写(如关卡进度、计数器)
  • AI 追踪数据 — inject 状态开启时字段值会注入 AI 提示词,AI 每轮自动更新

AI 追踪可以双端控制

  • 创作台:字段级 / 分组级开关,作为新增字段的初始 inject 状态
  • SDK:运行时调用 setInject(key, value)set(data, { inject: true }) 动态切换
  • 分组的 AI 追踪是整组开关:开启后组内所有子字段都被 AI 看到
  • 调用 /sync 时只会为新增 key 写入作者最新的 inject 默认值;已有 key 的 inject 状态由 SDK 自由控制,/sync 不再覆盖
  • 需要存任意 JSON、永不被 AI 看到?请用 storvia.save

限制

项目限制
字段总数(平铺 + 所有分组内字段)无限制——可建任意多字段
注入 AI 的字段数(rules + state 值)100 个——按作者填写顺序累计,超出的不进 prompt、不进 state XML
字段类型文本 / 数值
单字符串值长度无限制——按 token 计费自然约束成本

注入 AI 的字段数达到 100 后,AI 动态新增字段(op="add")会被拒绝;其余非注入字段不计入这个上限,可继续随意读写。控制"哪些字段被注入"用 inject 开关 + 场景设定 组合:把字段绑到特定场景,AI 只在该场景看到。

custom.get(key?)

获取扩展属性。不传参数返回全部,传 key 返回指定字段。

// 获取全部
const all = await storvia.custom.get();
// { chapter: 3, bgm: "rain", endings: { he: false, be: true } }

// 获取单个字段
const chapter = await storvia.custom.get("chapter");
// 3

custom.set(data, options?)

深合并更新。平铺字段直接覆盖,分组字段合并子字段(不会丢失未传入的子字段)。options.inject 可一次性把这次写入的所有 key 标记为对应 inject 状态。

// 更新平铺字段:推进到第 4 章
await storvia.custom.set({ chapter: 4 });

// 更新分组内的字段(只改 he,be 保持不变)
await storvia.custom.set({ endings: { he: true } });

// 写入并同时开启 AI 追踪
await storvia.custom.set({ chapter: 4 }, { inject: true });

custom.setInject(key, inject)

单独切换某个顶层 key 的 AI 追踪状态(不修改值)。分组的 setInject 等价于整组开关。

await storvia.custom.setInject("chapter", true); // 开启注入
await storvia.custom.setInject("endings", false); // 整组关闭注入

custom.getInject()

读取当前所有顶层 key 的 inject 状态(同步方法)。

const injectMap = storvia.custom.getInject();
// { chapter: true, endings: false }

custom.delete(key)

删除一个平铺字段或整个分组。

// 删除平铺字段
await storvia.custom.delete("bgm");

// 删除整个分组
await storvia.custom.delete("endings");

custom.setGroupField(groupKey, fieldKey, value)

更新分组内的单个字段。如果分组不存在会自动创建。

await storvia.custom.setGroupField("endings", "se", true);

custom.deleteGroupField(groupKey, fieldKey)

删除分组内的单个字段。分组本身会保留(即使字段全空),不会自动消失。如需删除整个分组请调用 custom.delete(groupKey)

await storvia.custom.deleteGroupField("endings", "be");

AI 追踪

inject 状态决定字段是否注入 AI 提示词。开启后:

  • 字段的当前值会注入到 AI 提示词中,AI 能感知这个数据
  • AI 每轮回复时会自动更新该字段(和角色属性、物品栏一样)

两种控制方式(任选其一或组合使用):

  1. 创作台静态配置——在「自定义属性」区域,每个平铺字段分组有一个「AI」开关。分组开关是整组开关,开启后组内所有子字段都注入。
  2. SDK 运行时切换——storvia.custom.setInject(key, value)set(data, { inject: true }) 动态切换。

配合「场景设定」:创作台为字段或分组配置场景设定后,字段只在指定场景下注入(如 viewer_count 只在直播场景注入)。SDK 只能切 inject 开关,场景设定始终来自创作台配置。

/sync 行为:增量同步——只会为新增 key 写入作者最新的 inject 默认值。已有 key(不论是作者预设还是 AI/SDK 运行时新增)的 inject 状态保留,/sync 不再覆盖。所以 SDK 调 setInject(key, value) 之后即使 /sync 也不会被回退。

适用场景:

  • AI 追踪:剧情进度、任务阶段、密室锁定状态 等需要 AI 自动维护的变量
  • 纯 SDK:UI 主题、音量、调试开关 等纯前端逻辑数据

扩展属性单字符串字段值无长度上限——按 token 计费的成本会自然约束过长内容的使用。


storvia.state — 完整游戏状态

一次性返回当前会话所有模块(world / player / characters / inventory / relationships)的合并快照。适合渲染整体属性面板、做存档导出、或调试时观察当前游戏状态。

state.get()

const snapshot = await storvia.state.get();

返回值

{
  current: PublicCurrentState,           // 当前活跃模块的合并快照
  previous: PublicCurrentState | null,    // 上一轮的 current(用于 before/after 对比)
  dormant: {                              // 因角色数量超出上限被移入休眠区的数据
    characters: Record<string, CharacterState>,
    relationships: Array<Record<string, unknown>>,
  }
}

会话尚未初始化时返回 null

完整 JSON 示例

{
  "current": {
    "world": {
      "time": "晚上 22:00",
      "date": "2024年3月15日",
      "location": "秦照野的直播间",
      "region": "江南水乡",
      "weather": "小雨"
    },
    "player": {
      "attributes": {
        "基础": {
          "等级": { "value": 5, "type": "number", "min": 1, "max": 100 },
          "经验": { "value": 180, "type": "number", "min": 0, "max": 9999 }
        },
        "经济": {
          "花园币": { "value": 450, "type": "number", "min": 0, "max": 99999 }
        }
      }
    },
    "characters": {
      "秦照野": {
        "isPreset": true,
        "priority": 100,
        "avatar": "https://cdn.storvia.com/avatars/qzy.png",
        "gender": "male",
        "attributes": {
          "档案": {
            "好感度": { "value": 50, "type": "number", "min": 0, "max": 100 },
            "心情": { "value": "开心", "type": "text" }
          }
        }
      },
      "路人甲": {
        "isPreset": false,
        "priority": 60,
        "gender": "other",
        "attributes": {
          "档案": {
            "好感度": { "value": 0, "type": "number", "min": 0, "max": 100 }
          }
        }
      }
    },
    "inventory": {
      "礼物": {
        "玫瑰花": { "count": 3, "desc": "送给主播的礼物", "icon_url": "https://cdn.storvia.com/items/rose.png" }
      },
      "装备": {}
    },
    "relationships": [
      { "from": "玩家", "to": "秦照野", "好感度": 50, "关系阶段": "朋友" }
    ]
  },
  "previous": {
    "world": { "time": "晚上 21:00", "...": "..." },
    "player": { "...": "..." },
    "characters": { "...": "..." },
    "inventory": { "...": "..." },
    "relationships": []
  },
  "dormant": {
    "characters": {
      "过客": {
        "isPreset": false,
        "priority": 10,
        "attributes": { "档案": { "好感度": { "value": 5, "type": "number" } } }
      }
    },
    "relationships": []
  }
}

字段说明

  • current.world — 扁平 KV,对应 storvia.world.get()
  • current.player.attributes — 按分组的玩家属性,对应 storvia.player.state.get()
  • current.characters[name].attributes — 按分组的角色属性,对应 storvia.characters.state.get(name)isPreset / priority / avatar / gender 为顶层 meta 字段
  • current.inventory — 分组 → 物品名 → { count, desc?, icon_url? }
  • current.relationships — 关系数组,每条形如 { from, to, ...自定义字段 }
  • previous — 与 current 同结构,但是 AI 上一轮回复前的快照;首次对话时为 null
  • dormant.characters — 休眠的角色(priority 较低、被挤出活跃区的);不会注入 AI,AI 也不会更新这些角色

和 chat 响应里 full 的关系storvia.chat.send() / generate() / retry() 在 AI 本轮有属性变更时,会在响应里携带同样结构的 full 字段。两者数据结构完全一致,区别在于:

  • chat.*full对话响应顺带返回——AI 改了什么自动给你
  • storvia.state.get()主动拉取——任意时刻取当前最新值

该方法在预览模式下无法正常使用,需要发布后在 Storvia 平台测试。 预览会话不持久化到数据库;调用会抛出 StorviaError(code: NOT_SUPPORTED_IN_PREVIEW)。预览阶段需要查看状态时,用各分模块的 get() 单独读取(如 storvia.world.get() / storvia.player.state.get())。


storvia.save — 游戏存档

save 是作者自由读写的任意 JSON,专供游戏运行状态持久化。和 custom 的关键区别:

特性customsave
数据类型仅文本/数值(可分组)任意合法 JSON(嵌套对象、数组、布尔均可)
AI 注入可选(创作台开启 AI 追踪时)永不注入
配额共享 100 字段上限独立配额,不计入 custom
大小上限单字符串无上限整个存档序列化后 ≤ 256KB
写入语义深合并(分组合并子字段)整体覆写

save.get()

读取整个存档对象。第一次调用(未写入过)返回 {}

const save = await storvia.save.get();
// {} 或上次写入的对象

save.set(data)

整体覆写存档。增量更新需要自行 get → 修改 → set

// 典型存档场景
await storvia.save.set({
    chapter: 3,
    cursor: { x: 120, y: 340 },
    flags: { metAlice: true, doorUnlocked: false },
    inventory: [
        { id: "key_red", count: 1 },
        { id: "potion", count: 5 },
    ],
    history: ["scene_intro", "scene_market"],
    meta: { savedAt: Date.now(), version: 2 },
});

// 增量更新:先读再改
const cur = await storvia.save.get();
cur.flags.doorUnlocked = true;
await storvia.save.set(cur);

存档大小上限为 256KBJSON.stringify(data).length),超出会返回 SAVE_DATA_TOO_LARGE。如果你的游戏需要存储更多状态(如完整地图数据),考虑只存关键索引,详细内容用 localStorage 或后端服务存储。

禁止把图片本体(base64 / dataURL / 二进制等)直接写入 save 一张图片就能轻松占用几百 KB 到几 MB,远远超过 256KB 上限,会直接导致 save.set() 失败、玩家整局存档丢失。

正确做法:把图片上传到图床或对象存储,save 里只存图片的 URL / 路径。比如:

// ❌ 错误:把整张图塞进去
await storvia.save.set({ avatar: "data:image/png;base64,iVBORw0KG..." });

// ✅ 正确:只存路径
await storvia.save.set({ avatar: "https://cdn.example.com/avatars/u123.png" });

同理适用于音频、视频、PDF 等任意二进制资源——save 的所有字段只用来存轻量结构化数据(数字、布尔、短文本、引用 URL),永远不要存原始资源本身。


storvia.memory — AI 记忆

读取/编辑当前会话的 AI 记忆——也就是聊天界面"AI 记忆"对话框里那段长期总结,会自动注入每一轮对话提示词,用于跨长对话保持剧情连贯。

  • 覆写语义update(content) 用新内容整体替换旧记忆,写入时自动 trim

关于自动总结(开发中)

目前 world-engine 后端不会自动为通过 SDK 创建的会话生成 AI 记忆——memory.get() 在你(或玩家)首次手动 update 之前会一直返回 null。如果你的游戏需要长期记忆能力来跨长对话保持剧情连贯,请在剧情关键节点自行调用 storvia.memory.update(...) 写入。

平台正在开发新版自动总结方案,上线后会按消息数阈值在后台自动生成总结并写入此字段,作者代码无需变更即可受益。进度会在 更新日志 公告。

返回类型

interface AISummary {
    content: string; // 记忆内容
    updated_at: string; // ISO 时间戳,最近一次写入时间
}

memory.get() → Promise<AISummary | null>

读取当前会话的 AI 记忆。首次未生成时返回 null

const m = await storvia.memory.get();
// null 或:
// { content: "主角进入山洞后揭开了……", updated_at: "2026-05-06T10:00:00.000Z" }

memory.update(content) → Promise<AISummary>

整体覆写记忆内容,返回写入后的最新结构。

const updated = await storvia.memory.update("主角揭开了山洞中的秘密,与伙伴重逢。");
// { content: "主角揭开了山洞中的秘密,与伙伴重逢。", updated_at: "..." }

update 是覆写而非追加。如需在原记忆基础上扩写,请先 get 取出旧 content,自行拼接后再 update


storvia.getAssets() — 素材库

平台级方法(非会话模块),用于获取官方素材库中的头像和物品图标。

getAssets(type, category?)

按类型获取素材列表,可选按分类过滤。

参数

参数类型必填说明
type'avatar' | 'icon'素材类型:头像或物品图标
categorystring分类名称,不传则返回全部(分类待更新)

返回值Promise<AssetItem[]>

interface AssetItem {
    id: number;
    name: string;
    url: string;
    assetType: "avatar" | "icon";
    category: string;
}

示例

// 获取所有头像素材
const avatars = await storvia.getAssets("avatar");
// [
//   { id: 1, name: "骑士", url: "https://...", assetType: "avatar", category: "奇幻" },
//   { id: 2, name: "法师", url: "https://...", assetType: "avatar", category: "奇幻" },
//   ...
// ]

// 按分类获取物品图标
const weapons = await storvia.getAssets("icon", "武器");

// 用获取到的素材设置角色头像
const avatar = avatars[0];
await storvia.characters.update("骑士", { avatar: avatar.url });

素材库数据由平台官方维护。


数据应该放哪里?

需求推荐模块
需要 AI 感知的角色/世界/物品状态world / player.state / characters.state / relationships / inventory
需要 AI 感知的简单变量(剧情进度、好感度等)custom(创作台开启 AI 追踪)
不需要 AI 感知的简单 KV(计数器、开关)custom(创作台关闭 AI 追踪)
游戏运行状态、UI 缓存、复杂结构save(不占 custom 配额,永不注入 AI)

On this page