@tecet/ollm 0.1.3 → 0.1.4-b

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 (59) hide show
  1. package/README.md +529 -529
  2. package/dist/cli.js +307 -254
  3. package/dist/cli.js.map +3 -3
  4. package/dist/config/LLM_profiles.json +4 -4
  5. package/dist/config/settingsService.d.ts +5 -0
  6. package/dist/config/settingsService.d.ts.map +1 -1
  7. package/dist/config/settingsService.js +20 -0
  8. package/dist/config/settingsService.js.map +1 -1
  9. package/dist/config/toolsConfig.d.ts +6 -3
  10. package/dist/config/toolsConfig.d.ts.map +1 -1
  11. package/dist/config/toolsConfig.js +52 -3
  12. package/dist/config/toolsConfig.js.map +1 -1
  13. package/dist/features/chat/hooks/useChatNetwork.d.ts.map +1 -1
  14. package/dist/features/chat/hooks/useChatNetwork.js +15 -4
  15. package/dist/features/chat/hooks/useChatNetwork.js.map +1 -1
  16. package/dist/features/context/ContextManagerContext.d.ts.map +1 -1
  17. package/dist/features/context/ContextManagerContext.js +14 -73
  18. package/dist/features/context/ContextManagerContext.js.map +1 -1
  19. package/dist/features/context/hooks/useToolSupport.d.ts.map +1 -1
  20. package/dist/features/context/hooks/useToolSupport.js +13 -5
  21. package/dist/features/context/hooks/useToolSupport.js.map +1 -1
  22. package/dist/features/context/utils/systemPromptBuilder.d.ts.map +1 -1
  23. package/dist/features/context/utils/systemPromptBuilder.js +6 -34
  24. package/dist/features/context/utils/systemPromptBuilder.js.map +1 -1
  25. package/dist/nonInteractive.d.ts.map +1 -1
  26. package/dist/nonInteractive.js +1 -2
  27. package/dist/nonInteractive.js.map +1 -1
  28. package/dist/services/documentService.d.ts.map +1 -1
  29. package/dist/services/documentService.js +12 -2
  30. package/dist/services/documentService.js.map +1 -1
  31. package/dist/templates/assistant/tier3.txt +2 -0
  32. package/dist/templates/system/CoreMandates.txt +3 -0
  33. package/dist/templates/system/ToolDescriptions.txt +11 -3
  34. package/dist/templates/system/skills/SkillsAssistant.txt +1 -2
  35. package/dist/ui/App.js +15 -15
  36. package/dist/ui/components/docs/DocsPanel.d.ts.map +1 -1
  37. package/dist/ui/components/docs/DocsPanel.js +1 -1
  38. package/dist/ui/components/docs/DocsPanel.js.map +1 -1
  39. package/dist/ui/components/launch/VersionBanner.js +1 -1
  40. package/dist/ui/components/launch/VersionBanner.js.map +1 -1
  41. package/dist/ui/components/layout/KeybindsLegend.d.ts.map +1 -1
  42. package/dist/ui/components/layout/KeybindsLegend.js +1 -1
  43. package/dist/ui/components/layout/KeybindsLegend.js.map +1 -1
  44. package/dist/ui/components/tabs/BugReportTab.js +1 -1
  45. package/dist/ui/components/tabs/BugReportTab.js.map +1 -1
  46. package/dist/ui/components/tools/CategorySection.d.ts.map +1 -1
  47. package/dist/ui/components/tools/CategorySection.js +1 -0
  48. package/dist/ui/components/tools/CategorySection.js.map +1 -1
  49. package/dist/ui/contexts/__tests__/mcpTestUtils.d.ts +14 -14
  50. package/dist/ui/services/docsService.d.ts +12 -27
  51. package/dist/ui/services/docsService.d.ts.map +1 -1
  52. package/dist/ui/services/docsService.js +40 -67
  53. package/dist/ui/services/docsService.js.map +1 -1
  54. package/docs/DevelopmentRoadmap/OLLM-CLI_Releases.md +419 -419
  55. package/docs/DevelopmentRoadmap/RoadmapVisual.md +372 -372
  56. package/docs/LLM Models/LLM_ModelsList.md +1071 -1071
  57. package/docs/MCP/MCP_Architecture.md +1086 -1086
  58. package/package.json +85 -82
  59. package/scripts/copy-docs-to-user.cjs +34 -0
package/dist/cli.js CHANGED
@@ -1549,6 +1549,87 @@ var init_chatClient = __esm({
1549
1549
  options.modeManager
1550
1550
  ) : this.toolRegistry.getFunctionSchemas();
1551
1551
  }
