sparkecoder 0.1.59 → 0.1.60

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 (95) hide show
  1. package/dist/agent/index.js +74 -27
  2. package/dist/agent/index.js.map +1 -1
  3. package/dist/cli.js +88 -34
  4. package/dist/cli.js.map +1 -1
  5. package/dist/index.js +87 -33
  6. package/dist/index.js.map +1 -1
  7. package/dist/server/index.js +87 -33
  8. package/dist/server/index.js.map +1 -1
  9. package/dist/skills/default/browser.md +143 -0
  10. package/dist/skills/default/code-review.md +122 -0
  11. package/dist/skills/default/debugging.md +105 -0
  12. package/dist/skills/default/refactoring.md +197 -0
  13. package/dist/tools/index.d.ts +16 -1
  14. package/dist/tools/index.js +74 -27
  15. package/dist/tools/index.js.map +1 -1
  16. package/package.json +4 -1
  17. package/src/skills/default/browser.md +143 -0
  18. package/src/skills/default/code-review.md +122 -0
  19. package/src/skills/default/debugging.md +105 -0
  20. package/src/skills/default/refactoring.md +197 -0
  21. package/web/.next/BUILD_ID +1 -1
  22. package/web/.next/standalone/web/.next/BUILD_ID +1 -1
  23. package/web/.next/standalone/web/.next/build-manifest.json +2 -2
  24. package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
  25. package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
  26. package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
  27. package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  28. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  29. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  30. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  31. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  32. package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
  33. package/web/.next/standalone/web/.next/server/app/_not-found.rsc +1 -1
  34. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  35. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  36. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  37. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  38. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  39. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  40. package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
  41. package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +1 -1
  42. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +1 -1
  43. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
  44. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +1 -1
  45. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +1 -1
  46. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
  47. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
  48. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
  49. package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
  50. package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +1 -1
  51. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +1 -1
  52. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
  53. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +1 -1
  54. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +1 -1
  55. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
  56. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
  57. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
  58. package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
  59. package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +1 -1
  60. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +1 -1
  61. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
  62. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +1 -1
  63. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +1 -1
  64. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
  65. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
  66. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
  67. package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
  68. package/web/.next/standalone/web/.next/server/app/docs.rsc +1 -1
  69. package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +1 -1
  70. package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
  71. package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +1 -1
  72. package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +1 -1
  73. package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
  74. package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
  75. package/web/.next/standalone/web/.next/server/app/index.html +1 -1
  76. package/web/.next/standalone/web/.next/server/app/index.rsc +1 -1
  77. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +1 -1
  78. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +1 -1
  79. package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +1 -1
  80. package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  81. package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
  82. package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  83. package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
  84. package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
  85. package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
  86. package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
  87. /package/web/.next/standalone/web/.next/static/{static/u5qqIWWrYpWW_mZUgKKjg → R5xiWSOp_Nqqe_js-LROo}/_buildManifest.js +0 -0
  88. /package/web/.next/standalone/web/.next/static/{static/u5qqIWWrYpWW_mZUgKKjg → R5xiWSOp_Nqqe_js-LROo}/_clientMiddlewareManifest.json +0 -0
  89. /package/web/.next/standalone/web/.next/static/{static/u5qqIWWrYpWW_mZUgKKjg → R5xiWSOp_Nqqe_js-LROo}/_ssgManifest.js +0 -0
  90. /package/web/.next/standalone/web/.next/static/{u5qqIWWrYpWW_mZUgKKjg → static/R5xiWSOp_Nqqe_js-LROo}/_buildManifest.js +0 -0
  91. /package/web/.next/standalone/web/.next/static/{u5qqIWWrYpWW_mZUgKKjg → static/R5xiWSOp_Nqqe_js-LROo}/_clientMiddlewareManifest.json +0 -0
  92. /package/web/.next/standalone/web/.next/static/{u5qqIWWrYpWW_mZUgKKjg → static/R5xiWSOp_Nqqe_js-LROo}/_ssgManifest.js +0 -0
  93. /package/web/.next/static/{u5qqIWWrYpWW_mZUgKKjg → R5xiWSOp_Nqqe_js-LROo}/_buildManifest.js +0 -0
  94. /package/web/.next/static/{u5qqIWWrYpWW_mZUgKKjg → R5xiWSOp_Nqqe_js-LROo}/_clientMiddlewareManifest.json +0 -0
  95. /package/web/.next/static/{u5qqIWWrYpWW_mZUgKKjg → R5xiWSOp_Nqqe_js-LROo}/_ssgManifest.js +0 -0
