mastracode 0.48.1 → 0.48.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.
Files changed (94) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/browser-lifecycle.d.ts +17 -0
  3. package/dist/browser-lifecycle.d.ts.map +1 -0
  4. package/dist/cli.cjs +15 -4
  5. package/dist/cli.cjs.map +1 -1
  6. package/dist/cli.js +15 -4
  7. package/dist/cli.js.map +1 -1
  8. package/dist/commit-attribution.d.ts +1 -1
  9. package/dist/commit-attribution.d.ts.map +1 -1
  10. package/dist/docs/SKILL.md +1 -1
  11. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  12. package/dist/initial-prompt.d.ts +3 -3
  13. package/dist/tui/assistant-render-registry.d.ts.map +1 -1
  14. package/dist/tui/background-tool-result.d.ts +1 -1
  15. package/dist/tui/commands/browser.d.ts.map +1 -1
  16. package/dist/tui/components/account-switch-notice.d.ts.map +1 -1
  17. package/dist/tui/components/api-key-dialog.d.ts.map +1 -1
  18. package/dist/tui/components/ask-question-dialog.d.ts.map +1 -1
  19. package/dist/tui/components/ask-question-inline.d.ts.map +1 -1
  20. package/dist/tui/components/assistant-message.d.ts.map +1 -1
  21. package/dist/tui/components/background-activity-selector.d.ts.map +1 -1
  22. package/dist/tui/components/banner.d.ts.map +1 -1
  23. package/dist/tui/components/chat-boundary-spacer.d.ts.map +1 -1
  24. package/dist/tui/components/collapsible.d.ts.map +1 -1
  25. package/dist/tui/components/custom-editor.d.ts.map +1 -1
  26. package/dist/tui/components/diff-output.d.ts.map +1 -1
  27. package/dist/tui/components/error-display.d.ts.map +1 -1
  28. package/dist/tui/components/github-pr-picker.d.ts.map +1 -1
  29. package/dist/tui/components/global-background-notice.d.ts.map +1 -1
  30. package/dist/tui/components/goal-cycles-dialog.d.ts.map +1 -1
  31. package/dist/tui/components/idle-counter.d.ts.map +1 -1
  32. package/dist/tui/components/judge-display.d.ts.map +1 -1
  33. package/dist/tui/components/knowledge-browser.d.ts.map +1 -1
  34. package/dist/tui/components/login-account-manager.d.ts.map +1 -1
  35. package/dist/tui/components/login-dialog.d.ts.map +1 -1
  36. package/dist/tui/components/login-mode-selector.d.ts.map +1 -1
  37. package/dist/tui/components/login-selector.d.ts.map +1 -1
  38. package/dist/tui/components/masked-input.d.ts.map +1 -1
  39. package/dist/tui/components/mcp-selector.d.ts.map +1 -1
  40. package/dist/tui/components/model-selector.d.ts.map +1 -1
  41. package/dist/tui/components/multi-step-progress.d.ts.map +1 -1
  42. package/dist/tui/components/multiline-input.d.ts.map +1 -1
  43. package/dist/tui/components/notification-summary.d.ts.map +1 -1
  44. package/dist/tui/components/notification.d.ts.map +1 -1
  45. package/dist/tui/components/obi-loader.d.ts.map +1 -1
  46. package/dist/tui/components/om-marker.d.ts.map +1 -1
  47. package/dist/tui/components/om-output.d.ts.map +1 -1
  48. package/dist/tui/components/om-progress.d.ts.map +1 -1
  49. package/dist/tui/components/om-settings.d.ts.map +1 -1
  50. package/dist/tui/components/plan-approval-inline.d.ts.map +1 -1
  51. package/dist/tui/components/reactive-signal.d.ts.map +1 -1
  52. package/dist/tui/components/schedule-fire.d.ts.map +1 -1
  53. package/dist/tui/components/settings.d.ts.map +1 -1
  54. package/dist/tui/components/shell-output.d.ts.map +1 -1
  55. package/dist/tui/components/simple-progress.d.ts.map +1 -1
  56. package/dist/tui/components/slash-command.d.ts.map +1 -1
  57. package/dist/tui/components/state-signal.d.ts.map +1 -1
  58. package/dist/tui/components/subagent-execution.d.ts.map +1 -1
  59. package/dist/tui/components/subconscious-activity.d.ts.map +1 -1
  60. package/dist/tui/components/system-reminder.d.ts.map +1 -1
  61. package/dist/tui/components/task-progress.d.ts.map +1 -1
  62. package/dist/tui/components/temporal-gap.d.ts.map +1 -1
  63. package/dist/tui/components/thinking-settings.d.ts.map +1 -1
  64. package/dist/tui/components/thread-selector.d.ts.map +1 -1
  65. package/dist/tui/components/tool-approval-dialog.d.ts.map +1 -1
  66. package/dist/tui/components/tool-execution-enhanced.d.ts.map +1 -1
  67. package/dist/tui/components/tool-validation-error.d.ts.map +1 -1
  68. package/dist/tui/components/user-message.d.ts.map +1 -1
  69. package/dist/tui/components/width-aware-container.d.ts.map +1 -1
  70. package/dist/tui/components/wrapping-autocomplete-list.d.ts.map +1 -1
  71. package/dist/tui/components/wrapping-select-list.d.ts.map +1 -1
  72. package/dist/tui/footer-animation-renderer.d.ts.map +1 -1
  73. package/dist/tui/mastra-tui.d.ts.map +1 -1
  74. package/dist/tui/onboarding-inline.d.ts.map +1 -1
  75. package/dist/tui/render-scheduler.d.ts.map +1 -1
  76. package/dist/tui/shell-runner.d.ts +3 -3
  77. package/dist/tui/theme.d.ts +36 -36
  78. package/dist/tui/theme.d.ts.map +1 -1
  79. package/dist/tui/voice/engines/cloud-engine.d.ts +1 -1
  80. package/dist/tui/voice/engines/cloud-engine.d.ts.map +1 -1
  81. package/dist/tui/voice/engines/macos-native-engine.d.ts +1 -1
  82. package/dist/tui/voice/engines/macos-native-engine.d.ts.map +1 -1
  83. package/dist/tui/voice/mic-capture.d.ts.map +1 -1
  84. package/dist/tui/voice/transcribe.d.ts.map +1 -1
  85. package/dist/tui/voice/voice-controller.d.ts.map +1 -1
  86. package/dist/{tui-ByXZNoag.cjs → tui-4Evog5Ks.cjs} +150 -21
  87. package/dist/tui-4Evog5Ks.cjs.map +1 -0
  88. package/dist/{tui-CEuwbh2h.js → tui-Db51Stlv.js} +127 -22
  89. package/dist/tui-Db51Stlv.js.map +1 -0
  90. package/dist/tui.cjs +1 -1
  91. package/dist/tui.js +1 -1
  92. package/package.json +15 -15
  93. package/dist/tui-ByXZNoag.cjs.map +0 -1
  94. package/dist/tui-CEuwbh2h.js.map +0 -1
