@compilr-dev/cli 0.5.9 → 0.5.11

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.
Binary file
package/dist/index.js CHANGED
@@ -237,9 +237,10 @@ async function main() {
237
237
  // Resolve model: CLI arg > settings > provider default
238
238
  const settingsModel = getDefaultModelSetting();
239
239
  let model = options.model ?? settingsModel ?? getDefaultModel(provider);
240
+ // On first run, skip API key check — the onboarding wizard handles setup
241
+ const isFirstRun = !isFirstRunComplete();
240
242
  // Check if API key is available for selected provider (skip for ollama and first run)
241
- // On first run, the onboarding wizard handles API key setup (step 4)
242
- if (provider !== 'ollama' && isFirstRunComplete()) {
243
+ if (provider !== 'ollama' && !isFirstRun) {
243
244
  const credentialKey = settingsProviderToCredentialKey(provider === 'claude' ? 'claude' : provider);
244
245
  if (!hasApiKey(credentialKey)) {
245
246
  console.log(s.warning('⚠ No API key found for ' + provider));
@@ -515,8 +516,9 @@ async function main() {
515
516
  };
516
517
  const defaultEpisodeRecorder = createEpisodeRecorder('default');
517
518
  // Create agent with permission handler and suggestion callback (no MCP tools yet)
519
+ // On first run, defer agent creation until after the onboarding wizard completes
518
520
  perf('create-agent-start');
519
- const agent = createAgent({
521
+ const agent = isFirstRun ? undefined : createAgent({
520
522
  provider,
521
523
  model,
522
524
  minimal: options.minimal,
@@ -564,7 +566,7 @@ async function main() {
564
566
  let defaultAgentRef = agent;
565
567
  // Bind grantSession for the permission handler to use
566
568
  sharedState.grantSession = (toolName) => {
567
- defaultAgentRef.grantSessionPermission(toolName);
569
+ defaultAgentRef?.grantSessionPermission(toolName);
568
570
  };
569
571
  // ==========================================================================
570
572
  // Create AgentTeam with the default agent (or restore from persistence)
@@ -628,7 +630,9 @@ async function main() {
628
630
  name: 'Team',
629
631
  agentFactory,
630
632
  });
631
- team.setDefaultAgent(agent);
633
+ if (agent) {
634
+ team.setDefaultAgent(agent);
635
+ }
632
636
  // Set the active shared context for activity recording
633
637
  setActiveSharedContext(team.sharedContext);
634
638
  // Populate shared context with actual project info so agents know the project name
@@ -789,7 +793,55 @@ async function main() {
789
793
  sharedState.sessionPrefix = sessionId.slice(0, 8);
790
794
  },
791
795
  // Show onboarding wizard on first run
792
- showOnboarding: !isFirstRunComplete(),
796
+ showOnboarding: isFirstRun,
797
+ // After onboarding, re-read settings and create the agent
798
+ onOnboardingComplete: () => {
799
+ // Re-read provider/model from settings (user may have changed them in the wizard)
800
+ const settingsProvider2 = getDefaultProvider();
801
+ provider = (settingsProvider2 !== 'auto' ? settingsProvider2 : null)
802
+ ?? detectProvider();
803
+ model = getDefaultModelSetting() ?? getDefaultModel(provider);
804
+ // Try to create the agent with the configured provider
805
+ const newAgent = createAgent({
806
+ provider,
807
+ model,
808
+ minimal: options.minimal,
809
+ quiet: true,
810
+ enableMetaTools: !options.minimal && getProviderMetadata(provider).supportsMetaTools,
811
+ onPermissionRequest,
812
+ onIterationLimitReached,
813
+ onSuggest: (event) => {
814
+ sharedState.pendingSuggestion = event.action;
815
+ },
816
+ projectName: liveProjectState.dbProject?.displayName,
817
+ projectSlug: liveProjectState.dbProject?.name,
818
+ projectId: liveProjectState.dbProject?.id,
819
+ projectContext: liveProjectState.projectContext,
820
+ guidedModeContext: liveProjectState.guidedModeContext,
821
+ enableAnchors: true,
822
+ persistedAnchors: persistedAnchors.length > 0 ? persistedAnchors : undefined,
823
+ enableGuardrails: true,
824
+ onGuardrailTriggered,
825
+ onSubagentStart: (toolUseId, agentType, description) => {
826
+ sharedState.onSubagentStart?.(toolUseId, agentType, description);
827
+ },
828
+ onSubagentEnd: (toolUseId, success, tokenCount, error) => {
829
+ sharedState.onSubagentEnd?.(toolUseId, success, tokenCount, error);
830
+ },
831
+ onSubagentToolUse: (toolUseId, toolName, summary) => {
832
+ sharedState.onSubagentToolUse?.(toolUseId, toolName, summary);
833
+ },
834
+ onSubagentTrackingReady: (clearTracking) => {
835
+ sharedState.clearSubagentTracking = clearTracking;
836
+ },
837
+ episodeRecorder: defaultEpisodeRecorder,
838
+ });
839
+ defaultAgentRef = newAgent;
840
+ sharedState.grantSession = (toolName) => {
841
+ defaultAgentRef?.grantSessionPermission(toolName);
842
+ };
843
+ return Promise.resolve(newAgent);
844
+ },
793
845
  // Show login overlay if not authenticated
794
846
  showLogin,
795
847
  });
@@ -816,7 +868,7 @@ async function main() {
816
868
  perf('mcp-background-done');
817
869
  replV2.setMCPLoading(false, tools.length);
818
870
  if (tools.length > 0) {
819
- agent.registerTools(tools);
871
+ agent?.registerTools(tools);
820
872
  mcpToolsRef = tools;
821
873
  }
822
874
  })
@@ -831,12 +883,33 @@ async function main() {
831
883
  // Provider Detection
832
884
  // =============================================================================
833
885
  function detectProvider() {
886
+ // Check env vars first (fastest)
834
887
  if (process.env.ANTHROPIC_API_KEY)
835
888
  return 'claude';
836
889
  if (process.env.OPENAI_API_KEY)
837
890
  return 'openai';
838
891
  if (process.env.GOOGLE_AI_API_KEY)
839
892
  return 'gemini';
893
+ // Check credential store (keys set via /keys)
894
+ if (hasApiKey('anthropic'))
895
+ return 'claude';
896
+ if (hasApiKey('openai'))
897
+ return 'openai';
898
+ if (hasApiKey('google'))
899
+ return 'gemini';
900
+ if (hasApiKey('together'))
901
+ return 'together';
902
+ if (hasApiKey('groq'))
903
+ return 'groq';
904
+ if (hasApiKey('fireworks'))
905
+ return 'fireworks';
906
+ if (hasApiKey('perplexity'))
907
+ return 'perplexity';
908
+ if (hasApiKey('openrouter'))
909
+ return 'openrouter';
910
+ // Ollama doesn't need a key — check if it's likely available
911
+ if (hasApiKey('ollama'))
912
+ return 'ollama';
840
913
  // Default to claude
841
914
  return 'claude';
842
915
  }
package/dist/repl-v2.d.ts CHANGED
@@ -170,6 +170,12 @@ export interface ReplV2Options {
170
170
  * Allows index.ts to update defaultAgentRef for grantSession.
171
171
  */
172
172
  onDefaultAgentSwapped?: (newAgent: Agent) => void;
173
+ /**
174
+ * Callback invoked after the onboarding wizard completes on first run.
175
+ * Returns the newly created agent (index.ts re-reads settings, updates
176
+ * provider/model, and creates the agent).
177
+ */
178
+ onOnboardingComplete?: () => Promise<Agent | undefined>;
173
179
  }
174
180
  /**
175
181
  * Options for switchAgent().
@@ -231,6 +237,7 @@ export declare class ReplV2 {
231
237
  private readonly onSessionRegistered?;
232
238
  private readonly onTeamReplaced?;
233
239
  private readonly onProjectStateUpdate?;
240
+ private readonly onOnboardingComplete?;
234
241
  private readonly onDefaultAgentSwapped?;
235
242
  private readonly authOnly;
236
243
  private restoredSessionInfo;
package/dist/repl-v2.js CHANGED
@@ -199,6 +199,7 @@ export class ReplV2 {
199
199
  onSessionRegistered;
200
200
  onTeamReplaced;
201
201
  onProjectStateUpdate;
202
+ onOnboardingComplete;
202
203
  onDefaultAgentSwapped;
203
204
  authOnly;
204
205
  restoredSessionInfo = null;
@@ -246,6 +247,7 @@ export class ReplV2 {
246
247
  this.onSessionRegistered = options.onSessionRegistered;
247
248
  this.onTeamReplaced = options.onTeamReplaced;
248
249
  this.onProjectStateUpdate = options.onProjectStateUpdate;
250
+ this.onOnboardingComplete = options.onOnboardingComplete;
249
251
  this.onDefaultAgentSwapped = options.onDefaultAgentSwapped;
250
252
  this.authOnly = options.authOnly ?? false;
251
253
  }
@@ -1521,6 +1523,26 @@ export class ReplV2 {
1521
1523
  await this.showOnboardingWizard();
1522
1524
  return;
1523
1525
  }
1526
+ // If agent wasn't created at startup (first run), create it now.
1527
+ // onOnboardingComplete re-reads provider/model from settings and creates the agent.
1528
+ if (!this.agent && this.onOnboardingComplete) {
1529
+ try {
1530
+ const newAgent = await this.onOnboardingComplete();
1531
+ if (newAgent) {
1532
+ this.agent = newAgent;
1533
+ if (this.team) {
1534
+ this.team.setDefaultAgent(newAgent);
1535
+ }
1536
+ }
1537
+ }
1538
+ catch {
1539
+ // Agent creation failed (no API key configured)
1540
+ this.ui.print({
1541
+ type: 'warning',
1542
+ message: 'No API key configured. Use /keys to set one, or /init to restart setup.',
1543
+ });
1544
+ }
1545
+ }
1524
1546
  // Start session heartbeat in background (don't block UI)
1525
1547
  const auth = getAuthManager();
1526
1548
  void auth.startSession();
@@ -126,7 +126,7 @@ export class OnboardingWizardOverlayV2 extends BaseOverlayV2 {
126
126
  placeholder: projectsPath,
127
127
  initialValue: projectsPath,
128
128
  });
129
- this.minHeight = 22;
129
+ this.minHeight = 25;
130
130
  }
131
131
  // ===========================================================================
132
132
  // Rendering
@@ -272,7 +272,7 @@ export class OnboardingWizardOverlayV2 extends BaseOverlayV2 {
272
272
  }
273
273
  renderStepApiKeys(s) {
274
274
  const lines = [];
275
- lines.push(` ${s.secondary('Step 2: LLM API Keys')}`);
275
+ lines.push(` ${s.secondary('LLM API Keys')}`);
276
276
  lines.push('');
277
277
  if (this.state.hasAnyKey) {
278
278
  lines.push(` ${s.success('✓')} You have API keys configured:`);
@@ -298,7 +298,7 @@ export class OnboardingWizardOverlayV2 extends BaseOverlayV2 {
298
298
  renderStepGitConfig(s) {
299
299
  const lines = [];
300
300
  const { gitConfig, inputMode } = this.state;
301
- lines.push(` ${s.secondary('Step 3: Git Configuration')}`);
301
+ lines.push(` ${s.secondary('Git Configuration')}`);
302
302
  lines.push('');
303
303
  // Input mode: entering git name
304
304
  if (inputMode === 'git-name') {
@@ -349,7 +349,7 @@ export class OnboardingWizardOverlayV2 extends BaseOverlayV2 {
349
349
  renderStepPaths(s) {
350
350
  const lines = [];
351
351
  const { inputMode, projectsPath } = this.state;
352
- lines.push(` ${s.secondary('Step 4: Projects Folder')}`);
352
+ lines.push(` ${s.secondary('Projects Folder')}`);
353
353
  lines.push('');
354
354
  // Input mode: editing path
355
355
  if (inputMode === 'projects-path') {
@@ -371,7 +371,7 @@ export class OnboardingWizardOverlayV2 extends BaseOverlayV2 {
371
371
  }
372
372
  renderStepCompilrMd(s) {
373
373
  const lines = [];
374
- lines.push(` ${s.secondary('Step 5: Project Memory (COMPILR.md)')}`);
374
+ lines.push(` ${s.secondary('Project Memory (COMPILR.md)')}`);
375
375
  lines.push('');
376
376
  lines.push(' Create a COMPILR.md file in your project root to give the');
377
377
  lines.push(' AI assistant context about your codebase.');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@compilr-dev/cli",
3
- "version": "0.5.9",
3
+ "version": "0.5.11",
4
4
  "description": "AI-powered coding assistant CLI using @compilr-dev/agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",