profclaw 0.0.1-beta.3 → 2.0.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 (156) hide show
  1. package/CHANGELOG.md +21 -38
  2. package/CONTRIBUTING.md +3 -5
  3. package/README.md +128 -63
  4. package/dist/chat/execution/tools/index.d.ts +1 -1
  5. package/dist/chat/execution/tools/index.js +41 -2
  6. package/dist/chat/providers/slack/index.d.ts +2 -2
  7. package/dist/cli/commands/models.js +39 -26
  8. package/dist/cli/commands/onboard.js +64 -79
  9. package/dist/cli/commands/setup.js +293 -90
  10. package/dist/cli/index.js +0 -6
  11. package/dist/cli/providers.d.ts +15 -0
  12. package/dist/cli/providers.js +41 -0
  13. package/dist/core/deployment.js +2 -0
  14. package/dist/providers/ai-sdk.js +26 -6
  15. package/dist/routes/channels.d.ts +12 -0
  16. package/dist/routes/channels.js +166 -0
  17. package/dist/server/route-loader.js +1 -0
  18. package/dist/server.js +115 -109
  19. package/package.json +1 -1
  20. package/skills/git-workflow/SKILL.md +3 -3
  21. package/ui/dist/assets/{ActivityView-DIPQSJ_d.js → ActivityView-BeshZXmE.js} +1 -1
  22. package/ui/dist/assets/{AgentList-CqyaYrcq.js → AgentList-QVHeldPi.js} +1 -1
  23. package/ui/dist/assets/{AnalyticsDashboard-C-mjuGHT.js → AnalyticsDashboard-C9R97dXE.js} +1 -1
  24. package/ui/dist/assets/{AreaChart-CfYWmbtr.js → AreaChart-B73gaiVQ.js} +1 -1
  25. package/ui/dist/assets/{CartesianChart-BaQ3It0c.js → CartesianChart-CXYL2R-A.js} +1 -1
  26. package/ui/dist/assets/{ChatView-DxxQy6pl.js → ChatView-qjZErlrp.js} +1 -1
  27. package/ui/dist/assets/{CostsDashboard-CDBBcGkg.js → CostsDashboard-O4DCLy1i.js} +1 -1
  28. package/ui/dist/assets/{EstimateSelect-CDjf5qKl.js → EstimateSelect-1hQf4Osk.js} +1 -1
  29. package/ui/dist/assets/{FloatingChatbot-CZHjvJIe.js → FloatingChatbot-BZBzrJxd.js} +1 -1
  30. package/ui/dist/assets/{InviteCodeManagement-DTm-IPTm.js → InviteCodeManagement-LEoGqYeA.js} +1 -1
  31. package/ui/dist/assets/{ProjectDetail-DlYUcOss.js → ProjectDetail--gPfvATB.js} +1 -1
  32. package/ui/dist/assets/{ProjectIcon-BMRpnM04.js → ProjectIcon-Chd_ofsw.js} +1 -1
  33. package/ui/dist/assets/{ProjectList-D85TN0i0.js → ProjectList-BvUfVB6c.js} +1 -1
  34. package/ui/dist/assets/{Settings-CgPqzUvj.js → Settings-1kaf7VHE.js} +1 -1
  35. package/ui/dist/assets/{StatusIndicator-yig0uZEA.js → StatusIndicator-pRfkNcdV.js} +1 -1
  36. package/ui/dist/assets/{SummaryDetail-CwLAfHgJ.js → SummaryDetail-DV3AmONk.js} +1 -1
  37. package/ui/dist/assets/{SummaryList-BvS5Idnu.js → SummaryList-B6kXiTxL.js} +1 -1
  38. package/ui/dist/assets/{TaskDetail-zarC1fOt.js → TaskDetail-CV6CzbOS.js} +1 -1
  39. package/ui/dist/assets/{TaskList-CyJq3ANE.js → TaskList-DL7brQKd.js} +1 -1
  40. package/ui/dist/assets/{TicketBoard-BlWr3-iH.js → TicketBoard-CrkkFj7C.js} +1 -1
  41. package/ui/dist/assets/{TicketDetail-DmqWKj2W.js → TicketDetail-hnnYclpD.js} +1 -1
  42. package/ui/dist/assets/{TicketList-Scj4pMWa.js → TicketList-CsDAyQCL.js} +1 -1
  43. package/ui/dist/assets/{UserManagement-BH7uG7dw.js → UserManagement-BGFQyTSr.js} +1 -1
  44. package/ui/dist/assets/{ViewSwitcher-3HzZUdWn.js → ViewSwitcher-CnL0OqA8.js} +1 -1
  45. package/ui/dist/assets/{alert-dialog-DWPb2IfQ.js → alert-dialog-SKM6Gjz4.js} +1 -1
  46. package/ui/dist/assets/{archive-CGck7gxR.js → archive-BsLa7brF.js} +1 -1
  47. package/ui/dist/assets/{badge-DEmc3Z_l.js → badge-CVHH1a-v.js} +1 -1
  48. package/ui/dist/assets/{brain-CfFdLVqb.js → brain-6o_RHVpe.js} +1 -1
  49. package/ui/dist/assets/{bug-DqSGPUUE.js → bug-CmZI7jqM.js} +1 -1
  50. package/ui/dist/assets/{calendar-BuZ4zbPW.js → calendar-Bf0t2B82.js} +1 -1
  51. package/ui/dist/assets/{chevron-up-DcJ4LL_N.js → chevron-up-CoUsOvZj.js} +1 -1
  52. package/ui/dist/assets/{circle-x-C78PNZjF.js → circle-x-Dgw11LgT.js} +1 -1
  53. package/ui/dist/assets/{constants-DhDjZe4P.js → constants-Q5Zivl-a.js} +1 -1
  54. package/ui/dist/assets/{cpu-Ck6AoG8c.js → cpu-DiPMQICV.js} +1 -1
  55. package/ui/dist/assets/{database-CA2w8Lvt.js → database-BwTfupDi.js} +1 -1
  56. package/ui/dist/assets/{dialog-BOdGWhgE.js → dialog-BUqN9Psj.js} +1 -1
  57. package/ui/dist/assets/{ellipsis-FhHKRbfl.js → ellipsis-UJx4Xnf6.js} +1 -1
  58. package/ui/dist/assets/{ellipsis-vertical-CO0UqE4-.js → ellipsis-vertical-DoULYEKn.js} +1 -1
  59. package/ui/dist/assets/{file-code-ChnhYYj1.js → file-code-B2UrJLwi.js} +1 -1
  60. package/ui/dist/assets/{folder-open-CHwA1-ve.js → folder-open-BJi577JH.js} +1 -1
  61. package/ui/dist/assets/{funnel-ByEjRFNB.js → funnel-PkaD_HSR.js} +1 -1
  62. package/ui/dist/assets/{git-branch-GTOPQgU4.js → git-branch-C_K30am0.js} +1 -1
  63. package/ui/dist/assets/{git-commit-horizontal-F5M84Kut.js → git-commit-horizontal-IT6ecxWQ.js} +1 -1
  64. package/ui/dist/assets/{globe-CQWfr7hT.js → globe-f-jjCa_g.js} +1 -1
  65. package/ui/dist/assets/{hash-nKC9gtLg.js → hash-DNEv8Elo.js} +1 -1
  66. package/ui/dist/assets/{history-DfFSA9xJ.js → history-BQSBo_1Q.js} +1 -1
  67. package/ui/dist/assets/{index-DHGvP9mp.js → index-BUmnwPQr.js} +1 -1
  68. package/ui/dist/assets/{index-Z4-RtZcs.js → index-BfF5G4Cw.js} +1 -1
  69. package/ui/dist/assets/{index-DeI8lKRR.js → index-C8N375c2.js} +1 -1
  70. package/ui/dist/assets/index-CuxnqVVz.css +1 -0
  71. package/ui/dist/assets/{index-Ca3vk7Gq.js → index-CzMM3QOk.js} +1 -1
  72. package/ui/dist/assets/{index--JkIxVXb.js → index-lJlNPFVJ.js} +3 -3
  73. package/ui/dist/assets/{index-a4Fxq0Hb.js → index-nS3EErDg.js} +1 -1
  74. package/ui/dist/assets/{layers-DFeLExSa.js → layers-jFqVrWMD.js} +1 -1
  75. package/ui/dist/assets/{layout-dashboard-WmgjMhWF.js → layout-dashboard-CcKt1hXw.js} +1 -1
  76. package/ui/dist/assets/{lightbulb-Bo8hEr7B.js → lightbulb-Jhp7FvbU.js} +1 -1
  77. package/ui/dist/assets/{link-2-YqrpQXBH.js → link-2-DdO7ostF.js} +1 -1
  78. package/ui/dist/assets/{markdown-renderer-Croje6Xe.js → markdown-renderer-n1ToC4XQ.js} +1 -1
  79. package/ui/dist/assets/{message-square-CD0H5hot.js → message-square-CBgH65X7.js} +1 -1
  80. package/ui/dist/assets/{pencil-DpFnj5dn.js → pencil-CYXCEPQh.js} +1 -1
  81. package/ui/dist/assets/{play-DVgea_jT.js → play-d1ONaH0-.js} +1 -1
  82. package/ui/dist/assets/{popover-JXecfWG5.js → popover-CrmZgoWu.js} +1 -1
  83. package/ui/dist/assets/{progress-C1ghf1Fu.js → progress-uv4SPkL5.js} +1 -1
  84. package/ui/dist/assets/{rocket-BFxPYGx9.js → rocket-DhvUetsk.js} +1 -1
  85. package/ui/dist/assets/{select-MADP8m6Q.js → select-CeQ8AHGy.js} +1 -1
  86. package/ui/dist/assets/{send-eYnW_7n-.js → send-P0r5D7td.js} +1 -1
  87. package/ui/dist/assets/{server-CPMaysH8.js → server-CVHTZB72.js} +1 -1
  88. package/ui/dist/assets/{settings-2-scXUOuE_.js → settings-2-ocj5uHGx.js} +1 -1
  89. package/ui/dist/assets/{sheet-r6NSOxi-.js → sheet-DuQExSho.js} +1 -1
  90. package/ui/dist/assets/{shield-check-PEr7nmVw.js → shield-check-DfVdE34l.js} +1 -1
  91. package/ui/dist/assets/{shield-off-CLtXio62.js → shield-off-8l0J6R-8.js} +1 -1
  92. package/ui/dist/assets/{skeleton-C9oEzNlU.js → skeleton-TFiFJ3nB.js} +1 -1
  93. package/ui/dist/assets/{smartphone-DusFfY0U.js → smartphone-77_g3SQn.js} +1 -1
  94. package/ui/dist/assets/{square-e1yxB2eR.js → square-Ckzsr3Rn.js} +1 -1
  95. package/ui/dist/assets/{switch-tNs0n-kz.js → switch-CAePkd6k.js} +1 -1
  96. package/ui/dist/assets/{table-CXxtLicg.js → table-ZjAZ7hkt.js} +1 -1
  97. package/ui/dist/assets/{tag-tAwMmQ9G.js → tag-C35mgoEv.js} +1 -1
  98. package/ui/dist/assets/{textarea-BjiEeIWh.js → textarea-DsVPnSgR.js} +1 -1
  99. package/ui/dist/assets/{timer-Vel1N3RP.js → timer-DHJBS2w1.js} +1 -1
  100. package/ui/dist/assets/{tooltip-ZMwtfr1J.js → tooltip-BYmQ331W.js} +1 -1
  101. package/ui/dist/assets/{trash-2-eM-CNwsZ.js → trash-2-keO5tKPE.js} +1 -1
  102. package/ui/dist/assets/{trending-up-BGafmjRo.js → trending-up-BBv8KbrY.js} +1 -1
  103. package/ui/dist/assets/{wand-sparkles-DPvcd9Pi.js → wand-sparkles-BusQ52ZK.js} +1 -1
  104. package/ui/dist/assets/{wrench-B8s3zYVV.js → wrench-02YaOSiK.js} +1 -1
  105. package/ui/dist/index.html +2 -2
  106. package/dist/chat/auto-reply.d.ts +0 -90
  107. package/dist/chat/auto-reply.js +0 -272
  108. package/dist/chat/execution/pty.d.ts +0 -92
  109. package/dist/chat/execution/pty.js +0 -285
  110. package/dist/chat/execution/tools/glinr-ops.d.ts +0 -202
  111. package/dist/chat/execution/tools/glinr-ops.js +0 -694
  112. package/dist/cli/commands/browser.d.ts +0 -3
  113. package/dist/cli/commands/browser.js +0 -138
  114. package/dist/cli/commands/canvas.d.ts +0 -3
  115. package/dist/cli/commands/canvas.js +0 -155
  116. package/dist/cli/commands/nodes.d.ts +0 -3
  117. package/dist/cli/commands/nodes.js +0 -193
  118. package/dist/diagnostics/exporters.d.ts +0 -21
  119. package/dist/diagnostics/exporters.js +0 -138
  120. package/dist/diagnostics/index.d.ts +0 -10
  121. package/dist/diagnostics/index.js +0 -9
  122. package/dist/diagnostics/middleware.d.ts +0 -12
  123. package/dist/diagnostics/middleware.js +0 -58
  124. package/dist/diagnostics/tracer.d.ts +0 -133
  125. package/dist/diagnostics/tracer.js +0 -257
  126. package/dist/discovery/index.d.ts +0 -8
  127. package/dist/discovery/index.js +0 -7
  128. package/dist/discovery/mdns.d.ts +0 -40
  129. package/dist/discovery/mdns.js +0 -249
  130. package/dist/plugins/registry.d.ts +0 -122
  131. package/dist/plugins/registry.js +0 -352
  132. package/dist/plugins/sandbox.d.ts +0 -77
  133. package/dist/plugins/sandbox.js +0 -287
  134. package/dist/plugins/search/brave.d.ts +0 -9
  135. package/dist/plugins/search/brave.js +0 -157
  136. package/dist/plugins/search/duckduckgo.d.ts +0 -9
  137. package/dist/plugins/search/duckduckgo.js +0 -171
  138. package/dist/plugins/search/index.d.ts +0 -13
  139. package/dist/plugins/search/index.js +0 -23
  140. package/dist/plugins/search/searxng.d.ts +0 -9
  141. package/dist/plugins/search/searxng.js +0 -170
  142. package/dist/plugins/search/serper.d.ts +0 -9
  143. package/dist/plugins/search/serper.js +0 -135
  144. package/dist/plugins/search/tavily.d.ts +0 -9
  145. package/dist/plugins/search/tavily.js +0 -146
  146. package/dist/providers/adapters/anthropic.d.ts +0 -26
  147. package/dist/providers/adapters/anthropic.js +0 -306
  148. package/dist/providers/adapters/base.d.ts +0 -53
  149. package/dist/providers/adapters/base.js +0 -99
  150. package/dist/providers/adapters/ollama.d.ts +0 -30
  151. package/dist/providers/adapters/ollama.js +0 -292
  152. package/dist/utils/ai-cache.d.ts +0 -72
  153. package/dist/utils/ai-cache.js +0 -204
  154. package/dist/utils/file-lock.d.ts +0 -85
  155. package/dist/utils/file-lock.js +0 -204
  156. package/ui/dist/assets/index-WclMPci1.css +0 -1
