@arcteninc/core 0.0.145 → 0.0.146

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcteninc/core",
3
- "version": "0.0.145",
3
+ "version": "0.0.146",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -135,7 +135,12 @@ async function discoverContext(): Promise<InitContext> {
135
135
  }
136
136
  if (!envContent.includes('ARCTEN_API_KEY')) {
137
137
  envContent += `\nARCTEN_API_KEY=${apiKeyInput}\n`;
138
- envContent += `NEXT_PUBLIC_ARCTEN_API_URL=https://api.arcten.com\n`;
138
+ // Use correct env prefix based on framework
139
+ if (framework === 'vite') {
140
+ envContent += `VITE_ARCTEN_API_URL=https://api.arcten.com\n`;
141
+ } else {
142
+ envContent += `NEXT_PUBLIC_ARCTEN_API_URL=https://api.arcten.com\n`;
143
+ }
139
144
  fs.writeFileSync(envPath, envContent.trim() + '\n');
140
145
  console.log(' Saved API key to .env.local');
141
146
  }
@@ -429,15 +434,100 @@ export async function POST(req: NextRequest) {
429
434
  fs.writeFileSync(path.join(tokenDir, 'route.ts'), tokenRouteContent);
430
435
  createdFiles.push(`${appDir}/api/arcten/token/route.ts`);
431
436
  console.log(` Created ${appDir}/api/arcten/token/route.ts`);
437
+ } else if (framework === 'vite') {
438
+ // Create Vite middleware plugin for token endpoint
439
+ const vitePluginContent = `// Arcten Token Plugin for Vite Dev Server
440
+ // This provides the /api/arcten/token endpoint during development
441
+
442
+ export function arctenTokenPlugin() {
443
+ return {
444
+ name: 'arcten-token',
445
+ configureServer(server: any) {
446
+ server.middlewares.use('/api/arcten/token', async (req: any, res: any, next: any) => {
447
+ if (req.method !== 'POST') {
448
+ return next();
449
+ }
450
+
451
+ let body = '';
452
+ req.on('data', (chunk: any) => body += chunk);
453
+ req.on('end', async () => {
454
+ try {
455
+ const { user } = JSON.parse(body || '{}');
456
+ const apiKey = process.env.ARCTEN_API_KEY;
457
+
458
+ if (!apiKey) {
459
+ res.statusCode = 500;
460
+ res.setHeader('Content-Type', 'application/json');
461
+ res.end(JSON.stringify({ error: 'ARCTEN_API_KEY not configured' }));
462
+ return;
463
+ }
464
+
465
+ // Dynamic import to avoid bundling issues
466
+ const { verifyToken } = await import('@arcteninc/core/server');
467
+ const tokenResponse = await verifyToken({
468
+ apiKey,
469
+ user: user || { id: 'anonymous', name: 'User' },
470
+ apiUrl: process.env.VITE_ARCTEN_API_URL || 'https://api.arcten.com',
471
+ });
472
+
473
+ res.setHeader('Content-Type', 'application/json');
474
+ res.end(JSON.stringify(tokenResponse));
475
+ } catch (error: any) {
476
+ console.error('Token generation error:', error);
477
+ res.statusCode = 500;
478
+ res.setHeader('Content-Type', 'application/json');
479
+ res.end(JSON.stringify({ error: error.message || 'Failed to generate token' }));
480
+ }
481
+ });
482
+ });
483
+ },
484
+ };
485
+ }
486
+ `;
487
+ fs.writeFileSync(path.join(projectRoot, 'vite-plugin-arcten.ts'), vitePluginContent);
488
+ createdFiles.push('vite-plugin-arcten.ts');
489
+ console.log(' Created vite-plugin-arcten.ts');
490
+
491
+ // Update vite.config.ts to include the plugin
492
+ const viteConfigPath = path.join(projectRoot, 'vite.config.ts');
493
+ if (fs.existsSync(viteConfigPath)) {
494
+ let viteConfig = fs.readFileSync(viteConfigPath, 'utf-8');
495
+
496
+ if (!viteConfig.includes('arctenTokenPlugin')) {
497
+ // Add import at the top
498
+ if (viteConfig.includes("from 'vite'")) {
499
+ viteConfig = viteConfig.replace(
500
+ /from ['"]vite['"]/,
501
+ `from 'vite'\nimport { arctenTokenPlugin } from './vite-plugin-arcten'`
502
+ );
503
+ } else {
504
+ viteConfig = `import { arctenTokenPlugin } from './vite-plugin-arcten'\n` + viteConfig;
505
+ }
506
+
507
+ // Add to plugins array
508
+ viteConfig = viteConfig.replace(
509
+ /plugins:\s*\[/,
510
+ 'plugins: [arctenTokenPlugin(), '
511
+ );
512
+
513
+ fs.writeFileSync(viteConfigPath, viteConfig);
514
+ createdFiles.push('vite.config.ts (modified)');
515
+ console.log(' Modified vite.config.ts');
516
+ }
517
+ }
432
518
  }
433
519
 
434
520
  // 3. Create wrapper component based on placement
435
521
  const toolsImportPath = path.relative(appDirPath, context.toolsFile).replace(/\.ts$/, '').replace(/\\/g, '/');
436
522
 
437
- if (placement === 'everywhere') {
438
- const wrapperContent = `"use client";
523
+ // Get the correct env variable syntax based on framework
524
+ const envVarSyntax = framework === 'vite'
525
+ ? 'import.meta.env.VITE_ARCTEN_API_URL'
526
+ : 'process.env.NEXT_PUBLIC_ARCTEN_API_URL';
527
+ const useClientDirective = framework === 'vite' ? '' : '"use client";\n\n';
439
528
 
440
- import { ArctenAgent } from "@arcteninc/core";
529
+ if (placement === 'everywhere') {
530
+ const wrapperContent = `${useClientDirective}import { ArctenAgent } from "@arcteninc/core";
441
531
  import { toolMetadata } from "../.arcten/tool-metadata";
442
532
  import { allTools, safeToolNames } from "../.arcten/arcten.tools";
443
533
 
@@ -452,7 +542,7 @@ export function ArctenWrapper({ children }: ArctenWrapperProps) {
452
542
  {children}
453
543
  </div>
454
544
  <ArctenAgent
455
- apiBaseUrl={process.env.NEXT_PUBLIC_ARCTEN_API_URL || "https://api.arcten.com"}
545
+ apiBaseUrl={${envVarSyntax} || "https://api.arcten.com"}
456
546
  user={{ id: "user-1", name: "User" }}
457
547
  tools={allTools}
458
548
  safeToolNames={safeToolNames}
@@ -468,46 +558,74 @@ export default ArctenWrapper;
468
558
  createdFiles.push(`${appDir}/ArctenWrapper.tsx`);
469
559
  console.log(` Created ${appDir}/ArctenWrapper.tsx`);
470
560
 
471
- // 4. Modify layout.tsx to wrap with ArctenWrapper
472
- const layoutPath = path.join(appDirPath, 'layout.tsx');
473
- if (fs.existsSync(layoutPath)) {
474
- let layoutContent = fs.readFileSync(layoutPath, 'utf-8');
475
-
476
- // Add import if not present
477
- if (!layoutContent.includes('ArctenWrapper')) {
478
- // Add import at the top (after existing imports)
479
- const importStatement = `import { ArctenWrapper } from "./ArctenWrapper";\n`;
480
- const lastImportIndex = layoutContent.lastIndexOf('import ');
481
- if (lastImportIndex !== -1) {
482
- const endOfImport = layoutContent.indexOf('\n', lastImportIndex);
483
- layoutContent = layoutContent.slice(0, endOfImport + 1) + importStatement + layoutContent.slice(endOfImport + 1);
484
- } else {
485
- layoutContent = importStatement + layoutContent;
561
+ if (framework === 'vite') {
562
+ // 4a. Modify main.tsx for Vite
563
+ const mainPath = path.join(projectRoot, 'src', 'main.tsx');
564
+ if (fs.existsSync(mainPath)) {
565
+ let mainContent = fs.readFileSync(mainPath, 'utf-8');
566
+
567
+ if (!mainContent.includes('ArctenWrapper')) {
568
+ // Add import after existing imports
569
+ const importStatement = `import { ArctenWrapper } from './ArctenWrapper'\n`;
570
+ const lastImportIndex = mainContent.lastIndexOf('import ');
571
+ if (lastImportIndex !== -1) {
572
+ const endOfImport = mainContent.indexOf('\n', lastImportIndex);
573
+ mainContent = mainContent.slice(0, endOfImport + 1) + importStatement + mainContent.slice(endOfImport + 1);
574
+ } else {
575
+ mainContent = importStatement + mainContent;
576
+ }
577
+
578
+ // Wrap <App /> with <ArctenWrapper>
579
+ mainContent = mainContent.replace(
580
+ /<App\s*\/>/,
581
+ '<ArctenWrapper><App /></ArctenWrapper>'
582
+ );
583
+
584
+ fs.writeFileSync(mainPath, mainContent);
585
+ createdFiles.push('src/main.tsx (modified)');
586
+ console.log(' Modified src/main.tsx');
587
+ }
588
+ }
589
+ } else {
590
+ // 4b. Modify layout.tsx for Next.js
591
+ const layoutPath = path.join(appDirPath, 'layout.tsx');
592
+ if (fs.existsSync(layoutPath)) {
593
+ let layoutContent = fs.readFileSync(layoutPath, 'utf-8');
594
+
595
+ // Add import if not present
596
+ if (!layoutContent.includes('ArctenWrapper')) {
597
+ // Add import at the top (after existing imports)
598
+ const importStatement = `import { ArctenWrapper } from "./ArctenWrapper";\n`;
599
+ const lastImportIndex = layoutContent.lastIndexOf('import ');
600
+ if (lastImportIndex !== -1) {
601
+ const endOfImport = layoutContent.indexOf('\n', lastImportIndex);
602
+ layoutContent = layoutContent.slice(0, endOfImport + 1) + importStatement + layoutContent.slice(endOfImport + 1);
603
+ } else {
604
+ layoutContent = importStatement + layoutContent;
605
+ }
606
+
607
+ // Wrap {children} with <ArctenWrapper>
608
+ layoutContent = layoutContent.replace(
609
+ /(\{children\})/,
610
+ '<ArctenWrapper>{children}</ArctenWrapper>'
611
+ );
612
+
613
+ fs.writeFileSync(layoutPath, layoutContent);
614
+ createdFiles.push(`${appDir}/layout.tsx (modified)`);
615
+ console.log(` Modified ${appDir}/layout.tsx`);
486
616
  }
487
-
488
- // Wrap {children} with <ArctenWrapper>
489
- layoutContent = layoutContent.replace(
490
- /(\{children\})/,
491
- '<ArctenWrapper>{children}</ArctenWrapper>'
492
- );
493
-
494
- fs.writeFileSync(layoutPath, layoutContent);
495
- createdFiles.push(`${appDir}/layout.tsx (modified)`);
496
- console.log(` Modified ${appDir}/layout.tsx`);
497
617
  }
498
618
  }
499
619
  } else if (placement === 'specific') {
500
620
  // Create standalone component for specific pages
501
- const componentContent = `"use client";
502
-
503
- import { ArctenAgent } from "@arcteninc/core";
621
+ const componentContent = `${useClientDirective}import { ArctenAgent } from "@arcteninc/core";
504
622
  import { toolMetadata } from "../.arcten/tool-metadata";
505
623
  import { allTools, safeToolNames } from "../.arcten/arcten.tools";
506
624
 
507
625
  export function ArctenChat() {
508
626
  return (
509
627
  <ArctenAgent
510
- apiBaseUrl={process.env.NEXT_PUBLIC_ARCTEN_API_URL || "https://api.arcten.com"}
628
+ apiBaseUrl={${envVarSyntax} || "https://api.arcten.com"}
511
629
  user={{ id: "user-1", name: "User" }}
512
630
  tools={allTools}
513
631
  safeToolNames={safeToolNames}
@@ -663,17 +663,28 @@ async function main() {
663
663
  const scriptDir = path.dirname(new URL(import.meta.url).pathname).replace(/^\/([A-Z]:)/, '$1');
664
664
 
665
665
  try {
666
+ // Read config to get tool file path
667
+ const configPath = path.join(projectRoot, '.arcten', 'config.ts');
668
+ let toolsArg = '';
669
+ if (fs.existsSync(configPath)) {
670
+ const configContent = fs.readFileSync(configPath, 'utf-8');
671
+ const toolFileMatch = configContent.match(/toolFile:\s*["']([^"']+)["']/);
672
+ if (toolFileMatch) {
673
+ toolsArg = ` --tools "${toolFileMatch[1]}"`;
674
+ }
675
+ }
676
+
666
677
  // Try running the wrapper script directly first
667
678
  const extractScript = path.join(scriptDir, 'cli-extract-types-auto-wrapper.js');
668
679
  if (fs.existsSync(extractScript)) {
669
- execSync(`node "${extractScript}"`, {
680
+ execSync(`node "${extractScript}"${toolsArg}`, {
670
681
  cwd: projectRoot,
671
682
  stdio: options.quiet ? 'pipe' : ['inherit', 'pipe', 'pipe'],
672
683
  });
673
684
  if (!options.quiet) console.log(' Done');
674
685
  } else {
675
686
  // Fall back to npx
676
- execSync('npx arcten-extract-types', {
687
+ execSync(`npx arcten-extract-types${toolsArg}`, {
677
688
  cwd: projectRoot,
678
689
  stdio: options.quiet ? 'pipe' : ['inherit', 'pipe', 'pipe'],
679
690
  });