@bike4mind/cli 0.2.8-feat-cli-context-file-loading.17148 → 0.2.8-feat-cli-session-resume.17148

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 (2) hide show
  1. package/dist/index.js +172 -193
  2. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -79,8 +79,8 @@ import {
79
79
  } from "./chunk-PDX44BCA.js";
80
80
 
81
81
  // src/index.tsx
82
- import React15, { useState as useState6, useEffect as useEffect3, useCallback, useRef } from "react";
83
- import { render, Box as Box14, Text as Text14, useApp, useInput as useInput5 } from "ink";
82
+ import React16, { useState as useState7, useEffect as useEffect3, useCallback, useRef } from "react";
83
+ import { render, Box as Box15, Text as Text15, useApp, useInput as useInput6 } from "ink";
84
84
  import { v4 as uuidv49 } from "uuid";
85
85
 
86
86
  // src/components/App.tsx
@@ -742,11 +742,9 @@ function InputPrompt({
742
742
  const [selectedIndex, setSelectedIndex] = useState2(0);
743
743
  const [historyIndex, setHistoryIndex] = useState2(-1);
744
744
  const [tempInput, setTempInput] = useState2("");
745
- const [inputKey, setInputKey] = useState2(0);
746
745
  useEffect(() => {
747
746
  if (prefillInput) {
748
747
  setValue(prefillInput);
749
- setInputKey((prev) => prev + 1);
750
748
  onPrefillConsumed?.();
751
749
  }
752
750
  }, [prefillInput, onPrefillConsumed]);
@@ -891,7 +889,6 @@ function InputPrompt({
891
889
  return /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text5, { bold: true, color: "cyan" }, "> "), /* @__PURE__ */ React5.createElement(
892
890
  CustomTextInput,
893
891
  {
894
- key: inputKey,
895
892
  value,
896
893
  onChange: handleChange,
897
894
  onSubmit: handleSubmit,
@@ -1569,9 +1566,72 @@ function RewindSelector({ messages, onSelect, onCancel }) {
1569
1566
  ), /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "Use \u2191\u2193 arrows to navigate, Enter to select, Esc to go back")));
1570
1567
  }
1571
1568
 
1569
+ // src/components/SessionSelector.tsx
1570
+ import React14, { useState as useState5 } from "react";
1571
+ import { Box as Box13, Text as Text13, useInput as useInput5 } from "ink";
1572
+ import SelectInput4 from "ink-select-input";
1573
+ function SessionSelector({ sessions, currentSession, onSelect, onCancel }) {
1574
+ const [step, setStep] = useState5("selection");
1575
+ const [selectedSession, setSelectedSession] = useState5(null);
1576
+ useInput5((input, key) => {
1577
+ if (key.escape) {
1578
+ if (step === "confirmation") {
1579
+ setStep("selection");
1580
+ setSelectedSession(null);
1581
+ } else {
1582
+ onCancel();
1583
+ }
1584
+ }
1585
+ });
1586
+ const hasUnsavedWork = currentSession && currentSession.messages.length > 0;
1587
+ const items = sessions.map((session, index) => {
1588
+ const messageCount = session.messages.length;
1589
+ const lastUpdated = new Date(session.updatedAt).toLocaleString();
1590
+ return {
1591
+ label: `[${index + 1}] ${session.name} (${messageCount} msg, ${session.model})
1592
+ Last updated: ${lastUpdated}`,
1593
+ value: session
1594
+ };
1595
+ });
1596
+ const handleSelectionSelect = (item) => {
1597
+ setSelectedSession(item.value);
1598
+ setStep("confirmation");
1599
+ };
1600
+ const handleConfirmationSelect = (item) => {
1601
+ if (item.value === "confirm" && selectedSession) {
1602
+ onSelect(selectedSession);
1603
+ } else {
1604
+ setStep("selection");
1605
+ setSelectedSession(null);
1606
+ }
1607
+ };
1608
+ if (step === "selection") {
1609
+ return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React14.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text13, { bold: true }, "Select a session to resume:")), /* @__PURE__ */ React14.createElement(
1610
+ SelectInput4,
1611
+ {
1612
+ items,
1613
+ onSelect: handleSelectionSelect,
1614
+ itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React14.createElement(Box13, null, /* @__PURE__ */ React14.createElement(Text13, { color: isSelected ? "cyan" : void 0 }, isSelected ? "\u276F " : " ", label))
1615
+ }
1616
+ ), /* @__PURE__ */ React14.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, "Use \u2191\u2193 arrows to navigate, Enter to select, Esc to cancel")));
1617
+ }
1618
+ const confirmationItems = [
1619
+ { label: "Yes, resume this session", value: "confirm" },
1620
+ { label: "No, go back to selection", value: "cancel" }
1621
+ ];
1622
+ return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React14.createElement(Box13, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React14.createElement(Text13, { bold: true }, 'Resume session: "', selectedSession?.name, '"'), /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, selectedSession?.messages.length, " messages | ", selectedSession?.model, " |", " ", selectedSession?.metadata?.totalTokens?.toLocaleString() ?? 0, " tokens"), hasUnsavedWork && /* @__PURE__ */ React14.createElement(Text13, { color: "yellow" }, "Warning: Your current session has unsaved messages. Use /save first if needed.")), /* @__PURE__ */ React14.createElement(
1623
+ SelectInput4,
1624
+ {
1625
+ items: confirmationItems,
1626
+ onSelect: handleConfirmationSelect,
1627
+ itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React14.createElement(Box13, null, /* @__PURE__ */ React14.createElement(Text13, { color: isSelected ? "cyan" : void 0 }, isSelected ? "\u276F " : " ", label))
1628
+ }
1629
+ ), /* @__PURE__ */ React14.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, "Use \u2191\u2193 arrows to navigate, Enter to select, Esc to go back")));
1630
+ }
1631
+
1572
1632
  // src/components/LoginFlow.tsx
