tuna-agent 0.1.173 → 0.1.175

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.
@@ -558,14 +558,11 @@ export class ClaudeCodeAdapter {
558
558
  pmSessionId = chatResult.sessionId || pmSessionId;
559
559
  // Update persisted PM session ID
560
560
  savePMState({ taskId: task.id, pmSessionId, repoPath: task.repoPath, savedAt: new Date().toISOString(), agentId: task.agentId });
561
- // PM produced a plan with subtasks → break out to execution
561
+ // PM produced a plan with subtasks → break out to execution.
562
+ // (No "Got it! <summary>" message — plan_ready already conveys the summary;
563
+ // sending both duplicated it and added a robotic English prefix.)
562
564
  if (chatResult.plan && chatResult.plan.subtasks.length > 0) {
563
565
  planResult = { plan: chatResult.plan, pmSessionId };
564
- ws.sendPMMessage(task.id, {
565
- sender: 'pm',
566
- content: `Got it! ${chatResult.plan.summary}`,
567
- startedAt: firstChunkIso || undefined,
568
- });
569
566
  break;
570
567
  }
571
568
  // PM responded conversationally — send to app and update latest message
@@ -709,11 +706,8 @@ export class ClaudeCodeAdapter {
709
706
  const { text: answer } = await waitForInput(task.id, pendingInputResolvers);
710
707
  console.log(`[ClaudeCode] User answered: ${answer.substring(0, 80)}`);
711
708
  pmAnswers.push({ question: q.question, answer });
712
- ws.sendPMMessage(task.id, {
713
- sender: 'pm',
714
- content: `Got it! Proceeding with: ${answer.substring(0, 100)}${answer.length > 100 ? '...' : ''}`,
715
- });
716
- // Delay to ensure "Got it!" is saved to DB before next question triggers refetch
709
+ // (No robotic "Got it! Proceeding with…" ack — the agent just continues.)
710
+ // Small delay to avoid a refetch race before the next question.
717
711
  await new Promise(resolve => setTimeout(resolve, 200));
718
712
  }
719
713
  }
