klyro 0.1.53 → 0.1.55

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 (50) hide show
  1. package/dist/agent/anthropic-adapter.js +22 -2
  2. package/dist/agent/registry.js +11 -1
  3. package/dist/agent/retry.d.ts +5 -0
  4. package/dist/agent/retry.js +28 -1
  5. package/dist/agent/runtime.d.ts +2 -0
  6. package/dist/agent/runtime.js +48 -35
  7. package/dist/chat.js +2 -2
  8. package/dist/checkpoints/store.js +86 -7
  9. package/dist/cli/config.js +13 -1
  10. package/dist/cli/repl.js +200 -36
  11. package/dist/cli/run.js +88 -69
  12. package/dist/context/klyro-md.d.ts +5 -0
  13. package/dist/context/klyro-md.js +28 -6
  14. package/dist/context/tokenizer.js +8 -1
  15. package/dist/index.js +49 -14
  16. package/dist/persistence/session.d.ts +2 -0
  17. package/dist/persistence/session.js +11 -5
  18. package/dist/persistence/store.d.ts +7 -0
  19. package/dist/persistence/store.js +77 -28
  20. package/dist/policy/engine.d.ts +10 -1
  21. package/dist/policy/engine.js +33 -2
  22. package/dist/tools/fs/apply-patch.d.ts +16 -1
  23. package/dist/tools/fs/apply-patch.js +163 -75
  24. package/dist/tools/fs/edit-file.d.ts +13 -0
  25. package/dist/tools/fs/edit-file.js +96 -54
  26. package/dist/tools/fs/list-dir.d.ts +2 -0
  27. package/dist/tools/fs/list-dir.js +7 -5
  28. package/dist/tools/fs/multi-edit.js +12 -1
  29. package/dist/tools/fs/read-file.js +1 -1
  30. package/dist/tools/fs/read-history.d.ts +2 -2
  31. package/dist/tools/fs/read-history.js +39 -7
  32. package/dist/tools/fs/write-file.js +1 -1
  33. package/dist/tools/normalize.js +11 -1
  34. package/dist/tools/shell/background.d.ts +5 -0
  35. package/dist/tools/shell/background.js +29 -0
  36. package/dist/tools/shell/shell-exec.d.ts +9 -0
  37. package/dist/tools/shell/shell-exec.js +54 -8
  38. package/dist/tools/verify/run-verify.js +2 -2
  39. package/dist/tui/app.js +10 -5
  40. package/dist/tui/app.test.js +42 -0
  41. package/dist/tui/approval.d.ts +1 -1
  42. package/dist/tui/approval.js +20 -5
  43. package/dist/tui/diff.d.ts +5 -19
  44. package/dist/tui/diff.js +9 -25
  45. package/dist/tui/status.d.ts +4 -8
  46. package/dist/tui/status.js +8 -17
  47. package/dist/tui/transcript.d.ts +13 -20
  48. package/dist/tui/transcript.js +9 -74
  49. package/dist/verification/engine.js +4 -4
  50. package/package.json +1 -1
