dsh-plugin-lcu 0.1.0
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/LICENSE +21 -0
- package/README.md +316 -0
- package/cordis.patch.yml +23 -0
- package/dev-types/dsh.d.ts +292 -0
- package/docs/README.zh.md +291 -0
- package/lib/approval.js +152 -0
- package/lib/approval.js.map +1 -0
- package/lib/connection.js +384 -0
- package/lib/connection.js.map +1 -0
- package/lib/diag.js +52 -0
- package/lib/diag.js.map +1 -0
- package/lib/host-guard.js +137 -0
- package/lib/host-guard.js.map +1 -0
- package/lib/index.js +318 -0
- package/lib/index.js.map +1 -0
- package/lib/tool.js +262 -0
- package/lib/tool.js.map +1 -0
- package/lib/types/approval.d.ts +71 -0
- package/lib/types/approval.d.ts.map +1 -0
- package/lib/types/connection.d.ts +178 -0
- package/lib/types/connection.d.ts.map +1 -0
- package/lib/types/diag.d.ts +17 -0
- package/lib/types/diag.d.ts.map +1 -0
- package/lib/types/host-guard.d.ts +46 -0
- package/lib/types/host-guard.d.ts.map +1 -0
- package/lib/types/index.d.ts +49 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/tool.d.ts +90 -0
- package/lib/types/tool.d.ts.map +1 -0
- package/package.json +79 -0
- package/scripts/codex-baseline.json +10 -0
- package/scripts/gen-presets.mjs +266 -0
- package/scripts/probe-lcu.mjs +154 -0
- package/scripts/update-codex.mjs +525 -0
package/lib/index.js
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `dsh-plugin-lcu` — drive the desktop and Chrome from DeepSeek Harness.
|
|
3
|
+
*
|
|
4
|
+
* The plugin is one root-scoped row. It does not open anything at load time:
|
|
5
|
+
* LCU (and the CUA runtime behind it) starts only for an Agent whose preset is
|
|
6
|
+
* listed in `presets`, and stops when that Agent is disposed. That keeps a
|
|
7
|
+
* heavy, permission-bearing capability off every session that does not need it.
|
|
8
|
+
*
|
|
9
|
+
* Visibility is decided per Agent rather than by mounting rows inside a preset,
|
|
10
|
+
* because the server owns the tool schemas: they can only be fetched after the
|
|
11
|
+
* handshake, so the tools are registered into the Agent's own context once its
|
|
12
|
+
* connection is up.
|
|
13
|
+
*
|
|
14
|
+
* @module dsh-plugin-lcu
|
|
15
|
+
*/
|
|
16
|
+
import { homedir } from 'node:os';
|
|
17
|
+
import { join } from 'node:path';
|
|
18
|
+
import { approvalValueForLabel, isPreApprovedOrigin, nativeAppApproval, nativeAppApprovalResponse, normalizeOrigins, originApprovalOrigin } from "./approval.js";
|
|
19
|
+
import { LcuConnection, LcuError, TURN_CLEANUP_TIMEOUT_CODE, resolveElicitation, } from "./connection.js";
|
|
20
|
+
import { diag, describe } from "./diag.js";
|
|
21
|
+
import { isAgentHostApp } from "./host-guard.js";
|
|
22
|
+
import { registerLcuTools } from "./tool.js";
|
|
23
|
+
export const name = 'lcu';
|
|
24
|
+
export const inject = ['tools', 'systemPrompt'];
|
|
25
|
+
/** Where the installer puts the launcher. */
|
|
26
|
+
const DEFAULT_COMMAND = join(homedir(), '.local/share/lcu/current/bin/lcu');
|
|
27
|
+
/** The section order of the injected instructions, after the tool guidance. */
|
|
28
|
+
const DEFAULT_SECTION_ORDER = 0;
|
|
29
|
+
/** The message shown for a browser-origin approval. */
|
|
30
|
+
const ORIGIN_QUESTION = 'Allow computer use to access this site?';
|
|
31
|
+
function resolveSettings(config) {
|
|
32
|
+
const args = [];
|
|
33
|
+
if (config.chrome === true)
|
|
34
|
+
args.push('--chrome');
|
|
35
|
+
if (config.audio === true)
|
|
36
|
+
args.push('--audio');
|
|
37
|
+
return {
|
|
38
|
+
command: config.command ?? DEFAULT_COMMAND,
|
|
39
|
+
args,
|
|
40
|
+
presets: config.presets ?? ['heavy'],
|
|
41
|
+
allowedOrigins: normalizeOrigins(config.allowedOrigins ?? []),
|
|
42
|
+
sectionOrder: config.sectionOrder ?? DEFAULT_SECTION_ORDER,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Mount the LCU capability.
|
|
47
|
+
*
|
|
48
|
+
* @param ctx - the host context this row mounts into.
|
|
49
|
+
* @param config - the row's configuration.
|
|
50
|
+
*/
|
|
51
|
+
export function apply(ctx, config) {
|
|
52
|
+
const settings = resolveSettings(config);
|
|
53
|
+
const connections = new Map();
|
|
54
|
+
diag(`apply: presets=${JSON.stringify(settings.presets)} command=${settings.command} args=${JSON.stringify(settings.args)}`);
|
|
55
|
+
diag(` services: agentPresets=${describe(ctx.get('agentPresets'))} userQuestions=${describe(ctx.get('userQuestions'))} computerUse=${describe(ctx.get('computerUse'))} attachments=${describe(ctx.get('attachments'))} llm=${describe(ctx.get('llm'))}`);
|
|
56
|
+
// Reserve the deployment's computer-use provider slot when the seam exists.
|
|
57
|
+
// This is bookkeeping: the tools below are what the model actually calls.
|
|
58
|
+
ctx.effect(() => {
|
|
59
|
+
const computerUse = ctx.get('computerUse');
|
|
60
|
+
if (computerUse === undefined)
|
|
61
|
+
return () => { };
|
|
62
|
+
const release = computerUse.register(computerUseProviderName('lcu'));
|
|
63
|
+
ctx.logger.info('lcu: registered as the computer-use provider');
|
|
64
|
+
return () => { void release(); };
|
|
65
|
+
});
|
|
66
|
+
/**
|
|
67
|
+
* Present one approval to the user.
|
|
68
|
+
*
|
|
69
|
+
* The model cannot answer this: `userQuestions.ask` is the same surface the
|
|
70
|
+
* `ask_user_question` tool uses, and only a person can reply to it.
|
|
71
|
+
*/
|
|
72
|
+
async function presentApproval(agent, request, signal) {
|
|
73
|
+
const questions = ctx.get('userQuestions');
|
|
74
|
+
const approval0 = nativeAppApproval(request);
|
|
75
|
+
diag(`approval: asked kind=${approval0 === undefined ? (originApprovalOrigin(request) === undefined ? 'unknown' : 'browser-origin') : 'native-app'} userQuestions=${describe(questions)}`);
|
|
76
|
+
if (questions === undefined) {
|
|
77
|
+
diag(' approval: no userQuestions service -> cancel (fail closed)');
|
|
78
|
+
return { action: 'cancel' };
|
|
79
|
+
}
|
|
80
|
+
const approval = approval0;
|
|
81
|
+
if (approval !== undefined) {
|
|
82
|
+
// Anti-self-approval: never let the agent approve its own host.
|
|
83
|
+
if (await isAgentHostApp(approval.resource)) {
|
|
84
|
+
diag(` approval: REFUSED agent-host app ${approval.resource}`);
|
|
85
|
+
ctx.logger.warn(`lcu: refusing to approve the app hosting this agent (${approval.resource})`);
|
|
86
|
+
return { action: 'decline' };
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const answer = await questions.ask({
|
|
90
|
+
agent,
|
|
91
|
+
signal,
|
|
92
|
+
questions: [{
|
|
93
|
+
id: 'choice',
|
|
94
|
+
header: 'Computer use approval',
|
|
95
|
+
question: approval.message,
|
|
96
|
+
detail: `Computer use will be able to see and control ${approval.resource}.`,
|
|
97
|
+
options: approval.choices.map((choice) => ({ label: choice.label })),
|
|
98
|
+
}],
|
|
99
|
+
});
|
|
100
|
+
// The answer carries the option LABEL; the response needs its VALUE.
|
|
101
|
+
const label = answer.answers.find((item) => item.id === 'choice')?.selected[0];
|
|
102
|
+
const value = approvalValueForLabel(approval, label);
|
|
103
|
+
diag(` approval: user chose ${describe(label)} -> value ${describe(value)} for ${approval.resource}`);
|
|
104
|
+
return nativeAppApprovalResponse(request, value);
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
ctx.logger.debug(`lcu: native-app approval ended without a choice (${String(error)})`);
|
|
108
|
+
return { action: 'cancel' };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const origin = originApprovalOrigin(request);
|
|
112
|
+
if (origin !== undefined) {
|
|
113
|
+
// LCU keeps no permission cache; an exact pre-approved origin is the only
|
|
114
|
+
// thing answered without asking. The log names every asked origin so a
|
|
115
|
+
// user can add the ones they keep approving to `allowedOrigins`.
|
|
116
|
+
const preApproved = isPreApprovedOrigin(request, settings.allowedOrigins);
|
|
117
|
+
diag(` approval: site ${origin} ${preApproved ? 'pre-approved' : 'asking'} (add it to allowedOrigins to skip this)`);
|
|
118
|
+
if (preApproved)
|
|
119
|
+
return { action: 'accept', content: {} };
|
|
120
|
+
try {
|
|
121
|
+
const answer = await questions.ask({
|
|
122
|
+
agent,
|
|
123
|
+
signal,
|
|
124
|
+
questions: [{
|
|
125
|
+
id: 'choice',
|
|
126
|
+
header: 'Computer use site approval',
|
|
127
|
+
question: ORIGIN_QUESTION,
|
|
128
|
+
detail: `The runtime asked to use ${origin}.`,
|
|
129
|
+
options: [{ label: 'Allow' }, { label: 'Decline' }],
|
|
130
|
+
}],
|
|
131
|
+
});
|
|
132
|
+
const selected = answer.answers.find((item) => item.id === 'choice')?.selected[0];
|
|
133
|
+
diag(` approval: site ${origin} user chose ${describe(selected)}`);
|
|
134
|
+
if (selected === 'Allow')
|
|
135
|
+
return { action: 'accept', content: {} };
|
|
136
|
+
return selected === 'Decline' ? { action: 'decline' } : { action: 'cancel' };
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
ctx.logger.debug(`lcu: site approval ended without a choice (${String(error)})`);
|
|
140
|
+
return { action: 'cancel' };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Anything else is a shape this host does not understand; cancelling keeps
|
|
144
|
+
// the fail-closed contract rather than silently granting access.
|
|
145
|
+
ctx.logger.warn('lcu: unrecognized approval request was cancelled');
|
|
146
|
+
return { action: 'cancel' };
|
|
147
|
+
}
|
|
148
|
+
/** Open and prepare one Agent's connection; never throws. */
|
|
149
|
+
async function attach(agent, signal) {
|
|
150
|
+
if (connections.has(agent))
|
|
151
|
+
return;
|
|
152
|
+
const connection = new LcuConnection({
|
|
153
|
+
command: settings.command,
|
|
154
|
+
args: settings.args,
|
|
155
|
+
onElicitation: (request, elicitSignal) => presentApproval(agent, request, elicitSignal),
|
|
156
|
+
onStderr: (line) => { ctx.logger.debug(`lcu: ${line}`); },
|
|
157
|
+
});
|
|
158
|
+
diag(` attach: connecting ${settings.command}`);
|
|
159
|
+
try {
|
|
160
|
+
await connection.connect(signal);
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
await connection.close();
|
|
164
|
+
// A missing or broken LCU must not fail the session: the preset simply
|
|
165
|
+
// runs without the desktop tools.
|
|
166
|
+
ctx.logger.warn(`lcu: could not start for this session (${error instanceof Error ? error.message : String(error)})`);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
diag(` attach: connected, server=${describe(connection.serverInfo)} tools=${JSON.stringify(connection.allTools.map((t) => t.name))} instructions=${String(connection.instructions.length)}B`);
|
|
170
|
+
const state = { connection };
|
|
171
|
+
connections.set(agent, state);
|
|
172
|
+
// Everything below is agent-scoped: it unwinds when the Agent is disposed.
|
|
173
|
+
agent.ctx.effect(() => () => {
|
|
174
|
+
connections.delete(agent);
|
|
175
|
+
void connection.close();
|
|
176
|
+
});
|
|
177
|
+
try {
|
|
178
|
+
registerLcuTools(agent.ctx, connection, ctx, {
|
|
179
|
+
beforeCall: async () => {
|
|
180
|
+
const pending = state.pendingCleanup;
|
|
181
|
+
if (pending === undefined)
|
|
182
|
+
return;
|
|
183
|
+
// Retry the unfinished cleanup; only a settled one clears the gate.
|
|
184
|
+
await connection.turnEnded(pending.sessionId, pending.turnId);
|
|
185
|
+
state.pendingCleanup = undefined;
|
|
186
|
+
diag(' cleanup gate: retry succeeded, calls unblocked');
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
diag(' attach: tools registered');
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
diag(` attach: TOOL REGISTRATION FAILED: ${error instanceof Error ? `${error.name}: ${error.message}` : String(error)}`);
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
if (connection.instructions !== '') {
|
|
196
|
+
agent.ctx.systemPrompt.section({
|
|
197
|
+
name: 'lcu-instructions',
|
|
198
|
+
order: settings.sectionOrder,
|
|
199
|
+
text: connection.instructions,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
ctx.logger.info(`lcu: ${connection.serverInfo.name ?? 'server'} attached for this session`);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Whether this session's Agent should hold an LCU connection.
|
|
206
|
+
*
|
|
207
|
+
* The registry is authoritative; the session header is only the value the
|
|
208
|
+
* session was created with, which the picker replaces afterwards.
|
|
209
|
+
*/
|
|
210
|
+
function presetAllows(agent) {
|
|
211
|
+
const registry = ctx.get('agentPresets');
|
|
212
|
+
let composed;
|
|
213
|
+
let composeError;
|
|
214
|
+
try {
|
|
215
|
+
composed = registry?.composedPreset(agent.ctx);
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
composeError = error instanceof Error ? error.message : String(error);
|
|
219
|
+
}
|
|
220
|
+
const header = agent.session.header.agentPreset;
|
|
221
|
+
diag(`decide id=${String(agent.id)} composed=${describe(composed)} header=${describe(header)} err=${describe(composeError)}`);
|
|
222
|
+
const preset = composed ?? header;
|
|
223
|
+
if (preset === undefined) {
|
|
224
|
+
diag(' -> skip: no preset');
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
const allowed = settings.presets.includes(preset);
|
|
228
|
+
diag(` -> preset ${preset} ${allowed ? 'allowed' : 'not in allowlist'}`);
|
|
229
|
+
return allowed;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* A session's committed preset choice.
|
|
233
|
+
*
|
|
234
|
+
* This is the event that matters: a new task is created with the deployment
|
|
235
|
+
* default and the picker's mode is applied afterwards, so `agent/created`
|
|
236
|
+
* alone sees the wrong composition.
|
|
237
|
+
*/
|
|
238
|
+
ctx.on('agent-preset/selected', async (sessionId, agentPreset) => {
|
|
239
|
+
diag(`agent-preset/selected session=${String(sessionId)} preset=${describe(agentPreset)}`);
|
|
240
|
+
if (!settings.presets.includes(agentPreset))
|
|
241
|
+
return;
|
|
242
|
+
const agent = ctx.get('agents')?.get(String(sessionId));
|
|
243
|
+
if (agent === undefined) {
|
|
244
|
+
diag(' -> no live agent for that session');
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
try {
|
|
248
|
+
await attach(agent);
|
|
249
|
+
diag(` -> attached=${String(connections.has(agent))}`);
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
diag(` -> attach THREW: ${error instanceof Error ? `${error.name}: ${error.message}` : String(error)}`);
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
ctx.on('agent/created', async ({ agent, signal }) => {
|
|
256
|
+
// Ask the registry which preset this Agent actually uses. The session header
|
|
257
|
+
// records the deployment default at creation, which the new-task picker may
|
|
258
|
+
// replace afterwards — so the header is a fallback, never the authority.
|
|
259
|
+
diag(`agent/created id=${String(agent.id)} agentCtxTools=${describe(agent.ctx.tools)}`);
|
|
260
|
+
if (!presetAllows(agent))
|
|
261
|
+
return;
|
|
262
|
+
try {
|
|
263
|
+
await attach(agent, signal);
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
diag(` -> attach THREW: ${error instanceof Error ? `${error.name}: ${error.message}` : String(error)}`);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
diag(` -> attach done, connections=${String(connections.size)}, tools=${JSON.stringify(agent.ctx.tools.schemas(agent).map((t) => t.name).slice(-4))}`);
|
|
270
|
+
});
|
|
271
|
+
// LCU's lifecycle contract: the runtime owns per-turn cleanup (native helper
|
|
272
|
+
// and Sky contexts on macOS, temporary Chrome tabs), and only the host knows
|
|
273
|
+
// when a turn really ended.
|
|
274
|
+
ctx.on('agent/turn-stopping', async ({ agent, turn, signal }) => {
|
|
275
|
+
const state = connections.get(agent);
|
|
276
|
+
diag(`agent/turn-stopping id=${String(agent.id)} turn=${String(turn)} aborted=${String(signal.aborted)} haveConnection=${String(state !== undefined)}`);
|
|
277
|
+
if (state === undefined)
|
|
278
|
+
return;
|
|
279
|
+
const sessionId = String(agent.id);
|
|
280
|
+
const turnId = String(turn);
|
|
281
|
+
try {
|
|
282
|
+
await state.connection.turnEnded(sessionId, turnId, signal.aborted ? 'Interrupt' : 'Stop');
|
|
283
|
+
state.pendingCleanup = undefined;
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
const code = error instanceof LcuError ? error.code : undefined;
|
|
287
|
+
if (code === TURN_CLEANUP_TIMEOUT_CODE) {
|
|
288
|
+
// Expected on macOS when the signed helper is slow. The runtime keeps
|
|
289
|
+
// cleaning in the background; block the next call until it settles.
|
|
290
|
+
state.pendingCleanup = { sessionId, turnId };
|
|
291
|
+
diag('turn_ended: cleanup still running; LCU calls blocked until it settles');
|
|
292
|
+
ctx.logger.warn('lcu: turn cleanup is still running; computer-use calls are blocked until it settles');
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
diag(`turn_ended FAILED: ${error instanceof Error ? error.message : String(error)}`);
|
|
296
|
+
ctx.logger.warn(`lcu: turn_ended failed (${error instanceof Error ? error.message : String(error)})`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
// Drain every connection if the plugin itself unloads.
|
|
301
|
+
ctx.effect(() => () => {
|
|
302
|
+
const live = [...connections.values()];
|
|
303
|
+
connections.clear();
|
|
304
|
+
for (const { connection } of live)
|
|
305
|
+
void connection.close();
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* The computer-use seam brands its provider name, but the brand is compile-time
|
|
310
|
+
* only: the runtime value is the plain string, and importing the seam's own
|
|
311
|
+
* helper would be a value import from a package this plugin only type-checks
|
|
312
|
+
* against.
|
|
313
|
+
*/
|
|
314
|
+
function computerUseProviderName(value) {
|
|
315
|
+
return value;
|
|
316
|
+
}
|
|
317
|
+
export { resolveElicitation };
|
|
318
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/lib/tool.js
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model-facing tools for LCU.
|
|
3
|
+
*
|
|
4
|
+
* The server owns the tool contract: `js` carries a ~1.5 KB description that is
|
|
5
|
+
* the API manual, and the model is told to read documentation out of the first
|
|
6
|
+
* tool result. So the definitions here are the server's, passed through
|
|
7
|
+
* unchanged — this module only adapts the transport (canonical value, text
|
|
8
|
+
* fallback, durable images) and enforces the visibility rule that only `js` and
|
|
9
|
+
* `js_reset` may reach the model.
|
|
10
|
+
*
|
|
11
|
+
* @module dsh-plugin-lcu/tool
|
|
12
|
+
*/
|
|
13
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
14
|
+
import { MODEL_TOOL_NAMES, LcuError } from "./connection.js";
|
|
15
|
+
/** Media types the attachment store admits. */
|
|
16
|
+
const IMAGE_MEDIA_TYPES = ['image/png', 'image/jpeg', 'image/webp', 'image/gif'];
|
|
17
|
+
/** Canonical base64: standard alphabet, padded, no embedded whitespace. */
|
|
18
|
+
const CANONICAL_BASE64 = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
19
|
+
const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
20
|
+
/**
|
|
21
|
+
* The model-facing text for one MCP result.
|
|
22
|
+
*
|
|
23
|
+
* LCU returns documentation and command output as text, and screenshots as
|
|
24
|
+
* separate image blocks, so joining the text blocks is the whole projection;
|
|
25
|
+
* images are appended by {@link prepareProjection}.
|
|
26
|
+
*
|
|
27
|
+
* @param content - the raw MCP content array.
|
|
28
|
+
* @param toolName - the tool, for the empty-result diagnostic.
|
|
29
|
+
* @returns text for the model, never empty.
|
|
30
|
+
*/
|
|
31
|
+
export function extractText(content, toolName) {
|
|
32
|
+
const texts = [];
|
|
33
|
+
let images = 0;
|
|
34
|
+
for (const block of content) {
|
|
35
|
+
if (!isRecord(block))
|
|
36
|
+
continue;
|
|
37
|
+
if (block.type === 'text' && typeof block.text === 'string')
|
|
38
|
+
texts.push(block.text);
|
|
39
|
+
else if (block.type === 'image')
|
|
40
|
+
images += 1;
|
|
41
|
+
}
|
|
42
|
+
if (texts.length > 0)
|
|
43
|
+
return texts.join('\n');
|
|
44
|
+
if (images > 0)
|
|
45
|
+
return `[${String(images)} image${images === 1 ? '' : 's'}]`;
|
|
46
|
+
return `[${toolName} returned no text content]`;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Decode one image block, rejecting anything the store would not accept.
|
|
50
|
+
*
|
|
51
|
+
* @param block - a declared MCP image block.
|
|
52
|
+
* @returns the decoded attachment payload.
|
|
53
|
+
* @throws {Error} when the media type is not admitted or the base64 is not canonical.
|
|
54
|
+
*/
|
|
55
|
+
export function decodeImage(block) {
|
|
56
|
+
if (!IMAGE_MEDIA_TYPES.includes(block.mimeType)) {
|
|
57
|
+
throw new Error('the declared media type is not PNG, JPEG, WebP, or GIF');
|
|
58
|
+
}
|
|
59
|
+
if (!CANONICAL_BASE64.test(block.data))
|
|
60
|
+
throw new Error('the image data is not canonical base64');
|
|
61
|
+
const data = Buffer.from(block.data, 'base64');
|
|
62
|
+
if (data.toString('base64') !== block.data)
|
|
63
|
+
throw new Error('the image data is not canonical base64');
|
|
64
|
+
return { data, mediaType: block.mimeType };
|
|
65
|
+
}
|
|
66
|
+
/** Stable diagnostic text for an image the host could not admit. */
|
|
67
|
+
export function imageDiagnostic(block, reason) {
|
|
68
|
+
const mediaType = isRecord(block) && typeof block.mimeType === 'string' ? block.mimeType : 'unknown media type';
|
|
69
|
+
return `[image unavailable: ${mediaType}; ${reason}; the raw image stays available to programmatic callers]`;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Resolve the attachment store for this call, verifying the model can take images.
|
|
73
|
+
*
|
|
74
|
+
* @param ctx - the plugin context.
|
|
75
|
+
* @param exec - the in-flight call.
|
|
76
|
+
* @returns the attachment store.
|
|
77
|
+
* @throws {Error} with the reason the images cannot be delivered.
|
|
78
|
+
*/
|
|
79
|
+
async function resolveAttachments(ctx, exec) {
|
|
80
|
+
const attachments = ctx.get('attachments');
|
|
81
|
+
if (attachments === undefined)
|
|
82
|
+
throw new Error('no attachment store is mounted');
|
|
83
|
+
const routed = exec.agent?.session.requestHeader()?.config;
|
|
84
|
+
const provider = routed?.provider ?? exec.agent?.options.provider;
|
|
85
|
+
const model = routed?.model ?? exec.agent?.options.model;
|
|
86
|
+
const llm = ctx.get('llm');
|
|
87
|
+
if (provider === undefined || model === undefined || llm === undefined) {
|
|
88
|
+
throw new Error('the current model route could not be resolved');
|
|
89
|
+
}
|
|
90
|
+
let info;
|
|
91
|
+
try {
|
|
92
|
+
info = await llm.resolveModelInfo(provider, model, exec.signal);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
throw new Error('the current model route could not be verified');
|
|
96
|
+
}
|
|
97
|
+
if (info.inputModalities === undefined || !info.inputModalities.includes('image')) {
|
|
98
|
+
throw new Error(`model "${model}" does not declare image input`);
|
|
99
|
+
}
|
|
100
|
+
if (exec.signal.aborted)
|
|
101
|
+
throw new Error('the tool call was canceled before image storage');
|
|
102
|
+
return attachments;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Build the ordered content blocks for one result: text and images interleaved
|
|
106
|
+
* exactly as the server emitted them, with any inadmissible image replaced by a
|
|
107
|
+
* diagnostic instead of failing the whole call.
|
|
108
|
+
*/
|
|
109
|
+
async function prepareProjection(ctx, exec, content, toolName) {
|
|
110
|
+
const decoded = [];
|
|
111
|
+
const indexes = [];
|
|
112
|
+
const failures = new Map();
|
|
113
|
+
content.forEach((block, index) => {
|
|
114
|
+
if (!isRecord(block) || block.type !== 'image')
|
|
115
|
+
return;
|
|
116
|
+
indexes.push(index);
|
|
117
|
+
try {
|
|
118
|
+
decoded.push(decodeImage(block));
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
failures.set(index, error instanceof Error ? error.message : String(error));
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
if (failures.size > 0) {
|
|
125
|
+
return content.map((block, index) => isRecord(block) && block.type === 'image'
|
|
126
|
+
? { type: 'text', text: imageDiagnostic(block, failures.get(index) ?? 'another image in the same result was invalid') }
|
|
127
|
+
: block);
|
|
128
|
+
}
|
|
129
|
+
let attachments;
|
|
130
|
+
try {
|
|
131
|
+
attachments = await resolveAttachments(ctx, exec);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
135
|
+
return content.map((block) => isRecord(block) && block.type === 'image'
|
|
136
|
+
? { type: 'text', text: imageDiagnostic(block, reason) }
|
|
137
|
+
: block);
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
const refs = await attachments.saveImages(decoded);
|
|
141
|
+
const byIndex = new Map(indexes.map((index, offset) => [index, refs[offset]]));
|
|
142
|
+
return content.map((block, index) => {
|
|
143
|
+
if (!isRecord(block) || block.type !== 'image')
|
|
144
|
+
return block;
|
|
145
|
+
const ref = byIndex.get(index);
|
|
146
|
+
return ref === undefined
|
|
147
|
+
? { type: 'text', text: imageDiagnostic(block, 'the attachment store returned no reference') }
|
|
148
|
+
: { type: 'image', attachment: ref };
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
153
|
+
return content.map((block) => isRecord(block) && block.type === 'image'
|
|
154
|
+
? { type: 'text', text: imageDiagnostic(block, `the image could not be stored: ${reason}`) }
|
|
155
|
+
: block);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Build one model-facing tool from a server descriptor.
|
|
160
|
+
*
|
|
161
|
+
* @param descriptor - the tool as `tools/list` reported it.
|
|
162
|
+
* @param connection - the connection this agent's calls go through.
|
|
163
|
+
* @param ctx - the plugin context, used for the attachment store.
|
|
164
|
+
* @param options - host hooks around the call.
|
|
165
|
+
* @returns a registrable tool definition.
|
|
166
|
+
*/
|
|
167
|
+
export function createLcuTool(descriptor, connection, ctx, options = {}) {
|
|
168
|
+
const projections = new WeakMap();
|
|
169
|
+
const toolName = descriptor.name;
|
|
170
|
+
return {
|
|
171
|
+
name: toolName,
|
|
172
|
+
// The server's description is the API manual; never truncate or rewrite it.
|
|
173
|
+
description: descriptor.description,
|
|
174
|
+
parameters: descriptor.inputSchema,
|
|
175
|
+
output: {
|
|
176
|
+
schema: {
|
|
177
|
+
type: 'object',
|
|
178
|
+
properties: {
|
|
179
|
+
content: { type: 'array', items: {} },
|
|
180
|
+
structuredContent: {},
|
|
181
|
+
},
|
|
182
|
+
required: ['content'],
|
|
183
|
+
additionalProperties: false,
|
|
184
|
+
},
|
|
185
|
+
render(_args, value) {
|
|
186
|
+
const content = isRecord(value) && Array.isArray(value.content) ? value.content : [];
|
|
187
|
+
return [{ type: 'text', text: extractText(content, toolName) }];
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
async execute(args, exec) {
|
|
191
|
+
// Refuse to touch the desktop while a previous turn's cleanup is unsettled.
|
|
192
|
+
await options.beforeCall?.();
|
|
193
|
+
// The loop hands us parsed model arguments, which can be any JSON value if
|
|
194
|
+
// the model misbehaves; an empty object lets the server report the missing
|
|
195
|
+
// parameter specifically instead of us inventing an error.
|
|
196
|
+
const callArgs = isRecord(args) ? args : {};
|
|
197
|
+
const result = await connection.callTool(toolName, callArgs, { signal: exec.signal });
|
|
198
|
+
const content = result.content;
|
|
199
|
+
const text = extractText(content, toolName);
|
|
200
|
+
// MCP isError becomes a thrown error so the runtime records a failed call.
|
|
201
|
+
if (result.isError)
|
|
202
|
+
throw new Error(text);
|
|
203
|
+
const value = { content };
|
|
204
|
+
if (result.structuredContent !== undefined)
|
|
205
|
+
value.structuredContent = result.structuredContent;
|
|
206
|
+
if (content.some((block) => isRecord(block) && block.type === 'image')) {
|
|
207
|
+
const projected = await prepareProjection(ctx, exec, content, toolName);
|
|
208
|
+
projections.set(exec, { value, content: projected });
|
|
209
|
+
}
|
|
210
|
+
return value;
|
|
211
|
+
},
|
|
212
|
+
projectContent(exec, result) {
|
|
213
|
+
const projection = projections.get(exec);
|
|
214
|
+
if (projection === undefined)
|
|
215
|
+
return undefined;
|
|
216
|
+
projections.delete(exec);
|
|
217
|
+
if (result.isError === true)
|
|
218
|
+
return undefined;
|
|
219
|
+
// Policy may have replaced the value; only install our images when the
|
|
220
|
+
// canonical value is still the one we prepared them for.
|
|
221
|
+
if (!isDeepStrictEqual(result.value, projection.value))
|
|
222
|
+
return undefined;
|
|
223
|
+
return projection.content;
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Build every model-facing tool for one agent's connection.
|
|
229
|
+
*
|
|
230
|
+
* @param connection - the connected LCU session.
|
|
231
|
+
* @param ctx - the plugin context.
|
|
232
|
+
* @returns tool definitions for `js` and `js_reset`, in server order.
|
|
233
|
+
* @throws {LcuError} when the server does not expose the model tools.
|
|
234
|
+
*/
|
|
235
|
+
export function buildLcuTools(connection, ctx, options = {}) {
|
|
236
|
+
const descriptors = connection.modelTools();
|
|
237
|
+
const missing = MODEL_TOOL_NAMES.filter((name) => !descriptors.some((tool) => tool.name === name));
|
|
238
|
+
if (missing.length > 0) {
|
|
239
|
+
throw new LcuError('tools/list', `the server does not expose ${missing.join(', ')}`);
|
|
240
|
+
}
|
|
241
|
+
return descriptors.map((descriptor) => createLcuTool(descriptor, connection, ctx, options));
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Register the model-facing tools in one agent's scope.
|
|
245
|
+
*
|
|
246
|
+
* Registration is per agent rather than at plugin mount because the server owns
|
|
247
|
+
* the schemas: they can only be fetched after connecting, and an agent only
|
|
248
|
+
* needs the capability once it exists.
|
|
249
|
+
*
|
|
250
|
+
* @param agentCtx - the agent's own context; its registrations unwind on disposal.
|
|
251
|
+
* @param connection - the agent's connected LCU session.
|
|
252
|
+
* @param ctx - the plugin context.
|
|
253
|
+
* @returns a disposer that unregisters every tool.
|
|
254
|
+
*/
|
|
255
|
+
export function registerLcuTools(agentCtx, connection, ctx, options = {}) {
|
|
256
|
+
const disposers = buildLcuTools(connection, ctx, options).map((definition) => agentCtx.tools.register(definition));
|
|
257
|
+
return () => {
|
|
258
|
+
for (const dispose of disposers.reverse())
|
|
259
|
+
dispose();
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=tool.js.map
|
package/lib/tool.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../src/tool.ts"],"names":[],"mappings":"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"}
|