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.
@@ -2368,9 +2368,18 @@ async function handleJudgeCommand(ctx) {
2368
2368
  ctx.showInfo(`Judge defaults set: ${defaults.judgeModelId}, ${defaults.maxTurns} max attempts.`);
2369
2369
  }
2370
2370
  async function startGoalWithDefaults(ctx, objective, cancelMessage = "Goal cancelled.") {
2371
+ const goal = await setGoalWithDefaults(ctx, objective, cancelMessage);
2372
+ if (goal) await sendGoalReminder(ctx, goal);
2373
+ }
2374
+ /**
2375
+ * Replace the thread's goal with `objective` without sending the goal reminder,
2376
+ * asking for judge defaults only if they are unset. Resolves to `null` when the
2377
+ * user cancels the defaults prompt or the goal could not be set.
2378
+ */
2379
+ async function setGoalWithDefaults(ctx, objective, cancelMessage = "Goal cancelled.") {
2371
2380
  const judgeDefaults = getJudgeDefaults() ?? await promptForJudgeDefaults(ctx, cancelMessage);
2372
- if (!judgeDefaults) return;
2373
- await startGoal(ctx, objective, judgeDefaults.judgeModelId, judgeDefaults.maxTurns);
2381
+ if (!judgeDefaults) return null;
2382
+ return setGoal(ctx, objective, judgeDefaults.judgeModelId, judgeDefaults.maxTurns);
2374
2383
  }
2375
2384
  function getJudgeDefaults() {
2376
2385
  const settings = loadSettings();
@@ -2441,7 +2450,7 @@ async function promptForJudgeDefaults(ctx, cancelMessage) {
2441
2450
  selector.focused = true;
2442
2451
  });
2443
2452
  }
