aiquila-mcp 0.4.15 → 0.4.16
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.
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { executeOCC } from '../../client/aiquila.js';
|
|
4
|
+
/** Effort levels `occ aiquila:configure` accepts; each model takes a subset. */
|
|
5
|
+
const EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max'];
|
|
6
|
+
/** Thinking modes; 'auto' follows the model's own default. */
|
|
7
|
+
const THINKING_MODES = ['auto', 'on', 'off'];
|
|
4
8
|
/**
|
|
5
9
|
* AIquila Internal Tools
|
|
6
10
|
* Provides configuration and testing for AIquila OCC commands
|
|
@@ -66,15 +70,31 @@ export const configureTool = {
|
|
|
66
70
|
idempotentHint: true,
|
|
67
71
|
openWorldHint: false,
|
|
68
72
|
},
|
|
69
|
-
description: 'Configure AIquila settings (API key, model, tokens, timeout)',
|
|
73
|
+
description: 'Configure AIquila settings (API key, model, tokens, timeout, effort and thinking for chat and background tasks)',
|
|
70
74
|
inputSchema: z.object({
|
|
71
75
|
apiKey: z.string().optional().describe('Anthropic API key'),
|
|
72
76
|
model: z
|
|
73
77
|
.string()
|
|
74
78
|
.optional()
|
|
75
|
-
.describe("Claude model to use (e.g., 'claude-fable-5', 'claude-opus-5', 'claude-sonnet-5')"),
|
|
79
|
+
.describe("Claude model to use (e.g., 'claude-fable-5-1', 'claude-opus-5-5', 'claude-opus-5', 'claude-sonnet-5')"),
|
|
76
80
|
maxTokens: z.number().optional().describe('Maximum tokens for responses (default: 4096)'),
|
|
77
81
|
timeout: z.number().optional().describe('Request timeout in seconds (default: 60)'),
|
|
82
|
+
effort: z
|
|
83
|
+
.enum(['', ...EFFORTS])
|
|
84
|
+
.optional()
|
|
85
|
+
.describe('Default effort level; empty string resets to the model default'),
|
|
86
|
+
thinking: z
|
|
87
|
+
.enum(THINKING_MODES)
|
|
88
|
+
.optional()
|
|
89
|
+
.describe("Default thinking: 'auto' follows the model (Fable, Opus 5.x and Sonnet 5 think on their own), 'on' or 'off'. Fable and Opus 5.5 always think."),
|
|
90
|
+
taskEffort: z
|
|
91
|
+
.enum(['', ...EFFORTS])
|
|
92
|
+
.optional()
|
|
93
|
+
.describe('Effort for Assistant tasks and coworkers; empty string uses the default effort'),
|
|
94
|
+
taskThinking: z
|
|
95
|
+
.enum(['', ...THINKING_MODES])
|
|
96
|
+
.optional()
|
|
97
|
+
.describe('Thinking for Assistant tasks and coworkers; empty string uses the default thinking'),
|
|
78
98
|
}),
|
|
79
99
|
handler: async (args) => {
|
|
80
100
|
try {
|
|
@@ -91,6 +111,19 @@ export const configureTool = {
|
|
|
91
111
|
if (args.timeout) {
|
|
92
112
|
configArgs.push('--timeout', args.timeout.toString());
|
|
93
113
|
}
|
|
114
|
+
// Empty strings are meaningful here (reset), so test for undefined.
|
|
115
|
+
if (args.effort !== undefined) {
|
|
116
|
+
configArgs.push('--effort', args.effort);
|
|
117
|
+
}
|
|
118
|
+
if (args.thinking !== undefined) {
|
|
119
|
+
configArgs.push('--thinking', args.thinking);
|
|
120
|
+
}
|
|
121
|
+
if (args.taskEffort !== undefined) {
|
|
122
|
+
configArgs.push('--task-effort', args.taskEffort);
|
|
123
|
+
}
|
|
124
|
+
if (args.taskThinking !== undefined) {
|
|
125
|
+
configArgs.push('--task-thinking', args.taskThinking);
|
|
126
|
+
}
|
|
94
127
|
const output = await runOCC('aiquila:configure', configArgs);
|
|
95
128
|
return {
|
|
96
129
|
content: [
|
|
@@ -203,7 +203,7 @@ function collectAlarmMinutes(alarm, alarms) {
|
|
|
203
203
|
/**
|
|
204
204
|
* Parse calendar collections from a PROPFIND response.
|
|
205
205
|
*/
|
|
206
|
-
function parseCalendars(responseXml) {
|
|
206
|
+
export function parseCalendars(responseXml) {
|
|
207
207
|
const calendars = [];
|
|
208
208
|
const responseBlocks = responseXml.match(/<d:response>[\s\S]*?<\/d:response>/g);
|
|
209
209
|
if (!responseBlocks)
|
package/dist/tools/apps/tasks.js
CHANGED
|
@@ -3,6 +3,7 @@ import { z } from 'zod';
|
|
|
3
3
|
import { decodeXmlEntities, encodeXmlEntities, fetchCalDAV, nsTagContent, } from '../../client/caldav.js';
|
|
4
4
|
import { escapeICalValue } from '../dav-utils.js';
|
|
5
5
|
import { getNextcloudConfig } from '../types.js';
|
|
6
|
+
import { parseCalendars } from './calendar.js';
|
|
6
7
|
// ---------------------------------------------------------------------------
|
|
7
8
|
// iCalendar helpers
|
|
8
9
|
// ---------------------------------------------------------------------------
|
|
@@ -221,6 +222,33 @@ function formatTask(task) {
|
|
|
221
222
|
line += `\n UID: ${task.uid}`;
|
|
222
223
|
return line;
|
|
223
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* Format a task list (VTODO-capable calendar) for human-readable display.
|
|
227
|
+
* `calendarName` is the URL slug the other task tools expect.
|
|
228
|
+
*/
|
|
229
|
+
function formatTaskList(cal, detailed = false) {
|
|
230
|
+
const slug = cal.url.split('/').filter(Boolean).pop() ?? '';
|
|
231
|
+
let line = decodeXmlEntities(cal.displayName);
|
|
232
|
+
if (cal.color)
|
|
233
|
+
line += ` [${cal.color}]`;
|
|
234
|
+
if (!cal.enabled)
|
|
235
|
+
line += ' (disabled)';
|
|
236
|
+
line += `\n calendarName: ${slug}`;
|
|
237
|
+
line += `\n URL: ${cal.url}`;
|
|
238
|
+
if (detailed) {
|
|
239
|
+
const parts = [];
|
|
240
|
+
if (cal.supportsEvents)
|
|
241
|
+
parts.push('events');
|
|
242
|
+
if (cal.supportsTasks)
|
|
243
|
+
parts.push('tasks');
|
|
244
|
+
if (cal.supportsJournals)
|
|
245
|
+
parts.push('journals');
|
|
246
|
+
line += `\n Supports: ${parts.join(', ')}`;
|
|
247
|
+
if (cal.ctag)
|
|
248
|
+
line += `\n CTag: ${decodeXmlEntities(cal.ctag)}`;
|
|
249
|
+
}
|
|
250
|
+
return line;
|
|
251
|
+
}
|
|
224
252
|
// ---------------------------------------------------------------------------
|
|
225
253
|
// CalDAV helpers
|
|
226
254
|
// ---------------------------------------------------------------------------
|
|
@@ -285,36 +313,67 @@ export const listTaskListsTool = {
|
|
|
285
313
|
idempotentHint: true,
|
|
286
314
|
openWorldHint: false,
|
|
287
315
|
},
|
|
288
|
-
description:
|
|
289
|
-
inputSchema: z.object({
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
316
|
+
description: "List all task lists in Nextcloud Tasks (calendars that support tasks). Returns each list's display name, color, URL and calendarName (the value to pass to the other task tools). Set detailed for supported component types and the CTag.",
|
|
317
|
+
inputSchema: z.object({
|
|
318
|
+
detailed: z
|
|
319
|
+
.boolean()
|
|
320
|
+
.optional()
|
|
321
|
+
.describe('Also include the component types each list supports (events, tasks, journals) and its CTag sync token (default false)'),
|
|
322
|
+
}),
|
|
323
|
+
handler: async (args = {}) => {
|
|
324
|
+
try {
|
|
325
|
+
const config = getNextcloudConfig();
|
|
326
|
+
const calDavUrl = `${config.url}/remote.php/dav/calendars/${config.user}/`;
|
|
327
|
+
const propfindBody = `<?xml version="1.0" encoding="UTF-8"?>
|
|
328
|
+
<d:propfind xmlns:d="DAV:" xmlns:cs="http://calendarserver.org/ns/" xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:x1="http://apple.com/ns/ical/" xmlns:x2="http://owncloud.org/ns">
|
|
295
329
|
<d:prop>
|
|
296
330
|
<d:resourcetype />
|
|
297
331
|
<d:displayname />
|
|
298
332
|
<cs:getctag />
|
|
333
|
+
<x1:calendar-color />
|
|
334
|
+
<x1:calendar-order />
|
|
335
|
+
<x2:calendar-enabled />
|
|
299
336
|
<c:supported-calendar-component-set />
|
|
300
337
|
</d:prop>
|
|
301
338
|
</d:propfind>`;
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
339
|
+
const response = await fetchCalDAV(calDavUrl, {
|
|
340
|
+
method: 'PROPFIND',
|
|
341
|
+
body: propfindBody,
|
|
342
|
+
headers: { Depth: '1' },
|
|
343
|
+
});
|
|
344
|
+
if (!response.ok) {
|
|
345
|
+
const errorText = await response.text();
|
|
346
|
+
throw new Error(`CalDAV PROPFIND failed: ${response.status} - ${errorText}`);
|
|
347
|
+
}
|
|
348
|
+
const taskLists = parseCalendars(await response.text())
|
|
349
|
+
.filter((cal) => cal.supportsTasks)
|
|
350
|
+
.sort((a, b) => (a.order ?? Infinity) - (b.order ?? Infinity));
|
|
351
|
+
if (taskLists.length === 0) {
|
|
352
|
+
return {
|
|
353
|
+
content: [{ type: 'text', text: 'No task lists found.' }],
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
const formatted = taskLists.map((cal) => formatTaskList(cal, args.detailed)).join('\n\n');
|
|
357
|
+
return {
|
|
358
|
+
content: [
|
|
359
|
+
{
|
|
360
|
+
type: 'text',
|
|
361
|
+
text: `Task lists (${taskLists.length} found):\n\n${formatted}`,
|
|
362
|
+
},
|
|
363
|
+
],
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
return {
|
|
368
|
+
content: [
|
|
369
|
+
{
|
|
370
|
+
type: 'text',
|
|
371
|
+
text: `Error listing task lists: ${error instanceof Error ? error.message : String(error)}`,
|
|
372
|
+
},
|
|
373
|
+
],
|
|
374
|
+
isError: true,
|
|
375
|
+
};
|
|
376
|
+
}
|
|
318
377
|
},
|
|
319
378
|
};
|
|
320
379
|
/**
|
package/package.json
CHANGED