apex-dev 3.10.20 → 3.10.23

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/index.js CHANGED
@@ -54,6 +54,7 @@ var require_store = __commonJS((exports, module2) => {
54
54
  var _detectedProvider = config.detectInitialProvider();
55
55
  var _providerEnvKey = config.PROVIDERS[_detectedProvider].envKey;
56
56
  var _apiKey = process.env[_providerEnvKey] || "";
57
+ var _needsConfig = process.env.APEX_DEV_NEEDS_CONFIG === "true" || !Boolean(_apiKey);
57
58
  var state = {
58
59
  messages: [],
59
60
  streamingContent: "",
@@ -63,7 +64,7 @@ var require_store = __commonJS((exports, module2) => {
63
64
  showSummary: false,
64
65
  apiKey: _apiKey,
65
66
  provider: _detectedProvider,
66
- needsConfig: !Boolean(_apiKey)
67
+ needsConfig: _needsConfig
67
68
  };
68
69
  var nextId = 1;
69
70
  var listeners = new Set;
@@ -103,6 +104,7 @@ var require_store = __commonJS((exports, module2) => {
103
104
  messages: state.messages.map((m2) => m2.id === id ? { ...m2, ...updates } : m2)
104
105
  };
105
106
  notify();
107
+ return id;
106
108
  }
107
109
  function toggleMessageExpanded(id) {
108
110
  state = {
@@ -3436,13 +3438,15 @@ function Header() {
3436
3438
  setBranch(b2);
3437
3439
  } catch {}
3438
3440
  }, []);
3439
- const provider = import_store_h.getSnapshot().provider;
3441
+ const snapshot = import_store_h.getSnapshot();
3442
+ const provider = snapshot.provider;
3440
3443
  const providerLabel = import_config.PROVIDERS[provider]?.label || provider;
3444
+ const configReady = !snapshot.needsConfig;
3441
3445
  return /* @__PURE__ */ jsx_runtime.jsxs("box", {
3442
- style: { flexDirection: "row", paddingLeft: 1, paddingRight: 1 },
3446
+ style: { flexDirection: "row", paddingLeft: 1, paddingRight: 1, paddingTop: 1, paddingBottom: 0 },
3443
3447
  children: [
3444
3448
  /* @__PURE__ */ jsx_runtime.jsx("box", {
3445
- style: { flexGrow: 1 },
3449
+ style: { flexGrow: 1, flexDirection: "column" },
3446
3450
  children: /* @__PURE__ */ jsx_runtime.jsxs("text", {
3447
3451
  children: [
3448
3452
  /* @__PURE__ */ jsx_runtime.jsx("span", {
@@ -3481,15 +3485,36 @@ function Header() {
3481
3485
  ]
3482
3486
  })
3483
3487
  }),
3484
- !isNarrow ? /* @__PURE__ */ jsx_runtime.jsxs("text", {
3488
+ !isNarrow ? /* @__PURE__ */ jsx_runtime.jsxs("box", {
3489
+ style: { flexDirection: "column", alignItems: "flex-end" },
3485
3490
  children: [
3486
- /* @__PURE__ */ jsx_runtime.jsx("span", {
3487
- fg: import_theme.colors.dim,
3488
- children: "\xB7 "
3491
+ /* @__PURE__ */ jsx_runtime.jsxs("text", {
3492
+ children: [
3493
+ /* @__PURE__ */ jsx_runtime.jsx("span", {
3494
+ fg: configReady ? import_theme.colors.green : import_theme.colors.yellow,
3495
+ children: configReady ? "\u25CF" : "\u25CB"
3496
+ }),
3497
+ /* @__PURE__ */ jsx_runtime.jsx("span", {
3498
+ fg: import_theme.colors.dim,
3499
+ children: " "
3500
+ }),
3501
+ /* @__PURE__ */ jsx_runtime.jsx("span", {
3502
+ fg: import_theme.colors.muted,
3503
+ children: configReady ? "ready" : "needs setup"
3504
+ })
3505
+ ]
3489
3506
  }),
3490
- /* @__PURE__ */ jsx_runtime.jsx("span", {
3491
- fg: import_theme.colors.muted,
3492
- children: providerLabel
3507
+ /* @__PURE__ */ jsx_runtime.jsxs("text", {
3508
+ children: [
3509
+ /* @__PURE__ */ jsx_runtime.jsx("span", {
3510
+ fg: import_theme.colors.dim,
3511
+ children: "provider "
3512
+ }),
3513
+ /* @__PURE__ */ jsx_runtime.jsx("span", {
3514
+ fg: import_theme.colors.primary,
3515
+ children: providerLabel
3516
+ })
3517
+ ]
3493
3518
  })
3494
3519
  ]
3495
3520
  }) : null
@@ -3512,7 +3537,7 @@ var jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
3512
3537
  function Welcome() {
3513
3538
  const { isNarrow } = useLayout();
3514
3539
  return /* @__PURE__ */ jsx_runtime3.jsxs("box", {
3515
- style: { flexDirection: "column", paddingLeft: 1, marginTop: 1 },
3540
+ style: { flexDirection: "column", paddingLeft: 1, marginTop: 1, marginBottom: 1 },
3516
3541
  children: [
3517
3542
  /* @__PURE__ */ jsx_runtime3.jsx("text", {
3518
3543
  fg: import_theme3.colors.white,
@@ -3521,8 +3546,13 @@ function Welcome() {
3521
3546
  }),
3522
3547
  /* @__PURE__ */ jsx_runtime3.jsx("text", {
3523
3548
  fg: import_theme3.colors.dim,
3524
- content: isNarrow ? `Max ${import_config2.MAX_TOOL_ITERATIONS} iterations` : `Tools available \xB7 Max ${import_config2.MAX_TOOL_ITERATIONS} iterations per turn`
3525
- })
3549
+ content: isNarrow ? `Type a message or /help` : `Apex can read, edit, run commands, and review your code. Use /help to see shortcuts.`
3550
+ }),
3551
+ !isNarrow ? /* @__PURE__ */ jsx_runtime3.jsx("text", {
3552
+ fg: import_theme3.colors.dim,
3553
+ style: { marginTop: 0 },
3554
+ content: `Shortcuts \xB7 /help \xB7 /files \xB7 /diff \xB7 /cost \xB7 /quit \xB7 Max ${import_config2.MAX_TOOL_ITERATIONS} iterations`
3555
+ }) : null
3526
3556
  ]
3527
3557
  });
3528
3558
  }
@@ -4050,16 +4080,18 @@ function InputBar({ disabled, onSubmit }) {
4050
4080
  inputRef.current.value = "";
4051
4081
  onSubmit(trimmed);
4052
4082
  };
4053
- const hint = isNarrow ? "^C \xB7 /?" : "Ctrl+C exit \xB7 /help";
4083
+ const hint = isNarrow ? "Ctrl+C \xB7 /" : "Ctrl+C exit \xB7 /help \xB7 /files";
4084
+ const placeholder = disabled ? "setup in progress..." : isNarrow ? "Message or /cmd" : "Ask Apex anything, or use /commands";
4054
4085
  return /* @__PURE__ */ jsx_runtime12.jsx("box", {
4055
- style: { flexDirection: "column" },
4086
+ style: { flexDirection: "column", paddingLeft: 1, paddingRight: 1, paddingBottom: 1 },
4056
4087
  children: /* @__PURE__ */ jsx_runtime12.jsxs("box", {
4057
4088
  style: {
4058
4089
  flexDirection: "row",
4059
4090
  paddingLeft: 1,
4060
4091
  paddingRight: 1,
4061
4092
  borderStyle: "rounded",
4062
- borderColor: disabled ? import_theme12.colors.dim : import_theme12.colors.border
4093
+ borderColor: disabled ? import_theme12.colors.dim : import_theme12.colors.border,
4094
+ backgroundColor: disabled ? import_theme12.colors.surface : undefined
4063
4095
  },
4064
4096
  children: [
4065
4097
  /* @__PURE__ */ jsx_runtime12.jsx("text", {
@@ -4070,7 +4102,7 @@ function InputBar({ disabled, onSubmit }) {
4070
4102
  /* @__PURE__ */ jsx_runtime12.jsx("input", {
4071
4103
  ref: inputRef,
4072
4104
  focused: !disabled,
4073
- placeholder: disabled ? "processing..." : "Type a message or /command",
4105
+ placeholder,
4074
4106
  onSubmit: handleSubmit,
4075
4107
  fg: import_theme12.colors.text,
4076
4108
  style: { flexGrow: 1 }
@@ -4086,10 +4118,13 @@ function InputBar({ disabled, onSubmit }) {
4086
4118
  var import_react_sb = __toESM(require_react(), 1);
4087
4119
  var import_theme13 = __toESM(require_theme(), 1);
4088
4120
  var import_config3 = __toESM(require_config(), 1);
4121
+ var import_store3 = __toESM(require_store(), 1);
4089
4122
  var jsx_runtime13 = __toESM(require_jsx_runtime(), 1);
4090
4123
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
4091
4124
  function StatusBar({ isProcessing }) {
4092
4125
  const { isNarrow } = useLayout();
4126
+ const snapshot = import_config3.session;
4127
+ const state = import_store3.getSnapshot();
4093
4128
  const [tick, setTick] = import_react_sb.useState(0);
4094
4129
  import_react_sb.useEffect(() => {
4095
4130
  const id = setInterval(() => setTick((t) => t + 1), 1000);
@@ -4102,11 +4137,12 @@ function StatusBar({ isProcessing }) {
4102
4137
  const id = setInterval(() => setSpinFrame((f) => (f + 1) % SPINNER_FRAMES.length), 80);
4103
4138
  return () => clearInterval(id);
4104
4139
  }, [isProcessing]);
4105
- const elapsed = (tick, ((Date.now() - import_config3.session.startTime) / 1000 / 60).toFixed(1));
4106
- const { totalCost, totalTokens, toolCallCount, turnCount, filesModified } = import_config3.session;
4107
- const tokStr = totalTokens >= 1000 ? (totalTokens / 1000).toFixed(1) + "k" : String(totalTokens);
4140
+ const elapsed = (tick, ((Date.now() - snapshot.startTime) / 1000 / 60).toFixed(1));
4141
+ const tokStr = snapshot.totalTokens >= 1000 ? (snapshot.totalTokens / 1000).toFixed(1) + "k" : String(snapshot.totalTokens);
4142
+ const configReady = !state.needsConfig;
4143
+ const providerLabel = state.provider ? import_config3.PROVIDERS[state.provider]?.label || state.provider : "unknown";
4108
4144
  return /* @__PURE__ */ jsx_runtime13.jsxs("box", {
4109
- style: { flexDirection: "row", paddingLeft: isNarrow ? 1 : 2, paddingRight: isNarrow ? 1 : 2 },
4145
+ style: { flexDirection: "row", paddingLeft: isNarrow ? 1 : 2, paddingRight: isNarrow ? 1 : 2, paddingBottom: 1 },
4110
4146
  children: [
4111
4147
  /* @__PURE__ */ jsx_runtime13.jsx("box", {
4112
4148
  style: { flexGrow: 1 },
@@ -4119,19 +4155,15 @@ function StatusBar({ isProcessing }) {
4119
4155
  /* @__PURE__ */ jsx_runtime13.jsx("span", { fg: import_theme13.colors.dim, children: " \xB7 " }),
4120
4156
  /* @__PURE__ */ jsx_runtime13.jsxs("span", {
4121
4157
  fg: import_theme13.colors.dim,
4122
- children: [turnCount, " turns"]
4158
+ children: [snapshot.turnCount, " turns"]
4123
4159
  }),
4124
4160
  !isNarrow ? /* @__PURE__ */ jsx_runtime13.jsxs(jsx_runtime13.Fragment, {
4125
4161
  children: [
4126
4162
  /* @__PURE__ */ jsx_runtime13.jsx("span", { fg: import_theme13.colors.dim, children: " \xB7 " }),
4127
4163
  /* @__PURE__ */ jsx_runtime13.jsxs("span", {
4128
4164
  fg: import_theme13.colors.dim,
4129
- children: [toolCallCount, " tools"]
4130
- })
4131
- ]
4132
- }) : null,
4133
- !isNarrow ? /* @__PURE__ */ jsx_runtime13.jsxs(jsx_runtime13.Fragment, {
4134
- children: [
4165
+ children: [snapshot.toolCallCount, " tools"]
4166
+ }),
4135
4167
  /* @__PURE__ */ jsx_runtime13.jsx("span", { fg: import_theme13.colors.dim, children: " \xB7 " }),
4136
4168
  /* @__PURE__ */ jsx_runtime13.jsxs("span", {
4137
4169
  fg: import_theme13.colors.dim,
@@ -4142,20 +4174,27 @@ function StatusBar({ isProcessing }) {
4142
4174
  /* @__PURE__ */ jsx_runtime13.jsx("span", { fg: import_theme13.colors.dim, children: " \xB7 " }),
4143
4175
  /* @__PURE__ */ jsx_runtime13.jsxs("span", {
4144
4176
  fg: import_theme13.colors.dim,
4145
- children: ["$", totalCost.toFixed(4)]
4146
- }),
4147
- filesModified.size > 0 && !isNarrow ? /* @__PURE__ */ jsx_runtime13.jsxs(jsx_runtime13.Fragment, {
4148
- children: [
4149
- /* @__PURE__ */ jsx_runtime13.jsx("span", { fg: import_theme13.colors.dim, children: " \xB7 " }),
4150
- /* @__PURE__ */ jsx_runtime13.jsxs("span", {
4151
- fg: import_theme13.colors.yellow,
4152
- children: [filesModified.size, " modified"]
4153
- })
4154
- ]
4155
- }) : null
4177
+ children: ["$", snapshot.totalCost.toFixed(4)]
4178
+ })
4156
4179
  ]
4157
4180
  })
4158
4181
  }),
4182
+ !isNarrow ? /* @__PURE__ */ jsx_runtime13.jsxs("text", {
4183
+ children: [
4184
+ /* @__PURE__ */ jsx_runtime13.jsx("span", {
4185
+ fg: configReady ? import_theme13.colors.green : import_theme13.colors.yellow,
4186
+ children: configReady ? "\u25CF" : "\u25CB"
4187
+ }),
4188
+ /* @__PURE__ */ jsx_runtime13.jsx("span", {
4189
+ fg: import_theme13.colors.dim,
4190
+ children: " "
4191
+ }),
4192
+ /* @__PURE__ */ jsx_runtime13.jsx("span", {
4193
+ fg: import_theme13.colors.muted,
4194
+ children: configReady ? providerLabel : "setup required"
4195
+ })
4196
+ ]
4197
+ }) : null,
4159
4198
  isProcessing ? /* @__PURE__ */ jsx_runtime13.jsxs("text", {
4160
4199
  children: [
4161
4200
  /* @__PURE__ */ jsx_runtime13.jsx("span", {
@@ -4164,11 +4203,11 @@ function StatusBar({ isProcessing }) {
4164
4203
  }),
4165
4204
  /* @__PURE__ */ jsx_runtime13.jsx("span", {
4166
4205
  fg: import_theme13.colors.accent,
4167
- children: isNarrow ? " ..." : " thinking "
4206
+ children: isNarrow ? " \u2026" : " thinking"
4168
4207
  }),
4169
4208
  !isNarrow ? /* @__PURE__ */ jsx_runtime13.jsx("span", {
4170
4209
  fg: import_theme13.colors.dim,
4171
- children: "\u25A0 Esc"
4210
+ children: " \xB7 Esc"
4172
4211
  }) : null
4173
4212
  ]
4174
4213
  }) : null
@@ -4188,6 +4227,11 @@ var COMMANDS = [
4188
4227
  { cmd: "/git <cmd>", desc: "Run a git command" },
4189
4228
  { cmd: "/quit", desc: "Exit" }
4190
4229
  ];
4230
+ var QUICK_TIPS = [
4231
+ "Ctrl+C exits the app",
4232
+ "Esc closes overlays and thinking blocks",
4233
+ "On first launch, choose a provider and paste your API key"
4234
+ ];
4191
4235
  var TOOLS = [
4192
4236
  "Read",
4193
4237
  "Write",
@@ -4263,6 +4307,19 @@ function HelpModal({ onClose, onCommand }) {
4263
4307
  })
4264
4308
  }, cmd))
4265
4309
  }),
4310
+ /* @__PURE__ */ jsx_runtime14.jsx("text", {
4311
+ fg: import_theme14.colors.white,
4312
+ attributes: TextAttributes.BOLD,
4313
+ style: { marginTop: 1 },
4314
+ content: "Quick Tips"
4315
+ }),
4316
+ /* @__PURE__ */ jsx_runtime14.jsx("box", {
4317
+ style: { flexDirection: "column", marginTop: 0 },
4318
+ children: QUICK_TIPS.map((tip) => /* @__PURE__ */ jsx_runtime14.jsx("text", {
4319
+ fg: import_theme14.colors.dim,
4320
+ content: `\u2022 ${tip}`
4321
+ }, tip))
4322
+ }),
4266
4323
  /* @__PURE__ */ jsx_runtime14.jsx("text", {
4267
4324
  fg: import_theme14.colors.white,
4268
4325
  attributes: TextAttributes.BOLD,
@@ -4303,7 +4360,7 @@ var import_useLayout = __toESM(require_useLayout(), 1);
4303
4360
  var jsx_runtime = __toESM(require_jsx_runtime(), 1);
4304
4361
  var PROVIDER_ORDER = ["fireworks", "openai", "openrouter", "groq", "gemini", "together"];
4305
4362
  var PROVIDER_EMOJI = {
4306
- fireworks: "\uD83C\uDF86",
4363
+ fireworks: "\uD83D\uDD25",
4307
4364
  openai: "\uD83E\uDD16",
4308
4365
  openrouter: "\uD83D\uDD00",
4309
4366
  groq: "\u26A1",
@@ -4337,9 +4394,9 @@ function ProviderSelector() {
4337
4394
  provider: providerKey,
4338
4395
  needsConfig: false
4339
4396
  });
4340
- } else {
4341
- setStep("key");
4397
+ return;
4342
4398
  }
4399
+ setStep("key");
4343
4400
  }
4344
4401
  function handleSubmitKey() {
4345
4402
  var key = input.trim();
@@ -4347,6 +4404,8 @@ function ProviderSelector() {
4347
4404
  return;
4348
4405
  import_config.setProvider(providerKey, key);
4349
4406
  import_store.setState({ apiKey: key, provider: providerKey, needsConfig: false });
4407
+ setInput("");
4408
+ setStep("select");
4350
4409
  }
4351
4410
  var handleKeyPress = function(key) {
4352
4411
  if (step === "select") {
@@ -4374,7 +4433,7 @@ function ProviderSelector() {
4374
4433
  style: {
4375
4434
  flexDirection: "column",
4376
4435
  flexGrow: 1,
4377
- paddingTop: 3
4436
+ paddingTop: 2
4378
4437
  },
4379
4438
  onKeyDown: handleKeyPress,
4380
4439
  focused: true,
@@ -4385,14 +4444,14 @@ function ProviderSelector() {
4385
4444
  children: jsx_runtime.jsx("text", {
4386
4445
  attributes: TextAttributes.BOLD,
4387
4446
  fg: import_theme.colors.white,
4388
- children: "\u26A1 Select AI Provider"
4447
+ children: "Choose your AI provider"
4389
4448
  })
4390
4449
  }),
4391
4450
  jsx_runtime.jsx("box", {
4392
4451
  style: { paddingLeft: 4, paddingRight: 4, marginBottom: 1 },
4393
4452
  children: jsx_runtime.jsx("text", {
4394
4453
  fg: import_theme.colors.dim,
4395
- children: "\u2191\u2193 or j/k to navigate \xB7 Enter to select \xB7 Ctrl+C to exit"
4454
+ children: "Use \u2191\u2193 or j/k to navigate, Enter to continue, or select a configured provider to reuse its key."
4396
4455
  })
4397
4456
  }),
4398
4457
  PROVIDER_ORDER.map(function(key, idx) {
@@ -4400,14 +4459,12 @@ function ProviderSelector() {
4400
4459
  var configured = isConfigured(key);
4401
4460
  var def = isDefault(key);
4402
4461
  var statusFg = def ? import_theme.colors.accent : configured ? import_theme.colors.green : import_theme.colors.dim;
4403
- var statusText = def ? "\u2713 Active" : configured ? "\u2713 Configured" : "\u2717 Not configured";
4462
+ var statusText = def ? "Active" : configured ? "Configured" : "Needs key";
4404
4463
  return jsx_runtime.jsxs("box", {
4405
4464
  style: {
4406
4465
  flexDirection: "row",
4407
- paddingLeft: focused ? 4 : 4,
4408
- paddingRight: 4,
4409
- paddingTop: 0,
4410
- paddingBottom: 0
4466
+ paddingLeft: 4,
4467
+ paddingRight: 4
4411
4468
  },
4412
4469
  onMouseEnter: function() {
4413
4470
  setFocusedIdx(idx);
@@ -4442,7 +4499,7 @@ function ProviderSelector() {
4442
4499
  style: { paddingLeft: 4, paddingRight: 4, marginTop: 2 },
4443
4500
  children: jsx_runtime.jsx("text", {
4444
4501
  fg: import_theme.colors.dim,
4445
- children: "Keys are stored in ~/.apex-dev/config.json or set via environment variables"
4502
+ children: "Keys are stored in ~/.apex-dev/config.json or can be supplied via environment variables."
4446
4503
  })
4447
4504
  })
4448
4505
  ]
@@ -4696,6 +4753,14 @@ function App() {
4696
4753
  });
4697
4754
  }
4698
4755
  }, []);
4756
+ const forceSetup = process.env.APEX_DEV_NEEDS_CONFIG === "true";
4757
+ const shouldShowSetup = forceSetup || state.needsConfig;
4758
+ if (shouldShowSetup) {
4759
+ return /* @__PURE__ */ jsx_runtime15.jsx("box", {
4760
+ style: { flexDirection: "column", flexGrow: 1 },
4761
+ children: /* @__PURE__ */ jsx_runtime15.jsx(globalThis._ProviderSelector, {})
4762
+ });
4763
+ }
4699
4764
  return /* @__PURE__ */ jsx_runtime15.jsxs("box", {
4700
4765
  style: { flexDirection: "column", flexGrow: 1 },
4701
4766
  children: [
@@ -4712,17 +4777,17 @@ function App() {
4712
4777
  isProcessing: state.isProcessing
4713
4778
  }),
4714
4779
  /* @__PURE__ */ jsx_runtime15.jsx(InputBar, {
4715
- disabled: state.isProcessing || state.showHelp || state.needsConfig,
4780
+ disabled: state.isProcessing || state.showHelp,
4716
4781
  onSubmit: handleInput
4717
4782
  }),
4718
4783
  state.showHelp ? /* @__PURE__ */ jsx_runtime15.jsx(HelpModal, {
4719
4784
  onClose: () => import_store5.setState({ showHelp: false }),
4720
4785
  onCommand: handleHelpCommand
4721
- }) : null,
4722
- state.needsConfig ? /* @__PURE__ */ jsx_runtime15.jsx(globalThis._ProviderSelector, {}) : null
4786
+ }) : null
4723
4787
  ]
4724
4788
  });
4725
4789
  }
4790
+ globalThis._App = App;
4726
4791
  async function main2() {
4727
4792
  if (process.env.APEX_LOCAL_SERVER === "1") {
4728
4793
  const srv = globalThis.require_server ? globalThis.require_server() : null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apex-dev",
3
- "version": "3.10.20",
3
+ "version": "3.10.23",
4
4
  "description": "Apex AI - a friendly agentic coding assistant for the terminal",
5
5
  "main": "dist/index.js",
6
6
  "bin": {