@@ -426,7 +426,7 @@ var init_hasher = __esm({
426
426
  });
427
427
 
428
428
  // src/semantic/chunker.ts
429
- import { extname as extname5, basename as basename2 } from "path";
429
+ import { extname as extname6, basename as basename2 } from "path";
430
430
  var init_chunker = __esm({
431
431
  "src/semantic/chunker.ts"() {
432
432
  "use strict";
@@ -1296,26 +1296,41 @@ Terminal output is stored in the global SparkECoder data directory. Use the \`ta
1296
1296
  import { tool as tool2 } from "ai";
1297
1297
  import { z as z3 } from "zod";
1298
1298
  import { readFile as readFile2, stat } from "fs/promises";
1299
- import { resolve as resolve2, relative, isAbsolute } from "path";
1299
+ import { resolve as resolve2, relative, isAbsolute, extname } from "path";
1300
1300
  import { existsSync as existsSync3 } from "fs";
1301
1301
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
1302
+ var MAX_IMAGE_SIZE = 20 * 1024 * 1024;
1302
1303
  var MAX_OUTPUT_CHARS3 = 5e4;
1304
+ var IMAGE_EXTENSIONS = {
1305
+ ".png": "image/png",
1306
+ ".jpg": "image/jpeg",
1307
+ ".jpeg": "image/jpeg",
1308
+ ".gif": "image/gif",
1309
+ ".webp": "image/webp"
1310
+ };
1311
+ function isImageFile(filePath) {
1312
+ return extname(filePath).toLowerCase() in IMAGE_EXTENSIONS;
1313
+ }
1314
+ function getImageMediaType(filePath) {
1315
+ return IMAGE_EXTENSIONS[extname(filePath).toLowerCase()] || "image/png";
1316
+ }
1303
1317
  var readFileInputSchema = z3.object({
1304
- path: z3.string().describe("The path to the file to read. Can be relative to working directory or absolute."),
1305
- startLine: z3.number().optional().describe("Optional: Start reading from this line number (1-indexed)"),
1306
- endLine: z3.number().optional().describe("Optional: Stop reading at this line number (1-indexed, inclusive)")
1318
+ path: z3.string().describe("The path to the file to read. Can be relative to working directory or absolute. Supports text files and images (png, jpg, jpeg, gif, webp)."),
1319
+ startLine: z3.number().optional().describe("Optional: Start reading from this line number (1-indexed). Only for text files."),
1320
+ endLine: z3.number().optional().describe("Optional: Stop reading at this line number (1-indexed, inclusive). Only for text files.")
1307
1321
  });
1308
1322
  function createReadFileTool(options) {
1309
1323
  return tool2({
1310
1324
  description: `Read the contents of a file. Provide a path relative to the working directory (${options.workingDirectory}) or an absolute path.
1311
- Large files will be automatically truncated. Binary files are not supported.
1312
- Use this to understand existing code, check file contents, or gather context.`,
1325
+ Supports text files (automatically truncated if large) and image files (png, jpg, jpeg, gif, webp).
1326
+ For images, the file contents are returned as visual data you can see and analyze.
1327
+ Use this to understand existing code, check file contents, view screenshots, or gather context.`,
1313
1328
  inputSchema: readFileInputSchema,
1314
- execute: async ({ path, startLine, endLine }) => {
1329
+ execute: async ({ path: filePath, startLine, endLine }) => {
1315
1330
  try {
1316
- const absolutePath = isAbsolute(path) ? path : resolve2(options.workingDirectory, path);
1331
+ const absolutePath = isAbsolute(filePath) ? filePath : resolve2(options.workingDirectory, filePath);
1317
1332
  const relativePath = relative(options.workingDirectory, absolutePath);
1318
- if (relativePath.startsWith("..") && !isAbsolute(path)) {
1333
+ if (relativePath.startsWith("..") && !isAbsolute(filePath)) {
1319
1334
  return {
1320
1335
  success: false,
1321
1336
  error: "Path escapes the working directory. Use an absolute path if intentional.",
@@ -1325,22 +1340,43 @@ Use this to understand existing code, check file contents, or gather context.`,
1325
1340
  if (!existsSync3(absolutePath)) {
1326
1341
  return {
1327
1342
  success: false,
1328
- error: `File not found: ${path}`,
1343
+ error: `File not found: ${filePath}`,
1329
1344
  content: null
1330
1345
  };
1331
1346
  }
1332
1347
  const stats = await stat(absolutePath);
1333
- if (stats.size > MAX_FILE_SIZE) {
1348
+ if (stats.isDirectory()) {
1334
1349
  return {
1335
1350
  success: false,
1336
- error: `File is too large (${(stats.size / 1024 / 1024).toFixed(2)}MB). Maximum size is ${MAX_FILE_SIZE / 1024 / 1024}MB.`,
1351
+ error: 'Path is a directory, not a file. Use bash with "ls" to list directory contents.',
1337
1352
  content: null
1338
1353
  };
1339
1354
  }
1340
- if (stats.isDirectory()) {
1355
+ if (isImageFile(absolutePath)) {
1356
+ if (stats.size > MAX_IMAGE_SIZE) {
1357
+ return {
1358
+ success: false,
1359
+ error: `Image is too large (${(stats.size / 1024 / 1024).toFixed(2)}MB). Maximum size is ${MAX_IMAGE_SIZE / 1024 / 1024}MB.`,
1360
+ content: null
1361
+ };
1362
+ }
1363
+ const buffer = await readFile2(absolutePath);
1364
+ const base64 = buffer.toString("base64");
1365
+ const mediaType = getImageMediaType(absolutePath);
1366
+ return {
1367
+ success: true,
1368
+ path: absolutePath,
1369
+ relativePath: relative(options.workingDirectory, absolutePath),
1370
+ content: `[Image: ${relativePath} (${mediaType}, ${(stats.size / 1024).toFixed(1)}KB)]`,
1371
+ mediaType,
1372
+ imageData: base64,
1373
+ sizeBytes: stats.size
1374
+ };
1375
+ }
1376
+ if (stats.size > MAX_FILE_SIZE) {
1341
1377
  return {
1342
1378
  success: false,
1343
- error: 'Path is a directory, not a file. Use bash with "ls" to list directory contents.',
1379
+ error: `File is too large (${(stats.size / 1024 / 1024).toFixed(2)}MB). Maximum size is ${MAX_FILE_SIZE / 1024 / 1024}MB.`,
1344
1380
  content: null
1345
1381
  };
1346
1382
  }
@@ -1356,9 +1392,7 @@ Use this to understand existing code, check file contents, or gather context.`,
1356
1392
  content: null
1357
1393
  };
1358
1394
  }
1359
- content = lines.slice(start, end).join("\n");
1360
- const lineNumbers = lines.slice(start, end).map((line, idx) => `${(start + idx + 1).toString().padStart(4)}: ${line}`).join("\n");
1361
- content = lineNumbers;
1395
+ content = lines.slice(start, end).map((line, idx) => `${(start + idx + 1).toString().padStart(4)}: ${line}`).join("\n");
1362
1396
  }
1363
1397
  const truncatedContent = truncateOutput(content, MAX_OUTPUT_CHARS3);
1364
1398
  const wasTruncated = truncatedContent.length < content.length;
@@ -1385,6 +1419,19 @@ Use this to understand existing code, check file contents, or gather context.`,
1385
1419
  content: null
1386
1420
  };
1387
1421
  }
1422
+ },
1423
+ toModelOutput: ({ output }) => {
1424
+ if (output && typeof output === "object" && "imageData" in output && output.imageData) {
1425
+ const result = output;
1426
+ return {
1427
+ type: "content",
1428
+ value: [
1429
+ { type: "text", text: result.content },
1430
+ { type: "image-data", data: result.imageData, mediaType: result.mediaType }
1431
+ ]
1432
+ };
1433
+ }
1434
+ return typeof output === "string" ? { type: "text", value: output } : { type: "json", value: output };
1388
1435
  }
1389
1436
  });
1390
1437
  }
@@ -1449,7 +1496,7 @@ async function backupFile(sessionId, workingDirectory, filePath) {
1449
1496
  }
1450
1497
 
1451
1498
  // src/lsp/index.ts
1452
- import { extname as extname2, dirname as dirname4 } from "path";
1499
+ import { extname as extname3, dirname as dirname4 } from "path";
1453
1500
 
1454
1501
  // src/lsp/servers.ts
1455
1502
  import { spawn } from "child_process";
@@ -1572,9 +1619,9 @@ import {
1572
1619
  import { pathToFileURL, fileURLToPath } from "url";
1573
1620
  import { readFile as readFile4 } from "fs/promises";
1574
1621
  import { existsSync as existsSync6 } from "fs";
1575
- import { extname, normalize } from "path";
1622
+ import { extname as extname2, normalize } from "path";
1576
1623
  function getLanguageId(filePath) {
1577
- const ext = extname(filePath).toLowerCase();
1624
+ const ext = extname2(filePath).toLowerCase();
1578
1625
  const map = {
1579
1626
  ".ts": "typescript",
1580
1627
  ".tsx": "typescriptreact",
@@ -1962,7 +2009,7 @@ var state = {
1962
2009
  };
1963
2010
  async function getClientForFile(filePath) {
1964
2011
  const normalized = normalizePath(filePath);
1965
- const ext = extname2(normalized);
2012
+ const ext = extname3(normalized);
1966
2013
  const serverDef = getServerForExtension(ext);
1967
2014
  if (!serverDef) {
1968
2015
  return null;
@@ -2055,7 +2102,7 @@ async function formatDiagnosticsOutput(filePath, options = {}) {
2055
2102
  return formatDiagnosticsForAgent(filePath, diagnostics, options);
2056
2103
  }
2057
2104
  function isSupported(filePath) {
2058
- const ext = extname2(filePath);
2105
+ const ext = extname3(filePath);
2059
2106
  return getServerForExtension(ext) !== null;
2060
2107
  }
2061
2108
 
@@ -2402,7 +2449,7 @@ import { z as z6 } from "zod";
2402
2449
  // src/skills/index.ts
2403
2450
  init_types();
2404
2451
  import { readFile as readFile6, readdir } from "fs/promises";
2405
- import { resolve as resolve6, basename, extname as extname3, relative as relative4 } from "path";
2452
+ import { resolve as resolve6, basename, extname as extname4, relative as relative4 } from "path";
2406
2453
  import { existsSync as existsSync8 } from "fs";
2407
2454
  import { minimatch } from "minimatch";
2408
2455
  function parseSkillFrontmatter(content) {
@@ -2473,7 +2520,7 @@ function parseSkillFrontmatter(content) {
2473
2520
  }
2474
2521
  }
2475
2522
  function getSkillNameFromPath(filePath) {
2476
- return basename(filePath, extname3(filePath)).replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
2523
+ return basename(filePath, extname4(filePath)).replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
2477
2524
  }
2478
2525
  async function loadSkillsFromDirectory(directory, options = {}) {
2479
2526
  const {
@@ -2661,7 +2708,7 @@ Once loaded, a skill's content will be available in the conversation context.`,
2661
2708
  // src/tools/linter.ts
2662
2709
  import { tool as tool6 } from "ai";
2663
2710
  import { z as z7 } from "zod";
2664
- import { resolve as resolve7, relative as relative5, isAbsolute as isAbsolute3, extname as extname4 } from "path";
2711
+ import { resolve as resolve7, relative as relative5, isAbsolute as isAbsolute3, extname as extname5 } from "path";
2665
2712
  import { existsSync as existsSync9 } from "fs";
2666
2713
  import { readdir as readdir2, stat as stat2 } from "fs/promises";
2667
2714
  var linterInputSchema = z7.object({
@@ -2684,7 +2731,7 @@ async function findSupportedFiles(dir, workingDirectory, maxFiles = 50) {
2684
2731
  }
2685
2732
  await walk(fullPath);
2686
2733
  } else if (entry.isFile()) {
2687
- const ext = extname4(entry.name);
2734
+ const ext = extname5(entry.name);
2688
2735
  if (supportedExtensions.includes(ext)) {
2689
2736
  files.push(fullPath);
2690
2737
  }