@@ -64,6 +64,70 @@ import { RequestContext } from "@mastra/core/request-context";
64
64
  import { MaintenanceLockError, acquireMaintenanceLock } from "@mastra/code-sdk/utils/maintenance-lock";
65
65
  import { runStorageMaintenance } from "@mastra/code-sdk/utils/storage-maintenance";
66
66
  import { loadCustomCommands } from "@mastra/code-sdk/utils/slash-command-loader";
67
+ // src/browser-lifecycle.ts
68
+ /**
69
+ * The browser Mastra Code's agents currently use. Mastra Code owns it: a local
70
+ * browser keeps running (and holds its profile's lock) until it is closed, so
71
+ * it must be closed when replaced and when Mastra Code exits.
72
+ */
73
+ let activeBrowser;
74
+ const CLOSE_TIMEOUT_MS = 5e3;
75
+ /**
76
+ * Retire a browser: it closes and never relaunches, even for a tool call that
77
+ * still holds it. If close fails or takes longer than CLOSE_TIMEOUT_MS, its
78
+ * processes are killed so the old Chrome cannot keep holding the profile.
79
+ */
80
+ async function closeBrowser(browser) {
81
+ let timer;
82
+ const closed = await Promise.race([browser.retire().then(() => true, () => false), new Promise((resolve) => {
83
+ timer = setTimeout(() => resolve(false), CLOSE_TIMEOUT_MS);
84
+ timer.unref?.();
85
+ })]);
86
+ clearTimeout(timer);
87
+ if (!closed) browser.killProcesses();
88
+ }
89
+ /**
90
+ * Counts replacements, so a caller that started creating a browser can tell
91
+ * whether another caller replaced the active browser in the meantime.
92
+ */
93
+ let generation = 0;
94
+ function activeBrowserGeneration() {
95
+ return generation;
96
+ }
97
+ /** Close a browser that never became active. Bounded like any other close. */
98
+ function discardBrowser(browser) {
99
+ return closeBrowser(browser);
100
+ }
101
+ /**
102
+ * Every close still in flight, chained so a later replacement (or exit) waits
103
+ * for all of them, not just the browser it replaced. Each browser is retired once.
104
+ */
105
+ let retiring = Promise.resolve();
106
+ let retiringBrowser;
107
+ /**
108
+ * Make `next` the active browser, closing the previous one first so it
109
+ * releases its profile before `next` launches on it. Also waits for any
110
+ * browser an earlier replacement is still closing.
111
+ *
112
+ * Returns whether `next` is still the active browser once those closes finish.
113
+ * False means a later call replaced (and closed) it meanwhile, so the caller
114
+ * must not hand `next` to agents.
115
+ */
116
+ async function replaceActiveBrowser(next) {
117
+ const previous = activeBrowser;
118
+ activeBrowser = next;
119
+ const mine = ++generation;
120
+ if (previous && previous !== next && previous !== retiringBrowser) {
121
+ retiringBrowser = previous;
122
+ retiring = Promise.all([retiring, closeBrowser(previous)]).then(() => {});
123
+ }
124
+ await retiring;
125
+ return generation === mine;
126
+ }
127
+ /** Close the active browser. Bounded so a hung browser cannot block exit. */
128
+ async function closeActiveBrowser() {
129
+ await replaceActiveBrowser(void 0);
130
+ }
67
131
  // src/commit-attribution.ts
