lonny-agent 0.2.4 → 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 (102) hide show
  1. package/README.md +326 -326
  2. package/dist/agent/llm.d.ts +4 -0
  3. package/dist/agent/llm.d.ts.map +1 -1
  4. package/dist/agent/prompt-builder.d.ts.map +1 -1
  5. package/dist/agent/prompt-builder.js +13 -9
  6. package/dist/agent/prompt-builder.js.map +1 -1
  7. package/dist/agent/providers/google.d.ts.map +1 -1
  8. package/dist/agent/providers/google.js.map +1 -1
  9. package/dist/agent/providers/openai.d.ts.map +1 -1
  10. package/dist/agent/providers/openai.js +43 -3
  11. package/dist/agent/providers/openai.js.map +1 -1
  12. package/dist/agent/session.d.ts +4 -0
  13. package/dist/agent/session.d.ts.map +1 -1
  14. package/dist/agent/session.js +45 -7
  15. package/dist/agent/session.js.map +1 -1
  16. package/dist/config/index.d.ts.map +1 -1
  17. package/dist/config/index.js +7 -1
  18. package/dist/config/index.js.map +1 -1
  19. package/dist/tools/__tests__/bash.test.js +1 -1
  20. package/dist/tools/__tests__/bash.test.js.map +1 -1
  21. package/dist/tools/__tests__/edit.test.js +875 -371
  22. package/dist/tools/__tests__/edit.test.js.map +1 -1
  23. package/dist/tools/__tests__/grep.test.js +32 -0
  24. package/dist/tools/__tests__/grep.test.js.map +1 -1
  25. package/dist/tools/__tests__/sed.test.d.ts +2 -0
  26. package/dist/tools/__tests__/sed.test.d.ts.map +1 -0
  27. package/dist/tools/__tests__/sed.test.js +228 -0
  28. package/dist/tools/__tests__/sed.test.js.map +1 -0
  29. package/dist/tools/bash.d.ts.map +1 -1
  30. package/dist/tools/bash.js +83 -10
  31. package/dist/tools/bash.js.map +1 -1
  32. package/dist/tools/edit.d.ts +50 -9
  33. package/dist/tools/edit.d.ts.map +1 -1
  34. package/dist/tools/edit.js +328 -158
  35. package/dist/tools/edit.js.map +1 -1
  36. package/dist/tools/grep.d.ts.map +1 -1
  37. package/dist/tools/grep.js +54 -30
  38. package/dist/tools/grep.js.map +1 -1
  39. package/dist/tools/registry.d.ts +0 -6
  40. package/dist/tools/registry.d.ts.map +1 -1
  41. package/dist/tools/registry.js +2 -29
  42. package/dist/tools/registry.js.map +1 -1
  43. package/dist/tools/sed.d.ts +4 -0
  44. package/dist/tools/sed.d.ts.map +1 -0
  45. package/dist/tools/sed.js +121 -0
  46. package/dist/tools/sed.js.map +1 -0
  47. package/dist/web/index.d.ts.map +1 -1
  48. package/dist/web/index.js +26 -3
  49. package/dist/web/index.js.map +1 -1
  50. package/dist/web/public/app.js +5 -855
  51. package/dist/web/public/confirm.js +70 -0
  52. package/dist/web/public/index.html +121 -120
  53. package/dist/web/public/input.js +107 -0
  54. package/dist/web/public/messages.js +395 -0
  55. package/dist/web/public/sidebar.js +82 -0
  56. package/dist/web/public/state.js +72 -0
  57. package/dist/web/public/style.css +996 -949
  58. package/dist/web/public/utils.js +37 -0
  59. package/dist/web/public/websocket.js +267 -0
  60. package/dist/web/public/ws.js +19 -0
  61. package/dist/web/session-bridge.d.ts.map +1 -1
  62. package/dist/web/session-bridge.js +3 -7
  63. package/dist/web/session-bridge.js.map +1 -1
  64. package/package.json +55 -54
  65. package/scripts/copy-native.mjs +24 -0
  66. package/scripts/copy-web.mjs +15 -0
  67. package/src/agent/index.ts +25 -25
  68. package/src/agent/llm.ts +4 -0
  69. package/src/agent/prompt-builder.ts +13 -9
  70. package/src/agent/providers/anthropic.ts +179 -179
  71. package/src/agent/providers/google.ts +210 -211
  72. package/src/agent/providers/ollama.ts +186 -186
  73. package/src/agent/providers/openai.ts +61 -5
  74. package/src/agent/session.ts +59 -3
  75. package/src/config/index.ts +342 -335
  76. package/src/tools/__tests__/bash.test.ts +1 -1
  77. package/src/tools/__tests__/edit.test.ts +981 -385
  78. package/src/tools/__tests__/grep.test.ts +35 -0
  79. package/src/tools/bash.ts +97 -11
  80. package/src/tools/edit.ts +362 -169
  81. package/src/tools/git.ts +76 -76
  82. package/src/tools/grep.ts +57 -30
  83. package/src/tools/registry.ts +2 -31
  84. package/src/tui/index.ts +786 -786
  85. package/src/web/index.ts +25 -3
  86. package/src/web/public/app.js +5 -855
  87. package/src/web/public/confirm.js +70 -0
  88. package/src/web/public/index.html +121 -120
  89. package/src/web/public/input.js +107 -0
  90. package/src/web/public/messages.js +395 -0
  91. package/src/web/public/sidebar.js +82 -0
  92. package/src/web/public/state.js +72 -0
  93. package/src/web/public/style.css +996 -949
  94. package/src/web/public/utils.js +37 -0
  95. package/src/web/public/websocket.js +267 -0
  96. package/src/web/public/ws.js +19 -0
  97. package/src/web/session-bridge.ts +193 -194
  98. package/.claude/settings.local.json +0 -14
  99. package/.kilo/plans/1780064105789-mighty-pixel.md +0 -171
  100. package/.kilo/plans/1780293725888-quick-wizard.md +0 -62
  101. package/.lonny/plan-web-cwd-status.md +0 -38
  102. 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}` }