1573
- import React14, { useState as useState5, useEffect as useEffect2 } from "react";
1574
- import { Box as Box13, Text as Text13 } from "ink";
1633
+ import React15, { useState as useState6, useEffect as useEffect2 } from "react";
1634
+ import { Box as Box14, Text as Text14 } from "ink";
1575
1635
  import Spinner2 from "ink-spinner";
1576
1636
  import jwt from "jsonwebtoken";
1577
1637
  import open from "open";
@@ -1687,10 +1747,10 @@ var OAuthClient = class {
1687
1747
 
1688
1748
  // src/components/LoginFlow.tsx
1689
1749
  function LoginFlow({ apiUrl = "http://localhost:3000", configStore, onSuccess, onError }) {
1690
- const [status, setStatus] = useState5("initiating");
1691
- const [deviceFlow, setDeviceFlow] = useState5(null);
1692
- const [statusMessage, setStatusMessage] = useState5("Initiating device authorization...");
1693
- const [error, setError] = useState5(null);
1750
+ const [status, setStatus] = useState6("initiating");
1751
+ const [deviceFlow, setDeviceFlow] = useState6(null);
1752
+ const [statusMessage, setStatusMessage] = useState6("Initiating device authorization...");
1753
+ const [error, setError] = useState6(null);
1694
1754
  useEffect2(() => {
1695
1755
  const runLoginFlow = async () => {
1696
1756
  const oauth = new OAuthClient(apiUrl);
@@ -1734,15 +1794,15 @@ function LoginFlow({ apiUrl = "http://localhost:3000", configStore, onSuccess, o
1734
1794
  }
1735
1795
  }, [deviceFlow, status]);
1736
1796
  if (status === "initiating") {
1737
- return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React14.createElement(Box13, null, /* @__PURE__ */ React14.createElement(Text13, { color: "cyan" }, /* @__PURE__ */ React14.createElement(Spinner2, { type: "dots" }), " Initiating device authorization...")));
1797
+ return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Text14, { color: "cyan" }, /* @__PURE__ */ React15.createElement(Spinner2, { type: "dots" }), " Initiating device authorization...")));
1738
1798
  }
1739
1799
  if (status === "error") {
1740
- return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React14.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text13, { color: "red", bold: true }, "\u2716 Authentication Failed")), /* @__PURE__ */ React14.createElement(Box13, null, /* @__PURE__ */ React14.createElement(Text13, { color: "red" }, error)));
1800
+ return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React15.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text14, { color: "red", bold: true }, "\u2716 Authentication Failed")), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Text14, { color: "red" }, error)));
1741
1801
  }
1742
1802
  if (status === "success") {
1743
- return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React14.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text13, { color: "green", bold: true }, "\u2714 Successfully authenticated!")), /* @__PURE__ */ React14.createElement(Box13, null, /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, "You can now use B4M CLI with your account.")));
1803
+ return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React15.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text14, { color: "green", bold: true }, "\u2714 Successfully authenticated!")), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Text14, { dimColor: true }, "You can now use B4M CLI with your account.")));
1744
1804
  }