@@ -730,22 +724,12 @@ export class ClaudeCodeAdapter {
730
724
  // Step 4: Execute subtasks
731
725
  console.log(`[ClaudeCode] Starting execution for task ${task.id}`);
732
726
  ws.sendProgress(task.id, 'executing', { startedAt: new Date().toISOString() });
733
- ws.sendPMMessage(task.id, {
734
- sender: 'pm',
735
- content: "Starting execution now. I'll keep you updated as each session progresses.",
736
- });
737
727
  // Step 4-6: Execute plan with follow-up loop
738
728
  const allSessions = [];
739
729
  let lastStatus = 'done';
740
730
  const MAX_FOLLOW_UP_ROUNDS = 10;
741
731
  for (let followUpRound = 0; followUpRound <= MAX_FOLLOW_UP_ROUNDS; followUpRound++) {
742
732
  ws.sendProgress(task.id, 'executing', { startedAt: new Date().toISOString() });
743
- if (followUpRound === 0) {
744
- ws.sendPMMessage(task.id, {
745
- sender: 'pm',
746
- content: "Starting execution now. I'll keep you updated as each session progresses.",
747
- });
748
- }
749
733
  const result = await executePlanAndReport(task, plan, ws, pendingInputResolvers, signal, confirmBeforeEdit, onPermissionRequest);
750
734
  allSessions.push(...result.sessions);
751
735
  lastStatus = result.status;
@@ -777,7 +777,7 @@ ${skillContent.slice(0, 15000)}`;
777
777
  // PM produced a plan → execute it using shared helper
778
778
  if (chatResult.plan && chatResult.plan.subtasks.length > 0) {
779
779
  const plan = chatResult.plan;
780
- wsClient.sendPMMessage(taskId, { sender: 'pm', content: `Got it! ${plan.summary}`, startedAt: firstChunkIso || undefined });
780
+ // (No "Got it! <summary>" plan_ready already conveys the summary.)
781
781
  wsClient.sendPlanReady(taskId, {
782
782
  summary: plan.summary,
783
783
  subtasks: plan.subtasks.map((s) => ({
@@ -65,11 +65,15 @@ export function buildExecutionCallbacks(taskId, plan, ws, resolvers, onPermissio
65
65
  role: subtask.role,
66
66
  description: subtask.description,
67
67
  });
68
- await new Promise(resolve => setTimeout(resolve, 100));
69
- ws.sendPMMessage(taskId, {
70
- sender: 'system',
71
- content: `${capitalize(subtask.role)} session started`,
72
- });
68
+ // Only announce a "session started" for real multi-role dev teams.
69
+ // A single 'self' agent doing its own work needs no orchestration noise.
70
+ if (subtask.role !== 'self') {
71
+ await new Promise(resolve => setTimeout(resolve, 100));
72
+ ws.sendPMMessage(taskId, {
73
+ sender: 'system',
74
+ content: `${capitalize(subtask.role)} session started`,
75
+ });
76
+ }
73
77
  }
74
78
  },
75
79
  onSubtaskLog: async (subtaskId, logData) => {
@@ -92,9 +96,13 @@ export function buildExecutionCallbacks(taskId, plan, ws, resolvers, onPermissio
92
96
  const durationStr = durationMs ? `${(durationMs / 1000).toFixed(1)}s` : '';
93
97
  const resultPreview = rawResult ? simplifyMarkdown(rawResult) : '';
94
98
  await new Promise(resolve => setTimeout(resolve, 100));
99
+ const isSelf = subtask?.role === 'self';
95
100
  ws.sendPMMessage(taskId, {
96
101
  sender: 'pm',
97
- content: `${roleName} completed successfully${durationStr ? ` in ${durationStr}` : ''}${resultPreview ? `\n\n${resultPreview}` : ''}`,
102
+ // Single 'self' agent: just deliver the result, no "X completed successfully" scaffolding.
103
+ content: isSelf
104
+ ? (resultPreview || 'Xong ạ.')
105
+ : `${roleName} completed successfully${durationStr ? ` in ${durationStr}` : ''}${resultPreview ? `\n\n${resultPreview}` : ''}`,
98
106
  });
99
107
  }
100
108
  else if (session.status === 'failed') {
@@ -109,9 +117,10 @@ export function buildExecutionCallbacks(taskId, plan, ws, resolvers, onPermissio
109
117
  onSubtaskNeedsInput: async (subtaskId, question) => {
110
118
  const subtask = plan.subtasks.find((s) => s.id === subtaskId);
111
119
  const roleName = subtask ? capitalize(subtask.role) : 'A session';
120
+ const askSelf = subtask?.role === 'self';
112
121
  ws.sendPMMessage(taskId, {
113
122
  sender: 'pm',
114
- content: `${roleName} is asking: ${question.question}`,
123
+ content: askSelf ? question.question : `${roleName} is asking: ${question.question}`,
115
124
  options: question.options,
116
125
  context: question.context,
117
126
  });
@@ -122,10 +131,13 @@ export function buildExecutionCallbacks(taskId, plan, ws, resolvers, onPermissio
122
131
  context: question.context,
123
132
  });
124
133
  const { text: answer } = await waitForInput(taskId, resolvers);
125
- ws.sendPMMessage(taskId, {
126
- sender: 'pm',
127
- content: `Got it! Passing this to ${roleName}...`,
128
- });
134
+ // No "passing this to X" scaffolding for a single self agent.
135
+ if (!askSelf) {
136
+ ws.sendPMMessage(taskId, {
137
+ sender: 'pm',
138
+ content: `Got it! Passing this to ${roleName}...`,
139
+ });
140
+ }
129
141
  return answer;
130
142
  },
131
143
  onLayerStart: async (layerIndex, totalLayers, subtaskIds) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tuna-agent",
3
- "version": "0.1.173",
3
+ "version": "0.1.175",
4
4
  "description": "Tuna Agent - Run AI coding tasks on your machine",
5
5
  "bin": {
6
6
  "tuna-agent": "dist/cli/index.js"