68
132
  const TUI_CO_AUTHOR = { name: "mastracode" };
69
133
  // src/tui/bundled-themes.ts
@@ -19792,16 +19856,28 @@ function resolveModeAgent(mode, agentControllerState) {
19792
19856
  /**
19793
19857
  * @param chatModelId the chat model passed to `createBrowserFromSettings` for
19794
19858
  * this browser, so the recorded model matches what was really launched.
19859
+ * @param startedAt `activeBrowserGeneration()` read before this call started
19860
+ * creating `browser`. If another /browser call replaced the active browser
19861
+ * since then, that call owns the agents: `browser` is discarded and false returned.
19795
19862
  */
19796
- function applyBrowserToAgents(ctx, browser, browserSettings, chatModelId) {
19797
- const modes = ctx.controller.listModes();
19798
- let agentControllerState;
19799
- for (const mode of modes) resolveModeAgent(mode, agentControllerState ??= ctx.state.session.state.get())?.setBrowser?.(browser);
19800
- ctx.state.local?.controller.setBrowser(browser);
19863
+ async function applyBrowserToAgents(ctx, browser, browserSettings, chatModelId, startedAt) {
19864
+ if (startedAt !== void 0 && activeBrowserGeneration() !== startedAt) {
19865
+ if (browser) await discardBrowser(browser);
19866
+ return false;
19867
+ }
19868
+ setAgentsBrowser(ctx, void 0);
19869
+ if (!await replaceActiveBrowser(browser)) return false;
19870
+ setAgentsBrowser(ctx, browser);
19801
19871
  ctx.state.session.state.set({
19802
19872
  [ACTIVE_BROWSER_KEY]: browserSettings ? toActiveBrowserSettings(browserSettings) : void 0,
19803
19873
  [ACTIVE_BROWSER_MODEL_KEY]: browserSettings?.enabled ? resolveStagehandModel(browserSettings, { chatModelId }) : void 0
19804
19874
  });
19875
+ return true;
19876
+ }
19877
+ function setAgentsBrowser(ctx, browser) {
19878
+ let agentControllerState;
19879
+ for (const mode of ctx.controller.listModes()) resolveModeAgent(mode, agentControllerState ??= ctx.state.session.state.get())?.setBrowser?.(browser);
19880
+ ctx.state.local?.controller.setBrowser(browser);
19805
19881
  }
19806
19882
  /**
19807
19883
  * Get a summary key for browser settings to detect config drift.
@@ -20009,9 +20085,12 @@ async function handleBrowserCommand(ctx, args = []) {
20009
20085
  ...settings.browser,
20010
20086
  enabled: false
20011
20087
  };
20088
+ if (!await applyBrowserToAgents(ctx, void 0, disabledSettings)) {
20089
+ ctx.showInfo("Another /browser command replaced this browser.");
20090
+ return;
20091
+ }
20012
20092
  settings.browser = disabledSettings;
20013
20093
  saveSettings(settings);
20014
- applyBrowserToAgents(ctx, void 0, disabledSettings);
20015
20094
  ctx.showInfo("Browser disabled.");
20016
20095
  return;
20017
20096
  }
@@ -20026,7 +20105,11 @@ async function handleBrowserCommand(ctx, args = []) {
20026
20105
  }
20027
20106
  try {
20028
20107
  const chatModelId = launchChatModelId(ctx);
20029
- applyBrowserToAgents(ctx, await createBrowserFromSettings(nextBrowser, { chatModelId }), nextBrowser, chatModelId);
20108
+ const startedAt = activeBrowserGeneration();
20109
+ if (!await applyBrowserToAgents(ctx, await createBrowserFromSettings(nextBrowser, { chatModelId }), nextBrowser, chatModelId, startedAt)) {
20110
+ ctx.showInfo("Another /browser command replaced this browser.");
20111
+ return;
20112
+ }
20030
20113
  if (nextBrowser.profile && nextBrowser.provider) setProfileProvider(nextBrowser.profile, nextBrowser.provider);
20031
20114
  settings.browser = nextBrowser;
20032
20115
  saveSettings(settings);
@@ -20050,18 +20133,29 @@ async function handleBrowserCommand(ctx, args = []) {
20050
20133
  height: 720
20051
20134
  }
20052
20135
  };
20053
- saveSettings(settings);
20054
- if (wasEnabled) try {
20055
- const chatModelId = launchChatModelId(ctx);
20056
- applyBrowserToAgents(ctx, await createBrowserFromSettings(settings.browser, { chatModelId }), settings.browser, chatModelId);
20057
- } catch (err) {
20058
- settings.browser.enabled = false;
20059
- saveSettings(settings);
20060
- applyBrowserToAgents(ctx, void 0);
20061
- ctx.showError(`Browser settings reset, but failed to restart: ${err instanceof Error ? err.message : String(err)}`);
20136
+ if (wasEnabled) {
20137
+ const startedAt = activeBrowserGeneration();
20138
+ try {
20139
+ const chatModelId = launchChatModelId(ctx);
20140
+ if (!await applyBrowserToAgents(ctx, await createBrowserFromSettings(settings.browser, { chatModelId }), settings.browser, chatModelId, startedAt)) {
20141
+ ctx.showInfo("Another /browser command replaced this browser.");
20142
+ return;
20143
+ }
20144
+ } catch (err) {
20145
+ if (!await applyBrowserToAgents(ctx, void 0, void 0, void 0, startedAt)) {
20146
+ ctx.showInfo("Another /browser command replaced this browser.");
20147
+ return;
20148
+ }
20149
+ settings.browser.enabled = false;
20150
+ saveSettings(settings);
20151
+ ctx.showError(`Browser settings reset, but failed to restart: ${err instanceof Error ? err.message : String(err)}`);
20152
+ return;
20153
+ }
20154
+ } else if (!await applyBrowserToAgents(ctx, void 0)) {
20155
+ ctx.showInfo("Another /browser command replaced this browser.");
20062
20156
  return;
20063
20157
  }
20064
- else applyBrowserToAgents(ctx, void 0);
20158
+ saveSettings(settings);
20065
20159
  ctx.showInfo("Browser settings reset to defaults.");
20066
20160
  return;
20067
20161
  }
@@ -20111,8 +20205,12 @@ async function handleBrowserCommand(ctx, args = []) {
20111
20205
  let browserInstance = resolveModeAgent(ctx.state.session.mode.resolve(), ctx.state.session.state.get())?.browser;
20112
20206
  if (!browserInstance && browser.enabled) {
20113
20207
  const chatModelId = launchChatModelId(ctx);
20208
+ const startedAt = activeBrowserGeneration();
20114
20209
  browserInstance = await createBrowserFromSettings(browser, { chatModelId });
20115
- applyBrowserToAgents(ctx, browserInstance, browser, chatModelId);
20210
+ if (!await applyBrowserToAgents(ctx, browserInstance, browser, chatModelId, startedAt)) {
20211
+ ctx.showError("Another /browser command replaced the browser. Run the export again.");
20212
+ return;
20213
+ }
20116
20214
  }
20117
20215
  if (!browserInstance) {
20118
20216
  ctx.showError("Browser not enabled. Run /browser on first.");
@@ -20170,9 +20268,12 @@ async function handleBrowserCommand(ctx, args = []) {
20170
20268
  }
20171
20269
  if (enableChoice === "No") {
20172
20270
  if (browser.enabled) {
20271
+ if (!await applyBrowserToAgents(ctx, void 0)) {
20272
+ ctx.showInfo("Another /browser command replaced this browser.");
20273
+ return;
20274
+ }
20173
20275
  settings.browser.enabled = false;
20174
20276
  saveSettings(settings);
20175
- applyBrowserToAgents(ctx, void 0);
20176
20277
  ctx.showInfo("Browser automation disabled.");
20177
20278
  } else ctx.showInfo("Browser automation remains disabled.");
20178
20279
  return;
@@ -20318,7 +20419,11 @@ async function handleBrowserCommand(ctx, args = []) {
20318
20419
  }
20319
20420
  const chatModelId = launchChatModelId(ctx);
20320
20421
  try {
20321
- applyBrowserToAgents(ctx, await createBrowserFromSettings(nextBrowser, { chatModelId }), nextBrowser, chatModelId);
20422
+ const startedAt = activeBrowserGeneration();
20423
+ if (!await applyBrowserToAgents(ctx, await createBrowserFromSettings(nextBrowser, { chatModelId }), nextBrowser, chatModelId, startedAt)) {
20424
+ ctx.showInfo("Another /browser command replaced this browser.");
20425
+ return;
20426
+ }
20322
20427
  if (nextBrowser.profile && nextBrowser.provider) setProfileProvider(nextBrowser.profile, nextBrowser.provider);
20323
20428
  settings.browser = nextBrowser;
20324
20429
  saveSettings(settings);
@@ -28706,6 +28811,6 @@ var MastraTUI = class MastraTUI {
28706
28811
  }, { startup: true });
28707
28812
  }
28708
28813
  };
28709
- export { mastraBrand as C, mastra as S, TUI_CO_AUTHOR as T, normalizeThemePreference as _, formatUpdateHeader as a, getMarkdownTheme as b, LoginDialogComponent as c, createTUIState as d, UserMessageComponent as f, applyThemePreference as g, AssistantMessageComponent as h, formatUpToDate as i, OMProgressComponent as l, ModelSelectorComponent as m, formatInstallingLabel as n, formatUpdateOutcome as o, ToolExecutionComponentEnhanced as p, formatRegistryError as r, LoginSelectorComponent as s, MastraTUI as t, formatOMStatus as u, applyThemeMode as v, theme as w, getThemeMode as x, getEditorTheme as y };
28814
+ export { mastraBrand as C, closeActiveBrowser as D, activeBrowserGeneration as E, discardBrowser as O, mastra as S, TUI_CO_AUTHOR as T, normalizeThemePreference as _, formatUpdateHeader as a, getMarkdownTheme as b, LoginDialogComponent as c, createTUIState as d, UserMessageComponent as f, applyThemePreference as g, AssistantMessageComponent as h, formatUpToDate as i, replaceActiveBrowser as k, OMProgressComponent as l, ModelSelectorComponent as m, formatInstallingLabel as n, formatUpdateOutcome as o, ToolExecutionComponentEnhanced as p, formatRegistryError as r, LoginSelectorComponent as s, MastraTUI as t, formatOMStatus as u, applyThemeMode as v, theme as w, getThemeMode as x, getEditorTheme as y };
28710
28815
 
28711
- //# sourceMappingURL=tui-CEuwbh2h.js.map
28816
+ //# sourceMappingURL=tui-Db51Stlv.js.map