@oh-my-pi/pi-coding-agent 12.17.0 → 12.17.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/CHANGELOG.md +19 -0
- package/package.json +414 -92
- package/src/cli/stats-cli.ts +3 -3
- package/src/exec/bash-executor.ts +92 -58
- package/src/mcp/config.ts +102 -5
- package/src/mcp/index.ts +3 -1
- package/src/mcp/loader.ts +3 -0
- package/src/mcp/manager.ts +3 -0
- package/src/sdk.ts +2 -0
- package/src/system-prompt.ts +1 -0
- package/src/tools/bash.ts +6 -7
- package/src/utils/shell-snapshot.ts +18 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [12.17.2] - 2026-02-21
|
|
6
|
+
### Changed
|
|
7
|
+
|
|
8
|
+
- Modified bash command normalization to only apply explicit head/tail parameters from tool input, removing automatic extraction from command pipes
|
|
9
|
+
- Updated shell snapshot creation to use explicit timeout and kill signal configuration for more reliable process termination
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Fixed persistent shell session state not being reset after command abort or hard timeout, preventing stale environment variables from affecting subsequent commands
|
|
14
|
+
- Fixed hard timeout handling to properly interrupt long-running commands that exceed the grace period beyond the configured timeout
|
|
15
|
+
|
|
16
|
+
## [12.17.1] - 2026-02-21
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Added `filterBrowser` option to filter out browser automation MCP servers when builtin browser tool is enabled
|
|
20
|
+
- Added `isBrowserMCPServer()` function to detect browser automation MCP servers by name, URL, or command patterns
|
|
21
|
+
- Added `filterBrowserMCPServers()` function to remove browser MCP servers from loaded configurations
|
|
22
|
+
- Added `BrowserFilterResult` type for browser MCP server filtering results
|
|
23
|
+
|
|
5
24
|
## [12.17.0] - 2026-02-21
|
|
6
25
|
### Added
|
|
7
26
|
|
package/package.json
CHANGED
|
@@ -1,50 +1,259 @@
|
|
|
1
1
|
{
|
|
2
|
+
"type": "module",
|
|
2
3
|
"name": "@oh-my-pi/pi-coding-agent",
|
|
3
|
-
"version": "12.17.
|
|
4
|
+
"version": "12.17.2",
|
|
4
5
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
|
|
6
|
+
"homepage": "https://github.com/can1357/oh-my-pi",
|
|
7
|
+
"author": "Can Bölük",
|
|
8
|
+
"contributors": [
|
|
9
|
+
"Mario Zechner"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/can1357/oh-my-pi.git",
|
|
15
|
+
"directory": "packages/coding-agent"
|
|
8
16
|
},
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/can1357/oh-my-pi/issues"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"coding-agent",
|
|
22
|
+
"ai",
|
|
23
|
+
"llm",
|
|
24
|
+
"cli",
|
|
25
|
+
"tui",
|
|
26
|
+
"agent"
|
|
27
|
+
],
|
|
9
28
|
"main": "./src/index.ts",
|
|
10
29
|
"types": "./src/index.ts",
|
|
30
|
+
"bin": {
|
|
31
|
+
"omp": "src/cli.ts"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"check": "tsgo -p tsconfig.json",
|
|
35
|
+
"format-prompts": "bun scripts/format-prompts.ts",
|
|
36
|
+
"generate-docs-index": "bun scripts/generate-docs-index.ts",
|
|
37
|
+
"prepack": "bun scripts/generate-docs-index.ts",
|
|
38
|
+
"build:binary": "cd ../.. && bun --cwd=packages/stats scripts/generate-client-bundle.ts && bun --cwd=packages/natives run embed:native && bun build --compile --define PI_COMPILED=true --root . ./packages/coding-agent/src/cli.ts --outfile packages/coding-agent/dist/omp && bun --cwd=packages/natives run embed:native --reset && bun --cwd=packages/stats scripts/generate-client-bundle.ts --reset",
|
|
39
|
+
"generate-template": "bun scripts/generate-template.ts",
|
|
40
|
+
"test": "bun test"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@mozilla/readability": "0.6.0",
|
|
44
|
+
"@oh-my-pi/omp-stats": "12.17.2",
|
|
45
|
+
"@oh-my-pi/pi-agent-core": "12.17.2",
|
|
46
|
+
"@oh-my-pi/pi-ai": "12.17.2",
|
|
47
|
+
"@oh-my-pi/pi-natives": "12.17.2",
|
|
48
|
+
"@oh-my-pi/pi-tui": "12.17.2",
|
|
49
|
+
"@oh-my-pi/pi-utils": "12.17.2",
|
|
50
|
+
"@sinclair/typebox": "^0.34.48",
|
|
51
|
+
"@xterm/headless": "^6.0.0",
|
|
52
|
+
"ajv": "^8.18.0",
|
|
53
|
+
"chalk": "^5.6.2",
|
|
54
|
+
"diff": "^8.0.3",
|
|
55
|
+
"file-type": "^21.3.0",
|
|
56
|
+
"glob": "^13.0.3",
|
|
57
|
+
"handlebars": "^4.7.8",
|
|
58
|
+
"ignore": "^7.0.5",
|
|
59
|
+
"linkedom": "^0.18.12",
|
|
60
|
+
"marked": "^17.0.2",
|
|
61
|
+
"node-html-parser": "^7.0.2",
|
|
62
|
+
"puppeteer": "^24.37.3",
|
|
63
|
+
"smol-toml": "^1.6.0",
|
|
64
|
+
"zod": "^4.3.6"
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@types/bun": "^1.3.9",
|
|
68
|
+
"@types/ms": "^2.1.0",
|
|
69
|
+
"ms": "^2.1.3"
|
|
70
|
+
},
|
|
71
|
+
"engines": {
|
|
72
|
+
"bun": ">=1.3.7"
|
|
73
|
+
},
|
|
74
|
+
"files": [
|
|
75
|
+
"src",
|
|
76
|
+
"scripts",
|
|
77
|
+
"examples",
|
|
78
|
+
"README.md",
|
|
79
|
+
"CHANGELOG.md"
|
|
80
|
+
],
|
|
11
81
|
"exports": {
|
|
12
82
|
".": {
|
|
13
83
|
"types": "./src/index.ts",
|
|
14
84
|
"import": "./src/index.ts"
|
|
15
85
|
},
|
|
16
|
-
"
|
|
17
|
-
"types": "./src
|
|
18
|
-
"import": "./src
|
|
86
|
+
"./*": {
|
|
87
|
+
"types": "./src/*.ts",
|
|
88
|
+
"import": "./src/*.ts"
|
|
19
89
|
},
|
|
20
|
-
"./
|
|
21
|
-
"types": "./src/
|
|
22
|
-
"import": "./src/
|
|
90
|
+
"./capability": {
|
|
91
|
+
"types": "./src/capability/index.ts",
|
|
92
|
+
"import": "./src/capability/index.ts"
|
|
23
93
|
},
|
|
24
|
-
"./prompts/*": "./src/prompts/*.md",
|
|
25
94
|
"./capability/*": {
|
|
26
95
|
"types": "./src/capability/*.ts",
|
|
27
96
|
"import": "./src/capability/*.ts"
|
|
28
97
|
},
|
|
98
|
+
"./cli/*": {
|
|
99
|
+
"types": "./src/cli/*.ts",
|
|
100
|
+
"import": "./src/cli/*.ts"
|
|
101
|
+
},
|
|
102
|
+
"./commands/*": {
|
|
103
|
+
"types": "./src/commands/*.ts",
|
|
104
|
+
"import": "./src/commands/*.ts"
|
|
105
|
+
},
|
|
106
|
+
"./commit": {
|
|
107
|
+
"types": "./src/commit/index.ts",
|
|
108
|
+
"import": "./src/commit/index.ts"
|
|
109
|
+
},
|
|
110
|
+
"./commit/*": {
|
|
111
|
+
"types": "./src/commit/*.ts",
|
|
112
|
+
"import": "./src/commit/*.ts"
|
|
113
|
+
},
|
|
114
|
+
"./commit/agentic": {
|
|
115
|
+
"types": "./src/commit/agentic/index.ts",
|
|
116
|
+
"import": "./src/commit/agentic/index.ts"
|
|
117
|
+
},
|
|
118
|
+
"./commit/agentic/*": {
|
|
119
|
+
"types": "./src/commit/agentic/*.ts",
|
|
120
|
+
"import": "./src/commit/agentic/*.ts"
|
|
121
|
+
},
|
|
122
|
+
"./commit/agentic/tools": {
|
|
123
|
+
"types": "./src/commit/agentic/tools/index.ts",
|
|
124
|
+
"import": "./src/commit/agentic/tools/index.ts"
|
|
125
|
+
},
|
|
126
|
+
"./commit/agentic/tools/*": {
|
|
127
|
+
"types": "./src/commit/agentic/tools/*.ts",
|
|
128
|
+
"import": "./src/commit/agentic/tools/*.ts"
|
|
129
|
+
},
|
|
130
|
+
"./commit/analysis": {
|
|
131
|
+
"types": "./src/commit/analysis/index.ts",
|
|
132
|
+
"import": "./src/commit/analysis/index.ts"
|
|
133
|
+
},
|
|
134
|
+
"./commit/analysis/*": {
|
|
135
|
+
"types": "./src/commit/analysis/*.ts",
|
|
136
|
+
"import": "./src/commit/analysis/*.ts"
|
|
137
|
+
},
|
|
138
|
+
"./commit/changelog": {
|
|
139
|
+
"types": "./src/commit/changelog/index.ts",
|
|
140
|
+
"import": "./src/commit/changelog/index.ts"
|
|
141
|
+
},
|
|
142
|
+
"./commit/changelog/*": {
|
|
143
|
+
"types": "./src/commit/changelog/*.ts",
|
|
144
|
+
"import": "./src/commit/changelog/*.ts"
|
|
145
|
+
},
|
|
146
|
+
"./commit/git": {
|
|
147
|
+
"types": "./src/commit/git/index.ts",
|
|
148
|
+
"import": "./src/commit/git/index.ts"
|
|
149
|
+
},
|
|
150
|
+
"./commit/git/*": {
|
|
151
|
+
"types": "./src/commit/git/*.ts",
|
|
152
|
+
"import": "./src/commit/git/*.ts"
|
|
153
|
+
},
|
|
154
|
+
"./commit/map-reduce": {
|
|
155
|
+
"types": "./src/commit/map-reduce/index.ts",
|
|
156
|
+
"import": "./src/commit/map-reduce/index.ts"
|
|
157
|
+
},
|
|
158
|
+
"./commit/map-reduce/*": {
|
|
159
|
+
"types": "./src/commit/map-reduce/*.ts",
|
|
160
|
+
"import": "./src/commit/map-reduce/*.ts"
|
|
161
|
+
},
|
|
162
|
+
"./commit/utils/*": {
|
|
163
|
+
"types": "./src/commit/utils/*.ts",
|
|
164
|
+
"import": "./src/commit/utils/*.ts"
|
|
165
|
+
},
|
|
29
166
|
"./config/*": {
|
|
30
167
|
"types": "./src/config/*.ts",
|
|
31
168
|
"import": "./src/config/*.ts"
|
|
32
169
|
},
|
|
170
|
+
"./debug": {
|
|
171
|
+
"types": "./src/debug/index.ts",
|
|
172
|
+
"import": "./src/debug/index.ts"
|
|
173
|
+
},
|
|
174
|
+
"./debug/*": {
|
|
175
|
+
"types": "./src/debug/*.ts",
|
|
176
|
+
"import": "./src/debug/*.ts"
|
|
177
|
+
},
|
|
178
|
+
"./discovery": {
|
|
179
|
+
"types": "./src/discovery/index.ts",
|
|
180
|
+
"import": "./src/discovery/index.ts"
|
|
181
|
+
},
|
|
182
|
+
"./discovery/*": {
|
|
183
|
+
"types": "./src/discovery/*.ts",
|
|
184
|
+
"import": "./src/discovery/*.ts"
|
|
185
|
+
},
|
|
186
|
+
"./exa": {
|
|
187
|
+
"types": "./src/exa/index.ts",
|
|
188
|
+
"import": "./src/exa/index.ts"
|
|
189
|
+
},
|
|
190
|
+
"./exa/*": {
|
|
191
|
+
"types": "./src/exa/*.ts",
|
|
192
|
+
"import": "./src/exa/*.ts"
|
|
193
|
+
},
|
|
194
|
+
"./exec/*": {
|
|
195
|
+
"types": "./src/exec/*.ts",
|
|
196
|
+
"import": "./src/exec/*.ts"
|
|
197
|
+
},
|
|
198
|
+
"./export/*": {
|
|
199
|
+
"types": "./src/export/*.ts",
|
|
200
|
+
"import": "./src/export/*.ts"
|
|
201
|
+
},
|
|
202
|
+
"./export/html": {
|
|
203
|
+
"types": "./src/export/html/index.ts",
|
|
204
|
+
"import": "./src/export/html/index.ts"
|
|
205
|
+
},
|
|
206
|
+
"./export/html/*": {
|
|
207
|
+
"types": "./src/export/html/*.ts",
|
|
208
|
+
"import": "./src/export/html/*.ts"
|
|
209
|
+
},
|
|
33
210
|
"./extensibility/*": {
|
|
34
211
|
"types": "./src/extensibility/*.ts",
|
|
35
212
|
"import": "./src/extensibility/*.ts"
|
|
36
213
|
},
|
|
37
|
-
"./extensibility/
|
|
38
|
-
"types": "./src/extensibility/
|
|
39
|
-
"import": "./src/extensibility/
|
|
214
|
+
"./extensibility/custom-commands": {
|
|
215
|
+
"types": "./src/extensibility/custom-commands/index.ts",
|
|
216
|
+
"import": "./src/extensibility/custom-commands/index.ts"
|
|
217
|
+
},
|
|
218
|
+
"./extensibility/custom-commands/*": {
|
|
219
|
+
"types": "./src/extensibility/custom-commands/*.ts",
|
|
220
|
+
"import": "./src/extensibility/custom-commands/*.ts"
|
|
221
|
+
},
|
|
222
|
+
"./extensibility/custom-commands/bundled/review": {
|
|
223
|
+
"types": "./src/extensibility/custom-commands/bundled/review/index.ts",
|
|
224
|
+
"import": "./src/extensibility/custom-commands/bundled/review/index.ts"
|
|
225
|
+
},
|
|
226
|
+
"./extensibility/custom-tools": {
|
|
227
|
+
"types": "./src/extensibility/custom-tools/index.ts",
|
|
228
|
+
"import": "./src/extensibility/custom-tools/index.ts"
|
|
229
|
+
},
|
|
230
|
+
"./extensibility/custom-tools/*": {
|
|
231
|
+
"types": "./src/extensibility/custom-tools/*.ts",
|
|
232
|
+
"import": "./src/extensibility/custom-tools/*.ts"
|
|
233
|
+
},
|
|
234
|
+
"./extensibility/extensions": {
|
|
235
|
+
"types": "./src/extensibility/extensions/index.ts",
|
|
236
|
+
"import": "./src/extensibility/extensions/index.ts"
|
|
40
237
|
},
|
|
41
238
|
"./extensibility/extensions/*": {
|
|
42
239
|
"types": "./src/extensibility/extensions/*.ts",
|
|
43
240
|
"import": "./src/extensibility/extensions/*.ts"
|
|
44
241
|
},
|
|
45
|
-
"./
|
|
46
|
-
"types": "./src/
|
|
47
|
-
"import": "./src/
|
|
242
|
+
"./extensibility/hooks": {
|
|
243
|
+
"types": "./src/extensibility/hooks/index.ts",
|
|
244
|
+
"import": "./src/extensibility/hooks/index.ts"
|
|
245
|
+
},
|
|
246
|
+
"./extensibility/hooks/*": {
|
|
247
|
+
"types": "./src/extensibility/hooks/*.ts",
|
|
248
|
+
"import": "./src/extensibility/hooks/*.ts"
|
|
249
|
+
},
|
|
250
|
+
"./extensibility/plugins": {
|
|
251
|
+
"types": "./src/extensibility/plugins/index.ts",
|
|
252
|
+
"import": "./src/extensibility/plugins/index.ts"
|
|
253
|
+
},
|
|
254
|
+
"./extensibility/plugins/*": {
|
|
255
|
+
"types": "./src/extensibility/plugins/*.ts",
|
|
256
|
+
"import": "./src/extensibility/plugins/*.ts"
|
|
48
257
|
},
|
|
49
258
|
"./internal-urls": {
|
|
50
259
|
"types": "./src/internal-urls/index.ts",
|
|
@@ -54,85 +263,198 @@
|
|
|
54
263
|
"types": "./src/internal-urls/*.ts",
|
|
55
264
|
"import": "./src/internal-urls/*.ts"
|
|
56
265
|
},
|
|
266
|
+
"./ipy/*": {
|
|
267
|
+
"types": "./src/ipy/*.ts",
|
|
268
|
+
"import": "./src/ipy/*.ts"
|
|
269
|
+
},
|
|
270
|
+
"./lsp": {
|
|
271
|
+
"types": "./src/lsp/index.ts",
|
|
272
|
+
"import": "./src/lsp/index.ts"
|
|
273
|
+
},
|
|
274
|
+
"./lsp/*": {
|
|
275
|
+
"types": "./src/lsp/*.ts",
|
|
276
|
+
"import": "./src/lsp/*.ts"
|
|
277
|
+
},
|
|
278
|
+
"./lsp/clients": {
|
|
279
|
+
"types": "./src/lsp/clients/index.ts",
|
|
280
|
+
"import": "./src/lsp/clients/index.ts"
|
|
281
|
+
},
|
|
282
|
+
"./lsp/clients/*": {
|
|
283
|
+
"types": "./src/lsp/clients/*.ts",
|
|
284
|
+
"import": "./src/lsp/clients/*.ts"
|
|
285
|
+
},
|
|
286
|
+
"./mcp": {
|
|
287
|
+
"types": "./src/mcp/index.ts",
|
|
288
|
+
"import": "./src/mcp/index.ts"
|
|
289
|
+
},
|
|
290
|
+
"./mcp/*": {
|
|
291
|
+
"types": "./src/mcp/*.ts",
|
|
292
|
+
"import": "./src/mcp/*.ts"
|
|
293
|
+
},
|
|
294
|
+
"./mcp/transports": {
|
|
295
|
+
"types": "./src/mcp/transports/index.ts",
|
|
296
|
+
"import": "./src/mcp/transports/index.ts"
|
|
297
|
+
},
|
|
298
|
+
"./mcp/transports/*": {
|
|
299
|
+
"types": "./src/mcp/transports/*.ts",
|
|
300
|
+
"import": "./src/mcp/transports/*.ts"
|
|
301
|
+
},
|
|
302
|
+
"./memories": {
|
|
303
|
+
"types": "./src/memories/index.ts",
|
|
304
|
+
"import": "./src/memories/index.ts"
|
|
305
|
+
},
|
|
306
|
+
"./memories/*": {
|
|
307
|
+
"types": "./src/memories/*.ts",
|
|
308
|
+
"import": "./src/memories/*.ts"
|
|
309
|
+
},
|
|
310
|
+
"./modes": {
|
|
311
|
+
"types": "./src/modes/index.ts",
|
|
312
|
+
"import": "./src/modes/index.ts"
|
|
313
|
+
},
|
|
314
|
+
"./modes/*": {
|
|
315
|
+
"types": "./src/modes/*.ts",
|
|
316
|
+
"import": "./src/modes/*.ts"
|
|
317
|
+
},
|
|
318
|
+
"./modes/components": {
|
|
319
|
+
"types": "./src/modes/components/index.ts",
|
|
320
|
+
"import": "./src/modes/components/index.ts"
|
|
321
|
+
},
|
|
322
|
+
"./modes/components/*": {
|
|
323
|
+
"types": "./src/modes/components/*.ts",
|
|
324
|
+
"import": "./src/modes/components/*.ts"
|
|
325
|
+
},
|
|
326
|
+
"./modes/components/extensions": {
|
|
327
|
+
"types": "./src/modes/components/extensions/index.ts",
|
|
328
|
+
"import": "./src/modes/components/extensions/index.ts"
|
|
329
|
+
},
|
|
330
|
+
"./modes/components/extensions/*": {
|
|
331
|
+
"types": "./src/modes/components/extensions/*.ts",
|
|
332
|
+
"import": "./src/modes/components/extensions/*.ts"
|
|
333
|
+
},
|
|
334
|
+
"./modes/components/status-line": {
|
|
335
|
+
"types": "./src/modes/components/status-line/index.ts",
|
|
336
|
+
"import": "./src/modes/components/status-line/index.ts"
|
|
337
|
+
},
|
|
338
|
+
"./modes/components/status-line/*": {
|
|
339
|
+
"types": "./src/modes/components/status-line/*.ts",
|
|
340
|
+
"import": "./src/modes/components/status-line/*.ts"
|
|
341
|
+
},
|
|
342
|
+
"./modes/controllers/*": {
|
|
343
|
+
"types": "./src/modes/controllers/*.ts",
|
|
344
|
+
"import": "./src/modes/controllers/*.ts"
|
|
345
|
+
},
|
|
346
|
+
"./modes/rpc/*": {
|
|
347
|
+
"types": "./src/modes/rpc/*.ts",
|
|
348
|
+
"import": "./src/modes/rpc/*.ts"
|
|
349
|
+
},
|
|
350
|
+
"./modes/theme/*": {
|
|
351
|
+
"types": "./src/modes/theme/*.ts",
|
|
352
|
+
"import": "./src/modes/theme/*.ts"
|
|
353
|
+
},
|
|
354
|
+
"./modes/theme/defaults": {
|
|
355
|
+
"types": "./src/modes/theme/defaults/index.ts",
|
|
356
|
+
"import": "./src/modes/theme/defaults/index.ts"
|
|
357
|
+
},
|
|
358
|
+
"./modes/utils/*": {
|
|
359
|
+
"types": "./src/modes/utils/*.ts",
|
|
360
|
+
"import": "./src/modes/utils/*.ts"
|
|
361
|
+
},
|
|
362
|
+
"./patch": {
|
|
363
|
+
"types": "./src/patch/index.ts",
|
|
364
|
+
"import": "./src/patch/index.ts"
|
|
365
|
+
},
|
|
57
366
|
"./patch/*": {
|
|
58
367
|
"types": "./src/patch/*.ts",
|
|
59
368
|
"import": "./src/patch/*.ts"
|
|
60
369
|
},
|
|
61
|
-
"./
|
|
62
|
-
"types": "./src/
|
|
63
|
-
"import": "./src/
|
|
370
|
+
"./plan-mode/*": {
|
|
371
|
+
"types": "./src/plan-mode/*.ts",
|
|
372
|
+
"import": "./src/plan-mode/*.ts"
|
|
64
373
|
},
|
|
65
|
-
"
|
|
66
|
-
|
|
67
|
-
"
|
|
374
|
+
"./prompts/*": "./src/prompts/*.md",
|
|
375
|
+
"./secrets": {
|
|
376
|
+
"types": "./src/secrets/index.ts",
|
|
377
|
+
"import": "./src/secrets/index.ts"
|
|
378
|
+
},
|
|
379
|
+
"./secrets/*": {
|
|
380
|
+
"types": "./src/secrets/*.ts",
|
|
381
|
+
"import": "./src/secrets/*.ts"
|
|
382
|
+
},
|
|
383
|
+
"./session/*": {
|
|
384
|
+
"types": "./src/session/*.ts",
|
|
385
|
+
"import": "./src/session/*.ts"
|
|
386
|
+
},
|
|
387
|
+
"./session/compaction": {
|
|
388
|
+
"types": "./src/session/compaction/index.ts",
|
|
389
|
+
"import": "./src/session/compaction/index.ts"
|
|
390
|
+
},
|
|
391
|
+
"./session/compaction/*": {
|
|
392
|
+
"types": "./src/session/compaction/*.ts",
|
|
393
|
+
"import": "./src/session/compaction/*.ts"
|
|
394
|
+
},
|
|
395
|
+
"./slash-commands/*": {
|
|
396
|
+
"types": "./src/slash-commands/*.ts",
|
|
397
|
+
"import": "./src/slash-commands/*.ts"
|
|
398
|
+
},
|
|
399
|
+
"./ssh/*": {
|
|
400
|
+
"types": "./src/ssh/*.ts",
|
|
401
|
+
"import": "./src/ssh/*.ts"
|
|
402
|
+
},
|
|
403
|
+
"./stt": {
|
|
404
|
+
"types": "./src/stt/index.ts",
|
|
405
|
+
"import": "./src/stt/index.ts"
|
|
406
|
+
},
|
|
407
|
+
"./stt/*": {
|
|
408
|
+
"types": "./src/stt/*.ts",
|
|
409
|
+
"import": "./src/stt/*.ts"
|
|
410
|
+
},
|
|
411
|
+
"./task": {
|
|
412
|
+
"types": "./src/task/index.ts",
|
|
413
|
+
"import": "./src/task/index.ts"
|
|
414
|
+
},
|
|
415
|
+
"./task/*": {
|
|
416
|
+
"types": "./src/task/*.ts",
|
|
417
|
+
"import": "./src/task/*.ts"
|
|
418
|
+
},
|
|
419
|
+
"./tools": {
|
|
420
|
+
"types": "./src/tools/index.ts",
|
|
421
|
+
"import": "./src/tools/index.ts"
|
|
422
|
+
},
|
|
423
|
+
"./tools/*": {
|
|
424
|
+
"types": "./src/tools/*.ts",
|
|
425
|
+
"import": "./src/tools/*.ts"
|
|
426
|
+
},
|
|
427
|
+
"./tui": {
|
|
428
|
+
"types": "./src/tui/index.ts",
|
|
429
|
+
"import": "./src/tui/index.ts"
|
|
430
|
+
},
|
|
431
|
+
"./tui/*": {
|
|
432
|
+
"types": "./src/tui/*.ts",
|
|
433
|
+
"import": "./src/tui/*.ts"
|
|
434
|
+
},
|
|
435
|
+
"./utils/*": {
|
|
436
|
+
"types": "./src/utils/*.ts",
|
|
437
|
+
"import": "./src/utils/*.ts"
|
|
438
|
+
},
|
|
439
|
+
"./web/scrapers": {
|
|
440
|
+
"types": "./src/web/scrapers/index.ts",
|
|
441
|
+
"import": "./src/web/scrapers/index.ts"
|
|
442
|
+
},
|
|
443
|
+
"./web/scrapers/*": {
|
|
444
|
+
"types": "./src/web/scrapers/*.ts",
|
|
445
|
+
"import": "./src/web/scrapers/*.ts"
|
|
446
|
+
},
|
|
447
|
+
"./web/search": {
|
|
448
|
+
"types": "./src/web/search/index.ts",
|
|
449
|
+
"import": "./src/web/search/index.ts"
|
|
450
|
+
},
|
|
451
|
+
"./web/search/*": {
|
|
452
|
+
"types": "./src/web/search/*.ts",
|
|
453
|
+
"import": "./src/web/search/*.ts"
|
|
454
|
+
},
|
|
455
|
+
"./web/search/providers/*": {
|
|
456
|
+
"types": "./src/web/search/providers/*.ts",
|
|
457
|
+
"import": "./src/web/search/providers/*.ts"
|
|
68
458
|
}
|
|
69
|
-
}
|
|
70
|
-
"files": [
|
|
71
|
-
"src",
|
|
72
|
-
"scripts",
|
|
73
|
-
"examples",
|
|
74
|
-
"README.md",
|
|
75
|
-
"CHANGELOG.md"
|
|
76
|
-
],
|
|
77
|
-
"scripts": {
|
|
78
|
-
"check": "tsgo -p tsconfig.json",
|
|
79
|
-
"format-prompts": "bun scripts/format-prompts.ts",
|
|
80
|
-
"generate-docs-index": "bun scripts/generate-docs-index.ts",
|
|
81
|
-
"prepack": "bun scripts/generate-docs-index.ts",
|
|
82
|
-
"build:binary": "cd ../.. && bun --cwd=packages/stats scripts/generate-client-bundle.ts && bun --cwd=packages/natives run embed:native && bun build --compile --define PI_COMPILED=true --root . ./packages/coding-agent/src/cli.ts --outfile packages/coding-agent/dist/omp && bun --cwd=packages/natives run embed:native --reset && bun --cwd=packages/stats scripts/generate-client-bundle.ts --reset",
|
|
83
|
-
"generate-template": "bun scripts/generate-template.ts",
|
|
84
|
-
"test": "bun test"
|
|
85
|
-
},
|
|
86
|
-
"dependencies": {
|
|
87
|
-
"@mozilla/readability": "0.6.0",
|
|
88
|
-
"@oh-my-pi/omp-stats": "12.17.0",
|
|
89
|
-
"@oh-my-pi/pi-agent-core": "12.17.0",
|
|
90
|
-
"@oh-my-pi/pi-ai": "12.17.0",
|
|
91
|
-
"@oh-my-pi/pi-natives": "12.17.0",
|
|
92
|
-
"@oh-my-pi/pi-tui": "12.17.0",
|
|
93
|
-
"@oh-my-pi/pi-utils": "12.17.0",
|
|
94
|
-
"@sinclair/typebox": "^0.34.48",
|
|
95
|
-
"@xterm/headless": "^6.0.0",
|
|
96
|
-
"ajv": "^8.18.0",
|
|
97
|
-
"chalk": "^5.6.2",
|
|
98
|
-
"diff": "^8.0.3",
|
|
99
|
-
"file-type": "^21.3.0",
|
|
100
|
-
"glob": "^13.0.3",
|
|
101
|
-
"handlebars": "^4.7.8",
|
|
102
|
-
"ignore": "^7.0.5",
|
|
103
|
-
"linkedom": "^0.18.12",
|
|
104
|
-
"marked": "^17.0.2",
|
|
105
|
-
"node-html-parser": "^7.0.2",
|
|
106
|
-
"puppeteer": "^24.37.3",
|
|
107
|
-
"smol-toml": "^1.6.0",
|
|
108
|
-
"zod": "^4.3.6"
|
|
109
|
-
},
|
|
110
|
-
"devDependencies": {
|
|
111
|
-
"@types/bun": "^1.3.9",
|
|
112
|
-
"@types/ms": "^2.1.0",
|
|
113
|
-
"ms": "^2.1.3"
|
|
114
|
-
},
|
|
115
|
-
"keywords": [
|
|
116
|
-
"coding-agent",
|
|
117
|
-
"ai",
|
|
118
|
-
"llm",
|
|
119
|
-
"cli",
|
|
120
|
-
"tui",
|
|
121
|
-
"agent"
|
|
122
|
-
],
|
|
123
|
-
"author": "Can Bölük",
|
|
124
|
-
"contributors": ["Mario Zechner"],
|
|
125
|
-
"license": "MIT",
|
|
126
|
-
"repository": {
|
|
127
|
-
"type": "git",
|
|
128
|
-
"url": "git+https://github.com/can1357/oh-my-pi.git",
|
|
129
|
-
"directory": "packages/coding-agent"
|
|
130
|
-
},
|
|
131
|
-
"homepage": "https://github.com/can1357/oh-my-pi",
|
|
132
|
-
"bugs": {
|
|
133
|
-
"url": "https://github.com/can1357/oh-my-pi/issues"
|
|
134
|
-
},
|
|
135
|
-
"engines": {
|
|
136
|
-
"bun": ">=1.3.7"
|
|
137
|
-
}
|
|
459
|
+
}
|
|
138
460
|
}
|
package/src/cli/stats-cli.ts
CHANGED
|
@@ -85,9 +85,9 @@ function formatPercent(n: number): string {
|
|
|
85
85
|
|
|
86
86
|
export async function runStatsCommand(cmd: StatsCommandArgs): Promise<void> {
|
|
87
87
|
// Lazy import to avoid loading stats module when not needed
|
|
88
|
-
const { getDashboardStats, syncAllSessions, getTotalMessageCount } = await import(
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
const { getDashboardStats, syncAllSessions, getTotalMessageCount, startServer, closeDb } = await import(
|
|
89
|
+
"@oh-my-pi/omp-stats"
|
|
90
|
+
);
|
|
91
91
|
|
|
92
92
|
// Sync session files first
|
|
93
93
|
console.log("Syncing session files...");
|
|
@@ -34,6 +34,8 @@ export interface BashResult {
|
|
|
34
34
|
artifactId?: string;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
const HARD_TIMEOUT_GRACE_MS = 5_000;
|
|
38
|
+
|
|
37
39
|
const shellSessions = new Map<string, Shell>();
|
|
38
40
|
|
|
39
41
|
export async function executeBash(command: string, options?: BashExecutorOptions): Promise<BashResult> {
|
|
@@ -65,74 +67,106 @@ export async function executeBash(command: string, options?: BashExecutorOptions
|
|
|
65
67
|
};
|
|
66
68
|
}
|
|
67
69
|
|
|
70
|
+
const sessionKey = buildSessionKey(shell, prefix, snapshotPath, shellEnv, options?.sessionKey);
|
|
71
|
+
let shellSession = shellSessions.get(sessionKey);
|
|
72
|
+
if (!shellSession) {
|
|
73
|
+
shellSession = new Shell({ sessionEnv: shellEnv, snapshotPath: snapshotPath ?? undefined });
|
|
74
|
+
shellSessions.set(sessionKey, shellSession);
|
|
75
|
+
}
|
|
76
|
+
const signal = options?.signal;
|
|
77
|
+
const abortHandler = () => {
|
|
78
|
+
shellSession.abort(signal?.reason instanceof Error ? signal.reason.message : undefined);
|
|
79
|
+
};
|
|
80
|
+
if (signal) {
|
|
81
|
+
signal.addEventListener("abort", abortHandler, { once: true });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let hardTimeoutTimer: NodeJS.Timeout | undefined;
|
|
85
|
+
const hardTimeoutDeferred = Promise.withResolvers<"hard-timeout">();
|
|
86
|
+
const baseTimeoutMs = Math.max(1_000, options?.timeout ?? 300_000);
|
|
87
|
+
const hardTimeoutMs = baseTimeoutMs + HARD_TIMEOUT_GRACE_MS;
|
|
88
|
+
hardTimeoutTimer = setTimeout(() => {
|
|
89
|
+
shellSession.abort(`Hard timeout after ${Math.round(hardTimeoutMs / 1000)}s`);
|
|
90
|
+
hardTimeoutDeferred.resolve("hard-timeout");
|
|
91
|
+
}, hardTimeoutMs);
|
|
92
|
+
|
|
93
|
+
let resetSession = false;
|
|
94
|
+
|
|
68
95
|
try {
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
96
|
+
const runPromise = shellSession.run(
|
|
97
|
+
{
|
|
98
|
+
command: finalCommand,
|
|
99
|
+
cwd: options?.cwd,
|
|
100
|
+
env: options?.env,
|
|
101
|
+
timeoutMs: options?.timeout,
|
|
102
|
+
signal,
|
|
103
|
+
},
|
|
104
|
+
(err, chunk) => {
|
|
105
|
+
if (!err) {
|
|
106
|
+
enqueueChunk(chunk);
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const winner = await Promise.race([
|
|
112
|
+
runPromise.then(result => ({ kind: "result" as const, result })),
|
|
113
|
+
hardTimeoutDeferred.promise.then(() => ({ kind: "hard-timeout" as const })),
|
|
114
|
+
]);
|
|
115
|
+
|
|
116
|
+
await pendingChunks;
|
|
117
|
+
|
|
118
|
+
if (winner.kind === "hard-timeout") {
|
|
119
|
+
resetSession = true;
|
|
120
|
+
return {
|
|
121
|
+
exitCode: undefined,
|
|
122
|
+
cancelled: true,
|
|
123
|
+
...(await sink.dump(`Command exceeded hard timeout after ${Math.round(hardTimeoutMs / 1000)} seconds`)),
|
|
124
|
+
};
|
|
74
125
|
}
|
|
75
126
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
127
|
+
// Handle timeout
|
|
128
|
+
if (winner.result.timedOut) {
|
|
129
|
+
const annotation = options?.timeout
|
|
130
|
+
? `Command timed out after ${Math.round(options.timeout / 1000)} seconds`
|
|
131
|
+
: "Command timed out";
|
|
132
|
+
resetSession = true;
|
|
133
|
+
return {
|
|
134
|
+
exitCode: undefined,
|
|
135
|
+
cancelled: true,
|
|
136
|
+
...(await sink.dump(annotation)),
|
|
137
|
+
};
|
|
82
138
|
}
|
|
83
139
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
command: finalCommand,
|
|
88
|
-
cwd: options?.cwd,
|
|
89
|
-
env: options?.env,
|
|
90
|
-
timeoutMs: options?.timeout,
|
|
91
|
-
signal,
|
|
92
|
-
},
|
|
93
|
-
(err, chunk) => {
|
|
94
|
-
if (!err) {
|
|
95
|
-
enqueueChunk(chunk);
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
await pendingChunks;
|
|
101
|
-
|
|
102
|
-
// Handle timeout
|
|
103
|
-
if (result.timedOut) {
|
|
104
|
-
const annotation = options?.timeout
|
|
105
|
-
? `Command timed out after ${Math.round(options.timeout / 1000)} seconds`
|
|
106
|
-
: "Command timed out";
|
|
107
|
-
return {
|
|
108
|
-
exitCode: undefined,
|
|
109
|
-
cancelled: true,
|
|
110
|
-
...(await sink.dump(annotation)),
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Handle cancellation
|
|
115
|
-
if (result.cancelled) {
|
|
116
|
-
return {
|
|
117
|
-
exitCode: undefined,
|
|
118
|
-
cancelled: true,
|
|
119
|
-
...(await sink.dump("Command cancelled")),
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Normal completion
|
|
140
|
+
// Handle cancellation
|
|
141
|
+
if (winner.result.cancelled) {
|
|
142
|
+
resetSession = true;
|
|
124
143
|
return {
|
|
125
|
-
exitCode:
|
|
126
|
-
cancelled:
|
|
127
|
-
...(await sink.dump()),
|
|
144
|
+
exitCode: undefined,
|
|
145
|
+
cancelled: true,
|
|
146
|
+
...(await sink.dump("Command cancelled")),
|
|
128
147
|
};
|
|
129
|
-
} finally {
|
|
130
|
-
if (signal) {
|
|
131
|
-
signal.removeEventListener("abort", abortHandler);
|
|
132
|
-
}
|
|
133
148
|
}
|
|
149
|
+
|
|
150
|
+
// Normal completion
|
|
151
|
+
return {
|
|
152
|
+
exitCode: winner.result.exitCode,
|
|
153
|
+
cancelled: false,
|
|
154
|
+
...(await sink.dump()),
|
|
155
|
+
};
|
|
156
|
+
} catch (err) {
|
|
157
|
+
resetSession = true;
|
|
158
|
+
throw err;
|
|
134
159
|
} finally {
|
|
160
|
+
if (hardTimeoutTimer) {
|
|
161
|
+
clearTimeout(hardTimeoutTimer);
|
|
162
|
+
}
|
|
163
|
+
if (signal) {
|
|
164
|
+
signal.removeEventListener("abort", abortHandler);
|
|
165
|
+
}
|
|
135
166
|
await pendingChunks;
|
|
167
|
+
if (resetSession) {
|
|
168
|
+
shellSessions.delete(sessionKey);
|
|
169
|
+
}
|
|
136
170
|
}
|
|
137
171
|
}
|
|
138
172
|
|
package/src/mcp/config.ts
CHANGED
|
@@ -18,6 +18,8 @@ export interface LoadMCPConfigsOptions {
|
|
|
18
18
|
enableProjectConfig?: boolean;
|
|
19
19
|
/** Whether to filter out Exa MCP servers (default: true) */
|
|
20
20
|
filterExa?: boolean;
|
|
21
|
+
/** Whether to filter out browser MCP servers when builtin browser tool is enabled (default: false) */
|
|
22
|
+
filterBrowser?: boolean;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
/** Result of loading MCP configs */
|
|
@@ -91,6 +93,7 @@ function convertToLegacyConfig(server: MCPServer): MCPServerConfig {
|
|
|
91
93
|
export async function loadAllMCPConfigs(cwd: string, options?: LoadMCPConfigsOptions): Promise<LoadMCPConfigsResult> {
|
|
92
94
|
const enableProjectConfig = options?.enableProjectConfig ?? true;
|
|
93
95
|
const filterExa = options?.filterExa ?? true;
|
|
96
|
+
const filterBrowser = options?.filterBrowser ?? false;
|
|
94
97
|
|
|
95
98
|
// Load MCP servers via capability system
|
|
96
99
|
const result = await loadCapability<MCPServer>(mcpCapability.id, { cwd });
|
|
@@ -103,8 +106,8 @@ export async function loadAllMCPConfigs(cwd: string, options?: LoadMCPConfigsOpt
|
|
|
103
106
|
// Load user-level disabled servers list
|
|
104
107
|
const disabledServers = new Set(await readDisabledServers(getMCPConfigPath("user", cwd)));
|
|
105
108
|
// Convert to legacy format and preserve source metadata
|
|
106
|
-
|
|
107
|
-
|
|
109
|
+
let configs: Record<string, MCPServerConfig> = {};
|
|
110
|
+
let sources: Record<string, SourceMeta> = {};
|
|
108
111
|
for (const server of servers) {
|
|
109
112
|
const config = convertToLegacyConfig(server);
|
|
110
113
|
if (config.enabled === false || (server._source.level !== "user" && disabledServers.has(server.name))) {
|
|
@@ -114,11 +117,19 @@ export async function loadAllMCPConfigs(cwd: string, options?: LoadMCPConfigsOpt
|
|
|
114
117
|
sources[server.name] = server._source;
|
|
115
118
|
}
|
|
116
119
|
|
|
117
|
-
|
|
120
|
+
let exaApiKeys: string[] = [];
|
|
118
121
|
|
|
119
122
|
if (filterExa) {
|
|
120
|
-
const
|
|
121
|
-
|
|
123
|
+
const exaResult = filterExaMCPServers(configs, sources);
|
|
124
|
+
configs = exaResult.configs;
|
|
125
|
+
sources = exaResult.sources;
|
|
126
|
+
exaApiKeys = exaResult.exaApiKeys;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (filterBrowser) {
|
|
130
|
+
const browserResult = filterBrowserMCPServers(configs, sources);
|
|
131
|
+
configs = browserResult.configs;
|
|
132
|
+
sources = browserResult.sources;
|
|
122
133
|
}
|
|
123
134
|
|
|
124
135
|
return { configs, exaApiKeys, sources };
|
|
@@ -264,3 +275,89 @@ export function validateServerConfig(name: string, config: MCPServerConfig): str
|
|
|
264
275
|
|
|
265
276
|
return errors;
|
|
266
277
|
}
|
|
278
|
+
|
|
279
|
+
/** Known browser automation MCP server names (lowercase) */
|
|
280
|
+
const BROWSER_MCP_NAMES = new Set([
|
|
281
|
+
"puppeteer",
|
|
282
|
+
"playwright",
|
|
283
|
+
"browserbase",
|
|
284
|
+
"browser-tools",
|
|
285
|
+
"browser-use",
|
|
286
|
+
"browser",
|
|
287
|
+
]);
|
|
288
|
+
|
|
289
|
+
/** Patterns matching browser MCP package names in command/args */
|
|
290
|
+
const BROWSER_MCP_PKG_PATTERN =
|
|
291
|
+
// Official packages
|
|
292
|
+
// - @modelcontextprotocol/server-puppeteer
|
|
293
|
+
// - @playwright/mcp
|
|
294
|
+
// - @browserbasehq/mcp-server-browserbase
|
|
295
|
+
// - @agentdeskai/browser-tools-mcp
|
|
296
|
+
// - @agent-infra/mcp-server-browser
|
|
297
|
+
// Community packages: puppeteer-mcp-server, playwright-mcp, pptr-mcp, etc.
|
|
298
|
+
/(?:@modelcontextprotocol\/server-puppeteer|@playwright\/mcp|@browserbasehq\/mcp-server-browserbase|@agentdeskai\/browser-tools-mcp|@agent-infra\/mcp-server-browser|puppeteer-mcp|playwright-mcp|pptr-mcp|browser-use-mcp|mcp-browser-use)/i;
|
|
299
|
+
|
|
300
|
+
/** URL patterns for hosted browser MCP services */
|
|
301
|
+
const BROWSER_MCP_URL_PATTERN = /browserbase\.com|browser-use\.com/i;
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Check if a server config is a browser automation MCP server.
|
|
305
|
+
*/
|
|
306
|
+
export function isBrowserMCPServer(name: string, config: MCPServerConfig): boolean {
|
|
307
|
+
// Check by server name
|
|
308
|
+
if (BROWSER_MCP_NAMES.has(name.toLowerCase())) {
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Check by URL for HTTP/SSE servers
|
|
313
|
+
if (config.type === "http" || config.type === "sse") {
|
|
314
|
+
const httpConfig = config as { url?: string };
|
|
315
|
+
if (httpConfig.url && BROWSER_MCP_URL_PATTERN.test(httpConfig.url)) {
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Check by command/args for stdio servers
|
|
321
|
+
if (!config.type || config.type === "stdio") {
|
|
322
|
+
const stdioConfig = config as { command?: string; args?: string[] };
|
|
323
|
+
if (stdioConfig.command && BROWSER_MCP_PKG_PATTERN.test(stdioConfig.command)) {
|
|
324
|
+
return true;
|
|
325
|
+
}
|
|
326
|
+
if (stdioConfig.args?.some(arg => BROWSER_MCP_PKG_PATTERN.test(arg))) {
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/** Result of filtering browser MCP servers */
|
|
335
|
+
export interface BrowserFilterResult {
|
|
336
|
+
/** Configs with browser servers removed */
|
|
337
|
+
configs: Record<string, MCPServerConfig>;
|
|
338
|
+
/** Source metadata for remaining servers */
|
|
339
|
+
sources: Record<string, SourceMeta>;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Filter out browser automation MCP servers.
|
|
344
|
+
* Since we have a native browser tool, we don't need these MCP servers.
|
|
345
|
+
*/
|
|
346
|
+
export function filterBrowserMCPServers(
|
|
347
|
+
configs: Record<string, MCPServerConfig>,
|
|
348
|
+
sources: Record<string, SourceMeta>,
|
|
349
|
+
): BrowserFilterResult {
|
|
350
|
+
const filtered: Record<string, MCPServerConfig> = {};
|
|
351
|
+
const filteredSources: Record<string, SourceMeta> = {};
|
|
352
|
+
|
|
353
|
+
for (const [name, config] of Object.entries(configs)) {
|
|
354
|
+
if (!isBrowserMCPServer(name, config)) {
|
|
355
|
+
filtered[name] = config;
|
|
356
|
+
if (sources[name]) {
|
|
357
|
+
filteredSources[name] = sources[name];
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
return { configs: filtered, sources: filteredSources };
|
|
363
|
+
}
|
package/src/mcp/index.ts
CHANGED
|
@@ -8,10 +8,12 @@
|
|
|
8
8
|
// Client
|
|
9
9
|
export { callTool, connectToServer, disconnectServer, listTools, serverSupportsTools } from "./client";
|
|
10
10
|
// Config
|
|
11
|
-
export type { ExaFilterResult, LoadMCPConfigsOptions, LoadMCPConfigsResult } from "./config";
|
|
11
|
+
export type { BrowserFilterResult, ExaFilterResult, LoadMCPConfigsOptions, LoadMCPConfigsResult } from "./config";
|
|
12
12
|
export {
|
|
13
13
|
extractExaApiKey,
|
|
14
|
+
filterBrowserMCPServers,
|
|
14
15
|
filterExaMCPServers,
|
|
16
|
+
isBrowserMCPServer,
|
|
15
17
|
isExaMCPServer,
|
|
16
18
|
loadAllMCPConfigs,
|
|
17
19
|
validateServerConfig,
|
package/src/mcp/loader.ts
CHANGED
|
@@ -32,6 +32,8 @@ export interface MCPToolsLoadOptions {
|
|
|
32
32
|
enableProjectConfig?: boolean;
|
|
33
33
|
/** Whether to filter out Exa MCP servers (default: true) */
|
|
34
34
|
filterExa?: boolean;
|
|
35
|
+
/** Whether to filter out browser MCP servers when builtin browser tool is enabled (default: false) */
|
|
36
|
+
filterBrowser?: boolean;
|
|
35
37
|
/** SQLite storage for MCP tool cache (null disables cache) */
|
|
36
38
|
cacheStorage?: AgentStorage | null;
|
|
37
39
|
/** Auth storage used to resolve OAuth credentials before initial MCP connect */
|
|
@@ -69,6 +71,7 @@ export async function discoverAndLoadMCPTools(cwd: string, options?: MCPToolsLoa
|
|
|
69
71
|
onConnecting: options?.onConnecting,
|
|
70
72
|
enableProjectConfig: options?.enableProjectConfig,
|
|
71
73
|
filterExa: options?.filterExa,
|
|
74
|
+
filterBrowser: options?.filterBrowser,
|
|
72
75
|
});
|
|
73
76
|
} catch (error) {
|
|
74
77
|
// If discovery fails entirely, return empty result
|
package/src/mcp/manager.ts
CHANGED
|
@@ -68,6 +68,8 @@ export interface MCPDiscoverOptions {
|
|
|
68
68
|
enableProjectConfig?: boolean;
|
|
69
69
|
/** Whether to filter out Exa MCP servers (default: true) */
|
|
70
70
|
filterExa?: boolean;
|
|
71
|
+
/** Whether to filter out browser MCP servers when builtin browser tool is enabled (default: false) */
|
|
72
|
+
filterBrowser?: boolean;
|
|
71
73
|
/** Called when starting to connect to servers */
|
|
72
74
|
onConnecting?: (serverNames: string[]) => void;
|
|
73
75
|
}
|
|
@@ -105,6 +107,7 @@ export class MCPManager {
|
|
|
105
107
|
const { configs, exaApiKeys, sources } = await loadAllMCPConfigs(this.cwd, {
|
|
106
108
|
enableProjectConfig: options?.enableProjectConfig,
|
|
107
109
|
filterExa: options?.filterExa,
|
|
110
|
+
filterBrowser: options?.filterBrowser,
|
|
108
111
|
});
|
|
109
112
|
const result = await this.connectServers(configs, sources, options?.onConnecting);
|
|
110
113
|
result.exaApiKeys = exaApiKeys;
|
package/src/sdk.ts
CHANGED
|
@@ -806,6 +806,8 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
806
806
|
enableProjectConfig: settings.get("mcp.enableProjectConfig") ?? true,
|
|
807
807
|
// Always filter Exa - we have native integration
|
|
808
808
|
filterExa: true,
|
|
809
|
+
// Filter browser MCP servers when builtin browser tool is active
|
|
810
|
+
filterBrowser: (settings.get("browser.enabled") as boolean) ?? false,
|
|
809
811
|
cacheStorage: settings.getStorage(),
|
|
810
812
|
authStorage,
|
|
811
813
|
});
|
package/src/system-prompt.ts
CHANGED
|
@@ -61,6 +61,7 @@ export async function loadGitContext(cwd: string): Promise<GitContext | null> {
|
|
|
61
61
|
stdout: "pipe",
|
|
62
62
|
stderr: "ignore",
|
|
63
63
|
timeout: timeout,
|
|
64
|
+
killSignal: "SIGKILL",
|
|
64
65
|
});
|
|
65
66
|
return untilAborted(abortSignal, async () => {
|
|
66
67
|
const exitCode = await proc.exited;
|
package/src/tools/bash.ts
CHANGED
|
@@ -17,7 +17,7 @@ import { CachedOutputBlock } from "../tui/output-block";
|
|
|
17
17
|
import type { ToolSession } from ".";
|
|
18
18
|
import { type BashInteractiveResult, runInteractiveBashPty } from "./bash-interactive";
|
|
19
19
|
import { checkBashInterception } from "./bash-interceptor";
|
|
20
|
-
import { applyHeadTail
|
|
20
|
+
import { applyHeadTail } from "./bash-normalize";
|
|
21
21
|
import { expandInternalUrls } from "./bash-skill-urls";
|
|
22
22
|
import type { OutputMeta } from "./output-meta";
|
|
23
23
|
import { allocateOutputArtifact, createTailBuffer } from "./output-utils";
|
|
@@ -75,13 +75,11 @@ export class BashTool implements AgentTool<typeof bashSchema, BashToolDetails> {
|
|
|
75
75
|
onUpdate?: AgentToolUpdateCallback<BashToolDetails>,
|
|
76
76
|
ctx?: AgentToolContext,
|
|
77
77
|
): Promise<AgentToolResult<BashToolDetails>> {
|
|
78
|
-
|
|
79
|
-
const normalized = normalizeBashCommand(rawCommand);
|
|
80
|
-
let command = normalized.command;
|
|
78
|
+
let command = rawCommand;
|
|
81
79
|
|
|
82
|
-
//
|
|
83
|
-
const headLines = head
|
|
84
|
-
const tailLines = tail
|
|
80
|
+
// Only apply explicit head/tail params from tool input.
|
|
81
|
+
const headLines = head;
|
|
82
|
+
const tailLines = tail;
|
|
85
83
|
|
|
86
84
|
// Check interception if enabled and available tools are known
|
|
87
85
|
if (this.session.settings.get("bashInterceptor.enabled")) {
|
|
@@ -140,6 +138,7 @@ export class BashTool implements AgentTool<typeof bashSchema, BashToolDetails> {
|
|
|
140
138
|
})
|
|
141
139
|
: await executeBash(command, {
|
|
142
140
|
cwd: commandCwd,
|
|
141
|
+
sessionKey: this.session.getSessionId?.() ?? undefined,
|
|
143
142
|
timeout: timeoutMs,
|
|
144
143
|
signal,
|
|
145
144
|
env: extraEnv,
|
|
@@ -9,9 +9,9 @@ import * as fs from "node:fs";
|
|
|
9
9
|
import * as os from "node:os";
|
|
10
10
|
import * as path from "node:path";
|
|
11
11
|
import { postmortem } from "@oh-my-pi/pi-utils";
|
|
12
|
-
import { $ } from "bun";
|
|
13
12
|
|
|
14
13
|
const cachedSnapshotPaths = new Map<string, string>();
|
|
14
|
+
const SNAPSHOT_TIMEOUT_MS = 2_000;
|
|
15
15
|
|
|
16
16
|
function sanitizeSnapshotEnv(env: Record<string, string | undefined>): Record<string, string | undefined> {
|
|
17
17
|
const sanitized = { ...env };
|
|
@@ -153,8 +153,23 @@ export async function getOrCreateSnapshot(
|
|
|
153
153
|
|
|
154
154
|
try {
|
|
155
155
|
const snapshotEnv = sanitizeSnapshotEnv(env);
|
|
156
|
-
|
|
157
|
-
|
|
156
|
+
const spawnEnv: Record<string, string> = {};
|
|
157
|
+
for (const [key, value] of Object.entries(snapshotEnv)) {
|
|
158
|
+
if (value !== undefined) {
|
|
159
|
+
spawnEnv[key] = value;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const child = Bun.spawn([shell, "-c", script], {
|
|
163
|
+
env: spawnEnv,
|
|
164
|
+
stdin: "ignore",
|
|
165
|
+
stdout: "ignore",
|
|
166
|
+
stderr: "ignore",
|
|
167
|
+
timeout: SNAPSHOT_TIMEOUT_MS,
|
|
168
|
+
killSignal: "SIGKILL",
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
await child.exited;
|
|
172
|
+
if (child.exitCode === 0 && fs.existsSync(snapshotPath)) {
|
|
158
173
|
cachedSnapshotPaths.set(cacheKey, snapshotPath);
|
|
159
174
|
return snapshotPath;
|
|
160
175
|
}
|