dominds 1.19.2 → 1.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +1 -0
  2. package/dist/access-control.js +2 -2
  3. package/dist/cli/team-definition-audit.d.ts +2 -1
  4. package/dist/cli/team-definition-audit.js +20 -8
  5. package/dist/cli/validate-team-def.js +3 -3
  6. package/dist/dialog.d.ts +6 -1
  7. package/dist/dialog.js +13 -4
  8. package/dist/docs/context-health.md +39 -13
  9. package/dist/docs/context-health.zh.md +14 -7
  10. package/dist/docs/idle-reminder-wake.md +227 -0
  11. package/dist/docs/idle-reminder-wake.zh.md +227 -0
  12. package/dist/docs/mcp-support.md +11 -0
  13. package/dist/docs/mcp-support.zh.md +7 -0
  14. package/dist/docs/team_mgmt-toolset.md +5 -2
  15. package/dist/docs/team_mgmt-toolset.zh.md +4 -2
  16. package/dist/docs/tool-availability-protocol.md +4 -2
  17. package/dist/llm/client.d.ts +2 -0
  18. package/dist/llm/client.js +32 -2
  19. package/dist/llm/defaults.yaml +51 -10
  20. package/dist/llm/gen/codex.js +15 -0
  21. package/dist/llm/kernel-driver/drive.js +6 -0
  22. package/dist/llm/kernel-driver/flow.js +9 -0
  23. package/dist/llm/kernel-driver/idle-reminder-wake.d.ts +4 -0
  24. package/dist/llm/kernel-driver/idle-reminder-wake.js +351 -0
  25. package/dist/llm/kernel-driver/types.d.ts +1 -1
  26. package/dist/mcp/config.d.ts +1 -0
  27. package/dist/mcp/config.js +16 -0
  28. package/dist/mcp/supervisor.d.ts +7 -1
  29. package/dist/mcp/supervisor.js +298 -16
  30. package/dist/minds/load.js +7 -1
  31. package/dist/minds/minds-i18n.js +2 -2
  32. package/dist/minds/system-prompt-parts.js +56 -20
  33. package/dist/minds/system-prompt.d.ts +1 -0
  34. package/dist/minds/system-prompt.js +24 -16
  35. package/dist/runtime/driver-messages.d.ts +3 -0
  36. package/dist/runtime/driver-messages.js +91 -8
  37. package/dist/server/setup-routes.js +5 -5
  38. package/dist/tool.d.ts +8 -0
  39. package/dist/tools/builtins.js +6 -2
  40. package/dist/tools/ctrl.d.ts +2 -0
  41. package/dist/tools/ctrl.js +253 -67
  42. package/dist/tools/env.js +10 -58
  43. package/dist/tools/manual/render.js +4 -0
  44. package/dist/tools/mcp.d.ts +1 -0
  45. package/dist/tools/mcp.js +55 -5
  46. package/dist/tools/os.js +198 -0
  47. package/dist/tools/prompts/control/en/errors.md +2 -2
  48. package/dist/tools/prompts/control/en/index.md +1 -1
  49. package/dist/tools/prompts/control/en/principles.md +15 -14
  50. package/dist/tools/prompts/control/en/scenarios.md +6 -0
  51. package/dist/tools/prompts/control/en/tools.md +37 -4
  52. package/dist/tools/prompts/control/zh/errors.md +2 -2
  53. package/dist/tools/prompts/control/zh/index.md +1 -1
  54. package/dist/tools/prompts/control/zh/principles.md +15 -14
  55. package/dist/tools/prompts/control/zh/scenarios.md +6 -0
  56. package/dist/tools/prompts/control/zh/tools.md +37 -4
  57. package/dist/tools/prompts/mcp_admin/en/errors.md +0 -14
  58. package/dist/tools/prompts/mcp_admin/en/index.md +5 -3
  59. package/dist/tools/prompts/mcp_admin/en/principles.md +11 -5
  60. package/dist/tools/prompts/mcp_admin/en/scenarios.md +19 -3
  61. package/dist/tools/prompts/mcp_admin/en/tools.md +85 -21
  62. package/dist/tools/prompts/mcp_admin/zh/errors.md +0 -14
  63. package/dist/tools/prompts/mcp_admin/zh/index.md +5 -3
  64. package/dist/tools/prompts/mcp_admin/zh/principles.md +11 -5
  65. package/dist/tools/prompts/mcp_admin/zh/scenarios.md +19 -3
  66. package/dist/tools/prompts/mcp_admin/zh/tools.md +85 -21
  67. package/dist/tools/prompts/os/en/errors.md +0 -28
  68. package/dist/tools/prompts/os/en/scenarios.md +1 -1
  69. package/dist/tools/prompts/os/en/tools.md +8 -17
  70. package/dist/tools/prompts/os/zh/errors.md +0 -28
  71. package/dist/tools/prompts/os/zh/scenarios.md +1 -1
  72. package/dist/tools/prompts/os/zh/tools.md +8 -17
  73. package/dist/tools/prompts/personal_memory/en/principles.md +1 -1
  74. package/dist/tools/prompts/personal_memory/zh/principles.md +1 -1
  75. package/dist/tools/prompts/team_memory/en/principles.md +1 -1
  76. package/dist/tools/prompts/team_memory/zh/principles.md +1 -1
  77. package/dist/tools/registry.d.ts +5 -0
  78. package/dist/tools/team_mgmt-mcp-manual.d.ts +2 -2
  79. package/dist/tools/team_mgmt-mcp-manual.js +57 -16
  80. package/dist/tools/team_mgmt.js +9 -12
  81. package/dist/utils/task-package.d.ts +7 -0
  82. package/dist/utils/task-package.js +46 -23
  83. package/dist/utils/taskdoc.js +21 -17
  84. package/package.json +4 -4
