tuna-agent 0.1.179 → 0.1.181
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.
|
@@ -445,8 +445,6 @@ export class ClaudeCodeAdapter {
|
|
|
445
445
|
durationMs: totalDurationMs,
|
|
446
446
|
sessionId,
|
|
447
447
|
});
|
|
448
|
-
await new Promise(resolve => setTimeout(resolve, 150));
|
|
449
|
-
ws.sendPMMessage(task.id, { sender: 'pm', content: 'Task completed.' });
|
|
450
448
|
this.trackMetrics('done', totalDurationMs, localAgentId);
|
|
451
449
|
console.log(`[ClaudeCode] Agent Team task ${task.id} completed (${(totalDurationMs / 1000).toFixed(1)}s)`);
|
|
452
450
|
// Post-task reflection with actual output (non-blocking)
|
|
@@ -803,11 +801,6 @@ export class ClaudeCodeAdapter {
|
|
|
803
801
|
})),
|
|
804
802
|
},
|
|
805
803
|
});
|
|
806
|
-
await new Promise(resolve => setTimeout(resolve, 150));
|
|
807
|
-
ws.sendPMMessage(task.id, {
|
|
808
|
-
sender: 'pm',
|
|
809
|
-
content: `Task completed.`,
|
|
810
|
-
});
|
|
811
804
|
console.log(`[ClaudeCode] Task ${task.id} completed`);
|
|
812
805
|
// Post-task reflection
|
|
813
806
|
this.runReflection(task, plan.summary, 'done', task.repoPath).catch(() => { });
|
package/dist/daemon/index.js
CHANGED
|
@@ -794,8 +794,6 @@ ${skillContent.slice(0, 15000)}`;
|
|
|
794
794
|
if (result.status === 'done' && !result.followUpMessage) {
|
|
795
795
|
const totalDuration = result.sessions.reduce((sum, s) => sum + (s.durationMs ?? 0), 0);
|
|
796
796
|
wsClient.sendTaskDone(taskId, { result: plan.summary, durationMs: totalDuration });
|
|
797
|
-
await new Promise(resolve => setTimeout(resolve, 150));
|
|
798
|
-
wsClient.sendPMMessage(taskId, { sender: 'pm', content: `Task completed.` });
|
|
799
797
|
}
|
|
800
798
|
else if (result.followUpMessage) {
|
|
801
799
|
userMessage = result.followUpMessage;
|
|
@@ -333,7 +333,7 @@ export async function executeSubtask(subtask, repoPath, contracts, callbacks, si
|
|
|
333
333
|
const result = await runClaude({
|
|
334
334
|
prompt: subtask.description,
|
|
335
335
|
cwd,
|
|
336
|
-
allowedTools: ['Read', 'Edit', 'Write', 'Bash', 'Glob', 'Grep'],
|
|
336
|
+
allowedTools: ['Read', 'Edit', 'Write', 'Bash', 'Glob', 'Grep', 'mcp__mem0', 'mcp__tuna-knowledge', 'mcp__tuna-idea', 'mcp__tuna-browser', 'mcp__appeeky'],
|
|
337
337
|
disallowedTools: ['AskUserQuestion'],
|
|
338
338
|
systemPrompt: buildSessionPrompt(subtask, contracts),
|
|
339
339
|
outputFormat: 'stream-json',
|
|
@@ -370,7 +370,7 @@ export async function executeSubtask(subtask, repoPath, contracts, callbacks, si
|
|
|
370
370
|
const resumeResult = await runClaude({
|
|
371
371
|
prompt: `The answer to your question "${question.question}" is: ${answer}\n\nContinue your work with this information.`,
|
|
372
372
|
cwd,
|
|
373
|
-
allowedTools: ['Read', 'Edit', 'Write', 'Bash', 'Glob', 'Grep'],
|
|
373
|
+
allowedTools: ['Read', 'Edit', 'Write', 'Bash', 'Glob', 'Grep', 'mcp__mem0', 'mcp__tuna-knowledge', 'mcp__tuna-idea', 'mcp__tuna-browser', 'mcp__appeeky'],
|
|
374
374
|
disallowedTools: ['AskUserQuestion'],
|
|
375
375
|
resumeSessionId: info.sessionId,
|
|
376
376
|
outputFormat: 'stream-json',
|
|
@@ -449,7 +449,7 @@ export async function executeSubtask(subtask, repoPath, contracts, callbacks, si
|
|
|
449
449
|
const resumeResult = await runClaude({
|
|
450
450
|
prompt: `The answer to your question "${fallbackQuestion.question}" is: ${answer}\n\nContinue your work with this information.`,
|
|
451
451
|
cwd,
|
|
452
|
-
allowedTools: ['Read', 'Edit', 'Write', 'Bash', 'Glob', 'Grep'],
|
|
452
|
+
allowedTools: ['Read', 'Edit', 'Write', 'Bash', 'Glob', 'Grep', 'mcp__mem0', 'mcp__tuna-knowledge', 'mcp__tuna-idea', 'mcp__tuna-browser', 'mcp__appeeky'],
|
|
453
453
|
disallowedTools: ['AskUserQuestion'],
|
|
454
454
|
resumeSessionId: info.sessionId,
|
|
455
455
|
outputFormat: 'stream-json',
|
package/dist/pm/planner.js
CHANGED
|
@@ -144,7 +144,7 @@ export async function planTask(task, onProgress, signal, onTextChunk, inputFiles
|
|
|
144
144
|
const result = await runClaude({
|
|
145
145
|
prompt: userPrompt,
|
|
146
146
|
cwd,
|
|
147
|
-
allowedTools: ['Read', 'Glob', 'Grep'],
|
|
147
|
+
allowedTools: ['Read', 'Glob', 'Grep', 'mcp__mem0', 'mcp__tuna-knowledge', 'mcp__tuna-idea'],
|
|
148
148
|
systemPrompt,
|
|
149
149
|
maxTurns,
|
|
150
150
|
outputFormat: 'stream-json',
|
|
@@ -287,17 +287,20 @@ User message: ${userMessage}`;
|
|
|
287
287
|
let firstDeltaMs = 0;
|
|
288
288
|
let deltaCount = 0;
|
|
289
289
|
const cwd = repoPath || path.join(os.homedir(), 'tuna-workspace');
|
|
290
|
+
let streamedText = '';
|
|
290
291
|
const result = await runClaude({
|
|
291
292
|
prompt: chatPrompt,
|
|
292
293
|
cwd,
|
|
293
294
|
resumeSessionId: pmSessionId || undefined,
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
295
|
+
// Read-only tools + knowledge/memory MCP: follow-ups like "check the skill
|
|
296
|
+
// list" need to actually look at files. No tools + 1 turn made the model
|
|
297
|
+
// attempt a tool call anyway and come back with an EMPTY result (silent task).
|
|
298
|
+
allowedTools: ['Read', 'Glob', 'Grep', 'mcp__mem0', 'mcp__tuna-knowledge', 'mcp__tuna-idea'],
|
|
299
|
+
maxTurns: 8,
|
|
297
300
|
outputFormat: 'stream-json',
|
|
298
301
|
includePartialMessages: true,
|
|
299
302
|
inputFiles,
|
|
300
|
-
onStreamLine:
|
|
303
|
+
onStreamLine: (data) => {
|
|
301
304
|
// Parse stream_event → content_block_delta for real token streaming
|
|
302
305
|
if (data.type === 'stream_event') {
|
|
303
306
|
const event = data.event;
|
|
@@ -305,15 +308,16 @@ User message: ${userMessage}`;
|
|
|
305
308
|
const delta = event.delta;
|
|
306
309
|
if (delta?.type === 'text_delta' && delta.text) {
|
|
307
310
|
deltaCount++;
|
|
311
|
+
streamedText += delta.text;
|
|
308
312
|
if (!firstDeltaMs) {
|
|
309
313
|
firstDeltaMs = Date.now();
|
|
310
314
|
console.log(`[PM] ⏱ first text delta: ${firstDeltaMs - chatStartMs}ms after chat start`);
|
|
311
315
|
}
|
|
312
|
-
onTextChunk(delta.text);
|
|
316
|
+
onTextChunk?.(delta.text);
|
|
313
317
|
}
|
|
314
318
|
}
|
|
315
319
|
}
|
|
316
|
-
}
|
|
320
|
+
},
|
|
317
321
|
signal,
|
|
318
322
|
});
|
|
319
323
|
const chatDoneMs = Date.now();
|
|
@@ -321,7 +325,11 @@ User message: ${userMessage}`;
|
|
|
321
325
|
if (result.isError) {
|
|
322
326
|
return { response: `Sorry, I encountered an error: ${result.result}`, sessionId: result.sessionId };
|
|
323
327
|
}
|
|
324
|
-
|
|
328
|
+
// A hit turn-cap (or odd stop) can yield an empty `result` even though text was
|
|
329
|
+
// streamed. Never return empty — a silent agent looks dead to the user.
|
|
330
|
+
const rawResult = result.result?.trim()
|
|
331
|
+
|| streamedText.trim()
|
|
332
|
+
|| 'Xin lỗi anh, phiên xử lý tin nhắn vừa rồi bị nghẽn (không có output). Anh nhắn lại giúp nhé.';
|
|
325
333
|
// Try extracting JSON plan
|
|
326
334
|
let jsonStr = null;
|
|
327
335
|
const codeBlockMatch = rawResult.match(/```(?:json)?\s*(\{[\s\S]*?"subtasks"[\s\S]*?\})\s*```/);
|
package/dist/utils/claude-cli.js
CHANGED
|
@@ -121,7 +121,7 @@ export function runClaude(options) {
|
|
|
121
121
|
}
|
|
122
122
|
// Always steer agents to answer the user in Vietnamese, regardless of the
|
|
123
123
|
// language of the task/skill/context. Merged with any caller system prompt.
|
|
124
|
-
const LANG_DIRECTIVE = 'ABSOLUTE OUTPUT RULES — these override everything else and apply to your ENTIRE response to the user: (1) Write 100% in Vietnamese (tiếng Việt). Never reply in English even when the task, skill, code or documents are in English; keep proper nouns / technical terms / commands / code as-is, but all explanation and prose MUST be Vietnamese. (2) Always address and refer to the user as "chủ tịch" (e.g. "Dạ chủ tịch", "Báo cáo chủ tịch", "Chủ tịch ơi"). Never use "bạn", "you", or the user\'s name to address them.';
|
|
124
|
+
const LANG_DIRECTIVE = 'ABSOLUTE OUTPUT RULES — these override everything else and apply to your ENTIRE response to the user: (1) Write 100% in Vietnamese (tiếng Việt). Never reply in English even when the task, skill, code or documents are in English; keep proper nouns / technical terms / commands / code as-is, but all explanation and prose MUST be Vietnamese. (2) Always address and refer to the user as "chủ tịch" (e.g. "Dạ chủ tịch", "Báo cáo chủ tịch", "Chủ tịch ơi"). Never use "bạn", "you", or the user\'s name to address them. (3) NEVER end your session with a promise of future work ("sẽ báo cáo sau", "sẽ làm tiếp khi có kết quả"...) — once your session ends, nothing resumes it, so that promise is a lie. If you started long-running/background work, WAIT for it inside this session (poll its output until it finishes) and deliver the actual result before ending. Only if it is truly impossible to finish, state clearly what is blocked and exactly what the user should say to resume it.';
|
|
125
125
|
const mergedSystemPrompt = options.systemPrompt
|
|
126
126
|
? `${options.systemPrompt}\n\n${LANG_DIRECTIVE}`
|
|
127
127
|
: LANG_DIRECTIVE;
|