@ridit/lens 0.3.7 → 0.3.9

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 (96) hide show
  1. package/dist/index.mjs +105368 -274002
  2. package/package.json +13 -19
  3. package/src/colors.ts +15 -15
  4. package/src/commands/chat.tsx +32 -23
  5. package/src/commands/provider.tsx +11 -238
  6. package/src/commands/repo.tsx +66 -120
  7. package/src/commands/timeline.tsx +11 -22
  8. package/src/components/ChatView.tsx +238 -0
  9. package/src/components/Message.tsx +46 -0
  10. package/src/components/ToolCall.tsx +67 -0
  11. package/src/components/chat/ChatView.tsx +550 -0
  12. package/src/components/chat/Message.tsx +152 -0
  13. package/src/components/chat/StatusBar.tsx +214 -0
  14. package/src/components/chat/TextArea.tsx +173 -176
  15. package/src/components/provider/ApiKeyStep.tsx +207 -199
  16. package/src/components/provider/ModelStep.tsx +90 -88
  17. package/src/components/provider/ProviderSetup.tsx +331 -0
  18. package/src/components/provider/ProviderTypeStep.tsx +53 -61
  19. package/src/components/repo/StepRow.tsx +68 -69
  20. package/src/components/timeline/TimelineView.tsx +840 -0
  21. package/src/components/toolcall-utils.ts +103 -0
  22. package/src/components/watch/RunView.tsx +497 -0
  23. package/src/hooks/useChatInput.ts +49 -0
  24. package/src/hooks/useCommandHandler.ts +117 -0
  25. package/src/index.tsx +386 -139
  26. package/src/utils/git.ts +149 -155
  27. package/src/utils/repo.ts +62 -69
  28. package/src/utils/thinking.tsx +64 -0
  29. package/src/utils/watch.ts +165 -307
  30. package/tests/message.test.ts +38 -0
  31. package/tests/toolcall-utils.test.ts +111 -0
  32. package/tsconfig.json +8 -24
  33. package/CLAUDE.md +0 -50
  34. package/LENS.md +0 -48
  35. package/LICENSE +0 -21
  36. package/README.md +0 -93
  37. package/addons/README.md +0 -55
  38. package/addons/clean-cache.js +0 -48
  39. package/addons/generate-readme.js +0 -67
  40. package/addons/git-stats.js +0 -29
  41. package/addons/run-tests.js +0 -127
  42. package/src/commands/commit.tsx +0 -668
  43. package/src/commands/review.tsx +0 -294
  44. package/src/commands/run.tsx +0 -56
  45. package/src/commands/task.tsx +0 -36
  46. package/src/components/chat/ChatMessage.tsx +0 -195
  47. package/src/components/chat/ChatOverlays.tsx +0 -399
  48. package/src/components/chat/ChatRunner.tsx +0 -517
  49. package/src/components/chat/hooks/useChat.ts +0 -631
  50. package/src/components/chat/hooks/useChatInput.ts +0 -79
  51. package/src/components/chat/hooks/useCommandHandlers.ts +0 -327
  52. package/src/components/provider/ProviderPicker.tsx +0 -76
  53. package/src/components/provider/RemoveProviderStep.tsx +0 -82
  54. package/src/components/repo/DiffViewer.tsx +0 -175
  55. package/src/components/repo/FileReviewer.tsx +0 -70
  56. package/src/components/repo/FileViewer.tsx +0 -60
  57. package/src/components/repo/IssueFixer.tsx +0 -666
  58. package/src/components/repo/LensFileMenu.tsx +0 -115
  59. package/src/components/repo/NoProviderPrompt.tsx +0 -28
  60. package/src/components/repo/PreviewRunner.tsx +0 -217
  61. package/src/components/repo/RepoAnalysis.tsx +0 -534
  62. package/src/components/task/TaskRunner.tsx +0 -396
  63. package/src/components/timeline/CommitDetail.tsx +0 -272
  64. package/src/components/timeline/CommitList.tsx +0 -162
  65. package/src/components/timeline/TimelineChat.tsx +0 -166
  66. package/src/components/timeline/TimelineRunner.tsx +0 -1285
  67. package/src/components/watch/RunRunner.tsx +0 -929
  68. package/src/prompts/fewshot.ts +0 -252
  69. package/src/prompts/index.ts +0 -2
  70. package/src/prompts/system.ts +0 -285
  71. package/src/tools/chart.ts +0 -202
  72. package/src/tools/convert-image.ts +0 -312
  73. package/src/tools/files.ts +0 -253
  74. package/src/tools/git.ts +0 -603
  75. package/src/tools/index.ts +0 -17
  76. package/src/tools/pdf.ts +0 -164
  77. package/src/tools/shell.ts +0 -96
  78. package/src/tools/view-image.ts +0 -335
  79. package/src/tools/web.ts +0 -212
  80. package/src/types/chat.ts +0 -86
  81. package/src/types/config.ts +0 -20
  82. package/src/types/repo.ts +0 -54
  83. package/src/utils/addons/loadAddons.ts +0 -34
  84. package/src/utils/ai.ts +0 -321
  85. package/src/utils/chat.ts +0 -326
  86. package/src/utils/chatHistory.ts +0 -121
  87. package/src/utils/config.ts +0 -61
  88. package/src/utils/files.ts +0 -105
  89. package/src/utils/intentClassifier.ts +0 -58
  90. package/src/utils/lensfile.ts +0 -142
  91. package/src/utils/llm.ts +0 -81
  92. package/src/utils/memory.ts +0 -209
  93. package/src/utils/preview.ts +0 -119
  94. package/src/utils/stats.ts +0 -174
  95. package/src/utils/tools/builtins.ts +0 -377
  96. package/src/utils/tools/registry.ts +0 -105
