lonny-agent 0.2.3 → 0.2.6

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 (129) hide show
  1. package/README.md +326 -326
  2. package/dist/agent/index.js +1 -1
  3. package/dist/agent/index.js.map +1 -1
  4. package/dist/agent/llm.d.ts +4 -0
  5. package/dist/agent/llm.d.ts.map +1 -1
  6. package/dist/agent/project.d.ts +26 -0
  7. package/dist/agent/project.d.ts.map +1 -0
  8. package/dist/agent/project.js +303 -0
  9. package/dist/agent/project.js.map +1 -0
  10. package/dist/agent/prompt-builder.d.ts +1 -1
  11. package/dist/agent/prompt-builder.d.ts.map +1 -1
  12. package/dist/agent/prompt-builder.js +22 -13
  13. package/dist/agent/prompt-builder.js.map +1 -1
  14. package/dist/agent/providers/anthropic.d.ts.map +1 -1
  15. package/dist/agent/providers/anthropic.js +20 -2
  16. package/dist/agent/providers/anthropic.js.map +1 -1
  17. package/dist/agent/providers/google.d.ts.map +1 -1
  18. package/dist/agent/providers/google.js +1 -1
  19. package/dist/agent/providers/google.js.map +1 -1
  20. package/dist/agent/providers/ollama.d.ts.map +1 -1
  21. package/dist/agent/providers/ollama.js +2 -1
  22. package/dist/agent/providers/ollama.js.map +1 -1
  23. package/dist/agent/providers/openai.d.ts.map +1 -1
  24. package/dist/agent/providers/openai.js +63 -3
  25. package/dist/agent/providers/openai.js.map +1 -1
  26. package/dist/agent/session.d.ts +8 -2
  27. package/dist/agent/session.d.ts.map +1 -1
  28. package/dist/agent/session.js +250 -153
  29. package/dist/agent/session.js.map +1 -1
  30. package/dist/config/index.d.ts.map +1 -1
  31. package/dist/config/index.js +7 -1
  32. package/dist/config/index.js.map +1 -1
  33. package/dist/tools/__tests__/bash.test.js +1 -1
  34. package/dist/tools/__tests__/bash.test.js.map +1 -1
  35. package/dist/tools/__tests__/edit.test.js +875 -371
  36. package/dist/tools/__tests__/edit.test.js.map +1 -1
  37. package/dist/tools/__tests__/grep.test.js +32 -0
  38. package/dist/tools/__tests__/grep.test.js.map +1 -1
  39. package/dist/tools/__tests__/sed.test.d.ts +2 -0
  40. package/dist/tools/__tests__/sed.test.d.ts.map +1 -0
  41. package/dist/tools/__tests__/sed.test.js +228 -0
  42. package/dist/tools/__tests__/sed.test.js.map +1 -0
  43. package/dist/tools/bash.d.ts.map +1 -1
  44. package/dist/tools/bash.js +83 -10
  45. package/dist/tools/bash.js.map +1 -1
  46. package/dist/tools/edit.d.ts +58 -0
  47. package/dist/tools/edit.d.ts.map +1 -1
  48. package/dist/tools/edit.js +366 -149
  49. package/dist/tools/edit.js.map +1 -1
  50. package/dist/tools/grep.d.ts.map +1 -1
  51. package/dist/tools/grep.js +54 -30
  52. package/dist/tools/grep.js.map +1 -1
  53. package/dist/tools/read.d.ts +6 -0
  54. package/dist/tools/read.d.ts.map +1 -1
  55. package/dist/tools/read.js +42 -15
  56. package/dist/tools/read.js.map +1 -1
  57. package/dist/tools/registry.d.ts +0 -6
  58. package/dist/tools/registry.d.ts.map +1 -1
  59. package/dist/tools/registry.js +2 -33
  60. package/dist/tools/registry.js.map +1 -1
  61. package/dist/tools/sed.d.ts +4 -0
  62. package/dist/tools/sed.d.ts.map +1 -0
  63. package/dist/tools/sed.js +121 -0
  64. package/dist/tools/sed.js.map +1 -0
  65. package/dist/tools/write_plan.d.ts +1 -1
  66. package/dist/tools/write_plan.d.ts.map +1 -1
  67. package/dist/tools/write_plan.js +14 -4
  68. package/dist/tools/write_plan.js.map +1 -1
  69. package/dist/tui/index.d.ts.map +1 -1
  70. package/dist/tui/index.js +5 -4
  71. package/dist/tui/index.js.map +1 -1
  72. package/dist/web/index.d.ts.map +1 -1
  73. package/dist/web/index.js +30 -7
  74. package/dist/web/index.js.map +1 -1
  75. package/dist/web/public/app.js +5 -855
  76. package/dist/web/public/confirm.js +70 -0
  77. package/dist/web/public/index.html +121 -120
  78. package/dist/web/public/input.js +107 -0
  79. package/dist/web/public/messages.js +395 -0
  80. package/dist/web/public/sidebar.js +82 -0
  81. package/dist/web/public/state.js +72 -0
  82. package/dist/web/public/style.css +996 -949
  83. package/dist/web/public/utils.js +37 -0
  84. package/dist/web/public/websocket.js +267 -0
  85. package/dist/web/public/ws.js +19 -0
  86. package/dist/web/session-bridge.d.ts.map +1 -1
  87. package/dist/web/session-bridge.js +3 -7
  88. package/dist/web/session-bridge.js.map +1 -1
  89. package/package.json +55 -54
  90. package/scripts/copy-native.mjs +24 -0
  91. package/scripts/copy-web.mjs +15 -0
  92. package/src/agent/index.ts +25 -25
  93. package/src/agent/llm.ts +4 -0
  94. package/src/agent/project.ts +366 -0
  95. package/src/agent/prompt-builder.ts +23 -13
  96. package/src/agent/providers/anthropic.ts +179 -172
  97. package/src/agent/providers/google.ts +210 -211
  98. package/src/agent/providers/ollama.ts +186 -182
  99. package/src/agent/providers/openai.ts +73 -5
  100. package/src/agent/session.ts +275 -153
  101. package/src/config/index.ts +342 -335
  102. package/src/tools/__tests__/bash.test.ts +1 -1
  103. package/src/tools/__tests__/edit.test.ts +981 -385
  104. package/src/tools/__tests__/grep.test.ts +35 -0
  105. package/src/tools/bash.ts +97 -11
  106. package/src/tools/edit.ts +414 -154
  107. package/src/tools/git.ts +76 -76
  108. package/src/tools/grep.ts +57 -30
  109. package/src/tools/read.ts +61 -25
  110. package/src/tools/registry.ts +231 -265
  111. package/src/tools/write_plan.ts +21 -5
  112. package/src/tui/index.ts +786 -785
  113. package/src/web/index.ts +29 -7
  114. package/src/web/public/app.js +5 -855
  115. package/src/web/public/confirm.js +70 -0
  116. package/src/web/public/index.html +121 -120
  117. package/src/web/public/input.js +107 -0
  118. package/src/web/public/messages.js +395 -0
  119. package/src/web/public/sidebar.js +82 -0
  120. package/src/web/public/state.js +72 -0
  121. package/src/web/public/style.css +996 -949
  122. package/src/web/public/utils.js +37 -0
  123. package/src/web/public/websocket.js +267 -0
  124. package/src/web/public/ws.js +19 -0
  125. package/src/web/session-bridge.ts +193 -194
  126. package/.kilo/plans/1780064105789-mighty-pixel.md +0 -171
  127. package/.kilo/plans/1780293725888-quick-wizard.md +0 -62
  128. package/.lonny/plan-web-cwd-status.md +0 -38
  129. package/src/tools/exec.ts +0 -348
