dominds 1.27.2 → 1.27.3

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 (36) hide show
  1. package/dist/apps/runtime.js +3 -1
  2. package/dist/dialog-global-registry.d.ts +11 -1
  3. package/dist/dialog-global-registry.js +45 -0
  4. package/dist/dialog.d.ts +11 -2
  5. package/dist/dialog.js +107 -17
  6. package/dist/docs/daemon-cmd-runner.md +5 -0
  7. package/dist/docs/daemon-cmd-runner.zh.md +5 -0
  8. package/dist/llm/kernel-driver/drive.js +163 -11
  9. package/dist/llm/kernel-driver/fbr.d.ts +9 -0
  10. package/dist/llm/kernel-driver/fbr.js +186 -59
  11. package/dist/minds/load.js +1 -0
  12. package/dist/persistence.js +18 -1
  13. package/dist/runtime/driver-messages.d.ts +9 -0
  14. package/dist/runtime/driver-messages.js +61 -5
  15. package/dist/runtime/shared-reminder-update-impact.d.ts +20 -0
  16. package/dist/runtime/shared-reminder-update-impact.js +110 -0
  17. package/dist/tool-availability.js +1 -0
  18. package/dist/tools/builtins.js +2 -0
  19. package/dist/tools/cmd-runner-protocol.d.ts +6 -0
  20. package/dist/tools/cmd-runner-protocol.js +57 -2
  21. package/dist/tools/cmd-runner.js +83 -2
  22. package/dist/tools/ctrl.d.ts +2 -0
  23. package/dist/tools/ctrl.js +179 -5
  24. package/dist/tools/os.js +115 -14
  25. package/dist/tools/process-kill.js +49 -0
  26. package/dist/tools/prompts/control/en/errors.md +1 -1
  27. package/dist/tools/prompts/control/en/index.md +1 -1
  28. package/dist/tools/prompts/control/en/principles.md +18 -17
  29. package/dist/tools/prompts/control/en/tools.md +24 -1
  30. package/dist/tools/prompts/control/zh/errors.md +1 -1
  31. package/dist/tools/prompts/control/zh/index.md +1 -1
  32. package/dist/tools/prompts/control/zh/principles.md +17 -16
  33. package/dist/tools/prompts/control/zh/tools.md +24 -1
  34. package/dist/tools/prompts/os/en/tools.md +2 -0
  35. package/dist/tools/prompts/os/zh/tools.md +2 -0
  36. package/package.json +4 -4
package/dist/tools/os.js CHANGED
@@ -24,6 +24,7 @@ const fs_1 = __importDefault(require("fs"));
24
24
  const module_1 = require("module");
25
25
  const net_1 = __importDefault(require("net"));
26
26
  const path_1 = __importDefault(require("path"));
27
+ const url_1 = require("url");
27
28
  const util_1 = require("util");
28
29
  const rtws_1 = require("../rtws");
29
30
  const driver_messages_1 = require("../runtime/driver-messages");
@@ -572,6 +573,8 @@ function getOsToolMessages(language) {
572
573
  daemonOutputHeader: (pid, streamLabel) => `📤 守护进程 ${pid} ${streamLabel} 输出:\n`,
573
574
  noOutput: '(无输出)',
574
575
  scrolledOutNotice: (lines) => `\n\n⚠️ 有 ${lines} 行已滚出可视范围`,
576
+ daemonOutputWaitTimedOut: (pid, streamLabel, timeoutMs) => `⏱️ 等待守护进程 ${pid} 的 ${streamLabel} 新输出已超时(timeout_ms=${timeoutMs})。以下是当前快照。\n\n`,
577
+ daemonOutputWaitExited: (pid, streamLabel) => `⏹️ 等待守护进程 ${pid} 的 ${streamLabel} 新输出期间进程已退出;未观察到新的所选流输出。以下是最终快照。\n\n`,
575
578
  };
576
579
  }
577
580
  return {
@@ -587,6 +590,8 @@ function getOsToolMessages(language) {
587
590
  daemonOutputHeader: (pid, streamLabel) => `📤 Daemon ${pid} ${streamLabel} output:\n`,
588
591
  noOutput: '(no output)',
589
592
  scrolledOutNotice: (lines) => `\n\n⚠️ ${lines} lines have scrolled out of view`,
593
+ daemonOutputWaitTimedOut: (pid, streamLabel, timeoutMs) => `⏱️ Timed out waiting for new ${streamLabel} output from daemon ${pid} (timeout_ms=${timeoutMs}). Current snapshot follows.\n\n`,
594
+ daemonOutputWaitExited: (pid, streamLabel) => `⏹️ Daemon ${pid} exited while waiting for new ${streamLabel} output; no new requested-stream output was observed. Final snapshot follows.\n\n`,
590
595
  };
591
596
  }