@@ -0,0 +1,227 @@
1
+ # Idle reminder wake 设计
2
+
3
+ 英文版:[English](./idle-reminder-wake.md)
4
+
5
+ 本文定义一种 driver 级后台协程机制:当对话进入 `idle_waiting_user` 后,runtime 可以等待 reminder owner 产生的可唤醒事件;若事件到达时对话仍处于 idle,则把事件打包成一条 `role=user` 的系统提示消息,并继续驱动对话。
6
+
7
+ 本文是设计文档。它描述业务语义、owner 接口、取消模型与当前落地场景,不规定最终代码拆分。
8
+
9
+ ---
10
+
11
+ ## 背景
12
+
13
+ 现有 reminder owner 已负责维护提醒项的真实语义,例如 `shell_cmd` daemon reminder 能在下一次 reminder 更新时发现 daemon 已退出,并把提醒项更新为终态。
14
+
15
+ 但这条链路有一个缺口:如果 daemon 在对话 idle 期间退出,系统只会在下一次打开对话、显示 reminders 或新一轮 drive 时发现。对用户而言,长期运行的 shell 命令已经完成,但对话没有被自动唤醒,也不会主动说明进程已退出。
16
+
17
+ 这个问题不应由 `shell_cmd` 工具直接驱动对话解决。driver 是唯一应决定对话是否继续运行的组件;reminder owner 只负责解释自己拥有的 reminder 何时产生了值得唤醒模型的环境事件。
18
+
19
+ ---
20
+
21
+ ## 目标
22
+
23
+ - 在对话真正进入 `idle_waiting_user` 后,启动一个可取消的后台 await 协程。
24
+ - 允许 reminder owner 暴露“可唤醒事件”,例如 daemon exited。
25
+ - 事件到达时先短暂聚合,再形成一条 runtime `role=user` 系统提示消息。
26
+ - 若聚合完成后对话仍是 idle,使用普通 driver 路径继续驱动。
27
+ - 任意新的继续驱动动作都取消已有 idle await 协程。
28
+ - 保持 owner metadata 语义封装:framework 只按 owner 路由,不偷看 owner meta。
29
+ - 保证幂等:同一个环境事件不能重复插入系统提示。
30
+
31
+ ## 非目标
32
+
33
+ - 不把普通 reminder 内容变更都视为唤醒信号。
34
+ - 不让 reminder owner 直接调用 `driveDialogStream`。
35
+ - 不把 idle await 协程纳入 `activeRun`,以免 UI 把等待环境事件误判为 proceeding。
36
+ - 不在对话 blocked、stopped、dead 或 completed/archived 时自动唤醒。
37
+ - 不把 daemon stdout/stderr 的每次增长都作为唤醒事件;当前场景只处理 daemon lifecycle exit。
38
+
39
+ ---
40
+
41
+ ## 核心结论
42
+
43
+ ### 1. Driver 拥有 idle wake 生命周期
44
+
45
+ 当 `driveDialogStreamCore` 最终把 display state 设置为 `idle_waiting_user` 后,driver 外层启动一个 dialog-scoped idle wake task。
46
+
47
+ 该 task:
48
+
49
+ - 不持有 dialog mutex
50
+ - 不创建 active run
51
+ - 不改变 display state
52
+ - 只等待 owner 提供的 wake event
53
+ - 在新一轮 drive 开始前被取消
54
+
55
+ 这样可以保证“等待环境事件”不是“正在工作”,也不会抢占用户可见的运行控制语义。
56
+
57
+ ### 2. Reminder owner 只报告 wake event
58
+
59
+ `ReminderOwner` 增加可选接口:
60
+
61
+ ```ts
62
+ export type ReminderWakeEvent = Readonly<{
63
+ eventId: string;
64
+ reminderId: string;
65
+ content: string;
66
+ updatedContent?: string;
67
+ updatedMeta?: JsonValue;
68
+ }>;
69
+
70
+ export interface ReminderOwner {
71
+ readonly name: string;
72
+ updateReminder(dlg: Dialog, reminder: Reminder): Promise<ReminderUpdateResult>;
73
+ renderReminder(dlg: Dialog, reminder: Reminder): Promise<ChatMessage>;
74
+
75
+ waitForReminderWakeEvent?(
76
+ dlg: Dialog,
77
+ reminders: readonly Reminder[],
78
+ signal: AbortSignal,
79
+ ): Promise<ReminderWakeEvent | readonly ReminderWakeEvent[] | null>;
80
+ }
81
+ ```
82
+
83
+ `content` 是 owner 已经格式化好的系统提示正文,必须以 `【系统提示】` / `[System notice]` 开头。它不是用户真实输入,但当前 provider role 限制下会经 runtime prompt 路径持久化为 `role=user` 消息。
84
+
85
+ `eventId` 是 owner 范围内稳定幂等键。owner 必须能在 reminder meta 或 owner 自己的状态中记录该事件已经投递,防止重复 wake。
86
+
87
+ ### 3. 首个事件到达后进入短聚合窗口
88
+
89
+ driver 不应在第一个 wake event 到达后立刻 drive。它应:
90
+
91
+ 1. await 到第一个 wake event
92
+ 2. 打开一个约 500ms 的聚合窗口
93
+ 3. 收集同一 dialog 当前 idle wake task 下其它 owner/reminder 已经到达的 wake event
94
+ 4. 对收集到的事件做稳定排序与去重
95
+ 5. 打包形成一条 runtime prompt
96
+
97
+ 这样可以避免多个 daemon 在相近时间退出时连续触发多轮 drive。用户和模型看到的是一条合并的环境状态消息,而不是多条碎片化系统提示。
98
+
99
+ ### 4. Wake 后必须重新检查真实状态
100
+
101
+ 聚合窗口结束后,driver 必须重新从 persistence 检查:
102
+
103
+ - dialog 仍存在且 status 为 running
104
+ - display state 仍是 `idle_waiting_user`
105
+ - execution marker 不是 dead,也不是需要人工 resume 的 interrupted
106
+ - 没有 pending Q4H
107
+ - 没有 blocking pending sideDialog
108
+ - 当前没有 active run
109
+
110
+ 只有这些条件都满足,才允许以 wake prompt 继续驱动。否则丢弃本次 wake,并只保留 owner 的幂等/状态更新。
111
+
112
+ ### 5. 任意 drive 都取消 idle wake task
113
+
114
+ 进入任何新 drive 前,runtime 必须取消该 dialog 已存在的 idle wake task。包括:
115
+
116
+ - 用户发送新消息
117
+ - 手动 Continue / Resume All
118
+ - Q4H answer 恢复
119
+ - sideDialog response 恢复
120
+ - Diligence Push / 其它 runtime auto-drive
121
+ - 本机制自己的 wake drive
122
+
123
+ 取消后,旧 task 即使有 promise resolve,也不得产生副作用。
124
+
125
+ ---
126
+
127
+ ## Wake 消息格式
128
+
129
+ owner event 的 `content` 应聚焦事实,不给模型伪造用户诉求。
130
+
131
+ daemon exit 示例:
132
+
133
+ ```text
134
+ 【系统提示】
135
+ 后台进程已退出。这是 runtime 环境事件,不是新的用户指令。
136
+
137
+ - PID: 12345
138
+ - 命令: pnpm run build
139
+ - 退出状态: code 0, signal null
140
+
141
+ 请根据当前任务上下文判断是否需要查看最终 stdout/stderr 或向用户汇报结果;不要只回复“收到”。
142
+ ```
143
+
144
+ driver 聚合多条事件时,应保留每条事件的事实块,并加一个总前缀:
145
+
146
+ ```text
147
+ 【系统提示】
148
+ 以下是对话空闲期间发生的 runtime 环境事件。这些事件不是新的用户指令。
149
+
150
+ 1. 后台进程已退出 ...
151
+ 2. 后台进程已退出 ...
152
+
153
+ 请结合当前任务上下文继续推进;若这些事件不影响当前工作,不要发送占位式确认。
154
+ ```
155
+
156
+ ---
157
+
158
+ ## Shell daemon exit 当前落地场景
159
+
160
+ `shellCmdReminderOwner` 实现 `waitForReminderWakeEvent`。
161
+
162
+ 语义:
163
+
164
+ - 只关注该 owner 拥有的 daemon reminders。
165
+ - 只在 daemon 从 running 进入 exited/gone 时产生 wake event。
166
+ - stdout/stderr 增长不产生 wake event。
167
+ - 如果 reminder meta 已标记对应 exit event 已投递,则返回 `null`。
168
+ - event 到达后,owner 同时提供终态 reminder 的 `updatedContent` / `updatedMeta`,由 driver 在投递 wake 前持久化。
169
+
170
+ 需要补充的 meta:
171
+
172
+ - `originRootId`:恢复 origin dialog 时必须知道 root。
173
+ - `originDialogId`:已有字段,继续表示 self id。
174
+ - `exitWakeEventId`:稳定事件 id,例如 `shellCmd:daemonExited:<pid>:<startTime>`。
175
+ - `exitWakeNotifiedAt`:该事件已被 runtime 采纳并投递的时间。
176
+
177
+ daemon runner 如果能提供可 await 的 exit 信号,应优先使用;如果当前只能通过本地 IPC 状态检查实现,轮询必须封装在 owner 内部,driver 不承担 daemon 专属扫描逻辑。
178
+
179
+ ---
180
+
181
+ ## 取消与并发模型
182
+
183
+ 每个 dialog 最多一个 idle wake task。
184
+
185
+ 建议 runtime 维护:
186
+
187
+ ```ts
188
+ type IdleReminderWakeTask = Readonly<{
189
+ dialogKey: string;
190
+ controller: AbortController;
191
+ startedAt: string;
192
+ }>;
193
+ ```
194
+
195
+ 新 drive preflight 的第一步取消旧 task。取消是幂等的。
196
+
197
+ idle wake task resolve 后也必须再次检查自己仍是当前 task;如果已经被替换或取消,直接返回。
198
+
199
+ ---
200
+
201
+ ## 崩溃恢复
202
+
203
+ idle wake task 本身不持久化。后端重启后不会恢复“正在等待”的 promise。
204
+
205
+ 恢复后的首次正常 driver/display/reminder 更新仍会修正 reminder 终态。若需要重启后也主动唤醒 idle dialog,可以补充“启动时对 running idle dialogs 重新安装 idle wake task”的 bootstrap。该能力不是当前机制闭环的必要条件。
206
+
207
+ ---
208
+
209
+ ## 观测与错误处理
210
+
211
+ owner wait 接口必须 loud by default:
212
+
213
+ - 非取消错误应 structured log,字段包含 `rootId`、`selfId`、`ownerName`、`reminderId`、`eventId`(若有)。
214
+ - owner 不得吞掉不合理状态,例如重复 event id 与不同内容冲突。
215
+ - driver 若发现聚合后的状态不允许 revive,应记录 debug/warn 级别诊断,但不应把被丢弃的 wake 作为用户可见消息。
216
+
217
+ ---
218
+
219
+ ## 实现顺序
220
+
221
+ 1. 增加 `ReminderWakeEvent` 与 `ReminderOwner.waitForReminderWakeEvent?` 类型。
222
+ 2. 增加 driver 侧 idle wake task 管理:start/cancel/race/500ms 聚合/状态复检。
223
+ 3. 在所有 drive 入口 preflight 取消该 dialog 的 idle wake task。
224
+ 4. 在 driver 最终落到 `idle_waiting_user` 后启动 idle wake task。
225
+ 5. 实现 `shellCmdReminderOwner` 的 daemon exit wake event。
226
+ 6. 为 daemon reminder meta 补充 `originRootId` 与 wake 幂等字段。
227
+ 7. 补测试:单 daemon 退出唤醒、多 daemon 500ms 聚合、用户消息取消、blocked 不唤醒、幂等不重复。
@@ -98,6 +98,12 @@ Releasing:
98
98
 
