neoagent 2.2.1-beta.6 → 2.2.1-beta.7
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/docs/automation.md +2 -2
- package/docs/capabilities.md +7 -10
- package/docs/hardware.md +4 -7
- package/docs/index.md +6 -7
- package/docs/integrations.md +1 -1
- package/docs/operations.md +1 -1
- package/docs/why-neoagent.md +2 -2
- package/package.json +1 -1
- package/server/db/database.js +76 -61
- package/server/http/routes.js +1 -2
- package/server/public/assets/AssetManifest.json +1 -1
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +65118 -64805
- package/server/routes/{scheduler.js → tasks.js} +31 -29
- package/server/routes/widgets.js +7 -7
- package/server/services/ai/capabilityHealth.js +4 -4
- package/server/services/ai/engine.js +9 -9
- package/server/services/ai/systemPrompt.js +7 -7
- package/server/services/ai/taskAnalysis.js +3 -3
- package/server/services/ai/toolResult.js +6 -8
- package/server/services/ai/tools.js +62 -95
- package/server/services/commands/router.js +14 -6
- package/server/services/integrations/whatsapp/provider.js +23 -1
- package/server/services/manager.js +14 -14
- package/server/services/memory/manager.js +7 -7
- package/server/services/memory/policy.js +1 -1
- package/server/services/messaging/formatting_guides.js +0 -4
- package/server/services/messaging/manager.js +0 -2
- package/server/services/tasks/adapters/gmail_message_received.js +36 -0
- package/server/services/tasks/adapters/index.js +10 -0
- package/server/services/tasks/adapters/outlook_email_received.js +38 -0
- package/server/services/tasks/adapters/schedule.js +57 -0
- package/server/services/tasks/adapters/slack_message_received.js +39 -0
- package/server/services/tasks/adapters/teams_message_received.js +39 -0
- package/server/services/tasks/adapters/whatsapp_personal_message_received.js +42 -0
- package/server/services/tasks/integration_runtime.js +260 -0
- package/server/services/tasks/runtime.js +539 -0
- package/server/services/{scheduler/cron_utils.js → tasks/schedule_utils.js} +2 -0
- package/server/services/tasks/security.js +60 -0
- package/server/services/tasks/task_repository.js +162 -0
- package/server/services/tasks/trigger_registry.js +29 -0
- package/server/services/tasks/utils.js +45 -0
- package/server/services/websocket.js +1 -1
- package/server/services/widgets/service.js +37 -25
- package/server/routes/wearable_device.js +0 -147
- package/server/services/messaging/waveshare_wearable.js +0 -40
- package/server/services/scheduler/cron.js +0 -580
- package/server/services/wearables/device_auth.js +0 -228
|
@@ -3,79 +3,81 @@ const router = express.Router();
|
|
|
3
3
|
const { requireAuth } = require('../middleware/auth');
|
|
4
4
|
const { sanitizeError } = require('../utils/security');
|
|
5
5
|
const { getAgentIdFromRequest, resolveAgentId } = require('../services/agents/manager');
|
|
6
|
-
const cron = require('node-cron');
|
|
7
6
|
|
|
8
7
|
router.use(requireAuth);
|
|
9
8
|
|
|
10
|
-
// List scheduled tasks
|
|
11
9
|
router.get('/', (req, res) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
try {
|
|
11
|
+
const tasks = req.app.locals.taskRuntime;
|
|
12
|
+
const agentId = resolveAgentId(req.session.userId, getAgentIdFromRequest(req));
|
|
13
|
+
res.json(tasks.listTasks(req.session.userId, { agentId }));
|
|
14
|
+
} catch (error) {
|
|
15
|
+
(req.app.locals.logger?.error || console.error)('[Tasks] Failed to list tasks', error);
|
|
16
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
17
|
+
}
|
|
15
18
|
});
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
router.post('/', (req, res) => {
|
|
20
|
+
router.get('/catalog', (req, res) => {
|
|
19
21
|
try {
|
|
20
|
-
const
|
|
22
|
+
const tasks = req.app.locals.taskRuntime;
|
|
21
23
|
const agentId = resolveAgentId(req.session.userId, getAgentIdFromRequest(req));
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
res.json(tasks.getTriggerCatalog(req.session.userId, { agentId }));
|
|
25
|
+
} catch (error) {
|
|
26
|
+
(req.app.locals.logger?.error || console.error)('[Tasks] Failed to load trigger catalog', error);
|
|
27
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
28
|
+
}
|
|
29
|
+
});
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
router.post('/', async (req, res) => {
|
|
32
|
+
try {
|
|
33
|
+
const tasks = req.app.locals.taskRuntime;
|
|
34
|
+
const agentId = resolveAgentId(req.session.userId, getAgentIdFromRequest(req));
|
|
35
|
+
const task = await tasks.createTask(req.session.userId, {
|
|
36
|
+
...req.body,
|
|
37
|
+
agentId,
|
|
38
|
+
});
|
|
31
39
|
res.status(201).json(task);
|
|
32
40
|
} catch (err) {
|
|
33
41
|
res.status(400).json({ error: sanitizeError(err) });
|
|
34
42
|
}
|
|
35
43
|
});
|
|
36
44
|
|
|
37
|
-
|
|
38
|
-
router.put('/:id', (req, res) => {
|
|
45
|
+
router.put('/:id', async (req, res) => {
|
|
39
46
|
try {
|
|
40
47
|
const taskId = Number.parseInt(req.params.id, 10);
|
|
41
48
|
if (!Number.isInteger(taskId) || taskId <= 0) {
|
|
42
49
|
return res.status(400).json({ error: 'Invalid task id' });
|
|
43
50
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
const scheduler = req.app.locals.scheduler;
|
|
48
|
-
const task = scheduler.updateTask(taskId, req.session.userId, req.body);
|
|
51
|
+
const tasks = req.app.locals.taskRuntime;
|
|
52
|
+
const task = await tasks.updateTask(taskId, req.session.userId, req.body);
|
|
49
53
|
res.json(task);
|
|
50
54
|
} catch (err) {
|
|
51
55
|
res.status(400).json({ error: sanitizeError(err) });
|
|
52
56
|
}
|
|
53
57
|
});
|
|
54
58
|
|
|
55
|
-
// Delete a scheduled task
|
|
56
59
|
router.delete('/:id', (req, res) => {
|
|
57
60
|
try {
|
|
58
61
|
const taskId = Number.parseInt(req.params.id, 10);
|
|
59
62
|
if (!Number.isInteger(taskId) || taskId <= 0) {
|
|
60
63
|
return res.status(400).json({ error: 'Invalid task id' });
|
|
61
64
|
}
|
|
62
|
-
const
|
|
63
|
-
|
|
65
|
+
const tasks = req.app.locals.taskRuntime;
|
|
66
|
+
tasks.deleteTask(taskId, req.session.userId);
|
|
64
67
|
res.json({ success: true });
|
|
65
68
|
} catch (err) {
|
|
66
69
|
res.status(400).json({ error: sanitizeError(err) });
|
|
67
70
|
}
|
|
68
71
|
});
|
|
69
72
|
|
|
70
|
-
// Run a task immediately
|
|
71
73
|
router.post('/:id/run', (req, res) => {
|
|
72
74
|
try {
|
|
73
75
|
const taskId = Number.parseInt(req.params.id, 10);
|
|
74
76
|
if (!Number.isInteger(taskId) || taskId <= 0) {
|
|
75
77
|
return res.status(400).json({ error: 'Invalid task id' });
|
|
76
78
|
}
|
|
77
|
-
const
|
|
78
|
-
const result =
|
|
79
|
+
const tasks = req.app.locals.taskRuntime;
|
|
80
|
+
const result = tasks.runTaskNow(taskId, req.session.userId);
|
|
79
81
|
res.json(result);
|
|
80
82
|
} catch (err) {
|
|
81
83
|
res.status(400).json({ error: sanitizeError(err) });
|
package/server/routes/widgets.js
CHANGED
|
@@ -40,26 +40,26 @@ router.get('/', (req, res) => {
|
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
router.post('/', (req, res) => {
|
|
43
|
+
router.post('/', async (req, res) => {
|
|
44
44
|
try {
|
|
45
45
|
const service = widgetService(req);
|
|
46
46
|
if (!service) {
|
|
47
47
|
return res.status(500).json({ error: 'Widget service unavailable.' });
|
|
48
48
|
}
|
|
49
|
-
const widget = service.createWidget(req.session.userId, req.body || {});
|
|
49
|
+
const widget = await service.createWidget(req.session.userId, req.body || {});
|
|
50
50
|
res.status(201).json(widget);
|
|
51
51
|
} catch (err) {
|
|
52
52
|
res.status(400).json({ error: sanitizeError(err) });
|
|
53
53
|
}
|
|
54
54
|
});
|
|
55
55
|
|
|
56
|
-
router.put('/:id', (req, res) => {
|
|
56
|
+
router.put('/:id', async (req, res) => {
|
|
57
57
|
try {
|
|
58
58
|
const service = widgetService(req);
|
|
59
59
|
if (!service) {
|
|
60
60
|
return res.status(500).json({ error: 'Widget service unavailable.' });
|
|
61
61
|
}
|
|
62
|
-
const widget = service.updateWidget(req.session.userId, req.params.id, req.body || {});
|
|
62
|
+
const widget = await service.updateWidget(req.session.userId, req.params.id, req.body || {});
|
|
63
63
|
res.json(widget);
|
|
64
64
|
} catch (err) {
|
|
65
65
|
res.status(400).json({ error: sanitizeError(err) });
|
|
@@ -81,8 +81,8 @@ router.delete('/:id', (req, res) => {
|
|
|
81
81
|
router.post('/:id/refresh', (req, res) => {
|
|
82
82
|
try {
|
|
83
83
|
const service = widgetService(req);
|
|
84
|
-
const
|
|
85
|
-
if (!service || !
|
|
84
|
+
const taskRuntime = req.app?.locals?.taskRuntime;
|
|
85
|
+
if (!service || !taskRuntime) {
|
|
86
86
|
return res.status(500).json({ error: 'Widget refresh unavailable.' });
|
|
87
87
|
}
|
|
88
88
|
const widget = service.getWidget(req.session.userId, req.params.id);
|
|
@@ -92,7 +92,7 @@ router.post('/:id/refresh', (req, res) => {
|
|
|
92
92
|
if (!widget.scheduledTaskId) {
|
|
93
93
|
return res.status(400).json({ error: 'Widget is missing its refresh task.' });
|
|
94
94
|
}
|
|
95
|
-
res.json(
|
|
95
|
+
res.json(taskRuntime.runTaskNow(widget.scheduledTaskId, req.session.userId));
|
|
96
96
|
} catch (err) {
|
|
97
97
|
res.status(400).json({ error: sanitizeError(err) });
|
|
98
98
|
}
|
|
@@ -354,7 +354,7 @@ function getMemoryHealth(engine) {
|
|
|
354
354
|
});
|
|
355
355
|
}
|
|
356
356
|
|
|
357
|
-
function
|
|
357
|
+
function getTaskHealth(userId, agentId = null) {
|
|
358
358
|
const taskCount = agentId
|
|
359
359
|
? db.prepare('SELECT COUNT(*) AS count FROM scheduled_tasks WHERE user_id = ? AND agent_id = ?').get(userId, agentId)?.count || 0
|
|
360
360
|
: db.prepare('SELECT COUNT(*) AS count FROM scheduled_tasks WHERE user_id = ?').get(userId)?.count || 0;
|
|
@@ -363,8 +363,8 @@ function getSchedulerHealth(userId, agentId = null) {
|
|
|
363
363
|
configured: true,
|
|
364
364
|
healthy: true,
|
|
365
365
|
summary: taskCount > 0
|
|
366
|
-
? `${taskCount}
|
|
367
|
-
: 'No
|
|
366
|
+
? `${taskCount} task(s) exist for this user.`
|
|
367
|
+
: 'No tasks are configured.',
|
|
368
368
|
details: { taskCount },
|
|
369
369
|
});
|
|
370
370
|
}
|
|
@@ -385,7 +385,7 @@ async function getCapabilityHealth({ userId, agentId = null, app, engine }) {
|
|
|
385
385
|
integrations: getIntegrationHealth(userId, app, agentId),
|
|
386
386
|
mcp: getMcpHealth(userId, app, engine, agentId),
|
|
387
387
|
skills: getSkillHealth(app, engine),
|
|
388
|
-
|
|
388
|
+
tasks: getTaskHealth(userId, agentId),
|
|
389
389
|
},
|
|
390
390
|
};
|
|
391
391
|
}
|
|
@@ -459,6 +459,7 @@ function classifyToolExecution(toolName, toolArgs = {}, result, errorMessage = '
|
|
|
459
459
|
'recordings_list',
|
|
460
460
|
'recordings_get',
|
|
461
461
|
'recordings_search',
|
|
462
|
+
'list_tasks',
|
|
462
463
|
'wait_subagent',
|
|
463
464
|
]);
|
|
464
465
|
const stateChangingExact = new Set([
|
|
@@ -471,10 +472,9 @@ function classifyToolExecution(toolName, toolArgs = {}, result, errorMessage = '
|
|
|
471
472
|
'create_skill',
|
|
472
473
|
'update_skill',
|
|
473
474
|
'delete_skill',
|
|
474
|
-
'
|
|
475
|
-
'
|
|
476
|
-
'
|
|
477
|
-
'schedule_run',
|
|
475
|
+
'create_task',
|
|
476
|
+
'update_task',
|
|
477
|
+
'delete_task',
|
|
478
478
|
'create_ai_widget',
|
|
479
479
|
'update_ai_widget',
|
|
480
480
|
'delete_ai_widget',
|
|
@@ -503,8 +503,8 @@ function classifyToolExecution(toolName, toolArgs = {}, result, errorMessage = '
|
|
|
503
503
|
? 'command'
|
|
504
504
|
: name.includes('skill')
|
|
505
505
|
? 'skills'
|
|
506
|
-
: name
|
|
507
|
-
? '
|
|
506
|
+
: (name === 'create_task' || name === 'update_task' || name === 'delete_task' || name === 'list_tasks' || name.includes('widget'))
|
|
507
|
+
? 'tasks'
|
|
508
508
|
: name === 'send_message' || name === 'make_call'
|
|
509
509
|
? 'messaging'
|
|
510
510
|
: name.startsWith('recordings_') || name === 'read_health_data'
|
|
@@ -647,7 +647,7 @@ class AgentEngine {
|
|
|
647
647
|
this.messagingManager = services.messagingManager || null;
|
|
648
648
|
this.mcpManager = services.mcpManager || services.mcpClient || null;
|
|
649
649
|
this.skillRunner = services.skillRunner || null;
|
|
650
|
-
this.
|
|
650
|
+
this.taskRuntime = services.taskRuntime || null;
|
|
651
651
|
this.memoryManager = services.memoryManager || null;
|
|
652
652
|
this.voiceRuntimeManager = services.voiceRuntimeManager || null;
|
|
653
653
|
}
|
|
@@ -2495,7 +2495,7 @@ class AgentEngine {
|
|
|
2495
2495
|
messagingManager: this.messagingManager,
|
|
2496
2496
|
mcpManager: this.mcpManager,
|
|
2497
2497
|
skillRunner: this.skillRunner,
|
|
2498
|
-
|
|
2498
|
+
taskRuntime: this.taskRuntime,
|
|
2499
2499
|
memoryManager: this.memoryManager,
|
|
2500
2500
|
});
|
|
2501
2501
|
|
|
@@ -2832,7 +2832,7 @@ class AgentEngine {
|
|
|
2832
2832
|
if (toolName === 'send_message') return 'messaging';
|
|
2833
2833
|
if (toolName === 'make_call') return 'messaging';
|
|
2834
2834
|
if (toolName.startsWith('mcp_') || toolName.includes('mcp')) return 'mcp';
|
|
2835
|
-
if (toolName
|
|
2835
|
+
if (toolName === 'create_task' || toolName === 'update_task' || toolName === 'delete_task' || toolName === 'list_tasks' || toolName.includes('widget')) return 'tasks';
|
|
2836
2836
|
if (toolName.includes('subagent')) return 'subagent';
|
|
2837
2837
|
if (toolName === 'think') return 'thinking';
|
|
2838
2838
|
return 'tool';
|
|
@@ -79,8 +79,8 @@ REPORT ACTUAL RESULTS
|
|
|
79
79
|
When a tool returns data, share the relevant parts — summarized if large, direct if short. Never paste raw JSON as the answer. Never narrate what you're about to do at length before doing it.
|
|
80
80
|
Never promise an action in the final answer unless you already took that action in this run. Do not say "I'll check", "I'll fix it", or "I'll send it" and then stop. Either do it first or say you have not done it yet.
|
|
81
81
|
Do not promise future follow-up work unless that work will actually happen automatically before the current run ends.
|
|
82
|
-
For
|
|
83
|
-
If the user asks you to debug
|
|
82
|
+
For task-config changes, never claim that a task was created, updated, deleted, enabled, disabled, or “fixed” unless the corresponding task tool call succeeded in this run. If you did not verify the actual task config, say that clearly instead of guessing.
|
|
83
|
+
If the user asks you to debug task timing or trigger behavior, inspect the current task list first and separate three things clearly: what you observed, what you infer, and what you actually changed.
|
|
84
84
|
|
|
85
85
|
RELIABILITY
|
|
86
86
|
If a claim depends on current external facts, status, timelines, or ambiguous relative dates, verify it with fresh evidence before stating it as fact. When relative time could be misunderstood, anchor it to explicit calendar dates.
|
|
@@ -97,7 +97,7 @@ Not every result is worth a message. If background work completes and the output
|
|
|
97
97
|
|
|
98
98
|
MEMORY
|
|
99
99
|
If the user references past work or context, use session_search before asking them to repeat themselves. Surface relevant memory naturally — never announce that you're "accessing memory" or "retrieving context". Just know it.
|
|
100
|
-
Store only durable memory candidates. Do not turn recent
|
|
100
|
+
Store only durable memory candidates. Do not turn recent task runs, task execution recaps, last-run statuses, or similar operational noise into long-term memory.
|
|
101
101
|
Never rely on memory alone for risky actions, private data changes, payments, sending messages, or current factual claims. Use memory to guide search and interpretation, then verify with the appropriate source.
|
|
102
102
|
Update core memory only for standing preferences, stable user facts, or durable agent-behavior preferences. For ordinary task facts, use regular memory or do nothing.
|
|
103
103
|
|
|
@@ -137,12 +137,12 @@ Messages to the user in the active conversation do not need extra confirmation.
|
|
|
137
137
|
When drafting on behalf of the user, match their likely voice from available context and relationship to the recipient. Keep the draft editable and do not send it until the user approves, unless the current message explicitly says to send.
|
|
138
138
|
If the user approves a previously shown draft, send that draft rather than silently rewriting it.
|
|
139
139
|
|
|
140
|
-
|
|
141
|
-
Use one-time
|
|
140
|
+
TASKS
|
|
141
|
+
Use one-time schedule triggers for single reminders or delayed actions, recurring schedule triggers for repeating automation, and official integration triggers when the task should react to connected Gmail, Outlook, Slack, Teams, or WhatsApp Personal events. Make task prompts self-contained: who/what to check, exact action to take, when to notify, and which channel to use if known.
|
|
142
142
|
Do not create vague tasks like "check this" when the future run would not know what "this" means. Resolve references into names, links, file paths, IDs, dates, and success criteria before saving the task.
|
|
143
143
|
For notification tasks, distinguish between notifying the user in their current messaging channel, emailing the user, and contacting someone else. Default reminders should notify the user through the active messaging channel unless the user explicitly asks for email, phone, or a third party.
|
|
144
|
-
When creating or updating a
|
|
145
|
-
For
|
|
144
|
+
When creating or updating a task, include whether it should notify every time, only on change, only on errors, or only when a condition is met. If unspecified, choose the least noisy useful behavior and say what you chose.
|
|
145
|
+
For tasks that may become stale, include an expiry condition or narrow scope when the user provided one.
|
|
146
146
|
|
|
147
147
|
SKILLS
|
|
148
148
|
Create or improve a skill only when it is clearly reusable, polished, and likely to matter again. Most completed tasks should not become skills.
|
|
@@ -49,7 +49,7 @@ const PLAN_PROMPT_INSTRUCTIONS = [
|
|
|
49
49
|
'Prefer native integrations and structured tools before browser automation or generic shell commands.',
|
|
50
50
|
'For external actions, include a step to draft or confirm before sending unless the user already gave explicit current-session approval.',
|
|
51
51
|
'For code or config changes, include inspection, scoped edit, and verification steps.',
|
|
52
|
-
'For
|
|
52
|
+
'For tasks that run later, make the future prompt self-contained and include notification conditions.',
|
|
53
53
|
];
|
|
54
54
|
const VERIFIER_PROMPT_INSTRUCTIONS = [
|
|
55
55
|
'Verify whether the draft final reply is adequately supported by the gathered evidence.',
|
|
@@ -58,14 +58,14 @@ const VERIFIER_PROMPT_INSTRUCTIONS = [
|
|
|
58
58
|
'A non-zero execute_command exit code means partial or failed shell evidence. Do not treat later sections of a chained shell command as observed unless they were verified separately.',
|
|
59
59
|
'A successful send_message or make_call means outbound delivery succeeded in this run unless a later messaging tool failed.',
|
|
60
60
|
'Any claim that an outbound action already happened (sent/submitted/called/"already done") must be backed by a successful outbound tool execution in this run. If not backed, rewrite the reply to "not sent yet" and provide a draft or next concrete step.',
|
|
61
|
-
'A successful
|
|
61
|
+
'A successful create_task or update_task tool call is required before claiming a task schedule changed.',
|
|
62
62
|
'If external evidence conflicts with memory, history, or another tool result, preserve the uncertainty instead of flattening it into a single confident claim.',
|
|
63
63
|
];
|
|
64
64
|
const EXECUTION_GUIDANCE_ACTION_LINES = [
|
|
65
65
|
'Act end-to-end. Run independent searches or inspections in parallel when possible. Prefer native integration tools and structured APIs over browser automation or shell scraping. Use exact IDs and required parameters; list or search first when you do not have them.',
|
|
66
66
|
'Use send_interim_update sparingly when a short real update or question would help.',
|
|
67
67
|
'When you must ask for missing required user input, ask once, then wait for the reply instead of re-asking in the same run.',
|
|
68
|
-
'For outbound messages, calls, emails, shared edits, installs, restarts, or
|
|
68
|
+
'For outbound messages, calls, emails, shared edits, installs, restarts, or task mutations, verify the action result before claiming it happened. If user confirmation is required and missing, draft or ask instead of sending.',
|
|
69
69
|
'Retry with alternative tools or approaches when one path fails. If evidence is still insufficient, say so explicitly instead of guessing.',
|
|
70
70
|
];
|
|
71
71
|
|
|
@@ -155,7 +155,7 @@ function compactToolResult(toolName, toolArgs = {}, toolResult, options = {}) {
|
|
|
155
155
|
});
|
|
156
156
|
break;
|
|
157
157
|
|
|
158
|
-
case '
|
|
158
|
+
case 'list_tasks':
|
|
159
159
|
envelope = trimObject({
|
|
160
160
|
tool: toolName,
|
|
161
161
|
status: toolResult?.success === false || toolResult?.error ? 'error' : 'ok',
|
|
@@ -167,9 +167,8 @@ function compactToolResult(toolName, toolArgs = {}, toolResult, options = {}) {
|
|
|
167
167
|
? toolResult.tasks.slice(0, 8).map((task) => trimObject({
|
|
168
168
|
id: task?.id,
|
|
169
169
|
name: task?.name,
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
oneTime: task?.oneTime,
|
|
170
|
+
triggerType: task?.triggerType,
|
|
171
|
+
triggerSummary: task?.triggerSummary,
|
|
173
172
|
enabled: task?.enabled,
|
|
174
173
|
...(task?.model ? { model: task.model } : {})
|
|
175
174
|
}))
|
|
@@ -217,10 +216,9 @@ function compactToolResult(toolName, toolArgs = {}, toolResult, options = {}) {
|
|
|
217
216
|
case 'memory_update_core':
|
|
218
217
|
case 'memory_read':
|
|
219
218
|
case 'memory_write':
|
|
220
|
-
case '
|
|
221
|
-
case '
|
|
222
|
-
case '
|
|
223
|
-
case 'update_scheduled_task':
|
|
219
|
+
case 'create_task':
|
|
220
|
+
case 'delete_task':
|
|
221
|
+
case 'update_task':
|
|
224
222
|
case 'create_ai_widget':
|
|
225
223
|
case 'update_ai_widget':
|
|
226
224
|
case 'delete_ai_widget':
|