@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,115 +0,0 @@
1
- import React from "react";
2
- import { Box, Text, useInput } from "ink";
3
- import figures from "figures";
4
- import { useState } from "react";
5
- import type { LensFile } from "../../utils/lensfile";
6
-
7
- type MenuOption =
8
- | { id: "use-cached"; label: string; description: string }
9
- | { id: "re-analyze"; label: string; description: string }
10
- | { id: "fix-issues"; label: string; description: string }
11
- | { id: "security"; label: string; description: string }
12
- | { id: "preview"; label: string; description: string };
13
-
14
- export type LensMenuChoice =
15
- | "use-cached"
16
- | "re-analyze"
17
- | "fix-issues"
18
- | "security"
19
- | "preview";
20
-
21
- const buildOptions = (lf: LensFile): MenuOption[] => {
22
- const opts: MenuOption[] = [
23
- {
24
- id: "use-cached",
25
- label: "View existing analysis",
26
- description: "Show the saved summary",
27
- },
28
- {
29
- id: "re-analyze",
30
- label: "Re-analyze",
31
- description: "Run a fresh AI analysis",
32
- },
33
- ];
34
- if (lf.suggestions.length > 0) {
35
- opts.push({
36
- id: "fix-issues",
37
- label: "Fix issues",
38
- description: `${lf.suggestions.length} issues found`,
39
- });
40
- }
41
- opts.push({
42
- id: "preview",
43
- label: "Preview repo",
44
- description: "Install deps and run dev server",
45
- });
46
- return opts;
47
- };
48
-
49
- export const LensFileMenu = ({
50
- repoPath,
51
- lensFile,
52
- onChoice,
53
- }: {
54
- repoPath: string;
55
- lensFile: LensFile;
56
- onChoice: (choice: LensMenuChoice) => void;
57
- }) => {
58
- const [index, setIndex] = useState(0);
59
- const options = buildOptions(lensFile);
60
-
61
- useInput((_, key) => {
62
- if (key.upArrow) setIndex((i) => Math.max(0, i - 1));
63
- if (key.downArrow) setIndex((i) => Math.min(options.length - 1, i + 1));
64
- if (key.return) onChoice(options[index]!.id as LensMenuChoice);
65
- });
66
-
67
- const age = (() => {
68
- try {
69
- const ms = Date.now() - new Date(lensFile.generatedAt).getTime();
70
- const mins = Math.floor(ms / 60000);
71
- const hours = Math.floor(mins / 60);
72
- const days = Math.floor(hours / 24);
73
- if (days > 0) return `${days}d ago`;
74
- if (hours > 0) return `${hours}h ago`;
75
- if (mins > 0) return `${mins}m ago`;
76
- return "just now";
77
- } catch {
78
- return "unknown";
79
- }
80
- })();
81
-
82
- return (
83
- <Box flexDirection="column" marginTop={1} gap={1}>
84
- <Box gap={2}>
85
- <Text bold color="cyan">
86
- {figures.info} LENS.md found
87
- </Text>
88
- <Text color="gray">analyzed {age}</Text>
89
- </Box>
90
- <Text color="gray" dimColor>
91
- {lensFile.overview.slice(0, 100)}
92
- {lensFile.overview.length > 100 ? "…" : ""}
93
- </Text>
94
- <Box flexDirection="column" gap={0}>
95
- {options.map((opt, i) => {
96
- const isSelected = i === index;
97
- return (
98
- <Box key={opt.id} marginLeft={1}>
99
- <Text color={isSelected ? "cyan" : "white"}>
100
- {isSelected ? figures.arrowRight : " "}
101
- {" "}
102
- <Text bold={isSelected}>{opt.label}</Text>
103
- <Text color="gray">
104
- {" "}
105
- {opt.description}
106
- </Text>
107
- </Text>
108
- </Box>
109
- );
110
- })}
111
- </Box>
112
- <Text color="gray">↑↓ navigate · enter to select</Text>
113
- </Box>
114
- );
115
- };
@@ -1,28 +0,0 @@
1
- import React from "react";
2
- import { Box, Text, useInput } from "ink";
3
- import figures from "figures";
4
-
5
- export const NoProviderPrompt = ({
6
- onAccept,
7
- onDecline,
8
- }: {
9
- onAccept: () => void;
10
- onDecline: () => void;
11
- }) => {
12
- useInput((input, key) => {
13
- if (input === "y" || input === "Y" || key.return) onAccept();
14
- if (input === "n" || input === "N" || key.escape) onDecline();
15
- });
16
-
17
- return (
18
- <Box flexDirection="column" gap={1}>
19
- <Text color="yellow">{figures.warning} No API provider configured.</Text>
20
- <Text>
21
- Run setup now?{" "}
22
- <Text color="green">[y] yes</Text>
23
- {" "}
24
- <Text color="red">[n] skip</Text>
25
- </Text>
26
- </Box>
27
- );
28
- };
@@ -1,217 +0,0 @@
1
- import React from "react";
2
- import { Box, Text, useInput } from "ink";
3
- import Spinner from "ink-spinner";
4
- import figures from "figures";
5
- import { useEffect, useState, useRef } from "react";
6
- import { ACCENT } from "../../colors";
7
- import { detectPreview, runInstall, runDev } from "../../utils/preview";
8
- import type { PreviewProcess } from "../../utils/preview";
9
-
10
- type PreviewStage =
11
- | { type: "detecting" }
12
- | { type: "not-supported" }
13
- | { type: "installing"; logs: string[] }
14
- | { type: "starting"; logs: string[] }
15
- | { type: "running"; port: number | null; logs: string[] }
16
- | { type: "error"; message: string };
17
-
18
- const MAX_LOGS = 8;
19
-
20
- export const PreviewRunner = ({
21
- repoPath,
22
- onExit,
23
- }: {
24
- repoPath: string;
25
- onExit: () => void;
26
- }) => {
27
- const [stage, setStage] = useState<PreviewStage>({ type: "detecting" });
28
- const devProcess = useRef<PreviewProcess | null>(null);
29
-
30
- useInput((_, key) => {
31
- if (key.escape || (key.ctrl && _.toLowerCase() === "c")) {
32
- devProcess.current?.kill();
33
- onExit();
34
- }
35
- });
36
-
37
- useEffect(() => {
38
- const info = detectPreview(repoPath);
39
- if (!info) {
40
- setStage({ type: "not-supported" });
41
- return;
42
- }
43
-
44
- setStage({ type: "installing", logs: [] });
45
- const installer = runInstall(repoPath, info.installCmd);
46
- const installLogs: string[] = [];
47
-
48
- installer.onLog((line) => {
49
- installLogs.push(line);
50
- setStage({ type: "installing", logs: [...installLogs].slice(-MAX_LOGS) });
51
- });
52
- installer.onError((line) => {
53
- installLogs.push(line);
54
- setStage({ type: "installing", logs: [...installLogs].slice(-MAX_LOGS) });
55
- });
56
- installer.onExit((code) => {
57
- if (code !== 0 && code !== null) {
58
- setStage({
59
- type: "error",
60
- message: `Install failed with exit code ${code}`,
61
- });
62
- return;
63
- }
64
-
65
- setStage({ type: "starting", logs: [] });
66
- const dev = runDev(repoPath, info.devCmd);
67
- devProcess.current = dev;
68
- const devLogs: string[] = [];
69
-
70
- dev.onLog((line) => {
71
- devLogs.push(line);
72
- const isRunning =
73
- line.toLowerCase().includes("localhost") ||
74
- line.toLowerCase().includes("ready") ||
75
- line.toLowerCase().includes("started") ||
76
- line.toLowerCase().includes("listening");
77
-
78
- if (isRunning) {
79
- setStage({
80
- type: "running",
81
- port: info.port,
82
- logs: [...devLogs].slice(-MAX_LOGS),
83
- });
84
- } else {
85
- setStage((s) =>
86
- s.type === "running"
87
- ? { ...s, logs: [...devLogs].slice(-MAX_LOGS) }
88
- : { type: "starting", logs: [...devLogs].slice(-MAX_LOGS) },
89
- );
90
- }
91
- });
92
-
93
- dev.onError((line) => {
94
- devLogs.push(line);
95
- setStage((s) =>
96
- s.type === "running"
97
- ? { ...s, logs: [...devLogs].slice(-MAX_LOGS) }
98
- : { type: "starting", logs: [...devLogs].slice(-MAX_LOGS) },
99
- );
100
- });
101
-
102
- dev.onExit((code) => {
103
- if (code !== 0 && code !== null) {
104
- setStage({
105
- type: "error",
106
- message: `Dev server exited with code ${code}`,
107
- });
108
- }
109
- });
110
- });
111
-
112
- return () => {
113
- devProcess.current?.kill();
114
- };
115
- }, [repoPath]);
116
-
117
- if (stage.type === "detecting") {
118
- return (
119
- <Box marginTop={1}>
120
- <Text color={ACCENT}>
121
- <Spinner />
122
- </Text>
123
- <Box marginLeft={1}>
124
- <Text>Detecting project type...</Text>
125
- </Box>
126
- </Box>
127
- );
128
- }
129
-
130
- if (stage.type === "not-supported") {
131
- return (
132
- <Box marginTop={1}>
133
- <Text color="yellow">
134
- {figures.warning} No supported run configuration found (no
135
- package.json, requirements.txt, etc.)
136
- </Text>
137
- </Box>
138
- );
139
- }
140
-
141
- if (stage.type === "installing") {
142
- return (
143
- <Box flexDirection="column" marginTop={1} gap={1}>
144
- <Box>
145
- <Text color={ACCENT}>
146
- <Spinner />
147
- </Text>
148
- <Box marginLeft={1}>
149
- <Text>Installing dependencies...</Text>
150
- </Box>
151
- </Box>
152
- <Box flexDirection="column" marginLeft={2}>
153
- {stage.logs.map((log, i) => (
154
- <Text key={i} color="gray">
155
- {log}
156
- </Text>
157
- ))}
158
- </Box>
159
- </Box>
160
- );
161
- }
162
-
163
- if (stage.type === "starting") {
164
- return (
165
- <Box flexDirection="column" marginTop={1} gap={1}>
166
- <Box>
167
- <Text color={ACCENT}>
168
- <Spinner />
169
- </Text>
170
- <Box marginLeft={1}>
171
- <Text>Starting dev server...</Text>
172
- </Box>
173
- </Box>
174
- <Box flexDirection="column" marginLeft={2}>
175
- {stage.logs.map((log, i) => (
176
- <Text key={i} color="gray">
177
- {log}
178
- </Text>
179
- ))}
180
- </Box>
181
- </Box>
182
- );
183
- }
184
-
185
- if (stage.type === "running") {
186
- return (
187
- <Box flexDirection="column" marginTop={1} gap={1}>
188
- <Box gap={1}>
189
- <Text color="green">{figures.tick} Dev server running</Text>
190
- {stage.port && (
191
- <Text color="cyan">→ http://localhost:{stage.port}</Text>
192
- )}
193
- </Box>
194
- <Box flexDirection="column" marginLeft={2}>
195
- {stage.logs.map((log, i) => (
196
- <Text key={i} color="gray">
197
- {log}
198
- </Text>
199
- ))}
200
- </Box>
201
- <Text color="gray">ctrl+c or esc to stop</Text>
202
- </Box>
203
- );
204
- }
205
-
206
- if (stage.type === "error") {
207
- return (
208
- <Box marginTop={1}>
209
- <Text color="red">
210
- {figures.cross} {stage.message}
211
- </Text>
212
- </Box>
213
- );
214
- }
215
-
216
- return null;
217
- };