99
99
  - Agents should call `mcp_release({"serverId":"<serverId>"})` (from `mcp_admin`) to release the
100
100
  leased runtime instance for the current dialog.
101
+ - `mcp_restart({"serverId":"<serverId>"})` enables a disabled server (`enabled: true`) before
102
+ starting it. After a successful restart, Dominds replaces the global runtime and clears all dialog
103
+ leases on the old runtime.
104
+ - `mcp_disable({"serverId":"<serverId>"})` disables a server (`enabled: false`) and stops any loaded
105
+ runtime/leases. Disabled servers remain visible as zero-tool MCP toolsets, and their configured
106
+ manual remains readable with an explicit disabled notice.
101
107
 
102
108
  ### Shared behavior (`truely-stateless: true`)
103
109
 
@@ -397,6 +403,11 @@ This is a Dominds-oriented schema. It is intentionally small and should be easy
397
403
  version: 1
398
404
  servers:
399
405
  <serverId>:
406
+ # Optional operational switch. `mcp_disable` writes this to false; `mcp_restart`
407
+ # writes it back to true before starting the server.
408
+ # Disabled servers start no runtime and expose a zero-tool toolset/manual marked disabled.
409
+ enabled: true
410
+
400
411
  # Concurrency model (IMPORTANT)
401
412
  # - Default false: per-dialog client leasing (safer for stateful servers)