1745
- return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan" }, /* @__PURE__ */ React14.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text13, { color: "cyan", bold: true }, "\u{1F510} Device Authorization")), /* @__PURE__ */ React14.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text13, null, "Opening browser automatically... If it doesn't open, please visit:")), /* @__PURE__ */ React14.createElement(Box13, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React14.createElement(Text13, { color: "blue", bold: true }, deviceFlow?.verification_uri)), /* @__PURE__ */ React14.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text13, null, "And enter this code when prompted:")), /* @__PURE__ */ React14.createElement(Box13, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React14.createElement(Text13, { color: "yellow", bold: true }, deviceFlow?.user_code)), /* @__PURE__ */ React14.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text13, { color: "cyan" }, /* @__PURE__ */ React14.createElement(Spinner2, { type: "dots" }), " ", statusMessage)), /* @__PURE__ */ React14.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, "Expires in ", deviceFlow ? Math.floor(deviceFlow.expires_in / 60) : 0, " minutes")));
1805
+ return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan" }, /* @__PURE__ */ React15.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text14, { color: "cyan", bold: true }, "\u{1F510} Device Authorization")), /* @__PURE__ */ React15.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text14, null, "Opening browser automatically... If it doesn't open, please visit:")), /* @__PURE__ */ React15.createElement(Box14, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React15.createElement(Text14, { color: "blue", bold: true }, deviceFlow?.verification_uri)), /* @__PURE__ */ React15.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text14, null, "And enter this code when prompted:")), /* @__PURE__ */ React15.createElement(Box14, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React15.createElement(Text14, { color: "yellow", bold: true }, deviceFlow?.user_code)), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text14, { color: "cyan" }, /* @__PURE__ */ React15.createElement(Spinner2, { type: "dots" }), " ", statusMessage)), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text14, { dimColor: true }, "Expires in ", deviceFlow ? Math.floor(deviceFlow.expires_in / 60) : 0, " minutes")));
1746
1806
  }
1747
1807
 
1748
1808
  // src/storage/SessionStore.ts
@@ -5024,8 +5084,8 @@ async function processAndStoreImages(images, context) {
5024
5084
  const buffer = await downloadImage(image);
5025
5085
  const fileType = await fileTypeFromBuffer2(buffer);
5026
5086
  const filename = `${uuidv45()}.${fileType?.ext}`;
5027
- const path14 = await context.imageGenerateStorage.upload(buffer, filename, {});
5028
- return path14;
5087
+ const path13 = await context.imageGenerateStorage.upload(buffer, filename, {});
5088
+ return path13;
5029
5089
  }));
5030
5090
  }
