sapper-iq 1.1.27 → 1.1.28

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 (2) hide show
  1. package/package.json +1 -1
  2. package/sapper.mjs +48 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sapper-iq",
3
- "version": "1.1.27",
3
+ "version": "1.1.28",
4
4
  "description": "AI-powered development assistant that executes commands and builds projects",
5
5
  "main": "sapper.mjs",
6
6
  "bin": {
package/sapper.mjs CHANGED
@@ -498,9 +498,9 @@ async function runSapper() {
498
498
 
499
499
  // Quick tips box
500
500
  console.log(box(
501
- `${chalk.yellow('šŸ’”')} Type ${chalk.cyan('/help')} for commands\n` +
501
+ `${chalk.yellow('šŸ’”')} Use ${chalk.cyan('@file')} to attach files (e.g., "fix @app.js")\n` +
502
502
  `${chalk.yellow('šŸ’”')} Type ${chalk.cyan('/scan')} to load entire codebase\n` +
503
- `${chalk.yellow('šŸ’”')} Type ${chalk.cyan('exit')} to quit`,
503
+ `${chalk.yellow('šŸ’”')} Type ${chalk.cyan('/help')} for all commands`,
504
504
  'Quick Tips', 'gray'
505
505
  ));
506
506
  console.log();
@@ -681,6 +681,7 @@ TOOL SYNTAX:
681
681
  if (input.toLowerCase() === '/help') {
682
682
  console.log();
683
683
  const helpContent =
684
+ `${chalk.cyan('@file')} ${chalk.gray('│')} Attach file to prompt (e.g., @src/app.js)\n` +
684
685
  `${chalk.cyan('/scan')} ${chalk.gray('│')} Scan codebase into context\n` +
685
686
  `${chalk.cyan('/recall')} ${chalk.gray('│')} Search memory for relevant context\n` +
686
687
  `${chalk.cyan('/reset /clear')} ${chalk.gray('│')} Clear all context\n` +
@@ -789,7 +790,51 @@ TOOL SYNTAX:
789
790
  continue;
790
791
  }
791
792
 
792
- messages.push({ role: 'user', content: input });
793
+ // Process @file attachments in prompt (e.g., "analyze @package.json" or "fix @src/index.js")
794
+ let processedInput = input;
795
+ const fileAttachments = [];
796
+ const attachRegex = /@([\w.\/\-_]+)/g;
797
+ let attachMatch;
798
+
799
+ while ((attachMatch = attachRegex.exec(input)) !== null) {
800
+ const filePath = attachMatch[1];
801
+ try {
802
+ if (fs.existsSync(filePath)) {
803
+ const stats = fs.statSync(filePath);
804
+ if (stats.isFile()) {
805
+ if (stats.size > MAX_FILE_SIZE) {
806
+ console.log(chalk.yellow(`āš ļø @${filePath} is too large (${Math.round(stats.size/1024)}KB), skipping`));
807
+ } else {
808
+ const content = fs.readFileSync(filePath, 'utf8');
809
+ fileAttachments.push({ path: filePath, content, size: stats.size });
810
+ console.log(chalk.green(`šŸ“Ž Attached: ${filePath} (${Math.round(stats.size/1024)}KB)`));
811
+ }
812
+ }
813
+ } else {
814
+ // Not a file - might be an @mention for something else, ignore
815
+ }
816
+ } catch (e) {
817
+ console.log(chalk.yellow(`āš ļø Could not read @${filePath}: ${e.message}`));
818
+ }
819
+ }
820
+
821
+ // Build the final message with attachments
822
+ if (fileAttachments.length > 0) {
823
+ let attachedContent = '\n\n══════════════════════════════════════\n';
824
+ attachedContent += `šŸ“Ž ATTACHED FILES (${fileAttachments.length})\n`;
825
+ attachedContent += '══════════════════════════════════════\n\n';
826
+
827
+ for (const file of fileAttachments) {
828
+ attachedContent += `ā”Œā”€ā”€ā”€ ${file.path} ───\n`;
829
+ attachedContent += file.content;
830
+ if (!file.content.endsWith('\n')) attachedContent += '\n';
831
+ attachedContent += `└─── END ${file.path} ───\n\n`;
832
+ }
833
+
834
+ processedInput = input + attachedContent;
835
+ }
836
+
837
+ messages.push({ role: 'user', content: processedInput });
793
838
 
794
839
  let toolRounds = 0; // Prevent infinite loops
795
840
  const MAX_TOOL_ROUNDS = 20;