shmakk 1.2.4 → 1.2.5

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 (51) hide show
  1. package/.env.example +11 -0
  2. package/README.md +75 -1
  3. package/docs/index.html +154 -16
  4. package/docs/mcp.md +78 -0
  5. package/docs/ssh.md +82 -0
  6. package/docs/vibedit-analysis.md +375 -0
  7. package/docs/vim.md +110 -0
  8. package/docs/voice.md +4 -0
  9. package/package.json +9 -5
  10. package/scripts/test-vibedit.js +45 -0
  11. package/scripts/vibedit-demo.sh +52 -0
  12. package/skills/shmakk-skill-creator.md +269 -0
  13. package/src/_check.js +7 -0
  14. package/src/_check_schema.js +5 -0
  15. package/src/_cleanup.js +18 -0
  16. package/src/_fix.js +9 -0
  17. package/src/_test_import.js +15 -0
  18. package/src/agent.js +11 -4
  19. package/src/browser-daemon.js +209 -0
  20. package/src/browser.js +10 -0
  21. package/src/cli/browserDaemon.js +60 -0
  22. package/src/cli/connectBrowser.js +137 -0
  23. package/src/cli.js +235 -8
  24. package/src/completions.js +8 -0
  25. package/src/control.js +273 -1
  26. package/src/core/browserConnector.js +523 -0
  27. package/src/electron.js +305 -0
  28. package/src/endpoints.js +74 -9
  29. package/src/index.js +24 -1
  30. package/src/llm.js +501 -61
  31. package/src/mobile.js +307 -0
  32. package/src/notify.js +51 -3
  33. package/src/orchestrator.js +35 -1
  34. package/src/pty.js +11 -6
  35. package/src/review.js +45 -11
  36. package/src/self-commands.js +153 -0
  37. package/src/session-convert.js +508 -0
  38. package/src/session-search.js +31 -0
  39. package/src/session.js +384 -46
  40. package/src/skills/browserActions.ts +984 -0
  41. package/src/skills.js +451 -24
  42. package/src/system-prompt.js +31 -25
  43. package/src/tools.js +81 -0
  44. package/src/vibedit/control.js +534 -0
  45. package/src/vibedit/electron.js +108 -0
  46. package/src/vibedit/files.js +171 -0
  47. package/src/vibedit/index.js +298 -0
  48. package/src/vibedit/overlay.js +1482 -0
  49. package/src/vibedit/prompts.js +245 -0
  50. package/src/vibedit/state.js +32 -0
  51. package/src/vim.js +410 -0
@@ -52,14 +52,18 @@ Core Principles:
52
52
  - Do not delete files, overwrite large sections, rename public APIs, change schemas, run destructive commands, or perform broad refactors without explicit user confirmation.
53
53
  - Never expose secrets, credentials, tokens, private keys, environment values, or sensitive paths.
54
54
 
55
- Tool Call Format:
56
- - If native tool calls are available, use native tool calls only.
57
- - If native tool calls are not available, output only this exact JSON shape and no prose:
58
-
55
+ Tool Call Format — use whichever your model supports natively:
56
+ - Native tool calls (preferred when your API endpoint supports tool_use / tool_calls).
57
+ - XML format:
58
+ <tool_calls>
59
+ <invoke name="tool_name">
60
+ <parameter name="arg_name" string="true|false">value</parameter>
61
+ </invoke>
62
+ </tool_calls>
63
+ - JSON fallback format (no other prose in the message):
59
64
  {"shmakk_actions":[{"tool":"tool_name","args":{...}}]}
60
65
 
61
- - Do not use XML tool calls.
62
- - Do not mix JSON tool calls with explanatory text.
66
+ - Do not mix tool call text with explanatory prose.
63
67
  - Do not wrap JSON tool calls in markdown fences.
64
68
  - Do not emit invalid JSON.
65
69
  - Do not include comments inside JSON.
@@ -224,24 +228,33 @@ Provide a concise final summary with:
224
228
 
225
229
  Examples:
226
230
 
227
- Correct fallback JSON tool call:
228
- {"shmakk_actions":[{"tool":"list_dir","args":{"path":"src"}}]}
229
-
230
- Correct fallback JSON tool call:
231
- {"shmakk_actions":[{"tool":"read_file","args":{"path":"package.json"}}]}
232
-
233
- Correct fallback JSON tool call:
234
- {"shmakk_actions":[{"tool":"run","args":{"cmd":"npm test"}}]}
235
-
236
- Incorrect:
237
- I will check the src directory:
231
+ Correct XML tool call:
232
+ <tool_calls>
233
+ <invoke name="list_dir">
234
+ <parameter name="path" string="true">src</parameter>
235
+ </invoke>
236
+ </tool_calls>
237
+
238
+ Correct XML tool call with explanation (one short sentence before the XML is fine):
239
+ I'll check the project structure first.
240
+ <tool_calls>
241
+ <invoke name="list_dir">
242
+ <parameter name="path" string="true">src</parameter>
243
+ </invoke>
244
+ </tool_calls>
245
+
246
+ Correct JSON fallback:
238
247
  {"shmakk_actions":[{"tool":"list_dir","args":{"path":"src"}}]}
