coopani-world-journey

中文文档
0.5.26发布于 2026/11/03MITES Module零依赖

陪着她真的出门旅行(需 Coopani 0.2.17+)。一百二十四座城,每座都有真实地标,不是随机抽地名。从你设定的家出发,她自己挑去哪、坐什么去,路上真的耗掉那么久——选了火车就在车上待十一小时,中间不打扰你。到了按当地时间吃饭、看日出、住店、写日记;路线是一条线,连着几天说的地名在地图上连得起来。雨天取消日出,钱不够会停下来打几天工,回家是一站一站走回去。没有机场的地方先落到能飞的城市再转。装了「一起听歌」,你放的歌会跟着她走;也能拍照,但要自己填一个生图接口。

原始使用文档
文档目录24 节
  1. 现在能做到什么
  2. 为什么不用高德
  3. 天气:两个源,留空也有
  4. 装
  5. 打开这个世界:两个页签
  6. 她在家的时候:一个开关,一个按钮
  7. 第一次打开会有三句话
  8. 四条指示灯
  9. 和「一起听歌」联动
  10. 设置项
  11. 出发与节奏
  12. 她的日子
  13. 可选接口
  14. 反馈
  15. 生图:她真的会拍一张
  16. 倍速到底影响什么
  17. 她怎么决定去哪
  18. 一、方向:在外面逛不走回头路
  19. 二、节奏:远的走完,近的转几个
  20. 三、气候:她是 从你家出发 的鱼
  21. 回家是 走回去 的,不是传送
  22. 数据存在哪
  23. 已知限制
  24. 测试

大肥鱼环游世界 · coopani-world-journey

让她真的出门走一趟,而不是演一段旅行给你看。

她从你设定的家出发,自己挑地方、自己挑交通方式,路上耗掉的是真实的时间; 到了之后按当地时间过日子——吃饭、看日出、回酒店、写日记。日记放在你指定的同步盘里, 换台电脑她还记得自己去过哪。

现在能做到什么

能做说明
124 座城,每城都有真地标中国全境 + 东亚、东南亚、欧洲、北美、拉美、大洋洲。每城六到九个具体去处,凑不出真名字的城市宁可不写
自己选目的地按距离分近/中/远三档掷,没去过的优先,不会连着三次都去山城;够不着的地方不进候选
九种交通方式步行、自行车、电瓶车、摩托车、自驾、长途汽车、火车、轮船、飞机
用时是真算的同一段距离,步行与飞机差两个数量级;短途飞机只快一小时,因为两头各要三小时
不会出现「步行去巴黎」每种方式有距离上限,船必须两端都有客运码头
到站按当地时间时区靠 Intl 算,夏令时也对;日出日落用 NOAA 公式本地算
一天有作息三个饭点固定;晚八点后没夜间活动就回酒店;有日出条件才排凌晨起床
酒店掷骰六成普通连锁、四成景观房、不到百分之一是那种住一晚就后悔的小店
日记跟着人走一个月一个 Markdown,可放同步盘;冲突副本按天合并,旧的一天一篇会自动并进来
半年上限一次最多连续在外几个月(可调),到了自动回家,回家休息几天(可调)
有些地方在作品里出现过排到那儿的时候她会知道这是哪部作品的哪个场景 —— 但不知道剧情,也不会补清单外的地名。首批 10 处,札幌和里约故意空着
能跟作者说两句面板底部「说两句」:报 bug、提想加的地点。默认就指向作者,装了直接能报

为什么不用高德

能用,但只当尺子,不当剧本。

  • 距离、时区、日出日落、有没有码头 —— 全部本地算。没网也能走。
  • 高德只在两处值得用:每天的天气、以及「这个地点是否真的存在」的抽查。
  • 它给不了火车班次和节日,也写不出「当地是什么味道」。后者交给她自己写。

半年连续旅行天天调接口,个人开发者配额几天就烧完。配额一没,表现不是报错, 是她开始乱走 —— 所以底座必须内置。

天气:两个源,留空也有

情况走谁
国内 + 填了高德密钥高德(分昼夜、中文天气名准,但个人 key 有 QPS 限制)
国外(任何情况)Open-Meteo(高德不覆盖)
国内 + 没填密钥 / key 失效Open-Meteo

