@denizokcu/haze 0.1.1 → 0.2.0
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/CHANGELOG.md +12 -0
- package/README.md +14 -13
- package/dist/cli/commands/chat.js +1 -1
- package/dist/cli/commands/formatters.js +19 -3
- package/dist/cli/commands/streaming.js +7 -5
- package/dist/core/agent/compaction.js +3 -1
- package/dist/core/goal/completionPolicy.d.ts +2 -1
- package/dist/core/goal/completionPolicy.js +17 -10
- package/dist/core/safety/bashClassifier.d.ts +10 -0
- package/dist/core/safety/bashClassifier.js +51 -0
- package/dist/core/subagent/subagentRunner.d.ts +1 -1
- package/dist/core/subagent/subagentRunner.js +9 -8
- package/dist/core/validation/outputParser.d.ts +12 -0
- package/dist/core/validation/outputParser.js +79 -0
- package/dist/llm/hazeTools.d.ts +19 -7
- package/dist/llm/hazeTools.js +64 -25
- package/dist/llm/systemPrompt.js +72 -34
- package/dist/llm/toolResultTypes.d.ts +38 -0
- package/dist/llm/toolResultTypes.js +9 -0
- package/dist/skills/builder/SkillBuilder.js +6 -8
- package/dist/ui/components/TextInput.d.ts +2 -1
- package/dist/ui/components/TextInput.js +95 -7
- package/package.json +1 -1
|
@@ -50,7 +50,59 @@ function compactPasteBlocksForDisplay(value, blocks) {
|
|
|
50
50
|
displayValue += value.slice(offset);
|
|
51
51
|
return displayValue;
|
|
52
52
|
}
|
|
53
|
-
|
|
53
|
+
function valueCursorForDisplayCursor(blocks, displayCursor) {
|
|
54
|
+
let valueCursor = displayCursor;
|
|
55
|
+
let displayOffset = 0;
|
|
56
|
+
for (const block of [...blocks].sort((a, b) => a.start - b.start)) {
|
|
57
|
+
const placeholderLength = pastePlaceholder(block).length;
|
|
58
|
+
const displayStart = block.start - displayOffset;
|
|
59
|
+
const displayEnd = displayStart + placeholderLength;
|
|
60
|
+
if (displayCursor <= displayStart)
|
|
61
|
+
break;
|
|
62
|
+
if (displayCursor <= displayEnd)
|
|
63
|
+
return block.end;
|
|
64
|
+
const compactedLength = block.end - block.start - placeholderLength;
|
|
65
|
+
valueCursor += compactedLength;
|
|
66
|
+
displayOffset += compactedLength;
|
|
67
|
+
}
|
|
68
|
+
return valueCursor;
|
|
69
|
+
}
|
|
70
|
+
function wrapDisplayValue(displayValue, width) {
|
|
71
|
+
const wrapWidth = Math.max(1, width);
|
|
72
|
+
const lines = [];
|
|
73
|
+
let start = 0;
|
|
74
|
+
let text = '';
|
|
75
|
+
for (let index = 0; index < displayValue.length; index += 1) {
|
|
76
|
+
const char = displayValue[index];
|
|
77
|
+
if (char === '\n') {
|
|
78
|
+
lines.push({ text, start, end: index });
|
|
79
|
+
start = index + 1;
|
|
80
|
+
text = '';
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (text.length >= wrapWidth) {
|
|
84
|
+
lines.push({ text, start, end: index });
|
|
85
|
+
start = index;
|
|
86
|
+
text = '';
|
|
87
|
+
}
|
|
88
|
+
text += char;
|
|
89
|
+
}
|
|
90
|
+
lines.push({ text, start, end: displayValue.length });
|
|
91
|
+
return lines;
|
|
92
|
+
}
|
|
93
|
+
function cursorPosition(lines, displayCursor) {
|
|
94
|
+
const foundIndex = lines.findIndex((line, index) => {
|
|
95
|
+
const isLast = index === lines.length - 1;
|
|
96
|
+
if (line.start === line.end)
|
|
97
|
+
return displayCursor === line.start;
|
|
98
|
+
const nextLineStartsAfterNewline = lines[index + 1]?.start === line.end + 1;
|
|
99
|
+
return displayCursor >= line.start && (displayCursor < line.end || (nextLineStartsAfterNewline && displayCursor === line.end) || (isLast && displayCursor <= line.end));
|
|
100
|
+
});
|
|
101
|
+
const lineIndex = Math.max(0, foundIndex);
|
|
102
|
+
const line = lines[lineIndex] ?? lines[0] ?? { start: 0, end: 0 };
|
|
103
|
+
return { lineIndex, column: Math.max(0, Math.min(displayCursor - line.start, line.end - line.start)) };
|
|
104
|
+
}
|
|
105
|
+
export function TextInput({ placeholder, disabled, mask, historyItems = [], recordHistory = true, suggestions = [], suggestionMode = 'slash', submitOnEmpty = false, width = 80, onHistoryAdd, onCancel, onEscape, onSubmit }) {
|
|
54
106
|
const [value, setValue] = useState('');
|
|
55
107
|
const [cursor, setCursor] = useState(0);
|
|
56
108
|
const [pasteBlocks, setPasteBlocks] = useState([]);
|
|
@@ -59,6 +111,7 @@ export function TextInput({ placeholder, disabled, mask, historyItems = [], reco
|
|
|
59
111
|
const historyIndex = useRef(null);
|
|
60
112
|
const draft = useRef('');
|
|
61
113
|
const nextPasteId = useRef(1);
|
|
114
|
+
const preferredColumn = useRef(null);
|
|
62
115
|
useEffect(() => {
|
|
63
116
|
history.current = historyItems;
|
|
64
117
|
}, [historyItems]);
|
|
@@ -74,6 +127,7 @@ export function TextInput({ placeholder, disabled, mask, historyItems = [], reco
|
|
|
74
127
|
}
|
|
75
128
|
}, [disabled]);
|
|
76
129
|
function setInput(next, nextCursor = next.length, nextPasteBlocks = []) {
|
|
130
|
+
preferredColumn.current = null;
|
|
77
131
|
setValue(next);
|
|
78
132
|
setCursor(Math.max(0, Math.min(nextCursor, next.length)));
|
|
79
133
|
setPasteBlocks(nextPasteBlocks);
|
|
@@ -105,6 +159,24 @@ export function TextInput({ placeholder, disabled, mask, historyItems = [], reco
|
|
|
105
159
|
.slice(0, 8);
|
|
106
160
|
const activeSuggestionIndex = Math.min(selectedSuggestionIndex, Math.max(0, filteredSuggestions.length - 1));
|
|
107
161
|
const activeSuggestion = filteredSuggestions[activeSuggestionIndex];
|
|
162
|
+
const displayValue = mask ? '•'.repeat(value.length) : compactPasteBlocksForDisplay(value, pasteBlocks);
|
|
163
|
+
const displayCursor = mask ? cursor : displayCursorForValueCursor(pasteBlocks, cursor);
|
|
164
|
+
const inputWidth = Math.max(1, width - 2);
|
|
165
|
+
const wrappedLines = wrapDisplayValue(displayValue, inputWidth);
|
|
166
|
+
const currentCursorPosition = cursorPosition(wrappedLines, displayCursor);
|
|
167
|
+
function moveCursorToDisplayPosition(nextDisplayCursor) {
|
|
168
|
+
const clampedDisplayCursor = Math.max(0, Math.min(nextDisplayCursor, displayValue.length));
|
|
169
|
+
setCursor(mask ? clampedDisplayCursor : valueCursorForDisplayCursor(pasteBlocks, clampedDisplayCursor));
|
|
170
|
+
}
|
|
171
|
+
function moveCursorVertically(direction) {
|
|
172
|
+
const targetLine = wrappedLines[currentCursorPosition.lineIndex + direction];
|
|
173
|
+
if (!targetLine)
|
|
174
|
+
return false;
|
|
175
|
+
const column = preferredColumn.current ?? currentCursorPosition.column;
|
|
176
|
+
preferredColumn.current = column;
|
|
177
|
+
moveCursorToDisplayPosition(Math.min(targetLine.start + column, targetLine.end));
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
108
180
|
function submitValue(submitted, historyValue = submitted) {
|
|
109
181
|
if (recordHistory && historyValue) {
|
|
110
182
|
if (history.current[history.current.length - 1] !== historyValue)
|
|
@@ -146,10 +218,12 @@ export function TextInput({ placeholder, disabled, mask, historyItems = [], reco
|
|
|
146
218
|
return;
|
|
147
219
|
}
|
|
148
220
|
if (key.leftArrow) {
|
|
221
|
+
preferredColumn.current = null;
|
|
149
222
|
setCursor(current => Math.max(0, current - 1));
|
|
150
223
|
return;
|
|
151
224
|
}
|
|
152
225
|
if (key.rightArrow) {
|
|
226
|
+
preferredColumn.current = null;
|
|
153
227
|
setCursor(current => Math.min(value.length, current + 1));
|
|
154
228
|
return;
|
|
155
229
|
}
|
|
@@ -158,6 +232,9 @@ export function TextInput({ placeholder, disabled, mask, historyItems = [], reco
|
|
|
158
232
|
setSelectedSuggestionIndex(current => Math.max(0, current - 1));
|
|
159
233
|
return;
|
|
160
234
|
}
|
|
235
|
+
if (filteredSuggestions.length === 0 && moveCursorVertically(-1))
|
|
236
|
+
return;
|
|
237
|
+
preferredColumn.current = null;
|
|
161
238
|
if (history.current.length === 0)
|
|
162
239
|
return;
|
|
163
240
|
if (historyIndex.current === null) {
|
|
@@ -174,6 +251,9 @@ export function TextInput({ placeholder, disabled, mask, historyItems = [], reco
|
|
|
174
251
|
setSelectedSuggestionIndex(current => Math.min(filteredSuggestions.length - 1, current + 1));
|
|
175
252
|
return;
|
|
176
253
|
}
|
|
254
|
+
if (filteredSuggestions.length === 0 && moveCursorVertically(1))
|
|
255
|
+
return;
|
|
256
|
+
preferredColumn.current = null;
|
|
177
257
|
if (historyIndex.current === null)
|
|
178
258
|
return;
|
|
179
259
|
if (historyIndex.current < history.current.length - 1) {
|
|
@@ -198,10 +278,12 @@ export function TextInput({ placeholder, disabled, mask, historyItems = [], reco
|
|
|
198
278
|
return;
|
|
199
279
|
}
|
|
200
280
|
if (key.ctrl && input === 'a') {
|
|
281
|
+
preferredColumn.current = null;
|
|
201
282
|
setCursor(0);
|
|
202
283
|
return;
|
|
203
284
|
}
|
|
204
285
|
if (key.ctrl && input === 'e') {
|
|
286
|
+
preferredColumn.current = null;
|
|
205
287
|
setCursor(value.length);
|
|
206
288
|
return;
|
|
207
289
|
}
|
|
@@ -211,10 +293,16 @@ export function TextInput({ placeholder, disabled, mask, historyItems = [], reco
|
|
|
211
293
|
replaceInput(cursor, cursor, input);
|
|
212
294
|
}
|
|
213
295
|
});
|
|
214
|
-
const
|
|
215
|
-
const
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
296
|
+
const maxVisibleLines = 4;
|
|
297
|
+
const firstVisibleLine = Math.max(0, Math.min(currentCursorPosition.lineIndex - maxVisibleLines + 1, wrappedLines.length - maxVisibleLines));
|
|
298
|
+
const visibleLines = wrappedLines.slice(firstVisibleLine, firstVisibleLine + maxVisibleLines);
|
|
299
|
+
return _jsxs(Box, { flexDirection: "column", width: "100%", children: [filteredSuggestions.length > 0 && _jsx(Box, { flexDirection: "column", marginBottom: 1, children: filteredSuggestions.map((suggestion, index) => _jsxs(Text, { color: index === activeSuggestionIndex ? theme.success : theme.muted, wrap: "truncate-end", children: [index === activeSuggestionIndex ? '› ' : ' ', suggestion.value, _jsxs(Text, { color: theme.muted, children: [" ", suggestion.kind ?? 'command', suggestion.description ? ` — ${suggestion.description}` : ''] })] }, suggestion.value)) }), value.length === 0 ? _jsxs(Text, { wrap: "truncate-end", children: [_jsx(Text, { color: theme.purple, children: "\u203A " }), _jsx(Text, { inverse: true, children: " " }), _jsxs(Text, { color: theme.muted, dimColor: true, children: [" ", placeholder ?? 'Type a message...'] })] }) : visibleLines.map((line, index) => {
|
|
300
|
+
const absoluteLineIndex = firstVisibleLine + index;
|
|
301
|
+
const isCursorLine = absoluteLineIndex === currentCursorPosition.lineIndex;
|
|
302
|
+
const lineCursor = isCursorLine ? Math.max(0, Math.min(displayCursor - line.start, line.text.length)) : -1;
|
|
303
|
+
const beforeCursor = isCursorLine ? line.text.slice(0, lineCursor) : line.text;
|
|
304
|
+
const cursorChar = isCursorLine ? line.text[lineCursor] ?? ' ' : '';
|
|
305
|
+
const afterCursor = isCursorLine ? line.text.slice(lineCursor + 1) : '';
|
|
306
|
+
return _jsxs(Text, { wrap: "truncate-end", children: [_jsx(Text, { color: absoluteLineIndex === 0 ? theme.purple : theme.muted, children: absoluteLineIndex === 0 ? '› ' : ' ' }), isCursorLine ? _jsxs(_Fragment, { children: [beforeCursor, _jsx(Text, { inverse: true, children: cursorChar }), afterCursor] }) : line.text] }, `${line.start}-${absoluteLineIndex}`);
|
|
307
|
+
})] });
|
|
220
308
|
}
|