create-supyagent-app 0.1.20 → 0.1.21

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/dist/index.js CHANGED
@@ -109,6 +109,23 @@ async function runPrompts(argName, options) {
109
109
  }
110
110
  aiProvider = selected;
111
111
  }
112
+ let agentMode;
113
+ if (options?.agentMode) {
114
+ agentMode = options.agentMode;
115
+ } else {
116
+ const selected = await p.select({
117
+ message: "Agent mode",
118
+ options: [
119
+ { value: "skills", label: "Skills (token-efficient)", hint: "recommended" },
120
+ { value: "tools", label: "Tools (rich tool definitions)" }
121
+ ]
122
+ });
123
+ if (p.isCancel(selected)) {
124
+ p.cancel("Cancelled.");
125
+ return null;
126
+ }
127
+ agentMode = selected;
128
+ }
112
129
  let database;
113
130
  if (options?.database || options?.skipDatabase) {
114
131
  database = options?.database ?? "sqlite";
@@ -126,7 +143,7 @@ async function runPrompts(argName, options) {
126
143
  }
127
144
  database = selected;
128
145
  }
129
- return { projectName, projectPath, aiProvider, database };
146
+ return { projectName, projectPath, aiProvider, agentMode, database };
130
147
  }
131
148
 
132
149
  // src/scaffold.ts
