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.cjs CHANGED
@@ -130,7 +130,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
130
130
  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;
131
131
  var init_constants = __esm({
132
132
  "src/constants.ts"() {
133
- CASCADE_VERSION = "0.2.11";
133
+ CASCADE_VERSION = "0.2.12";
134
134
  CASCADE_CONFIG_FILE = ".cascade/config.json";
135
135
  CASCADE_DB_FILE = ".cascade/memory.db";
136
136
  CASCADE_DASHBOARD_SECRET_FILE = ".cascade/dashboard-secret";
@@ -569,17 +569,38 @@ var init_anthropic = __esm({
569
569
  messages,
570
570
  tools: tools?.length ? tools : void 0
571
571
  });
572
+ let isThinking = false;
572
573
  for await (const event of stream) {
573
- if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
574
- const text = event.delta.text;
575
- fullContent += text;
576
- onChunk({ text, finishReason: null });
574
+ if (event.type === "content_block_delta") {
575
+ if (event.delta.type === "thinking_delta") {
576
+ if (!isThinking) {
577
+ isThinking = true;
578
+ fullContent += "<think>\n";
579
+ onChunk({ text: "<think>\n", finishReason: null });
580
+ }
581
+ const text = event.delta.thinking;
582
+ fullContent += text;
583
+ onChunk({ text, finishReason: null });
584
+ } else if (event.delta.type === "text_delta") {
585
+ if (isThinking) {
586
+ isThinking = false;
587
+ fullContent += "\n</think>\n\n";
588
+ onChunk({ text: "\n</think>\n\n", finishReason: null });
589
+ }
590
+ const text = event.delta.text;
591
+ fullContent += text;
592
+ onChunk({ text, finishReason: null });
593
+ }
577
594
  } else if (event.type === "message_delta" && event.usage) {
578
595
  outputTokens = event.usage.output_tokens;
579
596
  } else if (event.type === "message_start" && event.message.usage) {
580
597
  inputTokens = event.message.usage.input_tokens;
581
598
  }
582
599
  }
600
+ if (isThinking) {
601
+ fullContent += "\n</think>\n\n";
602
+ onChunk({ text: "\n</think>\n\n", finishReason: null });
603
+ }
583
604
  const finalMessage = await stream.finalMessage();
584
605
  const toolCalls = finalMessage.content.filter((b) => b.type === "tool_use").map((b) => ({
585
606
  id: b.id,
@@ -763,9 +784,25 @@ var init_openai = __esm({
763
784
  }
764
785
  }
765
786
  const toolCallsMap = {};
787
+ let isThinking = false;
766
788
  for await (const chunk of stream) {
767
789
  const delta = chunk.choices[0]?.delta;
790
+ const reasoningContent = delta?.reasoning_content;
791
+ if (reasoningContent) {
792
+ if (!isThinking) {
793
+ isThinking = true;
794
+ fullContent += "<think>\n";
795
+ onChunk({ text: "<think>\n", finishReason: null });
796
+ }
797
+ fullContent += reasoningContent;
798
+ onChunk({ text: reasoningContent, finishReason: null });
799
+ }
768
800
  if (delta?.content) {
801
+ if (isThinking) {
802
+ isThinking = false;
803
+ fullContent += "\n</think>\n\n";
804
+ onChunk({ text: "\n</think>\n\n", finishReason: null });
805
+ }
769
806
  fullContent += delta.content;
770
807
  onChunk({ text: delta.content, finishReason: null });
771
808
  }
@@ -788,6 +825,10 @@ var init_openai = __esm({
788
825
  outputTokens = chunk.usage.completion_tokens;
789
826
  }
790
827
  }
828
+ if (isThinking) {
829
+ fullContent += "\n</think>\n\n";
830
+ onChunk({ text: "\n</think>\n\n", finishReason: null });
831
+ }
791
832
  const toolCalls = Object.values(toolCallsMap).map((tc) => {
792
833
  let input = {};
793
834
  try {
@@ -2623,6 +2664,7 @@ var ConfigManager = class {
2623
2664
  }
2624
2665
  }
2625
2666
  async injectEnvKeys() {
2667
+ const isFirstRun = this.config.providers.length === 0;
2626
2668
  const envProviders = [
2627
2669
  { env: "ANTHROPIC_API_KEY", type: "anthropic" },
2628
2670
  { env: "OPENAI_API_KEY", type: "openai" },
@@ -2633,10 +2675,13 @@ var ConfigManager = class {
2633
2675
  const key = process.env[env];
2634
2676
  if (!key) continue;
2635
2677
  const existing = this.config.providers.find((p) => p.type === type);
2636
- if (!existing) this.config.providers.push({ type, apiKey: key });
2637
- else if (!existing.apiKey) existing.apiKey = key;
2678
+ if (!existing && isFirstRun) {
2679
+ this.config.providers.push({ type, apiKey: key });
2680
+ } else if (existing && !existing.apiKey) {
2681
+ existing.apiKey = key;
2682
+ }
2638
2683
  }
2639
- if (!this.config.providers.find((p) => p.type === "ollama")) {
2684
+ if (isFirstRun && !this.config.providers.find((p) => p.type === "ollama")) {
2640
2685
  this.config.providers.push({ type: "ollama" });
2641
2686
  }
2642
2687
  }
@@ -8102,11 +8147,6 @@ var SlashCommandRegistry = class {
8102
8147
  description: "Show active models per tier",
8103
8148
  handler: (_args, ctx) => ({ output: ctx.onModelInfo(), handled: true })
8104
8149
  });
8105
- this.register({
8106
- command: "/models",
8107
- description: "Browse available models by provider",
8108
- handler: (_args, ctx) => ({ output: ctx.onModelsInfo(), handled: true })
8109
- });
8110
8150
  this.register({
8111
8151
  command: "/providers",
8112
8152
  description: "Show configured providers",
@@ -9403,8 +9443,8 @@ Use /identity <name|id> to switch.`;
9403
9443
  const statusHeight = agentTreeHeight + timelineHeight;
9404
9444
  const costHeight = state.showCost ? 6 : 0;
9405
9445
  const approvalHeight = state.approvalRequest ? 12 : 0;
9406
- const slashVisibleCount = Math.min(SLASH_PAGE_SIZE, slashEntries.length);
9407
- const slashHeight = slashVisibleCount > 0 ? slashVisibleCount + 2 : 0;
9446
+ Math.min(SLASH_PAGE_SIZE, slashEntries.length);
9447
+ const slashHeight = isTypingCommand ? SLASH_PAGE_SIZE + 2 : 0;
9408
9448
  const chromeHeight = statusHeight + costHeight + approvalHeight + slashHeight + 7;
9409
9449
  const availableHeight = Math.max(4, height - chromeHeight);
9410
9450
  const allLines = formatToLines(
@@ -9816,8 +9856,21 @@ function wizardReducer(state, action) {
9816
9856
  addingAnotherCompat: false
9817
9857
  };
9818
9858
  }
9859
+ case "ADD_OLLAMA": {
9860
+ const newEntry = {
9861
+ id: crypto.randomUUID(),
9862
+ type: "ollama",
9863
+ label: `Ollama endpoint ${state.entries.filter((e) => e.type === "ollama").length + 1}`
9864
+ };
9865
+ return {
9866
+ ...state,
9867
+ entries: [...state.entries, newEntry],
9868
+ currentEntryIdx: state.entries.length,
9869
+ addingAnotherOllama: false
9870
+ };
9871
+ }
9819
9872
  case "SKIP_MORE":
9820
- return { ...state, addingAnotherAzure: false, addingAnotherCompat: false, step: "FETCH_MODELS", currentEntryIdx: 0 };
9873
+ return { ...state, addingAnotherAzure: false, addingAnotherCompat: false, addingAnotherOllama: false, step: "FETCH_MODELS", currentEntryIdx: 0 };
9821
9874
  case "GO_FETCH":
9822
9875
  return { ...state, step: "FETCH_MODELS", fetchLog: [], fetchedModels: [] };
9823
9876
  case "SET_FETCH_LOG":
@@ -9850,6 +9903,7 @@ function SetupWizard({ workspacePath, onComplete }) {
9850
9903
  currentEntryIdx: 0,
9851
9904
  addingAnotherAzure: false,
9852
9905
  addingAnotherCompat: false,
9906
+ addingAnotherOllama: false,
9853
9907
  fetchedModels: [],
9854
9908
  fetchLog: [],
9855
9909
  tierT1: "auto",
@@ -9949,13 +10003,16 @@ function SetupWizard({ workspacePath, onComplete }) {
9949
10003
  }, [state.step, state.entries, state.tierT1, state.tierT2, state.tierT3, workspacePath, onComplete, exit]);
9950
10004
  ink.useInput((_input, key) => {
9951
10005
  if (state.step === "PROVIDER_SELECT") {
9952
- if (key.upArrow) setProviderCursor((p) => Math.max(0, p - 1));
9953
- if (key.downArrow) setProviderCursor((p) => Math.min(providerOrder.length - 1, p + 1));
10006
+ if (key.upArrow) setProviderCursor((p) => p <= 0 ? providerOrder.length - 1 : p - 1);
10007
+ if (key.downArrow) setProviderCursor((p) => p >= providerOrder.length - 1 ? 0 : p + 1);
9954
10008
  if (_input === " ") dispatch({ type: "TOGGLE_PROVIDER", provider: providerOrder[providerCursor] });
9955
10009
  if (_input === "a") dispatch({ type: "TOGGLE_ALL" });
9956
10010
  if (_input === "i") dispatch({ type: "INVERT_SELECTION" });
9957
10011
  if (key.return) {
9958
- if (state.selectedTypes.size === 0) return;
10012
+ if (state.selectedTypes.size === 0) {
10013
+ dispatch({ type: "SET_ERROR", error: "Please select at least one provider using <space> before pressing <enter>." });
10014
+ return;
10015
+ }
9959
10016
  dispatch({ type: "CONFIRM_PROVIDERS" });
9960
10017
  const firstType = [...state.selectedTypes][0];
9961
10018
  setFieldStage(firstType === "azure" ? "deploymentName" : firstType === "openai-compatible" ? "label" : firstType === "ollama" ? "baseUrl" : "apiKey");
@@ -10012,11 +10069,7 @@ function SetupWizard({ workspacePath, onComplete }) {
10012
10069
  } else if (currentEntry.type === "ollama") {
10013
10070
  dispatch({ type: "SET_ENTRY_FIELD", field: "baseUrl", value: val || "http://localhost:11434" });
10014
10071
  setFieldBuffer("");
10015
- const nextEntry = state.entries[state.currentEntryIdx + 1];
10016
- if (nextEntry) {
10017
- setFieldStage(nextEntry.type === "azure" ? "deploymentName" : nextEntry.type === "openai-compatible" ? "label" : nextEntry.type === "ollama" ? "baseUrl" : "apiKey");
10018
- }
10019
- dispatch({ type: "NEXT_ENTRY" });
10072
+ setFieldStage("askMore");
10020
10073
  } else {
10021
10074
  dispatch({ type: "SET_ENTRY_FIELD", field: "apiKey", value: val });
10022
10075
  setFieldBuffer("");
@@ -10057,7 +10110,7 @@ function SetupWizard({ workspacePath, onComplete }) {
10057
10110
  return /* @__PURE__ */ jsxRuntime.jsxs(ink.Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
10058
10111
  /* @__PURE__ */ jsxRuntime.jsxs(ink.Box, { marginBottom: 1, children: [
10059
10112
  /* @__PURE__ */ jsxRuntime.jsx(ink.Text, { color: "magenta", bold: true, children: "? " }),
10060
- /* @__PURE__ */ jsxRuntime.jsx(ink.Text, { bold: true, children: isAzure ? "Add another Azure deployment? (y/n)" : "Add another custom endpoint? (y/n)" })
10113
+ /* @__PURE__ */ jsxRuntime.jsx(ink.Text, { bold: true, children: isAzure ? "Add another Azure deployment? (y/n)" : isOllama ? "Add another Ollama endpoint? (y/n)" : "Add another custom endpoint? (y/n)" })
10061
10114
  ] }),
10062
10115
  /* @__PURE__ */ jsxRuntime.jsx(ink.Box, { children: /* @__PURE__ */ jsxRuntime.jsx(
10063
10116
  SelectInput__default.default,
@@ -10071,8 +10124,9 @@ function SetupWizard({ workspacePath, onComplete }) {
10071
10124
  onSelect: (item) => {
10072
10125
  if (item.value === "yes") {
10073
10126
  if (isAzure) dispatch({ type: "ADD_AZURE" });
10127
+ else if (isOllama) dispatch({ type: "ADD_OLLAMA" });
10074
10128
  else dispatch({ type: "ADD_COMPAT" });
10075
- setFieldStage(isAzure ? "deploymentName" : "label");
10129
+ setFieldStage(isAzure ? "deploymentName" : isOllama ? "baseUrl" : "label");
10076
10130
  setFieldBuffer("");
10077
10131
  } else {
10078
10132
  const nextEntry = state.entries[state.currentEntryIdx + 1];
@@ -10088,7 +10142,7 @@ function SetupWizard({ workspacePath, onComplete }) {
10088
10142
  ] });
10089
10143
  }
10090
10144
  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`;
10091
- const isMasked = fieldStage === "apiKey";
10145
+ const isMasked = fieldStage === "apiKey" && !isOllama;
10092
10146
  return /* @__PURE__ */ jsxRuntime.jsxs(ink.Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
10093
10147
  /* @__PURE__ */ jsxRuntime.jsxs(ink.Box, { marginBottom: 1, children: [
10094
10148
  /* @__PURE__ */ jsxRuntime.jsx(ink.Text, { color: "magenta", bold: true, children: "? " }),