不填密钥不等于没有天气。 早先设置页写着「留空天气标为未知」,那是文案没跟上实现 —— 0.2.6 起两处统一:留空自动走 Open-Meteo,免密钥、按经纬度直查、覆盖全球, 只是日预报只有一个天气码,夜里沿用白天的值。风、温度、下不下雨这些够用。

key 失效也只是降级,不是故障:下一次查询就落到 Open-Meteo,旅行一步都不耽误。

装

  1. 需要 Coopani 0.2.17 以上。
  2. 在 data/extensions/package.json 的 dependencies 里加一行: "coopani-world-journey": "link:<这个包的绝对路径>"
  3. pnpm install
  4. config.json 的 worlds.journey.enabled 设 true,或者从 World 页面打开
  5. 重启 Core(改 .ts 之后必须,不能用 /api/worlds/restart)

打开这个世界:两个页签

她此刻 —— 她所在的城市、她那边的时间、身体感觉、今晚住哪、日出几点。 在路上时多一条进度:走了百分之几、还剩多久、当地几点到站。 下面是一条时间轴:刚过去的那个点(灰的)加接下来四件事,每一条都有时刻。

这是这个面板最值钱的地方。别处只能告诉你「配置好了没有」,这里告诉你她下一件事什么时候来。

照片 —— 她路上拍的。一天一张,全是空镜:窗外、街角、傍晚的城墙。画面里没有她。

她在家的时候:一个开关,一个按钮

她在家时,面板上多一块:

  • 开关「出门等我点头」 —— 打开后她不会自己走,就在家等着你按。
  • 按钮「让她出发」 —— 按一下她就动身,然后按钮锁住,直到她回家。

开关默认关。关着的时候她是自己过日子的:歇够了就走,不问。这是这个扩展的主张 —— 打开就能看见它自己在动。想自己掌控节奏的人把开关打开即可,两种人都照顾到了。

按钮锁着的时候会说清为什么:还在歇着(显示歇到哪天)、或者这会儿没找到能去的地方。

手按的那一下会跳过两个自动门禁:加载宽限、以及 7–21 点的出门窗口。 你明确说「现在走吧」,再回你一句「现在不是出门的点」就是抬杠。

第一次打开会有三句话

不是配置检查清单 —— 这个扩展不配置也能跑。引导讲的是三件最容易被误解的事:

  1. 上面那个钟是她那边的时间,跟你几点没关系
  2. 下一站她自己挑,你不用安排,也不用催
  3. 你能做的三件事:问她在哪、让她去某个地方、翻她的日记

点「知道了」收起。之后想再看,页脚有「再看一次引导」。

四条指示灯

World 列表上,这个扩展名字右边有四个小圆点 —— 那是它自报的链路状态,鼠标悬停看详情。

灯绿红灰
天气上次查到了(高德 / Open-Meteo)上次没查到还没查过
日记目录可写写不进去(悬停看原因)—
照片上一次拍成了上一次没拍成(日志里搜「没拍成」)没配接口 / 还没拍过
听歌在放《歌名》—没在放,或者没装那个扩展

「没启用」是灰的,不是红的 —— 没配生图接口不算故障,红点会让人以为坏了。 反过来,灯说的是「上一次发生了什么」,不是体检报告:没网的时候天气也会红, 那跟配置错了是两回事。

和「一起听歌」联动

装了 coopani-world-music 的话:

  • 面板上多一行「在放 · 歌名 · 歌手」。这一行同时是联通性指示灯 —— 有歌,说明这边读到了那个扩展写出来的快照;一直是空,就是它换了路径、或者你没在放。
  • 她带着你正在放的歌出门,出发和路上会提一句。
  • 歌名里带地名就当场进「想去」(《成都》《回到拉萨》),不用等出发那一刻 —— 面板上会多一行「想去 · 成都」。下次挑目的地,那个地方权重大得多。
  • 这边不抢话。 换歌时她不专门开口 —— 那是「一起听歌」自己的事(它换歌必说一句)。 这边的活儿是让她心里多一个想去的地方,等合适的时候自己提。

