dominds 1.23.1 → 1.23.2
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/cli/webui.js +8 -1
- package/dist/dialog-display-state.d.ts +1 -0
- package/dist/dialog-display-state.js +36 -4
- package/dist/llm/defaults.yaml +3 -0
- package/dist/llm/gen/mock.js +3 -6
- package/dist/llm/kernel-driver/flow.js +11 -13
- package/dist/llm/kernel-driver/loop.js +3 -1
- package/dist/llm/kernel-driver/reply-guidance.js +3 -7
- package/dist/llm/kernel-driver/types.d.ts +1 -0
- package/dist/persistence.js +1 -0
- package/dist/recovery/proceeding-drive.d.ts +1 -0
- package/dist/recovery/proceeding-drive.js +89 -0
- package/dist/runtime/reply-prompt-copy.d.ts +5 -1
- package/dist/runtime/reply-prompt-copy.js +13 -3
- package/dist/server.d.ts +1 -0
- package/dist/server.js +68 -14
- package/dist/tools/cmd-runner.js +76 -17
- package/package.json +2 -2
package/dist/cli/webui.js
CHANGED
|
@@ -134,7 +134,14 @@ async function main() {
|
|
|
134
134
|
const { language: resolvedLanguage, source } = (0, work_language_1.resolveWorkLanguage)({ env: process.env });
|
|
135
135
|
(0, work_language_1.setWorkLanguage)(resolvedLanguage);
|
|
136
136
|
log.info(`working language: ${(0, work_language_1.getWorkLanguage)()} (source: ${source})`);
|
|
137
|
-
const started = await (0, server_1.startServer)({
|
|
137
|
+
const started = await (0, server_1.startServer)({
|
|
138
|
+
port,
|
|
139
|
+
host,
|
|
140
|
+
mode,
|
|
141
|
+
strictPort,
|
|
142
|
+
portAutoDirection,
|
|
143
|
+
returnAfterListen: true,
|
|
144
|
+
});
|
|
138
145
|
const httpServer = started.httpServer;
|
|
139
146
|
const auth = started.auth;
|
|
140
147
|
const baseUrl = `http://${started.host}:${started.port}`;
|
|
@@ -52,6 +52,7 @@ export declare function broadcastDisplayStateMarker(dialogId: DialogID, marker:
|
|
|
52
52
|
}): void;
|
|
53
53
|
export declare function computeIdleDisplayState(dlg: Dialog): Promise<DialogDisplayState>;
|
|
54
54
|
export declare function refreshRunControlProjectionFromPersistenceFacts(dialogId: DialogID, trigger: 'resume_dialog' | 'resume_all' | 'run_control_snapshot' | 'pending_sideDialogs_changed' | 'q4h_changed'): Promise<DialogLatestFile | null>;
|
|
55
|
+
export declare function isRecoverableGeneratingLatest(latest: DialogLatestFile | null): boolean;
|
|
55
56
|
export declare function reconcileDisplayStatesAfterRestart(): Promise<void>;
|
|
56
57
|
export declare function requestInterruptDialog(dialogId: DialogID, reason: StopRequestedReason): Promise<{
|
|
57
58
|
applied: boolean;
|
|
@@ -40,6 +40,7 @@ exports.setDialogDisplayState = setDialogDisplayState;
|
|
|
40
40
|
exports.broadcastDisplayStateMarker = broadcastDisplayStateMarker;
|
|
41
41
|
exports.computeIdleDisplayState = computeIdleDisplayState;
|
|
42
42
|
exports.refreshRunControlProjectionFromPersistenceFacts = refreshRunControlProjectionFromPersistenceFacts;
|
|
43
|
+
exports.isRecoverableGeneratingLatest = isRecoverableGeneratingLatest;
|
|
43
44
|
exports.reconcileDisplayStatesAfterRestart = reconcileDisplayStatesAfterRestart;
|
|
44
45
|
exports.requestInterruptDialog = requestInterruptDialog;
|
|
45
46
|
exports.requestEmergencyStopAll = requestEmergencyStopAll;
|
|
@@ -580,6 +581,19 @@ async function computeIdleDisplayStateForReconciliation(dialogId) {
|
|
|
580
581
|
return null;
|
|
581
582
|
}
|
|
582
583
|
}
|
|
584
|
+
function isRecoverableGeneratingLatest(latest) {
|
|
585
|
+
if (latest?.generating !== true) {
|
|
586
|
+
return false;
|
|
587
|
+
}
|
|
588
|
+
const marker = latest.executionMarker;
|
|
589
|
+
if (!marker) {
|
|
590
|
+
return true;
|
|
591
|
+
}
|
|
592
|
+
if (marker.kind === 'dead') {
|
|
593
|
+
return false;
|
|
594
|
+
}
|
|
595
|
+
return marker.kind !== 'interrupted' || marker.reason.kind === 'pending_course_start';
|
|
596
|
+
}
|
|
583
597
|
async function reconcileDisplayStatesAfterRestart() {
|
|
584
598
|
const dialogIds = await persistence_1.DialogPersistence.listAllDialogIds('running');
|
|
585
599
|
for (const dialogId of dialogIds) {
|
|
@@ -618,10 +632,28 @@ async function reconcileDisplayStatesAfterRestart() {
|
|
|
618
632
|
}
|
|
619
633
|
continue;
|
|
620
634
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
(
|
|
624
|
-
|
|
635
|
+
if (isRecoverableGeneratingLatest(latest)) {
|
|
636
|
+
try {
|
|
637
|
+
await persistence_1.DialogPersistence.mutateDialogLatest(dialogId, () => ({
|
|
638
|
+
kind: 'patch',
|
|
639
|
+
patch: {
|
|
640
|
+
needsDrive: true,
|
|
641
|
+
displayState: { kind: 'proceeding' },
|
|
642
|
+
executionMarker: existingMarker?.kind === 'interrupted' &&
|
|
643
|
+
existingMarker.reason.kind === 'pending_course_start'
|
|
644
|
+
? undefined
|
|
645
|
+
: existingMarker,
|
|
646
|
+
},
|
|
647
|
+
}));
|
|
648
|
+
}
|
|
649
|
+
catch (err) {
|
|
650
|
+
log.warn('Failed to preserve proceeding dialog for auto-drive after restart', err, {
|
|
651
|
+
dialogId: dialogId.valueOf(),
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
continue;
|
|
655
|
+
}
|
|
656
|
+
if (latest?.generating === true || latest?.needsDrive === true) {
|
|
625
657
|
const nextIdle = await computeIdleDisplayStateForReconciliation(dialogId);
|
|
626
658
|
if (!nextIdle) {
|
|
627
659
|
continue;
|
package/dist/llm/defaults.yaml
CHANGED
|
@@ -484,6 +484,7 @@ providers:
|
|
|
484
484
|
models:
|
|
485
485
|
kimi-for-coding:
|
|
486
486
|
name: Kimi For Coding
|
|
487
|
+
optimal_max_tokens: 180000
|
|
487
488
|
supports_thinking: true
|
|
488
489
|
default_thinking: true
|
|
489
490
|
supports_tool_choice: false
|
|
@@ -603,6 +604,7 @@ providers:
|
|
|
603
604
|
context_window: '128K'
|
|
604
605
|
kimi-k2.6:
|
|
605
606
|
name: Kimi-K2.6
|
|
607
|
+
optimal_max_tokens: 180000
|
|
606
608
|
supports_thinking: true
|
|
607
609
|
default_thinking: true
|
|
608
610
|
supports_tool_choice: false
|
|
@@ -613,6 +615,7 @@ providers:
|
|
|
613
615
|
context_window: '200K'
|
|
614
616
|
kimi-k2.5:
|
|
615
617
|
name: Kimi-K2.5
|
|
618
|
+
optimal_max_tokens: 180000
|
|
616
619
|
supports_thinking: true
|
|
617
620
|
default_thinking: false
|
|
618
621
|
supports_tool_choice: false
|
package/dist/llm/gen/mock.js
CHANGED
|
@@ -66,13 +66,11 @@ const log_1 = require("../../log");
|
|
|
66
66
|
const reply_prompt_copy_1 = require("../../runtime/reply-prompt-copy");
|
|
67
67
|
const gen_1 = require("../gen");
|
|
68
68
|
const stop_reason_i18n_1 = require("../stop-reason-i18n");
|
|
69
|
-
const REPLY_TOOL_REMINDER_PREFIXES = [
|
|
70
|
-
'[Dominds replyTellask required]',
|
|
71
|
-
'[Dominds 必须调用回复工具]',
|
|
72
|
-
];
|
|
73
69
|
const RUNTIME_PROMPT_WRAPPER_PREFIXES = [
|
|
74
70
|
reply_prompt_copy_1.ACTIVE_REPLY_TOOL_PREFIX_EN,
|
|
75
71
|
reply_prompt_copy_1.ACTIVE_REPLY_TOOL_PREFIX_ZH,
|
|
72
|
+
reply_prompt_copy_1.NO_ACTIVE_REPLY_PREFIX_EN,
|
|
73
|
+
reply_prompt_copy_1.NO_ACTIVE_REPLY_PREFIX_ZH,
|
|
76
74
|
reply_prompt_copy_1.REPLY_REASSERTION_PREFIX_EN,
|
|
77
75
|
reply_prompt_copy_1.REPLY_REASSERTION_PREFIX_ZH,
|
|
78
76
|
reply_prompt_copy_1.REPLY_SUPPRESSION_PREFIX_EN,
|
|
@@ -277,8 +275,7 @@ class MockGen {
|
|
|
277
275
|
return null;
|
|
278
276
|
}
|
|
279
277
|
buildReplyToolReminderAutoResponse(input, role, context) {
|
|
280
|
-
if (role !== 'user' ||
|
|
281
|
-
!REPLY_TOOL_REMINDER_PREFIXES.some((prefix) => input.startsWith(prefix))) {
|
|
278
|
+
if (role !== 'user' || !(0, reply_prompt_copy_1.isReplyToolReminderPromptContent)(input)) {
|
|
282
279
|
return null;
|
|
283
280
|
}
|
|
284
281
|
const toolMatch = input.match(/`(replyTellask(?:Sessionless|Back)?)`/);
|
|
@@ -23,12 +23,8 @@ const idle_reminder_wake_1 = require("./idle-reminder-wake");
|
|
|
23
23
|
const reply_guidance_1 = require("./reply-guidance");
|
|
24
24
|
const sideDialog_1 = require("./sideDialog");
|
|
25
25
|
const tellask_special_1 = require("./tellask-special");
|
|
26
|
-
const REPLY_TOOL_REMINDER_PREFIX_EN = '[Dominds replyTellask required]';
|
|
27
|
-
const REPLY_TOOL_REMINDER_PREFIX_ZH = '[Dominds 必须调用回复工具]';
|
|
28
26
|
function isReplyToolReminderPrompt(prompt) {
|
|
29
|
-
return
|
|
30
|
-
(prompt.content.startsWith(REPLY_TOOL_REMINDER_PREFIX_EN) ||
|
|
31
|
-
prompt.content.startsWith(REPLY_TOOL_REMINDER_PREFIX_ZH)));
|
|
27
|
+
return typeof prompt?.content === 'string' && (0, reply_prompt_copy_1.isReplyToolReminderPromptContent)(prompt.content);
|
|
32
28
|
}
|
|
33
29
|
function isIgnorablePostResponseAnchorTailEvent(type) {
|
|
34
30
|
return type === 'tellask_reply_resolution_record' || type === 'gen_finish_record';
|
|
@@ -37,7 +33,6 @@ async function buildReplyToolReminderPrompt(args) {
|
|
|
37
33
|
return (0, reply_prompt_copy_1.buildReplyToolReminderText)({
|
|
38
34
|
language: args.language,
|
|
39
35
|
directive: args.directive,
|
|
40
|
-
prefix: args.language === 'zh' ? REPLY_TOOL_REMINDER_PREFIX_ZH : REPLY_TOOL_REMINDER_PREFIX_EN,
|
|
41
36
|
replyTargetAgentId: await (0, reply_guidance_1.resolveReplyTargetAgentId)({
|
|
42
37
|
dlg: args.dlg,
|
|
43
38
|
directive: args.directive,
|
|
@@ -280,6 +275,7 @@ async function inspectNoPromptSideDialogDrive(args) {
|
|
|
280
275
|
: undefined;
|
|
281
276
|
const explicitInterruptedResumeAllowed = args.driveOptions?.allowResumeFromInterrupted === true &&
|
|
282
277
|
latest?.executionMarker?.kind === 'interrupted';
|
|
278
|
+
const inProgressGenerationResumeAllowed = args.driveOptions?.resumeInProgressGeneration === true;
|
|
283
279
|
const supplyResponseParentReviveAllowed = source === 'kernel_driver_supply_response_parent_revive' &&
|
|
284
280
|
hasNoPromptSideDialogResumeEntitlement(args.dialog, args.driveOptions);
|
|
285
281
|
if (lastEvent?.type === 'tellask_anchor_record' && lastEvent.anchorRole === 'response') {
|
|
@@ -292,7 +288,9 @@ async function inspectNoPromptSideDialogDrive(args) {
|
|
|
292
288
|
lastEvent,
|
|
293
289
|
};
|
|
294
290
|
}
|
|
295
|
-
if (!explicitInterruptedResumeAllowed &&
|
|
291
|
+
if (!explicitInterruptedResumeAllowed &&
|
|
292
|
+
!inProgressGenerationResumeAllowed &&
|
|
293
|
+
!supplyResponseParentReviveAllowed) {
|
|
296
294
|
return {
|
|
297
295
|
shouldReject: true,
|
|
298
296
|
source,
|
|
@@ -578,7 +576,7 @@ async function executeDriveRound(args) {
|
|
|
578
576
|
: hasEntitledParentRevive
|
|
579
577
|
? await loadFreshSuspensionStatusFromPersistence(dialog, driveOptions)
|
|
580
578
|
: await dialog.getSuspensionStatus({
|
|
581
|
-
allowPendingSideDialogs:
|
|
579
|
+
allowPendingSideDialogs: driveOptions?.resumeInProgressGeneration === true,
|
|
582
580
|
});
|
|
583
581
|
const queuedPrompt = dialog.peekUpNext();
|
|
584
582
|
const queuedSideDialogPromptCanResume = dialog instanceof dialog_1.SideDialog && queuedPrompt !== undefined;
|
|
@@ -810,8 +808,7 @@ async function executeDriveRound(args) {
|
|
|
810
808
|
});
|
|
811
809
|
}
|
|
812
810
|
else {
|
|
813
|
-
|
|
814
|
-
if (!activePromptWasReplyToolReminder && !shouldDirectFallbackAfterParentRevive) {
|
|
811
|
+
if (!activePromptWasReplyToolReminder) {
|
|
815
812
|
const language = (0, work_language_1.getWorkLanguage)();
|
|
816
813
|
followUp =
|
|
817
814
|
sideDialogReplyTarget === undefined
|
|
@@ -846,7 +843,6 @@ async function executeDriveRound(args) {
|
|
|
846
843
|
dialogId: dialog.id.valueOf(),
|
|
847
844
|
targetCallId: activeTellaskReplyDirective.targetCallId,
|
|
848
845
|
targetOwnerDialogId: sideDialogReplyTarget?.ownerDialogId,
|
|
849
|
-
directFallbackAfterParentRevive: shouldDirectFallbackAfterParentRevive,
|
|
850
846
|
});
|
|
851
847
|
}
|
|
852
848
|
else {
|
|
@@ -1015,7 +1011,8 @@ async function executeDriveRound(args) {
|
|
|
1015
1011
|
: { skipTaskdoc: followUp.skipTaskdoc }),
|
|
1016
1012
|
};
|
|
1017
1013
|
if (followUp.kind === 'registered_assignment_update' ||
|
|
1018
|
-
followUp.kind === 'new_course_runtime_sideDialog'
|
|
1014
|
+
followUp.kind === 'new_course_runtime_sideDialog' ||
|
|
1015
|
+
followUp.kind === 'runtime_sideDialog_reply_reminder') {
|
|
1019
1016
|
const prompt = {
|
|
1020
1017
|
...runtimeCommon,
|
|
1021
1018
|
tellaskReplyDirective: followUp.tellaskReplyDirective,
|
|
@@ -1023,7 +1020,8 @@ async function executeDriveRound(args) {
|
|
|
1023
1020
|
};
|
|
1024
1021
|
return prompt;
|
|
1025
1022
|
}
|
|
1026
|
-
if (followUp.kind === 'new_course_runtime_reply'
|
|
1023
|
+
if (followUp.kind === 'new_course_runtime_reply' ||
|
|
1024
|
+
followUp.kind === 'runtime_reply_reminder') {
|
|
1027
1025
|
const prompt = {
|
|
1028
1026
|
...runtimeCommon,
|
|
1029
1027
|
tellaskReplyDirective: followUp.tellaskReplyDirective,
|
|
@@ -46,12 +46,14 @@ async function driveQueuedDialogsOnce() {
|
|
|
46
46
|
dialog_global_registry_1.globalDialogRegistry.noteActiveRunBlockedQueuedDrive(mainDialog.id.rootId);
|
|
47
47
|
continue;
|
|
48
48
|
}
|
|
49
|
-
|
|
49
|
+
const resumeInProgressGeneration = latest?.generating === true;
|
|
50
|
+
if (!resumeInProgressGeneration && !(await mainDialog.canDrive())) {
|
|
50
51
|
continue;
|
|
51
52
|
}
|
|
52
53
|
await (0, engine_1.driveDialogStream)(mainDialog, undefined, true, {
|
|
53
54
|
source: 'kernel_driver_backend_loop',
|
|
54
55
|
reason: 'global_dialog_registry_needs_drive',
|
|
56
|
+
...(resumeInProgressGeneration ? { resumeInProgressGeneration: true } : {}),
|
|
55
57
|
});
|
|
56
58
|
const status = await mainDialog.getSuspensionStatus();
|
|
57
59
|
const shouldStayQueued = mainDialog.hasUpNext() || !status.canDrive;
|
|
@@ -11,8 +11,6 @@ const interjection_pause_stop_1 = require("../../runtime/interjection-pause-stop
|
|
|
11
11
|
const reply_prompt_copy_1 = require("../../runtime/reply-prompt-copy");
|
|
12
12
|
const work_language_1 = require("../../runtime/work-language");
|
|
13
13
|
const tellask_special_1 = require("./tellask-special");
|
|
14
|
-
const REPLY_TOOL_REMINDER_PREFIX_EN = '[Dominds replyTellask required]';
|
|
15
|
-
const REPLY_TOOL_REMINDER_PREFIX_ZH = '[Dominds 必须调用回复工具]';
|
|
16
14
|
async function resolveReplyTargetAgentId(args) {
|
|
17
15
|
const mainDialog = args.dlg instanceof dialog_1.MainDialog
|
|
18
16
|
? args.dlg
|
|
@@ -30,13 +28,11 @@ async function resolveReplyTargetAgentId(args) {
|
|
|
30
28
|
function buildPromptContentWithExactReplyToolName(args) {
|
|
31
29
|
const isFbrSideDialog = args.dlg instanceof dialog_1.SideDialog &&
|
|
32
30
|
args.dlg.assignmentFromAsker.callName === 'freshBootsReasoning';
|
|
33
|
-
const noActivePrefix = args.language === 'zh'
|
|
34
|
-
? '[Dominds 当前无跨对话回复义务]'
|
|
35
|
-
: '[Dominds no active inter-dialog reply]';
|
|
31
|
+
const noActivePrefix = args.language === 'zh' ? reply_prompt_copy_1.NO_ACTIVE_REPLY_PREFIX_ZH : reply_prompt_copy_1.NO_ACTIVE_REPLY_PREFIX_EN;
|
|
36
32
|
const activePrefix = args.language === 'zh' ? reply_prompt_copy_1.ACTIVE_REPLY_TOOL_PREFIX_ZH : reply_prompt_copy_1.ACTIVE_REPLY_TOOL_PREFIX_EN;
|
|
37
33
|
const reminderPrefixes = [
|
|
38
|
-
REPLY_TOOL_REMINDER_PREFIX_EN,
|
|
39
|
-
REPLY_TOOL_REMINDER_PREFIX_ZH,
|
|
34
|
+
reply_prompt_copy_1.REPLY_TOOL_REMINDER_PREFIX_EN,
|
|
35
|
+
reply_prompt_copy_1.REPLY_TOOL_REMINDER_PREFIX_ZH,
|
|
40
36
|
reply_prompt_copy_1.REPLY_REASSERTION_PREFIX_EN,
|
|
41
37
|
reply_prompt_copy_1.REPLY_REASSERTION_PREFIX_ZH,
|
|
42
38
|
];
|
|
@@ -7,6 +7,7 @@ export type KernelDriverDriveSource = 'unspecified' | 'ws_user_message' | 'ws_us
|
|
|
7
7
|
export type KernelDriverDriveOptions = Readonly<{
|
|
8
8
|
suppressDiligencePush?: boolean;
|
|
9
9
|
allowResumeFromInterrupted?: boolean;
|
|
10
|
+
resumeInProgressGeneration?: boolean;
|
|
10
11
|
noPromptSideDialogResumeEntitlement?: Readonly<{
|
|
11
12
|
ownerDialogId: string;
|
|
12
13
|
reason: 'reply_tellask_back_delivered';
|
package/dist/persistence.js
CHANGED
|
@@ -3764,6 +3764,7 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
|
|
|
3764
3764
|
case 'pending_sideDialogs_reconciled_record':
|
|
3765
3765
|
case 'sideDialog_registry_reconciled_record':
|
|
3766
3766
|
case 'sideDialog_responses_reconciled_record':
|
|
3767
|
+
case 'tellask_anchor_record':
|
|
3767
3768
|
break;
|
|
3768
3769
|
case 'tellask_carryover_record': {
|
|
3769
3770
|
const base = {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function recoverProceedingDrivesAfterRestart(): Promise<void>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.recoverProceedingDrivesAfterRestart = recoverProceedingDrivesAfterRestart;
|
|
4
|
+
const dialog_display_state_1 = require("../dialog-display-state");
|
|
5
|
+
const dialog_global_registry_1 = require("../dialog-global-registry");
|
|
6
|
+
const dialog_instance_registry_1 = require("../dialog-instance-registry");
|
|
7
|
+
const kernel_driver_1 = require("../llm/kernel-driver");
|
|
8
|
+
const log_1 = require("../log");
|
|
9
|
+
const persistence_1 = require("../persistence");
|
|
10
|
+
const persistence_errors_1 = require("../persistence-errors");
|
|
11
|
+
const log = (0, log_1.createLogger)('proceeding-drive-recovery');
|
|
12
|
+
async function restoreDialogForProceedingDrive(dialogId) {
|
|
13
|
+
const mainDialog = await (0, dialog_instance_registry_1.getOrRestoreMainDialog)(dialogId.rootId, 'running');
|
|
14
|
+
if (!mainDialog) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
if (dialogId.selfId === dialogId.rootId) {
|
|
18
|
+
return mainDialog;
|
|
19
|
+
}
|
|
20
|
+
return await (0, dialog_instance_registry_1.ensureDialogLoaded)(mainDialog, dialogId, 'running');
|
|
21
|
+
}
|
|
22
|
+
async function recoverRootProceedingDrive(dialog) {
|
|
23
|
+
await persistence_1.DialogPersistence.setNeedsDrive(dialog.id, true, dialog.status);
|
|
24
|
+
dialog_global_registry_1.globalDialogRegistry.markNeedsDrive(dialog.id.rootId, {
|
|
25
|
+
source: 'restart_recovery',
|
|
26
|
+
reason: 'persisted_drive_in_progress',
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
async function recoverSideDialogProceedingDrive(dialog) {
|
|
30
|
+
await (0, kernel_driver_1.driveDialogStream)(dialog, undefined, true, {
|
|
31
|
+
source: 'kernel_driver_sideDialog_resume',
|
|
32
|
+
reason: 'restart_recovery:persisted_drive_in_progress',
|
|
33
|
+
resumeInProgressGeneration: true,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async function recoverProceedingDrivesAfterRestart() {
|
|
37
|
+
const dialogIds = await persistence_1.DialogPersistence.listAllDialogIds('running');
|
|
38
|
+
const recoveredRootIds = new Set();
|
|
39
|
+
const recoveredDialogKeys = new Set();
|
|
40
|
+
for (const dialogId of dialogIds) {
|
|
41
|
+
let latest;
|
|
42
|
+
try {
|
|
43
|
+
latest = await persistence_1.DialogPersistence.loadDialogLatest(dialogId, 'running');
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (!(0, persistence_errors_1.findDomindsPersistenceFileError)(error)) {
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
log.warn('Skipping malformed dialog during proceeding-drive restart recovery', error, {
|
|
50
|
+
dialogId: dialogId.valueOf(),
|
|
51
|
+
});
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (!(0, dialog_display_state_1.isRecoverableGeneratingLatest)(latest)) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const dialog = await restoreDialogForProceedingDrive(dialogId);
|
|
59
|
+
if (!dialog) {
|
|
60
|
+
log.warn('Proceeding-drive restart recovery could not restore dialog', undefined, {
|
|
61
|
+
rootId: dialogId.rootId,
|
|
62
|
+
selfId: dialogId.selfId,
|
|
63
|
+
});
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const dialogKey = dialog.id.key();
|
|
67
|
+
if (recoveredDialogKeys.has(dialogKey)) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
recoveredDialogKeys.add(dialogKey);
|
|
71
|
+
if (dialog.id.selfId === dialog.id.rootId) {
|
|
72
|
+
if (recoveredRootIds.has(dialog.id.rootId)) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
recoveredRootIds.add(dialog.id.rootId);
|
|
76
|
+
await recoverRootProceedingDrive(dialog);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
await recoverSideDialogProceedingDrive(dialog);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
log.error('Failed to recover proceeding drive after restart', error, {
|
|
84
|
+
rootId: dialogId.rootId,
|
|
85
|
+
selfId: dialogId.selfId,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -2,6 +2,10 @@ import type { LanguageCode } from '@longrun-ai/kernel/types/language';
|
|
|
2
2
|
import type { TellaskReplyDirective } from '@longrun-ai/kernel/types/storage';
|
|
3
3
|
export declare const ACTIVE_REPLY_TOOL_PREFIX_EN = "[Dominds active reply tool]";
|
|
4
4
|
export declare const ACTIVE_REPLY_TOOL_PREFIX_ZH = "[Dominds \u5F53\u524D\u56DE\u590D\u5DE5\u5177]";
|
|
5
|
+
export declare const NO_ACTIVE_REPLY_PREFIX_EN = "[Dominds no active inter-dialog reply]";
|
|
6
|
+
export declare const NO_ACTIVE_REPLY_PREFIX_ZH = "[Dominds \u5F53\u524D\u65E0\u8DE8\u5BF9\u8BDD\u56DE\u590D\u4E49\u52A1]";
|
|
7
|
+
export declare const REPLY_TOOL_REMINDER_PREFIX_EN = "[Dominds replyTellask required]";
|
|
8
|
+
export declare const REPLY_TOOL_REMINDER_PREFIX_ZH = "[Dominds \u5FC5\u987B\u8C03\u7528\u56DE\u590D\u5DE5\u5177]";
|
|
5
9
|
export declare const REPLY_REASSERTION_PREFIX_EN = "[Dominds long-line reminder]";
|
|
6
10
|
export declare const REPLY_REASSERTION_PREFIX_ZH = "[Dominds \u957F\u7EBF\u63D0\u9192]";
|
|
7
11
|
export declare const REPLY_SUPPRESSION_PREFIX_EN = "[Dominds handle this interjection first]";
|
|
@@ -30,8 +34,8 @@ export declare function buildReplyObligationReassertionText(args: ReplyObligatio
|
|
|
30
34
|
export declare function buildReplyToolReminderText(args: {
|
|
31
35
|
language: LanguageCode;
|
|
32
36
|
directive: TellaskReplyDirective;
|
|
33
|
-
prefix: string;
|
|
34
37
|
replyTargetAgentId?: string;
|
|
35
38
|
}): string;
|
|
39
|
+
export declare function isReplyToolReminderPromptContent(content: string): boolean;
|
|
36
40
|
export declare function isStandaloneRuntimeGuidePromptContent(content: string): boolean;
|
|
37
41
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.REPLY_SUPPRESSION_PREFIX_ZH = exports.REPLY_SUPPRESSION_PREFIX_EN = exports.REPLY_REASSERTION_PREFIX_ZH = exports.REPLY_REASSERTION_PREFIX_EN = exports.ACTIVE_REPLY_TOOL_PREFIX_ZH = exports.ACTIVE_REPLY_TOOL_PREFIX_EN = void 0;
|
|
3
|
+
exports.REPLY_SUPPRESSION_PREFIX_ZH = exports.REPLY_SUPPRESSION_PREFIX_EN = exports.REPLY_REASSERTION_PREFIX_ZH = exports.REPLY_REASSERTION_PREFIX_EN = exports.REPLY_TOOL_REMINDER_PREFIX_ZH = exports.REPLY_TOOL_REMINDER_PREFIX_EN = exports.NO_ACTIVE_REPLY_PREFIX_ZH = exports.NO_ACTIVE_REPLY_PREFIX_EN = exports.ACTIVE_REPLY_TOOL_PREFIX_ZH = exports.ACTIVE_REPLY_TOOL_PREFIX_EN = void 0;
|
|
4
4
|
exports.buildActiveReplyToolNote = buildActiveReplyToolNote;
|
|
5
5
|
exports.buildActiveReplyObligationContextText = buildActiveReplyObligationContextText;
|
|
6
6
|
exports.buildSideDialogCompletionRule = buildSideDialogCompletionRule;
|
|
@@ -8,10 +8,15 @@ exports.buildSideDialogRoleHeaderCopy = buildSideDialogRoleHeaderCopy;
|
|
|
8
8
|
exports.buildReplyObligationSuppressionGuideText = buildReplyObligationSuppressionGuideText;
|
|
9
9
|
exports.buildReplyObligationReassertionText = buildReplyObligationReassertionText;
|
|
10
10
|
exports.buildReplyToolReminderText = buildReplyToolReminderText;
|
|
11
|
+
exports.isReplyToolReminderPromptContent = isReplyToolReminderPromptContent;
|
|
11
12
|
exports.isStandaloneRuntimeGuidePromptContent = isStandaloneRuntimeGuidePromptContent;
|
|
12
13
|
const tellask_labels_1 = require("./tellask-labels");
|
|
13
14
|
exports.ACTIVE_REPLY_TOOL_PREFIX_EN = '[Dominds active reply tool]';
|
|
14
15
|
exports.ACTIVE_REPLY_TOOL_PREFIX_ZH = '[Dominds 当前回复工具]';
|
|
16
|
+
exports.NO_ACTIVE_REPLY_PREFIX_EN = '[Dominds no active inter-dialog reply]';
|
|
17
|
+
exports.NO_ACTIVE_REPLY_PREFIX_ZH = '[Dominds 当前无跨对话回复义务]';
|
|
18
|
+
exports.REPLY_TOOL_REMINDER_PREFIX_EN = '[Dominds replyTellask required]';
|
|
19
|
+
exports.REPLY_TOOL_REMINDER_PREFIX_ZH = '[Dominds 必须调用回复工具]';
|
|
15
20
|
exports.REPLY_REASSERTION_PREFIX_EN = '[Dominds long-line reminder]';
|
|
16
21
|
exports.REPLY_REASSERTION_PREFIX_ZH = '[Dominds 长线提醒]';
|
|
17
22
|
exports.REPLY_SUPPRESSION_PREFIX_EN = '[Dominds handle this interjection first]';
|
|
@@ -139,9 +144,10 @@ function buildReplyObligationReassertionText(args) {
|
|
|
139
144
|
].join('\n');
|
|
140
145
|
}
|
|
141
146
|
function buildReplyToolReminderText(args) {
|
|
147
|
+
const prefix = args.language === 'zh' ? exports.REPLY_TOOL_REMINDER_PREFIX_ZH : exports.REPLY_TOOL_REMINDER_PREFIX_EN;
|
|
142
148
|
return args.language === 'zh'
|
|
143
149
|
? [
|
|
144
|
-
|
|
150
|
+
prefix,
|
|
145
151
|
'',
|
|
146
152
|
`你刚才已经写了正文,但还没调用 \`${args.directive.expectedReplyCallName}\`。`,
|
|
147
153
|
'',
|
|
@@ -149,7 +155,7 @@ function buildReplyToolReminderText(args) {
|
|
|
149
155
|
'如果你再次直接输出最终消息而仍不调用该工具,运行时会按 direct-reply fallback 投递,并在 UI/传递正文中明确标注。',
|
|
150
156
|
].join('\n')
|
|
151
157
|
: [
|
|
152
|
-
|
|
158
|
+
prefix,
|
|
153
159
|
'',
|
|
154
160
|
`You already wrote the reply body, but you still have not called \`${args.directive.expectedReplyCallName}\`.`,
|
|
155
161
|
'',
|
|
@@ -157,6 +163,10 @@ function buildReplyToolReminderText(args) {
|
|
|
157
163
|
'If you still emit a plain final message without the tool, runtime will deliver it via direct-reply fallback and label that path explicitly in UI and transfer text.',
|
|
158
164
|
].join('\n');
|
|
159
165
|
}
|
|
166
|
+
function isReplyToolReminderPromptContent(content) {
|
|
167
|
+
return (content.startsWith(exports.REPLY_TOOL_REMINDER_PREFIX_ZH) ||
|
|
168
|
+
content.startsWith(exports.REPLY_TOOL_REMINDER_PREFIX_EN));
|
|
169
|
+
}
|
|
160
170
|
function isStandaloneRuntimeGuidePromptContent(content) {
|
|
161
171
|
return (content.startsWith(exports.REPLY_REASSERTION_PREFIX_ZH) ||
|
|
162
172
|
content.startsWith(exports.REPLY_REASSERTION_PREFIX_EN) ||
|
package/dist/server.d.ts
CHANGED
package/dist/server.js
CHANGED
|
@@ -50,6 +50,7 @@ const dialog_display_state_1 = require("./dialog-display-state");
|
|
|
50
50
|
const kernel_driver_1 = require("./llm/kernel-driver");
|
|
51
51
|
const log_1 = require("./log");
|
|
52
52
|
const supervisor_1 = require("./mcp/supervisor");
|
|
53
|
+
const proceeding_drive_1 = require("./recovery/proceeding-drive");
|
|
53
54
|
const reply_special_1 = require("./recovery/reply-special");
|
|
54
55
|
const work_language_1 = require("./runtime/work-language");
|
|
55
56
|
const auth_1 = require("./server/auth");
|
|
@@ -113,12 +114,53 @@ function parseArgs(argv) {
|
|
|
113
114
|
}
|
|
114
115
|
return out;
|
|
115
116
|
}
|
|
117
|
+
function attachPostListenStartupCancellation(httpServer, token) {
|
|
118
|
+
const originalStop = httpServer.stop.bind(httpServer);
|
|
119
|
+
httpServer.stop = async () => {
|
|
120
|
+
token.canceled = true;
|
|
121
|
+
await originalStop();
|
|
122
|
+
};
|
|
123
|
+
return httpServer;
|
|
124
|
+
}
|
|
116
125
|
function getErrnoCode(error) {
|
|
117
126
|
if (!(error instanceof Error))
|
|
118
127
|
return undefined;
|
|
119
128
|
const withCode = error;
|
|
120
129
|
return typeof withCode.code === 'string' ? withCode.code : undefined;
|
|
121
130
|
}
|
|
131
|
+
async function runPostListenStartup(params) {
|
|
132
|
+
await new Promise((resolve) => {
|
|
133
|
+
setImmediate(resolve);
|
|
134
|
+
});
|
|
135
|
+
if (params.token.canceled)
|
|
136
|
+
return;
|
|
137
|
+
// Apps host is optional for server boot: app failures must stay loud, but they must not block WebUI startup.
|
|
138
|
+
try {
|
|
139
|
+
await (0, runtime_1.initAppsRuntime)({ rtwsRootAbs: params.rtwsRootAbs, kernel: params.kernel });
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
if (params.token.canceled)
|
|
143
|
+
return;
|
|
144
|
+
log.warn('Apps runtime initialization failed during server startup; continuing without app runtime capabilities until the app issue is fixed', error instanceof Error ? error : new Error(String(error)));
|
|
145
|
+
}
|
|
146
|
+
if (params.token.canceled)
|
|
147
|
+
return;
|
|
148
|
+
// Crash recovery: persisted in-flight generations are re-queued; stale non-generating queues
|
|
149
|
+
// are surfaced as blocked/resumable from durable facts.
|
|
150
|
+
await (0, dialog_display_state_1.reconcileDisplayStatesAfterRestart)();
|
|
151
|
+
if (params.token.canceled)
|
|
152
|
+
return;
|
|
153
|
+
await (0, proceeding_drive_1.recoverProceedingDrivesAfterRestart)();
|
|
154
|
+
if (params.token.canceled)
|
|
155
|
+
return;
|
|
156
|
+
await (0, reply_special_1.recoverPendingReplyTellaskCallsAfterRestart)();
|
|
157
|
+
if (params.token.canceled)
|
|
158
|
+
return;
|
|
159
|
+
// Tests may opt out so the process can shut down cleanly without a driver stop API.
|
|
160
|
+
if (params.startBackendDriver) {
|
|
161
|
+
void (0, kernel_driver_1.runBackendDriver)();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
122
164
|
async function startServer(opts = {}) {
|
|
123
165
|
const { language: resolvedLanguage, source } = (0, work_language_1.resolveWorkLanguage)({ env: process.env });
|
|
124
166
|
(0, work_language_1.setWorkLanguage)(resolvedLanguage);
|
|
@@ -129,6 +171,7 @@ async function startServer(opts = {}) {
|
|
|
129
171
|
const portAutoDirection = opts.portAutoDirection ?? 'down';
|
|
130
172
|
const host = opts.host || '127.0.0.1';
|
|
131
173
|
const startBackendDriver = opts.startBackendDriver ?? true;
|
|
174
|
+
const returnAfterListen = opts.returnAfterListen === true;
|
|
132
175
|
const portCandidates = (0, port_selection_1.buildWebuiPortCandidates)({
|
|
133
176
|
preferredPort,
|
|
134
177
|
strictPort,
|
|
@@ -182,37 +225,48 @@ async function startServer(opts = {}) {
|
|
|
182
225
|
if (!strictPort && boundPort !== preferredPort) {
|
|
183
226
|
log.warn(`WebUI preferred port ${preferredPort} was unavailable; listening on ${boundPort}`);
|
|
184
227
|
}
|
|
228
|
+
const postListenStartupToken = { canceled: false };
|
|
229
|
+
const httpServer = attachPostListenStartupCancellation(startedCore, postListenStartupToken);
|
|
185
230
|
try {
|
|
231
|
+
const rtwsRootAbs = process.cwd();
|
|
186
232
|
(0, dominds_self_update_1.configureDomindsSelfUpdate)({
|
|
187
233
|
host,
|
|
188
234
|
port: boundPort,
|
|
189
235
|
mode: serverMode,
|
|
190
236
|
stopServer: async () => {
|
|
191
|
-
await
|
|
237
|
+
await httpServer.stop();
|
|
192
238
|
},
|
|
193
239
|
});
|
|
194
240
|
// MCP is best-effort: startup must not be blocked by MCP config/server issues.
|
|
195
|
-
(0, supervisor_1.startMcpSupervisor)();
|
|
196
|
-
// Apps host is optional for server boot: app failures must stay loud, but they must not block WebUI startup.
|
|
197
241
|
try {
|
|
198
|
-
|
|
242
|
+
(0, supervisor_1.startMcpSupervisor)();
|
|
199
243
|
}
|
|
200
244
|
catch (error) {
|
|
201
|
-
log.warn('
|
|
245
|
+
log.warn('MCP supervisor startup failed during server startup; continuing without MCP runtime capabilities until the MCP issue is fixed', error instanceof Error ? error : new Error(String(error)));
|
|
202
246
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
247
|
+
const postListenStartup = runPostListenStartup({
|
|
248
|
+
rtwsRootAbs,
|
|
249
|
+
kernel: { host, port: boundPort },
|
|
250
|
+
startBackendDriver,
|
|
251
|
+
token: postListenStartupToken,
|
|
252
|
+
});
|
|
253
|
+
if (returnAfterListen) {
|
|
254
|
+
void postListenStartup.catch((error) => {
|
|
255
|
+
log.error('Post-listen server startup failed; WebUI remains reachable, but runtime recovery/driver startup did not complete', error instanceof Error ? error : new Error(String(error)));
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
await postListenStartup;
|
|
209
260
|
}
|
|
210
261
|
}
|
|
211
262
|
catch (error) {
|
|
212
|
-
|
|
263
|
+
if (!returnAfterListen) {
|
|
264
|
+
await httpServer.stop();
|
|
265
|
+
await (0, runtime_1.shutdownAppsRuntime)();
|
|
266
|
+
}
|
|
213
267
|
throw error;
|
|
214
268
|
}
|
|
215
|
-
return { httpServer
|
|
269
|
+
return { httpServer, auth, host, port: boundPort, mode };
|
|
216
270
|
}
|
|
217
271
|
// Main function for CLI execution
|
|
218
272
|
async function main() {
|
|
@@ -240,7 +294,7 @@ async function main() {
|
|
|
240
294
|
const portAutoDirection = parsedPort?.portAutoDirection;
|
|
241
295
|
const host = cliArgs['H'] || undefined;
|
|
242
296
|
const mode = cliArgs['mode'] || undefined;
|
|
243
|
-
await startServer({ port, host, mode, strictPort, portAutoDirection });
|
|
297
|
+
await startServer({ port, host, mode, strictPort, portAutoDirection, returnAfterListen: true });
|
|
244
298
|
}
|
|
245
299
|
// Start server if this file is run directly
|
|
246
300
|
if (require.main === module) {
|
package/dist/tools/cmd-runner.js
CHANGED
|
@@ -37,18 +37,13 @@ class ScrollingBuffer {
|
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
function sendIpc(msg) {
|
|
41
|
-
if (typeof process.send !== 'function') {
|
|
42
|
-
throw new Error('cmd_runner must be launched with an IPC channel');
|
|
43
|
-
}
|
|
44
|
-
process.send(msg);
|
|
45
|
-
}
|
|
46
40
|
async function flushIpc(msg) {
|
|
47
|
-
|
|
41
|
+
const send = process.send;
|
|
42
|
+
if (typeof send !== 'function') {
|
|
48
43
|
throw new Error('cmd_runner must be launched with an IPC channel');
|
|
49
44
|
}
|
|
50
45
|
await new Promise((resolve, reject) => {
|
|
51
|
-
|
|
46
|
+
send.call(process, msg, (error) => {
|
|
52
47
|
if (error) {
|
|
53
48
|
reject(error);
|
|
54
49
|
return;
|
|
@@ -120,6 +115,16 @@ async function ensureSocketParentDir(endpoint) {
|
|
|
120
115
|
function writeSocketResponse(socket, response) {
|
|
121
116
|
socket.end(`${JSON.stringify(response)}\n`);
|
|
122
117
|
}
|
|
118
|
+
function isProcessAlive(pid) {
|
|
119
|
+
try {
|
|
120
|
+
process.kill(pid, 0);
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
const code = typeof error === 'object' && error !== null ? error.code : undefined;
|
|
125
|
+
return code !== 'ESRCH';
|
|
126
|
+
}
|
|
127
|
+
}
|
|
123
128
|
async function main() {
|
|
124
129
|
const initMessage = await new Promise((resolve, reject) => {
|
|
125
130
|
const timeout = setTimeout(() => {
|
|
@@ -139,8 +144,12 @@ async function main() {
|
|
|
139
144
|
if (typeof daemonPid !== 'number') {
|
|
140
145
|
throw new Error('cmd_runner failed to spawn daemon command: missing pid');
|
|
141
146
|
}
|
|
147
|
+
const stdout = childProcess.stdout;
|
|
148
|
+
const stderr = childProcess.stderr;
|
|
149
|
+
if (stdout === null || stderr === null) {
|
|
150
|
+
throw new Error('cmd_runner failed to spawn daemon command with piped stdout/stderr');
|
|
151
|
+
}
|
|
142
152
|
const endpoint = (0, cmd_runner_protocol_1.getCmdRunnerEndpointForDaemonPid)(daemonPid);
|
|
143
|
-
await ensureSocketParentDir(endpoint);
|
|
144
153
|
const state = {
|
|
145
154
|
endpoint,
|
|
146
155
|
daemonPid,
|
|
@@ -157,6 +166,46 @@ async function main() {
|
|
|
157
166
|
let server;
|
|
158
167
|
let closeRequested = false;
|
|
159
168
|
let timeoutHandle;
|
|
169
|
+
let initialResultSent = false;
|
|
170
|
+
const tryFlushInitialResult = async (msg) => {
|
|
171
|
+
if (initialResultSent) {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
initialResultSent = true;
|
|
175
|
+
await flushIpc(msg);
|
|
176
|
+
return true;
|
|
177
|
+
};
|
|
178
|
+
const waitForObservedChildExitOrMissingPid = async (timeoutMs) => {
|
|
179
|
+
if (!state.isRunning || closeRequested || !isProcessAlive(daemonPid)) {
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
return await new Promise((resolve) => {
|
|
183
|
+
let settled = false;
|
|
184
|
+
let timeout;
|
|
185
|
+
let interval;
|
|
186
|
+
const finish = (exited) => {
|
|
187
|
+
if (settled)
|
|
188
|
+
return;
|
|
189
|
+
settled = true;
|
|
190
|
+
clearTimeout(timeout);
|
|
191
|
+
clearInterval(interval);
|
|
192
|
+
childProcess.off('close', onClose);
|
|
193
|
+
resolve(exited || !state.isRunning || closeRequested || !isProcessAlive(daemonPid));
|
|
194
|
+
};
|
|
195
|
+
const onClose = () => {
|
|
196
|
+
finish(true);
|
|
197
|
+
};
|
|
198
|
+
timeout = setTimeout(() => {
|
|
199
|
+
finish(false);
|
|
200
|
+
}, timeoutMs);
|
|
201
|
+
interval = setInterval(() => {
|
|
202
|
+
if (!isProcessAlive(daemonPid)) {
|
|
203
|
+
finish(true);
|
|
204
|
+
}
|
|
205
|
+
}, 25);
|
|
206
|
+
childProcess.once('close', onClose);
|
|
207
|
+
});
|
|
208
|
+
};
|
|
160
209
|
const closeServerAndExit = (code) => {
|
|
161
210
|
if (closeRequested) {
|
|
162
211
|
return;
|
|
@@ -204,8 +253,8 @@ async function main() {
|
|
|
204
253
|
state.exitCode = code;
|
|
205
254
|
state.exitSignal = signal;
|
|
206
255
|
void (async () => {
|
|
207
|
-
if (state.daemonCommandLine === null) {
|
|
208
|
-
await
|
|
256
|
+
if (state.daemonCommandLine === null && !initialResultSent) {
|
|
257
|
+
await tryFlushInitialResult({
|
|
209
258
|
type: 'completed',
|
|
210
259
|
exitCode: code,
|
|
211
260
|
exitSignal: signal,
|
|
@@ -222,7 +271,7 @@ async function main() {
|
|
|
222
271
|
if (timeoutHandle) {
|
|
223
272
|
clearTimeout(timeoutHandle);
|
|
224
273
|
}
|
|
225
|
-
void
|
|
274
|
+
void tryFlushInitialResult({
|
|
226
275
|
type: 'failed',
|
|
227
276
|
errorText: error.message,
|
|
228
277
|
})
|
|
@@ -231,12 +280,16 @@ async function main() {
|
|
|
231
280
|
closeServerAndExit(1);
|
|
232
281
|
});
|
|
233
282
|
});
|
|
234
|
-
|
|
283
|
+
stdout.on('data', (data) => {
|
|
235
284
|
state.stdout.addText(data.toString());
|
|
236
285
|
});
|
|
237
|
-
|
|
286
|
+
stderr.on('data', (data) => {
|
|
238
287
|
state.stderr.addText(data.toString());
|
|
239
288
|
});
|
|
289
|
+
await ensureSocketParentDir(endpoint);
|
|
290
|
+
if (closeRequested) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
240
293
|
server = node_net_1.default.createServer((socket) => {
|
|
241
294
|
socket.setEncoding('utf8');
|
|
242
295
|
let buffer = '';
|
|
@@ -309,6 +362,9 @@ async function main() {
|
|
|
309
362
|
return;
|
|
310
363
|
}
|
|
311
364
|
if (daemonCommandLine === undefined || daemonCommandLine.trim() === '') {
|
|
365
|
+
if (await waitForObservedChildExitOrMissingPid(250)) {
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
312
368
|
try {
|
|
313
369
|
process.kill(daemonPid, 'SIGTERM');
|
|
314
370
|
}
|
|
@@ -318,7 +374,7 @@ async function main() {
|
|
|
318
374
|
if (!state.isRunning) {
|
|
319
375
|
return;
|
|
320
376
|
}
|
|
321
|
-
|
|
377
|
+
await tryFlushInitialResult({
|
|
322
378
|
type: 'failed',
|
|
323
379
|
errorText: `failed to capture daemon command line from OS for pid ${String(daemonPid)}`,
|
|
324
380
|
});
|
|
@@ -328,7 +384,7 @@ async function main() {
|
|
|
328
384
|
return;
|
|
329
385
|
}
|
|
330
386
|
state.daemonCommandLine = daemonCommandLine;
|
|
331
|
-
|
|
387
|
+
await tryFlushInitialResult({
|
|
332
388
|
type: 'daemonized',
|
|
333
389
|
daemonPid,
|
|
334
390
|
daemonCommandLine,
|
|
@@ -339,7 +395,10 @@ async function main() {
|
|
|
339
395
|
startTime: state.startTime,
|
|
340
396
|
});
|
|
341
397
|
})().catch((error) => {
|
|
342
|
-
|
|
398
|
+
if (initialResultSent) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
void tryFlushInitialResult({
|
|
343
402
|
type: 'failed',
|
|
344
403
|
errorText: error instanceof Error ? error.message : String(error),
|
|
345
404
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dominds",
|
|
3
|
-
"version": "1.23.
|
|
3
|
+
"version": "1.23.2",
|
|
4
4
|
"description": "Dominds CLI and aggregation shell for the LongRun AI kernel/runtime packages.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"publishConfig": {
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
"ws": "^8.19.0",
|
|
53
53
|
"yaml": "^2.8.2",
|
|
54
54
|
"zod": "^4.3.6",
|
|
55
|
-
"@longrun-ai/codex-auth": "0.13.0",
|
|
56
55
|
"@longrun-ai/kernel": "1.13.1",
|
|
56
|
+
"@longrun-ai/codex-auth": "0.13.0",
|
|
57
57
|
"@longrun-ai/shell": "1.13.1"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|