402
413
  # - True: shared client across dialogs (only for servers that are truly stateless)
@@ -75,6 +75,8 @@ Dominds 的行为:
75
75
  释放:
76
76
 
77
77
  - 智能体应调用 `mcp_release({"serverId":"<serverId>"})`(来自 `mcp_admin`)来释放当前对话持有的租赁运行时实例。
78
+ - `mcp_restart({"serverId":"<serverId>"})` 会先启用被禁用的 server(`enabled: true`),再启动它。成功重启后,Dominds 会替换全局 runtime,并清理旧 runtime 上的全部对话 lease。
79
+ - `mcp_disable({"serverId":"<serverId>"})` 会禁用 server(`enabled: false`),并停止已加载 runtime/lease。禁用 server 仍作为 0 工具 MCP toolset 可见,已配置手册也会带明确 disabled 提示继续可读。
78
80
 
79
81
  ### 共享行为(`truely-stateless: true`)
80
82
 
@@ -322,6 +324,11 @@ headers:
322
324
  version: 1
323
325
  servers:
324
326
  <serverId>:
327
+ # 可选运维开关。`mcp_disable` 会把它写成 false;`mcp_restart`
328
+ # 会在启动前写回 true。
329
+ # disabled server 不启动 runtime,并暴露为带 disabled 标记的 0 工具 toolset/手册。
330
+ enabled: true
331
+
325
332
  # 并发模型(重要)