@@ -1,74 +1,9 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Text, Box } from 'ink';
3
- import Spinner from 'ink-spinner';
4
- import { DiffView } from './diff.js';
5
- export function Transcript({ items }) {
6
- return (_jsx(Box, { flexDirection: "column", flexGrow: 1, paddingX: 1, children: items.length === 0 ? (_jsx(Text, { color: "gray", dimColor: true, children: "Type a prompt or /help for commands." })) : items.map((item) => (_jsx(TranscriptRow, { item: item }, item.id))) }));
7
- }
8
- /** Build a one-line summary of a tool call from its args JSON. */
9
- function summarizeTool(name, args) {
10
- if (!args || args === '{}')
11
- return '';
12
- let parsed = null;
13
- try {
14
- parsed = JSON.parse(args);
15
- }
16
- catch {
17
- return args.slice(0, 80);
18
- }
19
- switch (name) {
20
- case 'read_file':
21
- case 'write_file':
22
- case 'edit_file':
23
- return typeof parsed.path === 'string' ? parsed.path : '';
24
- case 'shell_exec':
25
- return typeof parsed.command === 'string' ? parsed.command : '';
26
- case 'search_files':
27
- case 'grep': {
28
- const q = parsed.query ?? parsed.pattern;
29
- return typeof q === 'string' ? `"${q}"` : '';
30
- }
31
- case 'list_directory':
32
- return typeof parsed.path === 'string' ? parsed.path : '';
33
- case 'git_status':
34
- case 'git_diff':
35
- return '';
36
- default:
37
- return '';
38
- }
39
- }
40
- function TranscriptRow({ item }) {
41
- if (item.kind === 'text') {
42
- const color = item.role === 'user' ? 'blue' : undefined;
43
- return (_jsx(Box, { marginY: 0, children: _jsxs(Text, { color: color, children: [item.role === 'user' ? '> ' : '', item.text] }) }));
44
- }
45
- if (item.kind === 'tool') {
46
- return _jsx(ToolCard, { item: item });
47
- }
48
- if (item.kind === 'policy') {
49
- const color = item.action === 'allow' ? 'green' : item.action === 'deny' ? 'red' : 'yellow';
50
- return (_jsxs(Box, { paddingLeft: 2, children: [_jsx(Text, { color: "gray", children: "[policy] " }), _jsx(Text, { color: color, children: item.action }), _jsxs(Text, { color: "gray", children: [" ", item.name] }), item.reason ? _jsxs(Text, { color: "gray", children: [" \u2014 ", item.reason] }) : null] }));
51
- }
52
- if (item.kind === 'file_changed') {
53
- const color = item.op === 'deleted' ? 'red' : item.op === 'created' ? 'green' : 'yellow';
54
- const glyph = item.op === 'created' ? '+' : item.op === 'deleted' ? '-' : '~';
55
- return (_jsx(Box, { paddingLeft: 2, children: _jsxs(Text, { color: color, children: ["[", glyph, " ", item.op, "] ", item.path] }) }));
56
- }
57
- if (item.kind === 'error') {
58
- return (_jsx(Box, { paddingLeft: 2, children: _jsxs(Text, { color: "red", children: ["[error] ", item.message] }) }));
59
- }
60
- if (item.kind === 'diff') {
61
- return _jsx(DiffView, { hunks: item.hunks, summary: item.summary });
62
- }
63
- return null;
64
- }
65
- function ToolCard({ item }) {
66
- const summary = summarizeTool(item.name, item.args);
67
- const borderColor = item.status === 'error' ? 'red' : item.status === 'running' ? 'cyan' : 'gray';
68
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: borderColor, marginY: 1, paddingX: 1, children: [_jsxs(Box, { children: [_jsx(Text, { color: "gray", children: "\u250C\u2500 " }), _jsx(Text, { bold: true, children: item.name }), item.status === 'running' ? (_jsxs(Text, { color: "cyan", children: [" ", _jsx(Spinner, { type: "dots" }), " running"] })) : item.status === 'error' ? (_jsx(Text, { color: "red", children: " \u2717 error" })) : (_jsxs(Text, { color: "green", children: [" \u2713 ", item.latencyMs ?? 0, "ms"] })), _jsx(Text, { color: "gray", children: " \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" })] }), summary ? (_jsx(Box, { paddingLeft: 2, children: _jsx(Text, { children: truncate(summary, 200) }) })) : null, item.status !== 'running' && item.result ? (_jsx(Box, { paddingLeft: 2, flexDirection: "column", children: _jsxs(Text, { color: item.isError ? 'red' : 'gray', children: [item.isError ? '✗ ' : '→ ', truncate(item.result, 400)] }) })) : null, _jsx(Box, { children: _jsx(Text, { color: "gray", children: "\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }) })] }));
69
- }
70
- function truncate(s, max) {
71
- if (s.length <= max)
72
- return s;
73
- return s.slice(0, max) + '…';
74
- }
1
+ /**
2
+ * Transcript item types — the scrollable entry list owned by App.
3
+ *
4
+ * NOTE: the old Transcript/TranscriptRow/ToolCard presentational components
5
+ * were removed: App renders entries inline (grouped tool activity), and the
6
+ * standalone components' tests gave false coverage for UI nobody sees.
7
+ * Only the item types remain.
8
+ */
9
+ export {};
@@ -18,7 +18,10 @@ function appendCapped(current, chunk) {
18
18
  return next.length > MAX_VERIFY_BYTES ? next.slice(0, MAX_VERIFY_BYTES) + '\n... [truncated]' : next;
19
19
  }
20
20
  // SEC-004: denylist for dangerous patterns in verify commands.
21
- // Reuses the same patterns as shell-exec.ts DANGEROUS_PATTERNS.
21
+ // Destructive-only: the verify command comes from CLI flags, project config,
22
+ // or auto-detected package scripts (never model-controlled), so shell
23
+ // metacharacters ($(), backticks, pipes) that are legitimate in test scripts
24
+ // are allowed here — unlike shell_exec's model-facing denylist.
22
25
  const DANGEROUS_VERIFY_PATTERNS = [
23
26
  { pattern: /rm\s+-rf?\s+\//, reason: 'recursive delete at filesystem root' },
24
27
  { pattern: /rm\s+-rf?\s+\/\/+/, reason: 'recursive delete at filesystem root (//)' },
@@ -39,9 +42,6 @@ const DANGEROUS_VERIFY_PATTERNS = [
39
42
  { pattern: /curl.*\|\s*(sh|bash|zsh|python|python3|perl|ruby|php)/i, reason: 'curl|sh to unknown host' },
40
43
  { pattern: /wget.*\|\s*(sh|bash|python|perl|ruby)/i, reason: 'wget|sh pipe' },
41
44
  { pattern: /rm\s+-rf\s+--no-preserve-root\s+\//, reason: 'recursive delete --no-preserve-root' },
42
- { pattern: /\$\(/, reason: 'command substitution $()' },
43
- { pattern: /`[^`]*`/, reason: 'command substitution via backticks' },
44
- { pattern: /\|\s*bash\b|\|\s*sh\b/, reason: 'pipe to shell' },
45
45
  { pattern: /;\s*rm\s+-rf/, reason: 'chained rm -rf' },
46
46
  { pattern: /&&\s*rm\s+-rf/, reason: 'chained rm -rf' },
47
47
  { pattern: /\|\|\s*rm\s+-rf/, reason: 'chained rm -rf' },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "klyro",
3
- "version": "0.1.53",
3
+ "version": "0.1.55",
4
4
  "description": "Klyro \u2014 autonomous coding harness CLI that streams from any OpenAI-compatible or Anthropic LLM endpoint.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",