1552
+ try {
1553
+ const usage = this.contextMgmtManager?.getUsage();
1554
+ const ollamaLimit = this.contextMgmtManager?.getOllamaContextLimit?.() ?? options?.ollamaContextSize;
1555
+ if (usage && ollamaLimit && options) {
1556
+ const remaining = Math.max(0, ollamaLimit - usage.currentTokens);
1557
+ const safeMax = Math.max(1, remaining - 100);
1558
+ if (options.maxTokens === void 0) {
1559
+ options.maxTokens = safeMax;
1560
+ debugLog("ChatClient", `Auto-setting maxTokens=${safeMax} (remaining=${remaining})`);
1561
+ } else {
1562
+ options.maxTokens = Math.min(options.maxTokens, Math.max(1, remaining));
1563
+ }
1564
+ try {
1565
+ const effectiveNumCtx = Math.min(
1566
+ ollamaLimit,
1567
+ usage.currentTokens + (options.maxTokens ?? 1)
1568
+ );
1569
+ options.ollamaContextSize = Math.max(effectiveNumCtx, usage.currentTokens + 1);
1570
+ debugLog(
1571
+ "ChatClient",
1572
+ `Setting effective ollamaContextSize=${options.ollamaContextSize} (usage=${usage.currentTokens}, maxTokens=${options.maxTokens}, profileLimit=${ollamaLimit})`
1573
+ );
1574
+ } catch (err) {
1575
+ debugLog("ChatClient", "Failed to compute effective ollamaContextSize", {
1576
+ error: String(err)
1577
+ });
1578
+ }
1579
+ try {
1580
+ const requested = options.maxTokens ?? 0;
1581
+ if (usage.currentTokens + requested > ollamaLimit) {
1582
+ debugLog("ChatClient", "Potential overflow detected before request start", {
1583
+ currentTokens: usage.currentTokens,
1584
+ requested,
1585
+ ollamaLimit
1586
+ });
1587
+ if (this.contextMgmtManager?.isSummarizationInProgress()) {
1588
+ const waitMs = 5e3;
1589
+ debugLog("ChatClient", `Waiting up to ${waitMs}ms for summarization to free space`);
1590
+ const waitPromise = this.contextMgmtManager.waitForSummarization(waitMs);
1591
+ if (options.abortSignal) {
1592
+ const abortPromise = new Promise((resolve9, reject) => {
1593
+ options.abortSignal.addEventListener(
1594
+ "abort",
1595
+ () => reject(new Error("aborted"))
1596
+ );
1597
+ });
1598
+ try {
1599
+ await Promise.race([waitPromise, abortPromise]);
1600
+ } catch (_e) {
1601
+ yield { type: "finish", reason: "cancelled" };
1602
+ return;
1603
+ }
1604
+ } else {
1605
+ try {
1606
+ await waitPromise;
1607
+ } catch (_e) {
1608
+ }
1609
+ }
1610
+ }
1611
+ const latestUsage = this.contextMgmtManager?.getUsage();
1612
+ const remainingAfter = Math.max(
1613
+ 0,
1614
+ (ollamaLimit || 0) - (latestUsage?.currentTokens ?? usage.currentTokens)
1615
+ );
1616
+ if (remainingAfter < (options.maxTokens ?? 0)) {
1617
+ yield {
1618
+ type: "error",
1619
+ error: new Error(
1620
+ "Insufficient context capacity: request would exceed Ollama context limit. Try reducing maxTokens or enable compression."
1621
+ )
1622
+ };
1623
+ return;
1624
+ }
1625
+ }
1626
+ } catch (err) {
1627
+ debugLog("ChatClient", "Overflow guard check failed", { error: String(err) });
1628
+ }
1629
+ }
1630
+ } catch (err) {
1631
+ debugLog("ChatClient", "Failed to compute safe maxTokens", { error: String(err) });
1632
+ }
1552
1633
  const turnOptions = {
1553
1634
  ...options,
1554
1635
  systemPrompt: systemPromptWithContext,
@@ -1903,7 +1984,7 @@ var init_generated_model_db = __esm({
1903
1984
  "family": "gemma3:1b",
1904
1985
  "contextWindow": 131072,
1905
1986
  "capabilities": {
1906
- "toolCalling": true,
1987
+ "toolCalling": false,
1907
1988
  "vision": false,
1908
1989
  "streaming": true,
1909
1990
  "reasoning": false
@@ -1922,7 +2003,7 @@ var init_generated_model_db = __esm({
1922
2003
  "family": "gemma3:4b",
1923
2004
  "contextWindow": 131072,
1924
2005
  "capabilities": {
1925
- "toolCalling": true,
2006
+ "toolCalling": false,
1926
2007
  "vision": false,
1927
2008
  "streaming": true,
1928
2009
  "reasoning": true
@@ -1941,7 +2022,7 @@ var init_generated_model_db = __esm({
1941
2022
  "family": "gemma3n:e2b",
1942
2023
  "contextWindow": 131072,
1943
2024
  "capabilities": {
1944
- "toolCalling": true,
2025
+ "toolCalling": false,
1945
2026
  "vision": false,
1946
2027
  "streaming": true,
1947
2028
  "reasoning": false
@@ -2079,7 +2160,7 @@ var init_generated_model_db = __esm({
2079
2160
  "family": "llama3.2:3b",
2080
2161
  "contextWindow": 131072,
2081
2162
  "capabilities": {
2082
- "toolCalling": true,
2163
+ "toolCalling": false,
2083
2164
  "vision": false,
2084
2165
  "streaming": true,
2085
2166
  "reasoning": false
@@ -2972,7 +3053,7 @@ var init_generated_model_db = __esm({
2972
3053
  "General Purpose",
2973
3054
  "Fast Inference"
2974
3055
  ],
2975
- "tool_support": true,
3056
+ "tool_support": false,
2976
3057
  "reasoning": false,
2977
3058
  "ollama_url": "https://ollama.com/library/gemma3",
2978
3059
  "max_context_window": 131072,
@@ -3034,7 +3115,7 @@ var init_generated_model_db = __esm({
3034
3115
  "General Purpose",
3035
3116
  "Reasoning"
3036
3117
  ],
3037
- "tool_support": true,
3118
+ "tool_support": false,
3038
3119
  "reasoning": false,
3039
3120
  "ollama_url": "https://ollama.com/library/gemma3",
3040
3121
  "max_context_window": 131072,
@@ -3096,7 +3177,7 @@ var init_generated_model_db = __esm({
3096
3177
  "General Purpose",
3097
3178
  "Experimental"
3098
3179
  ],
3099
- "tool_support": true,
3180
+ "tool_support": false,
3100
3181
  "reasoning": false,
3101
3182
  "ollama_url": "https://ollama.com/library/gemma3",
3102
3183
  "max_context_window": 131072,
@@ -3489,7 +3570,7 @@ var init_generated_model_db = __esm({
3489
3570
  "General Purpose",
3490
3571
  "Edge Optimized"
3491
3572
  ],
3492
- "tool_support": true,
3573
+ "tool_support": false,
3493
3574
  "reasoning": false,
3494
3575
  "ollama_url": "https://ollama.com/library/llama3.2",
3495
3576
  "max_context_window": 131072,
@@ -9172,7 +9253,11 @@ var init_toolRouter = __esm({
9172
9253
 
9173
9254
  // packages/core/src/tools/index.ts
9174
9255
  function registerBuiltInTools(registry2, config2) {
9175
- const { memoryPath = "~/.ollm/memory.json", todosPath = "~/.ollm/todos.json" } = config2 || {};
9256
+ const {
9257
+ memoryPath = "~/.ollm/memory.json",
9258
+ todosPath = "~/.ollm/todos.json"
9259
+ // enableGoalTools is ignored - goal tools are always registered but disabled by default
9260
+ } = config2 || {};
9176
9261
  registry2.register(new ReadFileTool());
9177
9262
  registry2.register(new ReadManyFilesTool());
9178
9263
  registry2.register(new WriteFileTool());
@@ -31183,7 +31268,7 @@ function deriveGPUPlacementHints(info, contextSize) {
31183
31268
  return {
31184
31269
  num_gpu: 999,
31185
31270
  gpu_layers: 0
31186
- // Not used, kept for compatibility
31271
+ // Not used but kept for compatibility
31187
31272
  };
31188
31273
  }
31189
31274
  var MIN_FREE_VRAM_BYTES, GPU_LAYER_CHUNK_BYTES, MIN_GPU_LAYERS, MAX_GPU_LAYERS;
@@ -31206,11 +31291,13 @@ var init_ContextSizeCalculator = __esm({
31206
31291
  });
31207
31292
 
31208
31293
  // packages/core/src/context/contextPool.ts
31209
- var DEFAULT_CONFIG4;
31294
+ var logger3, DEFAULT_CONFIG4;
31210
31295
  var init_contextPool = __esm({
31211
31296
  "packages/core/src/context/contextPool.ts"() {
31212
31297
  "use strict";
31213
31298
  init_ContextSizeCalculator();
31299
+ init_logger();
31300
+ logger3 = createLogger("ContextPool");
31214
31301
  DEFAULT_CONFIG4 = {
31215
31302
  minContextSize: 2048,
31216
31303
  maxContextSize: 131072,
@@ -34613,10 +34700,21 @@ var init_modelAwareCompression = __esm({
34613
34700
  });
34614
34701
 
34615
34702
  // packages/core/src/context/integration/promptOrchestratorIntegration.ts
34703
+ function mapTierToNumber(tier) {
34704
+ const mapping = {
34705
+ ["2-4K" /* TIER_1_MINIMAL */]: 1,
34706
+ ["8K" /* TIER_2_BASIC */]: 2,
34707
+ ["16K" /* TIER_3_STANDARD */]: 3,
34708
+ ["32K" /* TIER_4_PREMIUM */]: 4,
34709
+ ["64K+" /* TIER_5_ULTRA */]: 5
34710
+ };
34711
+ return mapping[tier] || 3;
34712
+ }
34616
34713
  var PromptOrchestratorIntegration;
34617
34714
  var init_promptOrchestratorIntegration = __esm({
34618
34715
  "packages/core/src/context/integration/promptOrchestratorIntegration.ts"() {
34619
34716
  "use strict";
34717
+ init_types3();
34620
34718
  PromptOrchestratorIntegration = class {
34621
34719
  promptOrchestrator;
34622
34720
  profileManager;
@@ -34647,7 +34745,25 @@ var init_promptOrchestratorIntegration = __esm({
34647
34745
  config2.mode,
34648
34746
  config2.tier
34649
34747
  );
34650
- const basePrompt = this.buildBasePrompt(config2);
34748
+ let modelSupportsTools = false;
34749
+ if (config2.modelId && this.profileManager) {
34750
+ try {
34751
+ const modelEntry = this.profileManager.getModelEntry(config2.modelId);
34752
+ const anyEntry = modelEntry;
34753
+ modelSupportsTools = anyEntry.tool_support || anyEntry.capabilities?.tools || false;
34754
+ } catch (_error) {
34755
+ modelSupportsTools = false;
34756
+ }
34757
+ }
34758
+ const basePrompt = this.promptOrchestrator.buildBasePrompt({
34759
+ interactive: true,
34760
+ mode: config2.mode,
34761
+ tier: mapTierToNumber(config2.tier),
34762
+ modelSupportsTools,
34763
+ allowedTools: config2.allowedTools,
34764
+ useSanityChecks: config2.useSanityChecks,
34765
+ skills: config2.activeSkills
34766
+ });
34651
34767
  const content = [tierPrompt, basePrompt].filter(Boolean).join("\n\n");
34652
34768
  const systemPrompt = {
34653
34769
  id: `system-${Date.now()}`,
@@ -34895,35 +35011,6 @@ var init_promptOrchestratorIntegration = __esm({
34895
35011
  message: `Prompt exceeds tier limit: ${totalTokens} > ${effectiveLimit} tokens. Tier ${tier} budget: ${tierBudget} tokens.`
34896
35012
  };
34897
35013
  }
34898
- /**
34899
- * Build base prompt with skills/tools/hooks
34900
- *
34901
- * @param config - System prompt configuration
34902
- * @returns Base prompt string
34903
- */
34904
- buildBasePrompt(config2) {
34905
- const parts = [];
34906
- if (config2.activeSkills.length > 0) {
34907
- parts.push(`Active Skills: ${config2.activeSkills.join(", ")}`);
34908
- }
34909
- let modelSupportsTools = false;
34910
- if (config2.modelId && this.profileManager) {
34911
- try {
34912
- const modelEntry = this.profileManager.getModelEntry(config2.modelId);
34913
- modelSupportsTools = modelEntry?.tool_support ?? false;
34914
- } catch (_error) {
34915
- modelSupportsTools = false;
34916
- }
34917
- }
34918
- if (modelSupportsTools && config2.allowedTools && config2.allowedTools.length > 0) {
34919
- parts.push(`Available Tools: ${config2.allowedTools.join(", ")}`);
34920
- }
34921
- parts.push("Hooks: Enabled");
34922
- if (config2.useSanityChecks) {
34923
- parts.push("Sanity Checks: Enabled");
34924
- }
34925
- return parts.join("\n\n");
34926
- }
34927
35014
  };
34928
35015
  }
34929
35016
  });
@@ -37534,7 +37621,17 @@ var init_SystemPromptBuilder = __esm({
37534
37621
  constructor(registry2) {
37535
37622
  this.registry = registry2;
37536
37623
  const moduleDir = path16.dirname(fileURLToPath(import.meta.url));
37537
- this.baseDir = path16.resolve(moduleDir, "../prompts/templates");
37624
+ const candidates = [
37625
+ // 1. Production bundle (CLI): ./templates (relative to cli.js in dist)
37626
+ path16.resolve(moduleDir, "templates"),
37627
+ // 2. Production package (Core): ../prompts/templates (relative to dist/context/SystemPromptBuilder.js)
37628
+ path16.resolve(moduleDir, "../prompts/templates"),
37629
+ // 3. Development/Source: ../prompts/templates (relative to src/context/SystemPromptBuilder.ts)
37630
+ path16.resolve(moduleDir, "../prompts/templates"),
37631
+ // 4. Monorepo fallback: resolve from CWD to core source
37632
+ path16.resolve(process.cwd(), "packages/core/src/prompts/templates")
37633
+ ];
37634
+ this.baseDir = candidates.find((dir) => fs18.existsSync(dir)) || candidates[0];
37538
37635
  }
37539
37636
  baseDir;
37540
37637
  /**
@@ -37565,6 +37662,12 @@ var init_SystemPromptBuilder = __esm({
37565
37662
  if (mandates) {
37566
37663
  sections2.push(mandates);
37567
37664
  }
37665
+ if (config2.useSanityChecks) {
37666
+ const sanity = this.loadTemplate("system/SanityChecks.txt");
37667
+ if (sanity) {
37668
+ sections2.push(sanity);
37669
+ }
37670
+ }
37568
37671
  if (config2.mode) {
37569
37672
  const skillsFile = `system/skills/Skills${this.capitalize(config2.mode)}.txt`;
37570
37673
  if (this.templateExists(skillsFile)) {
@@ -37580,12 +37683,6 @@ var init_SystemPromptBuilder = __esm({
37580
37683
  sections2.push(toolsSection);
37581
37684
  }
37582
37685
  }
37583
- if (config2.useSanityChecks) {
37584
- const sanity = this.loadTemplate("system/SanityChecks.txt");
37585
- if (sanity) {
37586
- sections2.push(sanity);
37587
- }
37588
- }
37589
37686
  if (config2.skills && config2.skills.length > 0) {
37590
37687
  const skillsContent = [];
37591
37688
  for (const skillId of config2.skills) {
@@ -37818,6 +37915,12 @@ var init_promptOrchestrator = __esm({
37818
37915
  this.promptStore = promptStore ?? _PromptOrchestrator.createPromptStore();
37819
37916
  this.systemPromptBuilder = new SystemPromptBuilder(this.promptRegistry);
37820
37917
  }
37918
+ /**
37919
+ * Build base prompt using SystemPromptBuilder
37920
+ */
37921
+ buildBasePrompt(config2) {
37922
+ return this.systemPromptBuilder.build(config2);
37923
+ }
37821
37924
  /**
37822
37925
  * Load the tiered prompt store with fallbacks (dist -> src) for dev flows.
37823
37926
  */
@@ -37914,8 +38017,8 @@ function createContextManager(config2) {
37914
38017
  try {
37915
38018
  const fs32 = await import("fs");
37916
38019
  const path34 = await import("path");
37917
- const os15 = await import("os");
37918
- const logPath = path34.join(os15.homedir(), ".ollm", "context-init-debug.log");
38020
+ const os16 = await import("os");
38021
+ const logPath = path34.join(os16.homedir(), ".ollm", "context-init-debug.log");
37919
38022
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
37920
38023
  const logMsg = `[${timestamp}] ${msg}
37921
38024
  `;
@@ -37954,14 +38057,24 @@ function createContextManager(config2) {
37954
38057
  log(`[ContextManagerFactory] Tier: ${tier}, Mode: ${mode}`);
37955
38058
  const promptOrchestrator = config2.services?.promptOrchestrator || createDefaultPromptOrchestrator(tokenCounter);
37956
38059
  const settingsService = config2.services?.settingsService;
38060
+ const modelSupportsTools = config2.modelInfo.tool_support ?? config2.modelInfo.capabilities?.tools ?? false;
38061
+ log(
38062
+ `[ContextManagerFactory] Model ${config2.modelInfo.modelId} supports tools: ${modelSupportsTools}`
38063
+ );
37957
38064
  let allowedTools;
37958
- if (settingsService && typeof settingsService.getToolsForMode === "function") {
37959
- try {
37960
- allowedTools = settingsService.getToolsForMode(mode);
37961
- } catch (error48) {
37962
- log(`[ContextManagerFactory] Failed to get tools for mode: ${error48}`);
38065
+ if (modelSupportsTools) {
38066
+ if (settingsService && typeof settingsService.getToolsForMode === "function") {
38067
+ try {
38068
+ allowedTools = settingsService.getToolsForMode(mode);
38069
+ } catch (error48) {
38070
+ log(`[ContextManagerFactory] Failed to get tools for mode: ${error48}`);
38071
+ }
37963
38072
  }
38073
+ } else {
38074
+ allowedTools = [];
38075
+ log("[ContextManagerFactory] Tools disabled because model does not support them");
37964
38076
  }
38077
+ const useSanityChecks = tier <= "8K" /* TIER_2_BASIC */;
37965
38078
  const promptIntegration = new PromptOrchestratorIntegration(
37966
38079
  promptOrchestrator,
37967
38080
  config2.services?.profileManager
@@ -37971,7 +38084,7 @@ function createContextManager(config2) {
37971
38084
  tier,
37972
38085
  activeSkills: [],
37973
38086
  // TODO: Get from config
37974
- useSanityChecks: false,
38087
+ useSanityChecks,
37975
38088
  modelId: config2.modelInfo.modelId,
37976
38089
  allowedTools
37977
38090
  });
@@ -39099,12 +39212,12 @@ var init_commands = __esm({
39099
39212
 
39100
39213
  // packages/core/src/mcp/mcpTransport.ts
39101
39214
  import { spawn as spawn3 } from "child_process";
39102
- var logger3, BaseMCPTransport, StdioTransport, SSETransport, HTTPTransport;
39215
+ var logger4, BaseMCPTransport, StdioTransport, SSETransport, HTTPTransport;
39103
39216
  var init_mcpTransport = __esm({
39104
39217
  "packages/core/src/mcp/mcpTransport.ts"() {
39105
39218
  "use strict";
39106
39219
  init_logger();
39107
- logger3 = createLogger("MCPTransport");
39220
+ logger4 = createLogger("MCPTransport");
39108
39221
  BaseMCPTransport = class {
39109
39222
  connected = false;
39110
39223
  isConnected() {
@@ -39174,7 +39287,7 @@ var init_mcpTransport = __esm({
39174
39287
  this.connected = true;
39175
39288
  resolve9();
39176
39289
  }).catch((error48) => {
39177
- logger3.warn("MCP Server initialize failed, assuming ready", {
39290
+ logger4.warn("MCP Server initialize failed, assuming ready", {
39178
39291
  command: this.command,
39179
39292
  error: error48.message
39180
39293
  });
@@ -39184,7 +39297,7 @@ var init_mcpTransport = __esm({
39184
39297
  });
39185
39298
  };
39186
39299
  this.process.on("error", (error48) => {
39187
- logger3.error("MCP Server process error", {
39300
+ logger4.error("MCP Server process error", {
39188
39301
  command: this.command,
39189
39302
  error: error48.message || String(error48)
39190
39303
  });
@@ -39200,7 +39313,7 @@ var init_mcpTransport = __esm({
39200
39313
  const sizeMB = (this.MAX_OUTPUT_SIZE / (1024 * 1024)).toFixed(1);
39201
39314
  const currentSizeMB = (this.outputSize / (1024 * 1024)).toFixed(1);
39202
39315
  const errorMsg = `MCP Server '${this.command}' exceeded output size limit: ${currentSizeMB}MB > ${sizeMB}MB. Consider implementing streaming or reducing output size.`;
39203
- logger3.error("MCP Server exceeded output size limit", {
39316
+ logger4.error("MCP Server exceeded output size limit", {
39204
39317
  command: this.command,
39205
39318
  currentSizeMB,
39206
39319
  limitSizeMB: sizeMB
@@ -39224,13 +39337,13 @@ var init_mcpTransport = __esm({
39224
39337
  });
39225
39338
  this.process.stderr?.on("data", (data) => {
39226
39339
  const stderrOutput = data.toString().trim();
39227
- logger3.error("MCP Server stderr output", {
39340
+ logger4.error("MCP Server stderr output", {
39228
39341
  command: this.command,
39229
39342
  stderr: stderrOutput
39230
39343
  });
39231
39344
  });
39232
39345
  this.process.on("exit", (code, signal) => {
39233
- logger3.info("MCP Server exited", {
39346
+ logger4.info("MCP Server exited", {
39234
39347
  command: this.command,
39235
39348
  code,
39236
39349
  signal
@@ -39362,7 +39475,7 @@ var init_mcpTransport = __esm({
39362
39475
  const jsonRpcResponse = JSON.parse(message);
39363
39476
  const id = jsonRpcResponse.id;
39364
39477
  if (typeof id !== "number") {
39365
- logger3.error("MCP Server received message without valid ID", {
39478
+ logger4.error("MCP Server received message without valid ID", {
39366
39479
  command: this.command,
39367
39480
  message: message.substring(0, 100)
39368
39481
  });
@@ -39370,7 +39483,7 @@ var init_mcpTransport = __esm({
39370
39483
  }
39371
39484
  const pending = this.pendingRequests.get(id);
39372
39485
  if (!pending) {
39373
- logger3.error("MCP Server received response for unknown request ID", {
39486
+ logger4.error("MCP Server received response for unknown request ID", {
39374
39487
  command: this.command,
39375
39488
  id
39376
39489
  });
@@ -39387,7 +39500,7 @@ var init_mcpTransport = __esm({
39387
39500
  };
39388
39501
  pending.resolve(response);
39389
39502
  } catch (error48) {
39390
- logger3.debug("Failed to parse JSON-RPC message", {
39503
+ logger4.debug("Failed to parse JSON-RPC message", {
39391
39504
  command: this.command,
39392
39505
  error: error48 instanceof Error ? error48.message : String(error48),
39393
39506
  message: message.substring(0, 100)
@@ -39459,7 +39572,7 @@ var init_mcpTransport = __esm({
39459
39572
  }
39460
39573
  } catch (error48) {
39461
39574
  if (error48 instanceof Error && error48.name !== "AbortError") {
39462
- logger3.error("SSE stream error", {
39575
+ logger4.error("SSE stream error", {
39463
39576
  url: this.url,
39464
39577
  error: error48.message
39465
39578
  });
@@ -39468,7 +39581,7 @@ var init_mcpTransport = __esm({
39468
39581
  }
39469
39582
  }).catch((error48) => {
39470
39583
  if (error48 instanceof Error && error48.name !== "AbortError") {
39471
- logger3.error("SSE connection error", {
39584
+ logger4.error("SSE connection error", {
39472
39585
  url: this.url,
39473
39586
  error: error48.message
39474
39587
  });
@@ -39572,7 +39685,7 @@ var init_mcpTransport = __esm({
39572
39685
  const jsonRpcResponse = JSON.parse(message);
39573
39686
  const id = jsonRpcResponse.id;
39574
39687
  if (typeof id !== "number") {
39575
- logger3.error("SSE received message without valid ID", {
39688
+ logger4.error("SSE received message without valid ID", {
39576
39689
  url: this.url,
39577
39690
  message: message.substring(0, 100)
39578
39691
  });
@@ -39580,7 +39693,7 @@ var init_mcpTransport = __esm({
39580
39693
  }
39581
39694
  const pending = this.pendingRequests.get(id);
39582
39695
  if (!pending) {
39583
- logger3.error("SSE received response for unknown request ID", {
39696
+ logger4.error("SSE received response for unknown request ID", {
39584
39697
  url: this.url,
39585
39698
  id
39586
39699
  });
@@ -39598,7 +39711,7 @@ var init_mcpTransport = __esm({
39598
39711
  pending.resolve(response);
39599
39712
  } catch (error48) {
39600
39713
  const errorMessage = error48 instanceof Error ? error48.message : String(error48);
39601
- logger3.error("SSE failed to parse JSON-RPC message", {
39714
+ logger4.error("SSE failed to parse JSON-RPC message", {
39602
39715
  error: errorMessage,
39603
39716
  message: message.substring(0, 100)
39604
39717
  });
@@ -42120,17 +42233,25 @@ var init_PromptModeManager = __esm({
42120
42233
  "developer->planning": 0.6,
42121
42234
  // Easier to step back
42122
42235
  "developer->debugger": 0.85,
42123
- "debugger->developer": 0.7,
42124
- // Tool mode
42125
- "any->tool": 0.9,
42126
- // Default threshold
42127
- default: 0.7
42236
+ // Defaults
42237
+ any: 0.5,
42238
+ default: 0.5
42128
42239
  };
42129
42240
  PromptModeManager = class extends EventEmitter6 {
42130
- // 30 seconds (increased from 10s)
42241
+ contextAnalyzer;
42242
+ minDuration;
42243
+ cooldownPeriod;
42244
+ metricsTracker;
42245
+ focusModeManager;
42246
+ animator;
42247
+ state;
42248
+ modeHistory = [];
42249
+ maxHistorySize = 100;
42131
42250
  constructor(contextAnalyzer, config2 = {}) {
42132
42251
  super();
42133
42252
  this.contextAnalyzer = contextAnalyzer;
42253
+ this.minDuration = config2.minDuration ?? 15e3;
42254
+ this.cooldownPeriod = config2.cooldownPeriod ?? 1e4;
42134
42255
  if (config2.enableMetrics) {
42135
42256
  this.metricsTracker = new ModeMetricsTracker();
42136
42257
  this.loadMetrics();
@@ -42138,27 +42259,15 @@ var init_PromptModeManager = __esm({
42138
42259
  this.focusModeManager = new FocusModeManager();
42139
42260
  this.animator = new ModeTransitionAnimator();
42140
42261
  this.state = {
42141
- currentMode: "assistant",
42262
+ currentMode: config2.mode ?? "assistant",
42142
42263
  previousMode: null,
42143
42264
  autoSwitchEnabled: false,
42144
- // DISABLED: Prevent mid-response mode switching
42145
42265
  lastSwitchTime: /* @__PURE__ */ new Date(),
42146
42266
  modeEntryTime: /* @__PURE__ */ new Date(),
42147
42267
  activeSkills: []
42148
42268
  };
42149
- this.metricsTracker?.trackModeEntry("assistant");
42269
+ this.metricsTracker?.trackModeEntry(this.state.currentMode);
42150
42270
  }
42151
- state;
42152
- modeHistory = [];
42153
- maxHistorySize = 100;
42154
- metricsTracker;
42155
- // Optional: only created if enabled
42156
- focusModeManager;
42157
- animator;
42158
- // Timing configuration
42159
- minDuration = 6e4;
42160
- // 60 seconds (increased from 15s to prevent rapid switching)
42161
- cooldownPeriod = 3e4;
42162
42271
  /**
42163
42272
  * Get current mode
42164
42273
  */
@@ -42423,6 +42532,7 @@ var init_PromptModeManager = __esm({
42423
42532
  getAllowedTools(mode) {
42424
42533
  const toolAccess = {
42425
42534
  assistant: [],
42535
+ // Pure chat mode by default - prevents tool overuse
42426
42536
  planning: [],
42427
42537
  developer: [],
42428
42538
  debugger: [],
@@ -43403,7 +43513,7 @@ function isToolUnsupportedError(errorText) {
43403
43513
  ];
43404
43514
  const matched = patterns.some((pattern) => pattern.test(errorText));
43405
43515
  if (matched) {
43406
- logger4.debug("Tool unsupported error detected", {
43516
+ logger5.debug("Tool unsupported error detected", {
43407
43517
  errorText: errorText.substring(0, 100)
43408
43518
  });
43409
43519
  }
@@ -43413,12 +43523,11 @@ function formatHttpError(status, statusText, details) {
43413
43523
  const trimmed = details.trim();
43414
43524
  return trimmed.length > 0 ? `HTTP ${status}: ${statusText} - ${trimmed}` : `HTTP ${status}: ${statusText}`;
43415
43525
  }
43416
- var TOKEN_MULTIPLIERS, logger4, LocalProvider;
43526
+ var TOKEN_MULTIPLIERS, logger5, LocalProvider;
43417
43527
  var init_localProvider = __esm({
43418
43528
  "packages/ollm-bridge/src/provider/localProvider.ts"() {
43419
43529
  "use strict";
43420
43530
  init_src();
43421
- init_gpuHints();
43422
43531
  TOKEN_MULTIPLIERS = {
43423
43532
  llama: 0.25,
43424
43533
  // ~4 chars per token
@@ -43435,7 +43544,7 @@ var init_localProvider = __esm({
43435
43544
  default: 0.25
43436
43545
  // Conservative default
43437
43546
  };
43438
- logger4 = createLogger("LocalProvider");
43547
+ logger5 = createLogger("LocalProvider");
43439
43548
  LocalProvider = class {
43440
43549
  constructor(config2) {
43441
43550
  this.config = config2;
@@ -43463,7 +43572,7 @@ var init_localProvider = __esm({
43463
43572
  return deriveGPUPlacementHints(source, numCtx);
43464
43573
  } catch (error48) {
43465
43574
  const message = error48 instanceof Error ? error48.message : String(error48);
43466
- logger4.debug("Failed to derive GPU placement hints", { error: message });
43575
+ logger5.debug("Failed to derive GPU placement hints", { error: message });
43467
43576
  return void 0;
43468
43577
  }
43469
43578
  }
@@ -43516,6 +43625,11 @@ var init_localProvider = __esm({
43516
43625
  optionsPayload[key] = value;
43517
43626
  }
43518
43627
  }
43628
+ if (optionsPayload.maxTokens !== void 0) {
43629
+ const v = optionsPayload.maxTokens;
43630
+ optionsPayload.max_new_tokens = v;
43631
+ optionsPayload.max_tokens = v;
43632
+ }
43519
43633
  if ("gpu_layers" in optionsPayload) {
43520
43634
  delete optionsPayload.gpu_layers;
43521
43635
  }
@@ -43545,15 +43659,16 @@ var init_localProvider = __esm({
43545
43659
  think: request.think
43546
43660
  // Pass thinking parameter to Ollama
43547
43661
  };
43662
+ logger5.debug("Ollama request payload options", { options: optionsPayload });
43548
43663
  if (body.tools && Array.isArray(body.tools) && body.tools.length > 0) {
43549
- logger4.info("Sending tools to Ollama", {
43664
+ logger5.info("Sending tools to Ollama", {
43550
43665
  model: request.model,
43551
43666
  toolCount: body.tools.length,
43552
43667
  toolNames: body.tools.map((t) => t.function?.name).filter(Boolean)
43553
43668
  });
43554
43669
  }
43555
43670
  if (request.options?.num_ctx) {
43556
- logger4.debug("Sending context window configuration to Ollama", {
43671
+ logger5.debug("Sending context window configuration to Ollama", {
43557
43672
  model: request.model,
43558
43673
  num_ctx: request.options.num_ctx
43559
43674
  });
@@ -43600,7 +43715,7 @@ var init_localProvider = __esm({
43600
43715
  const looksLikeToolError = response.status === 400 && payloadHasTools(body) && isToolUnsupportedError(errorText);
43601
43716
  if (looksLikeToolError) {
43602
43717
  const details = errorText.trim();
43603
- logger4.info("Tool unsupported error, retrying without tools", {
43718
+ logger5.info("Tool unsupported error, retrying without tools", {
43604
43719
  model: request.model,
43605
43720
  error: details.substring(0, 200)
43606
43721
  });
@@ -43622,7 +43737,7 @@ var init_localProvider = __esm({
43622
43737
  if (!response.ok) {
43623
43738
  if (timeoutId) clearTimeout(timeoutId);
43624
43739
  const details = errorText.trim();
43625
- logger4.error("HTTP error from Ollama", {
43740
+ logger5.error("HTTP error from Ollama", {
43626
43741
  status: response.status,
43627
43742
  statusText: response.statusText,
43628
43743
  error: details.substring(0, 200)
@@ -43664,7 +43779,7 @@ var init_localProvider = __esm({
43664
43779
  }
43665
43780
  yield* this.mapChunkToEvents(chunk);
43666
43781
  } catch (error48) {
43667
- logger4.debug("Malformed JSON in stream", {
43782
+ logger5.debug("Malformed JSON in stream", {
43668
43783
  line: line.substring(0, 100),
43669
43784
  // First 100 chars
43670
43785
  error: error48 instanceof Error ? error48.message : String(error48)
@@ -43681,7 +43796,7 @@ var init_localProvider = __esm({
43681
43796
  }
43682
43797
  yield* this.mapChunkToEvents(chunk);
43683
43798
  } catch (error48) {
43684
- logger4.debug("Malformed JSON in trailing buffer", {
43799
+ logger5.debug("Malformed JSON in trailing buffer", {
43685
43800
  buffer: trailing.substring(0, 100),
43686
43801
  error: error48 instanceof Error ? error48.message : String(error48)
43687
43802
  });
@@ -44077,7 +44192,7 @@ var init_localProvider = __esm({
44077
44192
  const modelLower = model.toLowerCase();
44078
44193
  for (const [family, multiplier] of Object.entries(TOKEN_MULTIPLIERS)) {
44079
44194
  if (modelLower.includes(family)) {
44080
- logger4.debug("Using token multiplier for model family", {
44195
+ logger5.debug("Using token multiplier for model family", {
44081
44196
  model,
44082
44197
  family,
44083
44198
  multiplier
@@ -44085,7 +44200,7 @@ var init_localProvider = __esm({
44085
44200
  return multiplier;
44086
44201
  }
44087
44202
  }
44088
- logger4.debug("Using default token multiplier", { model });
44203
+ logger5.debug("Using default token multiplier", { model });
44089
44204
  return TOKEN_MULTIPLIERS.default;
44090
44205
  }
44091
44206
  /**
@@ -44117,13 +44232,13 @@ var init_localProvider = __esm({
44117
44232
  }
44118
44233
  }
44119
44234
  encoding.free();
44120
- logger4.debug("Token count (tiktoken)", {
44235
+ logger5.debug("Token count (tiktoken)", {
44121
44236
  model: request.model,
44122
44237
  tokens: totalTokens
44123
44238
  });
44124
44239
  return totalTokens;
44125
44240
  } catch (error48) {
44126
- logger4.warn("Tiktoken failed, falling back to multiplier method", {
44241
+ logger5.warn("Tiktoken failed, falling back to multiplier method", {
44127
44242
  error: error48 instanceof Error ? error48.message : String(error48)
44128
44243
  });
44129
44244
  return this.countTokensWithMultiplier(request);
@@ -44155,7 +44270,7 @@ var init_localProvider = __esm({
44155
44270
  }
44156
44271
  const multiplier = this.getTokenMultiplier(request.model);
44157
44272
  const tokens = Math.ceil(totalChars * multiplier);
44158
- logger4.debug("Token count (multiplier)", {
44273
+ logger5.debug("Token count (multiplier)", {
44159
44274
  model: request.model,
44160
44275
  chars: totalChars,
44161
44276
  multiplier,
@@ -44616,10 +44731,17 @@ __export(settingsService_exports, {
44616
44731
  import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync7, mkdirSync as mkdirSync5 } from "fs";
44617
44732
  import { homedir as homedir15 } from "os";
44618
44733
  import { join as join26 } from "path";
44619
- var DEFAULT_TOOLS_BY_MODE, SettingsService;
44734
+ var GLOBALLY_DISABLED_TOOLS, DEFAULT_TOOLS_BY_MODE, SettingsService;
44620
44735
  var init_settingsService = __esm({
44621
44736
  "packages/cli/src/config/settingsService.ts"() {
44622
44737
  "use strict";
44738
+ GLOBALLY_DISABLED_TOOLS = [
44739
+ "create_goal",
44740
+ "create_checkpoint",
44741
+ "complete_goal",
44742
+ "record_decision",
44743
+ "switch_goal"
44744
+ ];
44623
44745
  DEFAULT_TOOLS_BY_MODE = {
44624
44746
  developer: [],
44625
44747
  debugger: [],
@@ -44816,10 +44938,18 @@ var init_settingsService = __esm({
44816
44938
  /**
44817
44939
  * Get the enabled state of a tool
44818
44940
  *
44941
+ * NOTE: Goal management tools (create_goal, create_checkpoint, complete_goal,
44942
+ * record_decision, switch_goal) are GLOBALLY DISABLED and marked as
44943
+ * "Under Development". They cannot be enabled through settings because they
44944
+ * cause LLMs to call tools unnecessarily, even for simple greetings like "hi".
44945
+ *
44819
44946
  * @param toolId The ID of the tool to check
44820
44947
  * @returns true if enabled (default), false if disabled
44821
44948
  */
44822
44949
  getToolState(toolId) {
44950
+ if (GLOBALLY_DISABLED_TOOLS.includes(toolId)) {
44951
+ return false;
44952
+ }
44823
44953
  if (!this.settings.tools) {
44824
44954
  return true;
44825
44955
  }
@@ -45900,8 +46030,8 @@ function ContextManagerProvider({
45900
46030
  const initManager = async () => {
45901
46031
  const fs32 = await import("fs");
45902
46032
  const path34 = await import("path");
45903
- const os15 = await import("os");
45904
- const logPath = path34.join(os15.homedir(), ".ollm", "context-init-debug.log");
46033
+ const os16 = await import("os");
46034
+ const logPath = path34.join(os16.homedir(), ".ollm", "context-init-debug.log");
45905
46035
  const log = (msg) => {
45906
46036
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
45907
46037
  const logMsg = `[${timestamp}] ${msg}
@@ -45916,67 +46046,6 @@ function ContextManagerProvider({
45916
46046
  log(`[ContextManagerContext] Provider available: ${!!provider}`);
45917
46047
  log(`[ContextManagerContext] Session ID: ${sessionId}`);
45918
46048
  log(`[ContextManagerContext] Model ID: ${modelInfo?.modelId}`);
45919
- let effectiveConfig = config2;
45920
- try {
45921
- const { getSessionManager: getSessionManager2 } = await Promise.resolve().then(() => (init_SessionManager(), SessionManager_exports));
45922
- const sessionManager = getSessionManager2();
45923
- const pendingSize = sessionManager.getPendingContextSize();
45924
- if (pendingSize !== null) {
45925
- log(`[ContextManagerContext] Using pending context size: ${pendingSize}`);
45926
- let ollamaContextSize = Math.floor(pendingSize * 0.85);
45927
- try {
45928
- const { profileManager: profileManager2 } = await Promise.resolve().then(() => (init_ProfileManager(), ProfileManager_exports));
45929
- const modelEntry = profileManager2.getModelEntry(modelInfo?.modelId || "");
45930
- const contextProfile = modelEntry.context_profiles?.find(
45931
- (p) => p.size === pendingSize
45932
- );
45933
- if (contextProfile?.ollama_context_size) {
45934
- ollamaContextSize = contextProfile.ollama_context_size;
45935
- log(
45936
- `[ContextManagerContext] Using ollama_context_size from profile: ${ollamaContextSize}`
45937
- );
45938
- }
45939
- } catch (error49) {
45940
- log(`[ContextManagerContext] Failed to get ollama_context_size: ${error49}`);
45941
- }
45942
- effectiveConfig = {
45943
- ...config2,
45944
- targetSize: pendingSize,
45945
- ollamaContextSize,
45946
- autoSize: false
45947
- };
45948
- } else {
45949
- const userContextSize = config2?.targetSize || 8192;
45950
- let ollamaContextSize = Math.floor(userContextSize * 0.85);
45951
- try {
45952
- const { profileManager: profileManager2 } = await Promise.resolve().then(() => (init_ProfileManager(), ProfileManager_exports));
45953
- const modelEntry = profileManager2.getModelEntry(modelInfo?.modelId || "");
45954
- const contextProfile = modelEntry.context_profiles?.find(
45955
- (p) => p.size === userContextSize
45956
- );
45957
- if (contextProfile?.ollama_context_size) {
45958
- ollamaContextSize = contextProfile.ollama_context_size;
45959
- log(
45960
- `[ContextManagerContext] Using ollama_context_size from profile: ${ollamaContextSize} for context ${userContextSize}`
45961
- );
45962
- } else {
45963
- log(
45964
- `[ContextManagerContext] No profile found for ${userContextSize}, using 85% fallback: ${ollamaContextSize}`
45965
- );
45966
- }
45967
- } catch (error49) {
45968
- log(`[ContextManagerContext] Failed to get ollama_context_size: ${error49}`);
45969
- }
45970
- effectiveConfig = {
45971
- ...config2,
45972
- targetSize: userContextSize,
45973
- ollamaContextSize
45974
- };
45975
- }
45976
- } catch (error49) {
45977
- log(`[ContextManagerContext] Failed to check pending context size: ${error49}`);
45978
- }
45979
- const storagePath = path34.join(os15.homedir(), ".ollm", "context-storage");
45980
46049
  if (!provider) {
45981
46050
  log(
45982
46051
  "[ContextManagerContext] ERROR: Provider not available - cannot initialize context manager"
@@ -45985,19 +46054,20 @@ function ContextManagerProvider({
45985
46054
  setActive(false);
45986
46055
  return;
45987
46056
  }
46057
+ const storagePath = path34.join(os16.homedir(), ".ollm", "context-storage");
45988
46058
  log("[ContextManagerContext] Creating context manager with factory...");
45989
46059
  log(`[ContextManagerContext] Model info: ${JSON.stringify(modelInfo)}`);
45990
- log(`[ContextManagerContext] Effective config: ${JSON.stringify(effectiveConfig)}`);
45991
- const savedMode = SettingsService.getInstance().getMode() || "developer";
46060
+ const savedMode = SettingsService.getInstance().getMode() || "assistant";
45992
46061
  log(`[ContextManagerContext] Using mode: ${savedMode}`);
45993
46062
  const { manager } = createContextManager({
45994
46063
  sessionId,
45995
46064
  modelInfo: {
45996
46065
  ...modelInfo,
45997
- contextSize: effectiveConfig?.targetSize
46066
+ // If targetSize is provided in config, use it. Otherwise factory defaults to 8192
46067
+ contextSize: config2?.targetSize
45998
46068
  },
45999
46069
  contextConfig: {
46000
- ...effectiveConfig,
46070
+ ...config2,
46001
46071
  mode: savedMode
46002
46072
  // Pass mode to factory
46003
46073
  },
@@ -46017,7 +46087,7 @@ function ContextManagerProvider({
46017
46087
  workflowManagerRef.current = workflowManager;
46018
46088
  const promptsSnapshotManager = new SnapshotManager({
46019
46089
  sessionId,
46020
- storagePath: path34.join(os15.homedir(), ".ollm", "mode-transition-snapshots"),
46090
+ storagePath: path34.join(os16.homedir(), ".ollm", "mode-transition-snapshots"),
46021
46091
  maxCacheSize: 20,
46022
46092
  pruneAfterMs: 72e5
46023
46093
  // 2 hours
@@ -46173,7 +46243,7 @@ function ContextManagerProvider({
46173
46243
  }
46174
46244
  modeChangeCallbackRef.current = null;
46175
46245
  };
46176
- }, [sessionId, modelInfo, config2]);
46246
+ }, [sessionId, modelInfo, config2, provider]);
46177
46247
  useEffect(() => {
46178
46248
  if (!active || !managerRef.current) return;
46179
46249
  const updateUsage = () => {
@@ -46340,6 +46410,7 @@ function ContextManagerProvider({
46340
46410
  },
46341
46411
  [modelInfo]
46342
46412
  );
46413
+ const promptRegistryRef = useRef(null);
46343
46414
  const hotSwap = useCallback(
46344
46415
  async (newSkills) => {
46345
46416
  if (!managerRef.current) return;
@@ -46348,10 +46419,12 @@ function ContextManagerProvider({
46348
46419
  return;
46349
46420
  }
46350
46421
  try {
46351
- const promptRegistry = new PromptRegistry();
46422
+ if (!promptRegistryRef.current) {
46423
+ promptRegistryRef.current = new PromptRegistry();
46424
+ }
46352
46425
  const hotSwapService = new HotSwapService(
46353
46426
  managerRef.current,
46354
- promptRegistry,
46427
+ promptRegistryRef.current,
46355
46428
  provider,
46356
46429
  modelId,
46357
46430
  modeManagerRef.current || void 0,
@@ -52481,25 +52554,25 @@ function UICallbacksProvider({ children, callbacks }) {
52481
52554
  function useUICallbacks() {
52482
52555
  return useContext4(UICallbacksContext);
52483
52556
  }
52484
- var logger5, defaultCallbacks, UICallbacksContext;
52557
+ var logger6, defaultCallbacks, UICallbacksContext;
52485
52558
  var init_UICallbacksContext = __esm({
52486
52559
  "packages/cli/src/ui/contexts/UICallbacksContext.tsx"() {
52487
52560
  "use strict";
52488
52561
  init_logger();
52489
- logger5 = createLogger("UICallbacksContext");
52562
+ logger6 = createLogger("UICallbacksContext");
52490
52563
  defaultCallbacks = {
52491
52564
  promptUser: async (message, options) => {
52492
- logger5.warn("[UICallbacks] promptUser called but no callback registered:", message);
52565
+ logger6.warn("[UICallbacks] promptUser called but no callback registered:", message);
52493
52566
  return options[options.length - 1];
52494
52567
  },
52495
52568
  addSystemMessage: (message) => {
52496
- logger5.warn("[UICallbacks] addSystemMessage called but no callback registered:", message);
52569
+ logger6.warn("[UICallbacks] addSystemMessage called but no callback registered:", message);
52497
52570
  },
52498
52571
  clearContext: () => {
52499
- logger5.warn("[UICallbacks] clearContext called but no callback registered");
52572
+ logger6.warn("[UICallbacks] clearContext called but no callback registered");
52500
52573
  },
52501
52574
  openModelMenu: () => {
52502
- logger5.warn("[UICallbacks] openModelMenu called but no callback registered");
52575
+ logger6.warn("[UICallbacks] openModelMenu called but no callback registered");
52503
52576
  }
52504
52577
  };
52505
52578
  UICallbacksContext = createContext4(defaultCallbacks);
@@ -52854,8 +52927,13 @@ function useToolSupport(provider, promptUser, addSystemMessage) {
52854
52927
  return override;
52855
52928
  }
52856
52929
  const profile = profileManager.findProfile(model);
52857
- if (profile && profile.tool_support === false) return false;
52858
- return true;
52930
+ if (profile && typeof profile.tool_support === "boolean") {
52931
+ return profile.tool_support;
52932
+ }
52933
+ if (profile && profile.capabilities?.tools === true) {
52934
+ return true;
52935
+ }
52936
+ return false;
52859
52937
  },
52860
52938
  [getToolSupportOverride]
52861
52939
  );
@@ -53620,42 +53698,11 @@ var init_promptUtils = __esm({
53620
53698
 
53621
53699
  // packages/cli/src/features/context/utils/systemPromptBuilder.ts
53622
53700
  function buildSystemPrompt(options) {
53623
- const { basePrompt, tierPrompt, modelProfile, supportsTools, injectFocusedFiles: injectFocusedFiles2 } = options;
53701
+ const { basePrompt, tierPrompt, supportsTools, injectFocusedFiles: injectFocusedFiles2 } = options;
53624
53702
  let systemPrompt = basePrompt;
53625
- const isReasoningModel = modelProfile?.thinking_enabled === true;
53626
- if (isReasoningModel) {
53627
- systemPrompt = `You are a helpful AI assistant for developers. You help with coding, debugging, and technical questions.
53628
-
53629
- Key guidelines:
53630
- - Provide accurate, clear information
53631
- - Explain concepts simply and directly
53632
- - Use code examples when helpful
53633
- - Follow project conventions when working with code
53634
- - Ask for clarification if the request is unclear
53635
- ${supportsTools ? `
53636
- IMPORTANT - Web Search Behavior:
53637
- - When you use web_search, it returns URLs and titles - SHARE THOSE DIRECTLY with the user
53638
- - DO NOT try to fetch or scrape the URLs unless the user explicitly asks you to read a specific page
53639
- - DO NOT make up information - if web_search returns no results, say "I couldn't find information about that"
53640
- - The search results ARE the answer - don't overthink it` : ""}
53641
-
53642
- Focus your thinking on the user's actual question, not on these instructions.`;
53643
- } else {
53644
- if (!supportsTools) {
53645
- systemPrompt += "\n\nNote: This model does not support function calling. Do not attempt to use tools or make tool calls.";
53646
- } else {
53647
- systemPrompt += `
53648
-
53649
- IMPORTANT - Web Search Behavior:
53650
- - When you use web_search, it returns URLs and titles - SHARE THOSE DIRECTLY with the user
53651
- - DO NOT try to fetch or scrape the URLs unless the user explicitly asks you to read a specific page
53652
- - DO NOT make up information - if web_search returns no results, say "I couldn't find information about that"
53653
- - The search results ARE the answer - don't overthink it`;
53654
- }
53655
- const toolNote = supportsTools ? "" : "Note: This model does not support function calling. Do not attempt to use tools or make tool calls.";
53656
- const rulesOnly = stripSection2(stripSection2(systemPrompt, tierPrompt), toolNote);
53657
- systemPrompt = [tierPrompt, rulesOnly, toolNote].filter(Boolean).join("\n\n");
53658
- }
53703
+ const toolNote = supportsTools ? "" : "Note: This model does not support function calling. Do not attempt to use tools or make tool calls.";
53704
+ const rulesOnly = stripSection2(stripSection2(systemPrompt, tierPrompt), toolNote);
53705
+ systemPrompt = [tierPrompt, rulesOnly, toolNote].filter(Boolean).join("\n\n");
53659
53706
  systemPrompt = injectFocusedFiles2(systemPrompt);
53660
53707
  return systemPrompt;
53661
53708
  }
@@ -56831,7 +56878,7 @@ function MCPProvider({
56831
56878
  try {
56832
56879
  await mcpClient.startServer(serverName, serverConfig);
56833
56880
  } catch (error48) {
56834
- logger6.warn(`Failed to start server ${serverName}:`, error48);
56881
+ logger7.warn(`Failed to start server ${serverName}:`, error48);
56835
56882
  }
56836
56883
  }
56837
56884
  }
@@ -56885,7 +56932,7 @@ function MCPProvider({
56885
56932
  { maxAttempts: 3, initialDelay: 500 }
56886
56933
  );
56887
56934
  } catch (err) {
56888
- logger6.warn(`Failed to get tools for ${serverName} after retries:`, err);
56935
+ logger7.warn(`Failed to get tools for ${serverName} after retries:`, err);
56889
56936
  if (serverConfig) {
56890
56937
  const errorMsg = err instanceof Error ? err.message : String(err);
56891
56938
  if (!errorMsg.includes("no tools") && !errorMsg.includes("not implemented") && !errorMsg.includes("Method not found") && !errorMsg.includes("tools/list")) {
@@ -56898,7 +56945,7 @@ function MCPProvider({
56898
56945
  }
56899
56946
  }
56900
56947
  } catch (error48) {
56901
- logger6.warn(`Failed to get tools for ${serverName}:`, error48);
56948
+ logger7.warn(`Failed to get tools for ${serverName}:`, error48);
56902
56949
  }
56903
56950
  const prevTools = lastRegisteredTools.current.get(serverName);
56904
56951
  if (prevTools) {
@@ -56915,7 +56962,7 @@ function MCPProvider({
56915
56962
  try {
56916
56963
  oauthStatus = await oauthProvider.getOAuthStatus(serverName);
56917
56964
  } catch (error48) {
56918
- logger6.warn(`Failed to get OAuth status for ${serverName}:`, error48);
56965
+ logger7.warn(`Failed to get OAuth status for ${serverName}:`, error48);
56919
56966
  }
56920
56967
  }
56921
56968
  const statusRecord = status;
@@ -56951,7 +56998,7 @@ function MCPProvider({
56951
56998
  marketplace: servers
56952
56999
  }));
56953
57000
  } catch (error48) {
56954
- logger6.warn("Failed to load marketplace:", error48);
57001
+ logger7.warn("Failed to load marketplace:", error48);
56955
57002
  }
56956
57003
  }, []);
56957
57004
  const toggleServer = useCallback13(
@@ -57126,7 +57173,7 @@ function MCPProvider({
57126
57173
  try {
57127
57174
  await oauthProvider.revokeAccess(serverName, server.config.oauth);
57128
57175
  } catch (error48) {
57129
- logger6.warn(`Failed to revoke OAuth for ${serverName}:`, error48);
57176
+ logger7.warn(`Failed to revoke OAuth for ${serverName}:`, error48);
57130
57177
  }
57131
57178
  }
57132
57179
  await loadServers();
@@ -57275,7 +57322,7 @@ function MCPProvider({
57275
57322
  try {
57276
57323
  return await mcpMarketplace.searchServers(query);
57277
57324
  } catch (error48) {
57278
- logger6.warn("Failed to search marketplace:", error48);
57325
+ logger7.warn("Failed to search marketplace:", error48);
57279
57326
  return [];
57280
57327
  }
57281
57328
  }, []);
@@ -57284,7 +57331,7 @@ function MCPProvider({
57284
57331
  await mcpMarketplace.refreshCache();
57285
57332
  await loadMarketplace();
57286
57333
  } catch (error48) {
57287
- logger6.warn("Failed to refresh marketplace:", error48);
57334
+ logger7.warn("Failed to refresh marketplace:", error48);
57288
57335
  }
57289
57336
  }, [loadMarketplace]);
57290
57337
  const getServerLogs = useCallback13(
@@ -57292,14 +57339,14 @@ function MCPProvider({
57292
57339
  try {
57293
57340
  return await mcpClient.getServerLogs(serverName, lines);
57294
57341
  } catch (error48) {
57295
- logger6.error(`Failed to get logs for ${serverName}:`, error48);
57342
+ logger7.error(`Failed to get logs for ${serverName}:`, error48);
57296
57343
  return [];
57297
57344
  }
57298
57345
  },
57299
57346
  [mcpClient]
57300
57347
  );
57301
57348
  const clearServerLogs = useCallback13(async (serverName) => {
57302
- logger6.warn(`Clear logs not yet implemented for ${serverName}`);
57349
+ logger7.warn(`Clear logs not yet implemented for ${serverName}`);
57303
57350
  }, []);
57304
57351
  const refreshServers = useCallback13(async () => {
57305
57352
  setState((prev) => ({ ...prev, isLoading: true }));
@@ -57377,7 +57424,7 @@ function MCPProvider({
57377
57424
  };
57378
57425
  return /* @__PURE__ */ jsx14(MCPContext.Provider, { value, children });
57379
57426
  }
57380
- var logger6, MCPContext;
57427
+ var logger7, MCPContext;
57381
57428
  var init_MCPContext = __esm({
57382
57429
  "packages/cli/src/ui/contexts/MCPContext.tsx"() {
57383
57430
  "use strict";
@@ -57392,7 +57439,7 @@ var init_MCPContext = __esm({
57392
57439
  init_mcpConfigService();
57393
57440
  init_mcpMarketplace();
57394
57441
  init_errorHandling();
57395
- logger6 = createLogger("MCPContext");
57442
+ logger7 = createLogger("MCPContext");
57396
57443
  MCPContext = createContext12(void 0);
57397
57444
  }
57398
57445
  });
@@ -63561,7 +63608,7 @@ var init_VersionBanner = __esm({
63561
63608
  return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", alignItems: "center", children: [
63562
63609
  /* @__PURE__ */ jsx39(Box18, { flexDirection: "column", alignItems: "center", children: WELCOME_ASCII_LINES.map((line, idx) => /* @__PURE__ */ jsx39(Box18, { children: /* @__PURE__ */ jsx39(ColoredLine, { line }) }, idx)) }),
63563
63610
  /* @__PURE__ */ jsxs18(Box18, { marginTop: 2, flexDirection: "column", alignItems: "center", children: [
63564
- /* @__PURE__ */ jsx39(Text19, { bold: true, color: theme.text.accent, children: "OLLM CLI v0.1.0 alpha" }),
63611
+ /* @__PURE__ */ jsx39(Text19, { bold: true, color: theme.text.accent, children: "OLLM CLI v0.1.4b alpha" }),
63565
63612
  /* @__PURE__ */ jsx39(Text19, { color: theme.text.accent, dimColor: true, children: "Press any key to continue" })
63566
63613
  ] }),
63567
63614
  (modelInfo || gpuInfo) && /* @__PURE__ */ jsxs18(Box18, { marginTop: 1, flexDirection: "column", alignItems: "center", children: [
@@ -69721,7 +69768,7 @@ function TerminalProvider({ children }) {
69721
69768
  const cursorY = buffer.baseY + (buffer.cursorY ?? 0);
69722
69769
  const baseY = buffer.baseY ?? 0;
69723
69770
  const viewportYraw = buffer.viewportY ?? startIndex;
69724
- logger7.debug(
69771
+ logger8.debug(
69725
69772
  "PTY data len=%d, cols=%d, viewportY=%d, baseY=%d, cursor=(%d,%d), totalLines=%d, startIndex=%d, firstLen=%d, lastLen=%d",
69726
69773
  data.length,
69727
69774
  xterm.cols,
@@ -69734,14 +69781,14 @@ function TerminalProvider({ children }) {
69734
69781
  firstText.length,
69735
69782
  lastText.length
69736
69783
  );
69737
- logger7.debug("firstLinePreview=%s", firstText.slice(0, 80));
69738
- logger7.debug("lastLinePreview=%s", lastText.slice(0, 160));
69784
+ logger8.debug("firstLinePreview=%s", firstText.slice(0, 80));
69785
+ logger8.debug("lastLinePreview=%s", lastText.slice(0, 160));
69739
69786
  } catch (_e) {
69740
69787
  }
69741
69788
  setOutput(serialized);
69742
69789
  });
69743
69790
  } catch (err) {
69744
- logger7.error("Terminal data processing error:", err);
69791
+ logger8.error("Terminal data processing error:", err);
69745
69792
  }
69746
69793
  });
69747
69794
  const exitDisposable = ptyProcess.onExit(() => {
@@ -69762,13 +69809,13 @@ function TerminalProvider({ children }) {
69762
69809
  try {
69763
69810
  ptyProcessRef.current.kill();
69764
69811
  } catch (error48) {
69765
- logger7.warn("Failed to kill PTY process:", error48);
69812
+ logger8.warn("Failed to kill PTY process:", error48);
69766
69813
  }
69767
69814
  }
69768
69815
  ptyProcessRef.current = null;
69769
69816
  };
69770
69817
  } catch (error48) {
69771
- logger7.error("Failed to spawn terminal:", error48);
69818
+ logger8.error("Failed to spawn terminal:", error48);
69772
69819
  setIsRunning(false);
69773
69820
  return () => {
69774
69821
  };
@@ -69787,7 +69834,7 @@ function TerminalProvider({ children }) {
69787
69834
  if (ptyProcessRef.current && isRunning) {
69788
69835
  try {
69789
69836
  const codes = Array.from(char).map((c) => c.charCodeAt(0)).join(",");
69790
- logger7.debug(
69837
+ logger8.debug(
69791
69838
  "sendRawInput: len=%d, text=%s, codes=%s",
69792
69839
  char.length,
69793
69840
  char.replace(/\n/g, "\\n").replace(/\r/g, "\\r"),
@@ -69854,14 +69901,14 @@ function useTerminal() {
69854
69901
  }
69855
69902
  return context;
69856
69903
  }
69857
- var import_headless, logger7, TerminalContext;
69904
+ var import_headless, logger8, TerminalContext;
69858
69905
  var init_TerminalContext = __esm({
69859
69906
  "packages/cli/src/ui/contexts/TerminalContext.tsx"() {
69860
69907
  "use strict";
69861
69908
  import_headless = __toESM(require_xterm_headless(), 1);
69862
69909
  init_logger();
69863
69910
  init_terminalSerializer();
69864
- logger7 = createLogger("TerminalContext");
69911
+ logger8 = createLogger("TerminalContext");
69865
69912
  TerminalContext = createContext23(void 0);
69866
69913
  }
69867
69914
  });
@@ -70567,7 +70614,7 @@ var init_DotIndicator = __esm({
70567
70614
  // packages/cli/src/ui/components/layout/KeybindsLegend.tsx
70568
70615
  import { Box as Box28, Text as Text28 } from "ink";
70569
70616
  import { jsx as jsx53, jsxs as jsxs24 } from "react/jsx-runtime";
70570
- function KeybindsLegend({ theme, version: version3 = "0.1.0-alpha" }) {
70617
+ function KeybindsLegend({ theme, version: version3 = "0.1.4b" }) {
70571
70618
  return /* @__PURE__ */ jsxs24(Box28, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
70572
70619
  /* @__PURE__ */ jsxs24(Box28, { marginBottom: 1, justifyContent: "center", children: [
70573
70620
  /* @__PURE__ */ jsx53(Text28, { bold: true, color: theme.text.accent, children: "OLLM CLI" }),
@@ -71981,7 +72028,7 @@ function BugReportTab({ width }) {
71981
72028
  /* @__PURE__ */ jsx62(Box37, { justifyContent: "center", marginBottom: 2, children: /* @__PURE__ */ jsx62(Text36, { color: uiState.theme.text.secondary, children: "have a feature suggestion, or just need help - we'd love to hear from you!" }) }),
71982
72029
  /* @__PURE__ */ jsx62(Box37, { marginBottom: 1, children: /* @__PURE__ */ jsx62(Text36, { bold: true, color: uiState.theme.text.primary, children: "\u{1F4DD} Before You Report:" }) }),
71983
72030
  /* @__PURE__ */ jsx62(Text36, { color: uiState.theme.text.secondary, children: "\u2713 Check if the issue still happens after restarting OLLM CLI" }),
71984
- /* @__PURE__ */ jsx62(Text36, { color: uiState.theme.text.secondary, children: "\u2713 Make sure you're running the latest version (v0.1.0)" }),
72031
+ /* @__PURE__ */ jsx62(Text36, { color: uiState.theme.text.secondary, children: "\u2713 Make sure you're running the latest version (v0.1.4b)" }),
71985
72032
  /* @__PURE__ */ jsx62(Box37, { marginBottom: 2, children: /* @__PURE__ */ jsx62(Text36, { color: uiState.theme.text.secondary, children: "\u2713 Try to reproduce the issue to confirm it's consistent" }) }),
71986
72033
  /* @__PURE__ */ jsx62(Box37, { marginBottom: 1, children: /* @__PURE__ */ jsx62(Text36, { bold: true, color: uiState.theme.text.primary, children: "\u{1F4CB} What Makes a Great Bug Report:" }) }),
71987
72034
  /* @__PURE__ */ jsx62(Text36, { color: uiState.theme.text.secondary, children: "\u2022 Clear description of what went wrong" }),
@@ -72820,14 +72867,19 @@ var init_ChatTab = __esm({
72820
72867
  // packages/cli/src/services/documentService.ts
72821
72868
  import fs31 from "fs";
72822
72869
  import path33 from "path";
72870
+ import { fileURLToPath as fileURLToPath4 } from "url";
72871
+ import os15 from "os";
72823
72872
  var DocumentService, documentService;
72824
72873
  var init_documentService = __esm({
72825
72874
  "packages/cli/src/services/documentService.ts"() {
72826
72875
  "use strict";
72827
72876
  DocumentService = class {
72828
72877
  basePath;
72829
- constructor(basePath = "docs") {
72830
- this.basePath = basePath;
72878
+ constructor(basePath) {
72879
+ const moduleDir = typeof __dirname !== "undefined" ? __dirname : path33.dirname(fileURLToPath4(import.meta.url));
72880
+ const packaged = path33.join(moduleDir, "..", "..", "..", "docs");
72881
+ const userDocs = path33.join(os15.homedir(), ".ollm", "docs");
72882
+ this.basePath = fs31.existsSync(userDocs) ? userDocs : packaged;
72831
72883
  }
72832
72884
  /**
72833
72885
  * Discover all documentation files organized by folder
@@ -73215,11 +73267,12 @@ function DocsPanel({ height, windowWidth }) {
73215
73267
  const folder = folders[item.folderIndex];
73216
73268
  const doc = folder.documents[item.docIndex];
73217
73269
  const isSelected = !isOnExitItem && item.folderIndex === selectedFolderIndex && item.docIndex === selectedDocIndex && focusedColumn === "left";
73218
- return /* @__PURE__ */ jsx67(Box42, { paddingLeft: 2, children: /* @__PURE__ */ jsxs35(
73270
+ return /* @__PURE__ */ jsx67(Box42, { paddingLeft: 2, marginBottom: 1, width: "100%", children: /* @__PURE__ */ jsxs35(
73219
73271
  Text39,
73220
73272
  {
73221
73273
  bold: isSelected && hasFocus,
73222
73274
  color: isSelected && hasFocus ? "yellow" : uiState.theme.text.primary,
73275
+ wrap: "truncate-end",
73223
73276
  children: [
73224
73277
  "\u{1F4C4} ",
73225
73278
  doc.title
@@ -79982,17 +80035,17 @@ function useMouse(onMouse) {
79982
80035
  }, [context, onMouse]);
79983
80036
  useEffect43(() => {
79984
80037
  if (!context) {
79985
- logger8.warn("useMouse used outside MouseProvider - mouse events will not work");
80038
+ logger9.warn("useMouse used outside MouseProvider - mouse events will not work");
79986
80039
  }
79987
80040
  }, [context]);
79988
80041
  }
79989
- var logger8, MouseContext;
80042
+ var logger9, MouseContext;
79990
80043
  var init_useMouse = __esm({
79991
80044
  "packages/cli/src/ui/hooks/useMouse.tsx"() {
79992
80045
  "use strict";
79993
80046
  init_logger();
79994
80047
  init_terminal();
79995
- logger8 = createLogger("useMouse");
80048
+ logger9 = createLogger("useMouse");
79996
80049
  MouseContext = createContext25(null);
79997
80050
  }
79998
80051
  });
@@ -80426,7 +80479,7 @@ var init_App = __esm({
80426
80479
  // packages/cli/src/cli.tsx
80427
80480
  import { readFileSync as readFileSync11, appendFileSync as appendFileSync3, mkdirSync as mkdirSync8, existsSync as existsSync13 } from "fs";
80428
80481
  import { dirname as dirname10, join as join35 } from "path";
80429
- import { fileURLToPath as fileURLToPath4 } from "url";
80482
+ import { fileURLToPath as fileURLToPath5 } from "url";
80430
80483
  import { render, Text as Text79 } from "ink";
80431
80484
  import { hideBin } from "yargs/helpers";
80432
80485
  import Yargs from "yargs/yargs";
@@ -80885,7 +80938,7 @@ function loadConfig(options = {}) {
80885
80938
  // packages/cli/src/cli.tsx
80886
80939
  init_stdio();
80887
80940
  import { Fragment as Fragment17, jsx as jsx114, jsxs as jsxs73 } from "react/jsx-runtime";
80888
- var __filename2 = fileURLToPath4(import.meta.url);
80941
+ var __filename2 = fileURLToPath5(import.meta.url);
80889
80942
  var __dirname3 = dirname10(__filename2);
80890
80943
  var packageJsonPath = join35(__dirname3, "..", "package.json");
80891
80944
  var packageJson = JSON.parse(readFileSync11(packageJsonPath, "utf-8"));