create-agentmark 0.6.0 → 0.7.0

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
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import fs5 from "fs-extra";
5
- import prompts from "prompts";
4
+ import fs8 from "fs-extra";
5
+ import path6 from "path";
6
+ import prompts2 from "prompts";
6
7
 
7
8
  // src/utils/examples/create-example-app.ts
8
- import fs3 from "fs-extra";
9
- import * as path from "path";
9
+ import fs4 from "fs-extra";
10
+ import * as path2 from "path";
10
11
 
11
12
  // src/utils/providers.ts
12
13
  var Providers = {
@@ -22,6 +23,17 @@ var Providers = {
22
23
  ],
23
24
  imageModels: ["dall-e-3", "dall-e-2"],
24
25
  speechModels: ["tts-1", "tts-1-hd"]
26
+ },
27
+ anthropic: {
28
+ label: "Anthropic",
29
+ languageModels: [
30
+ "claude-sonnet-4-20250514",
31
+ "claude-opus-4-20250514",
32
+ "claude-3-5-sonnet-20241022",
33
+ "claude-3-5-haiku-20241022"
34
+ ],
35
+ imageModels: [],
36
+ speechModels: []
25
37
  }
26
38
  };
27
39
 
@@ -49,6 +61,15 @@ var createAdapterConfig = (provider) => {
49
61
  toolRegistry: "MastraToolRegistry",
50
62
  webhookHandler: "MastraAdapterWebhookHandler"
51
63
  }
64
+ },
65
+ "claude-agent-sdk": {
66
+ package: "@agentmark-ai/claude-agent-sdk-adapter",
67
+ dependencies: ["@anthropic-ai/claude-agent-sdk@^0.1.0"],
68
+ classes: {
69
+ modelRegistry: "ClaudeAgentModelRegistry",
70
+ toolRegistry: "ClaudeAgentToolRegistry",
71
+ webhookHandler: "ClaudeAgentWebhookHandler"
72
+ }
52
73
  }
53
74
  };
54
75
  };
