@ridit/lens 0.2.0 → 0.2.2
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/index.mjs +2075 -1493
- package/package.json +1 -1
- package/src/components/chat/ChatMessage.tsx +15 -1
- package/src/components/chat/ChatOverlays.tsx +81 -47
- package/src/components/chat/ChatRunner.tsx +553 -369
- package/src/index.tsx +3 -0
- package/src/prompts/fewshot.ts +377 -0
- package/src/prompts/index.ts +2 -0
- package/src/prompts/system.ts +167 -0
- package/src/tools/files.ts +261 -0
- package/src/tools/index.ts +13 -0
- package/src/tools/pdf.ts +106 -0
- package/src/tools/shell.ts +96 -0
- package/src/tools/web.ts +216 -0
- package/src/utils/chat.ts +114 -1463
- package/src/utils/chatHistory.ts +121 -0
- package/src/utils/files.ts +1 -0
- package/src/utils/memory.ts +137 -0
- package/src/utils/tools/builtins.ts +324 -0
- package/src/utils/tools/registry.ts +119 -0
- package/src/utils/history.ts +0 -86
package/package.json
CHANGED
|
@@ -98,6 +98,20 @@ function MessageBody({ content }: { content: string }) {
|
|
|
98
98
|
);
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
function summarizeToolContent(toolName: string, content: string): string {
|
|
102
|
+
// For write-file, extract just the path
|
|
103
|
+
if (toolName === "write-file" || toolName === "read-file") {
|
|
104
|
+
const pathMatch = content.match(/"path"\s*:\s*"([^"]+)"/);
|
|
105
|
+
if (pathMatch) return pathMatch[1]!;
|
|
106
|
+
}
|
|
107
|
+
// For changes blocks, just say what changed
|
|
108
|
+
if (content.includes('"summary"')) {
|
|
109
|
+
const summaryMatch = content.match(/"summary"\s*:\s*"([^"]+)"/);
|
|
110
|
+
if (summaryMatch) return summaryMatch[1]!;
|
|
111
|
+
}
|
|
112
|
+
return content.length > 120 ? content.slice(0, 120) + "…" : content;
|
|
113
|
+
}
|
|
114
|
+
|
|
101
115
|
export function StaticMessage({ msg }: { msg: Message }) {
|
|
102
116
|
if (msg.role === "user") {
|
|
103
117
|
return (
|
|
@@ -130,7 +144,7 @@ export function StaticMessage({ msg }: { msg: Message }) {
|
|
|
130
144
|
? msg.content
|
|
131
145
|
: msg.toolName === "search"
|
|
132
146
|
? `"${msg.content}"`
|
|
133
|
-
: msg.content;
|
|
147
|
+
: summarizeToolContent(msg.toolName, msg.content);
|
|
134
148
|
|
|
135
149
|
return (
|
|
136
150
|
<Box flexDirection="column" marginBottom={1}>
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { Box,
|
|
2
|
+
import { Box, Static, Text } from "ink";
|
|
3
3
|
import Spinner from "ink-spinner";
|
|
4
4
|
import TextInput from "ink-text-input";
|
|
5
|
-
import figures from "figures";
|
|
6
5
|
import { ACCENT } from "../../colors";
|
|
7
6
|
import { DiffViewer } from "../repo/DiffViewer";
|
|
8
7
|
import { StaticMessage } from "./ChatMessage";
|
|
@@ -25,61 +24,89 @@ function Hint({ text }: { text: string }) {
|
|
|
25
24
|
);
|
|
26
25
|
}
|
|
27
26
|
|
|
27
|
+
// ── PermissionPrompt ──────────────────────────────────────────────────────────
|
|
28
|
+
//
|
|
29
|
+
// Works with both the old explicit ToolCall union and the new generic
|
|
30
|
+
// { type, _label, _display } shape produced by the plugin system.
|
|
31
|
+
|
|
28
32
|
export function PermissionPrompt({
|
|
29
33
|
tool,
|
|
30
34
|
onDecide,
|
|
31
35
|
}: {
|
|
32
|
-
tool: ToolCall;
|
|
36
|
+
tool: ToolCall | { type: string; _label: string; _display: string };
|
|
33
37
|
onDecide: (approved: boolean) => void;
|
|
34
38
|
}) {
|
|
35
39
|
let icon: string;
|
|
36
40
|
let label: string;
|
|
37
41
|
let value: string;
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
icon = "
|
|
57
|
-
label =
|
|
58
|
-
value =
|
|
59
|
-
} else if (tool.type === "delete-file") {
|
|
60
|
-
icon = "x";
|
|
61
|
-
label = "delete";
|
|
62
|
-
value = tool.filePath;
|
|
63
|
-
} else if (tool.type === "delete-folder") {
|
|
64
|
-
icon = "X";
|
|
65
|
-
label = "delete folder";
|
|
66
|
-
value = tool.folderPath;
|
|
67
|
-
} else if (tool.type === "open-url") {
|
|
68
|
-
icon = "↗";
|
|
69
|
-
label = "open";
|
|
70
|
-
value = tool.url;
|
|
71
|
-
} else if (tool.type === "generate-pdf") {
|
|
72
|
-
icon = "P";
|
|
73
|
-
label = "pdf";
|
|
74
|
-
value = tool.filePath;
|
|
75
|
-
} else if (tool.type === "write-file") {
|
|
76
|
-
icon = "w";
|
|
77
|
-
label = "write";
|
|
78
|
-
value = `${tool.filePath} (${tool.fileContent.length} bytes)`;
|
|
43
|
+
// Generic plugin tool shape
|
|
44
|
+
if ("_label" in tool) {
|
|
45
|
+
const iconMap: Record<string, string> = {
|
|
46
|
+
run: "$",
|
|
47
|
+
fetch: "~>",
|
|
48
|
+
read: "r",
|
|
49
|
+
write: "w",
|
|
50
|
+
delete: "x",
|
|
51
|
+
"delete folder": "X",
|
|
52
|
+
open: "↗",
|
|
53
|
+
pdf: "P",
|
|
54
|
+
search: "?",
|
|
55
|
+
folder: "d",
|
|
56
|
+
grep: "/",
|
|
57
|
+
clone: "↓",
|
|
58
|
+
query: "⌗",
|
|
59
|
+
};
|
|
60
|
+
icon = iconMap[tool._label] ?? "·";
|
|
61
|
+
label = tool._label;
|
|
62
|
+
value = tool._display;
|
|
79
63
|
} else {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
64
|
+
// Legacy explicit ToolCall union
|
|
65
|
+
if (tool.type === "shell") {
|
|
66
|
+
icon = "$";
|
|
67
|
+
label = "run";
|
|
68
|
+
value = tool.command;
|
|
69
|
+
} else if (tool.type === "fetch") {
|
|
70
|
+
icon = "~>";
|
|
71
|
+
label = "fetch";
|
|
72
|
+
value = tool.url;
|
|
73
|
+
} else if (tool.type === "read-file") {
|
|
74
|
+
icon = "r";
|
|
75
|
+
label = "read";
|
|
76
|
+
value = tool.filePath;
|
|
77
|
+
} else if (tool.type === "read-folder") {
|
|
78
|
+
icon = "d";
|
|
79
|
+
label = "folder";
|
|
80
|
+
value = tool.folderPath;
|
|
81
|
+
} else if (tool.type === "grep") {
|
|
82
|
+
icon = "/";
|
|
83
|
+
label = "grep";
|
|
84
|
+
value = `${tool.pattern} ${tool.glob}`;
|
|
85
|
+
} else if (tool.type === "delete-file") {
|
|
86
|
+
icon = "x";
|
|
87
|
+
label = "delete";
|
|
88
|
+
value = tool.filePath;
|
|
89
|
+
} else if (tool.type === "delete-folder") {
|
|
90
|
+
icon = "X";
|
|
91
|
+
label = "delete folder";
|
|
92
|
+
value = tool.folderPath;
|
|
93
|
+
} else if (tool.type === "open-url") {
|
|
94
|
+
icon = "↗";
|
|
95
|
+
label = "open";
|
|
96
|
+
value = tool.url;
|
|
97
|
+
} else if (tool.type === "generate-pdf") {
|
|
98
|
+
icon = "P";
|
|
99
|
+
label = "pdf";
|
|
100
|
+
value = tool.filePath;
|
|
101
|
+
} else if (tool.type === "write-file") {
|
|
102
|
+
icon = "w";
|
|
103
|
+
label = "write";
|
|
104
|
+
value = `${tool.filePath} (${tool.fileContent.length} bytes)`;
|
|
105
|
+
} else {
|
|
106
|
+
icon = "?";
|
|
107
|
+
label = "search";
|
|
108
|
+
value = (tool as any).query ?? "";
|
|
109
|
+
}
|
|
83
110
|
}
|
|
84
111
|
|
|
85
112
|
return (
|
|
@@ -100,10 +127,12 @@ export function InputBox({
|
|
|
100
127
|
value,
|
|
101
128
|
onChange,
|
|
102
129
|
onSubmit,
|
|
130
|
+
inputKey,
|
|
103
131
|
}: {
|
|
104
132
|
value: string;
|
|
105
133
|
onChange: (v: string) => void;
|
|
106
134
|
onSubmit: (v: string) => void;
|
|
135
|
+
inputKey?: number;
|
|
107
136
|
}) {
|
|
108
137
|
return (
|
|
109
138
|
<Box
|
|
@@ -117,7 +146,12 @@ export function InputBox({
|
|
|
117
146
|
>
|
|
118
147
|
<Box gap={1}>
|
|
119
148
|
<Text color={ACCENT}>{">"}</Text>
|
|
120
|
-
<TextInput
|
|
149
|
+
<TextInput
|
|
150
|
+
key={inputKey}
|
|
151
|
+
value={value}
|
|
152
|
+
onChange={onChange}
|
|
153
|
+
onSubmit={onSubmit}
|
|
154
|
+
/>
|
|
121
155
|
</Box>
|
|
122
156
|
</Box>
|
|
123
157
|
);
|