cascade-ai 0.2.11 → 0.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -83,7 +83,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
83
83
  var CASCADE_VERSION, CASCADE_CONFIG_FILE, CASCADE_DB_FILE, CASCADE_DASHBOARD_SECRET_FILE, GLOBAL_CONFIG_DIR, GLOBAL_DB_FILE, GLOBAL_KEYSTORE_FILE, GLOBAL_RUNTIME_DB_FILE, DEFAULT_DASHBOARD_PORT, DEFAULT_CONTEXT_LIMIT, DEFAULT_AUTO_SUMMARIZE_AT, MODELS, T1_MODEL_PRIORITY, T2_MODEL_PRIORITY, T3_MODEL_PRIORITY, VISION_MODEL_PRIORITY, COMPLEXITY_T2_COUNT, THEME_NAMES, DEFAULT_THEME, OLLAMA_BASE_URL, LM_STUDIO_BASE_URL, AZURE_BASE_URL_TEMPLATE, TOOL_NAMES, DEFAULT_APPROVAL_REQUIRED;
84
84
  var init_constants = __esm({
85
85
  "src/constants.ts"() {
86
- CASCADE_VERSION = "0.2.11";
86
+ CASCADE_VERSION = "0.2.12";
87
87
  CASCADE_CONFIG_FILE = ".cascade/config.json";
88
88
  CASCADE_DB_FILE = ".cascade/memory.db";
89
89
  CASCADE_DASHBOARD_SECRET_FILE = ".cascade/dashboard-secret";
@@ -522,17 +522,38 @@ var init_anthropic = __esm({
522
522
  messages,
523
523
  tools: tools?.length ? tools : void 0
524
524
  });
525
+ let isThinking = false;
525
526
  for await (const event of stream) {
526
- if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
527
- const text = event.delta.text;
528
- fullContent += text;
529
- onChunk({ text, finishReason: null });
527
+ if (event.type === "content_block_delta") {
528
+ if (event.delta.type === "thinking_delta") {
529
+ if (!isThinking) {
530
+ isThinking = true;
531
+ fullContent += "<think>\n";
532
+ onChunk({ text: "<think>\n", finishReason: null });
533
+ }
534
+ const text = event.delta.thinking;
535
+ fullContent += text;
536
+ onChunk({ text, finishReason: null });
537
+ } else if (event.delta.type === "text_delta") {
538
+ if (isThinking) {
539
+ isThinking = false;
540
+ fullContent += "\n</think>\n\n";
541
+ onChunk({ text: "\n</think>\n\n", finishReason: null });
542
+ }
543
+ const text = event.delta.text;
544
+ fullContent += text;
545
+ onChunk({ text, finishReason: null });
546
+ }
530
547
  } else if (event.type === "message_delta" && event.usage) {
531
548
  outputTokens = event.usage.output_tokens;
532
549
  } else if (event.type === "message_start" && event.message.usage) {
533
550
  inputTokens = event.message.usage.input_tokens;
534
551
  }
535
552
  }
553
+ if (isThinking) {
554
+ fullContent += "\n</think>\n\n";
555
+ onChunk({ text: "\n</think>\n\n", finishReason: null });
556
+ }
536
557
  const finalMessage = await stream.finalMessage();
537
558
  const toolCalls = finalMessage.content.filter((b) => b.type === "tool_use").map((b) => ({
538
559
  id: b.id,
@@ -716,9 +737,25 @@ var init_openai = __esm({
716
737
  }
717
738
  }
718
739
  const toolCallsMap = {};
740
+ let isThinking = false;
719
741
  for await (const chunk of stream) {
720
742
  const delta = chunk.choices[0]?.delta;
743
+ const reasoningContent = delta?.reasoning_content;
744
+ if (reasoningContent) {
745
+ if (!isThinking) {
746
+ isThinking = true;
747
+ fullContent += "<think>\n";
748
+ onChunk({ text: "<think>\n", finishReason: null });
749
+ }
750
+ fullContent += reasoningContent;
751
+ onChunk({ text: reasoningContent, finishReason: null });
752
+ }
721
753
  if (delta?.content) {
754
+ if (isThinking) {
755
+ isThinking = false;
756
+ fullContent += "\n</think>\n\n";
757
+ onChunk({ text: "\n</think>\n\n", finishReason: null });
758
+ }
722
759
  fullContent += delta.content;
723
760
  onChunk({ text: delta.content, finishReason: null });
724
761
  }
@@ -741,6 +778,10 @@ var init_openai = __esm({
741
778
  outputTokens = chunk.usage.completion_tokens;
742
779
  }
743
780
  }
781
+ if (isThinking) {
782
+ fullContent += "\n</think>\n\n";
783
+ onChunk({ text: "\n</think>\n\n", finishReason: null });
784
+ }
744
785
  const toolCalls = Object.values(toolCallsMap).map((tc) => {
745
786
  let input = {};
746
787
  try {
@@ -2576,6 +2617,7 @@ var ConfigManager = class {
2576
2617
  }
2577
2618
  }
2578
2619
  async injectEnvKeys() {
2620
+ const isFirstRun = this.config.providers.length === 0;
2579
2621
  const envProviders = [
2580
2622
  { env: "ANTHROPIC_API_KEY", type: "anthropic" },
2581
2623
  { env: "OPENAI_API_KEY", type: "openai" },
@@ -2586,10 +2628,13 @@ var ConfigManager = class {
2586
2628
  const key = process.env[env];
2587
2629
  if (!key) continue;
2588
2630
  const existing = this.config.providers.find((p) => p.type === type);
2589
- if (!existing) this.config.providers.push({ type, apiKey: key });
2590
- else if (!existing.apiKey) existing.apiKey = key;
2631
+ if (!existing && isFirstRun) {
2632
+ this.config.providers.push({ type, apiKey: key });
2633
+ } else if (existing && !existing.apiKey) {
2634
+ existing.apiKey = key;
2635
+ }
2591
2636
  }
2592
- if (!this.config.providers.find((p) => p.type === "ollama")) {
2637
+ if (isFirstRun && !this.config.providers.find((p) => p.type === "ollama")) {
2593
2638
  this.config.providers.push({ type: "ollama" });
2594
2639
  }
2595
2640
  }
@@ -8055,11 +8100,6 @@ var SlashCommandRegistry = class {
8055
8100
  description: "Show active models per tier",
8056
8101
  handler: (_args, ctx) => ({ output: ctx.onModelInfo(), handled: true })
8057
8102
  });
8058
- this.register({
8059
- command: "/models",
8060
- description: "Browse available models by provider",
8061
- handler: (_args, ctx) => ({ output: ctx.onModelsInfo(), handled: true })
8062
- });
8063
8103
  this.register({
8064
8104
  command: "/providers",
8065
8105
  description: "Show configured providers",
@@ -9356,8 +9396,8 @@ Use /identity <name|id> to switch.`;
9356
9396
  const statusHeight = agentTreeHeight + timelineHeight;
9357
9397
  const costHeight = state.showCost ? 6 : 0;
9358
9398
  const approvalHeight = state.approvalRequest ? 12 : 0;
9359
- const slashVisibleCount = Math.min(SLASH_PAGE_SIZE, slashEntries.length);
9360
- const slashHeight = slashVisibleCount > 0 ? slashVisibleCount + 2 : 0;
9399
+ Math.min(SLASH_PAGE_SIZE, slashEntries.length);
9400
+ const slashHeight = isTypingCommand ? SLASH_PAGE_SIZE + 2 : 0;
9361
9401
  const chromeHeight = statusHeight + costHeight + approvalHeight + slashHeight + 7;
9362
9402
  const availableHeight = Math.max(4, height - chromeHeight);
9363
9403
  const allLines = formatToLines(
@@ -9769,8 +9809,21 @@ function wizardReducer(state, action) {
9769
9809
  addingAnotherCompat: false
9770
9810
  };
9771
9811
  }
9812
+ case "ADD_OLLAMA": {
9813
+ const newEntry = {
9814
+ id: randomUUID(),
9815
+ type: "ollama",
9816
+ label: `Ollama endpoint ${state.entries.filter((e) => e.type === "ollama").length + 1}`
9817
+ };
9818
+ return {
9819
+ ...state,
9820
+ entries: [...state.entries, newEntry],
9821
+ currentEntryIdx: state.entries.length,
9822
+ addingAnotherOllama: false
9823
+ };
9824
+ }
9772
9825
  case "SKIP_MORE":
9773
- return { ...state, addingAnotherAzure: false, addingAnotherCompat: false, step: "FETCH_MODELS", currentEntryIdx: 0 };
9826
+ return { ...state, addingAnotherAzure: false, addingAnotherCompat: false, addingAnotherOllama: false, step: "FETCH_MODELS", currentEntryIdx: 0 };
9774
9827
  case "GO_FETCH":
9775
9828
  return { ...state, step: "FETCH_MODELS", fetchLog: [], fetchedModels: [] };
9776
9829
  case "SET_FETCH_LOG":
@@ -9803,6 +9856,7 @@ function SetupWizard({ workspacePath, onComplete }) {
9803
9856
  currentEntryIdx: 0,
9804
9857
  addingAnotherAzure: false,
9805
9858
  addingAnotherCompat: false,
9859
+ addingAnotherOllama: false,
9806
9860
  fetchedModels: [],
9807
9861
  fetchLog: [],
9808
9862
  tierT1: "auto",
@@ -9902,13 +9956,16 @@ function SetupWizard({ workspacePath, onComplete }) {
9902
9956
  }, [state.step, state.entries, state.tierT1, state.tierT2, state.tierT3, workspacePath, onComplete, exit]);
9903
9957
  useInput((_input, key) => {
9904
9958
  if (state.step === "PROVIDER_SELECT") {
9905
- if (key.upArrow) setProviderCursor((p) => Math.max(0, p - 1));
9906
- if (key.downArrow) setProviderCursor((p) => Math.min(providerOrder.length - 1, p + 1));
9959
+ if (key.upArrow) setProviderCursor((p) => p <= 0 ? providerOrder.length - 1 : p - 1);
9960
+ if (key.downArrow) setProviderCursor((p) => p >= providerOrder.length - 1 ? 0 : p + 1);
9907
9961
  if (_input === " ") dispatch({ type: "TOGGLE_PROVIDER", provider: providerOrder[providerCursor] });
9908
9962
  if (_input === "a") dispatch({ type: "TOGGLE_ALL" });
9909
9963
  if (_input === "i") dispatch({ type: "INVERT_SELECTION" });
9910
9964
  if (key.return) {
9911
- if (state.selectedTypes.size === 0) return;
9965
+ if (state.selectedTypes.size === 0) {
9966
+ dispatch({ type: "SET_ERROR", error: "Please select at least one provider using <space> before pressing <enter>." });
9967
+ return;
9968
+ }
9912
9969
  dispatch({ type: "CONFIRM_PROVIDERS" });
9913
9970
  const firstType = [...state.selectedTypes][0];
9914
9971
  setFieldStage(firstType === "azure" ? "deploymentName" : firstType === "openai-compatible" ? "label" : firstType === "ollama" ? "baseUrl" : "apiKey");
@@ -9965,11 +10022,7 @@ function SetupWizard({ workspacePath, onComplete }) {
9965
10022
  } else if (currentEntry.type === "ollama") {
9966
10023
  dispatch({ type: "SET_ENTRY_FIELD", field: "baseUrl", value: val || "http://localhost:11434" });
9967
10024
  setFieldBuffer("");
9968
- const nextEntry = state.entries[state.currentEntryIdx + 1];
9969
- if (nextEntry) {
9970
- setFieldStage(nextEntry.type === "azure" ? "deploymentName" : nextEntry.type === "openai-compatible" ? "label" : nextEntry.type === "ollama" ? "baseUrl" : "apiKey");
9971
- }
9972
- dispatch({ type: "NEXT_ENTRY" });
10025
+ setFieldStage("askMore");
9973
10026
  } else {
9974
10027
  dispatch({ type: "SET_ENTRY_FIELD", field: "apiKey", value: val });
9975
10028
  setFieldBuffer("");
@@ -10010,7 +10063,7 @@ function SetupWizard({ workspacePath, onComplete }) {
10010
10063
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
10011
10064
  /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
10012
10065
  /* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: "? " }),
10013
- /* @__PURE__ */ jsx(Text, { bold: true, children: isAzure ? "Add another Azure deployment? (y/n)" : "Add another custom endpoint? (y/n)" })
10066
+ /* @__PURE__ */ jsx(Text, { bold: true, children: isAzure ? "Add another Azure deployment? (y/n)" : isOllama ? "Add another Ollama endpoint? (y/n)" : "Add another custom endpoint? (y/n)" })
10014
10067
  ] }),
10015
10068
  /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(
10016
10069
  SelectInput,
@@ -10024,8 +10077,9 @@ function SetupWizard({ workspacePath, onComplete }) {
10024
10077
  onSelect: (item) => {
10025
10078
  if (item.value === "yes") {
10026
10079
  if (isAzure) dispatch({ type: "ADD_AZURE" });
10080
+ else if (isOllama) dispatch({ type: "ADD_OLLAMA" });
10027
10081
  else dispatch({ type: "ADD_COMPAT" });
10028
- setFieldStage(isAzure ? "deploymentName" : "label");
10082
+ setFieldStage(isAzure ? "deploymentName" : isOllama ? "baseUrl" : "label");
10029
10083
  setFieldBuffer("");
10030
10084
  } else {
10031
10085
  const nextEntry = state.entries[state.currentEntryIdx + 1];
@@ -10041,7 +10095,7 @@ function SetupWizard({ workspacePath, onComplete }) {
10041
10095
  ] });
10042
10096
  }
10043
10097
  const prompt = isAzure && fieldStage === "deploymentName" ? `Azure deployment name (${currentEntry.label})` : isAzure && fieldStage === "baseUrl" ? `Azure endpoint URL` : isCompat && fieldStage === "label" ? `Name for this endpoint (e.g. Groq)` : isCompat && fieldStage === "baseUrl" ? `Base URL (e.g. https://api.groq.com/openai/v1)` : isOllama ? `Ollama URL (Enter for http://localhost:11434)` : `${currentEntry.label} API Key`;
10044
- const isMasked = fieldStage === "apiKey";
10098
+ const isMasked = fieldStage === "apiKey" && !isOllama;
10045
10099
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
10046
10100
  /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
10047
10101
  /* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: "? " }),