@@ -179,10 +196,11 @@ function scaffoldProject(config) {
179
196
  writeProject(projectPath, "src/app/globals.css", readTemplate("base/src/app/globals.css"));
180
197
  writeProject(projectPath, "src/app/chat/page.tsx", readTemplate("base/src/app/chat/page.tsx"));
181
198
  writeProject(projectPath, "src/app/chat/[id]/page.tsx", readTemplate("base/src/app/chat/[id]/page.tsx"));
199
+ const routeTemplate = config.agentMode === "skills" ? "api-route/route.skills.ts.tmpl" : "api-route/route.tools.ts.tmpl";
182
200
  writeProject(
183
201
  projectPath,
184
202
  "src/app/api/chat/route.ts",
185
- applyTemplate(readTemplate("api-route/route.ts.tmpl"), vars)
203
+ applyTemplate(readTemplate(routeTemplate), vars)
186
204
  );
187
205
  writeProject(projectPath, "src/app/api/chats/route.ts", readTemplate("base/src/app/api/chats/route.ts"));
188
206
  writeProject(projectPath, "src/app/api/chats/[id]/route.ts", readTemplate("base/src/app/api/chats/[id]/route.ts"));
@@ -322,6 +340,8 @@ function parseArgs() {
322
340
  result.aiProvider = args[++i];
323
341
  } else if (arg === "--db" && hasValue) {
324
342
  result.database = args[++i];
343
+ } else if (arg === "--mode" && hasValue) {
344
+ result.agentMode = args[++i];
325
345
  } else if (arg === "--model" && hasValue) {
326
346
  result.model = args[++i];
327
347
  } else if (arg === "--quickstart") {
@@ -432,6 +452,7 @@ async function main() {
432
452
  projectName,
433
453
  projectPath,
434
454
  aiProvider,
455
+ agentMode: parsed.agentMode ?? "skills",
435
456
  database: "sqlite",
436
457
  model: parsed.model,
437
458
  quickstart: true,
@@ -470,6 +491,7 @@ async function main() {
470
491
  projectName: parsed.projectName,
471
492
  projectPath: parsed.projectPath,
472
493
  aiProvider: parsed.aiProvider,
494
+ agentMode: parsed.agentMode ?? "skills",
473
495
  database: parsed.database,
474
496
  model: parsed.model
475
497
  };
@@ -477,6 +499,7 @@ async function main() {
477
499
  } else {
478
500
  config = await runPrompts(parsed.projectName, {
479
501
  aiProvider: parsed.aiProvider,
502
+ agentMode: parsed.agentMode,
480
503
  database: parsed.database
481
504
  });
482
505
  if (config && parsed.model) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/prompts.ts","../src/utils.ts","../src/scaffold.ts","../src/template.ts","../src/post-install.ts","../src/quickstart.ts"],"sourcesContent":["import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { runPrompts } from \"./prompts.js\";\nimport { scaffoldProject } from \"./scaffold.js\";\nimport { installDeps } from \"./post-install.js\";\nimport { writeEnvLocal, runDbSetup, runDevServer } from \"./quickstart.js\";\nimport { AI_PROVIDERS, resolveProjectPath, projectExists } from \"./utils.js\";\nimport type { ProjectConfig, ApiKeys } from \"./utils.js\";\n\ninterface ParsedArgs extends Partial<ProjectConfig> {\n skipInstall?: boolean;\n supyagentApiKey?: string;\n anthropicApiKey?: string;\n openaiApiKey?: string;\n openrouterApiKey?: string;\n}\n\nfunction parseArgs(): ParsedArgs {\n const args = process.argv.slice(2);\n const result: ParsedArgs = {};\n let projectName: string | undefined;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n const next = args[i + 1];\n const hasValue = next && !next.startsWith(\"-\");\n\n if (arg === \"--provider\" && hasValue) {\n result.aiProvider = args[++i] as ProjectConfig[\"aiProvider\"];\n } else if (arg === \"--db\" && hasValue) {\n result.database = args[++i] as ProjectConfig[\"database\"];\n } else if (arg === \"--model\" && hasValue) {\n result.model = args[++i];\n } else if (arg === \"--quickstart\") {\n result.quickstart = true;\n } else if (arg === \"--skip-install\") {\n result.skipInstall = true;\n } else if (arg === \"--supyagent-api-key\" && hasValue) {\n result.supyagentApiKey = args[++i];\n } else if (arg === \"--anthropic-api-key\" && hasValue) {\n result.anthropicApiKey = args[++i];\n } else if (arg === \"--openai-api-key\" && hasValue) {\n result.openaiApiKey = args[++i];\n } else if (arg === \"--openrouter-api-key\" && hasValue) {\n result.openrouterApiKey = args[++i];\n } else if (!arg.startsWith(\"-\")) {\n projectName = arg;\n }\n }\n\n return {\n ...result,\n projectName,\n projectPath: projectName ? resolveProjectPath(projectName) : undefined,\n };\n}\n\nconst ENV_KEY_MAP: Record<ProjectConfig[\"aiProvider\"], string> = {\n anthropic: \"ANTHROPIC_API_KEY\",\n openai: \"OPENAI_API_KEY\",\n openrouter: \"OPENROUTER_API_KEY\",\n};\n\nconst CLI_KEY_MAP: Record<ProjectConfig[\"aiProvider\"], keyof ParsedArgs> = {\n anthropic: \"anthropicApiKey\",\n openai: \"openaiApiKey\",\n openrouter: \"openrouterApiKey\",\n};\n\nasync function promptForKey(name: string): Promise<string> {\n const value = await p.password({ message: `Enter your ${name}` });\n if (p.isCancel(value)) {\n p.cancel(\"Cancelled.\");\n process.exit(1);\n }\n return value;\n}\n\nasync function resolveApiKeys(\n provider: ProjectConfig[\"aiProvider\"],\n parsed: ParsedArgs,\n): Promise<ApiKeys> {\n const envKey = ENV_KEY_MAP[provider];\n const cliFlag = CLI_KEY_MAP[provider];\n\n const supyagent =\n parsed.supyagentApiKey ??\n process.env.SUPYAGENT_API_KEY ??\n (await promptForKey(\"SUPYAGENT_API_KEY\"));\n\n const providerKey =\n (parsed[cliFlag] as string | undefined) ??\n process.env[envKey] ??\n (await promptForKey(envKey));\n\n return { supyagent, provider: providerKey };\n}\n\nasync function main() {\n const parsed = parseArgs();\n\n if (parsed.quickstart) {\n // ── Quickstart mode ──\n if (parsed.database === \"postgres\") {\n p.log.warn(\n pc.yellow(\"--quickstart requires SQLite — ignoring --db postgres\"),\n );\n }\n if (parsed.skipInstall) {\n p.log.warn(\n pc.yellow(\n \"--quickstart needs dependencies installed — ignoring --skip-install\",\n ),\n );\n }\n\n p.intro(pc.bgCyan(pc.black(\" Create Supyagent App — Quickstart \")));\n\n // Resolve project name\n let projectName = parsed.projectName;\n if (!projectName) {\n const name = await p.text({\n message: \"Project name\",\n placeholder: \"my-supyagent-app\",\n defaultValue: \"my-supyagent-app\",\n validate(value) {\n if (!value) return \"Project name is required\";\n if (!/^[a-z0-9][a-z0-9._-]*$/.test(value)) {\n return \"Invalid project name (lowercase, alphanumeric, hyphens, dots)\";\n }\n },\n });\n if (p.isCancel(name)) {\n p.cancel(\"Cancelled.\");\n process.exit(1);\n }\n projectName = name as string;\n }\n\n const projectPath = resolveProjectPath(projectName);\n if (projectExists(projectPath)) {\n p.cancel(`Directory \"${projectName}\" already exists.`);\n process.exit(1);\n }\n\n // Resolve provider\n let aiProvider = parsed.aiProvider;\n if (!aiProvider) {\n const selected = await p.select({\n message: \"AI provider\",\n options: [\n { value: \"anthropic\", label: AI_PROVIDERS.anthropic.label },\n { value: \"openai\", label: AI_PROVIDERS.openai.label },\n { value: \"openrouter\", label: AI_PROVIDERS.openrouter.label },\n ],\n });\n if (p.isCancel(selected)) {\n p.cancel(\"Cancelled.\");\n process.exit(1);\n }\n aiProvider = selected as ProjectConfig[\"aiProvider\"];\n }\n\n // Resolve API keys\n const apiKeys = await resolveApiKeys(aiProvider, parsed);\n\n const config: ProjectConfig = {\n projectName,\n projectPath,\n aiProvider,\n database: \"sqlite\",\n model: parsed.model,\n quickstart: true,\n apiKeys,\n };\n\n const s = p.spinner();\n\n // Scaffold\n s.start(\"Scaffolding project...\");\n scaffoldProject(config);\n writeEnvLocal(config);\n s.stop(\"Scaffolded project\");\n\n // Install deps\n s.start(\"Installing dependencies...\");\n try {\n await installDeps(config.projectPath);\n s.stop(\"Installed dependencies\");\n } catch {\n s.stop(\"Failed to install dependencies — run install manually\");\n process.exit(1);\n }\n\n // Database setup\n s.start(\"Setting up database...\");\n try {\n await runDbSetup(config.projectPath);\n s.stop(\"Database ready\");\n } catch (err) {\n s.stop(\"Database setup failed\");\n p.log.warn(\n `Run ${pc.cyan(`cd ${projectName} && pnpm db:setup`)} manually`,\n );\n }\n\n // Dev server\n p.log.info(pc.green(\"Starting dev server...\"));\n await runDevServer(config.projectPath);\n } else {\n // ── Existing non-quickstart flow ──\n const isNonInteractive =\n parsed.projectName && parsed.aiProvider && parsed.database;\n\n let config: ProjectConfig | null;\n\n if (isNonInteractive) {\n config = {\n projectName: parsed.projectName!,\n projectPath: parsed.projectPath!,\n aiProvider: parsed.aiProvider!,\n database: parsed.database!,\n model: parsed.model,\n };\n console.log(`Creating ${config.projectName}...`);\n } else {\n config = await runPrompts(parsed.projectName, {\n aiProvider: parsed.aiProvider,\n database: parsed.database,\n });\n if (config && parsed.model) {\n config.model = parsed.model;\n }\n }\n\n if (!config) {\n process.exit(1);\n }\n\n if (isNonInteractive) {\n scaffoldProject(config);\n console.log(\"Scaffolded project\");\n\n if (!parsed.skipInstall) {\n console.log(\"Installing dependencies...\");\n try {\n await installDeps(config.projectPath);\n console.log(\"Installed dependencies\");\n } catch {\n console.log(\n \"Failed to install dependencies — run install manually\",\n );\n }\n }\n\n console.log(\n `\\nNext steps:\\n cd ${config.projectName}\\n cp .env.example .env.local\\n pnpm db:setup\\n pnpm dev`,\n );\n } else {\n const s = p.spinner();\n\n s.start(\"Scaffolding project...\");\n scaffoldProject(config);\n s.stop(\"Scaffolded project\");\n\n s.start(\"Installing dependencies...\");\n try {\n await installDeps(config.projectPath);\n s.stop(\"Installed dependencies\");\n } catch {\n s.stop(\"Failed to install dependencies — run install manually\");\n }\n\n p.note(\n [\n `cd ${config.projectName}`,\n `cp .env.example .env.local ${pc.dim(\"# Add your API keys\")}`,\n `pnpm db:setup ${pc.dim(\"# Initialize database\")}`,\n `pnpm dev ${pc.dim(\"# Start development server\")}`,\n ].join(\"\\n\"),\n \"Next steps\",\n );\n\n p.outro(pc.green(\"Done!\"));\n }\n }\n}\n\nmain().catch(console.error);\n","import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport type { ProjectConfig } from \"./utils.js\";\nimport { AI_PROVIDERS, DB_CONFIGS, resolveProjectPath, projectExists } from \"./utils.js\";\n\nexport interface PromptOptions {\n aiProvider?: ProjectConfig[\"aiProvider\"];\n database?: ProjectConfig[\"database\"];\n skipDatabase?: boolean;\n}\n\nexport async function runPrompts(\n argName?: string,\n options?: PromptOptions,\n): Promise<ProjectConfig | null> {\n p.intro(pc.bgCyan(pc.black(\" Create Supyagent App \")));\n\n const projectName = argName || await p.text({\n message: \"Project name\",\n placeholder: \"my-supyagent-app\",\n defaultValue: \"my-supyagent-app\",\n validate(value) {\n if (!value) return \"Project name is required\";\n if (!/^[a-z0-9][a-z0-9._-]*$/.test(value)) {\n return \"Invalid project name (lowercase, alphanumeric, hyphens, dots)\";\n }\n },\n }) as string;\n\n if (p.isCancel(projectName)) {\n p.cancel(\"Cancelled.\");\n return null;\n }\n\n const projectPath = resolveProjectPath(projectName);\n\n if (projectExists(projectPath)) {\n p.cancel(`Directory \"${projectName}\" already exists.`);\n return null;\n }\n\n let aiProvider: ProjectConfig[\"aiProvider\"];\n if (options?.aiProvider) {\n aiProvider = options.aiProvider;\n } else {\n const selected = await p.select({\n message: \"AI provider\",\n options: [\n { value: \"anthropic\", label: AI_PROVIDERS.anthropic.label },\n { value: \"openai\", label: AI_PROVIDERS.openai.label },\n { value: \"openrouter\", label: AI_PROVIDERS.openrouter.label },\n ],\n }) as \"anthropic\" | \"openai\" | \"openrouter\";\n\n if (p.isCancel(selected)) {\n p.cancel(\"Cancelled.\");\n return null;\n }\n aiProvider = selected;\n }\n\n let database: ProjectConfig[\"database\"];\n if (options?.database || options?.skipDatabase) {\n database = options?.database ?? \"sqlite\";\n } else {\n const selected = await p.select({\n message: \"Database\",\n options: [\n { value: \"sqlite\", label: DB_CONFIGS.sqlite.label },\n { value: \"postgres\", label: DB_CONFIGS.postgres.label },\n ],\n }) as \"sqlite\" | \"postgres\";\n\n if (p.isCancel(selected)) {\n p.cancel(\"Cancelled.\");\n return null;\n }\n database = selected;\n }\n\n return { projectName, projectPath, aiProvider, database };\n}\n","import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n\nexport function resolveProjectPath(name: string): string {\n return resolve(process.cwd(), name);\n}\n\nexport function projectExists(path: string): boolean {\n return existsSync(path);\n}\n\nexport interface ApiKeys {\n supyagent?: string;\n provider?: string;\n}\n\nexport interface ProjectConfig {\n projectName: string;\n projectPath: string;\n aiProvider: \"anthropic\" | \"openai\" | \"openrouter\";\n database: \"sqlite\" | \"postgres\";\n model?: string;\n quickstart?: boolean;\n apiKeys?: ApiKeys;\n}\n\nexport const AI_PROVIDERS = {\n anthropic: {\n label: \"Anthropic (Claude)\",\n package: \"@ai-sdk/anthropic\",\n packageVersion: \"^3.0.0\",\n import: `import { anthropic } from '@ai-sdk/anthropic'`,\n model: `anthropic('claude-sonnet-4-6-20250620')`,\n envKey: \"ANTHROPIC_API_KEY\",\n },\n openai: {\n label: \"OpenAI (GPT)\",\n package: \"@ai-sdk/openai\",\n packageVersion: \"^3.0.0\",\n import: `import { openai } from '@ai-sdk/openai'`,\n model: `openai('gpt-4o')`,\n envKey: \"OPENAI_API_KEY\",\n },\n openrouter: {\n label: \"OpenRouter (any model)\",\n package: \"@openrouter/ai-sdk-provider\",\n packageVersion: \"^2.2.3\",\n import: `import { createOpenRouter } from '@openrouter/ai-sdk-provider'`,\n model: `createOpenRouter({ apiKey: process.env.OPENROUTER_API_KEY })('anthropic/claude-sonnet-4.6')`,\n envKey: \"OPENROUTER_API_KEY\",\n },\n} as const;\n\nexport const DB_CONFIGS = {\n sqlite: {\n label: \"SQLite (local dev)\",\n provider: \"sqlite\",\n url: \"file:./dev.db\",\n },\n postgres: {\n label: \"PostgreSQL (production)\",\n provider: \"postgresql\",\n url: \"postgresql://user:password@localhost:5432/mydb\",\n },\n} as const;\n\nexport function buildModelExpression(\n provider: ProjectConfig[\"aiProvider\"],\n customModelId?: string,\n): string {\n const config = AI_PROVIDERS[provider];\n if (!customModelId) return config.model;\n switch (provider) {\n case \"anthropic\":\n return `anthropic('${customModelId}')`;\n case \"openai\":\n return `openai('${customModelId}')`;\n case \"openrouter\":\n return `createOpenRouter({ apiKey: process.env.OPENROUTER_API_KEY })('${customModelId}')`;\n }\n}\n","import { mkdirSync, writeFileSync, readFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { applyTemplate } from \"./template.js\";\nimport { AI_PROVIDERS, DB_CONFIGS, buildModelExpression, type ProjectConfig } from \"./utils.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst TEMPLATES_DIR = join(__dirname, \"..\", \"templates\");\n\nfunction readTemplate(relativePath: string): string {\n return readFileSync(join(TEMPLATES_DIR, relativePath), \"utf-8\");\n}\n\nfunction writeProject(projectPath: string, relativePath: string, content: string): void {\n const fullPath = join(projectPath, relativePath);\n mkdirSync(dirname(fullPath), { recursive: true });\n writeFileSync(fullPath, content, \"utf-8\");\n}\n\nexport function scaffoldProject(config: ProjectConfig): void {\n const { projectPath, projectName, aiProvider, database } = config;\n const ai = AI_PROVIDERS[aiProvider];\n const db = DB_CONFIGS[database];\n\n const vars: Record<string, string> = {\n projectName,\n aiProviderPackage: ai.package,\n aiProviderVersion: ai.packageVersion,\n aiProviderImport: ai.import,\n aiModel: buildModelExpression(aiProvider, config.model),\n aiProviderEnvKey: ai.envKey,\n dbProvider: db.provider,\n dbUrl: db.url,\n };\n\n mkdirSync(projectPath, { recursive: true });\n\n // ── Base files ──\n writeProject(projectPath, \"next.config.ts\", readTemplate(\"base/next.config.ts\"));\n writeProject(projectPath, \"tsconfig.json\", readTemplate(\"base/tsconfig.json\"));\n writeProject(projectPath, \"tailwind.config.ts\", readTemplate(\"base/tailwind.config.ts\"));\n writeProject(projectPath, \"postcss.config.js\", readTemplate(\"base/postcss.config.js\"));\n writeProject(projectPath, \".gitignore\", readTemplate(\"base/gitignore\"));\n writeProject(projectPath, \".npmrc\", readTemplate(\"base/npmrc\"));\n writeProject(projectPath, \"README.md\", applyTemplate(readTemplate(\"base/README.md.tmpl\"), vars));\n\n // ── Source files ──\n writeProject(projectPath, \"src/app/layout.tsx\", readTemplate(\"base/src/app/layout.tsx\"));\n writeProject(projectPath, \"src/app/page.tsx\", readTemplate(\"base/src/app/page.tsx\"));\n writeProject(projectPath, \"src/app/globals.css\", readTemplate(\"base/src/app/globals.css\"));\n writeProject(projectPath, \"src/app/chat/page.tsx\", readTemplate(\"base/src/app/chat/page.tsx\"));\n writeProject(projectPath, \"src/app/chat/[id]/page.tsx\", readTemplate(\"base/src/app/chat/[id]/page.tsx\"));\n\n // API routes\n writeProject(\n projectPath,\n \"src/app/api/chat/route.ts\",\n applyTemplate(readTemplate(\"api-route/route.ts.tmpl\"), vars)\n );\n writeProject(projectPath, \"src/app/api/chats/route.ts\", readTemplate(\"base/src/app/api/chats/route.ts\"));\n writeProject(projectPath, \"src/app/api/chats/[id]/route.ts\", readTemplate(\"base/src/app/api/chats/[id]/route.ts\"));\n\n // Components\n writeProject(projectPath, \"src/components/chat.tsx\", readTemplate(\"base/src/components/chat.tsx\"));\n writeProject(projectPath, \"src/components/chat-sidebar.tsx\", readTemplate(\"base/src/components/chat-sidebar.tsx\"));\n writeProject(projectPath, \"src/components/chat-message.tsx\", readTemplate(\"base/src/components/chat-message.tsx\"));\n writeProject(projectPath, \"src/components/chat-input.tsx\", readTemplate(\"base/src/components/chat-input.tsx\"));\n\n // UI primitives (shadcn-style)\n writeProject(projectPath, \"src/components/ui/badge.tsx\", readTemplate(\"base/src/components/ui/badge.tsx\"));\n writeProject(projectPath, \"src/components/ui/collapsible.tsx\", readTemplate(\"base/src/components/ui/collapsible.tsx\"));\n\n // AI Elements (pre-bundled Tool component)\n writeProject(projectPath, \"src/components/ai-elements/tool.tsx\", readTemplate(\"base/src/components/ai-elements/tool.tsx\"));\n\n // Supyagent tool rendering (local, editable)\n writeProject(projectPath, \"src/components/supyagent/tool-message.tsx\", readTemplate(\"base/src/components/supyagent/tool-message.tsx\"));\n writeProject(projectPath, \"src/components/supyagent/tool-renderers.tsx\", readTemplate(\"base/src/components/supyagent/tool-renderers.tsx\"));\n\n // Tool renderers — one per integration\n const toolRenderers = [\n \"gmail\", \"calendar\", \"slack\", \"github\", \"drive\", \"search\", \"docs\",\n \"sheets\", \"slides\", \"hubspot\", \"linear\", \"pipedrive\", \"compute\",\n \"resend\", \"inbox\", \"discord\", \"notion\", \"twitter\", \"telegram\",\n \"stripe\", \"jira\", \"salesforce\", \"brevo\", \"calendly\", \"twilio\",\n \"linkedin\", \"bash\", \"generic\",\n ];\n for (const tool of toolRenderers) {\n writeProject(projectPath, `src/components/supyagent/tools/${tool}.tsx`, readTemplate(`base/src/components/supyagent/tools/${tool}.tsx`));\n }\n\n // Lib\n writeProject(projectPath, \"src/lib/utils.ts\", readTemplate(\"base/src/lib/utils.ts\"));\n writeProject(projectPath, \"src/lib/prisma.ts\", readTemplate(\"base/src/lib/prisma.ts\"));\n\n // ── Prisma schema ──\n writeProject(\n projectPath,\n \"prisma/schema.prisma\",\n applyTemplate(readTemplate(\"prisma/schema.prisma.tmpl\"), vars)\n );\n\n // ── Env example ──\n writeProject(\n projectPath,\n \".env.example\",\n applyTemplate(readTemplate(\"env/.env.example.tmpl\"), vars)\n );\n\n // ── package.json ──\n writeProject(\n projectPath,\n \"package.json\",\n applyTemplate(readTemplate(\"package-json/package.json.tmpl\"), vars)\n );\n}\n","/**\n * Replace {{variable}} placeholders in template content.\n */\nexport function applyTemplate(\n content: string,\n variables: Record<string, string>\n): string {\n return content.replace(/\\{\\{(\\w+)\\}\\}/g, (match, key) => {\n return key in variables ? variables[key] : match;\n });\n}\n","import { detectPackageManager, installDependencies } from \"nypm\";\n\nexport async function installDeps(projectPath: string): Promise<void> {\n const pm = await detectPackageManager(projectPath);\n await installDependencies({\n cwd: projectPath,\n packageManager: pm?.name,\n });\n}\n","import { writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { execSync, spawn as nodeSpawn } from \"node:child_process\";\nimport { detectPackageManager } from \"nypm\";\nimport { AI_PROVIDERS, type ProjectConfig } from \"./utils.js\";\n\nexport function writeEnvLocal(config: ProjectConfig): void {\n const { projectPath, aiProvider, apiKeys } = config;\n const ai = AI_PROVIDERS[aiProvider];\n\n const lines = [\n \"# Supyagent — Get your API key at https://app.supyagent.com\",\n `SUPYAGENT_API_KEY=${apiKeys?.supyagent ?? \"\"}`,\n \"\",\n \"# AI Provider\",\n `${ai.envKey}=${apiKeys?.provider ?? \"\"}`,\n \"\",\n \"# Database\",\n `DATABASE_URL=\"file:./dev.db\"`,\n \"\",\n ];\n\n writeFileSync(join(projectPath, \".env.local\"), lines.join(\"\\n\"), \"utf-8\");\n}\n\nexport async function runDbSetup(projectPath: string): Promise<void> {\n const pm = await detectPackageManager(projectPath);\n const cmd = pm?.name ?? \"pnpm\";\n execSync(`${cmd} run db:setup`, {\n cwd: projectPath,\n stdio: \"inherit\",\n env: { ...process.env, DATABASE_URL: \"file:./dev.db\" },\n });\n}\n\nexport async function runDevServer(projectPath: string): Promise<never> {\n const pm = await detectPackageManager(projectPath);\n const cmd = pm?.name ?? \"pnpm\";\n\n const child = nodeSpawn(cmd, [\"run\", \"dev\"], {\n cwd: projectPath,\n stdio: \"inherit\",\n });\n\n const forward = (signal: NodeJS.Signals) => {\n child.kill(signal);\n };\n\n process.on(\"SIGINT\", forward);\n process.on(\"SIGTERM\", forward);\n\n return new Promise((_, reject) => {\n child.on(\"close\", (code) => {\n process.off(\"SIGINT\", forward);\n process.off(\"SIGTERM\", forward);\n process.exit(code ?? 0);\n });\n child.on(\"error\", reject);\n });\n}\n"],"mappings":"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","names":["p","pc","writeFileSync","join","detectPackageManager","writeFileSync","join","detectPackageManager","pc"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/prompts.ts","../src/utils.ts","../src/scaffold.ts","../src/template.ts","../src/post-install.ts","../src/quickstart.ts"],"sourcesContent":["import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { runPrompts } from \"./prompts.js\";\nimport { scaffoldProject } from \"./scaffold.js\";\nimport { installDeps } from \"./post-install.js\";\nimport { writeEnvLocal, runDbSetup, runDevServer } from \"./quickstart.js\";\nimport { AI_PROVIDERS, resolveProjectPath, projectExists } from \"./utils.js\";\nimport type { ProjectConfig, ApiKeys } from \"./utils.js\";\n\ninterface ParsedArgs extends Partial<ProjectConfig> {\n skipInstall?: boolean;\n supyagentApiKey?: string;\n anthropicApiKey?: string;\n openaiApiKey?: string;\n openrouterApiKey?: string;\n}\n\nfunction parseArgs(): ParsedArgs {\n const args = process.argv.slice(2);\n const result: ParsedArgs = {};\n let projectName: string | undefined;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n const next = args[i + 1];\n const hasValue = next && !next.startsWith(\"-\");\n\n if (arg === \"--provider\" && hasValue) {\n result.aiProvider = args[++i] as ProjectConfig[\"aiProvider\"];\n } else if (arg === \"--db\" && hasValue) {\n result.database = args[++i] as ProjectConfig[\"database\"];\n } else if (arg === \"--mode\" && hasValue) {\n result.agentMode = args[++i] as ProjectConfig[\"agentMode\"];\n } else if (arg === \"--model\" && hasValue) {\n result.model = args[++i];\n } else if (arg === \"--quickstart\") {\n result.quickstart = true;\n } else if (arg === \"--skip-install\") {\n result.skipInstall = true;\n } else if (arg === \"--supyagent-api-key\" && hasValue) {\n result.supyagentApiKey = args[++i];\n } else if (arg === \"--anthropic-api-key\" && hasValue) {\n result.anthropicApiKey = args[++i];\n } else if (arg === \"--openai-api-key\" && hasValue) {\n result.openaiApiKey = args[++i];\n } else if (arg === \"--openrouter-api-key\" && hasValue) {\n result.openrouterApiKey = args[++i];\n } else if (!arg.startsWith(\"-\")) {\n projectName = arg;\n }\n }\n\n return {\n ...result,\n projectName,\n projectPath: projectName ? resolveProjectPath(projectName) : undefined,\n };\n}\n\nconst ENV_KEY_MAP: Record<ProjectConfig[\"aiProvider\"], string> = {\n anthropic: \"ANTHROPIC_API_KEY\",\n openai: \"OPENAI_API_KEY\",\n openrouter: \"OPENROUTER_API_KEY\",\n};\n\nconst CLI_KEY_MAP: Record<ProjectConfig[\"aiProvider\"], keyof ParsedArgs> = {\n anthropic: \"anthropicApiKey\",\n openai: \"openaiApiKey\",\n openrouter: \"openrouterApiKey\",\n};\n\nasync function promptForKey(name: string): Promise<string> {\n const value = await p.password({ message: `Enter your ${name}` });\n if (p.isCancel(value)) {\n p.cancel(\"Cancelled.\");\n process.exit(1);\n }\n return value;\n}\n\nasync function resolveApiKeys(\n provider: ProjectConfig[\"aiProvider\"],\n parsed: ParsedArgs,\n): Promise<ApiKeys> {\n const envKey = ENV_KEY_MAP[provider];\n const cliFlag = CLI_KEY_MAP[provider];\n\n const supyagent =\n parsed.supyagentApiKey ??\n process.env.SUPYAGENT_API_KEY ??\n (await promptForKey(\"SUPYAGENT_API_KEY\"));\n\n const providerKey =\n (parsed[cliFlag] as string | undefined) ??\n process.env[envKey] ??\n (await promptForKey(envKey));\n\n return { supyagent, provider: providerKey };\n}\n\nasync function main() {\n const parsed = parseArgs();\n\n if (parsed.quickstart) {\n // ── Quickstart mode ──\n if (parsed.database === \"postgres\") {\n p.log.warn(\n pc.yellow(\"--quickstart requires SQLite — ignoring --db postgres\"),\n );\n }\n if (parsed.skipInstall) {\n p.log.warn(\n pc.yellow(\n \"--quickstart needs dependencies installed — ignoring --skip-install\",\n ),\n );\n }\n\n p.intro(pc.bgCyan(pc.black(\" Create Supyagent App — Quickstart \")));\n\n // Resolve project name\n let projectName = parsed.projectName;\n if (!projectName) {\n const name = await p.text({\n message: \"Project name\",\n placeholder: \"my-supyagent-app\",\n defaultValue: \"my-supyagent-app\",\n validate(value) {\n if (!value) return \"Project name is required\";\n if (!/^[a-z0-9][a-z0-9._-]*$/.test(value)) {\n return \"Invalid project name (lowercase, alphanumeric, hyphens, dots)\";\n }\n },\n });\n if (p.isCancel(name)) {\n p.cancel(\"Cancelled.\");\n process.exit(1);\n }\n projectName = name as string;\n }\n\n const projectPath = resolveProjectPath(projectName);\n if (projectExists(projectPath)) {\n p.cancel(`Directory \"${projectName}\" already exists.`);\n process.exit(1);\n }\n\n // Resolve provider\n let aiProvider = parsed.aiProvider;\n if (!aiProvider) {\n const selected = await p.select({\n message: \"AI provider\",\n options: [\n { value: \"anthropic\", label: AI_PROVIDERS.anthropic.label },\n { value: \"openai\", label: AI_PROVIDERS.openai.label },\n { value: \"openrouter\", label: AI_PROVIDERS.openrouter.label },\n ],\n });\n if (p.isCancel(selected)) {\n p.cancel(\"Cancelled.\");\n process.exit(1);\n }\n aiProvider = selected as ProjectConfig[\"aiProvider\"];\n }\n\n // Resolve API keys\n const apiKeys = await resolveApiKeys(aiProvider, parsed);\n\n const config: ProjectConfig = {\n projectName,\n projectPath,\n aiProvider,\n agentMode: parsed.agentMode ?? \"skills\",\n database: \"sqlite\",\n model: parsed.model,\n quickstart: true,\n apiKeys,\n };\n\n const s = p.spinner();\n\n // Scaffold\n s.start(\"Scaffolding project...\");\n scaffoldProject(config);\n writeEnvLocal(config);\n s.stop(\"Scaffolded project\");\n\n // Install deps\n s.start(\"Installing dependencies...\");\n try {\n await installDeps(config.projectPath);\n s.stop(\"Installed dependencies\");\n } catch {\n s.stop(\"Failed to install dependencies — run install manually\");\n process.exit(1);\n }\n\n // Database setup\n s.start(\"Setting up database...\");\n try {\n await runDbSetup(config.projectPath);\n s.stop(\"Database ready\");\n } catch (err) {\n s.stop(\"Database setup failed\");\n p.log.warn(\n `Run ${pc.cyan(`cd ${projectName} && pnpm db:setup`)} manually`,\n );\n }\n\n // Dev server\n p.log.info(pc.green(\"Starting dev server...\"));\n await runDevServer(config.projectPath);\n } else {\n // ── Existing non-quickstart flow ──\n const isNonInteractive =\n parsed.projectName && parsed.aiProvider && parsed.database;\n\n let config: ProjectConfig | null;\n\n if (isNonInteractive) {\n config = {\n projectName: parsed.projectName!,\n projectPath: parsed.projectPath!,\n aiProvider: parsed.aiProvider!,\n agentMode: parsed.agentMode ?? \"skills\",\n database: parsed.database!,\n model: parsed.model,\n };\n console.log(`Creating ${config.projectName}...`);\n } else {\n config = await runPrompts(parsed.projectName, {\n aiProvider: parsed.aiProvider,\n agentMode: parsed.agentMode,\n database: parsed.database,\n });\n if (config && parsed.model) {\n config.model = parsed.model;\n }\n }\n\n if (!config) {\n process.exit(1);\n }\n\n if (isNonInteractive) {\n scaffoldProject(config);\n console.log(\"Scaffolded project\");\n\n if (!parsed.skipInstall) {\n console.log(\"Installing dependencies...\");\n try {\n await installDeps(config.projectPath);\n console.log(\"Installed dependencies\");\n } catch {\n console.log(\n \"Failed to install dependencies — run install manually\",\n );\n }\n }\n\n console.log(\n `\\nNext steps:\\n cd ${config.projectName}\\n cp .env.example .env.local\\n pnpm db:setup\\n pnpm dev`,\n );\n } else {\n const s = p.spinner();\n\n s.start(\"Scaffolding project...\");\n scaffoldProject(config);\n s.stop(\"Scaffolded project\");\n\n s.start(\"Installing dependencies...\");\n try {\n await installDeps(config.projectPath);\n s.stop(\"Installed dependencies\");\n } catch {\n s.stop(\"Failed to install dependencies — run install manually\");\n }\n\n p.note(\n [\n `cd ${config.projectName}`,\n `cp .env.example .env.local ${pc.dim(\"# Add your API keys\")}`,\n `pnpm db:setup ${pc.dim(\"# Initialize database\")}`,\n `pnpm dev ${pc.dim(\"# Start development server\")}`,\n ].join(\"\\n\"),\n \"Next steps\",\n );\n\n p.outro(pc.green(\"Done!\"));\n }\n }\n}\n\nmain().catch(console.error);\n","import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport type { ProjectConfig } from \"./utils.js\";\nimport { AI_PROVIDERS, DB_CONFIGS, resolveProjectPath, projectExists } from \"./utils.js\";\n\nexport interface PromptOptions {\n aiProvider?: ProjectConfig[\"aiProvider\"];\n database?: ProjectConfig[\"database\"];\n agentMode?: ProjectConfig[\"agentMode\"];\n skipDatabase?: boolean;\n}\n\nexport async function runPrompts(\n argName?: string,\n options?: PromptOptions,\n): Promise<ProjectConfig | null> {\n p.intro(pc.bgCyan(pc.black(\" Create Supyagent App \")));\n\n const projectName = argName || await p.text({\n message: \"Project name\",\n placeholder: \"my-supyagent-app\",\n defaultValue: \"my-supyagent-app\",\n validate(value) {\n if (!value) return \"Project name is required\";\n if (!/^[a-z0-9][a-z0-9._-]*$/.test(value)) {\n return \"Invalid project name (lowercase, alphanumeric, hyphens, dots)\";\n }\n },\n }) as string;\n\n if (p.isCancel(projectName)) {\n p.cancel(\"Cancelled.\");\n return null;\n }\n\n const projectPath = resolveProjectPath(projectName);\n\n if (projectExists(projectPath)) {\n p.cancel(`Directory \"${projectName}\" already exists.`);\n return null;\n }\n\n let aiProvider: ProjectConfig[\"aiProvider\"];\n if (options?.aiProvider) {\n aiProvider = options.aiProvider;\n } else {\n const selected = await p.select({\n message: \"AI provider\",\n options: [\n { value: \"anthropic\", label: AI_PROVIDERS.anthropic.label },\n { value: \"openai\", label: AI_PROVIDERS.openai.label },\n { value: \"openrouter\", label: AI_PROVIDERS.openrouter.label },\n ],\n }) as \"anthropic\" | \"openai\" | \"openrouter\";\n\n if (p.isCancel(selected)) {\n p.cancel(\"Cancelled.\");\n return null;\n }\n aiProvider = selected;\n }\n\n let agentMode: ProjectConfig[\"agentMode\"];\n if (options?.agentMode) {\n agentMode = options.agentMode;\n } else {\n const selected = await p.select({\n message: \"Agent mode\",\n options: [\n { value: \"skills\", label: \"Skills (token-efficient)\", hint: \"recommended\" },\n { value: \"tools\", label: \"Tools (rich tool definitions)\" },\n ],\n }) as \"skills\" | \"tools\";\n\n if (p.isCancel(selected)) {\n p.cancel(\"Cancelled.\");\n return null;\n }\n agentMode = selected;\n }\n\n let database: ProjectConfig[\"database\"];\n if (options?.database || options?.skipDatabase) {\n database = options?.database ?? \"sqlite\";\n } else {\n const selected = await p.select({\n message: \"Database\",\n options: [\n { value: \"sqlite\", label: DB_CONFIGS.sqlite.label },\n { value: \"postgres\", label: DB_CONFIGS.postgres.label },\n ],\n }) as \"sqlite\" | \"postgres\";\n\n if (p.isCancel(selected)) {\n p.cancel(\"Cancelled.\");\n return null;\n }\n database = selected;\n }\n\n return { projectName, projectPath, aiProvider, agentMode, database };\n}\n","import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n\nexport function resolveProjectPath(name: string): string {\n return resolve(process.cwd(), name);\n}\n\nexport function projectExists(path: string): boolean {\n return existsSync(path);\n}\n\nexport interface ApiKeys {\n supyagent?: string;\n provider?: string;\n}\n\nexport interface ProjectConfig {\n projectName: string;\n projectPath: string;\n aiProvider: \"anthropic\" | \"openai\" | \"openrouter\";\n database: \"sqlite\" | \"postgres\";\n agentMode: \"skills\" | \"tools\";\n model?: string;\n quickstart?: boolean;\n apiKeys?: ApiKeys;\n}\n\nexport const AI_PROVIDERS = {\n anthropic: {\n label: \"Anthropic (Claude)\",\n package: \"@ai-sdk/anthropic\",\n packageVersion: \"^3.0.0\",\n import: `import { anthropic } from '@ai-sdk/anthropic'`,\n model: `anthropic('claude-sonnet-4-6-20250620')`,\n envKey: \"ANTHROPIC_API_KEY\",\n },\n openai: {\n label: \"OpenAI (GPT)\",\n package: \"@ai-sdk/openai\",\n packageVersion: \"^3.0.0\",\n import: `import { openai } from '@ai-sdk/openai'`,\n model: `openai('gpt-4o')`,\n envKey: \"OPENAI_API_KEY\",\n },\n openrouter: {\n label: \"OpenRouter (any model)\",\n package: \"@openrouter/ai-sdk-provider\",\n packageVersion: \"^2.2.3\",\n import: `import { createOpenRouter } from '@openrouter/ai-sdk-provider'`,\n model: `createOpenRouter({ apiKey: process.env.OPENROUTER_API_KEY })('anthropic/claude-sonnet-4.6')`,\n envKey: \"OPENROUTER_API_KEY\",\n },\n} as const;\n\nexport const DB_CONFIGS = {\n sqlite: {\n label: \"SQLite (local dev)\",\n provider: \"sqlite\",\n url: \"file:./dev.db\",\n },\n postgres: {\n label: \"PostgreSQL (production)\",\n provider: \"postgresql\",\n url: \"postgresql://user:password@localhost:5432/mydb\",\n },\n} as const;\n\nexport function buildModelExpression(\n provider: ProjectConfig[\"aiProvider\"],\n customModelId?: string,\n): string {\n const config = AI_PROVIDERS[provider];\n if (!customModelId) return config.model;\n switch (provider) {\n case \"anthropic\":\n return `anthropic('${customModelId}')`;\n case \"openai\":\n return `openai('${customModelId}')`;\n case \"openrouter\":\n return `createOpenRouter({ apiKey: process.env.OPENROUTER_API_KEY })('${customModelId}')`;\n }\n}\n","import { mkdirSync, writeFileSync, readFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { applyTemplate } from \"./template.js\";\nimport { AI_PROVIDERS, DB_CONFIGS, buildModelExpression, type ProjectConfig } from \"./utils.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst TEMPLATES_DIR = join(__dirname, \"..\", \"templates\");\n\nfunction readTemplate(relativePath: string): string {\n return readFileSync(join(TEMPLATES_DIR, relativePath), \"utf-8\");\n}\n\nfunction writeProject(projectPath: string, relativePath: string, content: string): void {\n const fullPath = join(projectPath, relativePath);\n mkdirSync(dirname(fullPath), { recursive: true });\n writeFileSync(fullPath, content, \"utf-8\");\n}\n\nexport function scaffoldProject(config: ProjectConfig): void {\n const { projectPath, projectName, aiProvider, database } = config;\n const ai = AI_PROVIDERS[aiProvider];\n const db = DB_CONFIGS[database];\n\n const vars: Record<string, string> = {\n projectName,\n aiProviderPackage: ai.package,\n aiProviderVersion: ai.packageVersion,\n aiProviderImport: ai.import,\n aiModel: buildModelExpression(aiProvider, config.model),\n aiProviderEnvKey: ai.envKey,\n dbProvider: db.provider,\n dbUrl: db.url,\n };\n\n mkdirSync(projectPath, { recursive: true });\n\n // ── Base files ──\n writeProject(projectPath, \"next.config.ts\", readTemplate(\"base/next.config.ts\"));\n writeProject(projectPath, \"tsconfig.json\", readTemplate(\"base/tsconfig.json\"));\n writeProject(projectPath, \"tailwind.config.ts\", readTemplate(\"base/tailwind.config.ts\"));\n writeProject(projectPath, \"postcss.config.js\", readTemplate(\"base/postcss.config.js\"));\n writeProject(projectPath, \".gitignore\", readTemplate(\"base/gitignore\"));\n writeProject(projectPath, \".npmrc\", readTemplate(\"base/npmrc\"));\n writeProject(projectPath, \"README.md\", applyTemplate(readTemplate(\"base/README.md.tmpl\"), vars));\n\n // ── Source files ──\n writeProject(projectPath, \"src/app/layout.tsx\", readTemplate(\"base/src/app/layout.tsx\"));\n writeProject(projectPath, \"src/app/page.tsx\", readTemplate(\"base/src/app/page.tsx\"));\n writeProject(projectPath, \"src/app/globals.css\", readTemplate(\"base/src/app/globals.css\"));\n writeProject(projectPath, \"src/app/chat/page.tsx\", readTemplate(\"base/src/app/chat/page.tsx\"));\n writeProject(projectPath, \"src/app/chat/[id]/page.tsx\", readTemplate(\"base/src/app/chat/[id]/page.tsx\"));\n\n // API routes — use skills or tools template based on agentMode\n const routeTemplate = config.agentMode === \"skills\"\n ? \"api-route/route.skills.ts.tmpl\"\n : \"api-route/route.tools.ts.tmpl\";\n writeProject(\n projectPath,\n \"src/app/api/chat/route.ts\",\n applyTemplate(readTemplate(routeTemplate), vars)\n );\n writeProject(projectPath, \"src/app/api/chats/route.ts\", readTemplate(\"base/src/app/api/chats/route.ts\"));\n writeProject(projectPath, \"src/app/api/chats/[id]/route.ts\", readTemplate(\"base/src/app/api/chats/[id]/route.ts\"));\n\n // Components\n writeProject(projectPath, \"src/components/chat.tsx\", readTemplate(\"base/src/components/chat.tsx\"));\n writeProject(projectPath, \"src/components/chat-sidebar.tsx\", readTemplate(\"base/src/components/chat-sidebar.tsx\"));\n writeProject(projectPath, \"src/components/chat-message.tsx\", readTemplate(\"base/src/components/chat-message.tsx\"));\n writeProject(projectPath, \"src/components/chat-input.tsx\", readTemplate(\"base/src/components/chat-input.tsx\"));\n\n // UI primitives (shadcn-style)\n writeProject(projectPath, \"src/components/ui/badge.tsx\", readTemplate(\"base/src/components/ui/badge.tsx\"));\n writeProject(projectPath, \"src/components/ui/collapsible.tsx\", readTemplate(\"base/src/components/ui/collapsible.tsx\"));\n\n // AI Elements (pre-bundled Tool component)\n writeProject(projectPath, \"src/components/ai-elements/tool.tsx\", readTemplate(\"base/src/components/ai-elements/tool.tsx\"));\n\n // Supyagent tool rendering (local, editable)\n writeProject(projectPath, \"src/components/supyagent/tool-message.tsx\", readTemplate(\"base/src/components/supyagent/tool-message.tsx\"));\n writeProject(projectPath, \"src/components/supyagent/tool-renderers.tsx\", readTemplate(\"base/src/components/supyagent/tool-renderers.tsx\"));\n\n // Tool renderers — one per integration\n const toolRenderers = [\n \"gmail\", \"calendar\", \"slack\", \"github\", \"drive\", \"search\", \"docs\",\n \"sheets\", \"slides\", \"hubspot\", \"linear\", \"pipedrive\", \"compute\",\n \"resend\", \"inbox\", \"discord\", \"notion\", \"twitter\", \"telegram\",\n \"stripe\", \"jira\", \"salesforce\", \"brevo\", \"calendly\", \"twilio\",\n \"linkedin\", \"bash\", \"generic\",\n ];\n for (const tool of toolRenderers) {\n writeProject(projectPath, `src/components/supyagent/tools/${tool}.tsx`, readTemplate(`base/src/components/supyagent/tools/${tool}.tsx`));\n }\n\n // Lib\n writeProject(projectPath, \"src/lib/utils.ts\", readTemplate(\"base/src/lib/utils.ts\"));\n writeProject(projectPath, \"src/lib/prisma.ts\", readTemplate(\"base/src/lib/prisma.ts\"));\n\n // ── Prisma schema ──\n writeProject(\n projectPath,\n \"prisma/schema.prisma\",\n applyTemplate(readTemplate(\"prisma/schema.prisma.tmpl\"), vars)\n );\n\n // ── Env example ──\n writeProject(\n projectPath,\n \".env.example\",\n applyTemplate(readTemplate(\"env/.env.example.tmpl\"), vars)\n );\n\n // ── package.json ──\n writeProject(\n projectPath,\n \"package.json\",\n applyTemplate(readTemplate(\"package-json/package.json.tmpl\"), vars)\n );\n}\n","/**\n * Replace {{variable}} placeholders in template content.\n */\nexport function applyTemplate(\n content: string,\n variables: Record<string, string>\n): string {\n return content.replace(/\\{\\{(\\w+)\\}\\}/g, (match, key) => {\n return key in variables ? variables[key] : match;\n });\n}\n","import { detectPackageManager, installDependencies } from \"nypm\";\n\nexport async function installDeps(projectPath: string): Promise<void> {\n const pm = await detectPackageManager(projectPath);\n await installDependencies({\n cwd: projectPath,\n packageManager: pm?.name,\n });\n}\n","import { writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { execSync, spawn as nodeSpawn } from \"node:child_process\";\nimport { detectPackageManager } from \"nypm\";\nimport { AI_PROVIDERS, type ProjectConfig } from \"./utils.js\";\n\nexport function writeEnvLocal(config: ProjectConfig): void {\n const { projectPath, aiProvider, apiKeys } = config;\n const ai = AI_PROVIDERS[aiProvider];\n\n const lines = [\n \"# Supyagent — Get your API key at https://app.supyagent.com\",\n `SUPYAGENT_API_KEY=${apiKeys?.supyagent ?? \"\"}`,\n \"\",\n \"# AI Provider\",\n `${ai.envKey}=${apiKeys?.provider ?? \"\"}`,\n \"\",\n \"# Database\",\n `DATABASE_URL=\"file:./dev.db\"`,\n \"\",\n ];\n\n writeFileSync(join(projectPath, \".env.local\"), lines.join(\"\\n\"), \"utf-8\");\n}\n\nexport async function runDbSetup(projectPath: string): Promise<void> {\n const pm = await detectPackageManager(projectPath);\n const cmd = pm?.name ?? \"pnpm\";\n execSync(`${cmd} run db:setup`, {\n cwd: projectPath,\n stdio: \"inherit\",\n env: { ...process.env, DATABASE_URL: \"file:./dev.db\" },\n });\n}\n\nexport async function runDevServer(projectPath: string): Promise<never> {\n const pm = await detectPackageManager(projectPath);\n const cmd = pm?.name ?? \"pnpm\";\n\n const child = nodeSpawn(cmd, [\"run\", \"dev\"], {\n cwd: projectPath,\n stdio: \"inherit\",\n });\n\n const forward = (signal: NodeJS.Signals) => {\n child.kill(signal);\n };\n\n process.on(\"SIGINT\", forward);\n process.on(\"SIGTERM\", forward);\n\n return new Promise((_, reject) => {\n child.on(\"close\", (code) => {\n process.off(\"SIGINT\", forward);\n process.off(\"SIGTERM\", forward);\n process.exit(code ?? 0);\n });\n child.on(\"error\", reject);\n });\n}\n"],"mappings":"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","names":["p","pc","writeFileSync","join","detectPackageManager","writeFileSync","join","detectPackageManager","pc"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-supyagent-app",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "Create a supyagent-powered chatbot app",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,32 @@
1
+ import { convertToModelMessages, streamText, stepCountIs, type UIMessage } from 'ai';
2
+ {{aiProviderImport}};
3
+ import { supyagent, createBashTool } from '@supyagent/sdk';
4
+ import { createPrismaAdapter } from '@supyagent/sdk/prisma';
5
+ import { prisma } from '@/lib/prisma';
6
+
7
+ const client = supyagent({ apiKey: process.env.SUPYAGENT_API_KEY! });
8
+ const adapter = createPrismaAdapter(prisma);
9
+
10
+ export async function POST(req: Request) {
11
+ const { messages, chatId }: { messages: UIMessage[]; chatId: string } = await req.json();
12
+
13
+ await adapter.saveChat(chatId, messages as any);
14
+
15
+ const { systemPrompt: skillsPrompt, tools: skillTools } = await client.skills({ cache: 300 });
16
+ const tools = { ...skillTools, bash: createBashTool() };
17
+
18
+ const result = streamText({
19
+ model: {{aiModel}},
20
+ system: `You are a helpful assistant.\n\n${skillsPrompt}\n\nUse the loadSkill tool to get detailed instructions before using any skill. Use the apiCall tool to make authenticated API requests. You can also run bash commands for general tasks. When a tool execution is not approved by the user, do not retry it — explain what you were trying to do and ask how to proceed.`,
21
+ messages: await convertToModelMessages(messages),
22
+ tools,
23
+ stopWhen: stepCountIs(5),
24
+ });
25
+
26
+ return result.toUIMessageStreamResponse({
27
+ originalMessages: messages,
28
+ onFinish: async ({ messages: updatedMessages }) => {
29
+ await adapter.saveChat(chatId, updatedMessages as any);
30
+ },
31
+ });
32
+ }
@@ -17,7 +17,7 @@
17
17
  "{{aiProviderPackage}}": "{{aiProviderVersion}}",
18
18
  "@prisma/client": "^6.2.0",
19
19
  "@radix-ui/react-collapsible": "^1.1.0",
20
- "@supyagent/sdk": "^0.1.18",
20
+ "@supyagent/sdk": "^0.1.19",
21
21
  "class-variance-authority": "^0.7.0",
22
22
  "ai": "^6.0.0",
23
23
  "clsx": "^2.1.0",