mastracode 0.13.1-alpha.2 → 0.14.0-alpha.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # mastracode
2
2
 
3
+ ## 0.14.0-alpha.3
4
+
5
+ ### Minor Changes
6
+
7
+ - Added /api-keys command to manage API keys for model providers. You can add, update, or remove keys directly, or access it from the settings menu. ([#15014](https://github.com/mastra-ai/mastra/pull/15014))
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [[`f5e254f`](https://github.com/mastra-ai/mastra/commit/f5e254f2984c4aae25e26a34ac2e2bbd637b27a6), [`6544c97`](https://github.com/mastra-ai/mastra/commit/6544c974182bccfb31f48efff07671ac528d1533)]:
12
+ - @mastra/pg@1.9.1-alpha.0
13
+ - @mastra/libsql@1.8.1-alpha.0
14
+
3
15
  ## 0.13.1-alpha.2
4
16
 
5
17
  ### Patch Changes
@@ -878,7 +878,7 @@ function getInstallCommand(pm, version) {
878
878
  }
879
879
  function getCurrentVersion() {
880
880
  {
881
- return "0.13.1-alpha.2";
881
+ return "0.14.0-alpha.3";
882
882
  }
883
883
  }
884
884
  async function fetchLatestVersion() {
@@ -5537,6 +5537,19 @@ var SettingsComponent = class extends Box {
5537
5537
  )
5538
5538
  }
5539
5539
  ];
5540
+ if (callbacks.onApiKeys) {
5541
+ items.push({
5542
+ id: "apiKeys",
5543
+ label: "API Keys",
5544
+ description: "Add, update, or remove API keys for model providers",
5545
+ currentValue: "Manage \u2192",
5546
+ submenu: (_currentValue, done) => {
5547
+ done();
5548
+ callbacks.onApiKeys();
5549
+ return new Text("", 0, 0);
5550
+ }
5551
+ });
5552
+ }
5540
5553
  this.settingsList = new SettingsList(
5541
5554
  items,
5542
5555
  10,
@@ -5551,6 +5564,175 @@ var SettingsComponent = class extends Box {
5551
5564
  this.settingsList.handleInput(data);
5552
5565
  }
5553
5566
  };
5567
+ function getProviderList(ctx, models) {
5568
+ const seen = /* @__PURE__ */ new Map();
5569
+ for (const model of models) {
5570
+ if (seen.has(model.provider)) continue;
5571
+ let source = "none";
5572
+ if (ctx.authStorage?.hasStoredApiKey(model.provider)) {
5573
+ source = "stored";
5574
+ } else if (model.apiKeyEnvVar && process.env[model.apiKeyEnvVar]) {
5575
+ source = "env";
5576
+ } else if (model.hasApiKey) {
5577
+ source = "env";
5578
+ }
5579
+ seen.set(model.provider, {
5580
+ provider: model.provider,
5581
+ envVar: model.apiKeyEnvVar,
5582
+ source
5583
+ });
5584
+ }
5585
+ return Array.from(seen.values()).sort((a, b) => a.provider.localeCompare(b.provider));
5586
+ }
5587
+ function statusLabel(info) {
5588
+ switch (info.source) {
5589
+ case "env":
5590
+ return theme.fg("success", "\u2713") + theme.fg("dim", " (env)");
5591
+ case "stored":
5592
+ return theme.fg("success", "\u2713") + theme.fg("dim", " (stored)");
5593
+ case "none":
5594
+ return theme.fg("error", "\u2717") + theme.fg("dim", " (not set)");
5595
+ }
5596
+ }
5597
+ function buildItems(providers) {
5598
+ return providers.map((info) => ({
5599
+ value: info.provider,
5600
+ label: ` ${info.provider} ${statusLabel(info)}${info.envVar ? theme.fg("dim", ` ${info.envVar}`) : ""}`
5601
+ }));
5602
+ }
5603
+ async function handleApiKeysCommand(ctx) {
5604
+ const models = await ctx.state.harness.listAvailableModels();
5605
+ let providers = getProviderList(ctx, models);
5606
+ if (providers.length === 0) {
5607
+ ctx.showInfo("No model providers found.");
5608
+ return;
5609
+ }
5610
+ return new Promise((resolve3) => {
5611
+ const container = new Box(1, 1);
5612
+ container.addChild(new Text(theme.bold(theme.fg("accent", "API Keys")), 0, 0));
5613
+ container.addChild(new Spacer(1));
5614
+ const detailText = new Text("", 0, 0);
5615
+ let currentSelection = providers[0].provider;
5616
+ const updateDetail = (providerName) => {
5617
+ const info = providers.find((p) => p.provider === providerName);
5618
+ if (!info) return;
5619
+ if (info.source === "env") {
5620
+ detailText.setText(
5621
+ theme.fg("dim", " Key set via environment variable. To change it, update your shell environment.")
5622
+ );
5623
+ } else if (info.source === "stored") {
5624
+ detailText.setText(theme.fg("dim", " Key stored locally. Press Enter to update or Delete to remove."));
5625
+ } else {
5626
+ detailText.setText(theme.fg("dim", " No key configured. Press Enter to add one."));
5627
+ }
5628
+ ctx.state.ui.requestRender();
5629
+ };
5630
+ let selectList;
5631
+ const buildSelectList = () => {
5632
+ const items = buildItems(providers);
5633
+ const list = new SelectList(items, Math.min(items.length, 15), getSelectListTheme());
5634
+ list.onSelect = (item) => {
5635
+ const info = providers.find((p) => p.provider === item.value);
5636
+ if (!info) return;
5637
+ if (info.source === "env") {
5638
+ ctx.showInfo(
5639
+ `${info.provider} key is set via environment variable${info.envVar ? ` (${info.envVar})` : ""}. Update it in your shell environment.`
5640
+ );
5641
+ return;
5642
+ }
5643
+ showKeyDialog(info);
5644
+ };
5645
+ list.onCancel = () => {
5646
+ ctx.state.activeInlineQuestion = void 0;
5647
+ container.clear();
5648
+ container.addChild(new Text(theme.fg("dim", `${theme.fg("error", "\u2717")} API Keys (closed)`), 0, 0));
5649
+ ctx.state.ui.requestRender();
5650
+ resolve3();
5651
+ };
5652
+ list.onSelectionChange = (item) => {
5653
+ currentSelection = item.value;
5654
+ updateDetail(item.value);
5655
+ };
5656
+ const originalHandleInput = list.handleInput.bind(list);
5657
+ list.handleInput = (data) => {
5658
+ if (data === "\x7F" || data === "\x1B[3~") {
5659
+ const info = providers.find((p) => p.provider === currentSelection);
5660
+ if (info?.source === "stored" && ctx.authStorage) {
5661
+ ctx.authStorage.remove(`apikey:${info.provider}`);
5662
+ if (info.envVar) {
5663
+ delete process.env[info.envVar];
5664
+ }
5665
+ providers = getProviderList(ctx, models);
5666
+ ctx.showInfo(`API key removed for ${info.provider}`);
5667
+ rebuildList();
5668
+ }
5669
+ return;
5670
+ }
5671
+ originalHandleInput(data);
5672
+ };
5673
+ return list;
5674
+ };
5675
+ const rebuildList = () => {
5676
+ const selectedIdx = Math.max(
5677
+ 0,
5678
+ providers.findIndex((p) => p.provider === currentSelection)
5679
+ );
5680
+ container.clear();
5681
+ container.addChild(new Text(theme.bold(theme.fg("accent", "API Keys")), 0, 0));
5682
+ container.addChild(new Spacer(1));
5683
+ selectList = buildSelectList();
5684
+ selectList.setSelectedIndex(selectedIdx);
5685
+ currentSelection = providers[selectedIdx]?.provider ?? providers[0].provider;
5686
+ container.addChild(selectList);
5687
+ container.addChild(new Spacer(1));
5688
+ container.addChild(detailText);
5689
+ container.addChild(new Spacer(1));
5690
+ container.addChild(new Text(theme.fg("dim", "\u2191\u2193 navigate \xB7 Enter add/update \xB7 Delete remove \xB7 Esc close"), 0, 0));
5691
+ updateDetail(currentSelection);
5692
+ ctx.state.ui.requestRender();
5693
+ };
5694
+ const showKeyDialog = (info) => {
5695
+ const dialog = new ApiKeyDialogComponent({
5696
+ providerName: info.provider,
5697
+ apiKeyEnvVar: info.envVar,
5698
+ onSubmit: (key) => {
5699
+ ctx.state.ui.hideOverlay();
5700
+ if (ctx.authStorage) {
5701
+ ctx.authStorage.setStoredApiKey(info.provider, key, info.envVar);
5702
+ ctx.showInfo(`API key saved for ${info.provider}`);
5703
+ providers = getProviderList(ctx, models);
5704
+ rebuildList();
5705
+ } else {
5706
+ ctx.showError("Unable to save API key: storage unavailable");
5707
+ }
5708
+ },
5709
+ onCancel: () => {
5710
+ ctx.state.ui.hideOverlay();
5711
+ }
5712
+ });
5713
+ ctx.state.ui.showOverlay(dialog, {
5714
+ width: "70%",
5715
+ maxHeight: "50%",
5716
+ anchor: "center"
5717
+ });
5718
+ dialog.focused = true;
5719
+ };
5720
+ selectList = buildSelectList();
5721
+ container.addChild(selectList);
5722
+ container.addChild(new Spacer(1));
5723
+ container.addChild(detailText);
5724
+ container.addChild(new Spacer(1));
5725
+ container.addChild(new Text(theme.fg("dim", "\u2191\u2193 navigate \xB7 Enter add/update \xB7 Delete remove \xB7 Esc close"), 0, 0));
5726
+ updateDetail(providers[0].provider);
5727
+ const inputShim = { handleInput: (data) => selectList.handleInput(data) };
5728
+ ctx.state.activeInlineQuestion = inputShim;
5729
+ ctx.state.chatContainer.addChild(new Spacer(1));
5730
+ ctx.state.chatContainer.addChild(container);
5731
+ ctx.state.chatContainer.addChild(new Spacer(1));
5732
+ ctx.state.ui.requestRender();
5733
+ ctx.state.chatContainer.invalidate();
5734
+ });
5735
+ }
5554
5736
 
5555
5737
  // src/tui/commands/settings.ts
5556
5738
  async function handleSettingsCommand(ctx) {
@@ -5610,6 +5792,11 @@ Storage backend changed to ${label}. Restarting is required.
5610
5792
  `);
5611
5793
  process.exit(0);
5612
5794
  },
5795
+ onApiKeys: () => {
5796
+ ctx.state.ui.hideOverlay();
5797
+ resolve3();
5798
+ handleApiKeysCommand(ctx);
5799
+ },
5613
5800
  onClose: () => {
5614
5801
  ctx.state.ui.hideOverlay();
5615
5802
  resolve3();
@@ -6677,6 +6864,9 @@ async function dispatchSlashCommand(input, state, buildCtx) {
6677
6864
  case "memory-gateway":
6678
6865
  await handleMemoryGatewayCommand(buildCtx());
6679
6866
  return true;
6867
+ case "api-keys":
6868
+ await handleApiKeysCommand(buildCtx());
6869
+ return true;
6680
6870
  default: {
6681
6871
  const customCommand = state.customSlashCommands.find((cmd) => cmd.name === command);
6682
6872
  if (customCommand) {
@@ -11321,6 +11511,7 @@ function setupAutocomplete(state) {
11321
11511
  { name: "browser", description: "Configure browser automation" },
11322
11512
  { name: "theme", description: "Switch color theme (auto/dark/light)" },
11323
11513
  { name: "update", description: "Check for and install updates" },
11514
+ { name: "api-keys", description: "Manage API keys for model providers" },
11324
11515
  { name: "exit", description: "Exit the TUI" },
11325
11516
  { name: "help", description: "Show available commands" }
11326
11517
  ];
@@ -13133,5 +13324,5 @@ var LoginSelectorComponent = class extends Box {
13133
13324
  };
13134
13325
 
13135
13326
  export { AssistantMessageComponent, LoginDialogComponent, LoginSelectorComponent, MastraTUI, ModelSelectorComponent, OMProgressComponent, ToolExecutionComponentEnhanced, UserMessageComponent, createTUIState, detectTerminalTheme, formatOMStatus, getCurrentVersion };
13136
- //# sourceMappingURL=chunk-AASZ7C6A.js.map
13137
- //# sourceMappingURL=chunk-AASZ7C6A.js.map
13327
+ //# sourceMappingURL=chunk-CIF3J6QG.js.map
13328
+ //# sourceMappingURL=chunk-CIF3J6QG.js.map