@@ -66,7 +87,61 @@ function getAdapterConfig(adapter, provider) {
66
87
 
67
88
  // src/utils/examples/templates/app-index.ts
68
89
  var getIndexFileContent = (adapter = "ai-sdk") => {
69
- if (adapter === "mastra") {
90
+ if (adapter === "claude-agent-sdk") {
91
+ return `import "dotenv/config";
92
+ import { query } from "@anthropic-ai/claude-agent-sdk";
93
+ import { withTracing } from "@agentmark-ai/claude-agent-sdk-adapter";
94
+ import { client } from "./agentmark.client";
95
+
96
+ const telemetry = {
97
+ isEnabled: true,
98
+ metadata: {
99
+ trace_name: "customer-support",
100
+ user_id: "user-123",
101
+ session_id: "session-123",
102
+ session_name: "my-first-session",
103
+ },
104
+ };
105
+
106
+ const runCustomerSupport = async (customer_message: string) => {
107
+ const prompt = await client.loadTextPrompt("customer-support-agent");
108
+ const adapted = await prompt.format({
109
+ props: {
110
+ customer_question: customer_message,
111
+ },
112
+ telemetry,
113
+ });
114
+
115
+ // Execute with Claude Agent SDK using withTracing for telemetry
116
+ // The adapted object contains { query, telemetry } ready for withTracing()
117
+ const tracedResult = await withTracing(query, adapted);
118
+
119
+ // traceId is available immediately
120
+ console.log("Trace ID:", tracedResult.traceId);
121
+
122
+ let result = "";
123
+ for await (const message of tracedResult) {
124
+ if (message.type === "result" && message.subtype === "success") {
125
+ result = message.result || "";
126
+ }
127
+ }
128
+
129
+ return result;
130
+ };
131
+
132
+ const main = async () => {
133
+ try {
134
+ const user_message = "How long does shipping take?";
135
+ const assistant = await runCustomerSupport(user_message);
136
+ console.log("Customer support response:", assistant);
137
+ } catch (error) {
138
+ console.error(error);
139
+ }
140
+ };
141
+
142
+ main();
143
+ `;
144
+ } else if (adapter === "mastra") {
70
145
  return `import "dotenv/config";
71
146
  import { Agent } from "@mastra/core/agent";
72
147
  import { client } from "./agentmark.client";
@@ -158,70 +233,328 @@ main();
158
233
  };
159
234
 
160
235
  // src/utils/examples/templates/env.ts
161
- var getEnvFileContent = (_modelProvider, apiKey = "") => {
236
+ var getEnvFileContent = (_modelProvider, apiKey = "", adapter = "ai-sdk") => {
162
237
  const apiKeyValue = apiKey || "your_api_key_here";
238
+ const apiKeyName = adapter === "claude-agent-sdk" ? "ANTHROPIC_API_KEY" : "OPENAI_API_KEY";
163
239
  return `# Cloud deployment: Set these environment variables
164
240
  # AGENTMARK_BASE_URL=https://api.agentmark.co
165
241
  # AGENTMARK_API_KEY=your_agentmark_api_key
166
242
  # AGENTMARK_APP_ID=your_agentmark_app_id
167
243
  # Learn more: https://docs.agentmark.co/platform/getting_started/quickstart
168
244
 
169
- OPENAI_API_KEY=${apiKeyValue}
245
+ ${apiKeyName}=${apiKeyValue}
170
246
  `;
171
247
  };
172
248
 
173
249
  // src/utils/examples/templates/package-setup.ts
250
+ import fs2 from "fs-extra";
251
+ import { execSync } from "child_process";
252
+
253
+ // src/utils/file-merge.ts
174
254
  import fs from "fs-extra";
175
- import { execSync, execFileSync } from "child_process";
176
- var setupPackageJson = (targetPath = ".", deploymentMode = "cloud") => {
255
+ import path from "path";
256
+ function mergePackageJson(targetPath, agentmarkDeps, agentmarkDevDeps, agentmarkScripts) {
257
+ const packageJsonPath = path.join(targetPath, "package.json");
258
+ const result = {
259
+ success: false,
260
+ warnings: [],
261
+ added: [],
262
+ skipped: []
263
+ };
264
+ try {
265
+ if (!fs.existsSync(packageJsonPath)) {
266
+ result.warnings.push("No existing package.json found");
267
+ return result;
268
+ }
269
+ const existing = fs.readJsonSync(packageJsonPath);
270
+ if (!existing.dependencies) {
271
+ existing.dependencies = {};
272
+ }
273
+ if (!existing.devDependencies) {
274
+ existing.devDependencies = {};
275
+ }
276
+ if (!existing.scripts) {
277
+ existing.scripts = {};
278
+ }
279
+ const deps = existing.dependencies;
280
+ const devDeps = existing.devDependencies;
281
+ const scripts = existing.scripts;
282
+ for (const [pkg, version] of Object.entries(agentmarkDeps)) {
283
+ if (deps[pkg]) {
284
+ result.skipped.push(`dependency: ${pkg} (already exists)`);
285
+ } else {
286
+ deps[pkg] = version;
287
+ result.added.push(`dependency: ${pkg}@${version}`);
288
+ }
289
+ }
290
+ for (const [pkg, version] of Object.entries(agentmarkDevDeps)) {
291
+ if (devDeps[pkg]) {
292
+ result.skipped.push(`devDependency: ${pkg} (already exists)`);
293
+ } else {
294
+ devDeps[pkg] = version;
295
+ result.added.push(`devDependency: ${pkg}@${version}`);
296
+ }
297
+ }
298
+ for (const [scriptName, scriptCmd] of Object.entries(agentmarkScripts)) {
299
+ if (scripts[scriptName]) {
300
+ const namespacedName = `agentmark:${scriptName}`;
301
+ if (scripts[namespacedName]) {
302
+ result.skipped.push(`script: ${scriptName}`);
303
+ result.warnings.push(
304
+ `Script "${scriptName}" and "${namespacedName}" both already exist. Skipping.`
305
+ );
306
+ } else {
307
+ scripts[namespacedName] = scriptCmd;
308
+ result.added.push(`script: ${namespacedName} (namespaced due to conflict)`);
309
+ result.warnings.push(
310
+ `Script "${scriptName}" already exists. Added as "${namespacedName}" instead.`
311
+ );
312
+ }
313
+ } else {
314
+ scripts[scriptName] = scriptCmd;
315
+ result.added.push(`script: ${scriptName}`);
316
+ }
317
+ }
318
+ fs.writeJsonSync(packageJsonPath, existing, { spaces: 2 });
319
+ result.success = true;
320
+ result.content = JSON.stringify(existing, null, 2);
321
+ return result;
322
+ } catch (error) {
323
+ result.warnings.push(`Error merging package.json: ${error}`);
324
+ return result;
325
+ }
326
+ }
327
+ function appendGitignore(targetPath, entries) {
328
+ const gitignorePath = path.join(targetPath, ".gitignore");
329
+ const result = {
330
+ success: false,
331
+ warnings: [],
332
+ added: [],
333
+ skipped: []
334
+ };
335
+ try {
336
+ let existingContent = "";
337
+ if (fs.existsSync(gitignorePath)) {
338
+ existingContent = fs.readFileSync(gitignorePath, "utf-8");
339
+ }
340
+ const existingEntries = new Set(
341
+ existingContent.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map((line) => line.replace(/\/$/, ""))
342
+ // Remove trailing slashes for comparison
343
+ );
344
+ const entriesToAdd = [];
345
+ for (const entry of entries) {
346
+ const normalizedEntry = entry.replace(/\/$/, "");
347
+ if (existingEntries.has(normalizedEntry)) {
348
+ result.skipped.push(entry);
349
+ } else {
350
+ entriesToAdd.push(entry);
351
+ result.added.push(entry);
352
+ }
353
+ }
354
+ if (entriesToAdd.length > 0) {
355
+ let newContent = existingContent;
356
+ if (newContent && !newContent.endsWith("\n")) {
357
+ newContent += "\n";
358
+ }
359
+ if (newContent.trim()) {
360
+ newContent += "\n";
361
+ }
362
+ newContent += "# AgentMark\n";
363
+ newContent += entriesToAdd.join("\n");
364
+ newContent += "\n";
365
+ fs.writeFileSync(gitignorePath, newContent);
366
+ result.content = newContent;
367
+ }
368
+ result.success = true;
369
+ return result;
370
+ } catch (error) {
371
+ result.warnings.push(`Error appending to .gitignore: ${error}`);
372
+ return result;
373
+ }
374
+ }
375
+ function appendEnv(targetPath, envVars) {
376
+ const envPath = path.join(targetPath, ".env");
377
+ const result = {
378
+ success: false,
379
+ warnings: [],
380
+ added: [],
381
+ skipped: []
382
+ };
383
+ try {
384
+ let existingContent = "";
385
+ if (fs.existsSync(envPath)) {
386
+ existingContent = fs.readFileSync(envPath, "utf-8");
387
+ }
388
+ const existingKeys = /* @__PURE__ */ new Set();
389
+ const lines = existingContent.split("\n");
390
+ for (const line of lines) {
391
+ const trimmed = line.trim();
392
+ if (trimmed && !trimmed.startsWith("#")) {
393
+ const match = trimmed.match(/^([^=]+)=/);
394
+ if (match && match[1]) {
395
+ existingKeys.add(match[1]);
396
+ }
397
+ }
398
+ }
399
+ const varsToAdd = [];
400
+ for (const [key, value] of Object.entries(envVars)) {
401
+ if (existingKeys.has(key)) {
402
+ result.skipped.push(key);
403
+ } else {
404
+ varsToAdd.push([key, value]);
405
+ result.added.push(key);
406
+ }
407
+ }
408
+ if (varsToAdd.length > 0) {
409
+ let newContent = existingContent;
410
+ if (newContent && !newContent.endsWith("\n")) {
411
+ newContent += "\n";
412
+ }
413
+ if (newContent.trim()) {
414
+ newContent += "\n";
415
+ }
416
+ newContent += "# AgentMark\n";
417
+ for (const [key, value] of varsToAdd) {
418
+ newContent += `${key}=${value}
419
+ `;
420
+ }
421
+ fs.writeFileSync(envPath, newContent);
422
+ result.content = newContent;
423
+ }
424
+ result.success = true;
425
+ return result;
426
+ } catch (error) {
427
+ result.warnings.push(`Error appending to .env: ${error}`);
428
+ return result;
429
+ }
430
+ }
431
+
432
+ // src/utils/types.ts
433
+ var PACKAGE_MANAGERS = {
434
+ "yarn.lock": {
435
+ name: "yarn",
436
+ lockFile: "yarn.lock",
437
+ installCmd: "yarn install",
438
+ addCmd: "yarn add",
439
+ addDevCmd: "yarn add --dev",
440
+ runCmd: "yarn"
441
+ },
442
+ "pnpm-lock.yaml": {
443
+ name: "pnpm",
444
+ lockFile: "pnpm-lock.yaml",
445
+ installCmd: "pnpm install",
446
+ addCmd: "pnpm add",
447
+ addDevCmd: "pnpm add --save-dev",
448
+ runCmd: "pnpm"
449
+ },
450
+ "bun.lockb": {
451
+ name: "bun",
452
+ lockFile: "bun.lockb",
453
+ installCmd: "bun install",
454
+ addCmd: "bun add",
455
+ addDevCmd: "bun add --dev",
456
+ runCmd: "bun run"
457
+ },
458
+ "package-lock.json": {
459
+ name: "npm",
460
+ lockFile: "package-lock.json",
461
+ installCmd: "npm install",
462
+ addCmd: "npm install",
463
+ addDevCmd: "npm install --save-dev",
464
+ runCmd: "npm run"
465
+ }
466
+ };
467
+ var DEFAULT_PACKAGE_MANAGER = PACKAGE_MANAGERS["package-lock.json"];
468
+ var CONFLICT_FILES = [
469
+ { path: "agentmark.json", type: "config", strategy: "prompt" },
470
+ { path: "agentmark", type: "directory", strategy: "prompt" },
471
+ { path: "agentmark.client.ts", type: "source", strategy: "prompt" },
472
+ { path: "agentmark_client.py", type: "source", strategy: "prompt" },
473
+ { path: ".gitignore", type: "dotfile", strategy: "append" },
474
+ { path: ".env", type: "dotfile", strategy: "append" },
475
+ { path: "package.json", type: "config", strategy: "merge" },
476
+ { path: "index.ts", type: "source", strategy: "skip" },
477
+ { path: "main.py", type: "source", strategy: "skip" },
478
+ { path: "tsconfig.json", type: "config", strategy: "skip" },
479
+ { path: "pyproject.toml", type: "config", strategy: "skip" }
480
+ ];
481
+
482
+ // src/utils/examples/templates/package-setup.ts
483
+ var setupPackageJson = (targetPath = ".", deploymentMode = "cloud", projectInfo = null) => {
177
484
  const packageJsonPath = `${targetPath}/package.json`;
178
- if (!fs.existsSync(packageJsonPath)) {
485
+ const isExistingProject = projectInfo?.isExistingProject ?? false;
486
+ if (!fs2.existsSync(packageJsonPath)) {
179
487
  console.log("Creating package.json...");
180
488
  execSync("npm init -y", { cwd: targetPath });
181
489
  }
182
- const pkgJson = fs.readJsonSync(packageJsonPath);
183
- pkgJson.name = pkgJson.name === "test" || !pkgJson.name ? "agentmark-example-app" : pkgJson.name;
184
- pkgJson.description = pkgJson.description || "A simple Node.js app using the Agentmark SDK";
185
- const devScript = "agentmark dev";
186
- const scripts = {
187
- ...pkgJson.scripts,
188
- "demo": "npx tsx index.ts",
189
- "dev": devScript,
190
- "prompt": "agentmark run-prompt",
191
- "experiment": "agentmark run-experiment"
192
- };
193
- if (deploymentMode === "static") {
194
- scripts["build"] = "agentmark build --out dist/agentmark";
490
+ if (isExistingProject && fs2.existsSync(packageJsonPath)) {
491
+ const scriptsToAdd = {
492
+ "demo": "npx tsx index.ts",
493
+ "dev": "agentmark dev",
494
+ "prompt": "agentmark run-prompt",
495
+ "experiment": "agentmark run-experiment"
496
+ };
497
+ if (deploymentMode === "static") {
498
+ scriptsToAdd["build"] = "agentmark build --out dist/agentmark";
499
+ }
500
+ const result = mergePackageJson(targetPath, {}, {}, scriptsToAdd);
501
+ if (result.added.length > 0) {
502
+ console.log(`\u2705 Added to package.json: ${result.added.join(", ")}`);
503
+ }
504
+ if (result.skipped.length > 0) {
505
+ console.log(`\u23ED\uFE0F Skipped existing in package.json: ${result.skipped.join(", ")}`);
506
+ }
507
+ if (result.warnings.length > 0) {
508
+ result.warnings.forEach((w) => console.log(`\u26A0\uFE0F ${w}`));
509
+ }
510
+ } else {
511
+ const pkgJson = fs2.readJsonSync(packageJsonPath);
512
+ pkgJson.name = pkgJson.name === "test" || !pkgJson.name ? "agentmark-example-app" : pkgJson.name;
513
+ pkgJson.description = pkgJson.description || "A simple Node.js app using the Agentmark SDK";
514
+ const devScript = "agentmark dev";
515
+ const scripts = {
516
+ ...pkgJson.scripts,
517
+ "demo": "npx tsx index.ts",
518
+ "dev": devScript,
519
+ "prompt": "agentmark run-prompt",
520
+ "experiment": "agentmark run-experiment"
521
+ };
522
+ if (deploymentMode === "static") {
523
+ scripts["build"] = "agentmark build --out dist/agentmark";
524
+ }
525
+ pkgJson.scripts = scripts;
526
+ pkgJson.overrides = {
527
+ ...pkgJson.overrides,
528
+ "axios": "^1.7.9"
529
+ };
530
+ fs2.writeJsonSync(packageJsonPath, pkgJson, { spaces: 2 });
195
531
  }
196
- pkgJson.scripts = scripts;
197
- pkgJson.overrides = {
198
- ...pkgJson.overrides,
199
- "axios": "^1.7.9"
200
- };
201
- fs.writeJsonSync(packageJsonPath, pkgJson, { spaces: 2 });
202
532
  };
203
- var installDependencies = (modelProvider, targetPath = ".", adapter = "ai-sdk", deploymentMode = "cloud") => {
533
+ var installDependencies = (modelProvider, targetPath = ".", adapter = "ai-sdk", deploymentMode = "cloud", packageManager = null) => {
204
534
  console.log("Installing required packages...");
205
535
  console.log("This might take a moment...");
206
536
  const adapterConfig = getAdapterConfig(adapter, modelProvider);
537
+ const pm = packageManager || DEFAULT_PACKAGE_MANAGER;
538
+ const npmSuffix = pm.name === "npm" ? " --legacy-peer-deps" : "";
207
539
  try {
208
- const devDepsCmd = "npm install --save-dev typescript ts-node @types/node @agentmark-ai/cli --legacy-peer-deps";
540
+ const devDeps = ["typescript", "ts-node", "@types/node", "@agentmark-ai/cli"];
541
+ const devDepsCmd = `${pm.addDevCmd} ${devDeps.join(" ")}${npmSuffix}`;
542
+ console.log(`Using ${pm.name} to install dependencies...`);
209
543
  execSync(devDepsCmd, {
210
544
  stdio: "inherit",
211
545
  cwd: targetPath
212
546
  });
213
547
  const loaderPackages = deploymentMode === "static" ? ["@agentmark-ai/loader-api", "@agentmark-ai/loader-file"] : ["@agentmark-ai/loader-api"];
214
- const installArgs = [
215
- "install",
548
+ const deps = [
216
549
  "dotenv",
217
550
  "@agentmark-ai/prompt-core",
218
551
  "@agentmark-ai/sdk",
219
552
  adapterConfig.package,
220
553
  ...loaderPackages,
221
- ...adapterConfig.dependencies,
222
- "--legacy-peer-deps"
554
+ ...adapterConfig.dependencies
223
555
  ];
224
- execFileSync("npm", installArgs, { stdio: "inherit", cwd: targetPath });
556
+ const depsCmd = `${pm.addCmd} ${deps.join(" ")}${npmSuffix}`;
557
+ execSync(depsCmd, { stdio: "inherit", cwd: targetPath });
225
558
  console.log("Packages installed successfully!");
226
559
  } catch (error) {
227
560
  console.error("Error installing packages:", error);
@@ -395,28 +728,32 @@ var getStoryDataset = () => {
395
728
  };
396
729
 
397
730
  // src/utils/examples/templates/example-prompts.ts
398
- import fs2 from "fs-extra";
731
+ import fs3 from "fs-extra";
399
732
  var createExamplePrompts = (model, targetPath = ".", adapter = "ai-sdk") => {
400
- fs2.ensureDirSync(`${targetPath}/agentmark`);
401
- if (adapter !== "mastra") {
733
+ fs3.ensureDirSync(`${targetPath}/agentmark`);
734
+ const noImageSupport = ["mastra", "claude-agent-sdk"];
735
+ const noSpeechSupport = ["mastra", "claude-agent-sdk"];
736
+ const skipImagePrompts = noImageSupport.includes(adapter);
737
+ const skipSpeechPrompts = noSpeechSupport.includes(adapter);
738
+ if (!skipImagePrompts) {
402
739
  const animalDrawingPrompt = getAnimalDrawingPrompt();
403
- fs2.writeFileSync(`${targetPath}/agentmark/animal-drawing.prompt.mdx`, animalDrawingPrompt);
740
+ fs3.writeFileSync(`${targetPath}/agentmark/animal-drawing.prompt.mdx`, animalDrawingPrompt);
404
741
  const animalDataset = getAnimalDataset();
405
- fs2.writeFileSync(`${targetPath}/agentmark/animal.jsonl`, animalDataset);
742
+ fs3.writeFileSync(`${targetPath}/agentmark/animal.jsonl`, animalDataset);
406
743
  }
407
744
  const customerSupportPrompt = getCustomerSupportPrompt(model);
408
- fs2.writeFileSync(`${targetPath}/agentmark/customer-support-agent.prompt.mdx`, customerSupportPrompt);
745
+ fs3.writeFileSync(`${targetPath}/agentmark/customer-support-agent.prompt.mdx`, customerSupportPrompt);
409
746
  const customerQueryDataset = getCustomerQueryDataset();
410
- fs2.writeFileSync(`${targetPath}/agentmark/customer-query.jsonl`, customerQueryDataset);
747
+ fs3.writeFileSync(`${targetPath}/agentmark/customer-query.jsonl`, customerQueryDataset);
411
748
  const partyPlannerPrompt = getPartyPlannerPrompt(model);
412
- fs2.writeFileSync(`${targetPath}/agentmark/party-planner.prompt.mdx`, partyPlannerPrompt);
749
+ fs3.writeFileSync(`${targetPath}/agentmark/party-planner.prompt.mdx`, partyPlannerPrompt);
413
750
  const partyDataset = getPartyDataset();
414
- fs2.writeFileSync(`${targetPath}/agentmark/party.jsonl`, partyDataset);
415
- if (adapter !== "mastra") {
751
+ fs3.writeFileSync(`${targetPath}/agentmark/party.jsonl`, partyDataset);
752
+ if (!skipSpeechPrompts) {
416
753
  const storyTellerPrompt = getStoryTellerPrompt();
417
- fs2.writeFileSync(`${targetPath}/agentmark/story-teller.prompt.mdx`, storyTellerPrompt);
754
+ fs3.writeFileSync(`${targetPath}/agentmark/story-teller.prompt.mdx`, storyTellerPrompt);
418
755
  const storyDataset = getStoryDataset();
419
- fs2.writeFileSync(`${targetPath}/agentmark/story.jsonl`, storyDataset);
756
+ fs3.writeFileSync(`${targetPath}/agentmark/story.jsonl`, storyDataset);
420
757
  }
421
758
  };
422
759
 
@@ -425,8 +762,9 @@ var getClientConfigContent = (options) => {
425
762
  const { provider, languageModels, adapter, deploymentMode = "cloud" } = options;
426
763
  const adapterConfig = getAdapterConfig(adapter, provider);
427
764
  const { modelRegistry, toolRegistry } = adapterConfig.classes;
428
- const providerImport = `import { ${provider} } from '@ai-sdk/${provider}';`;
429
- const extraModelRegs = provider === "openai" ? `.registerModels(["dall-e-3"], (name: string) => ${provider}.image(name))
765
+ const isClaudeAgentSdk = adapter === "claude-agent-sdk";
766
+ const providerImport = isClaudeAgentSdk ? "" : `import { ${provider} } from '@ai-sdk/${provider}';`;
767
+ const extraModelRegs = provider === "openai" && !isClaudeAgentSdk ? `.registerModels(["dall-e-3"], (name: string) => ${provider}.image(name))
430
768
  .registerModels(["tts-1-hd"], (name: string) => ${provider}.speech(name))` : "";
431
769
  const loaderImport = deploymentMode === "cloud" ? `import { ApiLoader } from "@agentmark-ai/loader-api";` : `import { ApiLoader } from "@agentmark-ai/loader-api";
432
770
  import { FileLoader } from "@agentmark-ai/loader-file";`;
@@ -441,6 +779,51 @@ import { FileLoader } from "@agentmark-ai/loader-file";`;
441
779
  });` : ` const loader = process.env.NODE_ENV === 'development'
442
780
  ? ApiLoader.local({ baseUrl: process.env.AGENTMARK_BASE_URL || 'http://localhost:9418' })
443
781
  : new FileLoader('./dist/agentmark');`;
782
+ const modelRegistrySetup = isClaudeAgentSdk ? `function createModelRegistry() {
783
+ // Claude Agent SDK accepts model names directly.
784
+ // Use createDefault() for simple pass-through of model names.
785
+ const modelRegistry = ${modelRegistry}.createDefault();
786
+
787
+ // To configure specific models (e.g., extended thinking), use:
788
+ // const modelRegistry = new ${modelRegistry}()
789
+ // .registerModels(/claude-.*-thinking/, (name) => ({
790
+ // model: name,
791
+ // maxThinkingTokens: 10000, // Enable extended thinking
792
+ // }))
793
+ // .registerModels("claude-sonnet-4-20250514", (name) => ({ model: name }));
794
+
795
+ return modelRegistry;
796
+ }` : `function createModelRegistry() {
797
+ const modelRegistry = new ${modelRegistry}()
798
+ .registerModels(${JSON.stringify(languageModels)}, (name: string) => ${provider}(name))
799
+ ${extraModelRegs};
800
+ return modelRegistry;
801
+ }`;
802
+ const adapterOptionsImport = isClaudeAgentSdk ? `
803
+ // Claude Agent SDK adapter options
804
+ // See: https://github.com/anthropics/claude-agent-sdk
805
+ const adapterOptions = {
806
+ // Permission mode controls tool access:
807
+ // - 'default': Requires user approval for each tool use
808
+ // - 'acceptEdits': Auto-approve file edits only
809
+ // - 'bypassPermissions': Auto-approve all tools (use for automated pipelines)
810
+ // - 'plan': Planning mode only, no tool execution
811
+ permissionMode: 'bypassPermissions' as const,
812
+
813
+ // Maximum conversation turns before stopping
814
+ maxTurns: 20,
815
+
816
+ // Optional: Set working directory for file operations
817
+ // cwd: process.cwd(),
818
+
819
+ // Optional: Budget limit in USD
820
+ // maxBudgetUsd: 10.00,
821
+
822
+ // Optional: Restrict which tools the agent can use
823
+ // allowedTools: ['Read', 'Write', 'Glob'],
824
+ // disallowedTools: ['Bash'],
825
+ };` : "";
826
+ const createClientCall = isClaudeAgentSdk ? `return createAgentMarkClient<AgentMarkTypes, typeof toolRegistry>({ loader, modelRegistry, toolRegistry, evalRegistry, adapterOptions });` : `return createAgentMarkClient<AgentMarkTypes, typeof toolRegistry>({ loader, modelRegistry, toolRegistry, evalRegistry });`;
444
827
  return `// agentmark.client.ts
445
828
  import path from 'node:path';
446
829
  import dotenv from 'dotenv';
@@ -449,13 +832,9 @@ import { createAgentMarkClient, ${modelRegistry}, ${toolRegistry}, EvalRegistry
449
832
  ${loaderImport}
450
833
  import AgentMarkTypes, { Tools } from './agentmark.types';
451
834
  ${providerImport}
835
+ ${adapterOptionsImport}
452
836
 
453
- function createModelRegistry() {
454
- const modelRegistry = new ${modelRegistry}()
455
- .registerModels(${JSON.stringify(languageModels)}, (name: string) => ${provider}(name))
456
- ${extraModelRegs};
457
- return modelRegistry;
458
- }
837
+ ${modelRegistrySetup}
459
838
 
460
839
  function createToolRegistry() {
461
840
  const toolRegistry = new ${toolRegistry}<Tools>()
@@ -502,7 +881,7 @@ ${loaderSetup}
502
881
  const modelRegistry = createModelRegistry();
503
882
  const toolRegistry = createToolRegistry();
504
883
  const evalRegistry = createEvalRegistry();
505
- return createAgentMarkClient<AgentMarkTypes, typeof toolRegistry>({ loader, modelRegistry, toolRegistry, evalRegistry });
884
+ ${createClientCall}
506
885
  }
507
886
 
508
887
  export const client = createClient();
@@ -511,6 +890,99 @@ export const client = createClient();
511
890
 
512
891
  // src/utils/examples/create-example-app.ts
513
892
  import { fetchPromptsFrontmatter, generateTypeDefinitions } from "@agentmark-ai/shared-utils";
893
+
894
+ // src/utils/conflict-resolution.ts
895
+ import prompts from "prompts";
896
+ function getPromptableConflicts(conflictingFiles) {
897
+ return conflictingFiles.filter((file) => file.strategy === "prompt");
898
+ }
899
+ async function promptForSingleConflict(conflict) {
900
+ const typeLabel = conflict.type === "directory" ? "directory" : "file";
901
+ const { action } = await prompts({
902
+ type: "select",
903
+ name: "action",
904
+ message: `${conflict.path} already exists. What would you like to do?`,
905
+ choices: [
906
+ {
907
+ title: `Skip (keep existing ${typeLabel})`,
908
+ value: "skip",
909
+ description: `Don't modify the existing ${typeLabel}`
910
+ },
911
+ {
912
+ title: "Overwrite",
913
+ value: "overwrite",
914
+ description: `Replace with new AgentMark ${typeLabel}`
915
+ }
916
+ ],
917
+ initial: 0
918
+ // Default to skip for safety
919
+ });
920
+ return {
921
+ path: conflict.path,
922
+ action: action || "skip"
923
+ };
924
+ }
925
+ async function promptForResolutions(conflictingFiles) {
926
+ const promptableConflicts = getPromptableConflicts(conflictingFiles);
927
+ if (promptableConflicts.length === 0) {
928
+ return [];
929
+ }
930
+ console.log("\n\u26A0\uFE0F Found existing files that may conflict with AgentMark initialization:\n");
931
+ const resolutions = [];
932
+ for (const conflict of promptableConflicts) {
933
+ const resolution = await promptForSingleConflict(conflict);
934
+ resolutions.push(resolution);
935
+ }
936
+ console.log("");
937
+ return resolutions;
938
+ }
939
+ function getResolutionAction(filePath, resolutions, conflictingFiles) {
940
+ const userResolution = resolutions.find((r) => r.path === filePath);
941
+ if (userResolution) {
942
+ return userResolution.action;
943
+ }
944
+ const conflictFile = conflictingFiles.find((f) => f.path === filePath);
945
+ if (conflictFile) {
946
+ switch (conflictFile.strategy) {
947
+ case "skip":
948
+ return "skip";
949
+ case "merge":
950
+ return "merge";
951
+ case "append":
952
+ return "merge";
953
+ // Append is a form of merge
954
+ case "prompt":
955
+ return "skip";
956
+ }
957
+ }
958
+ return "overwrite";
959
+ }
960
+ function shouldMergeFile(filePath, projectInfo, resolutions) {
961
+ if (!projectInfo || !projectInfo.isExistingProject) {
962
+ return false;
963
+ }
964
+ const action = getResolutionAction(filePath, resolutions, projectInfo.conflictingFiles);
965
+ return action === "merge";
966
+ }
967
+ function displayProjectDetectionSummary(projectInfo) {
968
+ if (!projectInfo.isExistingProject) {
969
+ return;
970
+ }
971
+ console.log("\n\u{1F4C1} Detected existing project:");
972
+ console.log(` Type: ${projectInfo.type}`);
973
+ if (projectInfo.type === "typescript") {
974
+ console.log(` Package Manager: ${projectInfo.packageManager.name}`);
975
+ }
976
+ if (projectInfo.pythonVenv) {
977
+ console.log(` Python Venv: ${projectInfo.pythonVenv.name}`);
978
+ }
979
+ if (projectInfo.hasAgentmarkDir) {
980
+ console.log(" \u26A0\uFE0F AgentMark directory already exists");
981
+ }
982
+ console.log("");
983
+ }
984
+
985
+ // src/utils/examples/create-example-app.ts
514
986
  var setupMCPServer = (client, targetPath) => {
515
987
  if (client === "skip") {
516
988
  console.log("Skipping MCP server setup.");
@@ -520,16 +992,23 @@ var setupMCPServer = (client, targetPath) => {
520
992
  if (client === "vscode") {
521
993
  try {
522
994
  console.log(`Setting up MCP server for VS Code in ${folderName}...`);
523
- const vscodeDir = path.join(targetPath, ".vscode");
524
- fs3.ensureDirSync(vscodeDir);
995
+ const vscodeDir = path2.join(targetPath, ".vscode");
996
+ fs4.ensureDirSync(vscodeDir);
525
997
  const mcpConfig = {
526
998
  servers: {
527
999
  "agentmark-docs": {
528
1000
  url: "https://docs.agentmark.co/mcp"
1001
+ },
1002
+ "agentmark-traces": {
1003
+ command: "npx",
1004
+ args: ["@agentmark-ai/mcp-server"],
1005
+ env: {
1006
+ AGENTMARK_URL: "http://localhost:9418"
1007
+ }
529
1008
  }
530
1009
  }
531
1010
  };
532
- fs3.writeJsonSync(path.join(vscodeDir, "mcp.json"), mcpConfig, { spaces: 2 });
1011
+ fs4.writeJsonSync(path2.join(vscodeDir, "mcp.json"), mcpConfig, { spaces: 2 });
533
1012
  console.log(`\u2705 MCP server configured for VS Code in ${folderName}/.vscode/mcp.json`);
534
1013
  } catch (error) {
535
1014
  console.warn(`Warning: Could not set up MCP server for VS Code:`, error);
@@ -540,16 +1019,23 @@ var setupMCPServer = (client, targetPath) => {
540
1019
  if (client === "zed") {
541
1020
  try {
542
1021
  console.log(`Setting up MCP server for Zed in ${folderName}...`);
543
- const zedDir = path.join(targetPath, ".zed");
544
- fs3.ensureDirSync(zedDir);
1022
+ const zedDir = path2.join(targetPath, ".zed");
1023
+ fs4.ensureDirSync(zedDir);
545
1024
  const zedConfig = {
546
1025
  context_servers: {
547
1026
  "agentmark-docs": {
548
1027
  url: "https://docs.agentmark.co/mcp"
1028
+ },
1029
+ "agentmark-traces": {
1030
+ command: "npx",
1031
+ args: ["@agentmark-ai/mcp-server"],
1032
+ env: {
1033
+ AGENTMARK_URL: "http://localhost:9418"
1034
+ }
549
1035
  }
550
1036
  }
551
1037
  };
552
- fs3.writeJsonSync(path.join(zedDir, "settings.json"), zedConfig, { spaces: 2 });
1038
+ fs4.writeJsonSync(path2.join(zedDir, "settings.json"), zedConfig, { spaces: 2 });
553
1039
  console.log(`\u2705 MCP server configured for Zed in ${folderName}/.zed/settings.json`);
554
1040
  } catch (error) {
555
1041
  console.warn(`Warning: Could not set up MCP server for Zed:`, error);
@@ -560,16 +1046,23 @@ var setupMCPServer = (client, targetPath) => {
560
1046
  if (client === "cursor") {
561
1047
  try {
562
1048
  console.log(`Setting up MCP server for Cursor in ${folderName}...`);
563
- const cursorDir = path.join(targetPath, ".cursor");
564
- fs3.ensureDirSync(cursorDir);
1049
+ const cursorDir = path2.join(targetPath, ".cursor");
1050
+ fs4.ensureDirSync(cursorDir);
565
1051
  const cursorConfig = {
566
1052
  mcpServers: {
567
1053
  "agentmark-docs": {
568
1054
  url: "https://docs.agentmark.co/mcp"
1055
+ },
1056
+ "agentmark-traces": {
1057
+ command: "npx",
1058
+ args: ["@agentmark-ai/mcp-server"],
1059
+ env: {
1060
+ AGENTMARK_URL: "http://localhost:9418"
1061
+ }
569
1062
  }
570
1063
  }
571
1064
  };
572
- fs3.writeJsonSync(path.join(cursorDir, "mcp.json"), cursorConfig, { spaces: 2 });
1065
+ fs4.writeJsonSync(path2.join(cursorDir, "mcp.json"), cursorConfig, { spaces: 2 });
573
1066
  console.log(`\u2705 MCP server configured for Cursor in ${folderName}/.cursor/mcp.json`);
574
1067
  } catch (error) {
575
1068
  console.warn(`Warning: Could not set up MCP server for Cursor:`, error);
@@ -585,10 +1078,17 @@ var setupMCPServer = (client, targetPath) => {
585
1078
  "agentmark-docs": {
586
1079
  type: "http",
587
1080
  url: "https://docs.agentmark.co/mcp"
1081
+ },
1082
+ "agentmark-traces": {
1083
+ command: "npx",
1084
+ args: ["@agentmark-ai/mcp-server"],
1085
+ env: {
1086
+ AGENTMARK_URL: "http://localhost:9418"
1087
+ }
588
1088
  }
589
1089
  }
590
1090
  };
591
- fs3.writeJsonSync(path.join(targetPath, ".mcp.json"), mcpConfig, { spaces: 2 });
1091
+ fs4.writeJsonSync(path2.join(targetPath, ".mcp.json"), mcpConfig, { spaces: 2 });
592
1092
  console.log(`\u2705 MCP server configured for Claude Code in ${folderName}/.mcp.json`);
593
1093
  } catch (error) {
594
1094
  console.warn(`Warning: Could not set up MCP server for Claude Code:`, error);
@@ -597,48 +1097,90 @@ var setupMCPServer = (client, targetPath) => {
597
1097
  return;
598
1098
  }
599
1099
  };
600
- var createExampleApp = async (client, targetPath = ".", apiKey = "", adapter = "ai-sdk", deploymentMode = "cloud") => {
1100
+ var createExampleApp = async (client, targetPath = ".", apiKey = "", adapter = "ai-sdk", deploymentMode = "cloud", projectInfo = null, resolutions = []) => {
601
1101
  try {
602
- const modelProvider = "openai";
603
- const model = "gpt-4o";
604
- console.log("Creating Agent Mark example app...");
1102
+ const modelProvider = adapter === "claude-agent-sdk" ? "anthropic" : "openai";
1103
+ const model = adapter === "claude-agent-sdk" ? "claude-sonnet-4-20250514" : "gpt-4o";
1104
+ const isExistingProject = projectInfo?.isExistingProject ?? false;
1105
+ if (isExistingProject) {
1106
+ console.log("Adding AgentMark to existing project...");
1107
+ } else {
1108
+ console.log("Creating AgentMark example app...");
1109
+ }
605
1110
  const folderName = targetPath;
606
- fs3.ensureDirSync(`${targetPath}/agentmark`);
1111
+ fs4.ensureDirSync(`${targetPath}/agentmark`);
607
1112
  setupMCPServer(client, targetPath);
608
1113
  createExamplePrompts(model, targetPath, adapter);
609
1114
  console.log(`\u2705 Example prompts and datasets created in ${folderName}/agentmark/`);
610
1115
  const langModels = Providers[modelProvider].languageModels.slice(0, 1);
611
- fs3.writeFileSync(
1116
+ fs4.writeFileSync(
612
1117
  `${targetPath}/agentmark.client.ts`,
613
1118
  getClientConfigContent({ provider: modelProvider, languageModels: langModels, adapter, deploymentMode })
614
1119
  );
615
- fs3.writeFileSync(`${targetPath}/.env`, getEnvFileContent(modelProvider, apiKey));
616
- const gitignore = ["node_modules", ".env", "*.agentmark-outputs/", ".agentmark", "dist"].join("\n");
617
- fs3.writeFileSync(`${targetPath}/.gitignore`, gitignore);
618
- fs3.writeFileSync(
619
- `${targetPath}/index.ts`,
620
- getIndexFileContent(adapter)
621
- );
622
- fs3.writeJsonSync(`${targetPath}/tsconfig.json`, getTsConfigContent(), { spaces: 2 });
623
- setupPackageJson(targetPath, deploymentMode);
624
- installDependencies(modelProvider, targetPath, adapter, deploymentMode);
1120
+ if (shouldMergeFile(".env", projectInfo, resolutions)) {
1121
+ const envVars = {};
1122
+ const apiKeyEnvVar = adapter === "claude-agent-sdk" ? "ANTHROPIC_API_KEY" : "OPENAI_API_KEY";
1123
+ if (apiKey) {
1124
+ envVars[apiKeyEnvVar] = apiKey;
1125
+ } else {
1126
+ envVars[apiKeyEnvVar] = adapter === "claude-agent-sdk" ? "your-anthropic-api-key" : "your-openai-api-key";
1127
+ }
1128
+ const result = appendEnv(targetPath, envVars);
1129
+ if (result.added.length > 0) {
1130
+ console.log(`\u2705 Added to .env: ${result.added.join(", ")}`);
1131
+ }
1132
+ if (result.skipped.length > 0) {
1133
+ console.log(`\u23ED\uFE0F Skipped existing .env vars: ${result.skipped.join(", ")}`);
1134
+ }
1135
+ } else {
1136
+ fs4.writeFileSync(`${targetPath}/.env`, getEnvFileContent(modelProvider, apiKey, adapter));
1137
+ }
1138
+ const gitignoreEntries = ["node_modules/", ".env", "*.agentmark-outputs/", ".agentmark/", "dist/"];
1139
+ if (shouldMergeFile(".gitignore", projectInfo, resolutions)) {
1140
+ const result = appendGitignore(targetPath, gitignoreEntries);
1141
+ if (result.added.length > 0) {
1142
+ console.log(`\u2705 Added to .gitignore: ${result.added.join(", ")}`);
1143
+ }
1144
+ if (result.skipped.length > 0) {
1145
+ console.log(`\u23ED\uFE0F Already in .gitignore: ${result.skipped.join(", ")}`);
1146
+ }
1147
+ } else {
1148
+ const gitignore = gitignoreEntries.join("\n");
1149
+ fs4.writeFileSync(`${targetPath}/.gitignore`, gitignore);
1150
+ }
1151
+ if (!isExistingProject) {
1152
+ fs4.writeFileSync(
1153
+ `${targetPath}/index.ts`,
1154
+ getIndexFileContent(adapter)
1155
+ );
1156
+ } else {
1157
+ console.log("\u23ED\uFE0F Skipped index.ts (existing project)");
1158
+ }
1159
+ if (!isExistingProject) {
1160
+ fs4.writeJsonSync(`${targetPath}/tsconfig.json`, getTsConfigContent(), { spaces: 2 });
1161
+ } else {
1162
+ console.log("\u23ED\uFE0F Skipped tsconfig.json (existing project)");
1163
+ }
1164
+ const packageManager = projectInfo?.packageManager ?? null;
1165
+ setupPackageJson(targetPath, deploymentMode, projectInfo);
1166
+ installDependencies(modelProvider, targetPath, adapter, deploymentMode, packageManager);
625
1167
  console.log("Generating types from prompts...");
626
1168
  try {
627
- const agentmarkDir = path.join(targetPath, "agentmark");
628
- const prompts2 = await fetchPromptsFrontmatter({ rootDir: agentmarkDir });
629
- const typeDefinitions = await generateTypeDefinitions(prompts2);
630
- fs3.writeFileSync(`${targetPath}/agentmark.types.ts`, typeDefinitions);
1169
+ const agentmarkDir = path2.join(targetPath, "agentmark");
1170
+ const prompts3 = await fetchPromptsFrontmatter({ rootDir: agentmarkDir });
1171
+ const typeDefinitions = await generateTypeDefinitions(prompts3);
1172
+ fs4.writeFileSync(`${targetPath}/agentmark.types.ts`, typeDefinitions);
631
1173
  } catch (error) {
632
1174
  console.warn("Warning: Could not generate types automatically:", error);
633
1175
  console.log("You can generate types later by running: npx agentmark generate-types --root-dir agentmark");
634
- fs3.writeFileSync(`${targetPath}/agentmark.types.ts`, `// Auto-generated types from AgentMark
1176
+ fs4.writeFileSync(`${targetPath}/agentmark.types.ts`, `// Auto-generated types from AgentMark
635
1177
  // Run 'npx agentmark generate-types --root-dir agentmark' to generate types
636
1178
  export default interface AgentmarkTypes {}
637
1179
  `);
638
1180
  }
639
1181
  console.log("Creating development server entry point...");
640
- const agentmarkInternalDir = path.join(targetPath, ".agentmark");
641
- fs3.ensureDirSync(agentmarkInternalDir);
1182
+ const agentmarkInternalDir = path2.join(targetPath, ".agentmark");
1183
+ fs4.ensureDirSync(agentmarkInternalDir);
642
1184
  const adapterConfig = getAdapterConfig(adapter, modelProvider);
643
1185
  const { webhookHandler } = adapterConfig.classes;
644
1186
  const devEntryContent = `// Auto-generated webhook server entry point
@@ -689,7 +1231,7 @@ main().catch((err) => {
689
1231
  process.exit(1);
690
1232
  });
691
1233
  `;
692
- fs3.writeFileSync(path.join(agentmarkInternalDir, "dev-entry.ts"), devEntryContent);
1234
+ fs4.writeFileSync(path2.join(agentmarkInternalDir, "dev-entry.ts"), devEntryContent);
693
1235
  console.log("\n\u2705 Agentmark initialization completed successfully!");
694
1236
  console.log(
695
1237
  `
@@ -705,11 +1247,21 @@ main().catch((err) => {
705
1247
  console.log("\n" + "\u2550".repeat(70));
706
1248
  console.log("Next Steps");
707
1249
  console.log("\u2550".repeat(70));
1250
+ const runCmd = packageManager?.runCmd ?? "npm run";
1251
+ const pkgJsonPath = path2.join(targetPath, "package.json");
1252
+ let devScriptName = "dev";
1253
+ if (fs4.existsSync(pkgJsonPath)) {
1254
+ const pkgJson = fs4.readJsonSync(pkgJsonPath);
1255
+ if (pkgJson.scripts?.["agentmark:dev"]) {
1256
+ devScriptName = "agentmark:dev";
1257
+ }
1258
+ }
708
1259
  console.log("\n Get Started:");
709
- if (folderName !== "." && folderName !== "./") {
1260
+ if (folderName !== "." && folderName !== "./" && !isExistingProject) {
710
1261
  console.log(` $ cd ${folderName}`);
711
1262
  }
712
- console.log(" $ npm run dev\n");
1263
+ console.log(` $ ${runCmd} ${devScriptName}
1264
+ `);
713
1265
  console.log("\u2500".repeat(70));
714
1266
  console.log("Resources");
715
1267
  console.log("\u2500".repeat(70));
@@ -722,8 +1274,8 @@ main().catch((err) => {
722
1274
  };
723
1275
 
724
1276
  // src/utils/examples/create-python-app.ts
725
- import fs4 from "fs-extra";
726
- import * as path2 from "path";
1277
+ import fs5 from "fs-extra";
1278
+ import * as path3 from "path";
727
1279
  var setupMCPServer2 = (client, targetPath) => {
728
1280
  if (client === "skip") {
729
1281
  console.log("Skipping MCP server setup.");
@@ -733,16 +1285,23 @@ var setupMCPServer2 = (client, targetPath) => {
733
1285
  if (client === "vscode") {
734
1286
  try {
735
1287
  console.log(`Setting up MCP server for VS Code in ${folderName}...`);
736
- const vscodeDir = path2.join(targetPath, ".vscode");
737
- fs4.ensureDirSync(vscodeDir);
1288
+ const vscodeDir = path3.join(targetPath, ".vscode");
1289
+ fs5.ensureDirSync(vscodeDir);
738
1290
  const mcpConfig = {
739
1291
  servers: {
740
1292
  "agentmark-docs": {
741
1293
  url: "https://docs.agentmark.co/mcp"
1294
+ },
1295
+ "agentmark-traces": {
1296
+ command: "npx",
1297
+ args: ["@agentmark-ai/mcp-server"],
1298
+ env: {
1299
+ AGENTMARK_URL: "http://localhost:9418"
1300
+ }
742
1301
  }
743
1302
  }
744
1303
  };
745
- fs4.writeJsonSync(path2.join(vscodeDir, "mcp.json"), mcpConfig, { spaces: 2 });
1304
+ fs5.writeJsonSync(path3.join(vscodeDir, "mcp.json"), mcpConfig, { spaces: 2 });
746
1305
  console.log(`MCP server configured for VS Code in ${folderName}/.vscode/mcp.json`);
747
1306
  } catch (error) {
748
1307
  console.warn(`Warning: Could not set up MCP server for VS Code:`, error);
@@ -752,16 +1311,23 @@ var setupMCPServer2 = (client, targetPath) => {
752
1311
  if (client === "zed") {
753
1312
  try {
754
1313
  console.log(`Setting up MCP server for Zed in ${folderName}...`);
755
- const zedDir = path2.join(targetPath, ".zed");
756
- fs4.ensureDirSync(zedDir);
1314
+ const zedDir = path3.join(targetPath, ".zed");
1315
+ fs5.ensureDirSync(zedDir);
757
1316
  const zedConfig = {
758
1317
  context_servers: {
759
1318
  "agentmark-docs": {
760
1319
  url: "https://docs.agentmark.co/mcp"
1320
+ },
1321
+ "agentmark-traces": {
1322
+ command: "npx",
1323
+ args: ["@agentmark-ai/mcp-server"],
1324
+ env: {
1325
+ AGENTMARK_URL: "http://localhost:9418"
1326
+ }
761
1327
  }
762
1328
  }
763
1329
  };
764
- fs4.writeJsonSync(path2.join(zedDir, "settings.json"), zedConfig, { spaces: 2 });
1330
+ fs5.writeJsonSync(path3.join(zedDir, "settings.json"), zedConfig, { spaces: 2 });
765
1331
  console.log(`MCP server configured for Zed in ${folderName}/.zed/settings.json`);
766
1332
  } catch (error) {
767
1333
  console.warn(`Warning: Could not set up MCP server for Zed:`, error);
@@ -771,16 +1337,23 @@ var setupMCPServer2 = (client, targetPath) => {
771
1337
  if (client === "cursor") {
772
1338
  try {
773
1339
  console.log(`Setting up MCP server for Cursor in ${folderName}...`);
774
- const cursorDir = path2.join(targetPath, ".cursor");
775
- fs4.ensureDirSync(cursorDir);
1340
+ const cursorDir = path3.join(targetPath, ".cursor");
1341
+ fs5.ensureDirSync(cursorDir);
776
1342
  const cursorConfig = {
777
1343
  mcpServers: {
778
1344
  "agentmark-docs": {
779
1345
  url: "https://docs.agentmark.co/mcp"
1346
+ },
1347
+ "agentmark-traces": {
1348
+ command: "npx",
1349
+ args: ["@agentmark-ai/mcp-server"],
1350
+ env: {
1351
+ AGENTMARK_URL: "http://localhost:9418"
1352
+ }
780
1353
  }
781
1354
  }
782
1355
  };
783
- fs4.writeJsonSync(path2.join(cursorDir, "mcp.json"), cursorConfig, { spaces: 2 });
1356
+ fs5.writeJsonSync(path3.join(cursorDir, "mcp.json"), cursorConfig, { spaces: 2 });
784
1357
  console.log(`MCP server configured for Cursor in ${folderName}/.cursor/mcp.json`);
785
1358
  } catch (error) {
786
1359
  console.warn(`Warning: Could not set up MCP server for Cursor:`, error);
@@ -795,10 +1368,17 @@ var setupMCPServer2 = (client, targetPath) => {
795
1368
  "agentmark-docs": {
796
1369
  type: "http",
797
1370
  url: "https://docs.agentmark.co/mcp"
1371
+ },
1372
+ "agentmark-traces": {
1373
+ command: "npx",
1374
+ args: ["@agentmark-ai/mcp-server"],
1375
+ env: {
1376
+ AGENTMARK_URL: "http://localhost:9418"
1377
+ }
798
1378
  }
799
1379
  }
800
1380
  };
801
- fs4.writeJsonSync(path2.join(targetPath, ".mcp.json"), mcpConfig, { spaces: 2 });
1381
+ fs5.writeJsonSync(path3.join(targetPath, ".mcp.json"), mcpConfig, { spaces: 2 });
802
1382
  console.log(`MCP server configured for Claude Code in ${folderName}/.mcp.json`);
803
1383
  } catch (error) {
804
1384
  console.warn(`Warning: Could not set up MCP server for Claude Code:`, error);
@@ -806,7 +1386,42 @@ var setupMCPServer2 = (client, targetPath) => {
806
1386
  return;
807
1387
  }
808
1388
  };
809
- var getPyprojectContent = (projectName) => {
1389
+ var getPyprojectContent = (projectName, adapter) => {
1390
+ if (adapter === "claude-agent-sdk") {
1391
+ return `[project]
1392
+ name = "${projectName}"
1393
+ version = "0.1.0"
1394
+ description = "An AgentMark application using Claude Agent SDK"
1395
+ requires-python = ">=3.12"
1396
+ dependencies = [
1397
+ "agentmark-claude-agent-sdk>=0.1.0",
1398
+ "agentmark-prompt-core>=0.1.0",
1399
+ "python-dotenv>=1.0.0",
1400
+ "claude-agent-sdk>=0.1.0",
1401
+ ]
1402
+
1403
+ [project.optional-dependencies]
1404
+ dev = [
1405
+ "pytest>=7.0",
1406
+ "pytest-asyncio>=0.21",
1407
+ "mypy>=1.0",
1408
+ ]
1409
+ otel = [
1410
+ "opentelemetry-api>=1.20",
1411
+ "opentelemetry-sdk>=1.20",
1412
+ ]
1413
+
1414
+ [build-system]
1415
+ requires = ["hatchling"]
1416
+ build-backend = "hatchling.build"
1417
+
1418
+ [tool.pytest.ini_options]
1419
+ asyncio_mode = "auto"
1420
+
1421
+ [tool.mypy]
1422
+ strict = true
1423
+ `;
1424
+ }
810
1425
  return `[project]
811
1426
  name = "${projectName}"
812
1427
  version = "0.1.0"
@@ -839,7 +1454,58 @@ asyncio_mode = "auto"
839
1454
  strict = true
840
1455
  `;
841
1456
  };
842
- var getAgentmarkClientContent = (_deploymentMode) => {
1457
+ var getAgentmarkClientContent = (_deploymentMode, adapter) => {
1458
+ if (adapter === "claude-agent-sdk") {
1459
+ return `"""AgentMark client configuration.
1460
+
1461
+ This file configures the AgentMark client with Claude Agent SDK adapter.
1462
+ Customize the model registry and tool registry as needed.
1463
+ """
1464
+
1465
+ import os
1466
+ from pathlib import Path
1467
+ from dotenv import load_dotenv
1468
+
1469
+ from agentmark.prompt_core import FileLoader
1470
+ from agentmark_claude_agent_sdk import (
1471
+ create_claude_agent_client,
1472
+ create_default_model_registry,
1473
+ ClaudeAgentToolRegistry,
1474
+ )
1475
+
1476
+ # Load environment variables
1477
+ load_dotenv()
1478
+
1479
+ # Configure model registry with default mappings
1480
+ # Supports: claude-* models
1481
+ model_registry = create_default_model_registry()
1482
+
1483
+ # Configure tool registry for custom tools
1484
+ tool_registry = ClaudeAgentToolRegistry()
1485
+
1486
+ # Example tool registration:
1487
+ # tool_registry.register(
1488
+ # "search",
1489
+ # lambda args, ctx: f"Search results for: {args['query']}",
1490
+ # description="Search the web",
1491
+ # parameters={"type": "object", "properties": {"query": {"type": "string"}}, "required": ["query"]},
1492
+ # )
1493
+
1494
+ # Create file loader for local development
1495
+ # Uses the project root as base directory for resolving relative paths
1496
+ project_root = Path(__file__).parent.resolve()
1497
+ loader = FileLoader(base_dir=str(project_root))
1498
+
1499
+ # Create the client
1500
+ client = create_claude_agent_client(
1501
+ model_registry=model_registry,
1502
+ tool_registry=tool_registry,
1503
+ loader=loader,
1504
+ )
1505
+
1506
+ __all__ = ["client"]
1507
+ `;
1508
+ }
843
1509
  return `"""AgentMark client configuration.
844
1510
 
845
1511
  This file configures the AgentMark client with Pydantic AI adapter.
@@ -888,7 +1554,57 @@ client = create_pydantic_ai_client(
888
1554
  __all__ = ["client"]
889
1555
  `;
890
1556
  };
891
- var getMainPyContent = () => {
1557
+ var getMainPyContent = (adapter) => {
1558
+ if (adapter === "claude-agent-sdk") {
1559
+ return `"""Example usage of AgentMark with Claude Agent SDK.
1560
+
1561
+ Run with: python main.py
1562
+ """
1563
+
1564
+ import asyncio
1565
+ import json
1566
+ from pathlib import Path
1567
+
1568
+ from agentmark_claude_agent_sdk import run_text_prompt
1569
+ from agentmark_client import client
1570
+
1571
+
1572
+ async def main():
1573
+ """Run the party planner prompt."""
1574
+ # Load the prompt AST (in production, use the API loader)
1575
+ prompt_path = Path("agentmark/party-planner.prompt.mdx.json")
1576
+
1577
+ if not prompt_path.exists():
1578
+ print("Prompt file not found. Run 'agentmark build' first.")
1579
+ return
1580
+
1581
+ with open(prompt_path) as f:
1582
+ ast = json.load(f)
1583
+
1584
+ # Load and format the prompt
1585
+ prompt = await client.load_text_prompt(ast)
1586
+ params = await prompt.format(props={
1587
+ "numberOfGuests": 10,
1588
+ "theme": "80s disco",
1589
+ "dietaryRestrictions": ["vegetarian", "gluten-free"],
1590
+ })
1591
+
1592
+ # Execute the prompt
1593
+ print("Running party planner prompt...")
1594
+ result = await run_text_prompt(params)
1595
+
1596
+ print("\\n" + "=" * 50)
1597
+ print("Party Plan:")
1598
+ print("=" * 50)
1599
+ print(result.output)
1600
+ print("\\n" + "-" * 50)
1601
+ print(f"Tokens used: {result.usage}")
1602
+
1603
+
1604
+ if __name__ == "__main__":
1605
+ asyncio.run(main())
1606
+ `;
1607
+ }
892
1608
  return `"""Example usage of AgentMark with Pydantic AI.
893
1609
 
894
1610
  Run with: python main.py
@@ -938,7 +1654,8 @@ if __name__ == "__main__":
938
1654
  asyncio.run(main())
939
1655
  `;
940
1656
  };
941
- var getDevServerContent = () => {
1657
+ var getDevServerContent = (adapter) => {
1658
+ const adapterPackage = adapter === "claude-agent-sdk" ? "agentmark_claude_agent_sdk" : "agentmark_pydantic_ai_v0";
942
1659
  return `"""Auto-generated webhook server for AgentMark development.
943
1660
 
944
1661
  This server is started by 'npm run dev' (agentmark dev) and handles
@@ -952,7 +1669,7 @@ from pathlib import Path
952
1669
  # Add parent directory to path for imports
953
1670
  sys.path.insert(0, str(Path(__file__).parent.parent))
954
1671
 
955
- from agentmark_pydantic_ai_v0 import create_webhook_server
1672
+ from ${adapterPackage} import create_webhook_server
956
1673
  from agentmark_client import client
957
1674
 
958
1675
 
@@ -965,7 +1682,12 @@ if __name__ == "__main__":
965
1682
  create_webhook_server(client, args.webhook_port, args.api_server_port)
966
1683
  `;
967
1684
  };
968
- var getEnvContent = (apiKey) => {
1685
+ var getEnvContent = (apiKey, adapter) => {
1686
+ if (adapter === "claude-agent-sdk") {
1687
+ return `# Anthropic API Key
1688
+ ANTHROPIC_API_KEY=${apiKey}
1689
+ `;
1690
+ }
969
1691
  return `# OpenAI API Key
970
1692
  OPENAI_API_KEY=${apiKey}
971
1693
 
@@ -1005,28 +1727,95 @@ build/
1005
1727
  htmlcov/
1006
1728
  `;
1007
1729
  };
1008
- var createPythonApp = async (client, targetPath = ".", apiKey = "", deploymentMode = "cloud") => {
1730
+ var createPythonApp = async (client, targetPath = ".", apiKey = "", deploymentMode = "cloud", adapter = "pydantic-ai", projectInfo = null, resolutions = []) => {
1009
1731
  try {
1010
- const model = "gpt-4o";
1011
- console.log("Creating AgentMark Python app with Pydantic AI...");
1732
+ const model = adapter === "claude-agent-sdk" ? "claude-sonnet-4-20250514" : "gpt-4o";
1733
+ const adapterDisplayName = adapter === "claude-agent-sdk" ? "Claude Agent SDK" : "Pydantic AI";
1734
+ const isExistingProject = projectInfo?.isExistingProject ?? false;
1735
+ if (isExistingProject) {
1736
+ console.log(`Adding AgentMark to existing Python project with ${adapterDisplayName}...`);
1737
+ } else {
1738
+ console.log(`Creating AgentMark Python app with ${adapterDisplayName}...`);
1739
+ }
1012
1740
  const folderName = targetPath;
1013
- fs4.ensureDirSync(`${targetPath}/agentmark`);
1741
+ fs5.ensureDirSync(`${targetPath}/agentmark`);
1014
1742
  setupMCPServer2(client, targetPath);
1015
- createExamplePrompts(model, targetPath, "pydantic-ai");
1743
+ createExamplePrompts(model, targetPath, adapter);
1016
1744
  console.log(`Example prompts and datasets created in ${folderName}/agentmark/`);
1017
- const projectName = path2.basename(targetPath).replace(/[^a-zA-Z0-9_-]/g, "-");
1018
- fs4.writeFileSync(`${targetPath}/pyproject.toml`, getPyprojectContent(projectName));
1019
- fs4.writeFileSync(`${targetPath}/agentmark_client.py`, getAgentmarkClientContent(deploymentMode));
1020
- fs4.writeFileSync(`${targetPath}/main.py`, getMainPyContent());
1021
- fs4.writeFileSync(`${targetPath}/.env`, getEnvContent(apiKey));
1022
- fs4.writeFileSync(`${targetPath}/.gitignore`, getGitignoreContent());
1023
- const agentmarkInternalDir = path2.join(targetPath, ".agentmark");
1024
- fs4.ensureDirSync(agentmarkInternalDir);
1025
- fs4.writeFileSync(path2.join(agentmarkInternalDir, "dev_server.py"), getDevServerContent());
1026
- console.log("Setting up Python environment...");
1027
- console.log("Note: You'll need to set up a virtual environment and install dependencies.");
1028
- console.log("");
1029
- console.log("\nAgentMark Python initialization completed successfully!");
1745
+ if (!isExistingProject) {
1746
+ const projectName = path3.basename(targetPath).replace(/[^a-zA-Z0-9_-]/g, "-");
1747
+ fs5.writeFileSync(`${targetPath}/pyproject.toml`, getPyprojectContent(projectName, adapter));
1748
+ } else {
1749
+ console.log("\u23ED\uFE0F Skipped pyproject.toml (existing project)");
1750
+ }
1751
+ fs5.writeFileSync(`${targetPath}/agentmark_client.py`, getAgentmarkClientContent(deploymentMode, adapter));
1752
+ if (!isExistingProject) {
1753
+ fs5.writeFileSync(`${targetPath}/main.py`, getMainPyContent(adapter));
1754
+ } else {
1755
+ console.log("\u23ED\uFE0F Skipped main.py (existing project)");
1756
+ }
1757
+ if (shouldMergeFile(".env", projectInfo, resolutions)) {
1758
+ const envVars = {};
1759
+ const apiKeyEnvVar = adapter === "claude-agent-sdk" ? "ANTHROPIC_API_KEY" : "OPENAI_API_KEY";
1760
+ if (apiKey) {
1761
+ envVars[apiKeyEnvVar] = apiKey;
1762
+ } else {
1763
+ envVars[apiKeyEnvVar] = adapter === "claude-agent-sdk" ? "your-anthropic-api-key" : "your-openai-api-key";
1764
+ }
1765
+ const result = appendEnv(targetPath, envVars);
1766
+ if (result.added.length > 0) {
1767
+ console.log(`\u2705 Added to .env: ${result.added.join(", ")}`);
1768
+ }
1769
+ if (result.skipped.length > 0) {
1770
+ console.log(`\u23ED\uFE0F Skipped existing .env vars: ${result.skipped.join(", ")}`);
1771
+ }
1772
+ } else {
1773
+ fs5.writeFileSync(`${targetPath}/.env`, getEnvContent(apiKey, adapter));
1774
+ }
1775
+ const gitignoreEntries = [
1776
+ "__pycache__/",
1777
+ "*.py[cod]",
1778
+ "*$py.class",
1779
+ ".venv/",
1780
+ "venv/",
1781
+ ".env",
1782
+ "*.agentmark-outputs/",
1783
+ ".agentmark/",
1784
+ ".idea/",
1785
+ ".vscode/",
1786
+ "*.swp",
1787
+ "dist/",
1788
+ "build/",
1789
+ "*.egg-info/",
1790
+ ".pytest_cache/",
1791
+ ".coverage",
1792
+ "htmlcov/"
1793
+ ];
1794
+ if (shouldMergeFile(".gitignore", projectInfo, resolutions)) {
1795
+ const result = appendGitignore(targetPath, gitignoreEntries);
1796
+ if (result.added.length > 0) {
1797
+ console.log(`\u2705 Added to .gitignore: ${result.added.join(", ")}`);
1798
+ }
1799
+ if (result.skipped.length > 0) {
1800
+ console.log(`\u23ED\uFE0F Already in .gitignore: ${result.skipped.join(", ")}`);
1801
+ }
1802
+ } else {
1803
+ fs5.writeFileSync(`${targetPath}/.gitignore`, getGitignoreContent());
1804
+ }
1805
+ const agentmarkInternalDir = path3.join(targetPath, ".agentmark");
1806
+ fs5.ensureDirSync(agentmarkInternalDir);
1807
+ fs5.writeFileSync(path3.join(agentmarkInternalDir, "dev_server.py"), getDevServerContent(adapter));
1808
+ const pythonVenv = projectInfo?.pythonVenv;
1809
+ if (pythonVenv) {
1810
+ console.log(`
1811
+ \u{1F4E6} Detected existing Python venv: ${pythonVenv.name}`);
1812
+ console.log(" Remember to activate it before running AgentMark commands.");
1813
+ } else if (!isExistingProject) {
1814
+ console.log("Setting up Python environment...");
1815
+ console.log("Note: You'll need to set up a virtual environment and install dependencies.");
1816
+ console.log("");
1817
+ }
1818
+ console.log("\n\u2705 AgentMark Python initialization completed successfully!");
1030
1819
  console.log(
1031
1820
  `
1032
1821
  \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2557
@@ -1042,12 +1831,18 @@ var createPythonApp = async (client, targetPath = ".", apiKey = "", deploymentMo
1042
1831
  console.log("Next Steps");
1043
1832
  console.log("\u2550".repeat(70));
1044
1833
  console.log("\n Get Started:");
1045
- if (folderName !== "." && folderName !== "./") {
1834
+ if (folderName !== "." && folderName !== "./" && !isExistingProject) {
1046
1835
  console.log(` $ cd ${folderName}`);
1047
1836
  }
1048
- console.log(" $ python -m venv .venv");
1049
- console.log(" $ source .venv/bin/activate # On Windows: .venv\\Scripts\\activate");
1050
- console.log(' $ pip install -e ".[dev]"');
1837
+ if (pythonVenv) {
1838
+ const activateCmd = process.platform === "win32" ? `${pythonVenv.name}\\Scripts\\activate` : `source ${pythonVenv.name}/bin/activate`;
1839
+ console.log(` $ ${activateCmd}`);
1840
+ console.log(' $ pip install agentmark-pydantic-ai agentmark-prompt-core python-dotenv "pydantic-ai[openai]"');
1841
+ } else {
1842
+ console.log(" $ python -m venv .venv");
1843
+ console.log(" $ source .venv/bin/activate # On Windows: .venv\\Scripts\\activate");
1844
+ console.log(' $ pip install -e ".[dev]"');
1845
+ }
1051
1846
  console.log(" $ npm run dev\n");
1052
1847
  console.log("\u2500".repeat(70));
1053
1848
  console.log("Resources");
@@ -1060,6 +1855,116 @@ var createPythonApp = async (client, targetPath = ".", apiKey = "", deploymentMo
1060
1855
  }
1061
1856
  };
1062
1857
 
1858
+ // src/utils/project-detection.ts
1859
+ import fs7 from "fs-extra";
1860
+ import path5 from "path";
1861
+
1862
+ // src/utils/package-manager.ts
1863
+ import fs6 from "fs-extra";
1864
+ import path4 from "path";
1865
+ function detectPackageManager(targetPath) {
1866
+ const lockFiles = ["yarn.lock", "pnpm-lock.yaml", "bun.lockb", "package-lock.json"];
1867
+ for (const lockFile of lockFiles) {
1868
+ if (fs6.existsSync(path4.join(targetPath, lockFile))) {
1869
+ const config = PACKAGE_MANAGERS[lockFile];
1870
+ if (config) {
1871
+ return config;
1872
+ }
1873
+ }
1874
+ }
1875
+ return DEFAULT_PACKAGE_MANAGER;
1876
+ }
1877
+
1878
+ // src/utils/project-detection.ts
1879
+ var IS_WINDOWS = process.platform === "win32";
1880
+ function detectTypeScriptProject(targetPath) {
1881
+ const indicators = ["package.json", "tsconfig.json", "node_modules"];
1882
+ return indicators.some((file) => fs7.existsSync(path5.join(targetPath, file)));
1883
+ }
1884
+ function detectPythonProject(targetPath) {
1885
+ const indicators = ["pyproject.toml", "requirements.txt", "setup.py", ".venv", "venv"];
1886
+ return indicators.some((file) => fs7.existsSync(path5.join(targetPath, file)));
1887
+ }
1888
+ function detectPythonVenv(targetPath) {
1889
+ const venvNames = [".venv", "venv"];
1890
+ for (const name of venvNames) {
1891
+ const venvPath = path5.join(targetPath, name);
1892
+ if (fs7.existsSync(venvPath) && fs7.statSync(venvPath).isDirectory()) {
1893
+ const binDir = IS_WINDOWS ? "Scripts" : "bin";
1894
+ const binPath = path5.join(venvPath, binDir);
1895
+ if (fs7.existsSync(binPath)) {
1896
+ const pipExe = IS_WINDOWS ? "pip.exe" : "pip";
1897
+ return {
1898
+ path: venvPath,
1899
+ name,
1900
+ activateCmd: IS_WINDOWS ? `${name}\\Scripts\\activate` : `source ${name}/bin/activate`,
1901
+ pipPath: path5.join(binPath, pipExe)
1902
+ };
1903
+ }
1904
+ }
1905
+ }
1906
+ const envVenv = process.env.VIRTUAL_ENV;
1907
+ if (envVenv && fs7.existsSync(envVenv)) {
1908
+ const resolvedTarget = path5.resolve(targetPath);
1909
+ const resolvedVenv = path5.resolve(envVenv);
1910
+ const isInsideTarget = resolvedVenv.startsWith(resolvedTarget + path5.sep) || resolvedVenv === resolvedTarget;
1911
+ if (!isInsideTarget) {
1912
+ console.warn(
1913
+ `\u26A0\uFE0F Note: VIRTUAL_ENV (${envVenv}) points outside the target directory. It will not be used for this initialization.`
1914
+ );
1915
+ return null;
1916
+ }
1917
+ const binDir = IS_WINDOWS ? "Scripts" : "bin";
1918
+ const pipExe = IS_WINDOWS ? "pip.exe" : "pip";
1919
+ const name = path5.basename(envVenv);
1920
+ return {
1921
+ path: envVenv,
1922
+ name,
1923
+ activateCmd: IS_WINDOWS ? `${name}\\Scripts\\activate` : `source ${name}/bin/activate`,
1924
+ pipPath: path5.join(envVenv, binDir, pipExe)
1925
+ };
1926
+ }
1927
+ return null;
1928
+ }
1929
+ function detectConflictingFiles(targetPath) {
1930
+ const existingConflicts = [];
1931
+ for (const conflictFile of CONFLICT_FILES) {
1932
+ const fullPath = path5.join(targetPath, conflictFile.path);
1933
+ if (fs7.existsSync(fullPath)) {
1934
+ existingConflicts.push(conflictFile);
1935
+ }
1936
+ }
1937
+ return existingConflicts;
1938
+ }
1939
+ function detectProjectInfo(targetPath) {
1940
+ const isTypeScript = detectTypeScriptProject(targetPath);
1941
+ const isPython = detectPythonProject(targetPath);
1942
+ const isExistingProject = isTypeScript || isPython;
1943
+ let type = "unknown";
1944
+ if (isTypeScript && !isPython) {
1945
+ type = "typescript";
1946
+ } else if (isPython && !isTypeScript) {
1947
+ type = "python";
1948
+ } else if (isTypeScript && isPython) {
1949
+ type = "typescript";
1950
+ }
1951
+ const packageManager = detectPackageManager(targetPath);
1952
+ const conflictingFiles = detectConflictingFiles(targetPath);
1953
+ const hasAgentmarkDir = fs7.existsSync(path5.join(targetPath, "agentmark"));
1954
+ const pythonVenv = detectPythonVenv(targetPath);
1955
+ return {
1956
+ isExistingProject,
1957
+ type,
1958
+ packageManager,
1959
+ conflictingFiles,
1960
+ hasAgentmarkDir,
1961
+ pythonVenv
1962
+ };
1963
+ }
1964
+ function isCurrentDirectory(folderName) {
1965
+ return folderName === "." || folderName === "./" || folderName === ".\\";
1966
+ }
1967
+
1063
1968
  // src/index.ts
1064
1969
  var parseArgs = () => {
1065
1970
  const args = process.argv.slice(2);
@@ -1087,17 +1992,25 @@ var main = async () => {
1087
1992
  agentmarkPath: "."
1088
1993
  };
1089
1994
  console.log("Initializing project.");
1090
- const { folderName } = await prompts({
1995
+ const { folderName } = await prompts2({
1091
1996
  name: "folderName",
1092
1997
  type: "text",
1093
1998
  message: "Where would you like to create your AgentMark app?",
1094
1999
  initial: "my-agentmark-app"
1095
2000
  });
1096
- const targetPath = `./${folderName}`;
1097
- fs5.ensureDirSync(targetPath);
2001
+ const isCurrentDir = isCurrentDirectory(folderName);
2002
+ const targetPath = isCurrentDir ? process.cwd() : path6.resolve(folderName);
2003
+ if (!isCurrentDir) {
2004
+ fs8.ensureDirSync(targetPath);
2005
+ }
2006
+ const projectInfo = detectProjectInfo(targetPath);
2007
+ if (projectInfo.isExistingProject) {
2008
+ displayProjectDetectionSummary(projectInfo);
2009
+ }
2010
+ const resolutions = await promptForResolutions(projectInfo.conflictingFiles);
1098
2011
  let language = cliArgs.language;
1099
2012
  if (!language) {
1100
- const response = await prompts({
2013
+ const response = await prompts2({
1101
2014
  name: "language",
1102
2015
  type: "select",
1103
2016
  message: "Which language would you like to use?",
@@ -1108,34 +2021,44 @@ var main = async () => {
1108
2021
  });
1109
2022
  language = response.language;
1110
2023
  }
1111
- config.builtInModels = ["gpt-4o"];
1112
- let apiKey = "";
1113
- const { providedApiKey } = await prompts({
1114
- name: "providedApiKey",
1115
- type: "password",
1116
- message: `Enter your OpenAI API key (or press Enter to skip):`,
1117
- initial: ""
1118
- });
1119
- apiKey = providedApiKey || "";
1120
2024
  let adapter;
1121
2025
  if (language === "python") {
1122
- adapter = "pydantic-ai";
1123
- console.log("Using Pydantic AI adapter for Python.");
2026
+ const response = await prompts2({
2027
+ name: "adapter",
2028
+ type: "select",
2029
+ message: "Which adapter would you like to use?",
2030
+ choices: [
2031
+ { title: "Pydantic AI", value: "pydantic-ai" },
2032
+ { title: "Claude Agent SDK", value: "claude-agent-sdk" }
2033
+ ]
2034
+ });
2035
+ adapter = response.adapter;
1124
2036
  } else {
1125
- const response = await prompts({
2037
+ const response = await prompts2({
1126
2038
  name: "adapter",
1127
2039
  type: "select",
1128
2040
  message: "Which adapter would you like to use?",
1129
2041
  choices: [
1130
2042
  { title: "AI SDK (Vercel)", value: "ai-sdk" },
2043
+ { title: "Claude Agent SDK", value: "claude-agent-sdk" },
1131
2044
  { title: "Mastra", value: "mastra" }
1132
2045
  ]
1133
2046
  });
1134
2047
  adapter = response.adapter;
1135
2048
  }
2049
+ config.builtInModels = adapter === "claude-agent-sdk" ? ["claude-sonnet-4-20250514"] : ["gpt-4o"];
2050
+ const apiKeyName = adapter === "claude-agent-sdk" ? "Anthropic" : "OpenAI";
2051
+ let apiKey = "";
2052
+ const { providedApiKey } = await prompts2({
2053
+ name: "providedApiKey",
2054
+ type: "password",
2055
+ message: `Enter your ${apiKeyName} API key (or press Enter to skip):`,
2056
+ initial: ""
2057
+ });
2058
+ apiKey = providedApiKey || "";
1136
2059
  let deploymentMode = cliArgs.deploymentMode;
1137
2060
  if (!deploymentMode) {
1138
- const response = await prompts({
2061
+ const response = await prompts2({
1139
2062
  name: "deploymentMode",
1140
2063
  type: "select",
1141
2064
  message: "Use AgentMark Cloud or manage yourself?",
@@ -1154,7 +2077,7 @@ var main = async () => {
1154
2077
  });
1155
2078
  deploymentMode = response.deploymentMode;
1156
2079
  }
1157
- const { client } = await prompts({
2080
+ const { client } = await prompts2({
1158
2081
  name: "client",
1159
2082
  type: "select",
1160
2083
  message: "Make your IDE an AgentMark expert",
@@ -1167,11 +2090,17 @@ var main = async () => {
1167
2090
  ]
1168
2091
  });
1169
2092
  if (language === "python") {
1170
- await createPythonApp(client, targetPath, apiKey, deploymentMode);
2093
+ await createPythonApp(client, targetPath, apiKey, deploymentMode, adapter, projectInfo, resolutions);
1171
2094
  } else {
1172
- await createExampleApp(client, targetPath, apiKey, adapter, deploymentMode);
2095
+ await createExampleApp(client, targetPath, apiKey, adapter, deploymentMode, projectInfo, resolutions);
2096
+ }
2097
+ const agentmarkJsonPath = path6.join(targetPath, "agentmark.json");
2098
+ const agentmarkJsonResolution = resolutions.find((r) => r.path === "agentmark.json");
2099
+ if (!fs8.existsSync(agentmarkJsonPath) || agentmarkJsonResolution?.action === "overwrite") {
2100
+ fs8.writeJsonSync(agentmarkJsonPath, config, { spaces: 2 });
2101
+ } else if (agentmarkJsonResolution?.action === "skip") {
2102
+ console.log("\u23ED\uFE0F Skipped agentmark.json (keeping existing file)");
1173
2103
  }
1174
- fs5.writeJsonSync(`${targetPath}/agentmark.json`, config, { spaces: 2 });
1175
2104
  };
1176
2105
  main().catch((error) => {
1177
2106
  console.error("Error:", error);