mastracode 0.44.1 → 0.44.2-alpha.0

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.
@@ -2393,9 +2393,18 @@ async function handleJudgeCommand(ctx) {
2393
2393
  ctx.showInfo(`Judge defaults set: ${defaults.judgeModelId}, ${defaults.maxTurns} max attempts.`);
2394
2394
  }
2395
2395
  async function startGoalWithDefaults(ctx, objective, cancelMessage = "Goal cancelled.") {
2396
+ const goal = await setGoalWithDefaults(ctx, objective, cancelMessage);
2397
+ if (goal) await sendGoalReminder(ctx, goal);
2398
+ }
2399
+ /**
2400
+ * Replace the thread's goal with `objective` without sending the goal reminder,
2401
+ * asking for judge defaults only if they are unset. Resolves to `null` when the
2402
+ * user cancels the defaults prompt or the goal could not be set.
2403
+ */
2404
+ async function setGoalWithDefaults(ctx, objective, cancelMessage = "Goal cancelled.") {
2396
2405
  const judgeDefaults = getJudgeDefaults() ?? await promptForJudgeDefaults(ctx, cancelMessage);
2397
- if (!judgeDefaults) return;
2398
- await startGoal(ctx, objective, judgeDefaults.judgeModelId, judgeDefaults.maxTurns);
2406
+ if (!judgeDefaults) return null;
2407
+ return setGoal(ctx, objective, judgeDefaults.judgeModelId, judgeDefaults.maxTurns);
2399
2408
  }
2400
2409
  function getJudgeDefaults() {
2401
2410
  const settings = (0, _mastra_code_sdk_onboarding_settings.loadSettings)();
@@ -2466,7 +2475,7 @@ async function promptForJudgeDefaults(ctx, cancelMessage) {
2466
2475
  selector.focused = true;
2467
2476
  });
2468
2477
  }
