clideck 1.31.6 → 1.31.8
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/bin/clideck.js +51 -1
- package/clideck-agents-cli.js +85 -0
- package/clideck-ask-cli.js +112 -2
- package/package.json +1 -1
- package/server.js +6 -0
- package/session-agents.js +53 -0
- package/session-ask.js +36 -5
package/bin/clideck.js
CHANGED
|
@@ -1,8 +1,58 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
const args = process.argv.slice(2);
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
function usage() {
|
|
5
|
+
const version = require('../package.json').version;
|
|
6
|
+
return [
|
|
7
|
+
`CliDeck v${version}`,
|
|
8
|
+
'',
|
|
9
|
+
'Usage:',
|
|
10
|
+
' clideck [--host <host>] [--port <port>]',
|
|
11
|
+
' clideck agents [--json]',
|
|
12
|
+
' clideck ask --session <name-or-id> --message <text> [--timeout 10m]',
|
|
13
|
+
'',
|
|
14
|
+
'Options:',
|
|
15
|
+
' --host <host> Host to bind. Default: 127.0.0.1. Use 0.0.0.0 for LAN access.',
|
|
16
|
+
' --port <port> Port to use. Default: 4000. Can also use CLIDECK_PORT.',
|
|
17
|
+
' -h, --help Show this help.',
|
|
18
|
+
' -v, --version Show version.',
|
|
19
|
+
'',
|
|
20
|
+
'Agent tools:',
|
|
21
|
+
' clideck agents',
|
|
22
|
+
' Lists active sessions in the same project as the caller session.',
|
|
23
|
+
' Use this first when an agent needs to discover who it can ask.',
|
|
24
|
+
'',
|
|
25
|
+
' clideck ask',
|
|
26
|
+
' Use from inside a CliDeck session when one agent needs an answer from another session.',
|
|
27
|
+
'',
|
|
28
|
+
'Ask behavior:',
|
|
29
|
+
' Target lookup is limited to the same project as the caller session.',
|
|
30
|
+
' CliDeck sends the message into the real target terminal, presses Enter, waits for the',
|
|
31
|
+
' target to finish, then prints the target agent response to stdout.',
|
|
32
|
+
'',
|
|
33
|
+
'Examples:',
|
|
34
|
+
' clideck agents',
|
|
35
|
+
' clideck agents --json',
|
|
36
|
+
' clideck ask --session "Reviewer" --message "Review my changes and return only findings."',
|
|
37
|
+
' clideck ask "research manager" "Check this plan and tell me what is missing." --timeout 15m',
|
|
38
|
+
' cat notes.md | clideck ask --session "Docs Writer" --timeout 10m',
|
|
39
|
+
'',
|
|
40
|
+
'Notes for agents:',
|
|
41
|
+
' Run `clideck agents` to discover available same-project sessions.',
|
|
42
|
+
' Run `clideck ask --help` for the exact ask command contract.',
|
|
43
|
+
' If the target name has spaces, quote it.',
|
|
44
|
+
' If several sessions have the same name in the same project, use the session id.',
|
|
45
|
+
].join('\n');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (args[0] === 'agents') {
|
|
49
|
+
require('../clideck-agents-cli').run(args.slice(1));
|
|
50
|
+
} else if (args[0] === 'ask') {
|
|
5
51
|
require('../clideck-ask-cli').run(args.slice(1));
|
|
52
|
+
} else if (args.includes('--help') || args.includes('-h')) {
|
|
53
|
+
console.log(usage());
|
|
54
|
+
} else if (args.includes('--version') || args.includes('-v')) {
|
|
55
|
+
console.log(require('../package.json').version);
|
|
6
56
|
} else {
|
|
7
57
|
require('../server.js');
|
|
8
58
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const http = require('http');
|
|
2
|
+
const https = require('https');
|
|
3
|
+
|
|
4
|
+
function usage() {
|
|
5
|
+
return [
|
|
6
|
+
'Usage:',
|
|
7
|
+
' clideck agents [--json]',
|
|
8
|
+
'',
|
|
9
|
+
'Lists active CliDeck sessions in the same project as the caller session.',
|
|
10
|
+
'Use this from inside a CliDeck session before `clideck ask` to discover target names.',
|
|
11
|
+
'',
|
|
12
|
+
'Options:',
|
|
13
|
+
' --json Print machine-readable JSON.',
|
|
14
|
+
' --url <url> CliDeck server URL. Default: CLIDECK_URL or http://127.0.0.1:<port>.',
|
|
15
|
+
' -h, --help Show this help.',
|
|
16
|
+
].join('\n');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function parseArgs(args) {
|
|
20
|
+
const port = process.env.CLIDECK_PORT || process.env.PORT || '4000';
|
|
21
|
+
const out = { json: false, url: process.env.CLIDECK_URL || `http://127.0.0.1:${port}` };
|
|
22
|
+
for (let i = 0; i < args.length; i++) {
|
|
23
|
+
const arg = args[i];
|
|
24
|
+
if (arg === '--json') out.json = true;
|
|
25
|
+
else if (arg === '--url') out.url = args[++i];
|
|
26
|
+
else if (arg === '--help' || arg === '-h') out.help = true;
|
|
27
|
+
else throw new Error(`Unknown argument: ${arg}`);
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getJson(url, callerSessionId) {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
const target = new URL('/api/session/agents', url);
|
|
35
|
+
target.searchParams.set('callerSessionId', callerSessionId);
|
|
36
|
+
const client = target.protocol === 'https:' ? https : http;
|
|
37
|
+
const req = client.get(target, (res) => {
|
|
38
|
+
let data = '';
|
|
39
|
+
res.setEncoding('utf8');
|
|
40
|
+
res.on('data', chunk => { data += chunk; });
|
|
41
|
+
res.on('end', () => {
|
|
42
|
+
let parsed = {};
|
|
43
|
+
try { parsed = data ? JSON.parse(data) : {}; } catch {}
|
|
44
|
+
if (res.statusCode >= 400) {
|
|
45
|
+
const err = new Error(parsed.error || `CliDeck agents failed (${res.statusCode})`);
|
|
46
|
+
err.statusCode = res.statusCode;
|
|
47
|
+
return reject(err);
|
|
48
|
+
}
|
|
49
|
+
resolve(parsed);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
req.on('error', reject);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function formatAgents(agents) {
|
|
57
|
+
if (!agents.length) return 'No active sessions found in this project.';
|
|
58
|
+
return agents.map(a => {
|
|
59
|
+
const marker = a.caller ? 'self' : 'peer';
|
|
60
|
+
const status = a.working ? 'working' : 'idle';
|
|
61
|
+
const preview = a.lastPreview ? ` - ${a.lastPreview}` : '';
|
|
62
|
+
return `${a.name} (${marker}, ${a.preset}, ${status}) id=${a.id}${preview}`;
|
|
63
|
+
}).join('\n');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function run(args) {
|
|
67
|
+
try {
|
|
68
|
+
const opts = parseArgs(args);
|
|
69
|
+
if (opts.help) {
|
|
70
|
+
console.log(usage());
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const callerSessionId = process.env.CLIDECK_SESSION_ID || '';
|
|
74
|
+
if (!callerSessionId) throw new Error('CLIDECK_SESSION_ID is missing. Run this from inside a CliDeck session.');
|
|
75
|
+
|
|
76
|
+
const res = await getJson(opts.url, callerSessionId);
|
|
77
|
+
if (opts.json) process.stdout.write(JSON.stringify(res.agents || [], null, 2) + '\n');
|
|
78
|
+
else process.stdout.write(formatAgents(res.agents || []) + '\n');
|
|
79
|
+
} catch (e) {
|
|
80
|
+
process.stderr.write(`${e.message}\n`);
|
|
81
|
+
process.exitCode = 1;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = { run, parseArgs, formatAgents };
|
package/clideck-ask-cli.js
CHANGED
|
@@ -6,6 +6,19 @@ function usage() {
|
|
|
6
6
|
'Usage:',
|
|
7
7
|
' clideck ask --session <name-or-id> --message <text> [--timeout 10m]',
|
|
8
8
|
' clideck ask <name-or-id> <message> [--timeout 10m]',
|
|
9
|
+
' cat file.txt | clideck ask --session <name-or-id> [--timeout 10m]',
|
|
10
|
+
'',
|
|
11
|
+
'Use from inside a CliDeck session when this agent needs an answer from another active session.',
|
|
12
|
+
'Target lookup is limited to the same project as the caller session.',
|
|
13
|
+
'Run `clideck agents` first to discover available target sessions.',
|
|
14
|
+
'',
|
|
15
|
+
'Options:',
|
|
16
|
+
' -s, --session <name-or-id> Target session name or id.',
|
|
17
|
+
' -m, --message <text> Message to send. If omitted, stdin is used.',
|
|
18
|
+
' -t, --timeout <duration> Wait time. Examples: 30s, 10m, 1h. Default: 10m.',
|
|
19
|
+
' --url <url> CliDeck server URL. Default: CLIDECK_URL or local port.',
|
|
20
|
+
' --no-progress Do not print waiting hints to stderr.',
|
|
21
|
+
' -h, --help Show this help.',
|
|
9
22
|
].join('\n');
|
|
10
23
|
}
|
|
11
24
|
|
|
@@ -21,7 +34,7 @@ function parseDuration(value) {
|
|
|
21
34
|
|
|
22
35
|
function parseArgs(args) {
|
|
23
36
|
const port = process.env.CLIDECK_PORT || process.env.PORT || '4000';
|
|
24
|
-
const out = { timeoutMs: 10 * 60 * 1000, url: process.env.CLIDECK_URL || `http://127.0.0.1:${port}
|
|
37
|
+
const out = { timeoutMs: 10 * 60 * 1000, url: process.env.CLIDECK_URL || `http://127.0.0.1:${port}`, progress: true };
|
|
25
38
|
const positional = [];
|
|
26
39
|
for (let i = 0; i < args.length; i++) {
|
|
27
40
|
const arg = args[i];
|
|
@@ -32,6 +45,7 @@ function parseArgs(args) {
|
|
|
32
45
|
if (!parsed) throw new Error('Invalid timeout value');
|
|
33
46
|
out.timeoutMs = parsed;
|
|
34
47
|
} else if (arg === '--url') out.url = args[++i];
|
|
48
|
+
else if (arg === '--no-progress') out.progress = false;
|
|
35
49
|
else if (arg === '--help' || arg === '-h') out.help = true;
|
|
36
50
|
else positional.push(arg);
|
|
37
51
|
}
|
|
@@ -50,6 +64,101 @@ function readStdinIfAvailable() {
|
|
|
50
64
|
});
|
|
51
65
|
}
|
|
52
66
|
|
|
67
|
+
function formatDuration(ms) {
|
|
68
|
+
const totalSeconds = Math.max(0, Math.round(ms / 1000));
|
|
69
|
+
if (totalSeconds < 60) return `${totalSeconds}s`;
|
|
70
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
71
|
+
const seconds = totalSeconds % 60;
|
|
72
|
+
if (minutes < 60) return seconds ? `${minutes}m ${seconds}s` : `${minutes}m`;
|
|
73
|
+
const hours = Math.floor(minutes / 60);
|
|
74
|
+
const restMinutes = minutes % 60;
|
|
75
|
+
return restMinutes ? `${hours}h ${restMinutes}m` : `${hours}h`;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function oneLine(text, max = 160) {
|
|
79
|
+
const compact = String(text || '').replace(/\s+/g, ' ').trim();
|
|
80
|
+
return compact.length > max ? compact.slice(0, max - 1) + '…' : compact;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function getJson(url, path, timeoutMs = 5000) {
|
|
84
|
+
return new Promise((resolve, reject) => {
|
|
85
|
+
const target = new URL(path, url);
|
|
86
|
+
const client = target.protocol === 'https:' ? https : http;
|
|
87
|
+
const req = client.get(target, { timeout: timeoutMs }, (res) => {
|
|
88
|
+
let data = '';
|
|
89
|
+
res.setEncoding('utf8');
|
|
90
|
+
res.on('data', chunk => { data += chunk; });
|
|
91
|
+
res.on('end', () => {
|
|
92
|
+
let parsed = {};
|
|
93
|
+
try { parsed = data ? JSON.parse(data) : {}; } catch {}
|
|
94
|
+
if (res.statusCode >= 400) {
|
|
95
|
+
const err = new Error(parsed.error || `CliDeck request failed (${res.statusCode})`);
|
|
96
|
+
err.statusCode = res.statusCode;
|
|
97
|
+
return reject(err);
|
|
98
|
+
}
|
|
99
|
+
resolve(parsed);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
req.on('timeout', () => req.destroy(new Error('CliDeck progress check timed out')));
|
|
103
|
+
req.on('error', reject);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function findAgent(agents, target) {
|
|
108
|
+
const text = String(target || '').trim();
|
|
109
|
+
if (!text) return null;
|
|
110
|
+
const byId = agents.filter(a => a.id === text);
|
|
111
|
+
if (byId.length === 1) return byId[0];
|
|
112
|
+
const exact = agents.filter(a => a.name === text);
|
|
113
|
+
if (exact.length === 1) return exact[0];
|
|
114
|
+
const lower = text.toLowerCase();
|
|
115
|
+
const insensitive = agents.filter(a => String(a.name || '').toLowerCase() === lower);
|
|
116
|
+
return insensitive.length === 1 ? insensitive[0] : null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function startProgressHints(opts, callerSessionId) {
|
|
120
|
+
if (!opts.progress) return () => {};
|
|
121
|
+
const started = Date.now();
|
|
122
|
+
let stopped = false;
|
|
123
|
+
let lastLine = '';
|
|
124
|
+
|
|
125
|
+
const write = (line) => {
|
|
126
|
+
if (!line || line === lastLine) return;
|
|
127
|
+
lastLine = line;
|
|
128
|
+
process.stderr.write(`${line}\n`);
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
write(`[clideck ask] sent to "${opts.session}". waiting up to ${formatDuration(opts.timeoutMs)}. keep waiting until this command exits.`);
|
|
132
|
+
|
|
133
|
+
const tick = async () => {
|
|
134
|
+
if (stopped) return;
|
|
135
|
+
try {
|
|
136
|
+
const path = `/api/session/agents?callerSessionId=${encodeURIComponent(callerSessionId)}`;
|
|
137
|
+
const res = await getJson(opts.url, path, 4000);
|
|
138
|
+
const agent = findAgent(res.agents || [], opts.session);
|
|
139
|
+
const elapsed = formatDuration(Date.now() - started);
|
|
140
|
+
if (!agent) {
|
|
141
|
+
write(`[clideck ask] still waiting for "${opts.session}" (${elapsed} elapsed).`);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const status = agent.working ? 'working' : 'idle/capturing answer';
|
|
145
|
+
const preview = oneLine(agent.lastPreview);
|
|
146
|
+
write(`[clideck ask] "${agent.name}" is ${status} (${elapsed} elapsed).${preview ? ` latest: ${preview}` : ''}`);
|
|
147
|
+
} catch {
|
|
148
|
+
const elapsed = formatDuration(Date.now() - started);
|
|
149
|
+
write(`[clideck ask] still waiting for "${opts.session}" (${elapsed} elapsed).`);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const first = setTimeout(tick, 5000);
|
|
154
|
+
const interval = setInterval(tick, 15000);
|
|
155
|
+
return () => {
|
|
156
|
+
stopped = true;
|
|
157
|
+
clearTimeout(first);
|
|
158
|
+
clearInterval(interval);
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
53
162
|
function postJson(url, payload, timeoutMs) {
|
|
54
163
|
return new Promise((resolve, reject) => {
|
|
55
164
|
const target = new URL('/api/session/ask', url);
|
|
@@ -95,12 +204,13 @@ async function run(args) {
|
|
|
95
204
|
const callerSessionId = process.env.CLIDECK_SESSION_ID || '';
|
|
96
205
|
if (!callerSessionId) throw new Error('CLIDECK_SESSION_ID is missing. Run this from inside a CliDeck session.');
|
|
97
206
|
|
|
207
|
+
const stopProgress = startProgressHints(opts, callerSessionId);
|
|
98
208
|
const res = await postJson(opts.url, {
|
|
99
209
|
callerSessionId,
|
|
100
210
|
target: opts.session,
|
|
101
211
|
message: opts.message,
|
|
102
212
|
timeoutMs: opts.timeoutMs,
|
|
103
|
-
}, opts.timeoutMs);
|
|
213
|
+
}, opts.timeoutMs).finally(stopProgress);
|
|
104
214
|
process.stdout.write((res.response || '').trimEnd() + '\n');
|
|
105
215
|
} catch (e) {
|
|
106
216
|
process.stderr.write(`${e.message}\n`);
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -237,6 +237,12 @@ const server = http.createServer((req, res) => {
|
|
|
237
237
|
return;
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
+
// Agent discovery bridge used by the `clideck agents` CLI command.
|
|
241
|
+
if (req.method === 'GET' && req.url.startsWith('/api/session/agents')) {
|
|
242
|
+
require('./session-agents').handleHttp(req, res, sessions);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
240
246
|
// DEBUG: log any POST (agents might use /v1/traces, /v1/metrics, or other paths)
|
|
241
247
|
if (req.method === 'POST') {
|
|
242
248
|
// console.log(`OTLP: received POST ${req.url} (not handled)`);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
function sendJson(res, status, payload) {
|
|
2
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
3
|
+
res.end(JSON.stringify(payload));
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function isLoopback(req) {
|
|
7
|
+
const addr = req.socket?.remoteAddress || '';
|
|
8
|
+
return addr === '::1' || addr === '127.0.0.1' || addr.startsWith('127.') || addr.startsWith('::ffff:127.');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function sameProject(a, b) {
|
|
12
|
+
return (a.projectId || null) === (b.projectId || null);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function listProjectAgents(callerSessionId, sessionsApi) {
|
|
16
|
+
const sessions = sessionsApi.getSessions();
|
|
17
|
+
const callerId = String(callerSessionId || '').trim();
|
|
18
|
+
const caller = sessions.get(callerId);
|
|
19
|
+
if (!caller) {
|
|
20
|
+
const err = new Error('Caller session is not active');
|
|
21
|
+
err.status = 404;
|
|
22
|
+
throw err;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return [...sessions]
|
|
26
|
+
.filter(([, s]) => sameProject(caller, s))
|
|
27
|
+
.map(([id, s]) => ({
|
|
28
|
+
id,
|
|
29
|
+
name: s.name || id.slice(0, 8),
|
|
30
|
+
preset: s.presetId || 'shell',
|
|
31
|
+
working: !!s.working,
|
|
32
|
+
lastPreview: s.lastPreview || '',
|
|
33
|
+
lastActivityAt: s.lastActivityAt || null,
|
|
34
|
+
caller: id === callerId,
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function handleHttp(req, res, sessionsApi) {
|
|
39
|
+
try {
|
|
40
|
+
if (!isLoopback(req)) {
|
|
41
|
+
const err = new Error('CliDeck agents only accepts local requests');
|
|
42
|
+
err.status = 403;
|
|
43
|
+
throw err;
|
|
44
|
+
}
|
|
45
|
+
const url = new URL(req.url, 'http://127.0.0.1');
|
|
46
|
+
const agents = listProjectAgents(url.searchParams.get('callerSessionId'), sessionsApi);
|
|
47
|
+
sendJson(res, 200, { agents });
|
|
48
|
+
} catch (e) {
|
|
49
|
+
sendJson(res, e.status || 500, { error: e.message || 'CliDeck agents failed' });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
module.exports = { handleHttp, listProjectAgents };
|
package/session-ask.js
CHANGED
|
@@ -78,6 +78,38 @@ function latestAgentTextSince(sessionId, sinceTs) {
|
|
|
78
78
|
return entries.length ? entries[entries.length - 1].text : '';
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
function previewTextSince(session, sinceTs) {
|
|
82
|
+
const text = String(session?.lastPreview || '').trim();
|
|
83
|
+
if (!text) return '';
|
|
84
|
+
const ts = Date.parse(session.lastActivityAt || '');
|
|
85
|
+
return Number.isFinite(ts) && ts >= sinceTs ? text : '';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function latestAnswerTextSince(sessions, sessionId, sinceTs) {
|
|
89
|
+
return latestAgentTextSince(sessionId, sinceTs)
|
|
90
|
+
|| previewTextSince(sessions.get(sessionId), sinceTs);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function askSubmitDelay(message) {
|
|
94
|
+
const len = String(message || '').length;
|
|
95
|
+
return Math.min(2500, Math.max(500, 300 + Math.ceil(len / 80) * 100));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function submitAskInput(sessionsApi, targetId, message) {
|
|
99
|
+
const sessions = sessionsApi.getSessions();
|
|
100
|
+
const timers = [];
|
|
101
|
+
|
|
102
|
+
sessionsApi.input({ id: targetId, data: message });
|
|
103
|
+
const delay = askSubmitDelay(message);
|
|
104
|
+
timers.push(setTimeout(() => sessionsApi.input({ id: targetId, data: '\r' }), delay));
|
|
105
|
+
timers.push(setTimeout(() => {
|
|
106
|
+
const target = sessions.get(targetId);
|
|
107
|
+
if (target && !target.working) sessionsApi.input({ id: targetId, data: '\r' });
|
|
108
|
+
}, delay + 1500));
|
|
109
|
+
|
|
110
|
+
return () => timers.forEach(clearTimeout);
|
|
111
|
+
}
|
|
112
|
+
|
|
81
113
|
function waitForAnswer({ sessionsApi, targetId, sinceTs, timeoutMs }) {
|
|
82
114
|
const sessions = sessionsApi.getSessions();
|
|
83
115
|
const target = sessions.get(targetId);
|
|
@@ -95,7 +127,7 @@ function waitForAnswer({ sessionsApi, targetId, sinceTs, timeoutMs }) {
|
|
|
95
127
|
};
|
|
96
128
|
const finish = () => {
|
|
97
129
|
if (settled) return;
|
|
98
|
-
const response =
|
|
130
|
+
const response = latestAnswerTextSince(sessions, targetId, sinceTs);
|
|
99
131
|
if (!response) return;
|
|
100
132
|
settled = true;
|
|
101
133
|
cleanup();
|
|
@@ -149,10 +181,9 @@ async function askSession(payload, sessionsApi) {
|
|
|
149
181
|
const injected = `[CliDeck ask from ${caller.name || callerId.slice(0, 8)}]\n\n${message}`;
|
|
150
182
|
|
|
151
183
|
console.log(`[ask] ${caller.name || callerId.slice(0, 8)} -> ${target.name || targetId.slice(0, 8)} (${timeoutMs}ms timeout)`);
|
|
152
|
-
sessionsApi
|
|
153
|
-
setTimeout(() => sessionsApi.input({ id: targetId, data: '\r' }), 150);
|
|
184
|
+
const cancelSubmit = submitAskInput(sessionsApi, targetId, injected);
|
|
154
185
|
|
|
155
|
-
const response = await waitForAnswer({ sessionsApi, targetId, sinceTs, timeoutMs });
|
|
186
|
+
const response = await waitForAnswer({ sessionsApi, targetId, sinceTs, timeoutMs }).finally(cancelSubmit);
|
|
156
187
|
console.log(`[ask] completed ${target.name || targetId.slice(0, 8)} -> ${caller.name || callerId.slice(0, 8)}`);
|
|
157
188
|
return { targetSessionId: targetId, targetName: target.name, response };
|
|
158
189
|
}
|
|
@@ -168,4 +199,4 @@ async function handleHttp(req, res, sessionsApi) {
|
|
|
168
199
|
}
|
|
169
200
|
}
|
|
170
201
|
|
|
171
|
-
module.exports = { handleHttp, askSession };
|
|
202
|
+
module.exports = { handleHttp, askSession, askSubmitDelay };
|