功能指南:为 Gemini 对话标注精确发送时间)
AI 应用前端【免费下载链接】voyagerEnhancement suite for Gemini, AI Studio, Claude ChatGPT — plus a prompt manager for any websites, DeepSeek Harness included. / 面向 Gemini、AI Studio、Claude 与 ChatGPT 的增强套件其中的提示词管理器可用于任意网站如 DeepSeek Harness。项目地址https://gitcode.com/gh_mirrors/ge/voyager点击查看免费下载导读本文面向使用 Voyager 增强套件的开发者与用户围绕docs/es/guide/timestamp.md文档中介绍的消息时间戳功能展开。该功能解决 Gemini 原生界面不显示消息发送时间的问题Voyager 在每条消息上自动标注精确到秒的时间戳格式YYYY-MM-DD HH:mm:ss并持久化到本地存储刷新页面后依然可见。读完本文你将掌握该功能的启用方式、时间戳的数据格式与存储结构、底层实现原理含服务端时间解析与本地兜底双通道以及它如何与时间线Timeline等模块协作从而在长对话、跨设备场景中准确回溯讨论时间。功能概述Voyager 的消息时间戳功能自版本1.3.7起可用见 1.3.7 变更日志 中的 Per-message timestamps 条目。它的核心价值在于补足 Gemini 的缺失能力Gemini 不原生显示消息的发送时间。随着对话变长用户很难回忆起某次具体讨论发生在何时。Voyager 为每条消息标注精确时间戳格式AAAA-MM-DD HH:mm:ss让时间线一目了然。AAAA-MM-DD HH:mm:ss为西班牙语文档中YYYY-MM-DD HH:mm:ss的本地化拼写实际渲染格式为年-月-日 时:分:秒。核心特性根据原文档该功能具备四个关键特性自动记录Registro automático时间戳在消息发送时自动捕获无需任何手动操作秒级精度Precisión al segundo包含完整的日期与时间适合回看长对话本地持久化Persistencia local时间戳保存在本地存储中页面刷新后依然可见零干扰Cero distracción时间信息以低调方式呈现不影响阅读体验。典型使用场景原文档列举了三个典型场景工作记录回顾某个决策是在什么时间达成的学习笔记标记某个概念是在何时讨论的便于日后复习长对话回顾在多天的深度对话中清晰区分不同时段的讨论。启用方式时间戳功能在 Voyager 的弹窗popup设置中提供开关。对应西班牙语本地化文案位于 src/locales/es/messages.jsonshowMessageTimestamps→ Mostrar marcas de tiempo de mensajes显示消息时间戳showMessageTimestampsHint→ Mostrar cuándo se envió cada mensaje显示每条消息的发送时间用户只需在 Voyager 弹窗中打开该开关Voyager 便会在 Gemini 聊天界面与时间线中为每条消息渲染时间戳无需其他配置。数据格式与存储结构时间戳的渲染格式由 TimestampService.ts 中的formatAbsoluteTime方法定义formatAbsoluteTime(timestamp: number): string { const date new Date(timestamp); const year date.getFullYear(); const month String(date.getMonth() 1).padStart(2, 0); const day String(date.getDate()).padStart(2, 0); const hours String(date.getHours()).padStart(2, 0); const minutes String(date.getMinutes()).padStart(2, 0); const seconds String(date.getSeconds()).padStart(2, 0); return ${year}-${month}-${day} ${hours}:${minutes}:${seconds}; }即输出YYYY-MM-DD HH:mm:ss形式时、分、秒均补零到两位全部取本地时区时间。存储层使用version: 2的结构化数据TimestampService.ts按会话conversation与轮次turn两级索引interface TimestampStorageData { version: 2; conversations: Recordstring, TimestampMap; } // TimestampMap: { [turnId: string]: number } —— 时间戳为毫秒级 epoch 数值存储键为StorageKeys.GV_MESSAGE_TIMESTAMPSgvMessageTimestamps见 src/core/types/common.ts。核心字段说明字段类型说明versionnumber存储格式版本当前为2conversationsRecordstring, TimestampMap按会话 ID 分组的时间戳表conversations[turnId]number该轮次消息的发送时间单位毫秒数据隔离与旧版迁移从源码可以看出时间戳按会话隔离存储避免不同会话之间串扰。initialize在加载存储时会检测旧版扁平结构v1 仅按 turnId 全局存储可能在会话间泄漏一旦发现即整体移除该键TimestampService.tsconst { conversations, legacyDetected } this.parseStorageData(result.data); this.timestamps conversations; if (legacyDetected) { await this.storageService.remove(StorageKeys.GV_MESSAGE_TIMESTAMPS); }上述行为均有对应测试覆盖见 src/pages/content/timestamp/tests/TimestampService.test.tsshould ignore legacy flat timestamp storage与 同文件should isolate timestamps by conversation。自动记录消息发送即写入原文档强调无需手动操作。这一点的实现由recordTimestamp完成TimestampService.tsasync recordTimestamp(conversationId: string, turnId: TurnId, timestamp?: number): Promisevoid { const ts timestamp ?? Date.now(); const conversationTimestamps this.getConversationTimestamps(conversationId, true); // 重复记录相同值例如每次加载会话时重新应用 API 时间不得反复触发存储写入 if (conversationTimestamps.get(turnId) ts) return; conversationTimestamps.set(turnId, ts); await this.schedulePersist(); }两个细节值得注意默认取当前时间调用方未传入timestamp时使用Date.now()毫秒精度去重防抖对同一turnId重复写入相同值会被短路避免在每次加载会话时产生无意义的存储写入——对应的测试见 TimestampService.test.tsshould not persist when re-recording the same value。异步合并写入schedulePersistrecordTimestamp不直接同步写存储而是通过schedulePersist把多次写入合并到一轮持久化中TimestampService.ts。其要点维护dirty标记与一个pendingPersist待决 Promise首次写入时用setTimeout(..., 0)调度flushPersist在微任务之后统一落盘若在落盘进行中又有新写入到达则复用同一个待决 Promise并在flushPersist的finally中检测dirty重新调度一轮确保飞行中的写入不会丢失。对应的并发测试见 TimestampService.test.tspersists mutations that arrive while a flush is writing to storage它用一个可阻塞的set模拟慢存储验证第二轮 flush 会包含中途到达的写入。双通道时间来源本地记录 服务端真实时间在源码层面时间戳功能实际包含两条互补的数据通道这是原文档之外更深入的实现细节首见记录first-seen recording消息在页面中被 Voyager 观察到时记录本地时间对应TimestampService服务端时间解析history timestamps从 Gemini 加载会话的batchexecuteRPCrpcidhNvQHb响应中解析服务器为每条轮次携带的[seconds, nanos]时间戳即使该对话发生在其设备上也能显示真实发送时间。第二条通道的实现位于 historyTimestamps.ts文件头注释说明了整体设计Geminis conversation-load RPC (hNvQHbbatchexecute) carries a[seconds, nanos]server timestamp for every turn. The MAIN-worldpublic/conversation-history-observer.jscaptures those responses and bridges them here via window.postMessage; this module parses them and the TimelineManager matches the parsed turns to its markers so tooltips and inline timestamps show when a message was actually sent — even for conversations that happened on another device.捕获层MAIN world 网络钩子public/conversation-history-observer.js 在document_start阶段注入 MAIN world通过usageObserverLoader在 Gemini 发起会话加载 RPC之前就挂钩网络通过window.fetch与XMLHttpRequest包装拦截 URL 同时包含batchexecute与hNvQHb的请求conversation-history-observer.js捕获的响应体先放入有界缓冲区最多 4 条、单条上限 16MB、总上限 24MB等待隔离世界的内容脚本ack确认后才释放SPA 导航不会重放已解析的大响应conversation-history-observer.js与内容脚本之间通过window.postMessage通信消息源标记为gv-history-observer/gv-history-observer-cmd刻意让 fetch 包装函数返回原始 Promise避免破坏 Angular 的 zone.js 变更检测参见同目录 fetchInterceptor.js 的说明。解析层结构性防御式解析historyTimestamps.ts 负责解码响应并提取每条轮次的[seconds, nanos]时间戳。由于 Gemini 的载荷结构可能随时变化解析采用结构化的防御式写法所有访问都从unknown收窄任何不匹配都返回空结果功能会静默回退到首见记录通道见 historyTimestamps.ts 的findTurnTimestampMs与 同文件 的findTurnUserText。解析出的HistoryTurnTimestamp包含三个字段historyTimestamps.ts字段说明turnIdGemini[cid, rid]元组派生出的稳定响应 IDuserText服务器存储的用户查询文本空白折叠后timestampMs轮次创建时间毫秒级 epoch时间戳有效性还需通过一个合理的 epoch 秒窗口校验20152096 年MIN_EPOCH_SEC/MAX_EPOCH_SEC避免把结构巧合误当时间historyTimestamps.ts。数据生命周期管理为了让本地存储保持可控TimestampService在每次持久化时执行两件事容量上限裁剪最多保存MAX_TIMESTAMP_CONVERSATIONS 300个会话TimestampService.ts。超出上限时按各会话最新时间戳排序最先淘汰最新时间最旧的会话空会话视为最旧纯函数selectConversationIdsToPruneTimestampService.ts。对应测试见 TimestampService.test.ts 与 同文件跳过空会话持久化时丢弃没有任何轮次时间的会话记录TimestampService.ts。此外还提供会话级清理方法clearOldTimestamps(conversationId)删除某个会话的全部时间戳后触发一次持久化TimestampService.ts。与时间线Timeline模块的协作原文档提到时间戳同时出现在聊天界面与时间线中。在源码层面时间线模块src/pages/content/timeline/是服务端时间通道的主要消费方HistoryTimestampStore以单例historyTimestampStore存在于页面文档中TimelineManager通过subscribe订阅解析结果收到新会话数据后刷新标记historyTimestamps.ts时间线内嵌时间戳与 tooltip 的渲染逻辑位于 TimelineTimestamps.ts其测试见tests/TimelineTimestamps.test.ts为兼容旧版时间线数据存储还会把位置型 turn ID解析为规范的服务端 IDresolveCanonicalTurnId/getTurnIdAliaseshistoryTimestamps.ts并将服务端 ID 列表持久化到StorageKeys.GV_TURN_IDENTITY_CACHEgvTurnIdentityCache见 src/core/types/common.ts作为后续访问时可靠的别名缓存。因此可以推断在聊天内联时间戳与时间线 tooltip 中Voyager 会优先展示解析到的服务端真实发送时间当服务端载荷不可解析时自动回退到本地首见记录的时间——这正是自动记录与跨设备准确时间两套能力如何共存的机制。小结Voyager 的消息时间戳功能从版本 1.3.7 起为 Gemini 聊天界面补齐了原生缺失的消息发送时间信息。它由四部分构成弹窗开关控制启用showMessageTimestamps本地记录通道TimestampService.ts在消息出现时自动写入YYYY-MM-DD HH:mm:ss格式的时间戳并持久化到gvMessageTimestampsv2 结构按会话隔离最多保留 300 个会话服务端解析通道historyTimestamps.ts 配合 conversation-history-observer.js从 Gemini 的hNvQHbbatchexecute 载荷中提取真实发送时间实现跨设备准确时间线模块消费以上数据在 tooltip 与内联位置呈现时间。对于需要回溯某个决定是什么时候做出的、区分多天长对话中不同讨论时段的用户这一功能提供了一条零操作、低干扰的精确时间线。相关测试与实现文件可继续在 src/pages/content/timestamp/ 目录中查阅。赞分享AI 应用前端【免费下载链接】voyagerEnhancement suite for Gemini, AI Studio, Claude ChatGPT — plus a prompt manager for any websites, DeepSeek Harness included. / 面向 Gemini、AI Studio、Claude 与 ChatGPT 的增强套件其中的提示词管理器可用于任意网站如 DeepSeek Harness。项目地址https://gitcode.com/gh_mirrors/ge/voyager点击查看免费下载相关推荐Voyager 消息时间戳Message Timestamps功能详解在 Gemini 中记录每条消息的精确发送时间Voyager 消息时间戳Message Timestamps功能详解在 Gemini 中记录每条消息的精确发送时间 Voyager 会在 GeminiAI 应用前端Voyager 消息时间戳功能详解在 Gemini 对话中自动标注精确发送时间Voyager 消息时间戳功能详解在 Gemini 对话中自动标注精确发送时间 Voyager 会在 Gemini 每条消息旁自动标注精确到秒的发送时间戳格AI 应用前端Voyager 消息时间戳Message Timestamp深度解析为 Gemini 对话构建可回溯的时间线Voyager 消息时间戳Message Timestamp深度解析为 Gemini 对话构建可回溯的时间线 Voyager 的消息时间戳功能会自动为AI 应用前端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考