dominds 1.27.2 → 1.27.4
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-fork.js +2 -1
- package/dist/dialog-global-registry.d.ts +11 -1
- package/dist/dialog-global-registry.js +45 -0
- package/dist/dialog.d.ts +14 -5
- package/dist/dialog.js +114 -21
- 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 +228 -49
- package/dist/llm/kernel-driver/fbr.d.ts +9 -0
- package/dist/llm/kernel-driver/fbr.js +186 -59
- package/dist/mcp/supervisor.js +4 -1
- package/dist/minds/load.js +1 -0
- package/dist/minds/system-prompt-parts.js +30 -30
- package/dist/persistence.js +83 -17
- package/dist/priming.js +2 -3
- package/dist/runtime/driver-messages.d.ts +9 -0
- package/dist/runtime/driver-messages.js +103 -33
- package/dist/runtime/shared-reminder-update-impact.d.ts +20 -0
- package/dist/runtime/shared-reminder-update-impact.js +110 -0
- package/dist/shared-reminders.js +2 -2
- package/dist/tool-availability.js +1 -0
- package/dist/tool.d.ts +7 -4
- package/dist/tool.js +10 -4
- package/dist/tools/app-reminders.js +4 -3
- 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 +183 -6
- package/dist/tools/os.js +115 -14
- package/dist/tools/pending-tellask-reminder.js +1 -0
- 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 +4 -4
- package/dist/tools/prompts/control/en/principles.md +22 -21
- package/dist/tools/prompts/control/en/scenarios.md +10 -3
- package/dist/tools/prompts/control/en/tools.md +28 -5
- package/dist/tools/prompts/control/zh/errors.md +1 -1
- package/dist/tools/prompts/control/zh/index.md +4 -4
- package/dist/tools/prompts/control/zh/principles.md +21 -20
- package/dist/tools/prompts/control/zh/scenarios.md +10 -3
- package/dist/tools/prompts/control/zh/tools.md +28 -5
- 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
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dispatchSharedReminderUpdateImpact = dispatchSharedReminderUpdateImpact;
|
|
4
|
+
exports.dispatchSharedReminderMigrationImpact = dispatchSharedReminderMigrationImpact;
|
|
5
|
+
const id_1 = require("@longrun-ai/kernel/utils/id");
|
|
6
|
+
const dialog_global_registry_1 = require("../dialog-global-registry");
|
|
7
|
+
const driver_messages_1 = require("./driver-messages");
|
|
8
|
+
function sharedReminderUpdateImpactsDialog(args) {
|
|
9
|
+
if (args.candidate.id.equals(args.updater.id)) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
if (args.candidate.agentId !== args.updater.agentId) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
return args.scope === 'task' ? args.candidate.taskDocPath === args.updater.taskDocPath : true;
|
|
16
|
+
}
|
|
17
|
+
function collectSharedReminderUpdatePeerDialogs(args) {
|
|
18
|
+
const peers = [];
|
|
19
|
+
for (const candidate of dialog_global_registry_1.globalDialogRegistry.getLoadedInFlightDialogsForSharedReminderImpact()) {
|
|
20
|
+
if (sharedReminderUpdateImpactsDialog({
|
|
21
|
+
scope: args.scope,
|
|
22
|
+
updater: args.updater,
|
|
23
|
+
candidate,
|
|
24
|
+
})) {
|
|
25
|
+
peers.push(candidate);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return peers;
|
|
29
|
+
}
|
|
30
|
+
async function queueSharedReminderUpdateImpactPrompt(args) {
|
|
31
|
+
await args.targetDialog.queueRuntimeGuidePrompt({
|
|
32
|
+
prompt: (0, driver_messages_1.formatSharedReminderUpdateImpactNotice)(args.language, {
|
|
33
|
+
reminderId: args.reminderId,
|
|
34
|
+
scope: args.scope,
|
|
35
|
+
audience: 'peer',
|
|
36
|
+
}),
|
|
37
|
+
msgId: (0, id_1.generateShortId)(),
|
|
38
|
+
grammar: 'markdown',
|
|
39
|
+
userLanguageCode: args.language,
|
|
40
|
+
skipTaskdoc: true,
|
|
41
|
+
});
|
|
42
|
+
dialog_global_registry_1.globalDialogRegistry.queueRootDrive(args.targetDialog.id.rootId, {
|
|
43
|
+
source: 'shared_reminder_update_impact',
|
|
44
|
+
reason: `reminder_id:${args.reminderId}`,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
async function queueSharedReminderMigrationImpactPrompt(args) {
|
|
48
|
+
await args.targetDialog.queueRuntimeGuidePrompt({
|
|
49
|
+
prompt: (0, driver_messages_1.formatSharedReminderMigrationImpactNotice)(args.language, {
|
|
50
|
+
reminderId: args.reminderId,
|
|
51
|
+
scope: args.scope,
|
|
52
|
+
}),
|
|
53
|
+
msgId: (0, id_1.generateShortId)(),
|
|
54
|
+
grammar: 'markdown',
|
|
55
|
+
userLanguageCode: args.language,
|
|
56
|
+
skipTaskdoc: true,
|
|
57
|
+
});
|
|
58
|
+
dialog_global_registry_1.globalDialogRegistry.queueRootDrive(args.targetDialog.id.rootId, {
|
|
59
|
+
source: 'shared_reminder_migration_impact',
|
|
60
|
+
reason: `migrated_reminder_id:${args.reminderId}`,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
async function dispatchSharedReminderUpdateImpact(args) {
|
|
64
|
+
const peerDialogs = collectSharedReminderUpdatePeerDialogs({
|
|
65
|
+
updater: args.updater,
|
|
66
|
+
scope: args.scope,
|
|
67
|
+
});
|
|
68
|
+
if (peerDialogs.length === 0) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
let dispatchedDialogCount = 0;
|
|
72
|
+
for (const peerDialog of peerDialogs) {
|
|
73
|
+
await queueSharedReminderUpdateImpactPrompt({
|
|
74
|
+
targetDialog: peerDialog,
|
|
75
|
+
reminderId: args.reminderId,
|
|
76
|
+
scope: args.scope,
|
|
77
|
+
language: args.language,
|
|
78
|
+
});
|
|
79
|
+
dispatchedDialogCount += 1;
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
scope: args.scope,
|
|
83
|
+
peerDialogCount: peerDialogs.length,
|
|
84
|
+
dispatchedDialogCount,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
async function dispatchSharedReminderMigrationImpact(args) {
|
|
88
|
+
const peerDialogs = collectSharedReminderUpdatePeerDialogs({
|
|
89
|
+
updater: args.updater,
|
|
90
|
+
scope: args.scope,
|
|
91
|
+
});
|
|
92
|
+
if (peerDialogs.length === 0) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
let dispatchedDialogCount = 0;
|
|
96
|
+
for (const peerDialog of peerDialogs) {
|
|
97
|
+
await queueSharedReminderMigrationImpactPrompt({
|
|
98
|
+
targetDialog: peerDialog,
|
|
99
|
+
reminderId: args.reminderId,
|
|
100
|
+
scope: args.scope,
|
|
101
|
+
language: args.language,
|
|
102
|
+
});
|
|
103
|
+
dispatchedDialogCount += 1;
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
scope: args.scope,
|
|
107
|
+
peerDialogCount: peerDialogs.length,
|
|
108
|
+
dispatchedDialogCount,
|
|
109
|
+
};
|
|
110
|
+
}
|
package/dist/shared-reminders.js
CHANGED
|
@@ -106,8 +106,8 @@ function serializeReminder(reminder) {
|
|
|
106
106
|
ownerName: reminder.owner?.name,
|
|
107
107
|
meta: reminder.meta,
|
|
108
108
|
echoback: reminder.echoback,
|
|
109
|
-
scope: reminder.scope
|
|
110
|
-
renderMode: reminder.renderMode
|
|
109
|
+
scope: reminder.scope,
|
|
110
|
+
renderMode: reminder.renderMode,
|
|
111
111
|
createdAt: reminder.createdAt ?? (0, time_1.formatUnifiedTimestamp)(new Date()),
|
|
112
112
|
priority: reminder.priority ?? 'medium',
|
|
113
113
|
};
|
package/dist/tool.d.ts
CHANGED
|
@@ -50,7 +50,11 @@ type PreparedRawToolArguments = Readonly<{
|
|
|
50
50
|
}>;
|
|
51
51
|
export interface ReminderOptions {
|
|
52
52
|
readonly echoback?: boolean;
|
|
53
|
-
readonly scope
|
|
53
|
+
readonly scope: ReminderScope;
|
|
54
|
+
readonly renderMode: ReminderRenderMode;
|
|
55
|
+
}
|
|
56
|
+
export interface ReminderUpdateOptions {
|
|
57
|
+
readonly echoback?: boolean;
|
|
54
58
|
readonly renderMode?: ReminderRenderMode;
|
|
55
59
|
}
|
|
56
60
|
export type ReminderScope = 'dialog' | 'task' | 'agent' | 'runtime';
|
|
@@ -63,7 +67,6 @@ export interface Reminder extends ReminderOptions {
|
|
|
63
67
|
readonly meta?: JsonValue;
|
|
64
68
|
readonly createdAt?: string;
|
|
65
69
|
readonly priority?: ReminderPriority;
|
|
66
|
-
readonly renderMode?: ReminderRenderMode;
|
|
67
70
|
}
|
|
68
71
|
export declare function reminderEchoBackEnabled(reminder: Reminder): boolean;
|
|
69
72
|
export declare function reminderIsVirtual(reminder: Reminder): boolean;
|
|
@@ -75,10 +78,10 @@ export declare function materializeReminder(input: Readonly<{
|
|
|
75
78
|
owner?: ReminderOwner;
|
|
76
79
|
meta?: JsonValue;
|
|
77
80
|
echoback?: boolean;
|
|
78
|
-
scope
|
|
81
|
+
scope: ReminderScope;
|
|
79
82
|
createdAt?: string;
|
|
80
83
|
priority?: ReminderPriority;
|
|
81
|
-
renderMode
|
|
84
|
+
renderMode: ReminderRenderMode;
|
|
82
85
|
}>): Reminder;
|
|
83
86
|
export declare function cloneReminder(reminder: Reminder): Reminder;
|
|
84
87
|
export declare function computeReminderRenderRevision(reminder: Reminder): string;
|
package/dist/tool.js
CHANGED
|
@@ -63,16 +63,22 @@ function ensureReminderId(value) {
|
|
|
63
63
|
return trimmed && trimmed.length > 0 ? trimmed : generateReminderId();
|
|
64
64
|
}
|
|
65
65
|
function materializeReminder(input) {
|
|
66
|
+
if (input.scope === undefined) {
|
|
67
|
+
throw new Error('materializeReminder requires explicit scope');
|
|
68
|
+
}
|
|
69
|
+
if (input.renderMode === undefined) {
|
|
70
|
+
throw new Error('materializeReminder requires explicit renderMode');
|
|
71
|
+
}
|
|
66
72
|
return {
|
|
67
73
|
id: ensureReminderId(input.id),
|
|
68
74
|
content: input.content,
|
|
69
75
|
owner: input.owner,
|
|
70
76
|
meta: input.meta,
|
|
71
77
|
echoback: input.echoback,
|
|
72
|
-
scope: input.scope
|
|
78
|
+
scope: input.scope,
|
|
73
79
|
createdAt: input.createdAt,
|
|
74
80
|
priority: input.priority,
|
|
75
|
-
renderMode: input.renderMode
|
|
81
|
+
renderMode: input.renderMode,
|
|
76
82
|
};
|
|
77
83
|
}
|
|
78
84
|
function cloneReminder(reminder) {
|
|
@@ -94,8 +100,8 @@ function computeReminderRenderRevision(reminder) {
|
|
|
94
100
|
content: reminder.content,
|
|
95
101
|
meta: reminder.meta ?? null,
|
|
96
102
|
echoback: reminder.echoback ?? true,
|
|
97
|
-
scope: reminder.scope
|
|
98
|
-
renderMode: reminder.renderMode
|
|
103
|
+
scope: reminder.scope,
|
|
104
|
+
renderMode: reminder.renderMode,
|
|
99
105
|
});
|
|
100
106
|
return `sha256:${(0, crypto_1.createHash)('sha256').update(payload, 'utf8').digest('hex')}`;
|
|
101
107
|
}
|
|
@@ -139,7 +139,7 @@ function toReminderState(reminder) {
|
|
|
139
139
|
content: reminder.content,
|
|
140
140
|
meta: extractOwnerMeta(reminder.meta),
|
|
141
141
|
echoback: reminder.echoback,
|
|
142
|
-
renderMode: reminder.renderMode
|
|
142
|
+
renderMode: reminder.renderMode,
|
|
143
143
|
};
|
|
144
144
|
}
|
|
145
145
|
function findOwnedReminderEntries(dlg, descriptor, owner) {
|
|
@@ -201,7 +201,7 @@ async function persistAndPublishReminders(dlg) {
|
|
|
201
201
|
renderRevision: (0, tool_1.computeReminderRenderRevision)(reminder),
|
|
202
202
|
echoback: (0, tool_1.reminderEchoBackEnabled)(reminder),
|
|
203
203
|
scope: reminder.scope,
|
|
204
|
-
renderMode: reminder.renderMode
|
|
204
|
+
renderMode: reminder.renderMode,
|
|
205
205
|
}));
|
|
206
206
|
const evt = { type: 'full_reminders_update', reminders };
|
|
207
207
|
(0, evt_registry_1.postDialogEvent)(dlg, evt);
|
|
@@ -321,6 +321,7 @@ async function applyAppReminderRequests(dlg, params) {
|
|
|
321
321
|
case 'add': {
|
|
322
322
|
dlg.addReminder(result.reminder.content, owner, buildAppReminderMeta(descriptor, result.reminder.meta), normalizeInsertPosition(dlg.reminders.length, result.position), {
|
|
323
323
|
echoback: result.reminder.echoback,
|
|
324
|
+
scope: 'dialog',
|
|
324
325
|
renderMode: result.reminder.renderMode ?? 'markdown',
|
|
325
326
|
});
|
|
326
327
|
changed = true;
|
|
@@ -334,7 +335,7 @@ async function applyAppReminderRequests(dlg, params) {
|
|
|
334
335
|
dlg.updateReminder(target.index, result.reminder.content, buildAppReminderMeta(descriptor, result.reminder.meta), {
|
|
335
336
|
echoback: result.reminder.echoback,
|
|
336
337
|
// Preserve the existing render mode when the app does not explicitly override it.
|
|
337
|
-
renderMode: result.reminder.renderMode ?? target.reminder.renderMode
|
|
338
|
+
renderMode: result.reminder.renderMode ?? target.reminder.renderMode,
|
|
338
339
|
});
|
|
339
340
|
changed = true;
|
|
340
341
|
break;
|
package/dist/tools/builtins.js
CHANGED
|
@@ -118,6 +118,7 @@ function manualSpecFor(toolsetId) {
|
|
|
118
118
|
(0, registry_1.registerTool)(ctrl_1.addReminderTool);
|
|
119
119
|
(0, registry_1.registerTool)(ctrl_1.deleteReminderTool);
|
|
120
120
|
(0, registry_1.registerTool)(ctrl_1.updateReminderTool);
|
|
121
|
+
(0, registry_1.registerTool)(ctrl_1.migrateReminderTool);
|
|
121
122
|
(0, registry_1.registerTool)(ctrl_1.clearMindTool);
|
|
122
123
|
(0, registry_1.registerTool)(ctrl_1.doMindTool);
|
|
123
124
|
(0, registry_1.registerTool)(ctrl_1.changeMindTool);
|
|
@@ -190,6 +191,7 @@ for (const tool of team_mgmt_1.teamMgmtTools) {
|
|
|
190
191
|
ctrl_1.addReminderTool,
|
|
191
192
|
ctrl_1.deleteReminderTool,
|
|
192
193
|
ctrl_1.updateReminderTool,
|
|
194
|
+
ctrl_1.migrateReminderTool,
|
|
193
195
|
ctrl_1.clearMindTool,
|
|
194
196
|
ctrl_1.doMindTool,
|
|
195
197
|
ctrl_1.changeMindTool,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare const MAX_CMD_RUNNER_OUTPUT_WAIT_TIMEOUT_MS: number;
|
|
1
2
|
export type CmdRunnerSpawnSpec = Readonly<{
|
|
2
3
|
command: string;
|
|
3
4
|
args: string[];
|
|
@@ -38,6 +39,8 @@ export type CmdRunnerRequest = Readonly<{
|
|
|
38
39
|
type: 'get_output';
|
|
39
40
|
stdout: boolean;
|
|
40
41
|
stderr: boolean;
|
|
42
|
+
waitForNewOutput: boolean;
|
|
43
|
+
timeoutMs?: number;
|
|
41
44
|
}> | Readonly<{
|
|
42
45
|
type: 'stop';
|
|
43
46
|
entirePg: boolean;
|
|
@@ -45,7 +48,9 @@ export type CmdRunnerRequest = Readonly<{
|
|
|
45
48
|
export type CmdRunnerStreamSnapshot = Readonly<{
|
|
46
49
|
content: string;
|
|
47
50
|
linesScrolledOut: number;
|
|
51
|
+
version: number;
|
|
48
52
|
}>;
|
|
53
|
+
export type CmdRunnerOutputWaitStatus = 'output' | 'timeout' | 'exited';
|
|
49
54
|
export type CmdRunnerStatusPayload = Readonly<{
|
|
50
55
|
daemonPid: number;
|
|
51
56
|
daemonCommandLine: string;
|
|
@@ -69,6 +74,7 @@ export type CmdRunnerResponse = (Readonly<{
|
|
|
69
74
|
}> & CmdRunnerStatusPayload) | (Readonly<{
|
|
70
75
|
type: 'output';
|
|
71
76
|
ok: true;
|
|
77
|
+
waitStatus?: CmdRunnerOutputWaitStatus;
|
|
72
78
|
}> & CmdRunnerStatusPayload) | (Readonly<{
|
|
73
79
|
type: 'stop_result';
|
|
74
80
|
ok: true;
|
|
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MAX_CMD_RUNNER_OUTPUT_WAIT_TIMEOUT_MS = void 0;
|
|
6
7
|
exports.parseCmdRunnerInitMessage = parseCmdRunnerInitMessage;
|
|
7
8
|
exports.parseCmdRunnerInitialIpcMessage = parseCmdRunnerInitialIpcMessage;
|
|
8
9
|
exports.parseCmdRunnerRequestLine = parseCmdRunnerRequestLine;
|
|
@@ -10,6 +11,7 @@ exports.parseCmdRunnerResponseLine = parseCmdRunnerResponseLine;
|
|
|
10
11
|
exports.getCmdRunnerEndpointForDaemonPid = getCmdRunnerEndpointForDaemonPid;
|
|
11
12
|
const node_os_1 = __importDefault(require("node:os"));
|
|
12
13
|
const node_path_1 = __importDefault(require("node:path"));
|
|
14
|
+
exports.MAX_CMD_RUNNER_OUTPUT_WAIT_TIMEOUT_MS = 24 * 60 * 60 * 1_000;
|
|
13
15
|
function isRecord(value) {
|
|
14
16
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
15
17
|
}
|
|
@@ -33,13 +35,39 @@ function parseStreamSnapshot(raw, label) {
|
|
|
33
35
|
}
|
|
34
36
|
const content = asString(raw['content']);
|
|
35
37
|
const linesScrolledOut = asNumber(raw['linesScrolledOut']);
|
|
38
|
+
const version = asNumber(raw['version']);
|
|
36
39
|
if (content === null) {
|
|
37
40
|
throw new Error(`Invalid cmd_runner ${label}.content: expected string`);
|
|
38
41
|
}
|
|
39
42
|
if (linesScrolledOut === null) {
|
|
40
43
|
throw new Error(`Invalid cmd_runner ${label}.linesScrolledOut: expected number`);
|
|
41
44
|
}
|
|
42
|
-
|
|
45
|
+
if (version === null) {
|
|
46
|
+
throw new Error(`Invalid cmd_runner ${label}.version: expected number`);
|
|
47
|
+
}
|
|
48
|
+
return { content, linesScrolledOut, version };
|
|
49
|
+
}
|
|
50
|
+
function parseOptionalTimeoutMs(raw, label) {
|
|
51
|
+
if (raw === undefined) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
const value = asNumber(raw);
|
|
55
|
+
if (value === null ||
|
|
56
|
+
!Number.isInteger(value) ||
|
|
57
|
+
value < 0 ||
|
|
58
|
+
value > exports.MAX_CMD_RUNNER_OUTPUT_WAIT_TIMEOUT_MS) {
|
|
59
|
+
throw new Error(`Invalid cmd_runner ${label}: expected non-negative integer <= ${String(exports.MAX_CMD_RUNNER_OUTPUT_WAIT_TIMEOUT_MS)}`);
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
function parseOutputWaitStatus(raw) {
|
|
64
|
+
if (raw === undefined) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
if (raw === 'output' || raw === 'timeout' || raw === 'exited') {
|
|
68
|
+
return raw;
|
|
69
|
+
}
|
|
70
|
+
throw new Error(`Invalid cmd_runner output waitStatus: ${String(raw)}`);
|
|
43
71
|
}
|
|
44
72
|
function parseStatusPayload(raw) {
|
|
45
73
|
const daemonPid = asNumber(raw['daemonPid']);
|
|
@@ -239,10 +267,28 @@ function parseCmdRunnerRequestLine(line) {
|
|
|
239
267
|
if (type === 'get_output') {
|
|
240
268
|
const stdout = asBoolean(raw['stdout']);
|
|
241
269
|
const stderr = asBoolean(raw['stderr']);
|
|
270
|
+
const waitForNewOutputRaw = raw['waitForNewOutput'];
|
|
271
|
+
const waitForNewOutput = waitForNewOutputRaw === undefined ? false : asBoolean(waitForNewOutputRaw);
|
|
272
|
+
const timeoutMs = parseOptionalTimeoutMs(raw['timeoutMs'], 'get_output.timeoutMs');
|
|
242
273
|
if (stdout === null || stderr === null) {
|
|
243
274
|
throw new Error('Invalid cmd_runner get_output request: stdout/stderr must be boolean');
|
|
244
275
|
}
|
|
245
|
-
|
|
276
|
+
if (waitForNewOutput === null) {
|
|
277
|
+
throw new Error('Invalid cmd_runner get_output request: waitForNewOutput must be boolean');
|
|
278
|
+
}
|
|
279
|
+
if (!stdout && !stderr) {
|
|
280
|
+
throw new Error('Invalid cmd_runner get_output request: at least one stream is required');
|
|
281
|
+
}
|
|
282
|
+
if (!waitForNewOutput && timeoutMs !== undefined) {
|
|
283
|
+
throw new Error('Invalid cmd_runner get_output request: timeoutMs requires waitForNewOutput=true');
|
|
284
|
+
}
|
|
285
|
+
return {
|
|
286
|
+
type,
|
|
287
|
+
stdout,
|
|
288
|
+
stderr,
|
|
289
|
+
waitForNewOutput,
|
|
290
|
+
...(timeoutMs === undefined ? {} : { timeoutMs }),
|
|
291
|
+
};
|
|
246
292
|
}
|
|
247
293
|
throw new Error(`Invalid cmd_runner request type: ${String(type)}`);
|
|
248
294
|
}
|
|
@@ -269,6 +315,15 @@ function parseCmdRunnerResponseLine(line) {
|
|
|
269
315
|
if (type !== 'pong' && type !== 'status' && type !== 'output' && type !== 'stop_result') {
|
|
270
316
|
throw new Error(`Invalid cmd_runner response type: ${String(type)}`);
|
|
271
317
|
}
|
|
318
|
+
if (type === 'output') {
|
|
319
|
+
const waitStatus = parseOutputWaitStatus(raw['waitStatus']);
|
|
320
|
+
return {
|
|
321
|
+
type,
|
|
322
|
+
ok: true,
|
|
323
|
+
...(waitStatus === undefined ? {} : { waitStatus }),
|
|
324
|
+
...parseStatusPayload(raw),
|
|
325
|
+
};
|
|
326
|
+
}
|
|
272
327
|
return {
|
|
273
328
|
type,
|
|
274
329
|
ok: true,
|
package/dist/tools/cmd-runner.js
CHANGED
|
@@ -17,10 +17,15 @@ class ScrollingBuffer {
|
|
|
17
17
|
maxLines;
|
|
18
18
|
lines = [];
|
|
19
19
|
linesScrolledOut = 0;
|
|
20
|
+
version = 0;
|
|
20
21
|
constructor(maxLines) {
|
|
21
22
|
this.maxLines = maxLines;
|
|
22
23
|
}
|
|
23
24
|
addText(text) {
|
|
25
|
+
if (text.length === 0) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
this.version += 1;
|
|
24
29
|
const newLines = text.split('\n');
|
|
25
30
|
if (newLines[newLines.length - 1] === '') {
|
|
26
31
|
newLines.pop();
|
|
@@ -37,8 +42,12 @@ class ScrollingBuffer {
|
|
|
37
42
|
return {
|
|
38
43
|
content: this.lines.join('\n'),
|
|
39
44
|
linesScrolledOut: this.linesScrolledOut,
|
|
45
|
+
version: this.version,
|
|
40
46
|
};
|
|
41
47
|
}
|
|
48
|
+
getVersion() {
|
|
49
|
+
return this.version;
|
|
50
|
+
}
|
|
42
51
|
}
|
|
43
52
|
async function flushIpc(msg) {
|
|
44
53
|
const send = process.send;
|
|
@@ -177,6 +186,64 @@ async function main() {
|
|
|
177
186
|
let closeRequested = false;
|
|
178
187
|
let timeoutHandle;
|
|
179
188
|
let initialResultSent = false;
|
|
189
|
+
const outputWaiters = [];
|
|
190
|
+
const requestedOutputChanged = (waiter) => (waiter.stdout && state.stdout.getVersion() !== waiter.initialStdoutVersion) ||
|
|
191
|
+
(waiter.stderr && state.stderr.getVersion() !== waiter.initialStderrVersion);
|
|
192
|
+
const removeOutputWaiter = (waiter) => {
|
|
193
|
+
const index = outputWaiters.indexOf(waiter);
|
|
194
|
+
if (index !== -1) {
|
|
195
|
+
outputWaiters.splice(index, 1);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
const settleOutputWaiter = (waiter, status) => {
|
|
199
|
+
removeOutputWaiter(waiter);
|
|
200
|
+
if (waiter.timeoutHandle !== undefined) {
|
|
201
|
+
clearTimeout(waiter.timeoutHandle);
|
|
202
|
+
}
|
|
203
|
+
waiter.resolve(status);
|
|
204
|
+
};
|
|
205
|
+
const notifyOutputWaiters = () => {
|
|
206
|
+
for (const waiter of [...outputWaiters]) {
|
|
207
|
+
if (requestedOutputChanged(waiter)) {
|
|
208
|
+
settleOutputWaiter(waiter, 'output');
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
if (!state.isRunning) {
|
|
212
|
+
settleOutputWaiter(waiter, 'exited');
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
const waitForRequestedNewOutput = async (request, socket) => {
|
|
217
|
+
if (!state.isRunning) {
|
|
218
|
+
return 'exited';
|
|
219
|
+
}
|
|
220
|
+
return await new Promise((resolve) => {
|
|
221
|
+
let waiter;
|
|
222
|
+
const onSocketClosed = () => {
|
|
223
|
+
if (waiter !== undefined) {
|
|
224
|
+
settleOutputWaiter(waiter, 'client_closed');
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
waiter = {
|
|
228
|
+
stdout: request.stdout,
|
|
229
|
+
stderr: request.stderr,
|
|
230
|
+
initialStdoutVersion: state.stdout.getVersion(),
|
|
231
|
+
initialStderrVersion: state.stderr.getVersion(),
|
|
232
|
+
resolve: (status) => {
|
|
233
|
+
socket.off('close', onSocketClosed);
|
|
234
|
+
resolve(status);
|
|
235
|
+
},
|
|
236
|
+
};
|
|
237
|
+
if (request.timeoutMs !== undefined) {
|
|
238
|
+
waiter.timeoutHandle = setTimeout(() => {
|
|
239
|
+
settleOutputWaiter(waiter, 'timeout');
|
|
240
|
+
}, request.timeoutMs);
|
|
241
|
+
}
|
|
242
|
+
socket.once('close', onSocketClosed);
|
|
243
|
+
outputWaiters.push(waiter);
|
|
244
|
+
notifyOutputWaiters();
|
|
245
|
+
});
|
|
246
|
+
};
|
|
180
247
|
const tryFlushInitialResult = async (msg) => {
|
|
181
248
|
if (initialResultSent) {
|
|
182
249
|
return false;
|
|
@@ -262,6 +329,7 @@ async function main() {
|
|
|
262
329
|
state.isRunning = false;
|
|
263
330
|
state.exitCode = code;
|
|
264
331
|
state.exitSignal = signal;
|
|
332
|
+
notifyOutputWaiters();
|
|
265
333
|
void (async () => {
|
|
266
334
|
if (state.daemonCommandLine === null && !initialResultSent) {
|
|
267
335
|
await tryFlushInitialResult({
|
|
@@ -292,9 +360,11 @@ async function main() {
|
|
|
292
360
|
});
|
|
293
361
|
stdout.on('data', (data) => {
|
|
294
362
|
state.stdout.addText(data.toString());
|
|
363
|
+
notifyOutputWaiters();
|
|
295
364
|
});
|
|
296
365
|
stderr.on('data', (data) => {
|
|
297
366
|
state.stderr.addText(data.toString());
|
|
367
|
+
notifyOutputWaiters();
|
|
298
368
|
});
|
|
299
369
|
await ensureSocketParentDir(endpoint);
|
|
300
370
|
if (closeRequested) {
|
|
@@ -331,13 +401,24 @@ async function main() {
|
|
|
331
401
|
return;
|
|
332
402
|
}
|
|
333
403
|
if (request.type === 'get_output') {
|
|
404
|
+
const waitStatus = request.waitForNewOutput
|
|
405
|
+
? await waitForRequestedNewOutput(request, socket)
|
|
406
|
+
: undefined;
|
|
407
|
+
if (waitStatus === 'client_closed') {
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
334
410
|
const payload = buildStatusPayload(state);
|
|
335
411
|
writeSocketResponse(socket, {
|
|
336
412
|
type: 'output',
|
|
337
413
|
ok: true,
|
|
414
|
+
...(waitStatus === undefined ? {} : { waitStatus }),
|
|
338
415
|
...payload,
|
|
339
|
-
stdout: request.stdout
|
|
340
|
-
|
|
416
|
+
stdout: request.stdout
|
|
417
|
+
? payload.stdout
|
|
418
|
+
: { content: '', linesScrolledOut: 0, version: 0 },
|
|
419
|
+
stderr: request.stderr
|
|
420
|
+
? payload.stderr
|
|
421
|
+
: { content: '', linesScrolledOut: 0, version: 0 },
|
|
341
422
|
});
|
|
342
423
|
return;
|
|
343
424
|
}
|
package/dist/tools/ctrl.d.ts
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* - add_reminder: Add a reminder
|
|
13
13
|
* - delete_reminder: Delete a reminder by id
|
|
14
14
|
* - update_reminder: Update reminder content
|
|
15
|
+
* - migrate_reminder: Move a visible shared reminder back into the current dialog
|
|
15
16
|
* - clear_mind: Start a new course, optionally add a reminder
|
|
16
17
|
* - do_mind: Main Dialog only; create a new `.tsk/` Taskdoc section without starting a new course
|
|
17
18
|
* - change_mind: Main Dialog only; update a `.tsk/` Taskdoc section without starting a new course
|
|
@@ -32,6 +33,7 @@ import { type FuncTool } from '../tool';
|
|
|
32
33
|
export declare const deleteReminderTool: FuncTool;
|
|
33
34
|
export declare const addReminderTool: FuncTool;
|
|
34
35
|
export declare const updateReminderTool: FuncTool;
|
|
36
|
+
export declare const migrateReminderTool: FuncTool;
|
|
35
37
|
export declare const clearMindTool: FuncTool;
|
|
36
38
|
export declare const changeMindTool: FuncTool;
|
|
37
39
|
export declare const doMindTool: FuncTool;
|