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.
- package/dist/apps/runtime.js +3 -1
- package/dist/dialog-global-registry.d.ts +11 -1
- package/dist/dialog-global-registry.js +45 -0
- package/dist/dialog.d.ts +11 -2
- package/dist/dialog.js +107 -17
- package/dist/docs/daemon-cmd-runner.md +5 -0
- package/dist/docs/daemon-cmd-runner.zh.md +5 -0
- package/dist/llm/kernel-driver/drive.js +163 -11
- package/dist/llm/kernel-driver/fbr.d.ts +9 -0
- package/dist/llm/kernel-driver/fbr.js +186 -59
- package/dist/minds/load.js +1 -0
- package/dist/persistence.js +18 -1
- package/dist/runtime/driver-messages.d.ts +9 -0
- package/dist/runtime/driver-messages.js +61 -5
- package/dist/runtime/shared-reminder-update-impact.d.ts +20 -0
- package/dist/runtime/shared-reminder-update-impact.js +110 -0
- package/dist/tool-availability.js +1 -0
- package/dist/tools/builtins.js +2 -0
- package/dist/tools/cmd-runner-protocol.d.ts +6 -0
- package/dist/tools/cmd-runner-protocol.js +57 -2
- package/dist/tools/cmd-runner.js +83 -2
- package/dist/tools/ctrl.d.ts +2 -0
- package/dist/tools/ctrl.js +179 -5
- package/dist/tools/os.js +115 -14
- package/dist/tools/process-kill.js +49 -0
- package/dist/tools/prompts/control/en/errors.md +1 -1
- package/dist/tools/prompts/control/en/index.md +1 -1
- package/dist/tools/prompts/control/en/principles.md +18 -17
- package/dist/tools/prompts/control/en/tools.md +24 -1
- package/dist/tools/prompts/control/zh/errors.md +1 -1
- package/dist/tools/prompts/control/zh/index.md +1 -1
- package/dist/tools/prompts/control/zh/principles.md +17 -16
- package/dist/tools/prompts/control/zh/tools.md +24 -1
- package/dist/tools/prompts/os/en/tools.md +2 -0
- package/dist/tools/prompts/os/zh/tools.md +2 -0
- 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
|
-
|
|
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
|
|
949
|
-
return { ok: true, scriptAbs: tsCandidate, execArgv: ['--import',
|
|
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
|
-
|
|
1025
|
+
if (timeoutHandle !== undefined) {
|
|
1026
|
+
clearTimeout(timeoutHandle);
|
|
1027
|
+
}
|
|
995
1028
|
socket.destroy();
|
|
996
1029
|
fn();
|
|
997
1030
|
};
|
|
998
|
-
const timeoutHandle =
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
34
|
-
- `agent`: visible in
|
|
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
|
|
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
|
|
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
|
|
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
|
|
89
|
-
|
|
|
90
|
-
| add_reminder
|
|
91
|
-
| delete_reminder
|
|
92
|
-
| update_reminder
|
|
93
|
-
|
|
|
94
|
-
|
|
|
95
|
-
|
|
|
96
|
-
|
|
|
97
|
-
|
|
|
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
|
|
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
|
|
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.
|
|
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`
|
|
76
|
+
A: `dialog` 提醒只用于当前对话的手头工作;`task` 提醒用于同一差遣牒任务内的手头工作,也是 `add_reminder` 默认范围;`agent` 提醒会在由你主理的后续对话里继续可见,只适合紧急、短期、全局刺眼提醒。它们都不是长期知识库。`personal_memory` 用于保存持久稳定事实和可复用知识;如果信息需要向全队同步当前有效状态、关键决策、下一步或仍成立阻塞,应写入 Taskdoc `progress`,而不是提醒项。
|
|
77
77
|
|
|
78
78
|
### Q: `dialog`、`task` 和 `agent` 怎么选?
|
|
79
79
|
|
|
@@ -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
|
-
|
|
|
93
|
-
|
|
|
94
|
-
|
|
|
95
|
-
|
|
|
96
|
-
|
|
|
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
|
-
-
|
|
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.
|
|
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.
|
|
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/
|
|
58
|
-
"@longrun-ai/
|
|
59
|
-
"@longrun-ai/
|
|
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",
|