create-agentmark 0.6.0 → 0.8.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,324 @@ 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
+ fs2.writeJsonSync(packageJsonPath, pkgJson, { spaces: 2 });
195
527
  }
196
- pkgJson.scripts = scripts;
197
- pkgJson.overrides = {
198
- ...pkgJson.overrides,
199
- "axios": "^1.7.9"
200
- };
201
- fs.writeJsonSync(packageJsonPath, pkgJson, { spaces: 2 });
202
528
  };
203
- var installDependencies = (modelProvider, targetPath = ".", adapter = "ai-sdk", deploymentMode = "cloud") => {
529
+ var installDependencies = (modelProvider, targetPath = ".", adapter = "ai-sdk", deploymentMode = "cloud", packageManager = null) => {
204
530
  console.log("Installing required packages...");
205
531
  console.log("This might take a moment...");
206
532
  const adapterConfig = getAdapterConfig(adapter, modelProvider);
533
+ const pm = packageManager || DEFAULT_PACKAGE_MANAGER;
534
+ const npmSuffix = pm.name === "npm" ? " --legacy-peer-deps" : "";
207
535
  try {
208
- const devDepsCmd = "npm install --save-dev typescript ts-node @types/node @agentmark-ai/cli --legacy-peer-deps";
536
+ const devDeps = ["typescript", "ts-node", "@types/node", "@agentmark-ai/cli"];
537
+ const devDepsCmd = `${pm.addDevCmd} ${devDeps.join(" ")}${npmSuffix}`;
538
+ console.log(`Using ${pm.name} to install dependencies...`);
209
539
  execSync(devDepsCmd, {
210
540
  stdio: "inherit",
211
541
  cwd: targetPath
212
542
  });
213
543
  const loaderPackages = deploymentMode === "static" ? ["@agentmark-ai/loader-api", "@agentmark-ai/loader-file"] : ["@agentmark-ai/loader-api"];
214
- const installArgs = [
215
- "install",
544
+ const deps = [
216
545
  "dotenv",
217
546
  "@agentmark-ai/prompt-core",
218
547
  "@agentmark-ai/sdk",
219
548
  adapterConfig.package,
220
549
  ...loaderPackages,
221
- ...adapterConfig.dependencies,
222
- "--legacy-peer-deps"
550
+ ...adapterConfig.dependencies
223
551
  ];
224
- execFileSync("npm", installArgs, { stdio: "inherit", cwd: targetPath });
552
+ const depsCmd = `${pm.addCmd} ${deps.join(" ")}${npmSuffix}`;
553
+ execSync(depsCmd, { stdio: "inherit", cwd: targetPath });
225
554
  console.log("Packages installed successfully!");
226
555
  } catch (error) {
227
556
  console.error("Error installing packages:", error);
@@ -395,28 +724,32 @@ var getStoryDataset = () => {
395
724
  };
396
725
 
397
726
  // src/utils/examples/templates/example-prompts.ts
398
- import fs2 from "fs-extra";
727
+ import fs3 from "fs-extra";
399
728
  var createExamplePrompts = (model, targetPath = ".", adapter = "ai-sdk") => {
400
- fs2.ensureDirSync(`${targetPath}/agentmark`);
401
- if (adapter !== "mastra") {
729
+ fs3.ensureDirSync(`${targetPath}/agentmark`);
730
+ const noImageSupport = ["mastra", "claude-agent-sdk"];
731
+ const noSpeechSupport = ["mastra", "claude-agent-sdk"];
732
+ const skipImagePrompts = noImageSupport.includes(adapter);
733
+ const skipSpeechPrompts = noSpeechSupport.includes(adapter);
734
+ if (!skipImagePrompts) {
402
735
  const animalDrawingPrompt = getAnimalDrawingPrompt();
403
- fs2.writeFileSync(`${targetPath}/agentmark/animal-drawing.prompt.mdx`, animalDrawingPrompt);
736
+ fs3.writeFileSync(`${targetPath}/agentmark/animal-drawing.prompt.mdx`, animalDrawingPrompt);
404
737
  const animalDataset = getAnimalDataset();
405
- fs2.writeFileSync(`${targetPath}/agentmark/animal.jsonl`, animalDataset);
738
+ fs3.writeFileSync(`${targetPath}/agentmark/animal.jsonl`, animalDataset);
406
739
  }
407
740
  const customerSupportPrompt = getCustomerSupportPrompt(model);
408
- fs2.writeFileSync(`${targetPath}/agentmark/customer-support-agent.prompt.mdx`, customerSupportPrompt);
741
+ fs3.writeFileSync(`${targetPath}/agentmark/customer-support-agent.prompt.mdx`, customerSupportPrompt);
409
742
  const customerQueryDataset = getCustomerQueryDataset();
410
- fs2.writeFileSync(`${targetPath}/agentmark/customer-query.jsonl`, customerQueryDataset);
743
+ fs3.writeFileSync(`${targetPath}/agentmark/customer-query.jsonl`, customerQueryDataset);
411
744
  const partyPlannerPrompt = getPartyPlannerPrompt(model);
412
- fs2.writeFileSync(`${targetPath}/agentmark/party-planner.prompt.mdx`, partyPlannerPrompt);
745
+ fs3.writeFileSync(`${targetPath}/agentmark/party-planner.prompt.mdx`, partyPlannerPrompt);
413
746
  const partyDataset = getPartyDataset();
414
- fs2.writeFileSync(`${targetPath}/agentmark/party.jsonl`, partyDataset);
415
- if (adapter !== "mastra") {
747
+ fs3.writeFileSync(`${targetPath}/agentmark/party.jsonl`, partyDataset);
748
+ if (!skipSpeechPrompts) {
416
749
  const storyTellerPrompt = getStoryTellerPrompt();
417
- fs2.writeFileSync(`${targetPath}/agentmark/story-teller.prompt.mdx`, storyTellerPrompt);
750
+ fs3.writeFileSync(`${targetPath}/agentmark/story-teller.prompt.mdx`, storyTellerPrompt);
418
751
  const storyDataset = getStoryDataset();
419
- fs2.writeFileSync(`${targetPath}/agentmark/story.jsonl`, storyDataset);
752
+ fs3.writeFileSync(`${targetPath}/agentmark/story.jsonl`, storyDataset);
420
753
  }
421
754
  };
422
755
 
@@ -425,8 +758,9 @@ var getClientConfigContent = (options) => {
425
758
  const { provider, languageModels, adapter, deploymentMode = "cloud" } = options;
426
759
  const adapterConfig = getAdapterConfig(adapter, provider);
427
760
  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))
761
+ const isClaudeAgentSdk = adapter === "claude-agent-sdk";
762
+ const providerImport = isClaudeAgentSdk ? "" : `import { ${provider} } from '@ai-sdk/${provider}';`;
763
+ const extraModelRegs = provider === "openai" && !isClaudeAgentSdk ? `.registerModels(["dall-e-3"], (name: string) => ${provider}.image(name))
430
764
  .registerModels(["tts-1-hd"], (name: string) => ${provider}.speech(name))` : "";
431
765
  const loaderImport = deploymentMode === "cloud" ? `import { ApiLoader } from "@agentmark-ai/loader-api";` : `import { ApiLoader } from "@agentmark-ai/loader-api";
432
766
  import { FileLoader } from "@agentmark-ai/loader-file";`;
@@ -441,6 +775,51 @@ import { FileLoader } from "@agentmark-ai/loader-file";`;
441
775
  });` : ` const loader = process.env.NODE_ENV === 'development'
442
776
  ? ApiLoader.local({ baseUrl: process.env.AGENTMARK_BASE_URL || 'http://localhost:9418' })
443
777
  : new FileLoader('./dist/agentmark');`;
778
+ const modelRegistrySetup = isClaudeAgentSdk ? `function createModelRegistry() {
779
+ // Claude Agent SDK accepts model names directly.
780
+ // Use createDefault() for simple pass-through of model names.
781
+ const modelRegistry = ${modelRegistry}.createDefault();
782
+
783
+ // To configure specific models (e.g., extended thinking), use:
784
+ // const modelRegistry = new ${modelRegistry}()
785
+ // .registerModels(/claude-.*-thinking/, (name) => ({
786
+ // model: name,
787
+ // maxThinkingTokens: 10000, // Enable extended thinking
788
+ // }))
789
+ // .registerModels("claude-sonnet-4-20250514", (name) => ({ model: name }));
790
+
791
+ return modelRegistry;
792
+ }` : `function createModelRegistry() {
793
+ const modelRegistry = new ${modelRegistry}()
794
+ .registerModels(${JSON.stringify(languageModels)}, (name: string) => ${provider}(name))
795
+ ${extraModelRegs};
796
+ return modelRegistry;
797
+ }`;
798
+ const adapterOptionsImport = isClaudeAgentSdk ? `
799
+ // Claude Agent SDK adapter options
800
+ // See: https://github.com/anthropics/claude-agent-sdk
801
+ const adapterOptions = {
802
+ // Permission mode controls tool access:
803
+ // - 'default': Requires user approval for each tool use
804
+ // - 'acceptEdits': Auto-approve file edits only
805
+ // - 'bypassPermissions': Auto-approve all tools (use for automated pipelines)
806
+ // - 'plan': Planning mode only, no tool execution
807
+ permissionMode: 'bypassPermissions' as const,
808
+
809
+ // Maximum conversation turns before stopping
810
+ maxTurns: 20,
811
+
812
+ // Optional: Set working directory for file operations
813
+ // cwd: process.cwd(),
814
+
815
+ // Optional: Budget limit in USD
816
+ // maxBudgetUsd: 10.00,
817
+
818
+ // Optional: Restrict which tools the agent can use
819
+ // allowedTools: ['Read', 'Write', 'Glob'],
820
+ // disallowedTools: ['Bash'],
821
+ };` : "";
822
+ const createClientCall = isClaudeAgentSdk ? `return createAgentMarkClient<AgentMarkTypes, typeof toolRegistry>({ loader, modelRegistry, toolRegistry, evalRegistry, adapterOptions });` : `return createAgentMarkClient<AgentMarkTypes, typeof toolRegistry>({ loader, modelRegistry, toolRegistry, evalRegistry });`;
444
823
  return `// agentmark.client.ts
445
824
  import path from 'node:path';
446
825
  import dotenv from 'dotenv';
@@ -449,13 +828,9 @@ import { createAgentMarkClient, ${modelRegistry}, ${toolRegistry}, EvalRegistry
449
828
  ${loaderImport}
450
829
  import AgentMarkTypes, { Tools } from './agentmark.types';
451
830
  ${providerImport}
831
+ ${adapterOptionsImport}
452
832
 
453
- function createModelRegistry() {
454
- const modelRegistry = new ${modelRegistry}()
455
- .registerModels(${JSON.stringify(languageModels)}, (name: string) => ${provider}(name))
456
- ${extraModelRegs};
457
- return modelRegistry;
458
- }
833
+ ${modelRegistrySetup}
459
834
 
460
835
  function createToolRegistry() {
461
836
  const toolRegistry = new ${toolRegistry}<Tools>()
@@ -502,7 +877,7 @@ ${loaderSetup}
502
877
  const modelRegistry = createModelRegistry();
503
878
  const toolRegistry = createToolRegistry();
504
879
  const evalRegistry = createEvalRegistry();
505
- return createAgentMarkClient<AgentMarkTypes, typeof toolRegistry>({ loader, modelRegistry, toolRegistry, evalRegistry });
880
+ ${createClientCall}
506
881
  }
507
882
 
508
883
  export const client = createClient();
@@ -511,6 +886,99 @@ export const client = createClient();
511
886
 
512
887
  // src/utils/examples/create-example-app.ts
513
888
  import { fetchPromptsFrontmatter, generateTypeDefinitions } from "@agentmark-ai/shared-utils";
889
+
890
+ // src/utils/conflict-resolution.ts
891
+ import prompts from "prompts";
892
+ function getPromptableConflicts(conflictingFiles) {
893
+ return conflictingFiles.filter((file) => file.strategy === "prompt");
894
+ }
895
+ async function promptForSingleConflict(conflict) {
896
+ const typeLabel = conflict.type === "directory" ? "directory" : "file";
897
+ const { action } = await prompts({
898
+ type: "select",
899
+ name: "action",
900
+ message: `${conflict.path} already exists. What would you like to do?`,
901
+ choices: [
902
+ {
903
+ title: `Skip (keep existing ${typeLabel})`,
904
+ value: "skip",
905
+ description: `Don't modify the existing ${typeLabel}`
906
+ },
907
+ {
908
+ title: "Overwrite",
909
+ value: "overwrite",
910
+ description: `Replace with new AgentMark ${typeLabel}`
911
+ }
912
+ ],
913
+ initial: 0
914
+ // Default to skip for safety
915
+ });
916
+ return {
917
+ path: conflict.path,
918
+ action: action || "skip"
919
+ };
920
+ }
921
+ async function promptForResolutions(conflictingFiles) {
922
+ const promptableConflicts = getPromptableConflicts(conflictingFiles);
923
+ if (promptableConflicts.length === 0) {
924
+ return [];
925
+ }
926
+ console.log("\n\u26A0\uFE0F Found existing files that may conflict with AgentMark initialization:\n");
927
+ const resolutions = [];
928
+ for (const conflict of promptableConflicts) {
929
+ const resolution = await promptForSingleConflict(conflict);
930
+ resolutions.push(resolution);
931
+ }
932
+ console.log("");
933
+ return resolutions;
934
+ }
935
+ function getResolutionAction(filePath, resolutions, conflictingFiles) {
936
+ const userResolution = resolutions.find((r) => r.path === filePath);
937
+ if (userResolution) {
938
+ return userResolution.action;
939
+ }
940
+ const conflictFile = conflictingFiles.find((f) => f.path === filePath);
941
+ if (conflictFile) {
942
+ switch (conflictFile.strategy) {
943
+ case "skip":
944
+ return "skip";
945
+ case "merge":
946
+ return "merge";
947
+ case "append":
948
+ return "merge";
949
+ // Append is a form of merge
950
+ case "prompt":
951
+ return "skip";
952
+ }
953
+ }
954
+ return "overwrite";
955
+ }
956
+ function shouldMergeFile(filePath, projectInfo, resolutions) {
957
+ if (!projectInfo || !projectInfo.isExistingProject) {
958
+ return false;
959
+ }
960
+ const action = getResolutionAction(filePath, resolutions, projectInfo.conflictingFiles);
961
+ return action === "merge";
962
+ }
963
+ function displayProjectDetectionSummary(projectInfo) {
964
+ if (!projectInfo.isExistingProject) {
965
+ return;
966
+ }
967
+ console.log("\n\u{1F4C1} Detected existing project:");
968
+ console.log(` Type: ${projectInfo.type}`);
969
+ if (projectInfo.type === "typescript") {
970
+ console.log(` Package Manager: ${projectInfo.packageManager.name}`);
971
+ }
972
+ if (projectInfo.pythonVenv) {
973
+ console.log(` Python Venv: ${projectInfo.pythonVenv.name}`);
974
+ }
975
+ if (projectInfo.hasAgentmarkDir) {
976
+ console.log(" \u26A0\uFE0F AgentMark directory already exists");
977
+ }
978
+ console.log("");
979
+ }
980
+
981
+ // src/utils/examples/create-example-app.ts
514
982
  var setupMCPServer = (client, targetPath) => {
515
983
  if (client === "skip") {
516
984
  console.log("Skipping MCP server setup.");
@@ -520,16 +988,23 @@ var setupMCPServer = (client, targetPath) => {
520
988
  if (client === "vscode") {
521
989
  try {
522
990
  console.log(`Setting up MCP server for VS Code in ${folderName}...`);
523
- const vscodeDir = path.join(targetPath, ".vscode");
524
- fs3.ensureDirSync(vscodeDir);
991
+ const vscodeDir = path2.join(targetPath, ".vscode");
992
+ fs4.ensureDirSync(vscodeDir);
525
993
  const mcpConfig = {
526
994
  servers: {
527
995
  "agentmark-docs": {
528
996
  url: "https://docs.agentmark.co/mcp"
997
+ },
998
+ "agentmark-traces": {
999
+ command: "npx",
1000
+ args: ["@agentmark-ai/mcp-server"],
1001
+ env: {
1002
+ AGENTMARK_URL: "http://localhost:9418"
1003
+ }
529
1004
  }
530
1005
  }
531
1006
  };
532
- fs3.writeJsonSync(path.join(vscodeDir, "mcp.json"), mcpConfig, { spaces: 2 });
1007
+ fs4.writeJsonSync(path2.join(vscodeDir, "mcp.json"), mcpConfig, { spaces: 2 });
533
1008
  console.log(`\u2705 MCP server configured for VS Code in ${folderName}/.vscode/mcp.json`);
534
1009
  } catch (error) {
535
1010
  console.warn(`Warning: Could not set up MCP server for VS Code:`, error);
@@ -540,16 +1015,23 @@ var setupMCPServer = (client, targetPath) => {
540
1015
  if (client === "zed") {
541
1016
  try {
542
1017
  console.log(`Setting up MCP server for Zed in ${folderName}...`);
543
- const zedDir = path.join(targetPath, ".zed");
544
- fs3.ensureDirSync(zedDir);
1018
+ const zedDir = path2.join(targetPath, ".zed");
1019
+ fs4.ensureDirSync(zedDir);
545
1020
  const zedConfig = {
546
1021
  context_servers: {
547
1022
  "agentmark-docs": {
548
1023
  url: "https://docs.agentmark.co/mcp"
1024
+ },
1025
+ "agentmark-traces": {
1026
+ command: "npx",
1027
+ args: ["@agentmark-ai/mcp-server"],
1028
+ env: {
1029
+ AGENTMARK_URL: "http://localhost:9418"
1030
+ }
549
1031
  }
550
1032
  }
551
1033
  };
552
- fs3.writeJsonSync(path.join(zedDir, "settings.json"), zedConfig, { spaces: 2 });
1034
+ fs4.writeJsonSync(path2.join(zedDir, "settings.json"), zedConfig, { spaces: 2 });
553
1035
  console.log(`\u2705 MCP server configured for Zed in ${folderName}/.zed/settings.json`);
554
1036
  } catch (error) {
555
1037
  console.warn(`Warning: Could not set up MCP server for Zed:`, error);
@@ -560,16 +1042,23 @@ var setupMCPServer = (client, targetPath) => {
560
1042
  if (client === "cursor") {
561
1043
  try {
562
1044
  console.log(`Setting up MCP server for Cursor in ${folderName}...`);
563
- const cursorDir = path.join(targetPath, ".cursor");
564
- fs3.ensureDirSync(cursorDir);
1045
+ const cursorDir = path2.join(targetPath, ".cursor");
1046
+ fs4.ensureDirSync(cursorDir);
565
1047
  const cursorConfig = {
566
1048
  mcpServers: {
567
1049
  "agentmark-docs": {
568
1050
  url: "https://docs.agentmark.co/mcp"
1051
+ },
1052
+ "agentmark-traces": {
1053
+ command: "npx",
1054
+ args: ["@agentmark-ai/mcp-server"],
1055
+ env: {
1056
+ AGENTMARK_URL: "http://localhost:9418"
1057
+ }
569
1058
  }
570
1059
  }
571
1060
  };
572
- fs3.writeJsonSync(path.join(cursorDir, "mcp.json"), cursorConfig, { spaces: 2 });
1061
+ fs4.writeJsonSync(path2.join(cursorDir, "mcp.json"), cursorConfig, { spaces: 2 });
573
1062
  console.log(`\u2705 MCP server configured for Cursor in ${folderName}/.cursor/mcp.json`);
574
1063
  } catch (error) {
575
1064
  console.warn(`Warning: Could not set up MCP server for Cursor:`, error);
@@ -585,10 +1074,17 @@ var setupMCPServer = (client, targetPath) => {
585
1074
  "agentmark-docs": {
586
1075
  type: "http",
587
1076
  url: "https://docs.agentmark.co/mcp"
1077
+ },
1078
+ "agentmark-traces": {
1079
+ command: "npx",
1080
+ args: ["@agentmark-ai/mcp-server"],
1081
+ env: {
1082
+ AGENTMARK_URL: "http://localhost:9418"
1083
+ }
588
1084
  }
589
1085
  }
590
1086
  };
591
- fs3.writeJsonSync(path.join(targetPath, ".mcp.json"), mcpConfig, { spaces: 2 });
1087
+ fs4.writeJsonSync(path2.join(targetPath, ".mcp.json"), mcpConfig, { spaces: 2 });
592
1088
  console.log(`\u2705 MCP server configured for Claude Code in ${folderName}/.mcp.json`);
593
1089
  } catch (error) {
594
1090
  console.warn(`Warning: Could not set up MCP server for Claude Code:`, error);
@@ -597,52 +1093,93 @@ var setupMCPServer = (client, targetPath) => {
597
1093
  return;
598
1094
  }
599
1095
  };
600
- var createExampleApp = async (client, targetPath = ".", apiKey = "", adapter = "ai-sdk", deploymentMode = "cloud") => {
1096
+ var createExampleApp = async (client, targetPath = ".", apiKey = "", adapter = "ai-sdk", deploymentMode = "cloud", projectInfo = null, resolutions = []) => {
601
1097
  try {
602
- const modelProvider = "openai";
603
- const model = "gpt-4o";
604
- console.log("Creating Agent Mark example app...");
1098
+ const modelProvider = adapter === "claude-agent-sdk" ? "anthropic" : "openai";
1099
+ const model = adapter === "claude-agent-sdk" ? "claude-sonnet-4-20250514" : "gpt-4o";
1100
+ const isExistingProject = projectInfo?.isExistingProject ?? false;
1101
+ if (isExistingProject) {
1102
+ console.log("Adding AgentMark to existing project...");
1103
+ } else {
1104
+ console.log("Creating AgentMark example app...");
1105
+ }
605
1106
  const folderName = targetPath;
606
- fs3.ensureDirSync(`${targetPath}/agentmark`);
1107
+ fs4.ensureDirSync(`${targetPath}/agentmark`);
607
1108
  setupMCPServer(client, targetPath);
608
1109
  createExamplePrompts(model, targetPath, adapter);
609
1110
  console.log(`\u2705 Example prompts and datasets created in ${folderName}/agentmark/`);
610
1111
  const langModels = Providers[modelProvider].languageModels.slice(0, 1);
611
- fs3.writeFileSync(
1112
+ fs4.writeFileSync(
612
1113
  `${targetPath}/agentmark.client.ts`,
613
1114
  getClientConfigContent({ provider: modelProvider, languageModels: langModels, adapter, deploymentMode })
614
1115
  );
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);
1116
+ if (shouldMergeFile(".env", projectInfo, resolutions)) {
1117
+ const envVars = {};
1118
+ const apiKeyEnvVar = adapter === "claude-agent-sdk" ? "ANTHROPIC_API_KEY" : "OPENAI_API_KEY";
1119
+ if (apiKey) {
1120
+ envVars[apiKeyEnvVar] = apiKey;
1121
+ } else {
1122
+ envVars[apiKeyEnvVar] = adapter === "claude-agent-sdk" ? "your-anthropic-api-key" : "your-openai-api-key";
1123
+ }
1124
+ const result = appendEnv(targetPath, envVars);
1125
+ if (result.added.length > 0) {
1126
+ console.log(`\u2705 Added to .env: ${result.added.join(", ")}`);
1127
+ }
1128
+ if (result.skipped.length > 0) {
1129
+ console.log(`\u23ED\uFE0F Skipped existing .env vars: ${result.skipped.join(", ")}`);
1130
+ }
1131
+ } else {
1132
+ fs4.writeFileSync(`${targetPath}/.env`, getEnvFileContent(modelProvider, apiKey, adapter));
1133
+ }
1134
+ const gitignoreEntries = ["node_modules/", ".env", "*.agentmark-outputs/", "dist/"];
1135
+ if (shouldMergeFile(".gitignore", projectInfo, resolutions)) {
1136
+ const result = appendGitignore(targetPath, gitignoreEntries);
1137
+ if (result.added.length > 0) {
1138
+ console.log(`\u2705 Added to .gitignore: ${result.added.join(", ")}`);
1139
+ }
1140
+ if (result.skipped.length > 0) {
1141
+ console.log(`\u23ED\uFE0F Already in .gitignore: ${result.skipped.join(", ")}`);
1142
+ }
1143
+ } else {
1144
+ const gitignore = gitignoreEntries.join("\n");
1145
+ fs4.writeFileSync(`${targetPath}/.gitignore`, gitignore);
1146
+ }
1147
+ if (!isExistingProject) {
1148
+ fs4.writeFileSync(
1149
+ `${targetPath}/index.ts`,
1150
+ getIndexFileContent(adapter)
1151
+ );
1152
+ } else {
1153
+ console.log("\u23ED\uFE0F Skipped index.ts (existing project)");
1154
+ }
1155
+ if (!isExistingProject) {
1156
+ fs4.writeJsonSync(`${targetPath}/tsconfig.json`, getTsConfigContent(), { spaces: 2 });
1157
+ } else {
1158
+ console.log("\u23ED\uFE0F Skipped tsconfig.json (existing project)");
1159
+ }
1160
+ const packageManager = projectInfo?.packageManager ?? null;
1161
+ setupPackageJson(targetPath, deploymentMode, projectInfo);
1162
+ installDependencies(modelProvider, targetPath, adapter, deploymentMode, packageManager);
625
1163
  console.log("Generating types from prompts...");
626
1164
  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);
1165
+ const agentmarkDir = path2.join(targetPath, "agentmark");
1166
+ const prompts3 = await fetchPromptsFrontmatter({ rootDir: agentmarkDir });
1167
+ const typeDefinitions = await generateTypeDefinitions(prompts3);
1168
+ fs4.writeFileSync(`${targetPath}/agentmark.types.ts`, typeDefinitions);
631
1169
  } catch (error) {
632
1170
  console.warn("Warning: Could not generate types automatically:", error);
633
1171
  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
1172
+ fs4.writeFileSync(`${targetPath}/agentmark.types.ts`, `// Auto-generated types from AgentMark
635
1173
  // Run 'npx agentmark generate-types --root-dir agentmark' to generate types
636
1174
  export default interface AgentmarkTypes {}
637
1175
  `);
638
1176
  }
639
1177
  console.log("Creating development server entry point...");
640
- const agentmarkInternalDir = path.join(targetPath, ".agentmark");
641
- fs3.ensureDirSync(agentmarkInternalDir);
642
1178
  const adapterConfig = getAdapterConfig(adapter, modelProvider);
643
1179
  const { webhookHandler } = adapterConfig.classes;
644
- const devEntryContent = `// Auto-generated webhook server entry point
645
- // To customize, create a dev-server.ts file in your project root
1180
+ const devEntryPath = path2.join(targetPath, "dev-entry.ts");
1181
+ const devEntryContent = `// Development webhook server entry point
1182
+ // This file is version controlled - customize as needed for your project
646
1183
 
647
1184
  import { createWebhookServer } from '@agentmark-ai/cli/runner-server';
648
1185
  import { ${webhookHandler} } from '${adapterConfig.package}/runner';
@@ -663,7 +1200,7 @@ async function main() {
663
1200
  process.env.AGENTMARK_BASE_URL = apiServerUrl;
664
1201
 
665
1202
  // Now import client - it will pick up the dev environment
666
- const { client } = await import('../agentmark.client.js');
1203
+ const { client } = await import('./agentmark.client.js');
667
1204
 
668
1205
  // Initialize OpenTelemetry tracing to export traces to the API server
669
1206
  const sdk = new AgentMarkSDK({
@@ -689,7 +1226,12 @@ main().catch((err) => {
689
1226
  process.exit(1);
690
1227
  });
691
1228
  `;
692
- fs3.writeFileSync(path.join(agentmarkInternalDir, "dev-entry.ts"), devEntryContent);
1229
+ if (fs4.existsSync(devEntryPath)) {
1230
+ console.log("\u23ED\uFE0F Skipped dev-entry.ts (already exists - preserving customizations)");
1231
+ } else {
1232
+ fs4.writeFileSync(devEntryPath, devEntryContent);
1233
+ console.log(`\u2705 Created dev-entry.ts at project root`);
1234
+ }
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);