5031
5091
  async function updateQuestAndReturnMarkdown(storedImageUrls, context) {
@@ -6237,8 +6297,8 @@ async function processAndStoreImage(imageUrl, context) {
6237
6297
  const buffer = await downloadImage2(imageUrl);
6238
6298
  const fileType = await fileTypeFromBuffer3(buffer);
6239
6299
  const filename = `${uuidv46()}.${fileType?.ext}`;
6240
- const path14 = await context.imageGenerateStorage.upload(buffer, filename, {});
6241
- return path14;
6300
+ const path13 = await context.imageGenerateStorage.upload(buffer, filename, {});
6301
+ return path13;
6242
6302
  }
6243
6303
  async function updateQuestAndReturnMarkdown2(storedImagePath, context) {
6244
6304
  await context.onFinish?.("edit_image", storedImagePath);
@@ -8952,7 +9012,7 @@ async function generateFileDeletePreview(args) {
8952
9012
  if (!existsSync7(args.path)) {
8953
9013
  return `[File does not exist: ${args.path}]`;
8954
9014
  }
8955
- const stats = await import("fs/promises").then((fs12) => fs12.stat(args.path));
9015
+ const stats = await import("fs/promises").then((fs11) => fs11.stat(args.path));
8956
9016
  return `[File will be deleted]
8957
9017
 
8958
9018
  Path: ${args.path}
@@ -9300,21 +9360,21 @@ var NoOpStorage = class extends BaseStorage {
9300
9360
  async upload(input, destination, options) {
9301
9361
  return `/tmp/${destination}`;
9302
9362
  }
9303
- async download(path14) {
9363
+ async download(path13) {
9304
9364
  throw new Error("Download not supported in CLI");
9305
9365
  }
9306
- async delete(path14) {
9366
+ async delete(path13) {
9307
9367
  }
9308
- async getSignedUrl(path14) {
9309
- return `/tmp/${path14}`;
9368
+ async getSignedUrl(path13) {
9369
+ return `/tmp/${path13}`;
9310
9370
  }
9311
- getPublicUrl(path14) {
9312
- return `/tmp/${path14}`;
9371
+ getPublicUrl(path13) {
9372
+ return `/tmp/${path13}`;
9313
9373
  }
9314
- async getPreview(path14) {
9315
- return `/tmp/${path14}`;
9374
+ async getPreview(path13) {
9375
+ return `/tmp/${path13}`;
9316
9376
  }
9317
- async getMetadata(path14) {
9377
+ async getMetadata(path13) {
9318
9378
  return { size: 0, contentType: "application/octet-stream" };
9319
9379
  }
9320
9380
  };
@@ -9668,122 +9728,10 @@ function getEnvironmentName(configApiConfig) {
9668
9728
  return "Bike4Mind";
9669
9729
  }
9670
9730
 
9671
- // src/utils/contextLoader.ts
9672
- import * as fs11 from "fs";
9673
- import * as path12 from "path";
9674
- import { homedir as homedir4 } from "os";
9675
- var CONTEXT_FILE_SIZE_LIMIT = 100 * 1024;
9676
- var PROJECT_CONTEXT_FILES = [
9677
- "CLAUDE.local.md",
9678
- // gitignored, highest priority
9679
- "CLAUDE.md",
9680
- "AGENTS.md",
9681
- // cross-tool standard
9682
- "AI.local.md",
9683
- // gitignored
9684
- "AI.md",
9685
- "INSTRUCTIONS.md"
9686
- ];
9687
- var GLOBAL_CONTEXT_FILES = ["AI.local.md", "AI.md"];
9688
- function formatFileSize2(bytes) {
9689
- if (bytes < 1024) return `${bytes}B`;
9690
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
9691
- return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
9692
- }
9693
- function tryReadContextFile(dir, filename, source) {
9694
- const filePath = path12.join(dir, filename);
9695
- try {
9696
- const stats = fs11.lstatSync(filePath);
9697
- if (stats.isDirectory()) {
9698
- return null;
9699
- }
9700
- if (stats.isSymbolicLink()) {
9701
- return {
9702
- error: `${source === "global" ? "Global" : "Project"} ${filename} is a symlink (not allowed for security)`
9703
- };
9704
- }
9705
- if (stats.size > CONTEXT_FILE_SIZE_LIMIT) {
9706
- return {
9707
- error: `${source === "global" ? "Global" : "Project"} ${filename} exceeds 100KB limit (${formatFileSize2(stats.size)})`
9708
- };
9709
- }
9710
- const content = fs11.readFileSync(filePath, "utf-8");
9711
- return {
9712
- filename,
9713
- content,
9714
- source,
9715
- path: filePath
9716
- };
9717
- } catch (err) {
9718
- if (err.code === "ENOENT") {
9719
- return null;
9720
- }
9721
- if (err.code === "EACCES") {
9722
- return {
9723
- error: `Cannot read ${source} ${filename}: permission denied`
9724
- };
9725
- }
9726
- return {
9727
- error: `Cannot read ${source} ${filename}: ${err instanceof Error ? err.message : "Unknown error"}`
9728
- };
9729
- }
9730
- }
9731
- function findContextFile(dir, candidates, source) {
9732
- for (const filename of candidates) {
9733
- const result = tryReadContextFile(dir, filename, source);
9734
- if (result === null) {
9735
- continue;
9736
- }
9737
- if ("error" in result) {
9738
- return { result: null, error: result.error };
9739
- }
9740
- return { result, error: null };
9741
- }
9742
- return { result: null, error: null };
9743
- }
9744
- function mergeContextContent(global, project) {
9745
- if (global && project) {
9746
- return `${global.content}
9747
-
9748
- ---
9749
-
9750
- ${project.content}`;
9751
- }
9752
- if (global) {
9753
- return global.content;
9754
- }
9755
- if (project) {
9756
- return project.content;
9757
- }
9758
- return "";
9759
- }
9760
- async function loadContextFiles(projectDir) {
9761
- const errors = [];
9762
- const globalDir = path12.join(homedir4(), ".bike4mind");
9763
- const projectDirectory = projectDir || process.cwd();
9764
- const [globalResult, projectResult] = await Promise.all([
9765
- Promise.resolve(findContextFile(globalDir, GLOBAL_CONTEXT_FILES, "global")),
9766
- Promise.resolve(findContextFile(projectDirectory, PROJECT_CONTEXT_FILES, "project"))
9767
- ]);
9768
- if (globalResult.error) {
9769
- errors.push(globalResult.error);
9770
- }
9771
- if (projectResult.error) {
9772
- errors.push(projectResult.error);
9773
- }
9774
- const mergedContent = mergeContextContent(globalResult.result, projectResult.result);
9775
- return {
9776
- globalContext: globalResult.result,
9777
- projectContext: projectResult.result,
9778
- mergedContent,
9779
- errors
9780
- };
9781
- }
9782
-
9783
9731
  // ../../b4m-core/packages/mcp/dist/src/client.js
9784
9732
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
9785
9733
  import { Client as Client2 } from "@modelcontextprotocol/sdk/client/index.js";
9786
- import path13 from "path";
9734
+ import path12 from "path";
9787
9735
  import { existsSync as existsSync8, readdirSync as readdirSync3 } from "fs";
9788
9736
  var MCPClient = class {
9789
9737
  // Note: This class handles MCP server communication with repository filtering
@@ -9824,16 +9772,16 @@ var MCPClient = class {
9824
9772
  const root = process.env.INIT_CWD || process.cwd();
9825
9773
  const candidatePaths = [
9826
9774
  // When running from SST Lambda with node_modules structure (copyFiles)
9827
- path13.join(root, `node_modules/@bike4mind/mcp/dist/src/${this.serverName}/index.js`),
9775
+ path12.join(root, `node_modules/@bike4mind/mcp/dist/src/${this.serverName}/index.js`),
9828
9776
  // When running from SST Lambda deployed environment (/var/task)
9829
- path13.join(root, `b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9777
+ path12.join(root, `b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9830
9778
  // When running from SST Lambda (.sst/artifacts/mcpHandler-dev), navigate to monorepo root (3 levels up)
9831
- path13.join(root, `../../../b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9779
+ path12.join(root, `../../../b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9832
9780
  // When running from packages/client (Next.js app), navigate to monorepo root (2 levels up)
9833
- path13.join(root, `../../b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9781
+ path12.join(root, `../../b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9834
9782
  // Original paths (backward compatibility)
9835
- path13.join(root, `/b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9836
- path13.join(root, "core", "mcp", "servers", this.serverName, "dist", "index.js")
9783
+ path12.join(root, `/b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9784
+ path12.join(root, "core", "mcp", "servers", this.serverName, "dist", "index.js")
9837
9785
  ];
9838
9786
  const serverScriptPath = candidatePaths.find((p) => existsSync8(p));
9839
9787
  if (!serverScriptPath) {
@@ -10637,7 +10585,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
10637
10585
  // package.json
10638
10586
  var package_default = {
10639
10587
  name: "@bike4mind/cli",
10640
- version: "0.2.8-feat-cli-context-file-loading.17148+ce4df6add",
10588
+ version: "0.2.8-feat-cli-session-resume.17148+30840381b",
10641
10589
  type: "module",
10642
10590
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
10643
10591
  license: "UNLICENSED",
@@ -10740,10 +10688,10 @@ var package_default = {
10740
10688
  },
10741
10689
  devDependencies: {
10742
10690
  "@bike4mind/agents": "0.1.0",
10743
- "@bike4mind/common": "2.38.2-feat-cli-context-file-loading.17148+ce4df6add",
10744
- "@bike4mind/mcp": "1.20.2-feat-cli-context-file-loading.17148+ce4df6add",
10745
- "@bike4mind/services": "2.33.2-feat-cli-context-file-loading.17148+ce4df6add",
10746
- "@bike4mind/utils": "2.1.3-feat-cli-context-file-loading.17148+ce4df6add",
10691
+ "@bike4mind/common": "2.38.2-feat-cli-session-resume.17148+30840381b",
10692
+ "@bike4mind/mcp": "1.20.2-feat-cli-session-resume.17148+30840381b",
10693
+ "@bike4mind/services": "2.33.2-feat-cli-session-resume.17148+30840381b",
10694
+ "@bike4mind/utils": "2.1.3-feat-cli-session-resume.17148+30840381b",
10747
10695
  "@types/better-sqlite3": "^7.6.12",
10748
10696
  "@types/diff": "^5.0.9",
10749
10697
  "@types/jsonwebtoken": "^9.0.4",
@@ -10756,7 +10704,7 @@ var package_default = {
10756
10704
  typescript: "^5.9.3",
10757
10705
  vitest: "^3.2.4"
10758
10706
  },
10759
- gitHead: "ce4df6add3c7091ebe97f2b87790ef684c56404d"
10707
+ gitHead: "30840381b429950872f0bb0c7eb7ea4408179cff"
10760
10708
  };
10761
10709
 
10762
10710
  // src/config/constants.ts
@@ -10778,7 +10726,7 @@ var usageCache = null;
10778
10726
  function CliApp() {
10779
10727
  const { exit } = useApp();
10780
10728
  const imageRenderer = new ImageRenderer();
10781
- const [state, setState] = useState6({
10729
+ const [state, setState] = useState7({
10782
10730
  session: null,
10783
10731
  sessionStore: new SessionStore(),
10784
10732
  configStore: new ConfigStore(),
@@ -10792,11 +10740,12 @@ function CliApp() {
10792
10740
  permissionManager: null,
10793
10741
  permissionPrompt: null,
10794
10742
  trustLocationSelector: null,
10795
- rewindSelector: null
10743
+ rewindSelector: null,
10744
+ sessionSelector: null
10796
10745
  });
10797
- const [isInitialized, setIsInitialized] = useState6(false);
10798
- const [initError, setInitError] = useState6(null);
10799
- const [commandHistory, setCommandHistory] = useState6([]);
10746
+ const [isInitialized, setIsInitialized] = useState7(false);
10747
+ const [initError, setInitError] = useState7(null);
10748
+ const [commandHistory, setCommandHistory] = useState7([]);
10800
10749
  const imageStoreInitPromise = useRef(null);
10801
10750
  const setStoreSession = useCliStore((state2) => state2.setSession);
10802
10751
  const setPermissionPrompt = useCliStore((state2) => state2.setPermissionPrompt);
@@ -10837,7 +10786,7 @@ function CliApp() {
10837
10786
  process.exit(0);
10838
10787
  }, 100);
10839
10788
  }, [state.session, state.sessionStore, state.mcpManager, state.agent, state.imageStore]);
10840
- useInput5((input, key) => {
10789
+ useInput6((input, key) => {
10841
10790
  if (key.ctrl && input === "c") {
10842
10791
  const now = Date.now();
10843
10792
  if (exitTimestamp && now - exitTimestamp < EXIT_TIMEOUT_MS) {
@@ -11007,24 +10956,6 @@ function CliApp() {
11007
10956
  }
11008
10957
  const allTools = [...b4mTools, ...mcpTools];
11009
10958
  console.log(`\u2705 Total: ${allTools.length} tool(s) available`);
11010
- const projectDir = state.configStore.getProjectConfigDir();
11011
- const contextResult = await loadContextFiles(projectDir);
11012
- if (contextResult.globalContext) {
11013
- console.log(`\u{1F4C4} Global context: ${contextResult.globalContext.filename}`);
11014
- }
11015
- if (contextResult.projectContext) {
11016
- console.log(`\u{1F4C4} Project context: ${contextResult.projectContext.filename}`);
11017
- }
11018
- for (const error of contextResult.errors) {
11019
- console.log(`\u26A0\uFE0F Context file error: ${error}`);
11020
- }
11021
- const contextSection = contextResult.mergedContent ? `
11022
-
11023
- ## Project Context
11024
-
11025
- Follow these project-specific instructions:
11026
-
11027
- ${contextResult.mergedContent}` : "";
11028
10959
  const cliSystemPrompt = `You are an autonomous AI assistant with access to tools. Your job is to help users by taking action and solving problems proactively.
11029
10960
 
11030
10961
  CORE BEHAVIOR:
@@ -11054,7 +10985,7 @@ EXAMPLES:
11054
10985
  - "enhance README" \u2192 file_read \u2192 generate \u2192 create_file
11055
10986
  - "what packages installed?" \u2192 glob_files "**/package.json" \u2192 file_read
11056
10987
 
11057
- Remember: Use context from previous messages to understand follow-up questions.${contextSection}`;
10988
+ Remember: Use context from previous messages to understand follow-up questions.`;
11058
10989
  const maxIterations = config.preferences.maxIterations === null ? 999999 : config.preferences.maxIterations;
11059
10990
  const agent = new ReActAgent({
11060
10991
  userId: config.userId,
@@ -11276,15 +11207,44 @@ Project Configuration:
11276
11207
  await state.sessionStore.save(state.session);
11277
11208
  console.log(`\u2705 Session saved as "${sessionName}"`);
11278
11209
  break;
11279
- case "sessions":
11210
+ case "sessions": {
11280
11211
  const sessions = await state.sessionStore.list();
11281
- console.log("\n\u{1F4DA} Saved Sessions:\n");
11282
- sessions.forEach((s, i) => {
11283
- console.log(`${i + 1}. ${s.name} (${s.messages.length} messages)`);
11284
- console.log(` Last updated: ${new Date(s.updatedAt).toLocaleString()}`);
11285
- });
11286
- console.log("");
11212
+ if (sessions.length === 0) {
11213
+ console.log("\n\u{1F4DA} No saved sessions found.");
11214
+ console.log("\u{1F4A1} Use /save <name> to save your current session.\n");
11215
+ break;
11216
+ }
11217
+ const handleSessionSelect = async (selectedSession) => {
11218
+ setState((prev) => ({ ...prev, sessionSelector: null }));
11219
+ if (!selectedSession) {
11220
+ console.log("\u274C Session selection cancelled");
11221
+ return;
11222
+ }
11223
+ const loadedSession = await state.sessionStore.load(selectedSession.id);
11224
+ if (!loadedSession) {
11225
+ console.log(`\u274C Failed to load session: ${selectedSession.name}`);
11226
+ console.log(" The session file may be corrupted or deleted.");
11227
+ return;
11228
+ }
11229
+ await logger.initialize(loadedSession.id);
11230
+ logger.debug("=== Session Resumed ===");
11231
+ setState((prev) => ({ ...prev, session: loadedSession }));
11232
+ setStoreSession(loadedSession);
11233
+ useCliStore.getState().clearAgentSteps();
11234
+ usageCache = null;
11235
+ console.log(`
11236
+ \u2705 Session resumed: "${loadedSession.name}"`);
11237
+ console.log(
11238
+ `\u{1F4DD} ${loadedSession.messages.length} messages | \u{1F916} ${loadedSession.model} | \u{1F4CA} ${loadedSession.metadata.totalTokens.toLocaleString()} tokens
11239
+ `
11240
+ );
11241
+ };
11242
+ setState((prev) => ({
11243
+ ...prev,
11244
+ sessionSelector: { sessions, resolve: handleSessionSelect }
11245
+ }));
11287
11246
  break;
11247
+ }
11288
11248
  case "config": {
11289
11249
  setShowConfigEditor(true);
11290
11250
  break;
@@ -11725,12 +11685,12 @@ No usage data available for the last ${USAGE_DAYS} days.`);
11725
11685
  setState((prev) => ({ ...prev, config: updatedConfig }));
11726
11686
  };
11727
11687
  if (initError) {
11728
- return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React15.createElement(Text14, { color: "red", bold: true }, "\u274C Initialization Error"), /* @__PURE__ */ React15.createElement(Text14, null, initError), /* @__PURE__ */ React15.createElement(Text14, { dimColor: true }, "\n", "Tip: Run /config to set up your API keys"));
11688
+ return /* @__PURE__ */ React16.createElement(Box15, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React16.createElement(Text15, { color: "red", bold: true }, "\u274C Initialization Error"), /* @__PURE__ */ React16.createElement(Text15, null, initError), /* @__PURE__ */ React16.createElement(Text15, { dimColor: true }, "\n", "Tip: Run /config to set up your API keys"));
11729
11689
  }
11730
11690
  if (state.trustLocationSelector) {
11731
11691
  const projectDir = state.configStore.getProjectConfigDir();
11732
11692
  const inProject = projectDir !== null;
11733
- return /* @__PURE__ */ React15.createElement(
11693
+ return /* @__PURE__ */ React16.createElement(
11734
11694
  TrustLocationSelector,
11735
11695
  {
11736
11696
  inProject,
@@ -11748,7 +11708,7 @@ No usage data available for the last ${USAGE_DAYS} days.`);
11748
11708
  );
11749
11709
  }
11750
11710
  if (state.rewindSelector && state.session) {
11751
- return /* @__PURE__ */ React15.createElement(
11711
+ return /* @__PURE__ */ React16.createElement(
11752
11712
  RewindSelector,
11753
11713
  {
11754
11714
  messages: state.session.messages,
@@ -11765,9 +11725,28 @@ No usage data available for the last ${USAGE_DAYS} days.`);
11765
11725
  }
11766
11726
  );
11767
11727
  }
11728
+ if (state.sessionSelector) {
11729
+ return /* @__PURE__ */ React16.createElement(
11730
+ SessionSelector,
11731
+ {
11732
+ sessions: state.sessionSelector.sessions,
11733
+ currentSession: state.session,
11734
+ onSelect: (session) => {
11735
+ if (state.sessionSelector) {
11736
+ state.sessionSelector.resolve(session);
11737
+ }
11738
+ },
11739
+ onCancel: () => {
11740
+ if (state.sessionSelector) {
11741
+ state.sessionSelector.resolve(null);
11742
+ }
11743
+ }
11744
+ }
11745
+ );
11746
+ }
11768
11747
  if (state.showLoginFlow) {
11769
11748
  const loginApiUrl = getApiUrl(state.config?.apiConfig);
11770
- return /* @__PURE__ */ React15.createElement(
11749
+ return /* @__PURE__ */ React16.createElement(
11771
11750
  LoginFlow,
11772
11751
  {
11773
11752
  apiUrl: loginApiUrl,
@@ -11790,9 +11769,9 @@ No usage data available for the last ${USAGE_DAYS} days.`);
11790
11769
  );
11791
11770
  }
11792
11771
  if (!isInitialized) {
11793
- return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React15.createElement(Text14, null, "\u{1F680} Initializing..."));
11772
+ return /* @__PURE__ */ React16.createElement(Box15, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React16.createElement(Text15, null, "\u{1F680} Initializing..."));
11794
11773
  }
11795
- return /* @__PURE__ */ React15.createElement(
11774
+ return /* @__PURE__ */ React16.createElement(
11796
11775
  App,
11797
11776
  {
11798
11777
  onMessage: handleMessage,
@@ -11831,6 +11810,6 @@ var isDevMode = import.meta.url.includes("/src/") || process.env.NODE_ENV === "d
11831
11810
  if (isDevMode) {
11832
11811
  console.log("\u{1F527} Running in development mode (using TypeScript source)\n");
11833
11812
  }
11834
- render(/* @__PURE__ */ React15.createElement(CliApp, null), {
11813
+ render(/* @__PURE__ */ React16.createElement(CliApp, null), {
11835
11814
  exitOnCtrlC: false
11836
11815
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.2.8-feat-cli-context-file-loading.17148+ce4df6add",
3
+ "version": "0.2.8-feat-cli-session-resume.17148+30840381b",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -103,10 +103,10 @@
103
103
  },
104
104
  "devDependencies": {
105
105
  "@bike4mind/agents": "0.1.0",
106
- "@bike4mind/common": "2.38.2-feat-cli-context-file-loading.17148+ce4df6add",
107
- "@bike4mind/mcp": "1.20.2-feat-cli-context-file-loading.17148+ce4df6add",
108
- "@bike4mind/services": "2.33.2-feat-cli-context-file-loading.17148+ce4df6add",
109
- "@bike4mind/utils": "2.1.3-feat-cli-context-file-loading.17148+ce4df6add",
106
+ "@bike4mind/common": "2.38.2-feat-cli-session-resume.17148+30840381b",
107
+ "@bike4mind/mcp": "1.20.2-feat-cli-session-resume.17148+30840381b",
108
+ "@bike4mind/services": "2.33.2-feat-cli-session-resume.17148+30840381b",
109
+ "@bike4mind/utils": "2.1.3-feat-cli-session-resume.17148+30840381b",
110
110
  "@types/better-sqlite3": "^7.6.12",
111
111
  "@types/diff": "^5.0.9",
112
112
  "@types/jsonwebtoken": "^9.0.4",
@@ -119,5 +119,5 @@
119
119
  "typescript": "^5.9.3",
120
120
  "vitest": "^3.2.4"
121
121
  },
122
- "gitHead": "ce4df6add3c7091ebe97f2b87790ef684c56404d"
122
+ "gitHead": "30840381b429950872f0bb0c7eb7ea4408179cff"
123
123
  }