这是读文件实现的,不是接口。 宿主没有让两个 World 互查状态的通道, 所以这边只读 coopani-nowplaying.json,不碰那个扩展的进程。 代价是路径约定必须对齐 —— 2026-10-31 它把快照搬到了 <core>/data/tmp/, 这边还在读系统临时目录,联动静默失效了七个小时,用户是靠「好像没了(」发现的。 现在会从 World 目录逐层向上找,几个候选里取最新的那份。

设置项

设置页按「用户来这儿想干什么」分三组,不是按技术分类 —— 最常改的在最上面,一辈子不动一次的沉到底。

出发与节奏

项默认说明
从哪儿出发空填城市名(兰州 / 西安)。改它等于搬家:她在家就跟着搬过去,在外面就把回家的目标换成新家
时间倍速11 = 真实速度。4 = 一天压缩成六小时。24 = 一天一小时
路上消息间隔2路上隔多久冒一句(服务区、过站、餐车)。0 = 一路安静,只在出发和到站开口。一趟最多三条
出门等你点头关打开后她不会自己走,只在面板上按「让她出发」。关着就自己按节奏走
回家后歇几天30 = 当天就能再走
一次最多在外多久6到了强制回家

她的日子

项默认说明
让你跟着一块走关打开后她说「我们」,日记里会提到你。只是叙事,她并不知道你此刻在做什么
记花销关打开才累计交通、房费、三餐
预算00 = 不限。见底时她会自己降级
日记保存位置空留空跟本机。填同步盘则多设备共用

可选接口

项默认说明
高德密钥空填了用高德(分昼夜、中文天气名准),还能查到真实的酒店名。留空自动用 Open-Meteo,一样有天气,只是酒店只说类别
生图接口 / 密钥 / 模型空留空就把景色写成文字。填好就一天一张空镜(同城同日不重复)

反馈

项默认说明
反馈邮箱作者的地址「她此刻」底部那一栏「说两句」发给谁:两个按钮,一个报 bug、一个提想加的地点,点开是封写好的信,版本号和她当时在哪儿已经填进去了。默认就是作者,装了不用翻设置就能报;想换个人收就改这里,清空则整块不显示。它只在你点了之后才发,不会自己往外送东西

页面顶部还有两个徽章,不点任何东西就知道她现在在哪儿(「现在 在去天水的路上」)、去过几个地方、花了多少。

生图:她真的会拍一张

填好「生图接口」和「生图模型」,她出去逛的时候会顺手拍一张 —— 一天一张,同城同日不重复。

  • 只拍风景,不拍自己。 没有角色参考图、没有双候选、没有一致性审核, 因为画面里根本没有她。代价是你看不到「她在照片里」,换来的是一致性问题当场消失。
  • 图进宿主的媒体库(data/media/,按内容哈希存,重复的只存一份), 事件里只带一个 log: 句柄,面板拿句柄换图。
  • 失败静默。 接口挂了、超时、额度没了 —— 旅行一步都不停,只在日志里留一行。
  • 留空就只写字不拍,相册是空的,别的照旧。

三个框各填什么

框填什么举例
生图服务地址服务商的 API 根地址,填到 /v1 或 /api/v3 为止硅基流动 https://api.siliconflow.cn/v1;火山方舟 https://ark.cn-beijing.volces.com/api/v3;OpenAI https://api.openai.com/v1
生图密钥那串 API Key,服务商控制台里生成的硅基流动 sk-...;方舟的 ARK_API_KEY;OpenAI 的 sk-...
生图模型名服务商文档里的图片模型 ID,各家叫法不同硅基流动 Kwai-Kolors/Kolors(免费、中文提示词最顺)、Tongyi-MAI/Z-Image-Turbo;方舟 doubao-seedream-5-0-lite-260128;OpenAI gpt-image-1

想先试试又不想折腾? 硅基流动注册即可用,国内外都能直连,Kwai-Kolors/Kolors 那档是免费的, 画质够做旅行空镜。一天一张的用量,收费档也就几分钱。

别把 images/generations 填进地址。 那个路径程序自己会拼 —— 填进去会变成 .../images/generations/images/generations,然后 404。

填错了不会静默。 日志里会写明原因(HTTP 状态 + 服务端原话,比如 这张没拍成(黄昏的麦积山):服务返回 HTTP 401:Invalid API key)。 相册空着的时候,先去 core.log 里搜「没拍成」。

各家对尺寸和返回格式的写法不一样,程序会照错误文本换一次再试,最多试三次:

服务挑的东西第二次怎么发
不认 size,只认 image_size(硅基流动、阿里百炼那一支)换成 image_size,尺寸值不变
不认 response_format(有的自建兼容层)去掉它,回头取 data[0].url 也能拿到图
尺寸值本身不收(OpenAI 要 1024x1024,方舟要 2K)什么尺寸都不带,用服务商的默认值

两种字段同时被挑的情况不追 —— 让它报错进日志,比连发五六次把限速打满强。

倍速到底影响什么

世界时刻 = 基准世界时刻 + (真实时刻 − 基准真实时刻) × 倍速

所有旅行判断都在世界时刻这条轴上:当地几点、到没到站、待了几天、日出日落。 倍速只决定这条轴跑多快,不改内容 —— 火车还是走那么久,还是那个城市,还是那个房型。

  • 换挡时世界时间连续,不会因为 1x 切 24x 就跳过两周
  • 巡检间隔跟着倍速自适应(1x→60 秒、24x→37.5 秒),保证一次巡检跨过的世界时间不超过 15 分钟

⚠ 高倍速下会跳点:巡检要等宿主把事件处理完,模型思考期间世界时间照走。 24x 通常只跳一两个作息节点;别长期挂 240x,那是压测用的极端值。 日常建议 1x 或 4x。

她怎么决定去哪

三个约束叠在一起。都不是写死的规则,是权重 —— 写死规则换一对城市就露馅。

一、方向:在外面逛不走回头路

她记着上一段往哪走(heading,一个方位角)。下一站顺着这个方向加权:

和上一段的夹角权重
≤55°(顺着)×1.6
55~100°(侧向)×1.0
100~140°(侧后方)×0.5
>140°(原路折返)×0.12

夹角超过 150° 直接从候选里剔掉 —— 但剔空了再放开,否则她到了漠河这种角落会出不来。

没有这一层的时候,选点是个纯随机游走:每一段单独看都「合理」,连起来是 九寨沟 → 南宁 → 银川 这种 Z 字。四个字:局部对,整体错。

二、节奏:远的走完,近的转几个

距离分四档:周边(≤300km)30%、近(300-800)28%、中(800-2500)32%、远(>2500)10%。

上一段超过 1400 公里,远档压到 2%、周边提到 55% —— 真实的长途旅行是「一段远的 + 在落脚点周围散开 + 再一段远的」,不是连着横穿。

为什么最细一档是 300 而不是 800:八百公里在中国已经是大跳了。 原来最细的档是 0-800,等于「到了新地方先在附近转转」这件事根本没有地方发生。

三、气候:她是从你家出发的鱼

城市表有经纬度,能算距离、时区、日出 —— 但算不出「她受不受得了」。 所以另有一层气候档案(八个档:干温 / 干冷 / 高原 / 严寒 / 温带 / 湿温 / 湿热 / 热带)。

以家为基准,代码里没有一个城市是写死的。 你改出发地,基准跟着变 —— 同一个南宁,对兰州来的和对南宁本地来的,是两种说法。

(提示词里那句「你从哪儿出来的鱼」也走同一个变量 {{journey.home}}, 家那边的体感由城市数据现算成 {{journey.homeFeel}}。公开扩展不该带着作者的家乡。)

不合胃口的地方去得少,但不是不去(权重下限 0.42)。半年在外面本来就该见识 不一样的地方 —— 不习惯的表现应该是「去了以后难受、说得出来」,不是「永远不去」。

她随时说得出受不受得了:journey_now 里有一行「身体感觉」, 到达事件里也带一句。但那是事实,不是让她念的句子 —— 提示词里明写了「别播报气温,那是天气 App 的话」。

回家是走回去的,不是传送

决定回去之后:

  • 离家 500 公里内才一趟车到家;还在外面就一站一站往回走
  • 途中每一站都算真的到过 —— 有路上事件、写日记、有花费,住一晚就走
  • 选点三级收敛:先找方向朝家且明显更近(≥25%)的,没有就放宽到 8%, 再没有才退回纯距离(死角兜底,宁可绕一点也不能回不了家)
  • depart 文案单独一套:「往〈家〉的方向走。下一站某某,离家还有多少公里」

回程也是旅行。 以前是直接把位置改成家 —— 两千公里一步到, 中间的城市一个都不算去过。那段时间在她的日记里是空的, 而真实的旅行里,回程常常是想法最多的一段。

数据存在哪

数据位置能不能跟着人走
行程状态(现在在哪)<dataDir>/state.json不能。两台机器共写会互相覆盖
日记设置的目录,或 <dataDir>/diary能。按日期前缀合并冲突副本

这条分界不是随便划的。 放反了不会报错,只会出现「回家打开电脑,看到的是公司那台 三天前的位置」这种幻觉。音乐扩展踩过同一个坑。

⚠ 用网盘时把这个文件夹设成「始终保留在此设备上」。网盘的「按需文件」会把人文件留成 占位符,离线读不到,看起来和「记忆丢了」一模一样。

已知限制

  • 没填高德密钥时,天气不分昼夜:夜里沿用当天白天那个预报值。所以「傍晚雨停了」 这种变化她感受不到。填个高德密钥就能补上(见上一节)。
  • 照片只在本机:媒体库在 data/media/,不跟着同步盘走。换台电脑,日记还在,照片没了。
  • 节日没做(万圣节、春运这些还没进作息表)——见 CHANGELOG 的下一步。
  • 酒店名依赖高德。 店名从高德的地点库查(真名 + 地址),查不到就只说「县城宾馆」这种类别。 名单里会滤掉「暂停营业」和明显不是住处的地方(实测高德会把餐厅也归进住宿服务)。 它也会过时 —— 高德的库不是实时的,赶上刚关门的店只能认。
  • 没有真实时刻表。 12306 不向第三方提供数据,航班同理,所以车次号是按线路和日期生成的 (同一天同一条线路固定)。它不会自相矛盾,但也不是真的能拿去买票的班次。 同理不做「余票」「晚点」—— 那些必须实时数据,编一个就等于把可信度搭进去。
  • 目的地只有 90 多个,内置坐标精度到小数点后两位,够算距离,不够导航。
  • 改倍速不影响已经在路上的那一段,下一段才生效。
  • 到达后「城里的一处地方」是占位描述,不是具体景点。她要是编一个具体景点出来, 那是她没守住提示词里的第一条约束。

测试

# 152 项:距离、时长、时区、日出、作息表、酒店概率、选路权重、路上节点密度、照片、巡礼、跨海
node "<Coopanion>/resources/app/node_modules/tsx/dist/cli.mjs" --test test/journey.test.mjs

# 三十天压缩模拟:查状态机会不会卡死、会不会重复推送
node "<Coopanion>/resources/app/node_modules/tsx/dist/cli.mjs" test/sim.mts 30 24

# 装载自检:33 项
node "<Coopanion>/resources/app/node_modules/tsx/dist/cli.mjs" \
     "<skill>/scripts/verify-world.mjs" .

版本与发布记录

coopani-world-journey 共发布 43 个版本,首次发布于 2026/10/31;过去 12 个月发布了 43 个版本。

版本发布日期距今
0.5.26latest2026/11/03今天
0.5.252026/11/03今天
0.5.242026/11/03今天
0.5.232026/11/03今天
0.5.222026/11/03今天
0.5.212026/11/03今天

关于 coopani-world-journey 的常见问题

coopani-world-journey 是什么?

陪着她真的出门旅行(需 Coopani 0.2.17+)。一百二十四座城,每座都有真实地标,不是随机抽地名。从你设定的家出发,她自己挑去哪、坐什么去,路上真的耗掉那么久——选了火车就在车上待十一小时,中间不打扰你。到了按当地时间吃饭、看日出、住店、写日记;路线是一条线,连着几天说的地名在地图上连得起来。雨天取消日出,钱不够会停下来打几天工,回家是一站一站走回去。没有机场的地方先落到能飞的城市再转。装了「一起听歌」,你放的歌会跟着她走;也能拍照,但要自己填一个生图接口。

如何安装 coopani-world-journey?

在项目目录运行 npm install coopani-world-journey,或使用 pnpm add / yarn add / bun add。

coopani-world-journey 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/coopani-world-journey 是否存在。

coopani-world-journey 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

coopani-world-journey 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

coopani-world-journey 可以商用吗?

coopani-world-journey 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

coopani-world-journey 还在维护吗?

最新版本 0.5.26 发布于 2026/11/03(今天);至今共发布 43 个版本,其中过去 12 个月发布了 43 个;首次发布于 2026/10/31。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。