@@ -1,162 +0,0 @@
1
- import React from "react";
2
- import { Box, Text } from "ink";
3
- import type { Commit } from "../../utils/git";
4
- import { ACCENT } from "../../colors";
5
-
6
- type Props = {
7
- commits: Commit[];
8
- selectedIndex: number;
9
- scrollOffset: number;
10
- visibleCount: number;
11
- searchQuery: string;
12
- width: number;
13
- };
14
-
15
- function formatRefs(refs: string): string {
16
- if (!refs) return "";
17
- return refs
18
- .split(",")
19
- .map((r) => r.trim())
20
- .filter(Boolean)
21
- .map((r) => {
22
- if (r.startsWith("HEAD -> ")) return `[${r.slice(8)}]`;
23
- if (r.startsWith("origin/")) return `[${r}]`;
24
- if (r.startsWith("tag: ")) return `<${r.slice(5)}>`;
25
- return `[${r}]`;
26
- })
27
- .join(" ");
28
- }
29
-
30
- function shortDate(dateStr: string): string {
31
- try {
32
- const d = new Date(dateStr);
33
- return d.toLocaleDateString("en-US", { month: "short", day: "numeric" });
34
- } catch {
35
- return dateStr.slice(0, 10);
36
- }
37
- }
38
-
39
- function graphSymbol(
40
- commit: Commit,
41
- index: number,
42
- ): { symbol: string; color: string } {
43
- if (commit.parents.length > 1) return { symbol: "⎇", color: "magenta" };
44
- if (index === 0) return { symbol: "◉", color: ACCENT };
45
- return { symbol: "●", color: "gray" };
46
- }
47
-
48
- export function CommitList({
49
- commits,
50
- selectedIndex,
51
- scrollOffset,
52
- visibleCount,
53
- searchQuery,
54
- width,
55
- }: Props) {
56
- const visible = commits.slice(scrollOffset, scrollOffset + visibleCount);
57
-
58
- return (
59
- <Box flexDirection="column" width={width}>
60
- {/* header */}
61
- <Box paddingX={1} marginBottom={1}>
62
- <Text color="gray" dimColor>
63
- {"─".repeat(Math.max(0, width - 2))}
64
- </Text>
65
- </Box>
66
- <Box paddingX={1} marginBottom={1}>
67
- <Text color={ACCENT} bold>
68
- {" COMMITS "}
69
- </Text>
70
- <Text color="gray" dimColor>
71
- {commits.length} total
72
- {searchQuery ? ` / ${searchQuery}` : ""}
73
- </Text>
74
- </Box>
75
-
76
- {visible.map((commit, i) => {
77
- const absoluteIndex = scrollOffset + i;
78
- const isSelected = absoluteIndex === selectedIndex;
79
- const { symbol, color } = graphSymbol(commit, absoluteIndex);
80
- const refs = formatRefs(commit.refs);
81
- const date = shortDate(commit.date);
82
-
83
- const prefixLen = 14;
84
- const maxMsg = Math.max(10, width - prefixLen - 3);
85
- const msg =
86
- commit.message.length > maxMsg
87
- ? commit.message.slice(0, maxMsg - 1) + "…"
88
- : commit.message;
89
-
90
- return (
91
- <Box key={commit.hash} paddingX={1} flexDirection="column">
92
- {i > 0 && (
93
- <Text color="gray" dimColor>
94
- {"│"}
95
- </Text>
96
- )}
97
- <Box gap={1}>
98
- <Text color={isSelected ? ACCENT : "gray"}>
99
- {isSelected ? "▶" : " "}
100
- </Text>
101
-
102
- <Text color={isSelected ? ACCENT : color}>{symbol}</Text>
103
-
104
- <Text
105
- color={isSelected ? "white" : "gray"}
106
- dimColor={!isSelected}
107
- >
108
- {commit.shortHash}
109
- </Text>
110
-
111
- <Text color="cyan" dimColor={!isSelected}>
112
- {date}
113
- </Text>
114
-
115
- <Text
116
- color={isSelected ? "white" : "gray"}
117
- bold={isSelected}
118
- wrap="truncate"
119
- >
120
- {msg}
121
- </Text>
122
- </Box>
123
-
124
- {isSelected && refs && (
125
- <Box paddingLeft={4}>
126
- <Text color="yellow">{refs}</Text>
127
- </Box>
128
- )}
129
-
130
- {isSelected && (
131
- <Box paddingLeft={4} gap={2}>
132
- <Text color="gray" dimColor>
133
- {commit.author}
134
- </Text>
135
- {commit.filesChanged > 0 && (
136
- <>
137
- <Text color="green">+{commit.insertions}</Text>
138
- <Text color="red">-{commit.deletions}</Text>
139
- <Text color="gray" dimColor>
140
- {commit.filesChanged} file
141
- {commit.filesChanged !== 1 ? "s" : ""}
142
- </Text>
143
- </>
144
- )}
145
- </Box>
146
- )}
147
- </Box>
148
- );
149
- })}
150
-
151
- <Box paddingX={1} marginTop={1}>
152
- <Text color="gray" dimColor>
153
- {scrollOffset > 0 ? "↑ more above" : ""}
154
- {scrollOffset > 0 && scrollOffset + visibleCount < commits.length
155
- ? " "
156
- : ""}
157
- {scrollOffset + visibleCount < commits.length ? "↓ more below" : ""}
158
- </Text>
159
- </Box>
160
- </Box>
161
- );
162
- }
@@ -1,166 +0,0 @@
1
- import React, { useState } from "react";
2
- import { Box, Text, Static } from "ink";
3
- import TextInput from "ink-text-input";
4
- import type { Commit } from "../../utils/git";
5
- import { summarizeTimeline } from "../../utils/git";
6
- import type { Provider } from "../../types/config";
7
- import { callChat } from "../../utils/chat";
8
- import { ACCENT } from "../../colors";
9
-
10
- type TLMessage = { role: "user" | "assistant"; content: string; type: "text" };
11
-
12
- type StaticMsg =
13
- | { kind: "user"; content: string; id: number }
14
- | { kind: "assistant"; content: string; id: number };
15
-
16
- type Props = {
17
- commits: Commit[];
18
- repoPath: string;
19
- provider: Provider | null;
20
- onExit: () => void;
21
- width: number;
22
- height: number;
23
- };
24
-
25
- const SUGGESTIONS = [
26
- "which commit changed the most files?",
27
- "who made the most commits?",
28
- "what happened last week?",
29
- "show me all merge commits",
30
- "which day had the most activity?",
31
- ];
32
-
33
- let msgId = 0;
34
-
35
- export function TimelineChat({
36
- commits,
37
- provider,
38
- onExit,
39
- width,
40
- height,
41
- }: Props) {
42
- const [committed, setCommitted] = useState<StaticMsg[]>([]);
43
- const [live, setLive] = useState<TLMessage[]>([]);
44
- const [input, setInput] = useState("");
45
- const [thinking, setThinking] = useState(false);
46
-
47
- const divider = "─".repeat(Math.max(0, width - 2));
48
-
49
- const systemPrompt = `You are a git history analyst. You have access to the full commit timeline of a repository.
50
- Answer questions about the git history concisely and accurately.
51
- Use only the data provided — never make up commits or dates.
52
- Keep answers short. Plain text only, no markdown headers.
53
-
54
- ${summarizeTimeline(commits)}`;
55
-
56
- const sendMessage = async (text: string) => {
57
- if (!text.trim() || thinking || !provider) return;
58
-
59
- const userTL: TLMessage = { role: "user", content: text, type: "text" };
60
- const nextLive = [...live, userTL];
61
-
62
- setCommitted((prev) => [
63
- ...prev,
64
- { kind: "user", content: text, id: ++msgId },
65
- ]);
66
- setLive(nextLive);
67
- setThinking(true);
68
- setInput("");
69
-
70
- try {
71
- const raw = await callChat(provider, systemPrompt, nextLive as any);
72
- const answer = typeof raw === "string" ? raw : "(no response)";
73
- const assistantTL: TLMessage = {
74
- role: "assistant",
75
- content: answer,
76
- type: "text",
77
- };
78
- setLive((prev) => [...prev, assistantTL]);
79
- setCommitted((prev) => [
80
- ...prev,
81
- { kind: "assistant", content: answer, id: ++msgId },
82
- ]);
83
- } catch (e) {
84
- const errText = `Error: ${e instanceof Error ? e.message : String(e)}`;
85
- setCommitted((prev) => [
86
- ...prev,
87
- { kind: "assistant", content: errText, id: ++msgId },
88
- ]);
89
- } finally {
90
- setThinking(false);
91
- }
92
- };
93
-
94
- return (
95
- <Box width={width} flexDirection="column">
96
- <Box paddingX={1}>
97
- <Text color="gray" dimColor>
98
- {divider}
99
- </Text>
100
- </Box>
101
- <Box paddingX={1} marginBottom={1} gap={2}>
102
- <Text color={ACCENT} bold>
103
- ASK TIMELINE
104
- </Text>
105
- <Text color="gray" dimColor>
106
- tab · esc to go back
107
- </Text>
108
- </Box>
109
-
110
- <Static items={committed}>
111
- {(msg) => (
112
- <Box key={msg.id} paddingX={1} marginBottom={1} gap={1}>
113
- <Text color={msg.kind === "user" ? "gray" : ACCENT}>
114
- {msg.kind === "user" ? ">" : "*"}
115
- </Text>
116
- <Text color="white" wrap="wrap">
117
- {msg.content}
118
- </Text>
119
- </Box>
120
- )}
121
- </Static>
122
-
123
- {thinking && (
124
- <Box paddingX={1} marginBottom={1} gap={1}>
125
- <Text color={ACCENT}>*</Text>
126
- <Text color="gray" dimColor>
127
- thinking…
128
- </Text>
129
- </Box>
130
- )}
131
-
132
- {committed.length === 0 && !thinking && (
133
- <Box paddingX={1} flexDirection="column" marginBottom={1}>
134
- <Text color="gray" dimColor>
135
- try asking:
136
- </Text>
137
- {SUGGESTIONS.map((s, i) => (
138
- <Text key={i} color="gray" dimColor>
139
- {" "}
140
- {s}
141
- </Text>
142
- ))}
143
- </Box>
144
- )}
145
-
146
- <Box paddingX={1}>
147
- <Text color="gray" dimColor>
148
- {divider}
149
- </Text>
150
- </Box>
151
- <Box paddingX={1} paddingY={1} gap={1}>
152
- <Text color={ACCENT}>{">"}</Text>
153
- <TextInput
154
- value={input}
155
- onChange={setInput}
156
- onSubmit={sendMessage}
157
- placeholder={
158
- provider
159
- ? "ask about the timeline…"
160
- : "no provider — run lens provider first"
161
- }
162
- />
163
- </Box>
164
- </Box>
165
- );
166
- }