clairo 1.0.5 → 1.0.6

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/cli.js +135 -5
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1961,30 +1961,128 @@ import { TitledBox as TitledBox6 } from "@mishieck/ink-titled-box";
1961
1961
  import { Box as Box13, Text as Text13, useInput as useInput11 } from "ink";
1962
1962
  import { ScrollView as ScrollView2 } from "ink-scroll-view";
1963
1963
  import TextInput2 from "ink-text-input";
1964
+
1965
+ // src/lib/claude/api.ts
1966
+ import { exec as exec4 } from "child_process";
1967
+ function runClaudePrompt(prompt) {
1968
+ let childProcess = null;
1969
+ let cancelled = false;
1970
+ const promise = new Promise((resolve) => {
1971
+ const escapedPrompt = prompt.replace(/'/g, "'\\''").replace(/\n/g, "\\n");
1972
+ const command = `claude -p $'${escapedPrompt}' --output-format json < /dev/null`;
1973
+ childProcess = exec4(command, { maxBuffer: 10 * 1024 * 1024 }, (error, stdout, stderr) => {
1974
+ if (cancelled) {
1975
+ resolve({
1976
+ success: false,
1977
+ error: "Cancelled",
1978
+ errorType: "execution_error"
1979
+ });
1980
+ return;
1981
+ }
1982
+ if (error) {
1983
+ if (error.message.includes("command not found") || error.message.includes("ENOENT") || error.code === "ENOENT") {
1984
+ resolve({
1985
+ success: false,
1986
+ error: "Claude CLI not installed. Run: npm install -g @anthropic-ai/claude-code",
1987
+ errorType: "not_installed"
1988
+ });
1989
+ return;
1990
+ }
1991
+ resolve({
1992
+ success: false,
1993
+ error: (stderr == null ? void 0 : stderr.trim()) || error.message,
1994
+ errorType: "execution_error"
1995
+ });
1996
+ return;
1997
+ }
1998
+ if (!(stdout == null ? void 0 : stdout.trim())) {
1999
+ resolve({
2000
+ success: false,
2001
+ error: (stderr == null ? void 0 : stderr.trim()) || "Claude returned empty response",
2002
+ errorType: "execution_error"
2003
+ });
2004
+ return;
2005
+ }
2006
+ try {
2007
+ const json = JSON.parse(stdout.trim());
2008
+ if (json.is_error) {
2009
+ resolve({
2010
+ success: false,
2011
+ error: json.result || "Claude returned an error",
2012
+ errorType: "execution_error"
2013
+ });
2014
+ return;
2015
+ }
2016
+ resolve({
2017
+ success: true,
2018
+ data: json.result || stdout.trim()
2019
+ });
2020
+ } catch {
2021
+ resolve({
2022
+ success: true,
2023
+ data: stdout.trim()
2024
+ });
2025
+ }
2026
+ });
2027
+ });
2028
+ const cancel = () => {
2029
+ cancelled = true;
2030
+ if (childProcess) {
2031
+ childProcess.kill("SIGTERM");
2032
+ }
2033
+ };
2034
+ return { promise, cancel };
2035
+ }
2036
+ function generateStandupNotes(logContent) {
2037
+ const prompt = `You are helping a developer prepare standup notes. Based on the following log entries, generate concise standup notes that summarize what was accomplished.
2038
+
2039
+ Format the output as bullet points grouped by category (e.g., Features, Bug Fixes, Refactoring, etc.). Keep it brief and professional.
2040
+
2041
+ Log entries:
2042
+ ${logContent}
2043
+
2044
+ Generate the standup notes:`;
2045
+ return runClaudePrompt(prompt);
2046
+ }
2047
+
2048
+ // src/components/logs/LogViewerBox.tsx
1964
2049
  import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
1965
2050
  function LogViewerBox({ date, content, isFocused, onRefresh, onLogCreated }) {
1966
2051
  const scrollRef = useRef3(null);
1967
2052
  const [isInputMode, setIsInputMode] = useState8(false);
1968
2053
  const [inputValue, setInputValue] = useState8("");
2054
+ const [isGeneratingStandup, setIsGeneratingStandup] = useState8(false);
2055
+ const [standupResult, setStandupResult] = useState8(null);
2056
+ const claudeProcessRef = useRef3(null);
1969
2057
  const title = "[6] Log Content";
1970
2058
  const borderColor = isFocused ? "yellow" : void 0;
1971
2059
  const displayTitle = date ? `${title} - ${date}.md` : title;
1972
2060
  useInput11(
1973
2061
  (input, key) => {
1974
- var _a, _b;
2062
+ var _a, _b, _c;
1975
2063
  if (key.escape && isInputMode) {
1976
2064
  setIsInputMode(false);
1977
2065
  setInputValue("");
1978
2066
  return;
1979
2067
  }
1980
- if (isInputMode) {
2068
+ if (key.escape && isGeneratingStandup) {
2069
+ (_a = claudeProcessRef.current) == null ? void 0 : _a.cancel();
2070
+ claudeProcessRef.current = null;
2071
+ setIsGeneratingStandup(false);
2072
+ return;
2073
+ }
2074
+ if (key.escape && standupResult) {
2075
+ setStandupResult(null);
2076
+ return;
2077
+ }
2078
+ if (isInputMode || standupResult) {
1981
2079
  return;
1982
2080
  }
1983
2081
  if (key.upArrow || input === "k") {
1984
- (_a = scrollRef.current) == null ? void 0 : _a.scrollBy(-1);
2082
+ (_b = scrollRef.current) == null ? void 0 : _b.scrollBy(-1);
1985
2083
  }
1986
2084
  if (key.downArrow || input === "j") {
1987
- (_b = scrollRef.current) == null ? void 0 : _b.scrollBy(1);
2085
+ (_c = scrollRef.current) == null ? void 0 : _c.scrollBy(1);
1988
2086
  }
1989
2087
  if (input === "e" && date) {
1990
2088
  openLogInEditor(date);
@@ -2003,6 +2101,21 @@ function LogViewerBox({ date, content, isFocused, onRefresh, onLogCreated }) {
2003
2101
  if (input === "r") {
2004
2102
  onRefresh();
2005
2103
  }
2104
+ if (input === "c" && date && content && !isGeneratingStandup) {
2105
+ setIsGeneratingStandup(true);
2106
+ setStandupResult(null);
2107
+ const process2 = generateStandupNotes(content);
2108
+ claudeProcessRef.current = process2;
2109
+ process2.promise.then((result) => {
2110
+ claudeProcessRef.current = null;
2111
+ setIsGeneratingStandup(false);
2112
+ if (result.success) {
2113
+ setStandupResult({ type: "success", message: result.data });
2114
+ } else if (result.error !== "Cancelled") {
2115
+ setStandupResult({ type: "error", message: result.error });
2116
+ }
2117
+ });
2118
+ }
2006
2119
  },
2007
2120
  { isActive: isFocused }
2008
2121
  );
@@ -2037,7 +2150,23 @@ ${value.trim()}
2037
2150
  onChange: (val) => setInputValue(val.replace(/[\r\n]/g, "")),
2038
2151
  onSubmit: handleInputSubmit
2039
2152
  }
2040
- ) }) })
2153
+ ) }) }),
2154
+ isGeneratingStandup && /* @__PURE__ */ jsx13(TitledBox6, { borderStyle: "round", titles: ["Standup Notes"], borderColor: "yellow", children: /* @__PURE__ */ jsxs13(Box13, { paddingX: 1, flexDirection: "column", children: [
2155
+ /* @__PURE__ */ jsx13(Text13, { color: "yellow", children: "Generating standup notes..." }),
2156
+ /* @__PURE__ */ jsx13(Text13, { dimColor: true, children: "Press Esc to cancel" })
2157
+ ] }) }),
2158
+ standupResult && /* @__PURE__ */ jsx13(
2159
+ TitledBox6,
2160
+ {
2161
+ borderStyle: "round",
2162
+ titles: ["Standup Notes"],
2163
+ borderColor: standupResult.type === "error" ? "red" : "green",
2164
+ children: /* @__PURE__ */ jsxs13(Box13, { paddingX: 1, flexDirection: "column", children: [
2165
+ standupResult.type === "error" ? /* @__PURE__ */ jsx13(Text13, { color: "red", children: standupResult.message }) : /* @__PURE__ */ jsx13(Markdown, { children: standupResult.message }),
2166
+ /* @__PURE__ */ jsx13(Text13, { dimColor: true, children: "Press Esc to dismiss" })
2167
+ ] })
2168
+ }
2169
+ )
2041
2170
  ] });
2042
2171
  }
2043
2172
 
@@ -2060,6 +2189,7 @@ function LogsView({ isFocused, onKeybindingsChange, refreshKey, focusedBox, onFo
2060
2189
  bindings.push({ key: "i", label: "Add Entry" });
2061
2190
  bindings.push({ key: "e", label: "Edit" });
2062
2191
  bindings.push({ key: "n", label: "New Log", color: "green" });
2192
+ bindings.push({ key: "c", label: "Standup" });
2063
2193
  bindings.push({ key: "r", label: "Refresh" });
2064
2194
  }
2065
2195
  onKeybindingsChange == null ? void 0 : onKeybindingsChange(bindings);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clairo",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",