snow-ai 0.3.30 โ 0.3.31
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/api/systemPrompt.js
CHANGED
|
@@ -176,6 +176,18 @@ const SYSTEM_PROMPT_TEMPLATE = `You are Snow AI CLI, an intelligent command-line
|
|
|
176
176
|
- \`notebook-query\` - Manual search (rarely needed, auto-shown when reading files)
|
|
177
177
|
- ๐ Auto-attached: Last 10 notebooks appear when reading ANY file
|
|
178
178
|
- ๐ก Use before: Adding features that might affect existing behavior
|
|
179
|
+
- \`notebook-update\` - Update existing note to fix mistakes or refine information
|
|
180
|
+
- โ๏ธ Fix errors in previously recorded notes
|
|
181
|
+
- ๐ Clarify or improve wording after better understanding
|
|
182
|
+
- ๐ Update note when code changes but constraint still applies
|
|
183
|
+
- \`notebook-delete\` - Remove outdated or incorrect notes
|
|
184
|
+
- ๐๏ธ Delete when code is refactored and note is obsolete
|
|
185
|
+
- โ Remove notes recorded by mistake
|
|
186
|
+
- ๐งน Clean up after workarounds are properly fixed
|
|
187
|
+
- \`notebook-list\` - View all notes for a specific file
|
|
188
|
+
- ๐ List all constraints for a file before making changes
|
|
189
|
+
- ๐ Find note IDs for update/delete operations
|
|
190
|
+
- ๐ง Review all warnings before refactoring
|
|
179
191
|
|
|
180
192
|
**Web Search:**
|
|
181
193
|
- \`websearch-search\` - Search web for latest docs/solutions
|
|
@@ -189,13 +201,103 @@ manipulation, workflow automation, and complex command chaining to solve sophist
|
|
|
189
201
|
system administration and data processing challenges.
|
|
190
202
|
|
|
191
203
|
**Sub-Agent:**
|
|
192
|
-
*If you don't have a sub-agent tool, ignore this feature*
|
|
193
|
-
- A sub-agent is a separate session isolated from the main session, and a sub-agent may have some of the tools described above to focus on solving a specific problem.
|
|
194
|
-
If you have a sub-agent tool, then you can leave some of the work to the sub-agent to solve.
|
|
195
|
-
For example, if you have a sub-agent of a work plan, you can hand over the work plan to the sub-agent to solve when you receive user requirements.
|
|
196
|
-
This way, the master agent can focus on task fulfillment.
|
|
197
204
|
|
|
198
|
-
|
|
205
|
+
### ๐ฏ CRITICAL: AGGRESSIVE DELEGATION TO SUB-AGENTS
|
|
206
|
+
|
|
207
|
+
**โก Core Principle: MAXIMIZE context saving by delegating as much work as possible to sub-agents!**
|
|
208
|
+
|
|
209
|
+
**๐ฅ WHY DELEGATE AGGRESSIVELY:**
|
|
210
|
+
- ๐พ **Save Main Context** - Each delegated task saves thousands of tokens in the main session
|
|
211
|
+
- ๐ **Parallel Processing** - Sub-agents work independently without cluttering main context
|
|
212
|
+
- ๐ฏ **Focused Sessions** - Sub-agents have dedicated context for specific tasks
|
|
213
|
+
- ๐ **Scalability** - Main agent stays lean and efficient even for complex projects
|
|
214
|
+
|
|
215
|
+
**๐ DELEGATION STRATEGY - DEFAULT TO SUB-AGENT:**
|
|
216
|
+
|
|
217
|
+
**โ
ALWAYS DELEGATE (High Priority):**
|
|
218
|
+
- ๐ **Code Analysis & Planning** - File structure analysis, architecture review, impact analysis
|
|
219
|
+
- ๐ **Research Tasks** - Investigating patterns, finding similar code, exploring codebase
|
|
220
|
+
- ๐บ๏ธ **Work Planning** - Breaking down requirements, creating task plans, designing solutions
|
|
221
|
+
- ๐ **Documentation Review** - Reading and summarizing large files, extracting key information
|
|
222
|
+
- ๐ **Dependency Mapping** - Finding all imports, exports, references across files
|
|
223
|
+
- ๐งช **Test Planning** - Analyzing what needs testing, planning test cases
|
|
224
|
+
- ๐ง **Refactoring Analysis** - Identifying refactoring opportunities, impact assessment
|
|
225
|
+
|
|
226
|
+
**โ
STRONGLY CONSIDER DELEGATING:**
|
|
227
|
+
- ๐ **Bug Investigation** - Root cause analysis, reproduction steps, related code search
|
|
228
|
+
- ๐ **Migration Planning** - Planning API changes, version upgrades, dependency updates
|
|
229
|
+
- ๐ **Design Reviews** - Evaluating architectural decisions, pattern consistency
|
|
230
|
+
- ๐ **Code Quality Checks** - Finding code smells, inconsistencies, potential issues
|
|
231
|
+
|
|
232
|
+
**โ ๏ธ KEEP IN MAIN AGENT (Low Volume):**
|
|
233
|
+
- โ๏ธ **Direct Code Edits** - Simple, well-understood modifications
|
|
234
|
+
- ๐จ **Quick Fixes** - Single-file changes with clear context
|
|
235
|
+
- โก **Immediate Actions** - Terminal commands, file operations
|
|
236
|
+
|
|
237
|
+
**๐ฏ DELEGATION WORKFLOW:**
|
|
238
|
+
|
|
239
|
+
1. **Receive User Request** โ Immediately consider: "Can a sub-agent handle the analysis/planning?"
|
|
240
|
+
2. **Complex Task** โ Delegate research/planning to sub-agent, wait for result, then execute
|
|
241
|
+
3. **Multi-Step Task** โ Delegate planning to sub-agent, receive roadmap, execute in main
|
|
242
|
+
4. **Unfamiliar Code** โ Delegate exploration to sub-agent, get summary, then modify
|
|
243
|
+
|
|
244
|
+
**๐ก PRACTICAL EXAMPLES:**
|
|
245
|
+
|
|
246
|
+
โ **BAD - Doing everything in main agent:**
|
|
247
|
+
- User: "Add user authentication"
|
|
248
|
+
- Main: *reads 20 files, analyzes auth patterns, plans implementation, writes code*
|
|
249
|
+
- Result: Main context bloated with analysis that won't be reused
|
|
250
|
+
|
|
251
|
+
โ
**GOOD - Aggressive delegation:**
|
|
252
|
+
- User: "Add user authentication"
|
|
253
|
+
- Main: Delegate to sub-agent โ "Analyze current auth patterns and create implementation plan"
|
|
254
|
+
- Sub-agent: *analyzes, returns concise plan*
|
|
255
|
+
- Main: Execute plan with focused context
|
|
256
|
+
- Result: Main context stays lean, only contains execution context
|
|
257
|
+
|
|
258
|
+
**๐ง USAGE RULES:**
|
|
259
|
+
|
|
260
|
+
1. **When tool available**: Check if you have \`subagent-agent_*\` tools in your toolkit
|
|
261
|
+
2. **Explicit user request**: User message contains \`#agent_*\` โ MUST use that specific sub-agent
|
|
262
|
+
3. **Implicit delegation**: Even without \`#agent_*\`, proactively delegate analysis/planning tasks
|
|
263
|
+
4. **Return focus**: After sub-agent responds, main agent focuses purely on execution
|
|
264
|
+
|
|
265
|
+
**๐ REMEMBER: If it's not direct code editing or immediate action, consider delegating to sub-agent first!**
|
|
266
|
+
|
|
267
|
+
**๐ฒ DECISION TREE - When to Delegate to Sub-Agent:**
|
|
268
|
+
|
|
269
|
+
\`\`\`
|
|
270
|
+
๐ฅ User Request
|
|
271
|
+
โ
|
|
272
|
+
โ Can a sub-agent handle this task?
|
|
273
|
+
โโ โ
YES โ ๐ DELEGATE to sub-agent
|
|
274
|
+
โ โโ Code search/exploration
|
|
275
|
+
โ โโ Analysis & planning
|
|
276
|
+
โ โโ Research & investigation
|
|
277
|
+
โ โโ Architecture review
|
|
278
|
+
โ โโ Impact assessment
|
|
279
|
+
โ โโ Dependency mapping
|
|
280
|
+
โ โโ Documentation review
|
|
281
|
+
โ โโ Test planning
|
|
282
|
+
โ โโ Bug investigation
|
|
283
|
+
โ โโ Pattern finding
|
|
284
|
+
โ โโ ANY task sub-agent can do
|
|
285
|
+
โ
|
|
286
|
+
โโ โ NO โ Execute directly in main agent
|
|
287
|
+
โโ Direct code editing (clear target)
|
|
288
|
+
โโ File operations (create/delete)
|
|
289
|
+
โโ Simple terminal commands
|
|
290
|
+
โโ Immediate actions (no research needed)
|
|
291
|
+
\`\`\`
|
|
292
|
+
|
|
293
|
+
**๐ฏ Golden Rule:**
|
|
294
|
+
**"If sub-agent CAN do it โ sub-agent SHOULD do it"**
|
|
295
|
+
|
|
296
|
+
**Decision in 3 seconds:**
|
|
297
|
+
1. โ Does this need research/exploration/planning? โ **Delegate**
|
|
298
|
+
2. โ Is this a straightforward code edit? โ **Execute directly**
|
|
299
|
+
3. โ ๏ธ **When in doubt** โ **Delegate to sub-agent** (safer default)
|
|
300
|
+
|
|
199
301
|
|
|
200
302
|
## ๐ Quality Assurance
|
|
201
303
|
|
|
@@ -692,6 +692,21 @@ export async function handleConversationWithTools(options) {
|
|
|
692
692
|
}, requestToolConfirmation, isToolAutoApproved, yoloMode, addToAlwaysApproved);
|
|
693
693
|
// Check if aborted during tool execution
|
|
694
694
|
if (controller.signal.aborted) {
|
|
695
|
+
// Need to add tool results for all pending tool calls to complete conversation history
|
|
696
|
+
// This is critical for sub-agents and any tools that were being executed
|
|
697
|
+
if (receivedToolCalls && receivedToolCalls.length > 0) {
|
|
698
|
+
for (const toolCall of receivedToolCalls) {
|
|
699
|
+
const abortedResult = {
|
|
700
|
+
role: 'tool',
|
|
701
|
+
tool_call_id: toolCall.id,
|
|
702
|
+
content: 'Error: Tool execution aborted by user',
|
|
703
|
+
};
|
|
704
|
+
conversationMessages.push(abortedResult);
|
|
705
|
+
saveMessage(abortedResult).catch(error => {
|
|
706
|
+
console.error('Failed to save aborted tool result:', error);
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
}
|
|
695
710
|
freeEncoder();
|
|
696
711
|
break;
|
|
697
712
|
}
|
package/dist/mcp/notebook.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { addNotebook, queryNotebook } from '../utils/notebookManager.js';
|
|
1
|
+
import { addNotebook, queryNotebook, updateNotebook, deleteNotebook, getNotebooksByFile, } from '../utils/notebookManager.js';
|
|
2
2
|
/**
|
|
3
3
|
* Notebook MCP ๅทฅๅ
ทๅฎไน
|
|
4
4
|
* ็จไบไปฃ็ ๅคๅฟๅฝ็ฎก็๏ผๅธฎๅฉAI่ฎฐๅฝ้่ฆ็ไปฃ็ ๆณจๆไบ้กน
|
|
@@ -60,6 +60,91 @@ export const mcpTools = [
|
|
|
60
60
|
},
|
|
61
61
|
},
|
|
62
62
|
},
|
|
63
|
+
{
|
|
64
|
+
name: 'notebook-update',
|
|
65
|
+
description: `โ๏ธ Update an existing notebook entry to fix mistakes or refine notes.
|
|
66
|
+
|
|
67
|
+
**Core Purpose:** Correct errors in previously recorded notes or update outdated information.
|
|
68
|
+
|
|
69
|
+
**When to use:**
|
|
70
|
+
- Found a mistake in a previously recorded note
|
|
71
|
+
- Need to clarify or improve the wording
|
|
72
|
+
- Update note after code changes
|
|
73
|
+
- Refine warning messages for better clarity
|
|
74
|
+
|
|
75
|
+
**Usage:**
|
|
76
|
+
1. Use notebook-query or notebook-list to find the entry ID
|
|
77
|
+
2. Call notebook-update with the ID and new note content
|
|
78
|
+
|
|
79
|
+
**Example:**
|
|
80
|
+
- Old: "โ ๏ธ Don't change this"
|
|
81
|
+
- New: "โ ๏ธ validateInput() MUST be called first - parser depends on sanitized input"`,
|
|
82
|
+
inputSchema: {
|
|
83
|
+
type: 'object',
|
|
84
|
+
properties: {
|
|
85
|
+
notebookId: {
|
|
86
|
+
type: 'string',
|
|
87
|
+
description: 'Notebook entry ID to update (get from notebook-query or notebook-list)',
|
|
88
|
+
},
|
|
89
|
+
note: {
|
|
90
|
+
type: 'string',
|
|
91
|
+
description: 'New note content to replace the existing one',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
required: ['notebookId', 'note'],
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: 'notebook-delete',
|
|
99
|
+
description: `๐๏ธ Delete an outdated or incorrect notebook entry.
|
|
100
|
+
|
|
101
|
+
**Core Purpose:** Remove notes that are no longer relevant or were recorded by mistake.
|
|
102
|
+
|
|
103
|
+
**When to use:**
|
|
104
|
+
- Code has been refactored and note is obsolete
|
|
105
|
+
- Note was recorded by mistake
|
|
106
|
+
- Workaround has been properly fixed
|
|
107
|
+
- Entry is duplicate or redundant
|
|
108
|
+
|
|
109
|
+
**Usage:**
|
|
110
|
+
1. Use notebook-query or notebook-list to find the entry ID
|
|
111
|
+
2. Call notebook-delete with the ID to remove it
|
|
112
|
+
|
|
113
|
+
**โ ๏ธ Warning:** Deletion is permanent. Make sure the note is truly obsolete.`,
|
|
114
|
+
inputSchema: {
|
|
115
|
+
type: 'object',
|
|
116
|
+
properties: {
|
|
117
|
+
notebookId: {
|
|
118
|
+
type: 'string',
|
|
119
|
+
description: 'Notebook entry ID to delete (get from notebook-query)',
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
required: ['notebookId'],
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: 'notebook-list',
|
|
127
|
+
description: `๐ List all notebook entries for a specific file.
|
|
128
|
+
|
|
129
|
+
**Core Purpose:** View all notes associated with a particular file for management.
|
|
130
|
+
|
|
131
|
+
**When to use:**
|
|
132
|
+
- Need to see all notes for a file before editing
|
|
133
|
+
- Want to clean up old notes for a specific file
|
|
134
|
+
- Review constraints before making changes to a file
|
|
135
|
+
|
|
136
|
+
**Returns:** All notebook entries for the specified file, ordered by creation time.`,
|
|
137
|
+
inputSchema: {
|
|
138
|
+
type: 'object',
|
|
139
|
+
properties: {
|
|
140
|
+
filePath: {
|
|
141
|
+
type: 'string',
|
|
142
|
+
description: 'File path (relative or absolute) to list notebooks for',
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
required: ['filePath'],
|
|
146
|
+
},
|
|
147
|
+
},
|
|
63
148
|
];
|
|
64
149
|
/**
|
|
65
150
|
* ๆง่ก Notebook ๅทฅๅ
ท
|
|
@@ -135,6 +220,127 @@ export async function executeNotebookTool(toolName, args) {
|
|
|
135
220
|
],
|
|
136
221
|
};
|
|
137
222
|
}
|
|
223
|
+
case 'notebook-update': {
|
|
224
|
+
const { notebookId, note } = args;
|
|
225
|
+
if (!notebookId || !note) {
|
|
226
|
+
return {
|
|
227
|
+
content: [
|
|
228
|
+
{
|
|
229
|
+
type: 'text',
|
|
230
|
+
text: 'Error: Both notebookId and note are required',
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
isError: true,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
const updatedEntry = updateNotebook(notebookId, note);
|
|
237
|
+
if (!updatedEntry) {
|
|
238
|
+
return {
|
|
239
|
+
content: [
|
|
240
|
+
{
|
|
241
|
+
type: 'text',
|
|
242
|
+
text: JSON.stringify({
|
|
243
|
+
success: false,
|
|
244
|
+
message: `Notebook entry not found: ${notebookId}`,
|
|
245
|
+
}, null, 2),
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
isError: true,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
content: [
|
|
253
|
+
{
|
|
254
|
+
type: 'text',
|
|
255
|
+
text: JSON.stringify({
|
|
256
|
+
success: true,
|
|
257
|
+
message: `Notebook entry updated: ${notebookId}`,
|
|
258
|
+
entry: {
|
|
259
|
+
id: updatedEntry.id,
|
|
260
|
+
filePath: updatedEntry.filePath,
|
|
261
|
+
note: updatedEntry.note,
|
|
262
|
+
updatedAt: updatedEntry.updatedAt,
|
|
263
|
+
},
|
|
264
|
+
}, null, 2),
|
|
265
|
+
},
|
|
266
|
+
],
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
case 'notebook-delete': {
|
|
270
|
+
const { notebookId } = args;
|
|
271
|
+
if (!notebookId) {
|
|
272
|
+
return {
|
|
273
|
+
content: [
|
|
274
|
+
{
|
|
275
|
+
type: 'text',
|
|
276
|
+
text: 'Error: notebookId is required',
|
|
277
|
+
},
|
|
278
|
+
],
|
|
279
|
+
isError: true,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
const deleted = deleteNotebook(notebookId);
|
|
283
|
+
if (!deleted) {
|
|
284
|
+
return {
|
|
285
|
+
content: [
|
|
286
|
+
{
|
|
287
|
+
type: 'text',
|
|
288
|
+
text: JSON.stringify({
|
|
289
|
+
success: false,
|
|
290
|
+
message: `Notebook entry not found: ${notebookId}`,
|
|
291
|
+
}, null, 2),
|
|
292
|
+
},
|
|
293
|
+
],
|
|
294
|
+
isError: true,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
return {
|
|
298
|
+
content: [
|
|
299
|
+
{
|
|
300
|
+
type: 'text',
|
|
301
|
+
text: JSON.stringify({
|
|
302
|
+
success: true,
|
|
303
|
+
message: `Notebook entry deleted: ${notebookId}`,
|
|
304
|
+
}, null, 2),
|
|
305
|
+
},
|
|
306
|
+
],
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
case 'notebook-list': {
|
|
310
|
+
const { filePath } = args;
|
|
311
|
+
if (!filePath) {
|
|
312
|
+
return {
|
|
313
|
+
content: [
|
|
314
|
+
{
|
|
315
|
+
type: 'text',
|
|
316
|
+
text: 'Error: filePath is required',
|
|
317
|
+
},
|
|
318
|
+
],
|
|
319
|
+
isError: true,
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
const entries = getNotebooksByFile(filePath);
|
|
323
|
+
return {
|
|
324
|
+
content: [
|
|
325
|
+
{
|
|
326
|
+
type: 'text',
|
|
327
|
+
text: JSON.stringify({
|
|
328
|
+
message: entries.length > 0
|
|
329
|
+
? `Found ${entries.length} notebook entries for: ${filePath}`
|
|
330
|
+
: `No notebook entries found for: ${filePath}`,
|
|
331
|
+
filePath,
|
|
332
|
+
totalEntries: entries.length,
|
|
333
|
+
entries: entries.map(entry => ({
|
|
334
|
+
id: entry.id,
|
|
335
|
+
note: entry.note,
|
|
336
|
+
createdAt: entry.createdAt,
|
|
337
|
+
updatedAt: entry.updatedAt,
|
|
338
|
+
})),
|
|
339
|
+
}, null, 2),
|
|
340
|
+
},
|
|
341
|
+
],
|
|
342
|
+
};
|
|
343
|
+
}
|
|
138
344
|
default:
|
|
139
345
|
return {
|
|
140
346
|
content: [
|
|
@@ -28,6 +28,13 @@ export declare function queryNotebook(filePathPattern?: string, topN?: number):
|
|
|
28
28
|
* @returns ่ฏฅๆไปถ็ๆๆๅคๅฟๅฝ
|
|
29
29
|
*/
|
|
30
30
|
export declare function getNotebooksByFile(filePath: string): NotebookEntry[];
|
|
31
|
+
/**
|
|
32
|
+
* ๆดๆฐๅคๅฟๅฝๅ
ๅฎน
|
|
33
|
+
* @param notebookId ๅคๅฟๅฝID
|
|
34
|
+
* @param newNote ๆฐ็ๅคๅฟ่ฏดๆ
|
|
35
|
+
* @returns ๆดๆฐๅ็ๅคๅฟๅฝๆก็ฎ๏ผๅฆๆๆชๆพๅฐๅ่ฟๅnull
|
|
36
|
+
*/
|
|
37
|
+
export declare function updateNotebook(notebookId: string, newNote: string): NotebookEntry | null;
|
|
31
38
|
/**
|
|
32
39
|
* ๅ ้คๅคๅฟๅฝ
|
|
33
40
|
* @param notebookId ๅคๅฟๅฝID
|
|
@@ -130,6 +130,31 @@ export function getNotebooksByFile(filePath) {
|
|
|
130
130
|
const data = readNotebookData();
|
|
131
131
|
return data[normalizedPath] || [];
|
|
132
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* ๆดๆฐๅคๅฟๅฝๅ
ๅฎน
|
|
135
|
+
* @param notebookId ๅคๅฟๅฝID
|
|
136
|
+
* @param newNote ๆฐ็ๅคๅฟ่ฏดๆ
|
|
137
|
+
* @returns ๆดๆฐๅ็ๅคๅฟๅฝๆก็ฎ๏ผๅฆๆๆชๆพๅฐๅ่ฟๅnull
|
|
138
|
+
*/
|
|
139
|
+
export function updateNotebook(notebookId, newNote) {
|
|
140
|
+
const data = readNotebookData();
|
|
141
|
+
let updatedEntry = null;
|
|
142
|
+
for (const [, entries] of Object.entries(data)) {
|
|
143
|
+
const entry = entries.find(e => e.id === notebookId);
|
|
144
|
+
if (entry) {
|
|
145
|
+
// ๆดๆฐ็ฌ่ฎฐๅ
ๅฎนๅๆดๆฐๆถ้ด
|
|
146
|
+
entry.note = newNote;
|
|
147
|
+
const now = new Date();
|
|
148
|
+
entry.updatedAt = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}T${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}.${String(now.getMilliseconds()).padStart(3, '0')}`;
|
|
149
|
+
updatedEntry = entry;
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (updatedEntry) {
|
|
154
|
+
saveNotebookData(data);
|
|
155
|
+
}
|
|
156
|
+
return updatedEntry;
|
|
157
|
+
}
|
|
133
158
|
/**
|
|
134
159
|
* ๅ ้คๅคๅฟๅฝ
|
|
135
160
|
* @param notebookId ๅคๅฟๅฝID
|
|
@@ -70,8 +70,19 @@ export async function executeSubAgent(agentId, prompt, onMessage, abortSignal, r
|
|
|
70
70
|
const sessionApprovedTools = new Set();
|
|
71
71
|
// eslint-disable-next-line no-constant-condition
|
|
72
72
|
while (true) {
|
|
73
|
-
// Check abort signal
|
|
73
|
+
// Check abort signal before streaming
|
|
74
74
|
if (abortSignal?.aborted) {
|
|
75
|
+
// Send done message to mark completion (like normal tool abort)
|
|
76
|
+
if (onMessage) {
|
|
77
|
+
onMessage({
|
|
78
|
+
type: 'sub_agent_message',
|
|
79
|
+
agentId: agent.id,
|
|
80
|
+
agentName: agent.name,
|
|
81
|
+
message: {
|
|
82
|
+
type: 'done',
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
}
|
|
75
86
|
return {
|
|
76
87
|
success: false,
|
|
77
88
|
result: finalResponse,
|
|
@@ -200,6 +211,17 @@ export async function executeSubAgent(agentId, prompt, onMessage, abortSignal, r
|
|
|
200
211
|
}
|
|
201
212
|
// Handle rejected tools
|
|
202
213
|
if (rejectedToolCalls.length > 0) {
|
|
214
|
+
// Send done message to mark completion when tools are rejected
|
|
215
|
+
if (onMessage) {
|
|
216
|
+
onMessage({
|
|
217
|
+
type: 'sub_agent_message',
|
|
218
|
+
agentId: agent.id,
|
|
219
|
+
agentName: agent.name,
|
|
220
|
+
message: {
|
|
221
|
+
type: 'done',
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
}
|
|
203
225
|
return {
|
|
204
226
|
success: false,
|
|
205
227
|
result: finalResponse,
|
|
@@ -211,6 +233,25 @@ export async function executeSubAgent(agentId, prompt, onMessage, abortSignal, r
|
|
|
211
233
|
// Execute approved tool calls
|
|
212
234
|
const toolResults = [];
|
|
213
235
|
for (const toolCall of approvedToolCalls) {
|
|
236
|
+
// Check abort signal before executing each tool
|
|
237
|
+
if (abortSignal?.aborted) {
|
|
238
|
+
// Send done message to mark completion
|
|
239
|
+
if (onMessage) {
|
|
240
|
+
onMessage({
|
|
241
|
+
type: 'sub_agent_message',
|
|
242
|
+
agentId: agent.id,
|
|
243
|
+
agentName: agent.name,
|
|
244
|
+
message: {
|
|
245
|
+
type: 'done',
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
success: false,
|
|
251
|
+
result: finalResponse,
|
|
252
|
+
error: 'Sub-agent execution aborted during tool execution',
|
|
253
|
+
};
|
|
254
|
+
}
|
|
214
255
|
try {
|
|
215
256
|
const args = JSON.parse(toolCall.function.arguments);
|
|
216
257
|
const result = await executeMCPTool(toolCall.function.name, args, abortSignal);
|