239
248
 
240
- Incorrect:
249
+ Incorrect (wrapping JSON in markdown fences):
241
250
  \`\`\`json
242
251
  {"shmakk_actions":[{"tool":"list_dir","args":{"path":"src"}}]}
243
252
  \`\`\`
244
253
 
254
+ Incorrect (mixing prose with JSON):
255
+ I'll check the src directory:
256
+ {"shmakk_actions":[{"tool":"list_dir","args":{"path":"src"}}]}
257
+
245
258
  Incorrect:
246
259
  Can you run npm test for me?
247
260
 
@@ -253,13 +266,6 @@ Remember:
253
266
  - Use tools directly.
254
267
  - Prefer minimal edits.
255
268
  - Verify when possible.
256
- - Use only native tool calls or the exact JSON fallback.
257
-
258
- Final rule:
259
- Never output XML, markdown, or prose when calling a tool.
260
- Use native tool calls if available.
261
- Otherwise output only:
262
- {"shmakk_actions":[{"tool":"tool_name","args":{...}}]}
263
269
  ${indexHint}
264
270
  ${activeSkillText ? `\n\n${activeSkillText}` : ''}
265
271
  ${specialistHint ? `\n\n${specialistHint.trim()}` : ''}
package/src/tools.js CHANGED
@@ -7,6 +7,8 @@ const { execFile } = require('child_process');
7
7
  const { classifyRunCommand, isSecretPath } = require('./safety');
8
8
  const { webSearch, fetchUrl } = require('./web');
9
9
  const { dispatchBrowser, classifyBrowserCommand } = require('./browser');
10
+ const { dispatchMobile, classifyMobileCommand } = require('./mobile');
11
+ const { dispatchElectron, classifyElectronCommand } = require('./electron');
10
12
  const { recordEdit } = require('./edit-tracker');
11
13
  const { appendMemory } = require('./memory');
12
14
  const { isMutationTool, hashArgs } = require('./guard');
@@ -178,6 +180,50 @@ const TOOLS = [
178
180
  },
179
181
  },
180
182
  }},
183
+ { type: 'function', function: {
184
+ name: 'mobile',
185
+ description: 'Control an Android device/emulator via ADB. Commands: screenshot (capture screen as PNG), click (tap at x,y coordinates), type (input text), swipe (drag from x1,y1 to x2,y2), key (press BACK/HOME/etc), read_page (parse UI hierarchy via uiautomator), list_apps (list installed packages), launch (start app by package name), close (force-stop app), wait (pause in ms). Requires adb on PATH and a connected device.',
186
+ parameters: {
187
+ type: 'object',
188
+ required: ['command'],
189
+ properties: {
190
+ command: { type: 'string', enum: ['screenshot', 'click', 'type', 'swipe', 'key', 'read_page', 'list_apps', 'launch', 'close', 'wait'] },
191
+ x: { type: 'number', description: 'X coordinate for click' },
192
+ y: { type: 'number', description: 'Y coordinate for click' },
193
+ x1: { type: 'number', description: 'Start X for swipe' },
194
+ y1: { type: 'number', description: 'Start Y for swipe' },
195
+ x2: { type: 'number', description: 'End X for swipe' },
196
+ y2: { type: 'number', description: 'End Y for swipe' },
197
+ duration: { type: 'number', description: 'Swipe duration in ms' },
198
+ text: { type: 'string', description: 'Text to type' },
199
+ code: { type: 'string', description: 'Key code: BACK, HOME, ENTER, DELETE, MENU, APP_SWITCH, VOLUME_UP, VOLUME_DOWN' },
200
+ package: { type: 'string', description: 'Android package name (e.g. com.example.app)' },
201
+ filter: { type: 'string', description: 'Package name filter for list_apps' },
202
+ ms: { type: 'number', description: 'Milliseconds to wait' },
203
+ },
204
+ },
205
+ }},
206
+ { type: 'function', function: {
207
+ name: 'electron',
208
+ description: 'Control an Electron desktop app via Chrome DevTools Protocol (CDP). Commands: screenshot (capture window as PNG), navigate (go to URL), click (CSS selector), type (fill input), read_page (extract page content, links, forms), evaluate (run JS), select (dropdown), wait (for selector or seconds), scroll (up/down), close (disconnect), connect (attach to a debug port). The Electron app must be running with --remote-debugging-port (default 9222). Requires playwright installed.',
209
+ parameters: {
210
+ type: 'object',
211
+ required: ['command'],
212
+ properties: {
213
+ command: { type: 'string', enum: ['screenshot', 'navigate', 'click', 'type', 'read_page', 'evaluate', 'select', 'wait', 'scroll', 'close', 'connect'] },
214
+ url: { type: 'string', description: 'URL for navigate' },
215
+ selector: { type: 'string', description: 'CSS selector for click/type/select/wait' },
216
+ text: { type: 'string', description: 'Text to type or option to select' },
217
+ code: { type: 'string', description: 'JavaScript for evaluate' },
218
+ seconds: { type: 'number', description: 'Seconds to wait' },
219
+ direction: { type: 'string', enum: ['up', 'down'], description: 'Scroll direction' },
220
+ amount: { type: 'number', description: 'Scroll amount in pixels' },
221
+ debugPort: { type: 'number', description: 'CDP debug port. Default 9222.' },
222
+ value: { type: 'string', description: 'Option value for select' },
223
+ fullPage: { type: 'boolean', description: 'Screenshot full page. Default true.' },
224
+ },
225
+ },
226
+ }},
181
227
  { type: 'function', function: {
182
228
  name: 'image_gen',
183
229
  description: 'Generate an image from a text prompt using OpenAI DALL-E. The image is saved to disk and the file path is returned. Requires SHMAKK_OPENAI_API_KEY env var.',
@@ -299,6 +345,8 @@ function classifyTool(name, args, mcpManager) {
299
345
  if (name === 'run') return classifyRunCommand(args.cmd || '');
300
346
  if (name === 'web_search' || name === 'fetch_url') return 'safe';
301
347
  if (name === 'browser') return classifyBrowserCommand(args);
348
+ if (name === 'mobile') return classifyMobileCommand(args);
349
+ if (name === 'electron') return classifyElectronCommand(args);
302
350
  if (name === 'remember') return 'safe';
303
351
  if (name === 'image_gen') return 'unsafe'; // external API call, costs money
304
352
  if (name === 'tts_generate') return 'safe'; // local-only, no network
@@ -330,6 +378,27 @@ function describeTool(name, args, mcpManager) {
330
378
  if (cmd === 'evaluate') return `browser eval JS`;
331
379
  return `browser ${cmd}`;
332
380
  }
381
+ if (name === 'mobile') {
382
+ const cmd = args.command || '';
383
+ if (cmd === 'screenshot') return 'mobile screenshot';
384
+ if (cmd === 'click') return `mobile click (${args.x}, ${args.y})`;
385
+ if (cmd === 'type') return `mobile type "${(args.text || '').slice(0, 40)}"`;
386
+ if (cmd === 'swipe') return `mobile swipe (${args.x1},${args.y1}) to (${args.x2},${args.y2})`;
387
+ if (cmd === 'read_page') return 'mobile read page';
388
+ if (cmd === 'launch') return `mobile launch ${args.package || ''}`;
389
+ if (cmd === 'close') return `mobile close ${args.package || ''}`;
390
+ return `mobile ${cmd}`;
391
+ }
392
+ if (name === 'electron') {
393
+ const cmd = args.command || '';
394
+ if (cmd === 'screenshot') return 'electron screenshot';
395
+ if (cmd === 'navigate') return `electron navigate ${args.url || ''}`;
396
+ if (cmd === 'click') return `electron click ${args.selector || ''}`;
397
+ if (cmd === 'type') return `electron type into ${args.selector || ''}`;
398
+ if (cmd === 'read_page') return 'electron read page content';
399
+ if (cmd === 'connect') return `electron connect port ${args.debugPort || 9222}`;
400
+ return `electron ${cmd}`;
401
+ }
333
402
  if (name === 'image_gen') return `image_gen: "${(args.prompt || '').slice(0, 80)}" (${args.size || '1024x1024'})`;
334
403
  if (name === 'tts_generate') return `tts_generate: "${(args.text || '').slice(0, 80)}" (voice: ${args.voice || 'af_heart'})`;
335
404
  if (name === 'video_probe') return `video_probe ${args.path || ''}`;
@@ -528,6 +597,12 @@ async function dispatchTool(name, args, roots, confirmTool, signal, mcpManager)
528
597
  if (name === 'browser') {
529
598
  return await dispatchBrowser(args);
530
599
  }
600
+ if (name === 'mobile') {
601
+ return await dispatchMobile(args);
602
+ }
603
+ if (name === 'electron') {
604
+ return await dispatchElectron(args);
605
+ }
531
606
  if (name === 'remember') {
532
607
  const r = appendMemory({
533
608
  category: args.category,
@@ -603,6 +678,12 @@ async function dispatchTool(name, args, roots, confirmTool, signal, mcpManager)
603
678
  prompt,
604
679
  size,
605
680
  revised_prompt: postData.data[0].revised_prompt || prompt,
681
+ images: [{
682
+ mimeType: 'image/png',
683
+ data: b64,
684
+ dataLength: b64.length,
685
+ truncated: false,
686
+ }],
606
687
  };
607
688
  }
608
689
  if (name === 'tts_generate') {