create-agentmark 0.5.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 fs4 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
 
@@ -29,7 +41,7 @@ var Providers = {
29
41
  var createAdapterConfig = (provider) => {
30
42
  return {
31
43
  "ai-sdk": {
32
- package: "@agentmark/ai-sdk-v5-adapter",
44
+ package: "@agentmark-ai/ai-sdk-v5-adapter",
33
45
  dependencies: ["ai@^5", `@ai-sdk/${provider}@^2`],
34
46
  classes: {
35
47
  modelRegistry: "VercelAIModelRegistry",
@@ -38,7 +50,7 @@ var createAdapterConfig = (provider) => {
38
50
  }
39
51
  },
40
52
  mastra: {
41
- package: "@agentmark/mastra-v0-adapter",
53
+ package: "@agentmark-ai/mastra-v0-adapter",
42
54
  dependencies: [
43
55
  "@mastra/core@<0.20.0",
44
56
  "@mastra/mcp@<0.13.4",
@@ -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";
@@ -74,11 +149,10 @@ import { client } from "./agentmark.client";
74
149
  const telemetry = {
75
150
  isEnabled: true,
76
151
  metadata: {
77
- traceId: "trace-123",
78
- traceName: "customer-support",
79
- userId: "user-123",
80
- sessionId: "session-123",
81
- sessionName: "my-first-session",
152
+ trace_name: "customer-support",
153
+ user_id: "user-123",
154
+ session_id: "session-123",
155
+ session_name: "my-first-session",
82
156
  },
83
157
  };
84
158
 
@@ -122,11 +196,10 @@ import { client } from "./agentmark.client";
122
196
  const telemetry = {
123
197
  isEnabled: true,
124
198
  metadata: {
125
- traceId: "trace-123",
126
- traceName: "customer-support",
127
- userId: "user-123",
128
- sessionId: "session-123",
129
- sessionName: "my-first-session",
199
+ trace_name: "customer-support",
200
+ user_id: "user-123",
201
+ session_id: "session-123",
202
+ session_name: "my-first-session",
130
203
  },
131
204
  };
132
205
 
@@ -160,70 +233,328 @@ main();
160
233
  };
161
234
 
162
235
  // src/utils/examples/templates/env.ts
163
- var getEnvFileContent = (_modelProvider, apiKey = "") => {
236
+ var getEnvFileContent = (_modelProvider, apiKey = "", adapter = "ai-sdk") => {
164
237
  const apiKeyValue = apiKey || "your_api_key_here";
238
+ const apiKeyName = adapter === "claude-agent-sdk" ? "ANTHROPIC_API_KEY" : "OPENAI_API_KEY";
165
239
  return `# Cloud deployment: Set these environment variables
166
240
  # AGENTMARK_BASE_URL=https://api.agentmark.co
167
241
  # AGENTMARK_API_KEY=your_agentmark_api_key
168
242
  # AGENTMARK_APP_ID=your_agentmark_app_id
169
243
  # Learn more: https://docs.agentmark.co/platform/getting_started/quickstart
170
244
 
171
- OPENAI_API_KEY=${apiKeyValue}
245
+ ${apiKeyName}=${apiKeyValue}
172
246
  `;
173
247
  };
174
248
 
175
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
176
254
  import fs from "fs-extra";
177
- import { execSync, execFileSync } from "child_process";
178
- 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) => {
179
484
  const packageJsonPath = `${targetPath}/package.json`;
180
- if (!fs.existsSync(packageJsonPath)) {
485
+ const isExistingProject = projectInfo?.isExistingProject ?? false;
486
+ if (!fs2.existsSync(packageJsonPath)) {
181
487
  console.log("Creating package.json...");
182
488
  execSync("npm init -y", { cwd: targetPath });
183
489
  }
184
- const pkgJson = fs.readJsonSync(packageJsonPath);
185
- pkgJson.name = pkgJson.name === "test" || !pkgJson.name ? "agentmark-example-app" : pkgJson.name;
186
- pkgJson.description = pkgJson.description || "A simple Node.js app using the Agentmark SDK";
187
- const devScript = "agentmark dev";
188
- const scripts = {
189
- ...pkgJson.scripts,
190
- "demo": "npx tsx index.ts",
191
- "dev": devScript,
192
- "prompt": "agentmark run-prompt",
193
- "experiment": "agentmark run-experiment"
194
- };
195
- if (deploymentMode === "static") {
196
- 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 });
197
531
  }
198
- pkgJson.scripts = scripts;
199
- pkgJson.overrides = {
200
- ...pkgJson.overrides,
201
- "axios": "^1.7.9"
202
- };
203
- fs.writeJsonSync(packageJsonPath, pkgJson, { spaces: 2 });
204
532
  };
205
- var installDependencies = (modelProvider, targetPath = ".", adapter = "ai-sdk", deploymentMode = "cloud") => {
533
+ var installDependencies = (modelProvider, targetPath = ".", adapter = "ai-sdk", deploymentMode = "cloud", packageManager = null) => {
206
534
  console.log("Installing required packages...");
207
535
  console.log("This might take a moment...");
208
536
  const adapterConfig = getAdapterConfig(adapter, modelProvider);
537
+ const pm = packageManager || DEFAULT_PACKAGE_MANAGER;
538
+ const npmSuffix = pm.name === "npm" ? " --legacy-peer-deps" : "";
209
539
  try {
210
- const devDepsCmd = "npm install --save-dev typescript ts-node @types/node @agentmark/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...`);
211
543
  execSync(devDepsCmd, {
212
544
  stdio: "inherit",
213
545
  cwd: targetPath
214
546
  });
215
- const loaderPackages = deploymentMode === "static" ? ["@agentmark/loader-api", "@agentmark/loader-file"] : ["@agentmark/loader-api"];
216
- const installArgs = [
217
- "install",
547
+ const loaderPackages = deploymentMode === "static" ? ["@agentmark-ai/loader-api", "@agentmark-ai/loader-file"] : ["@agentmark-ai/loader-api"];
548
+ const deps = [
218
549
  "dotenv",
219
- "@agentmark/prompt-core",
220
- "@agentmark/sdk",
550
+ "@agentmark-ai/prompt-core",
551
+ "@agentmark-ai/sdk",
221
552
  adapterConfig.package,
222
553
  ...loaderPackages,
223
- ...adapterConfig.dependencies,
224
- "--legacy-peer-deps"
554
+ ...adapterConfig.dependencies
225
555
  ];
226
- execFileSync("npm", installArgs, { stdio: "inherit", cwd: targetPath });
556
+ const depsCmd = `${pm.addCmd} ${deps.join(" ")}${npmSuffix}`;
557
+ execSync(depsCmd, { stdio: "inherit", cwd: targetPath });
227
558
  console.log("Packages installed successfully!");
228
559
  } catch (error) {
229
560
  console.error("Error installing packages:", error);
@@ -397,28 +728,32 @@ var getStoryDataset = () => {
397
728
  };
398
729
 
399
730
  // src/utils/examples/templates/example-prompts.ts
400
- import fs2 from "fs-extra";
731
+ import fs3 from "fs-extra";
401
732
  var createExamplePrompts = (model, targetPath = ".", adapter = "ai-sdk") => {
402
- fs2.ensureDirSync(`${targetPath}/agentmark`);
403
- 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) {
404
739
  const animalDrawingPrompt = getAnimalDrawingPrompt();
405
- fs2.writeFileSync(`${targetPath}/agentmark/animal-drawing.prompt.mdx`, animalDrawingPrompt);
740
+ fs3.writeFileSync(`${targetPath}/agentmark/animal-drawing.prompt.mdx`, animalDrawingPrompt);
406
741
  const animalDataset = getAnimalDataset();
407
- fs2.writeFileSync(`${targetPath}/agentmark/animal.jsonl`, animalDataset);
742
+ fs3.writeFileSync(`${targetPath}/agentmark/animal.jsonl`, animalDataset);
408
743
  }
409
744
  const customerSupportPrompt = getCustomerSupportPrompt(model);
410
- fs2.writeFileSync(`${targetPath}/agentmark/customer-support-agent.prompt.mdx`, customerSupportPrompt);
745
+ fs3.writeFileSync(`${targetPath}/agentmark/customer-support-agent.prompt.mdx`, customerSupportPrompt);
411
746
  const customerQueryDataset = getCustomerQueryDataset();
412
- fs2.writeFileSync(`${targetPath}/agentmark/customer-query.jsonl`, customerQueryDataset);
747
+ fs3.writeFileSync(`${targetPath}/agentmark/customer-query.jsonl`, customerQueryDataset);
413
748
  const partyPlannerPrompt = getPartyPlannerPrompt(model);
414
- fs2.writeFileSync(`${targetPath}/agentmark/party-planner.prompt.mdx`, partyPlannerPrompt);
749
+ fs3.writeFileSync(`${targetPath}/agentmark/party-planner.prompt.mdx`, partyPlannerPrompt);
415
750
  const partyDataset = getPartyDataset();
416
- fs2.writeFileSync(`${targetPath}/agentmark/party.jsonl`, partyDataset);
417
- if (adapter !== "mastra") {
751
+ fs3.writeFileSync(`${targetPath}/agentmark/party.jsonl`, partyDataset);
752
+ if (!skipSpeechPrompts) {
418
753
  const storyTellerPrompt = getStoryTellerPrompt();
419
- fs2.writeFileSync(`${targetPath}/agentmark/story-teller.prompt.mdx`, storyTellerPrompt);
754
+ fs3.writeFileSync(`${targetPath}/agentmark/story-teller.prompt.mdx`, storyTellerPrompt);
420
755
  const storyDataset = getStoryDataset();
421
- fs2.writeFileSync(`${targetPath}/agentmark/story.jsonl`, storyDataset);
756
+ fs3.writeFileSync(`${targetPath}/agentmark/story.jsonl`, storyDataset);
422
757
  }
423
758
  };
424
759
 
@@ -427,11 +762,12 @@ var getClientConfigContent = (options) => {
427
762
  const { provider, languageModels, adapter, deploymentMode = "cloud" } = options;
428
763
  const adapterConfig = getAdapterConfig(adapter, provider);
429
764
  const { modelRegistry, toolRegistry } = adapterConfig.classes;
430
- const providerImport = `import { ${provider} } from '@ai-sdk/${provider}';`;
431
- 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))
432
768
  .registerModels(["tts-1-hd"], (name: string) => ${provider}.speech(name))` : "";
433
- const loaderImport = deploymentMode === "cloud" ? `import { ApiLoader } from "@agentmark/loader-api";` : `import { ApiLoader } from "@agentmark/loader-api";
434
- import { FileLoader } from "@agentmark/loader-file";`;
769
+ const loaderImport = deploymentMode === "cloud" ? `import { ApiLoader } from "@agentmark-ai/loader-api";` : `import { ApiLoader } from "@agentmark-ai/loader-api";
770
+ import { FileLoader } from "@agentmark-ai/loader-file";`;
435
771
  const loaderSetup = deploymentMode === "cloud" ? ` // ApiLoader works for both development and production
436
772
  // - Development: 'agentmark dev' sets AGENTMARK_BASE_URL to localhost
437
773
  // - Production: Set AGENTMARK_API_KEY and AGENTMARK_APP_ID for cloud
@@ -443,6 +779,51 @@ import { FileLoader } from "@agentmark/loader-file";`;
443
779
  });` : ` const loader = process.env.NODE_ENV === 'development'
444
780
  ? ApiLoader.local({ baseUrl: process.env.AGENTMARK_BASE_URL || 'http://localhost:9418' })
445
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 });`;
446
827
  return `// agentmark.client.ts
447
828
  import path from 'node:path';
448
829
  import dotenv from 'dotenv';
@@ -451,13 +832,9 @@ import { createAgentMarkClient, ${modelRegistry}, ${toolRegistry}, EvalRegistry
451
832
  ${loaderImport}
452
833
  import AgentMarkTypes, { Tools } from './agentmark.types';
453
834
  ${providerImport}
835
+ ${adapterOptionsImport}
454
836
 
455
- function createModelRegistry() {
456
- const modelRegistry = new ${modelRegistry}()
457
- .registerModels(${JSON.stringify(languageModels)}, (name: string) => ${provider}(name))
458
- ${extraModelRegs};
459
- return modelRegistry;
460
- }
837
+ ${modelRegistrySetup}
461
838
 
462
839
  function createToolRegistry() {
463
840
  const toolRegistry = new ${toolRegistry}<Tools>()
@@ -504,7 +881,7 @@ ${loaderSetup}
504
881
  const modelRegistry = createModelRegistry();
505
882
  const toolRegistry = createToolRegistry();
506
883
  const evalRegistry = createEvalRegistry();
507
- return createAgentMarkClient<AgentMarkTypes, typeof toolRegistry>({ loader, modelRegistry, toolRegistry, evalRegistry });
884
+ ${createClientCall}
508
885
  }
509
886
 
510
887
  export const client = createClient();
@@ -512,7 +889,100 @@ export const client = createClient();
512
889
  };
513
890
 
514
891
  // src/utils/examples/create-example-app.ts
515
- import { fetchPromptsFrontmatter, generateTypeDefinitions } from "@agentmark/shared-utils";
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
516
986
  var setupMCPServer = (client, targetPath) => {
517
987
  if (client === "skip") {
518
988
  console.log("Skipping MCP server setup.");
@@ -522,16 +992,23 @@ var setupMCPServer = (client, targetPath) => {
522
992
  if (client === "vscode") {
523
993
  try {
524
994
  console.log(`Setting up MCP server for VS Code in ${folderName}...`);
525
- const vscodeDir = path.join(targetPath, ".vscode");
526
- fs3.ensureDirSync(vscodeDir);
995
+ const vscodeDir = path2.join(targetPath, ".vscode");
996
+ fs4.ensureDirSync(vscodeDir);
527
997
  const mcpConfig = {
528
998
  servers: {
529
999
  "agentmark-docs": {
530
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
+ }
531
1008
  }
532
1009
  }
533
1010
  };
534
- fs3.writeJsonSync(path.join(vscodeDir, "mcp.json"), mcpConfig, { spaces: 2 });
1011
+ fs4.writeJsonSync(path2.join(vscodeDir, "mcp.json"), mcpConfig, { spaces: 2 });
535
1012
  console.log(`\u2705 MCP server configured for VS Code in ${folderName}/.vscode/mcp.json`);
536
1013
  } catch (error) {
537
1014
  console.warn(`Warning: Could not set up MCP server for VS Code:`, error);
@@ -542,16 +1019,23 @@ var setupMCPServer = (client, targetPath) => {
542
1019
  if (client === "zed") {
543
1020
  try {
544
1021
  console.log(`Setting up MCP server for Zed in ${folderName}...`);
545
- const zedDir = path.join(targetPath, ".zed");
546
- fs3.ensureDirSync(zedDir);
1022
+ const zedDir = path2.join(targetPath, ".zed");
1023
+ fs4.ensureDirSync(zedDir);
547
1024
  const zedConfig = {
548
1025
  context_servers: {
549
1026
  "agentmark-docs": {
550
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
+ }
551
1035
  }
552
1036
  }
553
1037
  };
554
- fs3.writeJsonSync(path.join(zedDir, "settings.json"), zedConfig, { spaces: 2 });
1038
+ fs4.writeJsonSync(path2.join(zedDir, "settings.json"), zedConfig, { spaces: 2 });
555
1039
  console.log(`\u2705 MCP server configured for Zed in ${folderName}/.zed/settings.json`);
556
1040
  } catch (error) {
557
1041
  console.warn(`Warning: Could not set up MCP server for Zed:`, error);
@@ -562,16 +1046,23 @@ var setupMCPServer = (client, targetPath) => {
562
1046
  if (client === "cursor") {
563
1047
  try {
564
1048
  console.log(`Setting up MCP server for Cursor in ${folderName}...`);
565
- const cursorDir = path.join(targetPath, ".cursor");
566
- fs3.ensureDirSync(cursorDir);
1049
+ const cursorDir = path2.join(targetPath, ".cursor");
1050
+ fs4.ensureDirSync(cursorDir);
567
1051
  const cursorConfig = {
568
1052
  mcpServers: {
569
1053
  "agentmark-docs": {
570
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
+ }
571
1062
  }
572
1063
  }
573
1064
  };
574
- fs3.writeJsonSync(path.join(cursorDir, "mcp.json"), cursorConfig, { spaces: 2 });
1065
+ fs4.writeJsonSync(path2.join(cursorDir, "mcp.json"), cursorConfig, { spaces: 2 });
575
1066
  console.log(`\u2705 MCP server configured for Cursor in ${folderName}/.cursor/mcp.json`);
576
1067
  } catch (error) {
577
1068
  console.warn(`Warning: Could not set up MCP server for Cursor:`, error);
@@ -587,10 +1078,17 @@ var setupMCPServer = (client, targetPath) => {
587
1078
  "agentmark-docs": {
588
1079
  type: "http",
589
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
+ }
590
1088
  }
591
1089
  }
592
1090
  };
593
- fs3.writeJsonSync(path.join(targetPath, ".mcp.json"), mcpConfig, { spaces: 2 });
1091
+ fs4.writeJsonSync(path2.join(targetPath, ".mcp.json"), mcpConfig, { spaces: 2 });
594
1092
  console.log(`\u2705 MCP server configured for Claude Code in ${folderName}/.mcp.json`);
595
1093
  } catch (error) {
596
1094
  console.warn(`Warning: Could not set up MCP server for Claude Code:`, error);
@@ -599,70 +1097,112 @@ var setupMCPServer = (client, targetPath) => {
599
1097
  return;
600
1098
  }
601
1099
  };
602
- 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 = []) => {
603
1101
  try {
604
- const modelProvider = "openai";
605
- const model = "gpt-4o";
606
- 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
+ }
607
1110
  const folderName = targetPath;
608
- fs3.ensureDirSync(`${targetPath}/agentmark`);
1111
+ fs4.ensureDirSync(`${targetPath}/agentmark`);
609
1112
  setupMCPServer(client, targetPath);
610
1113
  createExamplePrompts(model, targetPath, adapter);
611
1114
  console.log(`\u2705 Example prompts and datasets created in ${folderName}/agentmark/`);
612
1115
  const langModels = Providers[modelProvider].languageModels.slice(0, 1);
613
- fs3.writeFileSync(
1116
+ fs4.writeFileSync(
614
1117
  `${targetPath}/agentmark.client.ts`,
615
1118
  getClientConfigContent({ provider: modelProvider, languageModels: langModels, adapter, deploymentMode })
616
1119
  );
617
- fs3.writeFileSync(`${targetPath}/.env`, getEnvFileContent(modelProvider, apiKey));
618
- const gitignore = ["node_modules", ".env", "*.agentmark-outputs/", ".agentmark", "dist"].join("\n");
619
- fs3.writeFileSync(`${targetPath}/.gitignore`, gitignore);
620
- fs3.writeFileSync(
621
- `${targetPath}/index.ts`,
622
- getIndexFileContent(adapter)
623
- );
624
- fs3.writeJsonSync(`${targetPath}/tsconfig.json`, getTsConfigContent(), { spaces: 2 });
625
- setupPackageJson(targetPath, deploymentMode);
626
- 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);
627
1167
  console.log("Generating types from prompts...");
628
1168
  try {
629
- const agentmarkDir = path.join(targetPath, "agentmark");
630
- const prompts2 = await fetchPromptsFrontmatter({ rootDir: agentmarkDir });
631
- const typeDefinitions = await generateTypeDefinitions(prompts2);
632
- 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);
633
1173
  } catch (error) {
634
1174
  console.warn("Warning: Could not generate types automatically:", error);
635
1175
  console.log("You can generate types later by running: npx agentmark generate-types --root-dir agentmark");
636
- fs3.writeFileSync(`${targetPath}/agentmark.types.ts`, `// Auto-generated types from AgentMark
1176
+ fs4.writeFileSync(`${targetPath}/agentmark.types.ts`, `// Auto-generated types from AgentMark
637
1177
  // Run 'npx agentmark generate-types --root-dir agentmark' to generate types
638
1178
  export default interface AgentmarkTypes {}
639
1179
  `);
640
1180
  }
641
1181
  console.log("Creating development server entry point...");
642
- const agentmarkInternalDir = path.join(targetPath, ".agentmark");
643
- fs3.ensureDirSync(agentmarkInternalDir);
644
- const adapterConfig = getAdapterConfig(adapter);
1182
+ const agentmarkInternalDir = path2.join(targetPath, ".agentmark");
1183
+ fs4.ensureDirSync(agentmarkInternalDir);
1184
+ const adapterConfig = getAdapterConfig(adapter, modelProvider);
645
1185
  const { webhookHandler } = adapterConfig.classes;
646
1186
  const devEntryContent = `// Auto-generated webhook server entry point
647
1187
  // To customize, create a dev-server.ts file in your project root
648
1188
 
649
- import { createWebhookServer } from '@agentmark/cli/runner-server';
1189
+ import { createWebhookServer } from '@agentmark-ai/cli/runner-server';
650
1190
  import { ${webhookHandler} } from '${adapterConfig.package}/runner';
651
- import { AgentMarkSDK } from '@agentmark/sdk';
1191
+ import { AgentMarkSDK } from '@agentmark-ai/sdk';
652
1192
  import path from 'path';
653
1193
 
654
1194
  async function main() {
655
1195
  const args = process.argv.slice(2);
656
1196
  const webhookPortArg = args.find(arg => arg.startsWith('--webhook-port='));
657
- const fileServerPortArg = args.find(arg => arg.startsWith('--file-server-port='));
1197
+ const apiServerPortArg = args.find(arg => arg.startsWith('--api-server-port='));
658
1198
 
659
1199
  const webhookPort = webhookPortArg ? parseInt(webhookPortArg.split('=')[1]) : 9417;
660
- const fileServerPort = fileServerPortArg ? parseInt(fileServerPortArg.split('=')[1]) : 9418;
661
- const fileServerUrl = \`http://localhost:\${fileServerPort}\`;
1200
+ const apiServerPort = apiServerPortArg ? parseInt(apiServerPortArg.split('=')[1]) : 9418;
1201
+ const apiServerUrl = \`http://localhost:\${apiServerPort}\`;
662
1202
 
663
1203
  // Set environment for development mode before importing client
664
1204
  process.env.NODE_ENV = 'development';
665
- process.env.AGENTMARK_BASE_URL = fileServerUrl;
1205
+ process.env.AGENTMARK_BASE_URL = apiServerUrl;
666
1206
 
667
1207
  // Now import client - it will pick up the dev environment
668
1208
  const { client } = await import('../agentmark.client.js');
@@ -671,7 +1211,7 @@ async function main() {
671
1211
  const sdk = new AgentMarkSDK({
672
1212
  apiKey: '',
673
1213
  appId: '',
674
- baseUrl: fileServerUrl,
1214
+ baseUrl: apiServerUrl,
675
1215
  });
676
1216
  sdk.initTracing({ disableBatch: true });
677
1217
 
@@ -681,7 +1221,7 @@ async function main() {
681
1221
  await createWebhookServer({
682
1222
  port: webhookPort,
683
1223
  handler,
684
- fileServerUrl,
1224
+ apiServerUrl,
685
1225
  templatesDirectory
686
1226
  });
687
1227
  }
@@ -691,7 +1231,7 @@ main().catch((err) => {
691
1231
  process.exit(1);
692
1232
  });
693
1233
  `;
694
- fs3.writeFileSync(path.join(agentmarkInternalDir, "dev-entry.ts"), devEntryContent);
1234
+ fs4.writeFileSync(path2.join(agentmarkInternalDir, "dev-entry.ts"), devEntryContent);
695
1235
  console.log("\n\u2705 Agentmark initialization completed successfully!");
696
1236
  console.log(
697
1237
  `
@@ -707,11 +1247,21 @@ main().catch((err) => {
707
1247
  console.log("\n" + "\u2550".repeat(70));
708
1248
  console.log("Next Steps");
709
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
+ }
710
1259
  console.log("\n Get Started:");
711
- if (folderName !== "." && folderName !== "./") {
1260
+ if (folderName !== "." && folderName !== "./" && !isExistingProject) {
712
1261
  console.log(` $ cd ${folderName}`);
713
1262
  }
714
- console.log(" $ npm run dev\n");
1263
+ console.log(` $ ${runCmd} ${devScriptName}
1264
+ `);
715
1265
  console.log("\u2500".repeat(70));
716
1266
  console.log("Resources");
717
1267
  console.log("\u2500".repeat(70));
@@ -723,18 +1273,715 @@ main().catch((err) => {
723
1273
  }
724
1274
  };
725
1275
 
1276
+ // src/utils/examples/create-python-app.ts
1277
+ import fs5 from "fs-extra";
1278
+ import * as path3 from "path";
1279
+ var setupMCPServer2 = (client, targetPath) => {
1280
+ if (client === "skip") {
1281
+ console.log("Skipping MCP server setup.");
1282
+ return;
1283
+ }
1284
+ const folderName = targetPath;
1285
+ if (client === "vscode") {
1286
+ try {
1287
+ console.log(`Setting up MCP server for VS Code in ${folderName}...`);
1288
+ const vscodeDir = path3.join(targetPath, ".vscode");
1289
+ fs5.ensureDirSync(vscodeDir);
1290
+ const mcpConfig = {
1291
+ servers: {
1292
+ "agentmark-docs": {
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
+ }
1301
+ }
1302
+ }
1303
+ };
1304
+ fs5.writeJsonSync(path3.join(vscodeDir, "mcp.json"), mcpConfig, { spaces: 2 });
1305
+ console.log(`MCP server configured for VS Code in ${folderName}/.vscode/mcp.json`);
1306
+ } catch (error) {
1307
+ console.warn(`Warning: Could not set up MCP server for VS Code:`, error);
1308
+ }
1309
+ return;
1310
+ }
1311
+ if (client === "zed") {
1312
+ try {
1313
+ console.log(`Setting up MCP server for Zed in ${folderName}...`);
1314
+ const zedDir = path3.join(targetPath, ".zed");
1315
+ fs5.ensureDirSync(zedDir);
1316
+ const zedConfig = {
1317
+ context_servers: {
1318
+ "agentmark-docs": {
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
+ }
1327
+ }
1328
+ }
1329
+ };
1330
+ fs5.writeJsonSync(path3.join(zedDir, "settings.json"), zedConfig, { spaces: 2 });
1331
+ console.log(`MCP server configured for Zed in ${folderName}/.zed/settings.json`);
1332
+ } catch (error) {
1333
+ console.warn(`Warning: Could not set up MCP server for Zed:`, error);
1334
+ }
1335
+ return;
1336
+ }
1337
+ if (client === "cursor") {
1338
+ try {
1339
+ console.log(`Setting up MCP server for Cursor in ${folderName}...`);
1340
+ const cursorDir = path3.join(targetPath, ".cursor");
1341
+ fs5.ensureDirSync(cursorDir);
1342
+ const cursorConfig = {
1343
+ mcpServers: {
1344
+ "agentmark-docs": {
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
+ }
1353
+ }
1354
+ }
1355
+ };
1356
+ fs5.writeJsonSync(path3.join(cursorDir, "mcp.json"), cursorConfig, { spaces: 2 });
1357
+ console.log(`MCP server configured for Cursor in ${folderName}/.cursor/mcp.json`);
1358
+ } catch (error) {
1359
+ console.warn(`Warning: Could not set up MCP server for Cursor:`, error);
1360
+ }
1361
+ return;
1362
+ }
1363
+ if (client === "claude-code") {
1364
+ try {
1365
+ console.log(`Setting up MCP server for Claude Code in ${folderName}...`);
1366
+ const mcpConfig = {
1367
+ mcpServers: {
1368
+ "agentmark-docs": {
1369
+ type: "http",
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
+ }
1378
+ }
1379
+ }
1380
+ };
1381
+ fs5.writeJsonSync(path3.join(targetPath, ".mcp.json"), mcpConfig, { spaces: 2 });
1382
+ console.log(`MCP server configured for Claude Code in ${folderName}/.mcp.json`);
1383
+ } catch (error) {
1384
+ console.warn(`Warning: Could not set up MCP server for Claude Code:`, error);
1385
+ }
1386
+ return;
1387
+ }
1388
+ };
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
+ }
1425
+ return `[project]
1426
+ name = "${projectName}"
1427
+ version = "0.1.0"
1428
+ description = "An AgentMark application using Pydantic AI"
1429
+ requires-python = ">=3.12"
1430
+ dependencies = [
1431
+ "agentmark-pydantic-ai>=0.1.0",
1432
+ "agentmark-prompt-core>=0.1.0",
1433
+ "python-dotenv>=1.0.0",
1434
+ "pydantic-ai[openai]>=0.1.0",
1435
+ ]
1436
+
1437
+ [project.optional-dependencies]
1438
+ dev = [
1439
+ "pytest>=7.0",
1440
+ "pytest-asyncio>=0.21",
1441
+ "mypy>=1.0",
1442
+ ]
1443
+ anthropic = ["pydantic-ai[anthropic]"]
1444
+ gemini = ["pydantic-ai[gemini]"]
1445
+
1446
+ [build-system]
1447
+ requires = ["hatchling"]
1448
+ build-backend = "hatchling.build"
1449
+
1450
+ [tool.pytest.ini_options]
1451
+ asyncio_mode = "auto"
1452
+
1453
+ [tool.mypy]
1454
+ strict = true
1455
+ `;
1456
+ };
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
+ }
1509
+ return `"""AgentMark client configuration.
1510
+
1511
+ This file configures the AgentMark client with Pydantic AI adapter.
1512
+ Customize the model registry and tool registry as needed.
1513
+ """
1514
+
1515
+ import os
1516
+ from pathlib import Path
1517
+ from dotenv import load_dotenv
1518
+
1519
+ from agentmark.prompt_core import FileLoader
1520
+ from agentmark_pydantic_ai_v0 import (
1521
+ create_pydantic_ai_client,
1522
+ create_default_model_registry,
1523
+ PydanticAIToolRegistry,
1524
+ )
1525
+
1526
+ # Load environment variables
1527
+ load_dotenv()
1528
+
1529
+ # Configure model registry with default mappings
1530
+ # Supports: gpt-*, claude-*, gemini-*, etc.
1531
+ model_registry = create_default_model_registry()
1532
+
1533
+ # Configure tool registry for custom tools
1534
+ tool_registry = PydanticAIToolRegistry()
1535
+
1536
+ # Example tool registration:
1537
+ # @tool_registry.register("search")
1538
+ # async def search_web(args: dict, ctx: dict | None) -> str:
1539
+ # query = args["query"]
1540
+ # return f"Search results for: {query}"
1541
+
1542
+ # Create file loader for local development
1543
+ # Uses the project root as base directory for resolving relative paths
1544
+ project_root = Path(__file__).parent.resolve()
1545
+ loader = FileLoader(base_dir=str(project_root))
1546
+
1547
+ # Create the client
1548
+ client = create_pydantic_ai_client(
1549
+ model_registry=model_registry,
1550
+ tool_registry=tool_registry,
1551
+ loader=loader,
1552
+ )
1553
+
1554
+ __all__ = ["client"]
1555
+ `;
1556
+ };
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
+ }
1608
+ return `"""Example usage of AgentMark with Pydantic AI.
1609
+
1610
+ Run with: python main.py
1611
+ """
1612
+
1613
+ import asyncio
1614
+ import json
1615
+ from pathlib import Path
1616
+
1617
+ from agentmark_pydantic_ai_v0 import run_text_prompt
1618
+ from agentmark_client import client
1619
+
1620
+
1621
+ async def main():
1622
+ """Run the party planner prompt."""
1623
+ # Load the prompt AST (in production, use the API loader)
1624
+ prompt_path = Path("agentmark/party-planner.prompt.mdx.json")
1625
+
1626
+ if not prompt_path.exists():
1627
+ print("Prompt file not found. Run 'agentmark build' first.")
1628
+ return
1629
+
1630
+ with open(prompt_path) as f:
1631
+ ast = json.load(f)
1632
+
1633
+ # Load and format the prompt
1634
+ prompt = await client.load_text_prompt(ast)
1635
+ params = await prompt.format(props={
1636
+ "numberOfGuests": 10,
1637
+ "theme": "80s disco",
1638
+ "dietaryRestrictions": ["vegetarian", "gluten-free"],
1639
+ })
1640
+
1641
+ # Execute the prompt
1642
+ print("Running party planner prompt...")
1643
+ result = await run_text_prompt(params)
1644
+
1645
+ print("\\n" + "=" * 50)
1646
+ print("Party Plan:")
1647
+ print("=" * 50)
1648
+ print(result.output)
1649
+ print("\\n" + "-" * 50)
1650
+ print(f"Tokens used: {result.usage.total_tokens}")
1651
+
1652
+
1653
+ if __name__ == "__main__":
1654
+ asyncio.run(main())
1655
+ `;
1656
+ };
1657
+ var getDevServerContent = (adapter) => {
1658
+ const adapterPackage = adapter === "claude-agent-sdk" ? "agentmark_claude_agent_sdk" : "agentmark_pydantic_ai_v0";
1659
+ return `"""Auto-generated webhook server for AgentMark development.
1660
+
1661
+ This server is started by 'npm run dev' (agentmark dev) and handles
1662
+ prompt execution requests from the CLI.
1663
+ """
1664
+
1665
+ import argparse
1666
+ import sys
1667
+ from pathlib import Path
1668
+
1669
+ # Add parent directory to path for imports
1670
+ sys.path.insert(0, str(Path(__file__).parent.parent))
1671
+
1672
+ from ${adapterPackage} import create_webhook_server
1673
+ from agentmark_client import client
1674
+
1675
+
1676
+ if __name__ == "__main__":
1677
+ parser = argparse.ArgumentParser()
1678
+ parser.add_argument("--webhook-port", type=int, default=9417)
1679
+ parser.add_argument("--api-server-port", type=int, default=9418)
1680
+ args = parser.parse_args()
1681
+
1682
+ create_webhook_server(client, args.webhook_port, args.api_server_port)
1683
+ `;
1684
+ };
1685
+ var getEnvContent = (apiKey, adapter) => {
1686
+ if (adapter === "claude-agent-sdk") {
1687
+ return `# Anthropic API Key
1688
+ ANTHROPIC_API_KEY=${apiKey}
1689
+ `;
1690
+ }
1691
+ return `# OpenAI API Key
1692
+ OPENAI_API_KEY=${apiKey}
1693
+
1694
+ # For Anthropic models, add:
1695
+ # ANTHROPIC_API_KEY=your-key-here
1696
+
1697
+ # For Google Gemini models, add:
1698
+ # GOOGLE_API_KEY=your-key-here
1699
+ `;
1700
+ };
1701
+ var getGitignoreContent = () => {
1702
+ return `# Python
1703
+ __pycache__/
1704
+ *.py[cod]
1705
+ *$py.class
1706
+ .venv/
1707
+ venv/
1708
+ .env
1709
+
1710
+ # AgentMark
1711
+ *.agentmark-outputs/
1712
+ .agentmark/
1713
+
1714
+ # IDE
1715
+ .idea/
1716
+ .vscode/
1717
+ *.swp
1718
+
1719
+ # Build
1720
+ dist/
1721
+ build/
1722
+ *.egg-info/
1723
+
1724
+ # Testing
1725
+ .pytest_cache/
1726
+ .coverage
1727
+ htmlcov/
1728
+ `;
1729
+ };
1730
+ var createPythonApp = async (client, targetPath = ".", apiKey = "", deploymentMode = "cloud", adapter = "pydantic-ai", projectInfo = null, resolutions = []) => {
1731
+ try {
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
+ }
1740
+ const folderName = targetPath;
1741
+ fs5.ensureDirSync(`${targetPath}/agentmark`);
1742
+ setupMCPServer2(client, targetPath);
1743
+ createExamplePrompts(model, targetPath, adapter);
1744
+ console.log(`Example prompts and datasets created in ${folderName}/agentmark/`);
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!");
1819
+ console.log(
1820
+ `
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
1822
+ \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u255A\u2588\u2588\u2557 \u2588\u2588\u2554\u255D\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551
1823
+ \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u255A\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551
1824
+ \u2588\u2588\u2554\u2550\u2550\u2550\u255D \u255A\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551
1825
+ \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551
1826
+ \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D
1827
+ + AgentMark
1828
+ `
1829
+ );
1830
+ console.log("\n" + "\u2550".repeat(70));
1831
+ console.log("Next Steps");
1832
+ console.log("\u2550".repeat(70));
1833
+ console.log("\n Get Started:");
1834
+ if (folderName !== "." && folderName !== "./" && !isExistingProject) {
1835
+ console.log(` $ cd ${folderName}`);
1836
+ }
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
+ }
1846
+ console.log(" $ npm run dev\n");
1847
+ console.log("\u2500".repeat(70));
1848
+ console.log("Resources");
1849
+ console.log("\u2500".repeat(70));
1850
+ console.log(" Documentation: https://docs.agentmark.co");
1851
+ console.log("\u2550".repeat(70) + "\n");
1852
+ } catch (error) {
1853
+ console.error("Error creating Python app:", error);
1854
+ throw error;
1855
+ }
1856
+ };
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
+
726
1968
  // src/index.ts
727
1969
  var parseArgs = () => {
728
1970
  const args = process.argv.slice(2);
729
1971
  let deploymentMode;
1972
+ let language;
730
1973
  for (const arg of args) {
731
1974
  if (arg === "--cloud") {
732
1975
  deploymentMode = "cloud";
733
1976
  } else if (arg === "--self-host") {
734
1977
  deploymentMode = "static";
1978
+ } else if (arg === "--python") {
1979
+ language = "python";
1980
+ } else if (arg === "--typescript") {
1981
+ language = "typescript";
735
1982
  }
736
1983
  }
737
- return { deploymentMode };
1984
+ return { deploymentMode, language };
738
1985
  };
739
1986
  var main = async () => {
740
1987
  const cliArgs = parseArgs();
@@ -745,35 +1992,73 @@ var main = async () => {
745
1992
  agentmarkPath: "."
746
1993
  };
747
1994
  console.log("Initializing project.");
748
- const { folderName } = await prompts({
1995
+ const { folderName } = await prompts2({
749
1996
  name: "folderName",
750
1997
  type: "text",
751
1998
  message: "Where would you like to create your AgentMark app?",
752
1999
  initial: "my-agentmark-app"
753
2000
  });
754
- const targetPath = `./${folderName}`;
755
- fs4.ensureDirSync(targetPath);
756
- config.builtInModels = ["gpt-4o"];
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);
2011
+ let language = cliArgs.language;
2012
+ if (!language) {
2013
+ const response = await prompts2({
2014
+ name: "language",
2015
+ type: "select",
2016
+ message: "Which language would you like to use?",
2017
+ choices: [
2018
+ { title: "TypeScript", value: "typescript" },
2019
+ { title: "Python", value: "python" }
2020
+ ]
2021
+ });
2022
+ language = response.language;
2023
+ }
2024
+ let adapter;
2025
+ if (language === "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;
2036
+ } else {
2037
+ const response = await prompts2({
2038
+ name: "adapter",
2039
+ type: "select",
2040
+ message: "Which adapter would you like to use?",
2041
+ choices: [
2042
+ { title: "AI SDK (Vercel)", value: "ai-sdk" },
2043
+ { title: "Claude Agent SDK", value: "claude-agent-sdk" },
2044
+ { title: "Mastra", value: "mastra" }
2045
+ ]
2046
+ });
2047
+ adapter = response.adapter;
2048
+ }
2049
+ config.builtInModels = adapter === "claude-agent-sdk" ? ["claude-sonnet-4-20250514"] : ["gpt-4o"];
2050
+ const apiKeyName = adapter === "claude-agent-sdk" ? "Anthropic" : "OpenAI";
757
2051
  let apiKey = "";
758
- const { providedApiKey } = await prompts({
2052
+ const { providedApiKey } = await prompts2({
759
2053
  name: "providedApiKey",
760
2054
  type: "password",
761
- message: `Enter your OpenAI API key (or press Enter to skip):`,
2055
+ message: `Enter your ${apiKeyName} API key (or press Enter to skip):`,
762
2056
  initial: ""
763
2057
  });
764
2058
  apiKey = providedApiKey || "";
765
- const { adapter } = await prompts({
766
- name: "adapter",
767
- type: "select",
768
- message: "Which adapter would you like to use?",
769
- choices: [
770
- { title: "AI SDK (Vercel)", value: "ai-sdk" },
771
- { title: "Mastra", value: "mastra" }
772
- ]
773
- });
774
2059
  let deploymentMode = cliArgs.deploymentMode;
775
2060
  if (!deploymentMode) {
776
- const response = await prompts({
2061
+ const response = await prompts2({
777
2062
  name: "deploymentMode",
778
2063
  type: "select",
779
2064
  message: "Use AgentMark Cloud or manage yourself?",
@@ -792,7 +2077,7 @@ var main = async () => {
792
2077
  });
793
2078
  deploymentMode = response.deploymentMode;
794
2079
  }
795
- const { client } = await prompts({
2080
+ const { client } = await prompts2({
796
2081
  name: "client",
797
2082
  type: "select",
798
2083
  message: "Make your IDE an AgentMark expert",
@@ -804,8 +2089,18 @@ var main = async () => {
804
2089
  { title: "Skip", value: "skip" }
805
2090
  ]
806
2091
  });
807
- await createExampleApp(client, targetPath, apiKey, adapter, deploymentMode);
808
- fs4.writeJsonSync(`${targetPath}/agentmark.json`, config, { spaces: 2 });
2092
+ if (language === "python") {
2093
+ await createPythonApp(client, targetPath, apiKey, deploymentMode, adapter, projectInfo, resolutions);
2094
+ } else {
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)");
2103
+ }
809
2104
  };
810
2105
  main().catch((error) => {
811
2106
  console.error("Error:", error);