dominds 1.25.4 → 1.25.5
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.
|
@@ -204,6 +204,11 @@ function getMemoryPromptCopy(ctx) {
|
|
|
204
204
|
? `工作流:先做事 → 再提炼(\`update_reminder\`;必要时整理差遣牒追加条目/更新提案并诉请 \`@${ctx.taskdocMaintainerId}\` 合并写入)→ 然后 \`clear_mind\` 清空噪音。`
|
|
205
205
|
: '工作流:停止扩张上下文 → 维护足够详尽的接续包提醒项(`add_reminder` 或 `update_reminder`,长度没有技术限制)→ 然后 `clear_mind` 开启新一程。',
|
|
206
206
|
mainDialogWorkflowLine: '工作流:先做事 -> 再提炼(`update_reminder` + `mind_more(progress)`;需要压缩/删旧时先 `recall_taskdoc` 取得 `content_hash`,再用带 `previous_content_hash` 的 `change_mind`;要删除整章文件时用 `never_mind`)-> 然后 `clear_mind` 清空噪音。',
|
|
207
|
+
...(ctx.isSideDialog
|
|
208
|
+
? {}
|
|
209
|
+
: {
|
|
210
|
+
progressVcsOrderLine: '硬性顺序:先补 `progress`,再动 git。只要这次代码/文档改动准备进 git(add / commit / push),先确认 `progress` 已经写清当前状态、决策、阻塞和下一步;如果还没写清,就先补写。简单判断:改动会进仓库 + `progress` 还没跟上 = 先别动 git。`git status` 只用来确认,不是提交动作。不要把“提交了某个 commit”“push 了”写进 `progress`。',
|
|
211
|
+
}),
|
|
207
212
|
contextHealthLine: contextHealthLineZh,
|
|
208
213
|
taskdocLogLine: taskdocLogLineZh,
|
|
209
214
|
};
|
|
@@ -239,6 +244,11 @@ function getMemoryPromptCopy(ctx) {
|
|
|
239
244
|
? `Workflow: do work → distill (\`update_reminder\`; when Taskdoc needs updates, draft append entries, a merged replacement, or a section deletion and ask \`@${ctx.taskdocMaintainerId}\`) → then \`clear_mind\` to drop noise.`
|
|
240
245
|
: 'Workflow: stop expanding context → maintain sufficiently detailed continuation-package reminders (`add_reminder` or `update_reminder`, with no technical length limit) → then `clear_mind` to start a new course.',
|
|
241
246
|
mainDialogWorkflowLine: 'Workflow: do work -> distill (`update_reminder` + `mind_more(progress)`; when compression/deletion is needed, first use `recall_taskdoc` to get `content_hash`, then use `change_mind` with `previous_content_hash`; use `never_mind` when removing a whole section file) -> then `clear_mind` to drop noise.',
|
|
247
|
+
...(ctx.isSideDialog
|
|
248
|
+
? {}
|
|
249
|
+
: {
|
|
250
|
+
progressVcsOrderLine: 'Hard order: update `progress` first, then use git. If this code/docs change is going into git (add / commit / push), make sure `progress` already says the current state, decisions, blockers, and next step; if not, write it first. Simple check: change will enter the repo + `progress` is behind = stop and update `progress` first. `git status` is only for checking, not a commit step. Do not write git events like “committed X” or “ran git push” into progress.',
|
|
251
|
+
}),
|
|
242
252
|
contextHealthLine: contextHealthLineEn,
|
|
243
253
|
taskdocLogLine: taskdocLogLineEn,
|
|
244
254
|
};
|
|
@@ -264,6 +274,7 @@ function buildMemorySystemPrompt(ctx) {
|
|
|
264
274
|
...(ctx.agentHasTeamMemoryTools ? [copy.teamMemoryHintLine] : []),
|
|
265
275
|
...(ctx.agentHasPersonalMemoryTools ? [copy.personalMemoryHintLine] : []),
|
|
266
276
|
ctx.isSideDialog ? copy.sideDialogWorkflowLine : copy.mainDialogWorkflowLine,
|
|
277
|
+
...(copy.progressVcsOrderLine === undefined ? [] : [copy.progressVcsOrderLine]),
|
|
267
278
|
copy.contextHealthLine,
|
|
268
279
|
copy.taskdocLogLine,
|
|
269
280
|
].join('\n');
|
|
@@ -16,9 +16,12 @@ const util_1 = require("util");
|
|
|
16
16
|
const time_1 = require("@longrun-ai/kernel/utils/time");
|
|
17
17
|
const log_1 = require("../log");
|
|
18
18
|
const dominds_running_version_1 = require("./dominds-running-version");
|
|
19
|
-
const
|
|
19
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
20
20
|
const log = (0, log_1.createLogger)('dominds-self-update');
|
|
21
21
|
const BACKGROUND_CHECK_INTERVAL_MS = 30 * 60 * 1000;
|
|
22
|
+
const LATEST_VERSION_CHECK_TIMEOUT_MS = 15000;
|
|
23
|
+
const RESTART_PORT_RELEASE_TIMEOUT_MS = 15000;
|
|
24
|
+
const RESTART_PORT_PROBE_INTERVAL_MS = 150;
|
|
22
25
|
const IDLE_RESTART_STATE = { kind: 'idle' };
|
|
23
26
|
let runtimeConfig = null;
|
|
24
27
|
let latestObservation = { kind: 'unknown' };
|
|
@@ -27,12 +30,6 @@ let installPromise = null;
|
|
|
27
30
|
let restartPromise = null;
|
|
28
31
|
let restartState = IDLE_RESTART_STATE;
|
|
29
32
|
let broadcastStatusUpdate = null;
|
|
30
|
-
function getNpmBin() {
|
|
31
|
-
return process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
32
|
-
}
|
|
33
|
-
function getNpxBin() {
|
|
34
|
-
return process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
35
|
-
}
|
|
36
33
|
function normalizeVersionString(value) {
|
|
37
34
|
return value.trim().replace(/^v/i, '');
|
|
38
35
|
}
|
|
@@ -74,17 +71,31 @@ function detectRunKind(mode) {
|
|
|
74
71
|
}
|
|
75
72
|
return 'npm_global';
|
|
76
73
|
}
|
|
74
|
+
function hasInteractiveConsole() {
|
|
75
|
+
return Boolean(process.stdin.isTTY || process.stdout.isTTY || process.stderr.isTTY);
|
|
76
|
+
}
|
|
77
|
+
function getRestartHelperStdio() {
|
|
78
|
+
return hasInteractiveConsole() ? 'inherit' : 'ignore';
|
|
79
|
+
}
|
|
80
|
+
function getRestartPortProbeHost(host) {
|
|
81
|
+
if (host === '0.0.0.0')
|
|
82
|
+
return '127.0.0.1';
|
|
83
|
+
if (host === '::')
|
|
84
|
+
return '::1';
|
|
85
|
+
return host;
|
|
86
|
+
}
|
|
77
87
|
async function queryLatestVersion() {
|
|
78
88
|
const checkedAt = (0, time_1.formatUnifiedTimestamp)(new Date());
|
|
79
89
|
try {
|
|
80
|
-
const { stdout } = await
|
|
90
|
+
const { stdout } = await execAsync('npm view dominds version --json', {
|
|
81
91
|
cwd: process.cwd(),
|
|
82
92
|
env: process.env,
|
|
83
93
|
maxBuffer: 1024 * 1024,
|
|
84
|
-
timeout:
|
|
94
|
+
timeout: LATEST_VERSION_CHECK_TIMEOUT_MS,
|
|
85
95
|
});
|
|
86
96
|
const trimmed = stdout.trim();
|
|
87
97
|
if (trimmed === '') {
|
|
98
|
+
log.warn('Dominds latest-version check returned empty stdout', undefined, { checkedAt });
|
|
88
99
|
return {
|
|
89
100
|
kind: 'error',
|
|
90
101
|
errorText: 'npm view dominds version returned empty stdout',
|
|
@@ -100,6 +111,10 @@ async function queryLatestVersion() {
|
|
|
100
111
|
}
|
|
101
112
|
const latestVersion = typeof parsed === 'string' ? parsed.trim() : '';
|
|
102
113
|
if (latestVersion === '') {
|
|
114
|
+
log.warn('Dominds latest-version check returned an invalid payload', undefined, {
|
|
115
|
+
checkedAt,
|
|
116
|
+
stdout: trimmed,
|
|
117
|
+
});
|
|
103
118
|
return {
|
|
104
119
|
kind: 'error',
|
|
105
120
|
errorText: `npm view dominds version returned non-string output: ${trimmed}`,
|
|
@@ -109,15 +124,21 @@ async function queryLatestVersion() {
|
|
|
109
124
|
return { kind: 'ok', latestVersion, checkedAt };
|
|
110
125
|
}
|
|
111
126
|
catch (error) {
|
|
127
|
+
const errorText = error instanceof Error && error.name === 'AbortError'
|
|
128
|
+
? 'npm view dominds version timed out'
|
|
129
|
+
: error instanceof Error
|
|
130
|
+
? error.message
|
|
131
|
+
: String(error);
|
|
132
|
+
log.warn('Dominds latest-version check failed', error, { checkedAt, errorText });
|
|
112
133
|
return {
|
|
113
134
|
kind: 'error',
|
|
114
|
-
errorText
|
|
135
|
+
errorText,
|
|
115
136
|
checkedAt,
|
|
116
137
|
};
|
|
117
138
|
}
|
|
118
139
|
}
|
|
119
140
|
async function resolveGlobalDomindsCommandAbs() {
|
|
120
|
-
const { stdout } = await
|
|
141
|
+
const { stdout } = await execAsync('npm prefix -g', {
|
|
121
142
|
cwd: process.cwd(),
|
|
122
143
|
env: process.env,
|
|
123
144
|
maxBuffer: 1024 * 1024,
|
|
@@ -422,7 +443,7 @@ async function installLatestDominds() {
|
|
|
422
443
|
if (!hasUpdate) {
|
|
423
444
|
throw new Error('No installable Dominds update is currently available');
|
|
424
445
|
}
|
|
425
|
-
await
|
|
446
|
+
await execAsync('npm i -g dominds@latest', {
|
|
426
447
|
cwd: process.cwd(),
|
|
427
448
|
env: process.env,
|
|
428
449
|
maxBuffer: 20 * 1024 * 1024,
|
|
@@ -435,7 +456,19 @@ async function installLatestDominds() {
|
|
|
435
456
|
globalCommandAbs,
|
|
436
457
|
};
|
|
437
458
|
return await getDomindsSelfUpdateStatus();
|
|
438
|
-
})()
|
|
459
|
+
})()
|
|
460
|
+
.catch((error) => {
|
|
461
|
+
const latestVersion = latestObservation.kind === 'ok' ? latestObservation.latestVersion : null;
|
|
462
|
+
const checkedAt = latestObservation.kind === 'unknown' ? null : latestObservation.checkedAt;
|
|
463
|
+
log.error('Dominds version install failed', error, {
|
|
464
|
+
runKind,
|
|
465
|
+
currentVersion: getRunningVersion(),
|
|
466
|
+
latestVersion,
|
|
467
|
+
checkedAt,
|
|
468
|
+
});
|
|
469
|
+
throw error;
|
|
470
|
+
})
|
|
471
|
+
.finally(() => {
|
|
439
472
|
installPromise = null;
|
|
440
473
|
publishStatusUpdateSoon();
|
|
441
474
|
});
|
|
@@ -446,33 +479,72 @@ function buildRestartArgs(cfg) {
|
|
|
446
479
|
return ['webui', '-p', String(cfg.port), '-h', cfg.host, '--mode', 'prod', '--nobrowser'];
|
|
447
480
|
}
|
|
448
481
|
function spawnDetachedRestartHelper(params) {
|
|
482
|
+
const stdioMode = getRestartHelperStdio();
|
|
449
483
|
const helperPayload = JSON.stringify({
|
|
450
484
|
command: params.command,
|
|
451
485
|
args: [...params.args],
|
|
452
486
|
cwd: params.cwd,
|
|
453
|
-
|
|
487
|
+
host: getRestartPortProbeHost(params.host),
|
|
488
|
+
port: params.port,
|
|
489
|
+
probeIntervalMs: RESTART_PORT_PROBE_INTERVAL_MS,
|
|
490
|
+
portReleaseTimeoutMs: RESTART_PORT_RELEASE_TIMEOUT_MS,
|
|
491
|
+
stdioMode,
|
|
454
492
|
});
|
|
455
493
|
const helperScript = [
|
|
494
|
+
"const net = require('net');",
|
|
456
495
|
"const { spawn } = require('child_process');",
|
|
457
496
|
'const payload = JSON.parse(process.argv[1]);',
|
|
458
|
-
'
|
|
497
|
+
'const detached = payload.stdioMode !== "inherit" || process.platform === "win32";',
|
|
498
|
+
'function isPortBusy() {',
|
|
499
|
+
' return new Promise((resolve) => {',
|
|
500
|
+
' const socket = net.createConnection({ host: payload.host, port: payload.port });',
|
|
501
|
+
' let settled = false;',
|
|
502
|
+
' const finish = (busy) => {',
|
|
503
|
+
' if (settled) return;',
|
|
504
|
+
' settled = true;',
|
|
505
|
+
' socket.destroy();',
|
|
506
|
+
' resolve(busy);',
|
|
507
|
+
' };',
|
|
508
|
+
' socket.once("connect", () => finish(true));',
|
|
509
|
+
' socket.once("error", () => finish(false));',
|
|
510
|
+
' socket.setTimeout(1000, () => finish(true));',
|
|
511
|
+
' });',
|
|
512
|
+
'}',
|
|
513
|
+
'async function waitForPortRelease() {',
|
|
514
|
+
' const deadline = Date.now() + payload.portReleaseTimeoutMs;',
|
|
515
|
+
' let consecutiveIdle = 0;',
|
|
516
|
+
' while (Date.now() < deadline) {',
|
|
517
|
+
' if (await isPortBusy()) {',
|
|
518
|
+
' consecutiveIdle = 0;',
|
|
519
|
+
' await new Promise((resolve) => setTimeout(resolve, payload.probeIntervalMs));',
|
|
520
|
+
' continue;',
|
|
521
|
+
' }',
|
|
522
|
+
' consecutiveIdle += 1;',
|
|
523
|
+
' if (consecutiveIdle >= 2) return;',
|
|
524
|
+
' await new Promise((resolve) => setTimeout(resolve, payload.probeIntervalMs));',
|
|
525
|
+
' }',
|
|
526
|
+
'}',
|
|
527
|
+
'(async () => {',
|
|
459
528
|
' try {',
|
|
460
|
-
|
|
461
|
-
|
|
529
|
+
' await waitForPortRelease();',
|
|
530
|
+
" const child = spawn(payload.command, payload.args, { cwd: payload.cwd, env: process.env, detached, stdio: payload.stdioMode, shell: process.platform === 'win32' });",
|
|
531
|
+
' if (detached) child.unref();',
|
|
462
532
|
' process.exit(0);',
|
|
463
533
|
' } catch (error) {',
|
|
464
534
|
' console.error(error instanceof Error ? error.message : String(error));',
|
|
465
535
|
' process.exit(1);',
|
|
466
536
|
' }',
|
|
467
|
-
'}
|
|
537
|
+
'})();',
|
|
468
538
|
].join('\n');
|
|
469
539
|
const helper = (0, child_process_1.spawn)(process.execPath, ['-e', helperScript, helperPayload], {
|
|
470
540
|
cwd: params.cwd,
|
|
471
541
|
env: process.env,
|
|
472
|
-
detached:
|
|
473
|
-
stdio:
|
|
542
|
+
detached: stdioMode !== 'inherit' || process.platform === 'win32',
|
|
543
|
+
stdio: stdioMode,
|
|
474
544
|
});
|
|
475
|
-
|
|
545
|
+
if (stdioMode !== 'inherit' || process.platform === 'win32') {
|
|
546
|
+
helper.unref();
|
|
547
|
+
}
|
|
476
548
|
}
|
|
477
549
|
async function stopAndExitForRestart() {
|
|
478
550
|
const cfg = assertRuntimeConfig();
|
|
@@ -500,7 +572,7 @@ async function restartDomindsIntoLatest() {
|
|
|
500
572
|
let command;
|
|
501
573
|
const previousRestartRequiredState = restartState.kind === 'restart_required' ? restartState : null;
|
|
502
574
|
if (runKind === 'npx_latest') {
|
|
503
|
-
command =
|
|
575
|
+
command = 'npx';
|
|
504
576
|
args.unshift('dominds@latest');
|
|
505
577
|
args.unshift('-y');
|
|
506
578
|
}
|
|
@@ -512,25 +584,48 @@ async function restartDomindsIntoLatest() {
|
|
|
512
584
|
}
|
|
513
585
|
restartState = { kind: 'restarting', targetVersion: status.targetVersion };
|
|
514
586
|
publishStatusUpdateSoon();
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
587
|
+
try {
|
|
588
|
+
spawnDetachedRestartHelper({
|
|
589
|
+
command,
|
|
590
|
+
args,
|
|
591
|
+
cwd: process.cwd(),
|
|
592
|
+
host: cfg.host,
|
|
593
|
+
port: cfg.port,
|
|
594
|
+
});
|
|
595
|
+
setImmediate(() => {
|
|
596
|
+
void stopAndExitForRestart().catch((error) => {
|
|
597
|
+
log.error('Failed to stop Dominds server during restart', error);
|
|
598
|
+
if (runKind === 'npm_global' && previousRestartRequiredState !== null) {
|
|
599
|
+
restartState = previousRestartRequiredState;
|
|
600
|
+
publishStatusUpdateSoon();
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
restartState = IDLE_RESTART_STATE;
|
|
525
604
|
publishStatusUpdateSoon();
|
|
526
|
-
|
|
527
|
-
}
|
|
528
|
-
restartState = IDLE_RESTART_STATE;
|
|
529
|
-
publishStatusUpdateSoon();
|
|
605
|
+
});
|
|
530
606
|
});
|
|
531
|
-
}
|
|
607
|
+
}
|
|
608
|
+
catch (error) {
|
|
609
|
+
if (previousRestartRequiredState !== null) {
|
|
610
|
+
restartState = previousRestartRequiredState;
|
|
611
|
+
}
|
|
612
|
+
else {
|
|
613
|
+
restartState = IDLE_RESTART_STATE;
|
|
614
|
+
}
|
|
615
|
+
publishStatusUpdateSoon();
|
|
616
|
+
throw error;
|
|
617
|
+
}
|
|
532
618
|
return await getDomindsSelfUpdateStatus();
|
|
533
|
-
})()
|
|
619
|
+
})()
|
|
620
|
+
.catch((error) => {
|
|
621
|
+
const statusSnapshot = restartState.kind === 'restarting' ? restartState : null;
|
|
622
|
+
log.error('Dominds version restart failed', error, {
|
|
623
|
+
runKind: detectRunKind(cfg.mode),
|
|
624
|
+
restartState: statusSnapshot,
|
|
625
|
+
});
|
|
626
|
+
throw error;
|
|
627
|
+
})
|
|
628
|
+
.finally(() => {
|
|
534
629
|
restartPromise = null;
|
|
535
630
|
publishStatusUpdateSoon();
|
|
536
631
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dominds",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.5",
|
|
4
4
|
"description": "Dominds CLI and aggregation shell for the LongRun AI kernel/runtime packages.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"publishConfig": {
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
"yaml": "^2.8.2",
|
|
54
54
|
"zod": "^4.3.6",
|
|
55
55
|
"@longrun-ai/codex-auth": "0.13.0",
|
|
56
|
-
"@longrun-ai/kernel": "1.15.
|
|
57
|
-
"@longrun-ai/shell": "1.15.
|
|
56
|
+
"@longrun-ai/kernel": "1.15.5",
|
|
57
|
+
"@longrun-ai/shell": "1.15.5"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@types/node": "^25.3.5",
|