shark-ai 0.4.22 → 0.4.26

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/bin/shark.js CHANGED
@@ -293,6 +293,7 @@ var AgentActionSchema = z2.object({
293
293
  "manage_subagents",
294
294
  "complete_task",
295
295
  "wait",
296
+ "notify_user",
296
297
  "ast_list_structure",
297
298
  "ast_get_method",
298
299
  "ast_add_method",
@@ -523,7 +524,9 @@ function parseAgentResponse(rawResponse) {
523
524
  "invoke_subagent",
524
525
  "send_message",
525
526
  "manage_subagents",
526
- "complete_task"
527
+ "complete_task",
528
+ "wait",
529
+ "notify_user"
527
530
  ];
528
531
  if (validTypes.includes(parsedObj.type)) {
529
532
  normalizedAction = parsedObj;
@@ -808,12 +811,14 @@ Seu objetivo \xE9 ajudar o usu\xE1rio a analisar, especificar e implementar c\xF
808
811
  \u{1F6A8} REGRAS CR\xCDTICAS DE RESPOSTA (JSON):
809
812
  - Voc\xEA DEVE responder APENAS com um objeto JSON v\xE1lido.
810
813
  - N\xE3o inclua nenhuma introdu\xE7\xE3o, explica\xE7\xE3o ou bloco de markdown fora do JSON.
811
- - Se precisar falar com o usu\xE1rio, use a action com type 'talk_with_user'.
814
+ - Se precisar falar com o usu\xE1rio e aguardar uma resposta dele, use a action com type 'talk_with_user'.
815
+ - Se voc\xEA quiser apenas enviar uma mensagem informativa ou relat\xF3rio detalhado para o usu\xE1rio sem bloquear ou parar a execu\xE7\xE3o para receber resposta, use a action 'notify_user'.
816
+
812
817
 
813
818
  SUA SA\xCDDA DEVE SEGUIR EXATAMENTE ESTE FORMATO JSON:
814
819
  {
815
820
  "action": {
816
- "type": "create_file" | "modify_file" | "read_file" | "list_files" | "search_file" | "search_code" | "delete_file" | "run_command" | "talk_with_user" | "use_mcp_tool" | "activate_skill" | "define_subagent" | "invoke_subagent" | "send_message" | "manage_subagents" | "complete_task" | "wait",
821
+ "type": "create_file" | "modify_file" | "read_file" | "list_files" | "search_file" | "search_code" | "delete_file" | "run_command" | "talk_with_user" | "use_mcp_tool" | "activate_skill" | "define_subagent" | "invoke_subagent" | "send_message" | "manage_subagents" | "complete_task" | "wait" | "notify_user",
817
822
  "path": "caminho/relativo/do/arquivo (opcional)",
818
823
  "content": "conte\xFAdo do arquivo ou mensagem para o usu\xE1rio (opcional)",
819
824
  "start_anchor": "\xE2ncora de in\xEDcio de substitui\xE7\xE3o (modify_file apenas)",
@@ -871,7 +876,8 @@ var AGENT_RESPONSE_JSON_SCHEMA = {
871
876
  "send_message",
872
877
  "manage_subagents",
873
878
  "complete_task",
874
- "wait"
879
+ "wait",
880
+ "notify_user"
875
881
  ]
876
882
  },
877
883
  "path": { "type": ["string", "null"] },
@@ -3605,6 +3611,7 @@ import { fileURLToPath as fileURLToPath2 } from "url";
3605
3611
  var SubagentManager = class {
3606
3612
  subagents = /* @__PURE__ */ new Map();
3607
3613
  customTypes = /* @__PURE__ */ new Map();
3614
+ messageSeq = 0;
3608
3615
  registerSubagent(id, type, role, parentId) {
3609
3616
  this.subagents.set(id, { id, type, role, status: "running", parentId });
3610
3617
  }
@@ -3639,7 +3646,8 @@ var SubagentManager = class {
3639
3646
  sendMessage(recipient, message) {
3640
3647
  const mailboxDir = path9.resolve(process.cwd(), ".shark", "mailbox", recipient);
3641
3648
  fs8.mkdirSync(mailboxDir, { recursive: true });
3642
- const filePath = path9.join(mailboxDir, `${Date.now()}-${crypto2.randomUUID()}.json`);
3649
+ const seq = (this.messageSeq++).toString().padStart(6, "0");
3650
+ const filePath = path9.join(mailboxDir, `${Date.now()}-${seq}-${crypto2.randomUUID()}.json`);
3643
3651
  fs8.writeFileSync(filePath, JSON.stringify({ message }), "utf-8");
3644
3652
  }
3645
3653
  retrieveMessages(id) {
@@ -3964,32 +3972,39 @@ async function promptUser(message, initialValue, placeholder, prefix = "") {
3964
3972
  }
3965
3973
  return userReply;
3966
3974
  }
3967
- async function waitForInputOrNotification(queue, promptMessage = "Your answer:", subagentPrefix = "", timeoutMs) {
3975
+ async function waitForInputOrNotification(queue, promptMessage = "Your answer:", subagentPrefix = "", timeoutMs, isAuto = false) {
3968
3976
  let cancelled = false;
3969
3977
  let resolvePromptPromise = null;
3970
3978
  let timerId = null;
3971
- const promptPromise = new Promise((resolve2) => {
3972
- resolvePromptPromise = resolve2;
3973
- });
3974
- const runPrompt = async () => {
3975
- try {
3976
- const userReply = await promptUser(promptMessage, void 0, void 0, subagentPrefix);
3977
- if (!cancelled && resolvePromptPromise) {
3978
- resolvePromptPromise({
3979
- type: "user",
3980
- content: userReply,
3981
- timestamp: Date.now()
3982
- });
3979
+ const promises = [];
3980
+ if (!isAuto) {
3981
+ const promptPromise = new Promise((resolve2) => {
3982
+ resolvePromptPromise = resolve2;
3983
+ });
3984
+ const runPrompt = async () => {
3985
+ try {
3986
+ const userReply = await promptUser(promptMessage, void 0, void 0, subagentPrefix);
3987
+ if (!cancelled && resolvePromptPromise) {
3988
+ resolvePromptPromise({
3989
+ type: "user",
3990
+ content: userReply,
3991
+ timestamp: Date.now()
3992
+ });
3993
+ }
3994
+ } catch (e) {
3983
3995
  }
3984
- } catch (e) {
3985
- }
3986
- };
3987
- runPrompt();
3996
+ };
3997
+ runPrompt();
3998
+ promises.push(promptPromise);
3999
+ }
3988
4000
  const queuePromise = queue.next();
3989
- const promises = [promptPromise, queuePromise];
4001
+ promises.push(queuePromise);
3990
4002
  if (timeoutMs !== void 0 && timeoutMs !== null) {
3991
4003
  const timeoutPromise = new Promise((resolve2) => {
3992
4004
  timerId = setTimeout(() => {
4005
+ if (resolvePromptPromise) {
4006
+ cancelled = true;
4007
+ }
3993
4008
  resolve2({
3994
4009
  type: "timeout",
3995
4010
  content: "Wait timeout expired.",
@@ -4005,10 +4020,12 @@ async function waitForInputOrNotification(queue, promptMessage = "Your answer:",
4005
4020
  }
4006
4021
  if (winner.type === "subagent_notification" || winner.type === "timeout") {
4007
4022
  cancelled = true;
4008
- process.stdin.emit("data", "\r");
4009
- await new Promise((r) => setTimeout(r, 50));
4010
- if (process.stdout.isTTY) {
4011
- process.stdout.write("\x1B[1A\x1B[2K\x1B[1A\x1B[2K");
4023
+ if (!isAuto) {
4024
+ process.stdin.emit("data", "\r");
4025
+ await new Promise((r) => setTimeout(r, 50));
4026
+ if (process.stdout.isTTY) {
4027
+ process.stdout.write("\x1B[1A\x1B[2K\x1B[1A\x1B[2K");
4028
+ }
4012
4029
  }
4013
4030
  }
4014
4031
  return winner;
@@ -4088,11 +4105,16 @@ You are a highly skilled Developer Agent.
4088
4105
  \u{1F449} **CURRENT TASK**: "${currentTask}"
4089
4106
 
4090
4107
  Your goal is to address the user's request:
4091
- - If the request is a question, a request for explanation, or a discussion, answer the user using the 'talk_with_user' action. You can search the codebase or read files first to answer accurately. Once the explanation/discussion is complete, output a final response starting with "TASK_COMPLETED:" followed by a brief summary.
4108
+ - If the request is a question, a request for explanation, or a discussion, answer the user using the 'talk_with_user' action. You can search the codebase or read files first to answer accurately. Once the explanation/discussion is complete, execute the 'complete_task' action with a brief summary in the 'summary' field and the full explanation in the 'content' field.
4092
4109
  - If the request is to implement changes, debug, or write code:
4093
4110
  1. Implement the necessary changes.
4094
4111
  2. Verify (compile/test).
4095
- 3. When you are confident the task is done, output a final response starting with "TASK_COMPLETED:" followed by a brief technical summary of what you did.
4112
+ 3. When you are confident the task is done, execute the 'complete_task' action with a brief technical summary of what you did in the 'summary' field and any additional details in the 'content' field.
4113
+
4114
+ - Handling Subagent Notifications:
4115
+ - When you receive notifications about subagent progress or completion in your mailbox, do NOT invoke the 'talk_with_user' action just to relay this information to the user if you still have other subagents running, or if you have further steps to execute yourself.
4116
+ - Instead, process the subagent's output, update your task progress in the 'summary' field of your next action, and proceed with executing your next planned steps (or use the 'wait' action to continue waiting for other running subagents).
4117
+ - Only use 'talk_with_user' if you genuinely require the user's input/decision to proceed, or when the entire task is ready for final discussion.
4096
4118
  `;
4097
4119
  let nextPrompt = basePrompt;
4098
4120
  let keepGoing = true;
@@ -4174,19 +4196,32 @@ ${mailboxMessages.map((m) => `- ${m}`).join("\n")}
4174
4196
  log.info(`\u{1F4CC} Status: ${response.summary}`);
4175
4197
  }
4176
4198
  if (response.message && response.message.includes("TASK_COMPLETED:")) {
4199
+ const mainContent = response.message.split("TASK_COMPLETED:")[0].trim();
4200
+ if (mainContent) {
4201
+ log.info(colors.primary("\u{1F916} Shark Dev:"));
4202
+ console.log(mainContent);
4203
+ }
4177
4204
  finalSummary = response.message.split("TASK_COMPLETED:")[1].trim();
4178
4205
  log.success(`\u2714 Task Completed: ${finalSummary}`);
4179
4206
  if (options.taskId) {
4180
4207
  subagentManager.updateSubagentSummary(options.taskId, finalSummary);
4208
+ if (process.env.SHARK_PARENT_ID) {
4209
+ subagentManager.sendMessage(
4210
+ process.env.SHARK_PARENT_ID,
4211
+ `[Subagent Notification] Subagent ${process.env.SHARK_SUBAGENT_ROLE || "Subagent"} (${options.taskId}) completed.
4212
+ Result Details:
4213
+ ${mainContent || finalSummary}`
4214
+ );
4215
+ }
4181
4216
  keepGoing = false;
4182
4217
  break;
4183
4218
  }
4184
- if (!options.taskInstruction) {
4219
+ if (!options.auto || subagentManager.getActiveSubagentsForParent(myId).length > 0) {
4185
4220
  let nextMsg;
4186
4221
  if (!messageQueue.isEmpty()) {
4187
4222
  nextMsg = await messageQueue.next();
4188
4223
  } else {
4189
- nextMsg = await waitForInputOrNotification(messageQueue, "Your answer:", subagentPrefix);
4224
+ nextMsg = await waitForInputOrNotification(messageQueue, "Your answer:", subagentPrefix, void 0, isAuto);
4190
4225
  }
4191
4226
  if (nextMsg.type === "user") {
4192
4227
  if (tui.isCancel(nextMsg.content)) {
@@ -4202,6 +4237,11 @@ ${mailboxMessages.map((m) => `- ${m}`).join("\n")}
4202
4237
  }
4203
4238
  }
4204
4239
  if (response.message && response.message.includes("TASK_FAILED:")) {
4240
+ const mainContent = response.message.split("TASK_FAILED:")[0].trim();
4241
+ if (mainContent) {
4242
+ log.info(colors.primary("\u{1F916} Shark Dev:"));
4243
+ console.log(mainContent);
4244
+ }
4205
4245
  const failureReason = response.message.split("TASK_FAILED:")[1].trim();
4206
4246
  log.error(`\u274C Agent reported task failure: ${failureReason}`);
4207
4247
  if (options.taskId) {
@@ -4215,12 +4255,12 @@ ${mailboxMessages.map((m) => `- ${m}`).join("\n")}
4215
4255
  }
4216
4256
  return { success: false, summary: failureReason };
4217
4257
  }
4218
- if (!options.taskInstruction) {
4258
+ if (!options.auto || subagentManager.getActiveSubagentsForParent(myId).length > 0) {
4219
4259
  let nextMsg;
4220
4260
  if (!messageQueue.isEmpty()) {
4221
4261
  nextMsg = await messageQueue.next();
4222
4262
  } else {
4223
- nextMsg = await waitForInputOrNotification(messageQueue, "Your answer:", subagentPrefix);
4263
+ nextMsg = await waitForInputOrNotification(messageQueue, "Your answer:", subagentPrefix, void 0, isAuto);
4224
4264
  }
4225
4265
  if (nextMsg.type === "user") {
4226
4266
  if (tui.isCancel(nextMsg.content)) {
@@ -4247,7 +4287,7 @@ ${mailboxMessages.map((m) => `- ${m}`).join("\n")}
4247
4287
  if (!messageQueue.isEmpty()) {
4248
4288
  nextMsg = await messageQueue.next();
4249
4289
  } else {
4250
- nextMsg = await waitForInputOrNotification(messageQueue, "Your answer:", subagentPrefix);
4290
+ nextMsg = await waitForInputOrNotification(messageQueue, "Your answer:", subagentPrefix, void 0, isAuto);
4251
4291
  }
4252
4292
  if (nextMsg.type === "user") {
4253
4293
  if (tui.isCancel(nextMsg.content)) {
@@ -4262,7 +4302,7 @@ ${mailboxMessages.map((m) => `- ${m}`).join("\n")}
4262
4302
  if (!messageQueue.isEmpty()) {
4263
4303
  nextMsg = await messageQueue.next();
4264
4304
  } else {
4265
- nextMsg = await waitForInputOrNotification(messageQueue, "Agent returned empty response. Type a message to continue or press Ctrl+C to cancel:", subagentPrefix);
4305
+ nextMsg = await waitForInputOrNotification(messageQueue, "Agent returned empty response. Type a message to continue or press Ctrl+C to cancel:", subagentPrefix, void 0, isAuto);
4266
4306
  }
4267
4307
  if (nextMsg.type === "user") {
4268
4308
  if (tui.isCancel(nextMsg.content)) {
@@ -4426,7 +4466,7 @@ ${result}`;
4426
4466
  if (!messageQueue.isEmpty()) {
4427
4467
  nextMsg = await messageQueue.next();
4428
4468
  } else {
4429
- nextMsg = await waitForInputOrNotification(messageQueue, "Seu prompt alternativo para o agente:", subagentPrefix);
4469
+ nextMsg = await waitForInputOrNotification(messageQueue, "Seu prompt alternativo para o agente:", subagentPrefix, void 0, isAuto);
4430
4470
  }
4431
4471
  if (nextMsg.type === "user") {
4432
4472
  if (tui.isCancel(nextMsg.content)) {
@@ -4443,19 +4483,33 @@ ${result}`;
4443
4483
  if (isSubagent) {
4444
4484
  const summary = hasCompleted ? contentStr.split("TASK_COMPLETED:")[1].trim() : contentStr;
4445
4485
  subagentManager.updateSubagentSummary(options.taskId, summary);
4486
+ if (process.env.SHARK_PARENT_ID) {
4487
+ const mainContent = hasCompleted ? contentStr.split("TASK_COMPLETED:")[0].trim() : contentStr;
4488
+ subagentManager.sendMessage(
4489
+ process.env.SHARK_PARENT_ID,
4490
+ `[Subagent Notification] Subagent ${process.env.SHARK_SUBAGENT_ROLE || "Subagent"} (${options.taskId}) completed.
4491
+ Result Details:
4492
+ ${mainContent}`
4493
+ );
4494
+ }
4446
4495
  finalSummary = summary;
4447
4496
  keepGoing = false;
4448
4497
  break;
4449
4498
  }
4450
4499
  if (hasCompleted) {
4500
+ const mainContent = contentStr.split("TASK_COMPLETED:")[0].trim();
4501
+ if (mainContent) {
4502
+ log.info(colors.primary("\u{1F916} Shark Dev:"));
4503
+ console.log(mainContent);
4504
+ }
4451
4505
  finalSummary = contentStr.split("TASK_COMPLETED:")[1].trim();
4452
4506
  log.success(`\u2714 Task Completed: ${finalSummary}`);
4453
- if (!options.taskInstruction) {
4507
+ if (!options.auto || subagentManager.getActiveSubagentsForParent(myId).length > 0) {
4454
4508
  let nextMsg2;
4455
4509
  if (!messageQueue.isEmpty()) {
4456
4510
  nextMsg2 = await messageQueue.next();
4457
4511
  } else {
4458
- nextMsg2 = await waitForInputOrNotification(messageQueue, "Your answer:", subagentPrefix);
4512
+ nextMsg2 = await waitForInputOrNotification(messageQueue, "Your answer:", subagentPrefix, void 0, isAuto);
4459
4513
  }
4460
4514
  if (nextMsg2.type === "user") {
4461
4515
  if (tui.isCancel(nextMsg2.content)) {
@@ -4476,7 +4530,7 @@ ${result}`;
4476
4530
  if (!messageQueue.isEmpty()) {
4477
4531
  nextMsg = await messageQueue.next();
4478
4532
  } else {
4479
- nextMsg = await waitForInputOrNotification(messageQueue, "Your answer:", subagentPrefix);
4533
+ nextMsg = await waitForInputOrNotification(messageQueue, "Your answer:", subagentPrefix, void 0, isAuto);
4480
4534
  }
4481
4535
  if (nextMsg.type === "user") {
4482
4536
  if (tui.isCancel(nextMsg.content)) {
@@ -4560,10 +4614,37 @@ Result Details:
4560
4614
  ${detailedContent}`
4561
4615
  );
4562
4616
  }
4617
+ finalSummary = taskSummary;
4618
+ keepGoing = false;
4619
+ break;
4620
+ } else {
4621
+ if (detailedContent) {
4622
+ log.info(colors.primary("\u{1F916} Shark Dev:"));
4623
+ console.log(detailedContent);
4624
+ }
4625
+ log.success(`\u2714 Task Completed: ${taskSummary}`);
4626
+ if (!options.auto || subagentManager.getActiveSubagentsForParent(myId).length > 0) {
4627
+ let nextMsg;
4628
+ if (!messageQueue.isEmpty()) {
4629
+ nextMsg = await messageQueue.next();
4630
+ } else {
4631
+ nextMsg = await waitForInputOrNotification(messageQueue, "Your answer:", subagentPrefix, void 0, isAuto);
4632
+ }
4633
+ if (nextMsg.type === "user") {
4634
+ if (tui.isCancel(nextMsg.content)) {
4635
+ finalSummary = taskSummary;
4636
+ keepGoing = false;
4637
+ break;
4638
+ }
4639
+ }
4640
+ nextPrompt = nextMsg.content;
4641
+ continue;
4642
+ } else {
4643
+ finalSummary = taskSummary;
4644
+ keepGoing = false;
4645
+ break;
4646
+ }
4563
4647
  }
4564
- finalSummary = taskSummary;
4565
- keepGoing = false;
4566
- break;
4567
4648
  } else if (action.type === "wait") {
4568
4649
  const durationSeconds = action.duration_seconds || 0;
4569
4650
  const durationMs = durationSeconds > 0 ? durationSeconds * 1e3 : void 0;
@@ -4572,7 +4653,7 @@ ${detailedContent}`
4572
4653
  if (!messageQueue.isEmpty()) {
4573
4654
  nextMsg = await messageQueue.next();
4574
4655
  } else {
4575
- nextMsg = await waitForInputOrNotification(messageQueue, "Your answer:", subagentPrefix, durationMs);
4656
+ nextMsg = await waitForInputOrNotification(messageQueue, "Your answer:", subagentPrefix, durationMs, isAuto);
4576
4657
  }
4577
4658
  if (nextMsg.type === "timeout") {
4578
4659
  resultMsg = `[System]: Wait duration of ${durationSeconds} seconds expired. No notifications received.`;
@@ -4585,6 +4666,13 @@ ${detailedContent}`
4585
4666
  } else {
4586
4667
  resultMsg = nextMsg.content;
4587
4668
  }
4669
+ } else if (action.type === "notify_user") {
4670
+ const messageContent = action.content || "";
4671
+ if (messageContent) {
4672
+ log.info(colors.primary("\u{1F916} Shark Dev:"));
4673
+ console.log(messageContent);
4674
+ }
4675
+ resultMsg = `[Action notify_user Success]: Notifica\xE7\xE3o exibida com sucesso para o usu\xE1rio.`;
4588
4676
  } else {
4589
4677
  resultMsg = `[Unsupported action type: ${action.type}]`;
4590
4678
  }