326
333
  # - 默认 false:每对话客户端租赁(对有状态服务器更安全)
327
334
  # - True:跨对话共享客户端(仅适用于真正无状态的服务器)
@@ -384,7 +384,9 @@ Notes:
384
384
 
385
385
  - MCP tool names are global across all toolsets (built-in + MCP). Collisions cause tools to be
386
386
  skipped and should surface via Problems + logs.
387
- - `mcp_admin` is a built-in toolset that contains `mcp_restart` (best-effort per-server restart).
387
+ - `mcp_admin` is a built-in toolset for MCP operations: `mcp_restart` enables/restarts a server,
388
+ `mcp_disable` disables a server while keeping its zero-tool toolset/manual visible, and
389
+ `mcp_release` releases the current dialog lease.
388
390
  - Optional manual information can live in `.minds/mcp.yaml` at `servers.<serverId>.manual`:
389
391
  - `contentFile`: the topic-file directory prefix for the formal runtime manual; the final `man({ "toolsetId": "<serverId>" })` content shown to the LLM is loaded from here
390
392
  - `content` / `sections`: inline team-management guidance shown in the `team_mgmt` MCP chapter (`sections` supports `[{ title, content }]` or `{ "<title>": "<content>" }`)
@@ -635,4 +637,5 @@ This avoids needing to grant full rtws access to configure the team.
635
637
  - Confirm the teammate is granted the relevant `<serverId>` toolset in `.minds/team.yaml`.
636
638
  - **MCP server keeps failing to (re)load**:
637
639
  - Check Problems details (missing env var, invalid tool name, collisions, connection errors).
638
- - After fixing config, use `mcp_restart` (from `mcp_admin`) for a best-effort per-server restart.
640
+ - After fixing config, use `mcp_restart` (from `mcp_admin`) to enable/restart the server. Use
641
+ `mcp_disable` to disable it while keeping the configured manual visible as a zero-tool toolset.
@@ -321,7 +321,8 @@ members:
321
321
  注意:
322
322
 
323
323
  - MCP 工具名称在所有工具集(内置 + MCP)中是全局的。冲突导致工具被跳过,应通过问题 + 日志暴露
324
- - `mcp_admin` 是一个内置工具集,包含 `mcp_restart`(每个服务器最佳努力重启)
324
+ - `mcp_admin` MCP 运维内置工具集:`mcp_restart` 启用/重启 server,`mcp_disable` 禁用
325
+ server 并保留 0 工具 toolset/手册可见性,`mcp_release` 释放当前对话 lease
325
326
  - 可选手册:可在 `.minds/mcp.yaml` 的 `servers.<serverId>.manual` 提供手册相关信息:
326
327
  - `contentFile`:正式 runtime 手册的 topic 文件目录前缀;`man({ "toolsetId": "<serverId>" })` 最终给 LLM 看的正文从这里加载
327
328
  - `content` / `sections`:补充给 `team_mgmt` MCP 章节看的 inline 团队管理说明(`sections` 支持 `[{ title, content }]` 或 `{ "<title>": "<content>" }`)
@@ -540,4 +541,5 @@ members:
540
541
  - 确认队友在 `.minds/team.yaml` 中被授予了相关的 `<serverId>` 工具集
541
542
  - **MCP 服务器持续 (re)load 失败**:
542
543
  - 检查问题详细信息(缺少 env 变量、无效的工具名称、冲突、连接错误)
543
- - 修复配置后,使用 `mcp_admin` 中的 `mcp_restart` 进行每个服务器的最佳努力重启
544
+ - 修复配置后,使用 `mcp_admin` 中的 `mcp_restart` 启用/重启 server。若需禁用,使用
545
+ `mcp_disable`,它会保留 0 工具 toolset 和已配置手册可见性
@@ -79,7 +79,8 @@ Non-goals:
79
79
  Update triggers:
80
80
 
81
81
  - `.minds/mcp.yaml` reload
82
- - `mcp_restart`
82
+ - `mcp_restart` (also writes `enabled: true` when a configured MCP server is disabled)
83
+ - `mcp_disable` (writes `enabled: false`; the server remains visible as a zero-tool toolset/manual)
83
84
  - MCP collision-resolution re-registration