@@ -16,6 +16,14 @@ import { existsSync, writeFileSync, readFileSync } from 'node:fs';
16
16
  import { join } from 'node:path';
17
17
  import { execSync } from 'node:child_process';
18
18
  import { success, error, info, warn, spinner } from '../utils/output.js';
19
+ import { PROVIDER_CATALOG, PROVIDER_ENV_KEYS } from '../providers.js';
20
+ /** Render a step header with progress bar. */
21
+ function stepHeader(step, total, title) {
22
+ const barLen = 20;
23
+ const filled = Math.round((step / total) * barLen);
24
+ const bar = chalk.cyan('━'.repeat(filled)) + chalk.dim('━'.repeat(barLen - filled));
25
+ console.log(`\n ${bar} ${chalk.dim(`${step}/${total}`)} ${chalk.bold.white(title)}\n`);
26
+ }
19
27
  const DETECT_TIMEOUT_MS = 5000;
20
28
  /** Wrap a detection check with a timeout so a hung service doesn't block onboarding. */
21
29
  async function withTimeout(promise, fallback, timeoutMs = DETECT_TIMEOUT_MS) {
@@ -146,7 +154,7 @@ async function runInteractive() {
146
154
  console.log(chalk.cyan(banner));
147
155
  console.log(chalk.dim(' Onboarding Wizard\n'));
148
156
  // Step 1: Detect environment
149
- console.log(chalk.bold.white(' Step 1: Environment Detection\n'));
157
+ stepHeader(1, 6, 'Environment Detection');
150
158
  const spin = spinner('Scanning environment...');
151
159
  spin.start();
152
160
  const env = await detectEnvironment();
@@ -220,8 +228,8 @@ async function runInteractive() {
220
228
  const recommended = recommendMode(env);
221
229
  console.log('');
222
230
  console.log(` ${chalk.cyan('Recommended mode:')} ${chalk.bold(recommended)}`);
223
- // Step 2: Choose mode (arrow keys)
224
- console.log(chalk.bold.white('\n Step 2: Deployment Mode\n'));
231
+ // Step 2: Choose mode
232
+ stepHeader(2, 6, 'Deployment Mode');
225
233
  let mode;
226
234
  try {
227
235
  mode = await select({
@@ -252,47 +260,25 @@ async function runInteractive() {
252
260
  process.exit(0);
253
261
  }
254
262
  success(`Mode: ${mode}`);
255
- // Step 3: AI Provider (searchable list)
256
- console.log(chalk.bold.white('\n Step 3: AI Provider\n'));
263
+ // Step 3: AI Provider
264
+ stepHeader(3, 6, 'AI Provider');
257
265
  let anthropicKey;
258
266
  let openaiKey;
259
267
  let ollamaUrl;
260
- const hasExistingProvider = !!process.env.ANTHROPIC_API_KEY || !!process.env.OPENAI_API_KEY;
261
- if (hasExistingProvider) {
262
- const which = process.env.ANTHROPIC_API_KEY ? 'Anthropic' : 'OpenAI';
263
- info(`AI provider already configured from environment (${which}).`);
268
+ // Check all provider env vars (not just Anthropic/OpenAI)
269
+ let detectedProviderName = null;
270
+ for (const p of PROVIDER_CATALOG) {
271
+ const val = process.env[p.envVar];
272
+ if (val && val !== '' && !val.startsWith('sk-ant-xxxx') && !val.startsWith('sk-xxxx')) {
273
+ detectedProviderName = p.name;
274
+ break;
275
+ }
276
+ }
277
+ if (detectedProviderName) {
278
+ info(`AI provider already configured from environment (${detectedProviderName}).`);
264
279
  }
265
280
  else {
266
- // Provider catalog
267
- const providers = [
268
- { key: 'anthropic', name: 'Anthropic', models: 'Claude 4.x, 3.5 Sonnet', envVar: 'ANTHROPIC_API_KEY', category: 'Popular', tag: 'recommended' },
269
- { key: 'openai', name: 'OpenAI', models: 'GPT-4o, o1, o3', envVar: 'OPENAI_API_KEY', category: 'Popular', tag: '' },
270
- { key: 'google', name: 'Google AI', models: 'Gemini 2.x, Flash', envVar: 'GOOGLE_GENERATIVE_AI_API_KEY', category: 'Popular', tag: '' },
271
- { key: 'ollama', name: 'Ollama', models: 'Llama, Mistral, Qwen', envVar: 'OLLAMA_BASE_URL', category: 'Popular', tag: env.hasOllama ? 'detected' : 'free, local' },
272
- { key: 'groq', name: 'Groq', models: 'Llama, Mixtral', envVar: 'GROQ_API_KEY', category: 'Fast Inference', tag: 'fast' },
273
- { key: 'cerebras', name: 'Cerebras', models: 'Llama 3.3 70B', envVar: 'CEREBRAS_API_KEY', category: 'Fast Inference', tag: 'fast' },
274
- { key: 'fireworks', name: 'Fireworks', models: 'Llama, Mixtral', envVar: 'FIREWORKS_API_KEY', category: 'Fast Inference', tag: '' },
275
- { key: 'together', name: 'Together', models: 'Open models', envVar: 'TOGETHER_API_KEY', category: 'Fast Inference', tag: '' },
276
- { key: 'azure', name: 'Azure OpenAI', models: 'GPT-4o', envVar: 'AZURE_OPENAI_API_KEY', category: 'Enterprise', tag: 'enterprise' },
277
- { key: 'bedrock', name: 'AWS Bedrock', models: 'Claude, Titan, Llama', envVar: 'AWS_ACCESS_KEY_ID', category: 'Enterprise', tag: 'enterprise' },
278
- { key: 'watsonx', name: 'IBM Watsonx', models: 'Granite, Llama', envVar: 'WATSONX_API_KEY', category: 'Enterprise', tag: 'enterprise' },
279
- { key: 'deepseek', name: 'DeepSeek', models: 'V3, R1 (reasoning)', envVar: 'DEEPSEEK_API_KEY', category: 'More Providers', tag: '' },
280
- { key: 'mistral', name: 'Mistral', models: 'Large, Codestral', envVar: 'MISTRAL_API_KEY', category: 'More Providers', tag: '' },
281
- { key: 'xai', name: 'xAI', models: 'Grok', envVar: 'XAI_API_KEY', category: 'More Providers', tag: '' },
282
- { key: 'perplexity', name: 'Perplexity', models: 'Sonar (search)', envVar: 'PERPLEXITY_API_KEY', category: 'More Providers', tag: 'search' },
283
- { key: 'cohere', name: 'Cohere', models: 'Command R+', envVar: 'COHERE_API_KEY', category: 'More Providers', tag: '' },
284
- { key: 'openrouter', name: 'OpenRouter', models: 'Any model (proxy)', envVar: 'OPENROUTER_API_KEY', category: 'Aggregators', tag: 'multi-model' },
285
- { key: 'replicate', name: 'Replicate', models: 'Open-source models', envVar: 'REPLICATE_API_TOKEN', category: 'Aggregators', tag: '' },
286
- { key: 'github-models', name: 'GitHub Models', models: 'Azure-backed', envVar: 'GITHUB_TOKEN', category: 'Aggregators', tag: '' },
287
- { key: 'huggingface', name: 'HuggingFace', models: 'Inference API', envVar: 'HF_TOKEN', category: 'Aggregators', tag: '' },
288
- { key: 'nvidia-nim', name: 'NVIDIA NIM', models: 'Llama, Nemotron', envVar: 'NVIDIA_NIM_API_KEY', category: 'Aggregators', tag: '' },
289
- { key: 'zhipu', name: 'Zhipu AI', models: 'GLM-4, GLM-5', envVar: 'ZHIPU_API_KEY', category: 'Asia', tag: '' },
290
- { key: 'moonshot', name: 'Moonshot', models: 'Kimi (128K context)', envVar: 'MOONSHOT_API_KEY', category: 'Asia', tag: '' },
291
- { key: 'qwen', name: 'Qwen', models: 'Qwen Max, Plus', envVar: 'QWEN_API_KEY', category: 'Asia', tag: '' },
292
- { key: 'minimax', name: 'MiniMax', models: 'abab series', envVar: 'MINIMAX_API_KEY', category: 'Asia', tag: '' },
293
- { key: 'volcengine', name: 'Volcengine', models: 'Doubao (Bytedance)', envVar: 'VOLCENGINE_API_KEY', category: 'Asia', tag: '' },
294
- { key: 'qianfan', name: 'Qianfan', models: 'ERNIE (Baidu)', envVar: 'QIANFAN_API_KEY', category: 'Asia', tag: '' },
295
- ];
281
+ const providers = PROVIDER_CATALOG;
296
282
  // Check which providers have keys in env
297
283
  const detected = new Set();
298
284
  for (const p of providers) {
@@ -306,6 +292,7 @@ async function runInteractive() {
306
292
  try {
307
293
  chosenProvider = await search({
308
294
  message: 'Select AI provider (type to filter, arrows to navigate)',
295
+ pageSize: 15,
309
296
  source: (term) => {
310
297
  const results = [];
311
298
  const filter = (term || '').toLowerCase();
@@ -405,16 +392,25 @@ async function runInteractive() {
405
392
  info('AI provider skipped. Configure later: profclaw provider');
406
393
  }
407
394
  }
395
+ // Collect extra env vars that were set during provider selection
396
+ const extraEnvVars = {};
397
+ if (!anthropicKey && !openaiKey && !ollamaUrl) {
398
+ for (const key of PROVIDER_ENV_KEYS) {
399
+ if (process.env[key])
400
+ extraEnvVars[key] = process.env[key];
401
+ }
402
+ }
408
403
  // Step 4: Generate .env
409
- console.log(chalk.bold.white('\n Step 4: Configuration\n'));
404
+ stepHeader(4, 6, 'Configuration');
405
+ const envPath = join(process.cwd(), '.env');
410
406
  if (!env.existingEnv) {
411
407
  const envContent = generateEnvFile({
412
408
  mode,
413
409
  anthropicKey,
414
410
  openaiKey,
415
411
  ollamaUrl,
412
+ extraEnvVars,
416
413
  });
417
- const envPath = join(process.cwd(), '.env');
418
414
  try {
419
415
  writeFileSync(envPath, envContent, { mode: 0o600 });
420
416
  success('.env file created.');
@@ -425,60 +421,49 @@ async function runInteractive() {
425
421
  }
426
422
  }
427
423
  else {
428
- info('.env file already exists. Updating PROFCLAW_MODE...');
429
- const envPath = join(process.cwd(), '.env');
430
424
  let content = readFileSync(envPath, 'utf-8');
425
+ // Update mode
431
426
  if (content.includes('PROFCLAW_MODE=')) {
432
427
  content = content.replace(/PROFCLAW_MODE=\w+/, `PROFCLAW_MODE=${mode}`);
433
428
  }
434
429
  else {
435
430
  content += `\nPROFCLAW_MODE=${mode}\n`;
436
431
  }
432
+ // Add provider keys to existing .env
433
+ const keysToWrite = { ...extraEnvVars };
434
+ if (anthropicKey)
435
+ keysToWrite['ANTHROPIC_API_KEY'] = anthropicKey;
436
+ if (openaiKey)
437
+ keysToWrite['OPENAI_API_KEY'] = openaiKey;
438
+ if (ollamaUrl)
439
+ keysToWrite['OLLAMA_BASE_URL'] = ollamaUrl;
440
+ for (const [key, value] of Object.entries(keysToWrite)) {
441
+ if (content.includes(`${key}=`)) {
442
+ content = content.replace(new RegExp(`${key}=.*`), `${key}=${value}`);
443
+ }
444
+ else {
445
+ content += `${key}=${value}\n`;
446
+ }
447
+ }
437
448
  writeFileSync(envPath, content);
438
- success(`PROFCLAW_MODE=${mode} set in .env`);
449
+ const keyCount = Object.keys(keysToWrite).length;
450
+ if (keyCount > 0) {
451
+ success(`PROFCLAW_MODE=${mode} + ${keyCount} provider key(s) saved to .env`);
452
+ }
453
+ else {
454
+ success(`PROFCLAW_MODE=${mode} set in .env`);
455
+ }
439
456
  }
440
- // Step 5: Run setup wizard
441
- console.log(chalk.bold.white('\n Step 5: Setup\n'));
442
- info('Launching setup wizard for admin account and provider configuration...\n');
457
+ // Steps 5-6: Delegate to setup wizard for admin account + registration
458
+ // Setup continues the step numbering (5/6, 6/6) and shows summary + server start
443
459
  try {
444
460
  const { setupCommand } = await import('./setup.js');
445
461
  const setupCmd = setupCommand();
446
- await setupCmd.parseAsync(['node', 'setup']);
462
+ await setupCmd.parseAsync(['node', 'setup', '--from-onboard']);
447
463
  }
448
464
  catch (err) {
449
465
  error(`Setup wizard failed: ${err instanceof Error ? err.message : 'Unknown error'}`);
450
466
  info('You can run it again later: profclaw setup');
451
- return;
452
- }
453
- // Step 6: Post-setup validation
454
- console.log(chalk.bold.white('\n Step 6: Validation\n'));
455
- const postSpin = spinner('Validating installation...');
456
- postSpin.start();
457
- const checks = [];
458
- // Check .env exists
459
- const envExists = existsSync(join(process.cwd(), '.env'));
460
- checks.push({ label: '.env file', ok: envExists });
461
- // Check config exists
462
- const configExists = existsSync(join(process.cwd(), 'config', 'settings.yml'));
463
- checks.push({ label: 'config/settings.yml', ok: configExists });
464
- // Check database was created
465
- const dbExists = existsSync(join(process.cwd(), 'data', 'profclaw.db'));
466
- checks.push({ label: 'Database', ok: dbExists });
467
- postSpin.stop();
468
- for (const check of checks) {
469
- const icon = check.ok ? chalk.green(' +') : chalk.red(' -');
470
- console.log(`${icon} ${check.label}: ${check.ok ? 'OK' : 'missing'}`);
471
- }
472
- const allPassed = checks.every((c) => c.ok);
473
- if (allPassed) {
474
- console.log('');
475
- success('Onboarding complete! Start the server:');
476
- console.log(`\n ${chalk.cyan.bold('profclaw serve')}\n`);
477
- }
478
- else {
479
- console.log('');
480
- warn('Some checks did not pass. You may need to run setup again:');
481
- console.log(`\n ${chalk.cyan('profclaw setup')}\n`);
482
467
  }
483
468
  }
484
469
  // Non-Interactive Onboarding