tuna-agent 0.1.167 → 0.1.169

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.
@@ -221,6 +221,15 @@ export async function startDaemon(config) {
221
221
  }
222
222
  // Per-agent concurrency: if busy, queue instead of rejecting.
223
223
  const agentId = task.agentId || '__default__';
224
+ // Dedup: the API sweep re-dispatches queued tasks every 30s. Without this,
225
+ // a task sent repeatedly while the agent is busy piles up as duplicates in
226
+ // the queue (and would run N times). Ignore if already running or queued.
227
+ const alreadyRunning = Array.from(activeAgentTasks.values()).includes(task.id);
228
+ const alreadyQueued = (agentQueues.get(agentId) || []).some((it) => it.kind === 'task' && it.task.id === task.id);
229
+ if (alreadyRunning || alreadyQueued) {
230
+ console.log(`[Daemon] Task ${task.id} already running/queued — ignoring duplicate dispatch`);
231
+ break;
232
+ }
224
233
  if (activeAgentTasks.has(agentId)) {
225
234
  enqueueForAgent(agentId, { kind: 'task', task });
226
235
  break;
@@ -259,16 +259,18 @@ function createPlanningStreamHandler(taskId, onProgress, onTextChunk) {
259
259
  export async function chatWithPM(pmSessionId, repoPath, userMessage, signal, onTextChunk, inputFiles) {
260
260
  const chatStartMs = Date.now();
261
261
  console.log(`[PM] Chat with PM: ${userMessage.substring(0, 80)}`);
262
- const chatPrompt = `You are a friendly AI assistant. You can help with anythingcoding, questions, or general tasks.
262
+ const chatPrompt = `You are the agent described in your project context (CLAUDE.md). Act within YOUR area of expertise which may be non-software (ASO, content, marketing, research, ops, etc.). Do NOT assume every task is software development.
263
263
 
264
264
  CRITICAL: You CANNOT execute commands, edit files, or make changes yourself. You are a PLANNER only.
265
- When the user wants ANY action done (create, build, fix, push, commit, deploy, update, run, install, etc.), you MUST output a JSON execution plan so the executor system can carry it out.
265
+ When the user wants ANY action done, output a JSON execution plan so the executor (which runs AS you) can carry it out.
266
266
 
267
267
  Rules:
268
- - General question (what is X, how does Y work, explain Z) → answer conversationally
269
- - ANY action request (do X, create Y, push Z, fix W) → output ONLY this JSON, nothing else:
270
- {"summary": "...", "subtasks": [{"id": "sub-1", "role": "fullstack", "description": "Detailed step-by-step instructions for the executor...", "cwd": ".", "dependencies": []}]}
271
- - NEVER say "I'll do it" or "Let me do that" you CANNOT do anything directly. Output a JSON plan instead.
268
+ - General question (what is X, explain Y) → answer conversationally
269
+ - ANY action request → output ONLY this JSON, nothing else:
270
+ {"summary": "...", "subtasks": [{"id": "sub-1", "role": "self", "description": "Detailed step-by-step instructions for the executor...", "cwd": ".", "dependencies": []}]}
271
+ - DEFAULT to ONE subtask with role "self": the task is done by you in a single focused execution. Do NOT invent a software dev team (backend/frontend/tester) unless this is genuinely a complex software build that needs parallel roles.
272
+ - "role" is just a short label for the kind of work — use "self" for your own-domain work, or a 1-word descriptor. NOT software roles unless truly building software.
273
+ - NEVER say "I'll do it" or "Let me do that" — output a JSON plan instead.
272
274
  - If you need clarification → ask a specific question (end with ?)
273
275
  - Keep answers concise for mobile reading
274
276
 
@@ -58,7 +58,7 @@ export interface ProgressEvent {
58
58
  event: string;
59
59
  data: Record<string, unknown>;
60
60
  }
61
- export type SubtaskRole = 'backend' | 'frontend' | 'tester' | 'fullstack';
61
+ export type SubtaskRole = string;
62
62
  export type SubtaskStatus = 'pending' | 'running' | 'waiting_input' | 'done' | 'failed';
63
63
  export type SessionStatus = 'running' | 'waiting_input' | 'done' | 'failed';
64
64
  export interface ApiContract {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tuna-agent",
3
- "version": "0.1.167",
3
+ "version": "0.1.169",
4
4
  "description": "Tuna Agent - Run AI coding tasks on your machine",
5
5
  "bin": {
6
6
  "tuna-agent": "dist/cli/index.js"