apex-dev 3.10.21 → 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.
Files changed (4) hide show
  1. package/cli.js +121 -13
  2. package/dist/apex-dev +45094 -41465
  3. package/dist/index.js +119 -58
  4. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -104,6 +104,7 @@ var require_store = __commonJS((exports, module2) => {
104
104
  messages: state.messages.map((m2) => m2.id === id ? { ...m2, ...updates } : m2)
105
105
  };
106
106
  notify();
107
+ return id;
107
108
  }
108
109
  function toggleMessageExpanded(id) {
109
110
  state = {
@@ -3437,13 +3438,15 @@ function Header() {
3437
3438
  setBranch(b2);
3438
3439
  } catch {}
3439
3440
  }, []);
3440
- const provider = import_store_h.getSnapshot().provider;
3441
+ const snapshot = import_store_h.getSnapshot();
3442
+ const provider = snapshot.provider;
3441
3443
  const providerLabel = import_config.PROVIDERS[provider]?.label || provider;
3444
+ const configReady = !snapshot.needsConfig;
3442
3445
  return /* @__PURE__ */ jsx_runtime.jsxs("box", {
3443
- style: { flexDirection: "row", paddingLeft: 1, paddingRight: 1 },
3446
+ style: { flexDirection: "row", paddingLeft: 1, paddingRight: 1, paddingTop: 1, paddingBottom: 0 },
3444
3447
  children: [
3445
3448
  /* @__PURE__ */ jsx_runtime.jsx("box", {
3446
- style: { flexGrow: 1 },
3449
+ style: { flexGrow: 1, flexDirection: "column" },
3447
3450
  children: /* @__PURE__ */ jsx_runtime.jsxs("text", {
3448
3451
  children: [
3449
3452
  /* @__PURE__ */ jsx_runtime.jsx("span", {
@@ -3482,15 +3485,36 @@ function Header() {
3482
3485
  ]
3483
3486
  })
3484
3487
  }),
3485
- !isNarrow ? /* @__PURE__ */ jsx_runtime.jsxs("text", {
3488
+ !isNarrow ? /* @__PURE__ */ jsx_runtime.jsxs("box", {
3489
+ style: { flexDirection: "column", alignItems: "flex-end" },
3486
3490
  children: [
3487
- /* @__PURE__ */ jsx_runtime.jsx("span", {
3488
- fg: import_theme.colors.dim,
3489
- 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
+ ]
3490
3506
  }),
3491
- /* @__PURE__ */ jsx_runtime.jsx("span", {
3492
- fg: import_theme.colors.muted,
3493
- 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
+ ]
3494
3518
  })
3495
3519
  ]
3496
3520
  }) : null
@@ -3513,7 +3537,7 @@ var jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
3513
3537
  function Welcome() {
3514
3538
  const { isNarrow } = useLayout();
3515
3539
  return /* @__PURE__ */ jsx_runtime3.jsxs("box", {
3516
- style: { flexDirection: "column", paddingLeft: 1, marginTop: 1 },
3540
+ style: { flexDirection: "column", paddingLeft: 1, marginTop: 1, marginBottom: 1 },
3517
3541
  children: [
3518
3542
  /* @__PURE__ */ jsx_runtime3.jsx("text", {
3519
3543
  fg: import_theme3.colors.white,
@@ -3522,8 +3546,13 @@ function Welcome() {
3522
3546
  }),
3523
3547
  /* @__PURE__ */ jsx_runtime3.jsx("text", {
3524
3548
  fg: import_theme3.colors.dim,
3525
- content: isNarrow ? `Max ${import_config2.MAX_TOOL_ITERATIONS} iterations` : `Tools available \xB7 Max ${import_config2.MAX_TOOL_ITERATIONS} iterations per turn`
3526
- })
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
3527
3556
  ]
3528
3557
  });
3529
3558
  }
@@ -4051,16 +4080,18 @@ function InputBar({ disabled, onSubmit }) {
4051
4080
  inputRef.current.value = "";
4052
4081
  onSubmit(trimmed);
4053
4082
  };
4054
- 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";
4055
4085
  return /* @__PURE__ */ jsx_runtime12.jsx("box", {
4056
- style: { flexDirection: "column" },
4086
+ style: { flexDirection: "column", paddingLeft: 1, paddingRight: 1, paddingBottom: 1 },
4057
4087
  children: /* @__PURE__ */ jsx_runtime12.jsxs("box", {
4058
4088
  style: {
4059
4089
  flexDirection: "row",
4060
4090
  paddingLeft: 1,
4061
4091
  paddingRight: 1,
4062
4092
  borderStyle: "rounded",
4063
- 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
4064
4095
  },
4065
4096
  children: [
4066
4097
  /* @__PURE__ */ jsx_runtime12.jsx("text", {
@@ -4071,7 +4102,7 @@ function InputBar({ disabled, onSubmit }) {
4071
4102
  /* @__PURE__ */ jsx_runtime12.jsx("input", {
4072
4103
  ref: inputRef,
4073
4104
  focused: !disabled,
4074
- placeholder: disabled ? "processing..." : "Type a message or /command",
4105
+ placeholder,
4075
4106
  onSubmit: handleSubmit,
4076
4107
  fg: import_theme12.colors.text,
4077
4108
  style: { flexGrow: 1 }
@@ -4087,10 +4118,13 @@ function InputBar({ disabled, onSubmit }) {
4087
4118
  var import_react_sb = __toESM(require_react(), 1);
4088
4119
  var import_theme13 = __toESM(require_theme(), 1);
4089
4120
  var import_config3 = __toESM(require_config(), 1);
4121
+ var import_store3 = __toESM(require_store(), 1);
4090
4122
  var jsx_runtime13 = __toESM(require_jsx_runtime(), 1);
4091
4123
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
4092
4124
  function StatusBar({ isProcessing }) {
4093
4125
  const { isNarrow } = useLayout();
4126
+ const snapshot = import_config3.session;
4127
+ const state = import_store3.getSnapshot();
4094
4128
  const [tick, setTick] = import_react_sb.useState(0);
4095
4129
  import_react_sb.useEffect(() => {
4096
4130
  const id = setInterval(() => setTick((t) => t + 1), 1000);
@@ -4103,11 +4137,12 @@ function StatusBar({ isProcessing }) {
4103
4137
  const id = setInterval(() => setSpinFrame((f) => (f + 1) % SPINNER_FRAMES.length), 80);
4104
4138
  return () => clearInterval(id);
4105
4139
  }, [isProcessing]);
4106
- const elapsed = (tick, ((Date.now() - import_config3.session.startTime) / 1000 / 60).toFixed(1));
4107
- const { totalCost, totalTokens, toolCallCount, turnCount, filesModified } = import_config3.session;
4108
- 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";
4109
4144
  return /* @__PURE__ */ jsx_runtime13.jsxs("box", {
4110
- 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 },
4111
4146
  children: [
4112
4147
  /* @__PURE__ */ jsx_runtime13.jsx("box", {
4113
4148
  style: { flexGrow: 1 },
@@ -4120,19 +4155,15 @@ function StatusBar({ isProcessing }) {
4120
4155
  /* @__PURE__ */ jsx_runtime13.jsx("span", { fg: import_theme13.colors.dim, children: " \xB7 " }),
4121
4156
  /* @__PURE__ */ jsx_runtime13.jsxs("span", {
4122
4157
  fg: import_theme13.colors.dim,
4123
- children: [turnCount, " turns"]
4158
+ children: [snapshot.turnCount, " turns"]
4124
4159
  }),
4125
4160
  !isNarrow ? /* @__PURE__ */ jsx_runtime13.jsxs(jsx_runtime13.Fragment, {
4126
4161
  children: [
4127
4162
  /* @__PURE__ */ jsx_runtime13.jsx("span", { fg: import_theme13.colors.dim, children: " \xB7 " }),
4128
4163
  /* @__PURE__ */ jsx_runtime13.jsxs("span", {
4129
4164
  fg: import_theme13.colors.dim,
4130
- children: [toolCallCount, " tools"]
4131
- })
4132
- ]
4133
- }) : null,
4134
- !isNarrow ? /* @__PURE__ */ jsx_runtime13.jsxs(jsx_runtime13.Fragment, {
4135
- children: [
4165
+ children: [snapshot.toolCallCount, " tools"]
4166
+ }),
4136
4167
  /* @__PURE__ */ jsx_runtime13.jsx("span", { fg: import_theme13.colors.dim, children: " \xB7 " }),
4137
4168
  /* @__PURE__ */ jsx_runtime13.jsxs("span", {
4138
4169
  fg: import_theme13.colors.dim,
@@ -4143,20 +4174,27 @@ function StatusBar({ isProcessing }) {
4143
4174
  /* @__PURE__ */ jsx_runtime13.jsx("span", { fg: import_theme13.colors.dim, children: " \xB7 " }),
4144
4175
  /* @__PURE__ */ jsx_runtime13.jsxs("span", {
4145
4176
  fg: import_theme13.colors.dim,
4146
- children: ["$", totalCost.toFixed(4)]
4147
- }),
4148
- filesModified.size > 0 && !isNarrow ? /* @__PURE__ */ jsx_runtime13.jsxs(jsx_runtime13.Fragment, {
4149
- children: [
4150
- /* @__PURE__ */ jsx_runtime13.jsx("span", { fg: import_theme13.colors.dim, children: " \xB7 " }),
4151
- /* @__PURE__ */ jsx_runtime13.jsxs("span", {
4152
- fg: import_theme13.colors.yellow,
4153
- children: [filesModified.size, " modified"]
4154
- })
4155
- ]
4156
- }) : null
4177
+ children: ["$", snapshot.totalCost.toFixed(4)]
4178
+ })
4157
4179
  ]
4158
4180
  })
4159
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,
4160
4198
  isProcessing ? /* @__PURE__ */ jsx_runtime13.jsxs("text", {
4161
4199
  children: [
4162
4200
  /* @__PURE__ */ jsx_runtime13.jsx("span", {
@@ -4165,11 +4203,11 @@ function StatusBar({ isProcessing }) {
4165
4203
  }),
4166
4204
  /* @__PURE__ */ jsx_runtime13.jsx("span", {
4167
4205
  fg: import_theme13.colors.accent,
4168
- children: isNarrow ? " ..." : " thinking "
4206
+ children: isNarrow ? " \u2026" : " thinking"
4169
4207
  }),
4170
4208
  !isNarrow ? /* @__PURE__ */ jsx_runtime13.jsx("span", {
4171
4209
  fg: import_theme13.colors.dim,
4172
- children: "\u25A0 Esc"
4210
+ children: " \xB7 Esc"
4173
4211
  }) : null
4174
4212
  ]
4175
4213
  }) : null
@@ -4189,6 +4227,11 @@ var COMMANDS = [
4189
4227
  { cmd: "/git <cmd>", desc: "Run a git command" },
4190
4228
  { cmd: "/quit", desc: "Exit" }
4191
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
+ ];
4192
4235
  var TOOLS = [
4193
4236
  "Read",
4194
4237
  "Write",
@@ -4264,6 +4307,19 @@ function HelpModal({ onClose, onCommand }) {
4264
4307
  })
4265
4308
  }, cmd))
4266
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
+ }),
4267
4323
  /* @__PURE__ */ jsx_runtime14.jsx("text", {
4268
4324
  fg: import_theme14.colors.white,
4269
4325
  attributes: TextAttributes.BOLD,
@@ -4304,7 +4360,7 @@ var import_useLayout = __toESM(require_useLayout(), 1);
4304
4360
  var jsx_runtime = __toESM(require_jsx_runtime(), 1);
4305
4361
  var PROVIDER_ORDER = ["fireworks", "openai", "openrouter", "groq", "gemini", "together"];
4306
4362
  var PROVIDER_EMOJI = {
4307
- fireworks: "\uD83C\uDF86",
4363
+ fireworks: "\uD83D\uDD25",
4308
4364
  openai: "\uD83E\uDD16",
4309
4365
  openrouter: "\uD83D\uDD00",
4310
4366
  groq: "\u26A1",
@@ -4338,9 +4394,9 @@ function ProviderSelector() {
4338
4394
  provider: providerKey,
4339
4395
  needsConfig: false
4340
4396
  });
4341
- } else {
4342
- setStep("key");
4397
+ return;
4343
4398
  }
4399
+ setStep("key");
4344
4400
  }
4345
4401
  function handleSubmitKey() {
4346
4402
  var key = input.trim();
@@ -4348,6 +4404,8 @@ function ProviderSelector() {
4348
4404
  return;
4349
4405
  import_config.setProvider(providerKey, key);
4350
4406
  import_store.setState({ apiKey: key, provider: providerKey, needsConfig: false });
4407
+ setInput("");
4408
+ setStep("select");
4351
4409
  }
4352
4410
  var handleKeyPress = function(key) {
4353
4411
  if (step === "select") {
@@ -4375,7 +4433,7 @@ function ProviderSelector() {
4375
4433
  style: {
4376
4434
  flexDirection: "column",
4377
4435
  flexGrow: 1,
4378
- paddingTop: 3
4436
+ paddingTop: 2
4379
4437
  },
4380
4438
  onKeyDown: handleKeyPress,
4381
4439
  focused: true,
@@ -4386,14 +4444,14 @@ function ProviderSelector() {
4386
4444
  children: jsx_runtime.jsx("text", {
4387
4445
  attributes: TextAttributes.BOLD,
4388
4446
  fg: import_theme.colors.white,
4389
- children: "\u26A1 Select AI Provider"
4447
+ children: "Choose your AI provider"
4390
4448
  })
4391
4449
  }),
4392
4450
  jsx_runtime.jsx("box", {
4393
4451
  style: { paddingLeft: 4, paddingRight: 4, marginBottom: 1 },
4394
4452
  children: jsx_runtime.jsx("text", {
4395
4453
  fg: import_theme.colors.dim,
4396
- 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."
4397
4455
  })
4398
4456
  }),
4399
4457
  PROVIDER_ORDER.map(function(key, idx) {
@@ -4401,14 +4459,12 @@ function ProviderSelector() {
4401
4459
  var configured = isConfigured(key);
4402
4460
  var def = isDefault(key);
4403
4461
  var statusFg = def ? import_theme.colors.accent : configured ? import_theme.colors.green : import_theme.colors.dim;
4404
- var statusText = def ? "\u2713 Active" : configured ? "\u2713 Configured" : "\u2717 Not configured";
4462
+ var statusText = def ? "Active" : configured ? "Configured" : "Needs key";
4405
4463
  return jsx_runtime.jsxs("box", {
4406
4464
  style: {
4407
4465
  flexDirection: "row",
4408
- paddingLeft: focused ? 4 : 4,
4409
- paddingRight: 4,
4410
- paddingTop: 0,
4411
- paddingBottom: 0
4466
+ paddingLeft: 4,
4467
+ paddingRight: 4
4412
4468
  },
4413
4469
  onMouseEnter: function() {
4414
4470
  setFocusedIdx(idx);
@@ -4443,7 +4499,7 @@ function ProviderSelector() {
4443
4499
  style: { paddingLeft: 4, paddingRight: 4, marginTop: 2 },
4444
4500
  children: jsx_runtime.jsx("text", {
4445
4501
  fg: import_theme.colors.dim,
4446
- 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."
4447
4503
  })
4448
4504
  })
4449
4505
  ]
@@ -4697,7 +4753,14 @@ function App() {
4697
4753
  });
4698
4754
  }
4699
4755
  }, []);
4700
- const showConfig = state.needsConfig || process.env.APEX_DEV_NEEDS_CONFIG === "true";
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
+ }
4701
4764
  return /* @__PURE__ */ jsx_runtime15.jsxs("box", {
4702
4765
  style: { flexDirection: "column", flexGrow: 1 },
4703
4766
  children: [
@@ -4714,15 +4777,13 @@ function App() {
4714
4777
  isProcessing: state.isProcessing
4715
4778
  }),
4716
4779
  /* @__PURE__ */ jsx_runtime15.jsx(InputBar, {
4717
- disabled: state.isProcessing || state.showHelp || state.needsConfig,
4780
+ disabled: state.isProcessing || state.showHelp,
4718
4781
  onSubmit: handleInput
4719
4782
  }),
4720
4783
  state.showHelp ? /* @__PURE__ */ jsx_runtime15.jsx(HelpModal, {
4721
4784
  onClose: () => import_store5.setState({ showHelp: false }),
4722
4785
  onCommand: handleHelpCommand
4723
- }) : null,
4724
- showConfig ? /* @__PURE__ */ jsx_runtime15.jsx(globalThis._ApiKeyModal, {}) : null,
4725
- state.needsConfig ? /* @__PURE__ */ jsx_runtime15.jsx(globalThis._ProviderSelector, {}) : null
4786
+ }) : null
4726
4787
  ]
4727
4788
  });
4728
4789
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apex-dev",
3
- "version": "3.10.21",
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": {