84
85
 
85
86
  ### 2. Runtime Lease Protocol
@@ -105,7 +106,8 @@ Update triggers:
105
106
 
106
107
  - first MCP tool call acquires a lease
107
108
  - `mcp_release`
108
- - restart/stop tears leases down
109
+ - successful `mcp_restart` tears old-runtime leases down
110
+ - `mcp_disable` tears loaded runtime leases down
109
111
 
110
112
  ### 3. Member Tool-Binding Protocol
111
113
 
@@ -80,3 +80,5 @@ export declare class LlmConfig {
80
80
  export declare namespace LlmConfig {
81
81
  function load(): Promise<LlmConfig>;
82
82
  }
83
+ export declare function getBuiltinDefaultsYamlPath(): string;
84
+ export declare function readBuiltinDefaultsYamlRaw(): Promise<string>;
@@ -4,10 +4,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.LlmConfig = void 0;
7
+ exports.getBuiltinDefaultsYamlPath = getBuiltinDefaultsYamlPath;
8
+ exports.readBuiltinDefaultsYamlRaw = readBuiltinDefaultsYamlRaw;
7
9
  const promises_1 = __importDefault(require("fs/promises"));
8
10
  const path_1 = __importDefault(require("path"));
9
11
  const yaml_1 = __importDefault(require("yaml"));
10
12
  const log_1 = require("../log");
13
+ const BUILTIN_DEFAULTS_YAML_PATH = path_1.default.join(__dirname, 'defaults.yaml');
14
+ // Special-case cache: built-in defaults are immutable at runtime, so this file may be cached
15
+ // forever to survive dogfooding rebuild windows. Do not generalize this to rtws/user-editable files.
16
+ let builtinDefaultsYamlRawCache;
17
+ let builtinDefaultsYamlRawReadPromise;
11
18
  /**
12
19
  * LlmConfig
13
20
  *
@@ -28,8 +35,7 @@ exports.LlmConfig = LlmConfig;
28
35
  (function (LlmConfig) {
29
36
  async function load() {
30
37
  // Load default providers from YAML file
31
- const defaultsPath = path_1.default.join(__dirname, 'defaults.yaml');
32
- const rawDefaults = await promises_1.default.readFile(defaultsPath, 'utf-8');
38
+ const rawDefaults = await readBuiltinDefaultsYamlRaw();
33
39
  const parsedDefaults = yaml_1.default.parse(rawDefaults);
34
40
  if (!isRecord(parsedDefaults) || !isRecord(parsedDefaults.providers)) {
35
41
  throw new Error('Invalid defaults.yaml: expected providers object');
@@ -64,6 +70,30 @@ exports.LlmConfig = LlmConfig;
64
70
  }
65
71
  LlmConfig.load = load;
66
72
  })(LlmConfig || (exports.LlmConfig = LlmConfig = {}));
73
+ function getBuiltinDefaultsYamlPath() {
74
+ return BUILTIN_DEFAULTS_YAML_PATH;
75
+ }
76
+ async function readBuiltinDefaultsYamlRaw() {
77
+ if (builtinDefaultsYamlRawCache !== undefined)
78
+ return builtinDefaultsYamlRawCache;
79
+ if (builtinDefaultsYamlRawReadPromise === undefined) {
80
+ builtinDefaultsYamlRawReadPromise = promises_1.default
81
+ .readFile(BUILTIN_DEFAULTS_YAML_PATH, 'utf-8')
82
+ .then((raw) => {
83
+ const parsed = yaml_1.default.parse(raw);
84
+ if (!isRecord(parsed) || !isRecord(parsed.providers)) {
85
+ throw new Error('Invalid defaults.yaml: expected providers object');
86
+ }
87
+ builtinDefaultsYamlRawCache = raw;
88
+ return raw;
89
+ })
90
+ .catch((error) => {
91
+ builtinDefaultsYamlRawReadPromise = undefined;
92
+ throw error;
93
+ });
94
+ }
95
+ return builtinDefaultsYamlRawReadPromise;
96
+ }
67
97
  function isRecord(value) {
68
98
  return typeof value === 'object' && value !== null;
69
99
  }
@@ -100,6 +100,15 @@ providers:
100
100
  min: 1
101
101
  description: Provider-specific max tokens override.
102
102
  models:
103
+ gpt-5.5:
104
+ name: GPT-5.5
105
+ optimal_max_tokens: 350000
106
+ # Caution remediation reinjection cadence in generation turns (default: 10).
107
+ caution_remediation_cadence_generations: 10
108
+ context_length: 400000
109
+ input_length: 272000
110
+ output_length: 128000
111
+ context_window: '400K'
103
112
  gpt-5.4:
104
113
  name: GPT-5.4
105
114
  optimal_max_tokens: 200000
@@ -653,20 +662,34 @@ providers:
653
662
  type: boolean
654
663
  description: Supported via thinking field (budget_tokens is ignored by DeepSeek).
655
664
  models:
665
+ deepseek-v4-flash:
666
+ name: DeepSeek-V4-Flash
667
+ supports_image_input: false
668
+ context_length: 1000000
669
+ input_length: 1000000
670
+ output_length: 384000
671
+ context_window: '1M'
672
+ deepseek-v4-pro:
673
+ name: DeepSeek-V4-Pro
674
+ supports_image_input: false
675
+ context_length: 1000000
676
+ input_length: 1000000
677
+ output_length: 384000
678
+ context_window: '1M'
656
679
  deepseek-chat:
657
- name: DeepSeek-V3.2
680
+ name: DeepSeek-V4-Flash (non-thinking alias)
658
681
  supports_image_input: false
659
- context_length: 128000
660
- input_length: 128000
661
- output_length: 8192
662
- context_window: '128K'
682
+ context_length: 1000000
683
+ input_length: 1000000
684
+ output_length: 384000
685
+ context_window: '1M'
663
686
  deepseek-reasoner:
664
- name: DeepSeek-R1 (reasoner, V3.2 thinking mode)
687
+ name: DeepSeek-V4-Flash (thinking alias)
665
688
  supports_image_input: false
666
- context_length: 128000
667
- input_length: 128000
668
- output_length: 65536
669
- context_window: '128K'
689
+ context_length: 1000000
690
+ input_length: 1000000
691
+ output_length: 384000
692
+ context_window: '1M'
670
693
  aliyun-bailian:
671
694
  name: Aliyun Bailian Coding Plan
672
695
  apiType: anthropic
@@ -846,6 +869,24 @@ providers:
846
869
  min: 1
847
870
  description: Provider-specific max tokens override.
848
871
  models:
872
+ gpt-5.5:
873
+ name: GPT-5.5
874
+ optimal_max_tokens: 350000
875
+ # Caution remediation reinjection cadence in generation turns (default: 10).
876
+ caution_remediation_cadence_generations: 10
877
+ context_length: 1000000
878
+ input_length: 1000000
879
+ output_length: 128000
880
+ context_window: '1M'
881
+ gpt-5.5-pro:
882
+ name: GPT-5.5 Pro
883
+ optimal_max_tokens: 600000
884
+ # Caution remediation reinjection cadence in generation turns (default: 10).
885
+ caution_remediation_cadence_generations: 10
886
+ context_length: 1000000
887
+ input_length: 1000000
888
+ output_length: 128000
889
+ context_window: '1M'
849
890
  gpt-5.4:
850
891
  name: GPT-5.4
851
892
  optimal_max_tokens: 200000
@@ -654,6 +654,21 @@ class CodexGen {
654
654
  // NOTE: `@longrun-ai/codex-auth` is an ESM package (`"type": "module"`). The Dominds backend is
655
655
  // compiled as CommonJS, so Node.js requires a dynamic `import()` for runtime access here.
656
656
  const codexAuth = await Promise.resolve().then(() => __importStar(require('@longrun-ai/codex-auth')));
657
+ const authPreparation = codexAuth.prepareCodexFileAuth({
658
+ codexHome,
659
+ codexHomeEnvVar: providerConfig.apiKeyEnvVar,
660
+ providerName: `Dominds codex provider '${providerConfig.name}'`,
661
+ });
662
+ if (authPreparation.kind === 'action_required') {
663
+ throw new Error(codexAuth.formatCodexFileAuthActionRequired(authPreparation));
664
+ }
665
+ if (authPreparation.changedConfigToFile) {
666
+ log.info('Codex CLI auth storage switched to file mode for Dominds codex provider', undefined, {
667
+ codexHome: authPreparation.codexHome,
668
+ configPath: authPreparation.configPath,
669
+ previousStoreMode: authPreparation.previousStoreMode,
670
+ });
671
+ }
657
672
  const manager = new codexAuth.AuthManager({ codexHome });
658
673
  const client = await codexAuth.createChatGptClientFromManager(manager, {
659
674
  baseUrl: providerConfig.baseUrl,
@@ -1189,14 +1189,17 @@ async function maybeContinueWithHealthPromptBeforeDiligence(args) {
1189
1189
  return { kind: 'health_continue', prompt: nextPrompt, resetTaskdoc: true };
1190
1190
  }
1191
1191
  const language = (0, work_language_1.getWorkLanguage)();
1192
+ const dialogScope = dlg instanceof dialog_1.SideDialog ? 'sideDialog' : 'mainDialog';
1192
1193
  const guideText = healthDecision.reason === 'caution_soft_remediation'
1193
1194
  ? (0, driver_messages_1.formatAgentFacingContextHealthV3RemediationGuide)(language, {
1194
1195
  kind: 'caution',
1195
1196
  mode: 'soft',
1197
+ dialogScope,
1196
1198
  })
1197
1199
  : (0, driver_messages_1.formatAgentFacingContextHealthV3RemediationGuide)(language, {
1198
1200
  kind: 'critical',
1199
1201
  mode: 'countdown',
1202
+ dialogScope,
1200
1203
  promptsRemainingAfterThis: (0, context_health_1.consumeCriticalCountdown)(dlg.id.key()),
1201
1204
  promptsTotal: context_health_1.KERNEL_DRIVER_DEFAULT_CRITICAL_COUNTDOWN_GENERATIONS,
1202
1205
  });
@@ -1381,14 +1384,17 @@ async function driveDialogStreamCore(dlg, callbacks, humanPrompt, driveOptions)
1381
1384
  }
1382
1385
  else if (!hasQueuedUpNext) {
1383
1386
  const language = (0, work_language_1.getWorkLanguage)();
1387
+ const dialogScope = dlg instanceof dialog_1.SideDialog ? 'sideDialog' : 'mainDialog';
1384
1388
  const guideText = healthDecision.reason === 'caution_soft_remediation'
1385
1389
  ? (0, driver_messages_1.formatAgentFacingContextHealthV3RemediationGuide)(language, {
1386
1390
  kind: 'caution',
1387
1391
  mode: 'soft',
1392
+ dialogScope,
1388
1393
  })
1389
1394
  : (0, driver_messages_1.formatAgentFacingContextHealthV3RemediationGuide)(language, {
1390
1395
  kind: 'critical',
1391
1396
  mode: 'countdown',
1397
+ dialogScope,
1392
1398
  promptsRemainingAfterThis: (0, context_health_1.consumeCriticalCountdown)(dlg.id.key()),
1393
1399
  promptsTotal: context_health_1.KERNEL_DRIVER_DEFAULT_CRITICAL_COUNTDOWN_GENERATIONS,
1394
1400
  });
@@ -19,6 +19,7 @@ const client_1 = require("../client");
19
19
  const context_health_1 = require("./context-health");
20
20
  const drive_1 = require("./drive");
21
21
  const guardrails_1 = require("./guardrails");
22
+ const idle_reminder_wake_1 = require("./idle-reminder-wake");
22
23
  const reply_guidance_1 = require("./reply-guidance");
23
24
  const sideDialog_1 = require("./sideDialog");
24
25
  const tellask_special_1 = require("./tellask-special");
@@ -459,6 +460,7 @@ async function resolveEffectivePrompt(dialog, humanPrompt) {
459
460
  }
460
461
  async function executeDriveRound(args) {
461
462
  const [dialog, humanPrompt, waitInQue, driveOptions] = args.driveArgs;
463
+ (0, idle_reminder_wake_1.cancelIdleReminderWake)(dialog.id, driveOptions?.reason ?? 'drive_start');
462
464
  if (!waitInQue && dialog.isLocked()) {
463
465
  throw new Error('Dialog busy driven, see how it proceeded and try again.');
464
466
  }
@@ -681,14 +683,17 @@ async function executeDriveRound(args) {
681
683
  }
682
684
  else if (!hasQueuedUpNext) {
683
685
  const language = (0, work_language_1.getWorkLanguage)();
686
+ const dialogScope = dialog instanceof dialog_1.SideDialog ? 'sideDialog' : 'mainDialog';
684
687
  const guideText = healthDecision.reason === 'caution_soft_remediation'
685
688
  ? (0, driver_messages_1.formatAgentFacingContextHealthV3RemediationGuide)(language, {
686
689
  kind: 'caution',
687
690
  mode: 'soft',
691
+ dialogScope,
688
692
  })
689
693
  : (0, driver_messages_1.formatAgentFacingContextHealthV3RemediationGuide)(language, {
690
694
  kind: 'critical',
691
695
  mode: 'countdown',
696
+ dialogScope,
692
697
  promptsRemainingAfterThis: (0, context_health_1.consumeCriticalCountdown)(dialog.id.key()),
693
698
  promptsTotal: context_health_1.KERNEL_DRIVER_DEFAULT_CRITICAL_COUNTDOWN_GENERATIONS,
694
699
  });
@@ -1077,5 +1082,9 @@ async function executeDriveRound(args) {
1077
1082
  (0, dialog_display_state_1.clearActiveRun)(dialog.id);
1078
1083
  }
1079
1084
  release();
1085
+ (0, idle_reminder_wake_1.maybeStartIdleReminderWake)(dialog, {
1086
+ scheduleDrive: args.scheduleDrive,
1087
+ driveDialog: args.driveDialog,
1088
+ }, driveOptions?.reason ?? 'drive_finished');
1080
1089
  }
1081
1090
  }
@@ -0,0 +1,4 @@
1
+ import { Dialog, DialogID } from '../../dialog';
2
+ import type { KernelDriverDriveCallbacks } from './types';
3
+ export declare function cancelIdleReminderWake(dialogId: DialogID, reason: string): void;
4
+ export declare function maybeStartIdleReminderWake(dialog: Dialog, callbacks: KernelDriverDriveCallbacks, reason: string): void;