2469
- async function startGoal(ctx, objective, judgeModelId, maxTurns) {
2478
+ async function setGoal(ctx, objective, judgeModelId, maxTurns) {
2470
2479
  const { state } = ctx;
2471
2480
  const goalManager = state.goalManager;
2472
2481
  const shouldPersistToCreatedThread = state.pendingNewThread || !state.session.thread.getId();
@@ -2485,13 +2494,24 @@ async function startGoal(ctx, objective, judgeModelId, maxTurns) {
2485
2494
  if (!goal) {
2486
2495
  if (shouldPersistToCreatedThread) goalManager.consumePersistOnNextThreadCreate();
2487
2496
  ctx.showError("Failed to set goal.");
2488
- return;
2497
+ return null;
2489
2498
  }
2490
2499
  state.planStartedGoalId = void 0;
2491
2500
  await goalManager.saveToThread(state);
2492
2501
  ctx.updateStatusLine();
2502
+ return goal;
2503
+ }
2504
+ /**
2505
+ * Send the canonical goal reminder for `goal`. It is delivered into an active
2506
+ * run; on an idle thread it starts the goal run, or with `persistIfIdle` it is
2507
+ * only recorded so no new run starts.
2508
+ */
2509
+ async function sendGoalReminder(ctx, goal, options = {}) {
2510
+ const { state } = ctx;
2511
+ const goalManager = state.goalManager;
2512
+ const signal = (0, _mastra_code_sdk_goal_signal.createGoalReminderSignal)(goal);
2493
2513
  try {
2494
- await state.session.sendSignal((0, _mastra_code_sdk_goal_signal.createGoalReminderSignal)(goal)).accepted;
2514
+ await (options.persistIfIdle ? state.session.sendSignal(signal, { ifIdle: { behavior: "persist" } }) : state.session.sendSignal(signal)).accepted;
2495
2515
  } catch (err) {
2496
2516
  goalManager.pause();
2497
2517
  await goalManager.saveToThread(state);
@@ -22395,6 +22415,32 @@ function resumeApprovedPlan(ctx, toolCallId, title, plan, submittedPath) {
22395
22415
  function formatPlanGoalObjective(title, plan) {
22396
22416
  return `# ${title}\n\n${plan}`;
22397
22417
  }
22418
+ /**
22419
+ * Resolves `true` once the resumed tool's result is recorded (`tool_end`), or
22420
+ * `false` if the run ends or parks first.
22421
+ */
22422
+ function waitForToolEnd(session, toolCallId) {
22423
+ let unsubscribe;
22424
+ let settle;
22425
+ const promise = new Promise((resolve) => {
22426
+ settle = resolve;
22427
+ });
22428
+ const cancel = () => {
22429
+ unsubscribe?.();
22430
+ unsubscribe = void 0;
22431
+ settle(false);
22432
+ };
22433
+ unsubscribe = session.subscribe((event) => {
22434
+ if (event.type === "tool_end" && event.toolCallId === toolCallId) {
22435
+ settle(true);
22436
+ cancel();
22437
+ } else if (event.type === "agent_end" || event.type === "error" || event.type === "tool_suspended") cancel();
22438
+ });
22439
+ return {
22440
+ promise,
22441
+ cancel
22442
+ };
22443
+ }
22398
22444
  async function handlePlanApproval(ctx, toolCallId, submittedPath) {
22399
22445
  const { state } = ctx;
22400
22446
  const projectPath = state.session.state.get()?.projectPath;
@@ -22439,13 +22485,24 @@ async function handlePlanApproval(ctx, toolCallId, submittedPath) {
22439
22485
  releaseApprovalFocus();
22440
22486
  firePermissionResult("approved");
22441
22487
  await prepareApprovedPlan(ctx, resolvedTitle, plan, planPath);
22488
+ const goal = await ctx.setGoal(formatPlanGoalObjective(resolvedTitle, plan), "Goal cancelled.").catch((error) => {
22489
+ ctx.showError(`Failed to set goal: ${error instanceof Error ? error.message : String(error)}`);
22490
+ return null;
22491
+ });
22492
+ if (goal) state.planStartedGoalId = goal.id;
22493
+ const approvalRecorded = goal ? waitForToolEnd(state.session, toolCallId) : void 0;
22442
22494
  const resumed = resumeApprovedPlan(ctx, toolCallId, resolvedTitle, plan, snapshotKey);
22443
22495
  resolve();
22496
+ if (goal && approvalRecorded) {
22497
+ let recorded = false;
22498
+ try {
22499
+ recorded = await Promise.race([approvalRecorded.promise, resumed.then(() => false)]);
22500
+ } finally {
22501
+ approvalRecorded.cancel();
22502
+ }
22503
+ if (recorded) await ctx.sendGoalReminder(goal, { persistIfIdle: true });
22504
+ }
22444
22505
  await resumed;
22445
- const objective = formatPlanGoalObjective(resolvedTitle, plan);
22446
- await ctx.startGoal(objective, "Goal cancelled.");
22447
- const goal = state.goalManager.getGoal();
22448
- if (goal?.id) state.planStartedGoalId = goal.id;
22449
22506
  },
22450
22507
  onReject: () => {
22451
22508
  releaseApprovalFocus();
@@ -27812,7 +27869,8 @@ var MastraTUI = class MastraTUI {
27812
27869
  addUserMessage: (msg) => addUserMessage(this.state, msg),
27813
27870
  addChildBeforeFollowUps: (child) => this.addChildBeforeFollowUps(child),
27814
27871
  fireMessage: (content, images) => this.fireMessage(content, images),
27815
- startGoal: (objective, cancelMessage) => startGoalWithDefaults(this.buildCommandContext(), objective, cancelMessage),
27872
+ setGoal: (objective, cancelMessage) => setGoalWithDefaults(this.buildCommandContext(), objective, cancelMessage),
27873
+ sendGoalReminder: (goal, options) => sendGoalReminder(this.buildCommandContext(), goal, options),
27816
27874
  queueFollowUpMessage: (content) => this.queueFollowUpMessage(content),
27817
27875
  renderExistingMessages: (isCurrent) => this.renderExistingMessagesAndSeedIdleCounter(isCurrent),
27818
27876
  renderClearedTasksInline: (clearedTasks, insertIndex) => renderClearedTasksInline(this.state, clearedTasks, insertIndex),
@@ -28321,4 +28379,4 @@ Object.defineProperty(exports, "theme", {
28321
28379
  }
28322
28380
  });
28323
28381
 
28324
- //# sourceMappingURL=tui-CvVJXUzA.cjs.map
28382
+ //# sourceMappingURL=tui-Be7-xm5L.cjs.map