@@ -16,6 +16,12 @@ describe('grep tool', () => {
16
16
  fs.writeFileSync(path.join(tmpDir, 'world.js'), 'const y = 2\nconsole.log("world")\n')
17
17
  fs.mkdirSync(path.join(tmpDir, 'sub'))
18
18
  fs.writeFileSync(path.join(tmpDir, 'sub', 'deep.ts'), 'const z = 3\n// TODO: implement\n')
19
+ // Additional files for include glob and path parameter tests
20
+ fs.mkdirSync(path.join(tmpDir, 'lib'))
21
+ fs.writeFileSync(path.join(tmpDir, 'lib', 'index.ts'), 'export const version = 1\n')
22
+ fs.writeFileSync(path.join(tmpDir, 'lib', 'helper.tsx'), 'export function helper() {}\n')
23
+ fs.writeFileSync(path.join(tmpDir, 'lib', 'config.tsx'), 'export const config = {}\n')
24
+ fs.writeFileSync(path.join(tmpDir, 'lib', 'readme.md'), '# no code here\n')
19
25
  })
20
26
 
21
27
  afterAll(() => {
@@ -44,6 +50,28 @@ describe('grep tool', () => {
44
50
  expect(result.output).not.toContain('world.js')
45
51
  })
46
52
 
53
+ it('filters by brace-enclosed glob pattern', async () => {
54
+ const result = await tool().execute({ pattern: 'export', include: '*.{ts,tsx}' })
55
+ expect(result.success).toBe(true)
56
+ expect(result.output).toContain('lib/index.ts')
57
+ expect(result.output).toContain('lib/helper.tsx')
58
+ expect(result.output).toContain('lib/config.tsx')
59
+ // Should NOT match hello.ts (it matches 'export' but is in root, not filtered out)
60
+ // All .ts and .tsx files should be included, including hello.ts which has 'export'
61
+ })
62
+
63
+ it('filters by include with path parameter', async () => {
64
+ const result = await tool().execute({
65
+ pattern: 'export',
66
+ include: '*.ts',
67
+ path: tmpDir + '/lib',
68
+ })
69
+ expect(result.success).toBe(true)
70
+ expect(result.output).toContain('lib/index.ts')
71
+ // helper.tsx and config.tsx are .tsx, not .ts, so should not appear
72
+ expect(result.output).not.toContain('lib/helper.tsx')
73
+ })
74
+
47
75
  it('rejects missing pattern argument', async () => {
48
76
  const result = await tool().execute({})
49
77
  expect(result.success).toBe(false)
@@ -55,4 +83,11 @@ describe('grep tool', () => {
55
83
  expect(result.success).toBe(true)
56
84
  expect(result.output).toContain('deep.ts')
57
85
  })
86
+
87
+ it('handles pattern with alternation', async () => {
88
+ const result = await tool().execute({ pattern: 'TODO|hello' })
89
+ expect(result.success).toBe(true)
90
+ expect(result.output).toContain('deep.ts')
91
+ expect(result.output).toContain('hello.ts')
92
+ })
58
93
  })
package/src/tools/bash.ts CHANGED
@@ -1,15 +1,89 @@
1
- import { exec } from 'node:child_process'
2
- import { promisify } from 'node:util'
3
-
4
- const execAsync = promisify(exec)
1
+ import { spawn } from 'node:child_process'
2
+ import * as os from 'node:os'
5
3
 
6
4
  import { fmtErr } from './errors.js'
7
5
  import type { Tool, ToolResult } from './types.js'
8
6
 
7
+ function detectEnv(): { osInfo: string; shell: string } {
8
+ const platform = os.platform()
9
+ const release = os.release()
10
+ const arch = os.arch()
11
+
12
+ if (platform === 'win32') {
13
+ return {
14
+ osInfo: `Windows ${release} (${arch})`,
15
+ shell: 'powershell.exe',
16
+ }
17
+ }
18
+
19
+ const osName = platform === 'darwin' ? 'macOS' : platform === 'linux' ? 'Linux' : platform
20
+ return {
21
+ osInfo: `${osName} ${release} (${arch})`,
22
+ shell: process.env.SHELL || '/bin/sh',
23
+ }
24
+ }
25
+
26
+ const env = detectEnv()
27
+
28
+ function execCommand(
29
+ command: string,
30
+ timeout: number,
31
+ ): Promise<{ stdout: string; stderr: string; exitCode: number }> {
32
+ return new Promise(resolve => {
33
+ const isWindows = os.platform() === 'win32'
34
+ const shellExe = isWindows ? 'powershell.exe' : process.env.SHELL || '/bin/sh'
35
+ const shellArgs = isWindows
36
+ ? ['-NoProfile', '-NonInteractive', '-Command', command]
37
+ : ['-c', command]
38
+
39
+ const child = spawn(shellExe, shellArgs, {
40
+ cwd: process.cwd(),
41
+ env: { ...process.env, FORCE_COLOR: '0', NO_COLOR: '1' },
42
+ windowsHide: true,
43
+ })
44
+
45
+ let stdout = ''
46
+ let stderr = ''
47
+ const timer = setTimeout(() => {
48
+ child.kill('SIGTERM')
49
+ setTimeout(() => {
50
+ try {
51
+ child.kill('SIGKILL')
52
+ } catch {
53
+ /* already exited */
54
+ }
55
+ }, 5000)
56
+ }, timeout)
57
+
58
+ child.stdout?.on('data', (data: Buffer) => {
59
+ stdout += data.toString('utf-8')
60
+ })
61
+
62
+ child.stderr?.on('data', (data: Buffer) => {
63
+ stderr += data.toString('utf-8')
64
+ })
65
+
66
+ child.on('close', code => {
67
+ clearTimeout(timer)
68
+ resolve({ stdout, stderr, exitCode: code ?? 0 })
69
+ })
70
+
71
+ child.on('error', err => {
72
+ clearTimeout(timer)
73
+ resolve({ stdout, stderr: stderr + fmtErr(err), exitCode: 1 })
74
+ })
75
+ })
76
+ }
77
+
9
78
  export const bashTool: Tool = {
10
79
  definition: {
11
80
  name: 'bash',
12
- description: 'Execute a shell command. Returns stdout and stderr.',
81
+ description: `Execute a shell command. Returns stdout and stderr.
82
+
83
+ Environment: ${env.osInfo}
84
+ Shell: ${env.shell}
85
+
86
+ ⚠️ IMPORTANT: Do NOT use this tool to create or modify files. Use the 'edit' tool for file modifications instead.`,
13
87
  parameters: {
14
88
  command: { type: 'string', description: 'Shell command to execute', required: true },
15
89
  description: { type: 'string', description: 'Brief description of what the command does' },
@@ -25,12 +99,24 @@ export const bashTool: Tool = {
25
99
  const timeout = (input.timeout as number) || 120_000
26
100
 
27
101
  try {
28
- const { stdout } = await execAsync(command, {
29
- encoding: 'utf-8',
30
- timeout,
31
- maxBuffer: 10 * 1024 * 1024,
32
- })
33
- return { success: true, output: stdout || '(no output)' }
102
+ const { stdout, stderr, exitCode } = await execCommand(command, timeout)
103
+
104
+ let output = ''
105
+ if (stdout.trim()) output += stdout.trim()
106
+ if (stderr.trim()) {
107
+ output += output ? '\n' + stderr.trim() : stderr.trim()
108
+ }
109
+ if (!output) output = '(no output)'
110
+
111
+ if (exitCode !== 0) {
112
+ return {
113
+ success: false,
114
+ output,
115
+ error: `Command exited with code ${exitCode}`,
116
+ }
117
+ }
118
+
119
+ return { success: true, output }
34
120
  } catch (err) {
35
121
  const msg = fmtErr(err)
36
122
  return { success: false, output: '', error: `Command failed: ${msg}` }