2444
- async function startGoal(ctx, objective, judgeModelId, maxTurns) {
2453
+ async function setGoal(ctx, objective, judgeModelId, maxTurns) {
2445
2454
  const { state } = ctx;
2446
2455
  const goalManager = state.goalManager;
2447
2456
  const shouldPersistToCreatedThread = state.pendingNewThread || !state.session.thread.getId();
@@ -2460,13 +2469,24 @@ async function startGoal(ctx, objective, judgeModelId, maxTurns) {
2460
2469
  if (!goal) {
2461
2470
  if (shouldPersistToCreatedThread) goalManager.consumePersistOnNextThreadCreate();
2462
2471
  ctx.showError("Failed to set goal.");
2463
- return;
2472
+ return null;
2464
2473
  }
2465
2474
  state.planStartedGoalId = void 0;
2466
2475
  await goalManager.saveToThread(state);
2467
2476
  ctx.updateStatusLine();
2477
+ return goal;
2478
+ }
2479
+ /**
2480
+ * Send the canonical goal reminder for `goal`. It is delivered into an active
2481
+ * run; on an idle thread it starts the goal run, or with `persistIfIdle` it is
2482
+ * only recorded so no new run starts.
2483
+ */
2484
+ async function sendGoalReminder(ctx, goal, options = {}) {
2485
+ const { state } = ctx;
2486
+ const goalManager = state.goalManager;
2487
+ const signal = createGoalReminderSignal(goal);
2468
2488
  try {
2469
- await state.session.sendSignal(createGoalReminderSignal(goal)).accepted;
2489
+ await (options.persistIfIdle ? state.session.sendSignal(signal, { ifIdle: { behavior: "persist" } }) : state.session.sendSignal(signal)).accepted;
2470
2490
  } catch (err) {
2471
2491
  goalManager.pause();
2472
2492
  await goalManager.saveToThread(state);
@@ -22364,6 +22384,32 @@ function resumeApprovedPlan(ctx, toolCallId, title, plan, submittedPath) {
22364
22384
  function formatPlanGoalObjective(title, plan) {
22365
22385
  return `# ${title}\n\n${plan}`;
22366
22386
  }
22387
+ /**
22388
+ * Resolves `true` once the resumed tool's result is recorded (`tool_end`), or
22389
+ * `false` if the run ends or parks first.
22390
+ */
22391
+ function waitForToolEnd(session, toolCallId) {
22392
+ let unsubscribe;
22393
+ let settle;
22394
+ const promise = new Promise((resolve) => {
22395
+ settle = resolve;
22396
+ });
22397
+ const cancel = () => {
22398
+ unsubscribe?.();
22399
+ unsubscribe = void 0;
22400
+ settle(false);
22401
+ };
22402
+ unsubscribe = session.subscribe((event) => {
22403
+ if (event.type === "tool_end" && event.toolCallId === toolCallId) {
22404
+ settle(true);
22405
+ cancel();
22406
+ } else if (event.type === "agent_end" || event.type === "error" || event.type === "tool_suspended") cancel();
22407
+ });
22408
+ return {
22409
+ promise,
22410
+ cancel
22411
+ };
22412
+ }
22367
22413
  async function handlePlanApproval(ctx, toolCallId, submittedPath) {
22368
22414
  const { state } = ctx;
22369
22415
  const projectPath = state.session.state.get()?.projectPath;
@@ -22408,13 +22454,24 @@ async function handlePlanApproval(ctx, toolCallId, submittedPath) {
22408
22454
  releaseApprovalFocus();
22409
22455
  firePermissionResult("approved");
22410
22456
  await prepareApprovedPlan(ctx, resolvedTitle, plan, planPath);
22457
+ const goal = await ctx.setGoal(formatPlanGoalObjective(resolvedTitle, plan), "Goal cancelled.").catch((error) => {
22458
+ ctx.showError(`Failed to set goal: ${error instanceof Error ? error.message : String(error)}`);
22459
+ return null;
22460
+ });
22461
+ if (goal) state.planStartedGoalId = goal.id;
22462
+ const approvalRecorded = goal ? waitForToolEnd(state.session, toolCallId) : void 0;
22411
22463
  const resumed = resumeApprovedPlan(ctx, toolCallId, resolvedTitle, plan, snapshotKey);
22412
22464
  resolve();
22465
+ if (goal && approvalRecorded) {
22466
+ let recorded = false;
22467
+ try {
22468
+ recorded = await Promise.race([approvalRecorded.promise, resumed.then(() => false)]);
22469
+ } finally {
22470
+ approvalRecorded.cancel();
22471
+ }
22472
+ if (recorded) await ctx.sendGoalReminder(goal, { persistIfIdle: true });
22473
+ }
22413
22474
  await resumed;
22414
- const objective = formatPlanGoalObjective(resolvedTitle, plan);
22415
- await ctx.startGoal(objective, "Goal cancelled.");
22416
- const goal = state.goalManager.getGoal();
22417
- if (goal?.id) state.planStartedGoalId = goal.id;
22418
22475
  },
22419
22476
  onReject: () => {
22420
22477
  releaseApprovalFocus();
@@ -27781,7 +27838,8 @@ var MastraTUI = class MastraTUI {
27781
27838
  addUserMessage: (msg) => addUserMessage(this.state, msg),
27782
27839
  addChildBeforeFollowUps: (child) => this.addChildBeforeFollowUps(child),
27783
27840
  fireMessage: (content, images) => this.fireMessage(content, images),
27784
- startGoal: (objective, cancelMessage) => startGoalWithDefaults(this.buildCommandContext(), objective, cancelMessage),
27841
+ setGoal: (objective, cancelMessage) => setGoalWithDefaults(this.buildCommandContext(), objective, cancelMessage),
27842
+ sendGoalReminder: (goal, options) => sendGoalReminder(this.buildCommandContext(), goal, options),
27785
27843
  queueFollowUpMessage: (content) => this.queueFollowUpMessage(content),
27786
27844
  renderExistingMessages: (isCurrent) => this.renderExistingMessagesAndSeedIdleCounter(isCurrent),
27787
27845
  renderClearedTasksInline: (clearedTasks, insertIndex) => renderClearedTasksInline(this.state, clearedTasks, insertIndex),
@@ -28171,4 +28229,4 @@ var MastraTUI = class MastraTUI {
28171
28229
  //#endregion
28172
28230
  export { mastraBrand as _, OMProgressComponent as a, TUI_CO_AUTHOR as b, ToolExecutionComponentEnhanced as c, detectTerminalTheme as d, applyThemeMode as f, mastra as g, getThemeMode as h, LoginDialogComponent as i, ModelSelectorComponent as l, getMarkdownTheme as m, createTUIState as n, formatOMStatus as o, getEditorTheme as p, LoginSelectorComponent as r, UserMessageComponent as s, MastraTUI as t, AssistantMessageComponent as u, restoreTerminalForeground as v, theme as y };
28173
28231
 
28174
- //# sourceMappingURL=tui-D2uNETXK.js.map
28232
+ //# sourceMappingURL=tui-ClYkgBN3.js.map