592
597
  function disconnectRunnerProcess(runnerProcess) {
@@ -818,12 +823,38 @@ function parseGetDaemonOutputArgs(args) {
818
823
  if (stderrRaw !== undefined && typeof stderrRaw !== 'boolean') {
819
824
  throw new Error('get_daemon_output.stderr must be a boolean if provided');
820
825
  }
826
+ const waitForNewOutputRaw = args.wait_for_new_output;
827
+ if (waitForNewOutputRaw !== undefined && typeof waitForNewOutputRaw !== 'boolean') {
828
+ throw new Error('get_daemon_output.wait_for_new_output must be a boolean if provided');
829
+ }
830
+ const timeoutMsRaw = args.timeout_ms;
831
+ if (timeoutMsRaw !== undefined && typeof timeoutMsRaw !== 'number') {
832
+ throw new Error('get_daemon_output.timeout_ms must be a number if provided');
833
+ }
834
+ const timeoutMs = timeoutMsRaw === undefined
835
+ ? undefined
836
+ : Number.isInteger(timeoutMsRaw) &&
837
+ timeoutMsRaw >= 0 &&
838
+ timeoutMsRaw <= cmd_runner_protocol_1.MAX_CMD_RUNNER_OUTPUT_WAIT_TIMEOUT_MS
839
+ ? timeoutMsRaw
840
+ : (() => {
841
+ throw new Error(`get_daemon_output.timeout_ms must be a non-negative integer <= ${String(cmd_runner_protocol_1.MAX_CMD_RUNNER_OUTPUT_WAIT_TIMEOUT_MS)}`);
842
+ })();
821
843
  const stdout = stdoutRaw ?? true;
822
844
  const stderr = stderrRaw ?? true;
823
845
  if (!stdout && !stderr) {
824
846
  throw new Error('get_daemon_output requires at least one of stdout/stderr to be true');
825
847
  }
826
- return { pid, stdout, stderr };
848
+ if (waitForNewOutputRaw === false && timeoutMs !== undefined) {
849
+ throw new Error('get_daemon_output.timeout_ms cannot be provided when wait_for_new_output is false');
850
+ }
851
+ return {
852
+ pid,
853
+ stdout,
854
+ stderr,
855
+ waitForNewOutput: waitForNewOutputRaw ?? timeoutMs !== undefined,
856
+ ...(timeoutMs === undefined ? {} : { timeoutMs }),
857
+ };
827
858
  }
828
859
  function getWindowsShellLabel(shell) {
829
860
  if (typeof shell !== 'string') {
@@ -945,8 +976,8 @@ function resolveCmdRunnerEntrypointAbs() {
945
976
  }
946
977
  const tsCandidate = path_1.default.resolve(__dirname, 'cmd-runner.ts');
947
978
  if (fs_1.default.existsSync(tsCandidate)) {
948
- const tsxLoaderAbs = requireFn.resolve('tsx');
949
- return { ok: true, scriptAbs: tsCandidate, execArgv: ['--import', tsxLoaderAbs] };
979
+ const tsxLoaderUrl = (0, url_1.pathToFileURL)(requireFn.resolve('tsx')).href;
980
+ return { ok: true, scriptAbs: tsCandidate, execArgv: ['--import', tsxLoaderUrl] };
950
981
  }
951
982
  return {
952
983
  ok: false,
@@ -991,21 +1022,30 @@ async function callRunner(endpoint, request, timeoutMs = 5_000) {
991
1022
  if (settled)
992
1023
  return;
993
1024
  settled = true;
994
- clearTimeout(timeoutHandle);
1025
+ if (timeoutHandle !== undefined) {
1026
+ clearTimeout(timeoutHandle);
1027
+ }
995
1028
  socket.destroy();
996
1029
  fn();
997
1030
  };
998
- const timeoutHandle = setTimeout(() => {
999
- finalize(() => {
1000
- reject(new Error(`cmd_runner request timed out for endpoint ${endpoint}`));
1001
- });
1002
- }, timeoutMs);
1031
+ const timeoutHandle = timeoutMs === null
1032
+ ? undefined
1033
+ : setTimeout(() => {
1034
+ finalize(() => {
1035
+ reject(new Error(`cmd_runner request timed out for endpoint ${endpoint}`));
1036
+ });
1037
+ }, timeoutMs);
1003
1038
  socket.setEncoding('utf8');
1004
1039
  socket.once('error', (error) => {
1005
1040
  finalize(() => {
1006
1041
  reject(error);
1007
1042
  });
1008
1043
  });
1044
+ socket.once('close', () => {
1045
+ finalize(() => {
1046
+ reject(new Error(`cmd_runner connection closed before response for endpoint ${endpoint}`));
1047
+ });
1048
+ });
1009
1049
  socket.on('data', (chunk) => {
1010
1050
  buffer += chunk;
1011
1051
  const newlineIndex = buffer.indexOf('\n');
@@ -1101,6 +1141,45 @@ async function resolveDaemonFromMeta(meta) {
1101
1141
  };
1102
1142
  }
1103
1143
  }
1144
+ function getRunnerRequestTimeoutForDaemonOutput(args) {
1145
+ if (!args.waitForNewOutput) {
1146
+ return undefined;
1147
+ }
1148
+ if (args.timeoutMs !== undefined) {
1149
+ return Math.max(5_000, args.timeoutMs + 5_000);
1150
+ }
1151
+ return null;
1152
+ }
1153
+ async function resolveDaemonOutputFromMeta(meta, args) {
1154
+ if (meta.runnerEndpoint !== undefined && meta.runnerEndpoint.trim() !== '') {
1155
+ try {
1156
+ const response = await callRunner(meta.runnerEndpoint, {
1157
+ type: 'get_output',
1158
+ stdout: args.stdout,
1159
+ stderr: args.stderr,
1160
+ waitForNewOutput: args.waitForNewOutput,
1161
+ ...(args.timeoutMs === undefined ? {} : { timeoutMs: args.timeoutMs }),
1162
+ }, getRunnerRequestTimeoutForDaemonOutput(args));
1163
+ if (response.ok &&
1164
+ response.type === 'output' &&
1165
+ runnerResponseMatchesReminder(meta, response)) {
1166
+ return {
1167
+ kind: 'live',
1168
+ daemon: buildRunnerBackedDaemon(meta, response),
1169
+ ...(response.waitStatus === undefined ? {} : { waitStatus: response.waitStatus }),
1170
+ };
1171
+ }
1172
+ }
1173
+ catch {
1174
+ // Fall through to stale-or-gone detection.
1175
+ }
1176
+ }
1177
+ const resolved = await resolveDaemonFromMeta(meta);
1178
+ if (resolved.kind !== 'live') {
1179
+ return resolved;
1180
+ }
1181
+ return { kind: 'live', daemon: resolved.daemon };
1182
+ }
1104
1183
  function formatRunnerBackedDaemonStatusDetails(daemon, language) {
1105
1184
  const uptime = Math.floor((Date.now() - daemon.startTime.getTime()) / 1000);
1106
1185
  const status = language === 'zh'
@@ -1248,6 +1327,14 @@ const getDaemonOutputSchema = {
1248
1327
  type: 'boolean',
1249
1328
  description: 'Whether to include stderr output (default: true unless stdout is explicitly set)',
1250
1329
  },
1330
+ wait_for_new_output: {
1331
+ type: 'boolean',
1332
+ description: 'Whether to wait until at least one requested stream receives new output before returning (default: false, or true when timeout_ms is provided)',
1333
+ },
1334
+ timeout_ms: {
1335
+ type: 'integer',
1336
+ description: 'Optional non-negative maximum time in milliseconds to wait for new output, up to 86400000 (24h); providing this implies wait_for_new_output=true unless wait_for_new_output is explicitly false, which is rejected',
1337
+ },
1251
1338
  },
1252
1339
  required: ['pid'],
1253
1340
  additionalProperties: false,
@@ -2788,26 +2875,33 @@ exports.stopDaemonTool = {
2788
2875
  }
2789
2876
  },
2790
2877
  };
2878
+ function formatRequestedDaemonOutputStreams(stdout, stderr) {
2879
+ if (stdout && stderr) {
2880
+ return 'stdout/stderr';
2881
+ }
2882
+ return stdout ? 'stdout' : 'stderr';
2883
+ }
2791
2884
  // Get daemon output tool implementation
2792
2885
  exports.getDaemonOutputTool = {
2793
2886
  type: 'func',
2794
2887
  name: 'get_daemon_output',
2795
- description: 'Retrieve captured stdout/stderr output from a tracked daemon process by PID. By default both streams are returned together; you may disable either stream explicitly. Returns (no output) if a requested stream has not produced output yet.',
2888
+ description: 'Retrieve captured stdout/stderr output from a tracked daemon process by PID. By default both streams are returned together; you may disable either stream explicitly. Set wait_for_new_output=true to wait until a requested stream receives new output before returning; timeout_ms optionally bounds that wait. Returns (no output) if a requested stream has not produced output yet.',
2796
2889
  descriptionI18n: {
2797
- en: 'Retrieve captured stdout/stderr output from a tracked daemon process by PID. By default both streams are returned together; you may disable either stream explicitly. Returns (no output) if a requested stream has not produced output yet.',
2798
- zh: '根据 PID 获取已追踪守护进程的 stdout/stderr 输出。默认会同时返回两个流,也可显式关闭其中一个;若所请求的流尚无输出,则返回 (no output)。',
2890
+ en: 'Retrieve captured stdout/stderr output from a tracked daemon process by PID. By default both streams are returned together; you may disable either stream explicitly. Set wait_for_new_output=true to wait until a requested stream receives new output before returning; timeout_ms optionally bounds that wait. Returns (no output) if a requested stream has not produced output yet.',
2891
+ zh: '根据 PID 获取已追踪守护进程的 stdout/stderr 输出。默认会同时返回两个流,也可显式关闭其中一个;设置 wait_for_new_output=true 时会等到所请求流出现新输出后再返回,timeout_ms 可选用于限制等待毫秒数;若所请求的流尚无输出,则返回 (no output)。',
2799
2892
  },
2800
2893
  parameters: getDaemonOutputSchema,
2801
2894
  async call(dlg, caller, args) {
2802
2895
  const language = (0, work_language_1.getWorkLanguage)();
2803
2896
  const t = getOsToolMessages(language);
2804
- const { pid, stdout, stderr } = parseGetDaemonOutputArgs(args);
2897
+ const parsedArgs = parseGetDaemonOutputArgs(args);
2898
+ const { pid, stdout, stderr } = parsedArgs;
2805
2899
  const reminders = await (0, shared_reminders_1.loadSharedReminders)({ kind: 'agent', agentId: dlg.agentId });
2806
2900
  const reminder = reminders.find((candidate) => isShellCmdReminder(candidate) && candidate.meta.pid === pid);
2807
2901
  if (!reminder || !isShellCmdReminder(reminder)) {
2808
2902
  return (0, tool_1.toolFailure)(t.noDaemonFound(pid));
2809
2903
  }
2810
- const resolved = await resolveDaemonFromMeta(reminder.meta);
2904
+ const resolved = await resolveDaemonOutputFromMeta(reminder.meta, parsedArgs);
2811
2905
  if (resolved.kind === 'gone') {
2812
2906
  await removeDaemonRemindersForPid(dlg, pid);
2813
2907
  return (0, tool_1.toolFailure)(t.noDaemonFound(pid));
@@ -2819,6 +2913,13 @@ exports.getDaemonOutputTool = {
2819
2913
  let result = '';
2820
2914
  const fenceConsole = '```console';
2821
2915
  const fenceEnd = '```';
2916
+ const requestedStreams = formatRequestedDaemonOutputStreams(stdout, stderr);
2917
+ if (resolved.waitStatus === 'timeout') {
2918
+ result += t.daemonOutputWaitTimedOut(pid, requestedStreams, parsedArgs.timeoutMs ?? 0);
2919
+ }
2920
+ else if (resolved.waitStatus === 'exited') {
2921
+ result += t.daemonOutputWaitExited(pid, requestedStreams);
2922
+ }
2822
2923
  if (stdout) {
2823
2924
  const stdoutContent = (0, output_limit_1.truncateToolOutputText)(daemon.stdoutContent, {
2824
2925
  toolName: 'get_daemon_output_stdout',
@@ -30,10 +30,59 @@ async function bestEffortTaskkill(pid, force) {
30
30
  // Best effort only.
31
31
  }
32
32
  }
33
+ async function bestEffortListWindowsDescendantPids(pid) {
34
+ assertValidPid(pid);
35
+ try {
36
+ const command = `
37
+ $processes = Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId
38
+ $frontier = @(${String(pid)})
39
+ $result = @()
40
+ while ($frontier.Count -gt 0) {
41
+ $next = @()
42
+ foreach ($parentPid in $frontier) {
43
+ foreach ($child in $processes | Where-Object { $_.ParentProcessId -eq $parentPid }) {
44
+ $childPid = [int]$child.ProcessId
45
+ $result += $childPid
46
+ $next += $childPid
47
+ }
48
+ }
49
+ $frontier = $next
50
+ }
51
+ $result | ForEach-Object { [Console]::Out.WriteLine($_) }
52
+ `;
53
+ const { stdout } = await execFileAsync('powershell.exe', ['-NoProfile', '-Command', command], {
54
+ windowsHide: true,
55
+ maxBuffer: 1024 * 1024,
56
+ });
57
+ const parsed = [];
58
+ for (const line of stdout.split(/\r?\n/)) {
59
+ const trimmed = line.trim();
60
+ if (trimmed === '') {
61
+ continue;
62
+ }
63
+ const parsedPid = Number(trimmed);
64
+ if (Number.isInteger(parsedPid) && parsedPid > 0) {
65
+ parsed.push(parsedPid);
66
+ }
67
+ }
68
+ return parsed;
69
+ }
70
+ catch {
71
+ return [];
72
+ }
73
+ }
33
74
  async function bestEffortKillWindowsProcessTree(pid) {
34
75
  assertValidPid(pid);
76
+ const descendantPids = await bestEffortListWindowsDescendantPids(pid);
77
+ for (const descendantPid of descendantPids.slice().reverse()) {
78
+ await bestEffortTaskkill(descendantPid, false);
79
+ }
35
80
  await bestEffortTaskkill(pid, false);
36
81
  await sleepMs(1_000);
82
+ for (const descendantPid of descendantPids.slice().reverse()) {
83
+ await bestEffortTaskkill(descendantPid, true);
84
+ bestEffortKillPid(descendantPid);
85
+ }
37
86
  await bestEffortTaskkill(pid, true);
38
87
  bestEffortKillPid(pid);
39
88
  }
@@ -73,7 +73,7 @@
73
73
 
74
74
  ### Q: What's the difference between dialog, task, agent reminders, and memory?
75
75
 
76
- A: `dialog` reminders are only for the current dialog's current work. `task` reminders are for current work under the same Taskdoc and are the default for `add_reminder`. `agent` reminders stay visible in all later dialogs you lead, but only for urgent, short-lived, globally visible cues. None of them are long-term knowledge. `personal_memory` is for durable facts and reusable knowledge saved to disk; if the information should synchronize the team's current effective state, key decisions, next step, or still-active blockers, write it to Taskdoc `progress` instead of a reminder.
76
+ A: `dialog` reminders are only for the current dialog's current work. `task` reminders are for current work under the same Taskdoc and are the default for `add_reminder`. `agent` reminders stay visible in later dialogs you lead, but only for urgent, short-lived, globally visible cues. None of them are long-term knowledge. `personal_memory` is for durable facts and reusable knowledge saved to disk; if the information should synchronize the team's current effective state, key decisions, next step, or still-active blockers, write it to Taskdoc `progress` instead of a reminder.
77
77
 
78
78
  ### Q: How do I choose `dialog`, `task`, and `agent`?
79
79
 
@@ -64,7 +64,7 @@ Scope rule:
64
64
 
65
65
  - `dialog`: current-dialog current work
66
66
  - `task`: current work under the current Taskdoc, and the default scope
67
- - `agent`: urgent, short-lived, globally visible cues you should keep seeing in all later dialogs you lead
67
+ - `agent`: urgent, short-lived, globally visible cues you should keep seeing across later dialogs you lead
68
68
 
69
69
  ### Taskdoc
70
70
 
@@ -30,8 +30,8 @@
30
30
  Reminders are temporary current-work notes with three scopes:
31
31
 
32
32
  - `dialog`: current-dialog only
33
- - `task`: visible in every dialog you lead for the current Taskdoc
34
- - `agent`: visible in all dialogs you lead, but only for urgent, short-lived, globally visible cues
33
+ - `task`: visible across dialogs for the current Taskdoc
34
+ - `agent`: visible in later dialogs you lead, but only for urgent, short-lived, globally visible cues
35
35
 
36
36
  Default to `task`. Use `dialog` only when the note is truly dialog-local; use `agent` only when the note is urgent, short-lived, and globally visible.
37
37
 
@@ -39,7 +39,7 @@ Default to `task`. Use `dialog` only when the note is truly dialog-local; use `a
39
39
 
40
40
  - `dialog` reminders stay in the current dialog only
41
41
  - `task` reminders stay visible under the current Taskdoc
42
- - `agent` reminders stay visible in all later dialogs you lead
42
+ - `agent` reminders stay visible in later dialogs you lead
43
43
  - Can be added, modified, or deleted at any time
44
44
  - Should stay compact, scannable, and directly actionable by default
45
45
  - Before `clear_mind`, the Main Dialog first records undocumented discussion details the next course needs to know into Taskdoc, then creates a structured continuation-package reminder; a Side Dialog directly maintains sufficiently detailed continuation-package reminders. If Dominds has already warned that context is tight or critical, Side Dialog reminders have no fixed length limit and rough multi-reminder carry-over is acceptable
@@ -47,7 +47,7 @@ Default to `task`. Use `dialog` only when the note is truly dialog-local; use `a
47
47
  **Difference from memory:**
48
48
  | Feature | dialog reminder | task reminder | agent reminder | personal memory |
49
49
  |---------|-----------------|---------------|----------------|-----------------|
50
- | Persistence | Current dialog only | Current Taskdoc | Across all later dialogs you lead | Long-term / file-backed |
50
+ | Persistence | Current dialog only | Current Taskdoc | Across later dialogs you lead | Long-term / file-backed |
51
51
  | Visibility | Current dialog | Current-task dialogs | Current Dialog Responder | Current agent |
52
52
  | Best for | Current next step, blocker, volatile clue | Current work under one task | Urgent, short-lived, global cue | Stable facts / reusable knowledge |
53
53
 
@@ -61,7 +61,7 @@ Default to `task`. Use `dialog` only when the note is truly dialog-local; use `a
61
61
  - current blockers
62
62
  - temporary paths, ids, commands, sample inputs
63
63
  - bridge notes that matter only for this dialog / current course
64
- - Use `agent` only for urgent, short-lived, globally visible cues that should appear in every dialog you lead.
64
+ - Use `agent` only for urgent, short-lived, globally visible cues that should appear across dialogs you lead.
65
65
  - If the content is a durable fact or knowledge asset rather than an active current-work cue, it likely belongs in `personal_memory`, not in any reminder scope.
66
66
 
67
67
  ### 2. Taskdoc
@@ -85,16 +85,17 @@ Taskdoc is a **task contract** and the task's **team-shared source of current tr
85
85
 
86
86
  ## Tool Overview
87
87
 
88
- | Tool | Function |
89
- | --------------- | ------------------------------------------------ |
90
- | add_reminder | Add reminder |
91
- | delete_reminder | Delete reminder |
92
- | update_reminder | Update reminder content |
93
- | do_mind | Create new Taskdoc section |
94
- | mind_more | Append entries to Taskdoc (defaults to progress) |
95
- | change_mind | Replace existing Taskdoc section |
96
- | never_mind | Delete Taskdoc section file |
97
- | recall_taskdoc | Read taskdoc chapter |
88
+ | Tool | Function |
89
+ | ---------------- | ------------------------------------------------ |
90
+ | add_reminder | Add reminder |
91
+ | delete_reminder | Delete reminder |
92
+ | update_reminder | Update reminder content |
93
+ | migrate_reminder | Move an over-shared reminder back to this dialog |
94
+ | do_mind | Create new Taskdoc section |
95
+ | mind_more | Append entries to Taskdoc (defaults to progress) |
96
+ | change_mind | Replace existing Taskdoc section |
97
+ | never_mind | Delete Taskdoc section file |
98
+ | recall_taskdoc | Read taskdoc chapter |
98
99
 
99
100
  ## Inter-dialog Reply Routing
100
101
 
@@ -125,7 +126,7 @@ Taskdoc is a **task contract** and the task's **team-shared source of current tr
125
126
  - **Easy-to-lose details**: temporary paths, ids, commands, sample inputs
126
127
  - **Course transition**: continuation-package notes before `clear_mind`, including rough multi-reminder carry-over when already degraded
127
128
  - **Task carry-over**: if you should keep seeing the note under the current Taskdoc, use `task`
128
- - **Global urgent cue**: if you should keep seeing it in all later dialogs you lead, and it is urgent, short-lived, and globally visible, use `agent`
129
+ - **Global urgent cue**: if you should keep seeing it across later dialogs you lead, and it is urgent, short-lived, and globally visible, use `agent`
129
130
 
130
131
  ### 2. Taskdoc Update Timing
131
132
 
@@ -161,7 +162,7 @@ Taskdoc is a **task contract** and the task's **team-shared source of current tr
161
162
 
162
163
  ## Limitations and Notes
163
164
 
164
- 1. `dialog` reminders end with the dialog; `task` reminders stay visible under the current Taskdoc; `agent` reminders stay visible in all later dialogs you lead
165
+ 1. `dialog` reminders end with the dialog; `task` reminders stay visible under the current Taskdoc; `agent` reminders stay visible in later dialogs you lead
165
166
  2. Use `do_mind` to create missing Taskdoc sections; use `mind_more` for small Taskdoc additions; use `change_mind` for full-section replacement of existing sections only after merging existing content and calling `recall_taskdoc` for the current `content_hash`; use `never_mind` when a whole section file should be deleted. Do not treat `mind_more` as a chronology tool; when cleanup, stale-entry removal, or same-topic consolidation is needed, use `recall_taskdoc` then `change_mind`
166
167
  3. `do_mind` / `mind_more` / `change_mind` / `never_mind` do not start a new course
167
168
  4. A continuation-package reminder should keep only details still not covered by Taskdoc but easy to lose during resume; in the Main Dialog, undocumented discussion details from current dialog history that the next course needs to know should be written to the appropriate Taskdoc sections first; in a Side Dialog after Dominds warns that context is tight or critical, maintain sufficiently detailed continuation-package reminders only
@@ -112,7 +112,30 @@ updated_at: <update timestamp>
112
112
 
113
113
  - `REMINDER_NOT_FOUND`: Reminder id does not exist
114
114
 
115
- ### 4. clear_mind
115
+ ### 4. migrate_reminder
116
+
117
+ Move a visible shared reminder back into the current dialog scope.
118
+
119
+ Use when:
120
+
121
+ - You just updated a task/agent shared reminder and then realize the new content belongs only to this dialog
122
+ - Dominds warned that the shared update affected same-agent parallel dialogs and you need to withdraw it from those dialogs
123
+
124
+ **Parameters:**
125
+
126
+ - `reminder_id` (required): Reminder id
127
+ - `scope` (required): Must be `dialog`
128
+
129
+ **Example:**
130
+
131
+ ```js
132
+ migrate_reminder({
133
+ reminder_id: 'abc123de',
134
+ scope: 'dialog',
135
+ });
136
+ ```
137
+
138
+ ### 5. clear_mind
116
139
 
117
140
  Start a new dialog course.
118
141
 
@@ -73,7 +73,7 @@
73
73
 
74
74
  ### Q: `dialog` / `task` / `agent` 提醒和 memory 有什么区别?
75
75
 
76
- A: `dialog` 提醒只用于当前对话的手头工作;`task` 提醒用于同一差遣牒任务内的手头工作,也是 `add_reminder` 默认范围;`agent` 提醒会在所有由你主理的后续对话里继续可见,只适合紧急、短期、全局刺眼提醒。它们都不是长期知识库。`personal_memory` 用于保存持久稳定事实和可复用知识;如果信息需要向全队同步当前有效状态、关键决策、下一步或仍成立阻塞,应写入 Taskdoc `progress`,而不是提醒项。
76
+ A: `dialog` 提醒只用于当前对话的手头工作;`task` 提醒用于同一差遣牒任务内的手头工作,也是 `add_reminder` 默认范围;`agent` 提醒会在由你主理的后续对话里继续可见,只适合紧急、短期、全局刺眼提醒。它们都不是长期知识库。`personal_memory` 用于保存持久稳定事实和可复用知识;如果信息需要向全队同步当前有效状态、关键决策、下一步或仍成立阻塞,应写入 Taskdoc `progress`,而不是提醒项。
77
77
 
78
78
  ### Q: `dialog`、`task` 和 `agent` 怎么选?
79
79
 
@@ -64,7 +64,7 @@ scope 规则:
64
64
 
65
65
  - `dialog`:当前对话手头工作
66
66
  - `task`:当前差遣牒任务下的手头工作,默认范围
67
- - `agent`:在所有由你主理的后续对话里也应继续看到的紧急、短期、全局刺眼提醒
67
+ - `agent`:在由你主理的后续对话里也应继续看到的紧急、短期、全局刺眼提醒
68
68
 
69
69
  ### 差遣牒
70
70
 
@@ -30,8 +30,8 @@
30
30
  提醒是临时手头工作提示,但现在分成三个 scope:
31
31
 
32
32
  - `dialog`:仅当前对话可见
33
- - `task`:当前差遣牒任务内、所有由你主理的对话里都可见
34
- - `agent`:所有由你主理的对话里都可见,但只用于紧急、短期、全局刺眼提醒
33
+ - `task`:当前差遣牒任务内跨对话可见
34
+ - `agent`:由你主理的后续对话会继续看到,但只用于紧急、短期、全局刺眼提醒
35
35
 
36
36
  默认用 `task`。只有当这条提醒只对当前对话局部有效时,才降到 `dialog`;只有当它是紧急、短期、全局刺眼提醒时,才升到 `agent`。
37
37
 
@@ -39,7 +39,7 @@
39
39
 
40
40
  - `dialog` 提醒只留在当前对话
41
41
  - `task` 提醒会在当前差遣牒任务内继续可见
42
- - `agent` 提醒会在所有由你主理的后续对话里继续可见
42
+ - `agent` 提醒会在由你主理的后续对话里继续可见
43
43
  - 可随时添加、修改、删除
44
44
  - 默认应保持少量、可扫读、可直接指导下一步
45
45
  - 准备 `clear_mind` 时,主线对话先把应由下一程知会的未落文档讨论细节补进差遣牒,再压缩成结构化接续包提醒项;支线对话直接维护足够详尽的接续包提醒项。若 Dominds 已提醒上下文吃紧/告急,支线提醒项没有固定长度限制,也可先保留多条粗略提醒项过桥
@@ -47,7 +47,7 @@
47
47
  **与 memory 的区别:**
48
48
  | 特性 | dialog reminder | task reminder | agent reminder | personal memory |
49
49
  |------|-----------------|---------------|----------------|-----------------|
50
- | 持久性 | 仅当前对话 | 当前差遣牒任务 | 跨所有由你主理的后续对话 | 长期 / 文件持久化 |
50
+ | 持久性 | 仅当前对话 | 当前差遣牒任务 | 跨由你主理的后续对话 | 长期 / 文件持久化 |
51
51
  | 可见性 | 当前对话 | 当前任务相关对话 | 你当前可见的提醒范围 | 当前智能体 |
52
52
  | 最适合 | 当前下一步、阻塞、易丢线索 | 同一任务下的手头工作 | 紧急、短期、全局刺眼提醒 | 稳定事实 / 可复用知识 |
53
53
 
@@ -84,16 +84,17 @@
84
84
 
85
85
  ## 工具概览
86
86
 
87
- | 工具 | 功能 |
88
- | --------------- | --------------------------------- |
89
- | add_reminder | 添加提醒 |
90
- | delete_reminder | 删除提醒 |
91
- | update_reminder | 更新提醒内容 |
92
- | do_mind | 创建新差遣牒章节 |
93
- | mind_more | 向差遣牒追加条目(默认 progress) |
94
- | change_mind | 整章替换已有差遣牒章节 |
95
- | never_mind | 删除差遣牒章节文件 |
96
- | recall_taskdoc | 读取差遣牒章节 |
87
+ | 工具 | 功能 |
88
+ | ---------------- | --------------------------------- |
89
+ | add_reminder | 添加提醒 |
90
+ | delete_reminder | 删除提醒 |
91
+ | update_reminder | 更新提醒内容 |
92
+ | migrate_reminder | 将误扩散的共享提醒迁回当前对话 |
93
+ | do_mind | 创建新差遣牒章节 |
94
+ | mind_more | 向差遣牒追加条目(默认 progress) |
95
+ | change_mind | 整章替换已有差遣牒章节 |
96
+ | never_mind | 删除差遣牒章节文件 |
97
+ | recall_taskdoc | 读取差遣牒章节 |
97
98
 
98
99
  ## 跨对话回复路由
99
100
 
@@ -124,7 +125,7 @@
124
125
  - **易丢细节**:临时路径、id、命令、样例输入
125
126
  - **换程接续**:在 `clear_mind` 前整理接续包;若 Dominds 已提醒当前程吃紧/告急,可先保留多条粗略提醒项
126
127
  - **任务延续提示**:如果在当前差遣牒任务内都应该继续看到它,用 `task`
127
- - **全局刺眼提示**:如果它应该在所有由你主理的后续对话里继续看到,而且是短期、紧急、全局刺眼提醒,用 `agent`
128
+ - **全局刺眼提示**:如果它应该在由你主理的后续对话里继续看到,而且是短期、紧急、全局刺眼提醒,用 `agent`
128
129
 
129
130
  ### 2. 差遣牒更新时机
130
131
 
@@ -160,7 +161,7 @@
160
161
 
161
162
  ## 限制与注意事项
162
163
 
163
- 1. `dialog` 提醒会随对话结束而结束;`task` 提醒会在当前差遣牒任务内继续可见;`agent` 提醒会在所有由你主理的后续对话里继续可见
164
+ 1. `dialog` 提醒会随对话结束而结束;`task` 提醒会在当前差遣牒任务内继续可见;`agent` 提醒会在由你主理的后续对话里继续可见
164
165
  2. 缺失差遣牒章节用 `do_mind` 创建;差遣牒少量新增可用 `mind_more` 追加;已有章节整段替换用 `change_mind`,请确保合并已有内容,并先调用 `recall_taskdoc` 取得当前 `content_hash` 作为 `previous_content_hash`;确需删除整章文件时用 `never_mind`。不要把 `mind_more` 当流水账工具;需要整理、去旧、合并同主题记录时先 `recall_taskdoc` 再 `change_mind`
165
166
  3. `do_mind` / `mind_more` / `change_mind` / `never_mind` 不开启新 course
166
167
  4. 接续包提醒项只保留差遣牒仍未覆盖、但恢复工作容易丢的细节;主线对话应先把当前对话历史中应由下一程知会的未落文档讨论细节写入差遣牒合适章节;支线对话在吃紧/告急时只维护足够详尽的接续包提醒项
@@ -112,7 +112,30 @@ updated_at: <更新时间戳>
112
112
 
113
113
  - `REMINDER_NOT_FOUND`:提醒 id 不存在
114
114
 
115
- ### 4. clear_mind
115
+ ### 4. migrate_reminder
116
+
117
+ 把当前可见的共享 reminder 迁回当前对话范围。
118
+
119
+ **适用:**
120
+
121
+ - 你刚更新 task/agent 共享提醒项后,发现新内容其实只属于当前对话
122
+ - Dominds 已提醒这次共享更新影响了同智能体并行对话,需要从其它并行对话撤下
123
+
124
+ **参数:**
125
+
126
+ - `reminder_id`(必需):提醒 id
127
+ - `scope`(必需):只能是 `dialog`
128
+
129
+ **示例:**
130
+
131
+ ```js
132
+ migrate_reminder({
133
+ reminder_id: 'abc123de',
134
+ scope: 'dialog',
135
+ });
136
+ ```
137
+
138
+ ### 5. clear_mind
116
139
 
117
140
  开启新一程对话。
118
141
 
@@ -79,6 +79,8 @@ Get daemon process output.
79
79
  - `pid` (required): Daemon process ID (number)
80
80
  - `stdout` (optional): Whether to include stdout output (default: `true`)
81
81
  - `stderr` (optional): Whether to include stderr output (default: `true`)
82
+ - `wait_for_new_output` (optional): Whether to wait until a requested stdout/stderr stream receives new output before returning (default: `false`; providing `timeout_ms` implies `true`)
83
+ - `timeout_ms` (optional): Maximum milliseconds to wait for new output, capped at `86400000` (24h); on timeout, returns the current snapshot with a timeout notice; cannot be combined with `wait_for_new_output:false`
82
84
 
83
85
  **Returns:**
84
86
 
@@ -79,6 +79,8 @@ stopped_at: <停止时间戳>
79
79
  - `pid`(必需):守护进程 PID(数字)
80
80
  - `stdout`(可选):是否包含 stdout 输出(默认 `true`)
81
81
  - `stderr`(可选):是否包含 stderr 输出(默认 `true`)
82
+ - `wait_for_new_output`(可选):是否等待所请求的 stdout/stderr 流出现新输出后再返回(默认 `false`;提供 `timeout_ms` 时默认视为 `true`)
83
+ - `timeout_ms`(可选):等待新输出的最长毫秒数,最大 `86400000`(24 小时);超时后返回当前快照并提示超时;不可与 `wait_for_new_output:false` 同时使用
82
84
 
83
85
  **返回:**
84
86
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dominds",
3
- "version": "1.27.2",
3
+ "version": "1.27.3",
4
4
  "description": "Dominds CLI and aggregation shell for the LongRun AI kernel/runtime packages.",
5
5
  "type": "commonjs",
6
6
  "publishConfig": {
@@ -54,9 +54,9 @@
54
54
  "ws": "^8.21.0",
55
55
  "yaml": "^2.9.0",
56
56
  "zod": "^4.4.3",
57
- "@longrun-ai/kernel": "1.17.2",
58
- "@longrun-ai/shell": "1.17.2",
59
- "@longrun-ai/codex-auth": "0.14.0"
57
+ "@longrun-ai/codex-auth": "0.14.0",
58
+ "@longrun-ai/kernel": "1.17.3",
59
+ "@longrun-ai/shell": "1.17.3"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@types/node": "^25.9.1",