create-agentmark 0.10.8 → 1.0.1

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,2274 +1,175 @@
1
1
  #!/usr/bin/env node
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __esm = (fn, res) => function __init() {
5
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
6
- };
7
- var __export = (target, all) => {
8
- for (var name in all)
9
- __defProp(target, name, { get: all[name], enumerable: true });
10
- };
11
-
12
- // src/utils/install-skill.ts
13
- var install_skill_exports = {};
14
- __export(install_skill_exports, {
15
- installAgentmarkSkill: () => installAgentmarkSkill
16
- });
17
- import { execFileSync } from "child_process";
18
- var shouldSkip, installAgentmarkSkill;
19
- var init_install_skill = __esm({
20
- "src/utils/install-skill.ts"() {
21
- "use strict";
22
- shouldSkip = () => process.env.VITEST === "true" || process.env.NODE_ENV === "test" || process.env.AGENTMARK_SKIP_SKILL_INSTALL === "1";
23
- installAgentmarkSkill = (targetPath) => {
24
- if (shouldSkip()) {
25
- console.log("\n\u23ED\uFE0F Skipping agent skill install (test environment detected).");
26
- return;
27
- }
28
- try {
29
- console.log("\n\u{1F4DA} Installing AgentMark agent skill...");
30
- console.log(" (teaches Claude Code / Codex / Cursor / Copilot how to use AgentMark)");
31
- execFileSync(
32
- "npx",
33
- ["--yes", "skills", "add", "agentmark-ai/skills"],
34
- {
35
- cwd: targetPath,
36
- stdio: "inherit"
37
- }
38
- );
39
- console.log("\u2705 Agent skill installed at ./.agents/skills/agentmark/");
40
- } catch (error) {
41
- console.warn(
42
- "\n\u26A0\uFE0F Could not install the AgentMark agent skill automatically."
43
- );
44
- console.warn(" You can install it later with:");
45
- console.warn(" cd " + targetPath);
46
- console.warn(" npx skills add agentmark-ai/skills");
47
- if (error instanceof Error) {
48
- console.warn(` Reason: ${error.message.split("\n")[0]}`);
49
- }
50
- }
51
- };
52
- }
53
- });
54
-
55
- // src/index.ts
56
- import fs8 from "fs-extra";
57
- import path6 from "path";
58
- import prompts2 from "prompts";
59
-
60
- // src/utils/examples/create-example-app.ts
61
- import fs4 from "fs-extra";
62
- import * as path2 from "path";
63
-
64
- // src/utils/examples/templates/adapters.ts
65
- var createAdapterConfig = (provider) => {
66
- return {
67
- "ai-sdk": {
68
- package: "@agentmark-ai/ai-sdk-v5-adapter",
69
- dependencies: ["ai@^5", `@ai-sdk/${provider}@^2`],
70
- classes: {
71
- modelRegistry: "VercelAIModelRegistry",
72
- webhookHandler: "VercelAdapterWebhookHandler"
73
- }
74
- },
75
- mastra: {
76
- package: "@agentmark-ai/mastra-v0-adapter",
77
- dependencies: [
78
- "@mastra/core@<0.20.0",
79
- "@mastra/mcp@<0.13.4",
80
- `@ai-sdk/${provider}@<2`,
81
- "ai@^4"
82
- ],
83
- classes: {
84
- modelRegistry: "MastraModelRegistry",
85
- webhookHandler: "MastraAdapterWebhookHandler"
86
- }
87
- },
88
- "claude-agent-sdk": {
89
- package: "@agentmark-ai/claude-agent-sdk-v0-adapter",
90
- dependencies: ["@anthropic-ai/claude-agent-sdk@^0.1.0"],
91
- classes: {
92
- modelRegistry: "ClaudeAgentModelRegistry",
93
- webhookHandler: "ClaudeAgentWebhookHandler"
94
- }
95
- }
96
- };
97
- };
98
- function getAdapterConfig(adapter, provider) {
99
- const config = createAdapterConfig(provider)[adapter];
100
- if (!config) {
101
- throw new Error(
102
- `Unknown adapter: ${adapter}. Available adapters: ${Object.keys(
103
- createAdapterConfig(provider)
104
- ).join(", ")}`
105
- );
106
- }
107
- return config;
108
- }
109
-
110
- // src/utils/examples/templates/app-index.ts
111
- var getIndexFileContent = (adapter = "ai-sdk", deploymentMode = "cloud") => {
112
- const isCloud = deploymentMode === "cloud";
113
- const tracingImport = `import { AgentMarkSDK } from "@agentmark-ai/sdk";
114
- `;
115
- const cloudTracingInit = `
116
- // Initialize tracing - traces will be sent to AgentMark Cloud
117
- // To disable tracing, comment out sdk.initTracing() below
118
- const sdk = new AgentMarkSDK({
119
- apiKey: process.env.AGENTMARK_API_KEY ?? "",
120
- appId: process.env.AGENTMARK_APP_ID ?? "",
121
- });
122
- sdk.initTracing({ disableBatch: true });
123
- `;
124
- const staticTracingInit = `
125
- // Initialize tracing - traces will be sent to local dev server
126
- // Make sure to run "npx agentmark dev" in another terminal first
127
- // To disable tracing, comment out sdk.initTracing() below
128
- const sdk = new AgentMarkSDK({
129
- apiKey: "",
130
- appId: "",
131
- baseUrl: "http://localhost:9418",
132
- });
133
- sdk.initTracing({ disableBatch: true });
134
- `;
135
- const tracingInit = isCloud ? cloudTracingInit : staticTracingInit;
136
- if (adapter === "claude-agent-sdk") {
137
- return `import "dotenv/config";
138
- import { query } from "@anthropic-ai/claude-agent-sdk";
139
- import { withTracing } from "@agentmark-ai/claude-agent-sdk-v0-adapter";
140
- ${tracingImport}import { client } from "./agentmark.client";
141
- ${tracingInit}
142
- const telemetry = {
143
- isEnabled: true,
144
- metadata: {
145
- trace_name: "customer-support",
146
- user_id: "user-123",
147
- session_id: "session-123",
148
- session_name: "my-first-session",
149
- },
150
- };
151
-
152
- const runCustomerSupport = async (customer_message: string) => {
153
- const prompt = await client.loadTextPrompt("customer-support-agent");
154
- const adapted = await prompt.format({
155
- props: {
156
- customer_question: customer_message,
157
- },
158
- telemetry,
159
- });
160
-
161
- // Execute with Claude Agent SDK using withTracing for telemetry
162
- // The adapted object contains { query, telemetry } ready for withTracing()
163
- const tracedResult = await withTracing(query, adapted);
164
-
165
- // traceId is available immediately
166
- console.log("Trace ID:", tracedResult.traceId);
167
-
168
- let result = "";
169
- for await (const message of tracedResult) {
170
- if (message.type === "result" && message.subtype === "success") {
171
- result = message.result || "";
172
- }
173
- }
174
-
175
- return result;
176
- };
177
-
178
- const main = async () => {
179
- try {
180
- const user_message = "How long does shipping take?";
181
- const assistant = await runCustomerSupport(user_message);
182
- console.log("Customer support response:", assistant);
183
- } catch (error) {
184
- console.error(error);
185
- }
186
- };
187
-
188
- main();
189
- `;
190
- } else if (adapter === "mastra") {
191
- return `import "dotenv/config";
192
- import { Agent } from "@mastra/core/agent";
193
- ${tracingImport}import { client } from "./agentmark.client";
194
- ${tracingInit}
195
- const telemetry = {
196
- isEnabled: true,
197
- metadata: {
198
- trace_name: "customer-support",
199
- user_id: "user-123",
200
- session_id: "session-123",
201
- session_name: "my-first-session",
202
- },
203
- };
204
-
205
- const runCustomerSupport = async (customer_message: string) => {
206
- const prompt = await client.loadTextPrompt("customer-support-agent");
207
- const agentConfig = await prompt.formatAgent({
208
- options: {
209
- telemetry,
210
- },
211
- });
212
-
213
- const [messages, generateOptions] = await agentConfig.formatMessages({
214
- props: {
215
- customer_question: customer_message,
216
- },
217
- });
218
-
219
- const agent = new Agent(agentConfig);
220
- const response = await agent.generate(messages, generateOptions);
221
-
222
- return (response as any).text || (response as any).content || String(response);
223
- };
224
-
225
- const main = async () => {
226
- try {
227
- const user_message = "How long does shipping take?";
228
- const assistant = await runCustomerSupport(user_message);
229
- console.log("Customer support response:", assistant);
230
- } catch (error) {
231
- console.error(error);
232
- }
233
- };
234
-
235
- main();
236
- `;
237
- } else {
238
- return `import "dotenv/config";
239
- import { generateText } from "ai";
240
- ${tracingImport}import { client } from "./agentmark.client";
241
- ${tracingInit}
242
- const telemetry = {
243
- isEnabled: true,
244
- metadata: {
245
- trace_name: "customer-support",
246
- user_id: "user-123",
247
- session_id: "session-123",
248
- session_name: "my-first-session",
249
- },
250
- };
251
-
252
- const runCustomerSupport = async (customer_message: string) => {
253
- const prompt = await client.loadTextPrompt("customer-support-agent");
254
- const vercelInput = await prompt.format({
255
- props: {
256
- customer_question: customer_message,
257
- },
258
- telemetry,
259
- });
260
-
261
- const resp = await generateText(vercelInput);
262
-
263
- return resp.text;
264
- };
265
-
266
- const main = async () => {
267
- try {
268
- const user_message = "How long does shipping take?";
269
- const assistant = await runCustomerSupport(user_message);
270
- console.log("Customer support response:", assistant);
271
- } catch (error) {
272
- console.error(error);
273
- }
274
- };
275
-
276
- main();
277
- `;
278
- }
279
- };
280
-
281
- // src/utils/examples/templates/env.ts
282
- var getEnvFileContent = (_modelProvider, apiKey = "", adapter = "ai-sdk", deploymentMode = "cloud") => {
283
- const apiKeyValue = apiKey || "your_api_key_here";
284
- const apiKeyName = adapter === "claude-agent-sdk" ? "ANTHROPIC_API_KEY" : "OPENAI_API_KEY";
285
- const cloudEnvVars = deploymentMode === "cloud" ? `
286
- # AgentMark Cloud \u2014 required for managed deployments
287
- AGENTMARK_API_KEY=your_agentmark_api_key
288
- AGENTMARK_APP_ID=your_agentmark_app_id
289
- ` : `
290
- # Cloud deployment: Set these environment variables
291
- # AGENTMARK_BASE_URL=https://api.agentmark.co
292
- # AGENTMARK_API_KEY=your_agentmark_api_key
293
- # AGENTMARK_APP_ID=your_agentmark_app_id
294
- `;
295
- return `${apiKeyName}=${apiKeyValue}
296
- ${cloudEnvVars}
297
- # Learn more: https://docs.agentmark.co/getting-started/quickstart
298
- `;
299
- };
300
-
301
- // src/utils/examples/templates/package-setup.ts
302
- import fs2 from "fs-extra";
303
- import { execSync } from "child_process";
304
-
305
- // src/utils/file-merge.ts
306
- import fs from "fs-extra";
307
- import path from "path";
308
- function mergePackageJson(targetPath, agentmarkDeps, agentmarkDevDeps, agentmarkScripts) {
309
- const packageJsonPath = path.join(targetPath, "package.json");
310
- const result = {
311
- success: false,
312
- warnings: [],
313
- added: [],
314
- skipped: []
315
- };
316
- try {
317
- if (!fs.existsSync(packageJsonPath)) {
318
- result.warnings.push("No existing package.json found");
319
- return result;
320
- }
321
- const existing = fs.readJsonSync(packageJsonPath);
322
- if (!existing.dependencies) {
323
- existing.dependencies = {};
324
- }
325
- if (!existing.devDependencies) {
326
- existing.devDependencies = {};
327
- }
328
- if (!existing.scripts) {
329
- existing.scripts = {};
330
- }
331
- const deps = existing.dependencies;
332
- const devDeps = existing.devDependencies;
333
- const scripts = existing.scripts;
334
- for (const [pkg, version] of Object.entries(agentmarkDeps)) {
335
- if (deps[pkg]) {
336
- result.skipped.push(`dependency: ${pkg} (already exists)`);
337
- } else {
338
- deps[pkg] = version;
339
- result.added.push(`dependency: ${pkg}@${version}`);
340
- }
341
- }
342
- for (const [pkg, version] of Object.entries(agentmarkDevDeps)) {
343
- if (devDeps[pkg]) {
344
- result.skipped.push(`devDependency: ${pkg} (already exists)`);
345
- } else {
346
- devDeps[pkg] = version;
347
- result.added.push(`devDependency: ${pkg}@${version}`);
348
- }
349
- }
350
- for (const [scriptName, scriptCmd] of Object.entries(agentmarkScripts)) {
351
- if (scripts[scriptName]) {
352
- const namespacedName = `agentmark:${scriptName}`;
353
- if (scripts[namespacedName]) {
354
- result.skipped.push(`script: ${scriptName}`);
355
- result.warnings.push(
356
- `Script "${scriptName}" and "${namespacedName}" both already exist. Skipping.`
357
- );
358
- } else {
359
- scripts[namespacedName] = scriptCmd;
360
- result.added.push(`script: ${namespacedName} (namespaced due to conflict)`);
361
- result.warnings.push(
362
- `Script "${scriptName}" already exists. Added as "${namespacedName}" instead.`
363
- );
364
- }
365
- } else {
366
- scripts[scriptName] = scriptCmd;
367
- result.added.push(`script: ${scriptName}`);
368
- }
369
- }
370
- fs.writeJsonSync(packageJsonPath, existing, { spaces: 2 });
371
- result.success = true;
372
- result.content = JSON.stringify(existing, null, 2);
373
- return result;
374
- } catch (error) {
375
- result.warnings.push(`Error merging package.json: ${error}`);
376
- return result;
377
- }
378
- }
379
- function appendGitignore(targetPath, entries) {
380
- const gitignorePath = path.join(targetPath, ".gitignore");
381
- const result = {
382
- success: false,
383
- warnings: [],
384
- added: [],
385
- skipped: []
386
- };
387
- try {
388
- let existingContent = "";
389
- if (fs.existsSync(gitignorePath)) {
390
- existingContent = fs.readFileSync(gitignorePath, "utf-8");
391
- }
392
- const existingEntries = new Set(
393
- existingContent.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map((line) => line.replace(/\/$/, ""))
394
- // Remove trailing slashes for comparison
395
- );
396
- const entriesToAdd = [];
397
- for (const entry of entries) {
398
- const normalizedEntry = entry.replace(/\/$/, "");
399
- if (existingEntries.has(normalizedEntry)) {
400
- result.skipped.push(entry);
401
- } else {
402
- entriesToAdd.push(entry);
403
- result.added.push(entry);
404
- }
405
- }
406
- if (entriesToAdd.length > 0) {
407
- let newContent = existingContent;
408
- if (newContent && !newContent.endsWith("\n")) {
409
- newContent += "\n";
410
- }
411
- if (newContent.trim()) {
412
- newContent += "\n";
413
- }
414
- newContent += "# AgentMark\n";
415
- newContent += entriesToAdd.join("\n");
416
- newContent += "\n";
417
- fs.writeFileSync(gitignorePath, newContent);
418
- result.content = newContent;
419
- }
420
- result.success = true;
421
- return result;
422
- } catch (error) {
423
- result.warnings.push(`Error appending to .gitignore: ${error}`);
424
- return result;
425
- }
426
- }
427
- function appendEnv(targetPath, envVars) {
428
- const envPath = path.join(targetPath, ".env");
429
- const result = {
430
- success: false,
431
- warnings: [],
432
- added: [],
433
- skipped: []
434
- };
435
- try {
436
- let existingContent = "";
437
- if (fs.existsSync(envPath)) {
438
- existingContent = fs.readFileSync(envPath, "utf-8");
439
- }
440
- const existingKeys = /* @__PURE__ */ new Set();
441
- const lines = existingContent.split("\n");
442
- for (const line of lines) {
443
- const trimmed = line.trim();
444
- if (trimmed && !trimmed.startsWith("#")) {
445
- const match = trimmed.match(/^([^=]+)=/);
446
- if (match && match[1]) {
447
- existingKeys.add(match[1]);
448
- }
449
- }
450
- }
451
- const varsToAdd = [];
452
- for (const [key, value] of Object.entries(envVars)) {
453
- if (existingKeys.has(key)) {
454
- result.skipped.push(key);
455
- } else {
456
- varsToAdd.push([key, value]);
457
- result.added.push(key);
458
- }
459
- }
460
- if (varsToAdd.length > 0) {
461
- let newContent = existingContent;
462
- if (newContent && !newContent.endsWith("\n")) {
463
- newContent += "\n";
464
- }
465
- if (newContent.trim()) {
466
- newContent += "\n";
467
- }
468
- newContent += "# AgentMark\n";
469
- for (const [key, value] of varsToAdd) {
470
- newContent += `${key}=${value}
471
- `;
472
- }
473
- fs.writeFileSync(envPath, newContent);
474
- result.content = newContent;
475
- }
476
- result.success = true;
477
- return result;
478
- } catch (error) {
479
- result.warnings.push(`Error appending to .env: ${error}`);
480
- return result;
481
- }
482
- }
483
-
484
- // src/utils/types.ts
485
- var PACKAGE_MANAGERS = {
486
- "yarn.lock": {
487
- name: "yarn",
488
- lockFile: "yarn.lock",
489
- installCmd: "yarn install",
490
- addCmd: "yarn add",
491
- addDevCmd: "yarn add --dev",
492
- runCmd: "yarn"
493
- },
494
- "pnpm-lock.yaml": {
495
- name: "pnpm",
496
- lockFile: "pnpm-lock.yaml",
497
- installCmd: "pnpm install",
498
- addCmd: "pnpm add",
499
- addDevCmd: "pnpm add --save-dev",
500
- runCmd: "pnpm"
501
- },
502
- "bun.lockb": {
503
- name: "bun",
504
- lockFile: "bun.lockb",
505
- installCmd: "bun install",
506
- addCmd: "bun add",
507
- addDevCmd: "bun add --dev",
508
- runCmd: "bun run"
509
- },
510
- "package-lock.json": {
511
- name: "npm",
512
- lockFile: "package-lock.json",
513
- installCmd: "npm install",
514
- addCmd: "npm install",
515
- addDevCmd: "npm install --save-dev",
516
- runCmd: "npm run"
517
- }
518
- };
519
- var DEFAULT_PACKAGE_MANAGER = PACKAGE_MANAGERS["package-lock.json"];
520
- var CONFLICT_FILES = [
521
- { path: "agentmark.json", type: "config", strategy: "prompt" },
522
- { path: "agentmark", type: "directory", strategy: "prompt" },
523
- { path: "agentmark.client.ts", type: "source", strategy: "prompt" },
524
- { path: "agentmark_client.py", type: "source", strategy: "prompt" },
525
- { path: ".gitignore", type: "dotfile", strategy: "append" },
526
- { path: ".env", type: "dotfile", strategy: "append" },
527
- { path: "package.json", type: "config", strategy: "merge" },
528
- { path: "index.ts", type: "source", strategy: "skip" },
529
- { path: "main.py", type: "source", strategy: "skip" },
530
- { path: "tsconfig.json", type: "config", strategy: "skip" },
531
- { path: "pyproject.toml", type: "config", strategy: "skip" }
532
- ];
533
-
534
- // src/utils/examples/templates/package-setup.ts
535
- var setupPackageJson = (targetPath = ".", deploymentMode = "cloud", projectInfo = null) => {
536
- const packageJsonPath = `${targetPath}/package.json`;
537
- const isExistingProject = projectInfo?.isExistingProject ?? false;
538
- if (!fs2.existsSync(packageJsonPath)) {
539
- console.log("Creating package.json...");
540
- execSync("npm init -y", { cwd: targetPath });
541
- }
542
- const demoScript = deploymentMode === "static" ? "npx agentmark build --out dist/agentmark && npx tsx index.ts" : "npx tsx index.ts";
543
- if (isExistingProject && fs2.existsSync(packageJsonPath)) {
544
- const scriptsToAdd = {
545
- "demo": demoScript,
546
- "agentmark": "agentmark"
547
- };
548
- if (deploymentMode === "static") {
549
- scriptsToAdd["build"] = "agentmark build --out dist/agentmark";
550
- }
551
- const result = mergePackageJson(targetPath, {}, {}, scriptsToAdd);
552
- if (result.added.length > 0) {
553
- console.log(`\u2705 Added to package.json: ${result.added.join(", ")}`);
554
- }
555
- if (result.skipped.length > 0) {
556
- console.log(`\u23ED\uFE0F Skipped existing in package.json: ${result.skipped.join(", ")}`);
557
- }
558
- if (result.warnings.length > 0) {
559
- result.warnings.forEach((w) => console.log(`\u26A0\uFE0F ${w}`));
560
- }
561
- } else {
562
- const pkgJson = fs2.readJsonSync(packageJsonPath);
563
- pkgJson.name = pkgJson.name === "test" || !pkgJson.name ? "agentmark-example-app" : pkgJson.name;
564
- pkgJson.description = pkgJson.description || "A simple Node.js app using the Agentmark SDK";
565
- if (pkgJson.type === "commonjs") {
566
- delete pkgJson.type;
567
- }
568
- const scripts = {
569
- ...pkgJson.scripts,
570
- "demo": demoScript,
571
- "agentmark": "agentmark"
572
- };
573
- if (deploymentMode === "static") {
574
- scripts["build"] = "agentmark build --out dist/agentmark";
575
- }
576
- pkgJson.scripts = scripts;
577
- fs2.writeJsonSync(packageJsonPath, pkgJson, { spaces: 2 });
578
- }
579
- };
580
- var installDependencies = (modelProvider, targetPath = ".", adapter = "ai-sdk", deploymentMode = "cloud", packageManager = null) => {
581
- console.log("Installing required packages...");
582
- console.log("This might take a moment...");
583
- const adapterConfig = getAdapterConfig(adapter, modelProvider);
584
- const pm = packageManager || DEFAULT_PACKAGE_MANAGER;
585
- const npmSuffix = pm.name === "npm" ? " --legacy-peer-deps" : "";
586
- try {
587
- const devDeps = ["typescript", "ts-node", "@types/node", "@agentmark-ai/cli"];
588
- const devDepsCmd = `${pm.addDevCmd} ${devDeps.join(" ")}${npmSuffix}`;
589
- console.log(`Using ${pm.name} to install dependencies...`);
590
- execSync(devDepsCmd, {
591
- stdio: "inherit",
592
- cwd: targetPath
593
- });
594
- const loaderPackages = deploymentMode === "static" ? ["@agentmark-ai/loader-api", "@agentmark-ai/loader-file"] : ["@agentmark-ai/loader-api"];
595
- const deps = [
596
- "dotenv",
597
- "@agentmark-ai/prompt-core",
598
- "@agentmark-ai/sdk",
599
- adapterConfig.package,
600
- ...loaderPackages,
601
- ...adapterConfig.dependencies
602
- ];
603
- const depsCmd = `${pm.addCmd} ${deps.join(" ")}${npmSuffix}`;
604
- execSync(depsCmd, { stdio: "inherit", cwd: targetPath });
605
- console.log("Packages installed successfully!");
606
- } catch (error) {
607
- console.error("Error installing packages:", error);
608
- throw new Error(
609
- "Failed to install required packages. Please check your network connection and try again."
610
- );
611
- }
612
- };
613
-
614
- // src/utils/examples/templates/tsconfig.ts
615
- var getTsConfigContent = () => {
616
- return {
617
- "compilerOptions": {
618
- "target": "ES2020",
619
- "module": "NodeNext",
620
- "moduleResolution": "NodeNext",
621
- "esModuleInterop": true,
622
- "forceConsistentCasingInFileNames": true,
623
- "strict": true,
624
- "skipLibCheck": true
625
- }
626
- };
627
- };
628
-
629
- // src/utils/examples/templates/animal-drawing-prompt.ts
630
- var getAnimalDrawingPrompt = () => {
631
- return `---
632
- name: animal-drawing
633
- image_config:
634
- model_name: openai/dall-e-3
635
- num_images: 1
636
- size: 1024x1024
637
- aspect_ratio: 1:1
638
- test_settings:
639
- dataset: animal.jsonl
640
- props:
641
- animal: "cat"
642
- ---
643
-
644
- <ImagePrompt>
645
- Draw a hyper-realistic picture of a {props.animal}
646
- </ImagePrompt>`;
647
- };
648
-
649
- // src/utils/examples/templates/customer-support-prompt.ts
650
- var getCustomerSupportPrompt = (model) => {
651
- return `---
652
- name: customer-support-agent
653
- text_config:
654
- model_name: ${model}
655
- max_calls: 2
656
- tools:
657
- - search_knowledgebase
658
- test_settings:
659
- dataset: customer-query.jsonl
660
- props:
661
- customer_question: "I'm having trouble with my order. How long does shipping take?"
662
- input_schema:
663
- type: object
664
- properties:
665
- customer_question:
666
- type: string
667
- description: "The customer's question"
668
- required:
669
- - customer_question
670
- ---
671
-
672
- <System>
673
- You are a customer service agent for a company that sells products online. You are given a customer's question and you need to respond to the customer. You need to be friendly, professional, and helpful.
674
-
675
- You have access to the following tool:
676
- - search_knowledgebase: Search the company knowledgebase for information about shipping, warranty, and returns. Use this when customers ask about these topics.
677
- </System>
678
-
679
- <User>{props.customer_question}</User>`;
680
- };
681
-
682
- // src/utils/examples/templates/party-planner-prompt.ts
683
- var getPartyPlannerPrompt = (model) => {
684
- return `---
685
- name: party-planner
686
- object_config:
687
- model_name: ${model}
688
- schema:
689
- type: object
690
- properties:
691
- names:
692
- type: array
693
- description: "List of names of people attending the party."
694
- items:
695
- type: string
696
- required:
697
- - names
698
- test_settings:
699
- dataset: party.jsonl
700
- evals:
701
- - exact_match_json
702
- props:
703
- party_text: "We're having a party with Alice, Bob, and Carol."
704
- input_schema:
705
- type: object
706
- properties:
707
- party_text:
708
- type: string
709
- description: "A block of text describing the upcoming party and attendees."
710
- required:
711
- - party_text
712
- ---
713
-
714
- <System>
715
- Extract the names of all people attending the party from the following text. Respond with a list of names only.
716
- </System>
717
-
718
- <User>
719
- Text: {props.party_text}
720
- </User>`;
721
- };
722
-
723
- // src/utils/examples/templates/story-teller-prompt.ts
724
- var getStoryTellerPrompt = () => {
725
- return `---
726
- name: story-teller
727
- speech_config:
728
- model_name: openai/tts-1-hd
729
- voice: "nova"
730
- speed: 1.0
731
- output_format: "mp3"
732
- test_settings:
733
- dataset: story.jsonl
734
- props:
735
- story: "Once upon a time, there was a cat who loved to play with a ball."
736
- ---
737
-
738
- <System>
739
- You are a storyteller for children. Make sure your story is engaging and interesting.
740
- </System>
741
-
742
- <SpeechPrompt>
743
- - {props.story}
744
- </SpeechPrompt>`;
745
- };
746
-
747
- // src/utils/examples/templates/datasets.ts
748
- var getAnimalDataset = () => {
749
- return `{"input": {"animal": "cat"}, "expected_output": "A realistic picture of a cat"}
750
- {"input": {"animal": "dog"}, "expected_output": "A realistic picture of a dog"}
751
- {"input": {"animal": "bird"}, "expected_output": "A realistic picture of a bird"}`;
752
- };
753
- var getCustomerQueryDataset = () => {
754
- return `{"input": {"customer_question": "My package hasn't arrived yet. Can you help me track it?"}}
755
- {"input": {"customer_question": "I received the wrong item in my order. What should I do?"}}
756
- {"input": {"customer_question": "How do I return a product that I purchased last week?"}}`;
757
- };
758
- var getPartyDataset = () => {
759
- return `{"input": {"party_text": "We're having a party with Alice, Bob, and Carol."}, "expected_output": "{\\"names\\": [\\"Alice\\", \\"Bob\\", \\"Carol\\"]}"}
760
- {"input": {"party_text": "The guest list includes Dave, Emma, and Frank."}, "expected_output": "{\\"names\\": [\\"Dave\\", \\"Emma\\", \\"Frank\\"]}"}
761
- {"input": {"party_text": "Join us for a celebration with Grace, Henry, and Isla."}, "expected_output": "{\\"names\\": [\\"Grace\\", \\"Henry\\", \\"Isla\\"]}"}`;
762
- };
763
- var getStoryDataset = () => {
764
- return `{"input": {"story": "Once upon a time, the Moon woke up and found her glow missing! She floated around the sky asking stars, clouds, and even comets if they'd seen her light. It wasn't until she peeked into a mountain lake that she saw her glow shining back\u2014hidden in her own reflection! Laughing, she realized she had never lost it\u2014it was with her all along, just hiding beneath a cloudy sky."}}
765
- {"input": {"story": "Benny was no ordinary banana\u2014he dreamed of becoming a superhero. One day, when a monkey slipped in the jungle and cried for help, Benny rolled into action, dodging vines and swinging from branches using his peel like a lasso. The monkey was saved, and from that day on, Benny was known as \\"The Peel of Justice,\\" the bravest fruit in the whole rainforest."}}
766
- {"input": {"story": "In the town of Maplebrook, there was a library that whispered stories when no one was looking. Curious little Nia tiptoed in one rainy day and heard the books giggling softly. She opened one called The Secret Tunnel, and to her surprise, it sucked her in! She found herself riding a dragon through glittering caves. When she returned, the book winked shut\u2014waiting for its next reader to listen."}}`;
767
- };
768
-
769
- // src/utils/examples/templates/example-prompts.ts
770
- import fs3 from "fs-extra";
771
- var createExamplePrompts = (model, targetPath = ".", adapter = "ai-sdk") => {
772
- fs3.ensureDirSync(`${targetPath}/agentmark`);
773
- const noImageSupport = ["mastra", "claude-agent-sdk", "pydantic-ai"];
774
- const noSpeechSupport = ["mastra", "claude-agent-sdk", "pydantic-ai"];
775
- const skipImagePrompts = noImageSupport.includes(adapter);
776
- const skipSpeechPrompts = noSpeechSupport.includes(adapter);
777
- const usedModels = [];
778
- if (!skipImagePrompts) {
779
- const animalDrawingPrompt = getAnimalDrawingPrompt();
780
- fs3.writeFileSync(`${targetPath}/agentmark/animal-drawing.prompt.mdx`, animalDrawingPrompt);
781
- const animalDataset = getAnimalDataset();
782
- fs3.writeFileSync(`${targetPath}/agentmark/animal.jsonl`, animalDataset);
783
- usedModels.push("openai/dall-e-3");
784
- }
785
- const customerSupportPrompt = getCustomerSupportPrompt(model);
786
- fs3.writeFileSync(`${targetPath}/agentmark/customer-support-agent.prompt.mdx`, customerSupportPrompt);
787
- const customerQueryDataset = getCustomerQueryDataset();
788
- fs3.writeFileSync(`${targetPath}/agentmark/customer-query.jsonl`, customerQueryDataset);
789
- usedModels.push(model);
790
- const partyPlannerPrompt = getPartyPlannerPrompt(model);
791
- fs3.writeFileSync(`${targetPath}/agentmark/party-planner.prompt.mdx`, partyPlannerPrompt);
792
- const partyDataset = getPartyDataset();
793
- fs3.writeFileSync(`${targetPath}/agentmark/party.jsonl`, partyDataset);
794
- if (!skipSpeechPrompts) {
795
- const storyTellerPrompt = getStoryTellerPrompt();
796
- fs3.writeFileSync(`${targetPath}/agentmark/story-teller.prompt.mdx`, storyTellerPrompt);
797
- const storyDataset = getStoryDataset();
798
- fs3.writeFileSync(`${targetPath}/agentmark/story.jsonl`, storyDataset);
799
- usedModels.push("openai/tts-1-hd");
800
- }
801
- return [...new Set(usedModels)];
802
- };
803
-
804
- // src/utils/examples/templates/user-client-config.ts
805
- var getClientConfigContent = (options) => {
806
- const { provider, adapter, deploymentMode = "cloud" } = options;
807
- const isMastra = adapter === "mastra";
808
- const adapterConfig = getAdapterConfig(adapter, provider);
809
- const { modelRegistry } = adapterConfig.classes;
810
- const isClaudeAgentSdk = adapter === "claude-agent-sdk";
811
- const providerImport = isClaudeAgentSdk ? "" : `import { ${provider} } from '@ai-sdk/${provider}';`;
812
- const loaderImport = deploymentMode === "cloud" ? `import { ApiLoader } from "@agentmark-ai/loader-api";` : `import { ApiLoader } from "@agentmark-ai/loader-api";
813
- import { FileLoader } from "@agentmark-ai/loader-file";`;
814
- const loaderSetup = deploymentMode === "cloud" ? ` // ApiLoader works for both development and production
815
- // - Development: 'agentmark dev' sets AGENTMARK_BASE_URL to localhost
816
- // - Production: Set AGENTMARK_API_KEY and AGENTMARK_APP_ID for cloud.
817
- // AGENTMARK_BASE_URL overrides the default https://api.agentmark.co
818
- // target \u2014 managed deployments use this to point back at the gateway
819
- // that dispatched the job.
820
- const loader = process.env.NODE_ENV === 'development'
821
- ? ApiLoader.local({ baseUrl: process.env.AGENTMARK_BASE_URL || 'http://localhost:9418' })
822
- : ApiLoader.cloud({
823
- apiKey: process.env.AGENTMARK_API_KEY!,
824
- appId: process.env.AGENTMARK_APP_ID!,
825
- baseUrl: process.env.AGENTMARK_BASE_URL,
826
- });` : ` const loader = process.env.NODE_ENV === 'development'
827
- ? ApiLoader.local({ baseUrl: process.env.AGENTMARK_BASE_URL || 'http://localhost:9418' })
828
- : new FileLoader('./dist/agentmark');`;
829
- const modelRegistrySetup = isClaudeAgentSdk ? `function createModelRegistry() {
830
- // Claude Agent SDK accepts model names directly.
831
- // Use createDefault() for simple pass-through of model names.
832
- const modelRegistry = ${modelRegistry}.createDefault();
833
-
834
- // To configure specific models (e.g., extended thinking), use:
835
- // const modelRegistry = new ${modelRegistry}()
836
- // .registerModels(/claude-.*-thinking/, (name) => ({
837
- // model: name,
838
- // maxThinkingTokens: 10000, // Enable extended thinking
839
- // }))
840
- // .registerModels("claude-sonnet-4-20250514", (name) => ({ model: name }));
841
-
842
- return modelRegistry;
843
- }` : `function createModelRegistry() {
844
- const modelRegistry = new ${modelRegistry}()
845
- .registerProviders({ ${provider} });
846
- return modelRegistry;
847
- }`;
848
- const adapterOptionsImport = isClaudeAgentSdk ? `
849
- // Claude Agent SDK adapter options
850
- // See: https://github.com/anthropics/claude-agent-sdk
851
- const adapterOptions = {
852
- // Permission mode controls tool access:
853
- // - 'default': Requires user approval for each tool use
854
- // - 'acceptEdits': Auto-approve file edits only
855
- // - 'bypassPermissions': Auto-approve all tools (use for automated pipelines)
856
- // - 'plan': Planning mode only, no tool execution
857
- permissionMode: 'bypassPermissions' as const,
858
-
859
- // Maximum conversation turns before stopping
860
- maxTurns: 20,
861
-
862
- // Optional: Set working directory for file operations
863
- // cwd: process.cwd(),
864
-
865
- // Optional: Budget limit in USD
866
- // maxBudgetUsd: 10.00,
867
-
868
- // Optional: Restrict which tools the agent can use
869
- // allowedTools: ['Read', 'Write', 'Glob'],
870
- // disallowedTools: ['Bash'],
871
- };` : "";
872
- const toolImport = isClaudeAgentSdk ? `import { tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
873
- import { z } from 'zod';` : isMastra ? `import { tool } from 'ai';
874
- import type { ToolsInput } from '@mastra/core/agent';
875
- import { z } from 'zod';` : `import { tool } from 'ai';
876
- import type { Tool } from 'ai';
877
- import { z } from 'zod';`;
878
- const createClientCall = isClaudeAgentSdk ? `return createAgentMarkClient<AgentMarkTypes>({ loader, modelRegistry, evals, adapterOptions, mcpServers: { 'customer-support': customerSupportTools } });` : `return createAgentMarkClient<AgentMarkTypes>({ loader, modelRegistry, tools, evals });`;
879
- const toolSchemaField = isMastra ? `parameters: z.object({ query: z.string().describe('The search query') })` : `inputSchema: z.object({ query: z.string().describe('The search query') })`;
880
- const toolsReturnType = isMastra ? "ToolsInput" : "Record<string, Tool>";
881
- const toolsSetup = isClaudeAgentSdk ? `
882
- // Custom tools exposed as an MCP server \u2014 the SDK's native tool mechanism.
883
- // The server name is used in mcpServers config; tool names are used in prompt files.
884
- const knowledgeBase = tool(
885
- 'search_knowledgebase',
886
- 'Search the knowledge base for relevant articles',
887
- { query: z.string().describe('The search query') },
888
- async ({ query }) => ({
889
- content: [{ type: 'text' as const, text: JSON.stringify({
890
- articles: [
891
- { topic: 'shipping', content: 'Standard shipping takes 3\u20135 business days.' },
892
- { topic: 'warranty', content: 'All products include a 1-year limited warranty.' },
893
- { topic: 'returns', content: 'You can return items within 30 days of delivery.' },
894
- ],
895
- }) }],
896
- })
897
- );
898
-
899
- const customerSupportTools = createSdkMcpServer({
900
- name: 'customer-support',
901
- tools: [knowledgeBase],
902
- });` : `
903
- function createTools(): ${toolsReturnType} {
904
- return {
905
- search_knowledgebase: tool({
906
- description: 'Search the knowledge base for relevant articles',
907
- ${toolSchemaField},
908
- execute: async ({ query }) => {
909
- // Simulate search delay
910
- await new Promise(resolve => setTimeout(resolve, 500));
911
-
912
- // Return all three knowledge base articles
913
- // The LLM will select the relevant one based on the query
914
- return {
915
- articles: [
916
- { topic: 'shipping', content: 'Standard shipping takes 3\u20135 business days.' },
917
- { topic: 'warranty', content: 'All products include a 1-year limited warranty.' },
918
- { topic: 'returns', content: 'You can return items within 30 days of delivery.' }
919
- ]
920
- };
921
- },
922
- }),
923
- };
924
- }`;
925
- const toolsVariable = isClaudeAgentSdk ? "" : ` const tools = createTools();`;
926
- return `// agentmark.client.ts
927
- import path from 'node:path';
928
- import dotenv from 'dotenv';
929
- dotenv.config({ path: path.resolve(__dirname, '.env') });
930
- import { createAgentMarkClient, ${modelRegistry} } from "${adapterConfig.package}";
931
- import type { EvalRegistry } from "@agentmark-ai/prompt-core";
932
- ${loaderImport}
933
- import AgentMarkTypes from './agentmark.types';
934
- ${providerImport}
935
- ${toolImport}
936
- ${adapterOptionsImport}
937
-
938
- ${modelRegistrySetup}
939
- ${toolsSetup}
940
-
941
- const evals: EvalRegistry = {
942
- exact_match_json: async ({ output, expectedOutput }) => {
943
- if (!expectedOutput) {
944
- return { score: 0, label: 'error', reason: 'No expected output provided', passed: false };
945
- }
946
- try {
947
- const ok = JSON.stringify(output) === JSON.stringify(JSON.parse(expectedOutput));
948
- return {
949
- score: ok ? 1 : 0,
950
- label: ok ? 'correct' : 'incorrect',
951
- reason: ok ? 'Exact match' : 'Mismatch',
952
- passed: ok
953
- };
954
- } catch (e) {
955
- return { score: 0, label: 'error', reason: 'Failed to parse expected output as JSON', passed: false };
956
- }
957
- },
958
- };
959
-
960
- function createClient() {
961
- ${loaderSetup}
962
- const modelRegistry = createModelRegistry();
963
- ${toolsVariable}
964
- ${createClientCall}
965
- }
966
-
967
- export const client = createClient();
968
- `;
969
- };
970
-
971
- // src/utils/examples/create-example-app.ts
972
- import { fetchPromptsFrontmatter, generateTypeDefinitions } from "@agentmark-ai/shared-utils";
973
-
974
- // src/utils/conflict-resolution.ts
975
- import prompts from "prompts";
976
- function getPromptableConflicts(conflictingFiles) {
977
- return conflictingFiles.filter((file) => file.strategy === "prompt");
978
- }
979
- async function promptForSingleConflict(conflict) {
980
- const typeLabel = conflict.type === "directory" ? "directory" : "file";
981
- const { action } = await prompts({
982
- type: "select",
983
- name: "action",
984
- message: `${conflict.path} already exists. What would you like to do?`,
985
- choices: [
986
- {
987
- title: `Skip (keep existing ${typeLabel})`,
988
- value: "skip",
989
- description: `Don't modify the existing ${typeLabel}`
990
- },
991
- {
992
- title: "Overwrite",
993
- value: "overwrite",
994
- description: `Replace with new AgentMark ${typeLabel}`
995
- }
996
- ],
997
- initial: 0
998
- // Default to skip for safety
999
- });
1000
- return {
1001
- path: conflict.path,
1002
- action: action || "skip"
1003
- };
1004
- }
1005
- async function promptForResolutions(conflictingFiles) {
1006
- const promptableConflicts = getPromptableConflicts(conflictingFiles);
1007
- if (promptableConflicts.length === 0) {
1008
- return [];
1009
- }
1010
- console.log("\n\u26A0\uFE0F Found existing files that may conflict with AgentMark initialization:\n");
1011
- const resolutions = [];
1012
- for (const conflict of promptableConflicts) {
1013
- const resolution = await promptForSingleConflict(conflict);
1014
- resolutions.push(resolution);
1015
- }
1016
- console.log("");
1017
- return resolutions;
1018
- }
1019
- function getResolutionAction(filePath, resolutions, conflictingFiles) {
1020
- const userResolution = resolutions.find((r) => r.path === filePath);
1021
- if (userResolution) {
1022
- return userResolution.action;
1023
- }
1024
- const conflictFile = conflictingFiles.find((f) => f.path === filePath);
1025
- if (conflictFile) {
1026
- switch (conflictFile.strategy) {
1027
- case "skip":
1028
- return "skip";
1029
- case "merge":
1030
- return "merge";
1031
- case "append":
1032
- return "merge";
1033
- // Append is a form of merge
1034
- case "prompt":
1035
- return "skip";
1036
- }
1037
- }
1038
- return "overwrite";
1039
- }
1040
- function shouldMergeFile(filePath, projectInfo, resolutions) {
1041
- if (!projectInfo || !projectInfo.isExistingProject) {
1042
- return false;
1043
- }
1044
- const action = getResolutionAction(filePath, resolutions, projectInfo.conflictingFiles);
1045
- return action === "merge";
1046
- }
1047
- function displayProjectDetectionSummary(projectInfo) {
1048
- if (!projectInfo.isExistingProject) {
1049
- return;
1050
- }
1051
- console.log("\n\u{1F4C1} Detected existing project:");
1052
- console.log(` Type: ${projectInfo.type}`);
1053
- if (projectInfo.type === "typescript") {
1054
- console.log(` Package Manager: ${projectInfo.packageManager.name}`);
1055
- }
1056
- if (projectInfo.pythonVenv) {
1057
- console.log(` Python Venv: ${projectInfo.pythonVenv.name}`);
1058
- }
1059
- if (projectInfo.hasAgentmarkDir) {
1060
- console.log(" \u26A0\uFE0F AgentMark directory already exists");
1061
- }
1062
- console.log("");
1063
- }
1064
-
1065
- // src/utils/examples/create-example-app.ts
1066
- var setupMCPServer = (client, targetPath) => {
1067
- if (client === "skip") {
1068
- console.log("Skipping MCP server setup.");
1069
- return;
1070
- }
1071
- const folderName = targetPath;
1072
- if (client === "vscode") {
1073
- try {
1074
- console.log(`Setting up MCP server for VS Code in ${folderName}...`);
1075
- const vscodeDir = path2.join(targetPath, ".vscode");
1076
- fs4.ensureDirSync(vscodeDir);
1077
- const mcpConfig = {
1078
- servers: {
1079
- "agentmark-docs": {
1080
- url: "https://docs.agentmark.co/mcp"
1081
- }
1082
- }
1083
- };
1084
- fs4.writeJsonSync(path2.join(vscodeDir, "mcp.json"), mcpConfig, { spaces: 2 });
1085
- console.log(`\u2705 MCP server configured for VS Code in ${folderName}/.vscode/mcp.json`);
1086
- } catch (error) {
1087
- console.warn(`Warning: Could not set up MCP server for VS Code:`, error);
1088
- console.log("See https://docs.agentmark.co/agentmark/further_reference/agentmark-mcp for setup instructions.");
1089
- }
1090
- return;
1091
- }
1092
- if (client === "zed") {
1093
- try {
1094
- console.log(`Setting up MCP server for Zed in ${folderName}...`);
1095
- const zedDir = path2.join(targetPath, ".zed");
1096
- fs4.ensureDirSync(zedDir);
1097
- const zedConfig = {
1098
- context_servers: {
1099
- "agentmark-docs": {
1100
- url: "https://docs.agentmark.co/mcp"
1101
- }
1102
- }
1103
- };
1104
- fs4.writeJsonSync(path2.join(zedDir, "settings.json"), zedConfig, { spaces: 2 });
1105
- console.log(`\u2705 MCP server configured for Zed in ${folderName}/.zed/settings.json`);
1106
- } catch (error) {
1107
- console.warn(`Warning: Could not set up MCP server for Zed:`, error);
1108
- console.log("See https://docs.agentmark.co/agentmark/further_reference/agentmark-mcp for setup instructions.");
1109
- }
1110
- return;
1111
- }
1112
- if (client === "cursor") {
1113
- try {
1114
- console.log(`Setting up MCP server for Cursor in ${folderName}...`);
1115
- const cursorDir = path2.join(targetPath, ".cursor");
1116
- fs4.ensureDirSync(cursorDir);
1117
- const cursorConfig = {
1118
- mcpServers: {
1119
- "agentmark-docs": {
1120
- url: "https://docs.agentmark.co/mcp"
1121
- }
1122
- }
1123
- };
1124
- fs4.writeJsonSync(path2.join(cursorDir, "mcp.json"), cursorConfig, { spaces: 2 });
1125
- console.log(`\u2705 MCP server configured for Cursor in ${folderName}/.cursor/mcp.json`);
1126
- } catch (error) {
1127
- console.warn(`Warning: Could not set up MCP server for Cursor:`, error);
1128
- console.log("See https://docs.agentmark.co/agentmark/further_reference/agentmark-mcp for setup instructions.");
1129
- }
1130
- return;
1131
- }
1132
- if (client === "claude-code") {
1133
- try {
1134
- console.log(`Setting up MCP server for Claude Code in ${folderName}...`);
1135
- const mcpConfig = {
1136
- mcpServers: {
1137
- "agentmark-docs": {
1138
- type: "http",
1139
- url: "https://docs.agentmark.co/mcp"
1140
- }
1141
- }
1142
- };
1143
- fs4.writeJsonSync(path2.join(targetPath, ".mcp.json"), mcpConfig, { spaces: 2 });
1144
- console.log(`\u2705 MCP server configured for Claude Code in ${folderName}/.mcp.json`);
1145
- } catch (error) {
1146
- console.warn(`Warning: Could not set up MCP server for Claude Code:`, error);
1147
- console.log("See https://docs.agentmark.co/agentmark/further_reference/agentmark-mcp for setup instructions.");
1148
- }
1149
- return;
1150
- }
1151
- };
1152
- var createExampleApp = async (client, targetPath = ".", apiKey = "", adapter = "ai-sdk", deploymentMode = "cloud", projectInfo = null, resolutions = []) => {
1153
- try {
1154
- const modelProvider = adapter === "claude-agent-sdk" ? "anthropic" : "openai";
1155
- const model = adapter === "claude-agent-sdk" ? "anthropic/claude-sonnet-4-20250514" : "openai/gpt-4o";
1156
- const isExistingProject = projectInfo?.isExistingProject ?? false;
1157
- if (isExistingProject) {
1158
- console.log("Adding AgentMark to existing project...");
1159
- } else {
1160
- console.log("Creating AgentMark example app...");
1161
- }
1162
- const folderName = targetPath;
1163
- fs4.ensureDirSync(`${targetPath}/agentmark`);
1164
- setupMCPServer(client, targetPath);
1165
- const usedModels = createExamplePrompts(model, targetPath, adapter);
1166
- console.log(`\u2705 Example prompts and datasets created in ${folderName}/agentmark/`);
1167
- fs4.writeFileSync(
1168
- `${targetPath}/agentmark.client.ts`,
1169
- getClientConfigContent({ provider: modelProvider, adapter, deploymentMode })
1170
- );
1171
- const gitignoreEntries = ["node_modules/", ".env", "*.agentmark-outputs/", "dist/"];
1172
- if (shouldMergeFile(".gitignore", projectInfo, resolutions)) {
1173
- const result = appendGitignore(targetPath, gitignoreEntries);
1174
- if (result.added.length > 0) {
1175
- console.log(`\u2705 Added to .gitignore: ${result.added.join(", ")}`);
1176
- }
1177
- if (result.skipped.length > 0) {
1178
- console.log(`\u23ED\uFE0F Already in .gitignore: ${result.skipped.join(", ")}`);
1179
- }
1180
- } else {
1181
- const gitignore = gitignoreEntries.join("\n");
1182
- fs4.writeFileSync(`${targetPath}/.gitignore`, gitignore);
1183
- }
1184
- if (shouldMergeFile(".env", projectInfo, resolutions)) {
1185
- const envVars = {};
1186
- const apiKeyEnvVar = adapter === "claude-agent-sdk" ? "ANTHROPIC_API_KEY" : "OPENAI_API_KEY";
1187
- if (apiKey) {
1188
- envVars[apiKeyEnvVar] = apiKey;
1189
- } else {
1190
- envVars[apiKeyEnvVar] = adapter === "claude-agent-sdk" ? "your-anthropic-api-key" : "your-openai-api-key";
1191
- }
1192
- if (deploymentMode === "cloud") {
1193
- envVars["AGENTMARK_API_KEY"] = "your_agentmark_api_key";
1194
- envVars["AGENTMARK_APP_ID"] = "your_agentmark_app_id";
1195
- }
1196
- const result = appendEnv(targetPath, envVars);
1197
- if (result.added.length > 0) {
1198
- console.log(`\u2705 Added to .env: ${result.added.join(", ")}`);
1199
- }
1200
- if (result.skipped.length > 0) {
1201
- console.log(`\u23ED\uFE0F Skipped existing .env vars: ${result.skipped.join(", ")}`);
1202
- }
1203
- } else {
1204
- fs4.writeFileSync(`${targetPath}/.env`, getEnvFileContent(modelProvider, apiKey, adapter, deploymentMode));
1205
- }
1206
- if (!isExistingProject) {
1207
- fs4.writeFileSync(
1208
- `${targetPath}/index.ts`,
1209
- getIndexFileContent(adapter, deploymentMode)
1210
- );
1211
- } else {
1212
- console.log("\u23ED\uFE0F Skipped index.ts (existing project)");
1213
- }
1214
- if (!isExistingProject) {
1215
- fs4.writeJsonSync(`${targetPath}/tsconfig.json`, getTsConfigContent(), { spaces: 2 });
1216
- } else {
1217
- console.log("\u23ED\uFE0F Skipped tsconfig.json (existing project)");
1218
- }
1219
- const packageManager = projectInfo?.packageManager ?? null;
1220
- setupPackageJson(targetPath, deploymentMode, projectInfo);
1221
- installDependencies(modelProvider, targetPath, adapter, deploymentMode, packageManager);
1222
- console.log("Generating types from prompts...");
1223
- try {
1224
- const agentmarkDir = path2.join(targetPath, "agentmark");
1225
- const prompts3 = await fetchPromptsFrontmatter({ rootDir: agentmarkDir });
1226
- const typeDefinitions = await generateTypeDefinitions(prompts3);
1227
- fs4.writeFileSync(`${targetPath}/agentmark.types.ts`, typeDefinitions);
1228
- } catch (error) {
1229
- console.warn("Warning: Could not generate types automatically:", error);
1230
- console.log("You can generate types later by running: npx agentmark generate-types --root-dir agentmark");
1231
- fs4.writeFileSync(`${targetPath}/agentmark.types.ts`, `// Auto-generated types from AgentMark
1232
- // Run 'npx agentmark generate-types --root-dir agentmark' to generate types
1233
- export default interface AgentmarkTypes {}
1234
- `);
1235
- }
1236
- if (deploymentMode === "cloud") {
1237
- const handlerAdapterConfig = getAdapterConfig(adapter, modelProvider);
1238
- const { webhookHandler: handlerClass } = handlerAdapterConfig.classes;
1239
- const handlerContent = `import { ${handlerClass} } from '${handlerAdapterConfig.package}/runner';
1240
- import { AgentMarkSDK } from '@agentmark-ai/sdk';
1241
- import { client } from './agentmark.client';
1242
-
1243
- // Initialize tracing \u2014 sends traces to AgentMark Cloud
1244
- const sdk = new AgentMarkSDK({
1245
- apiKey: process.env.AGENTMARK_API_KEY ?? '',
1246
- appId: process.env.AGENTMARK_APP_ID ?? '',
1247
- baseUrl: process.env.AGENTMARK_BASE_URL,
1248
- });
1249
- sdk.initTracing({ disableBatch: true });
1250
-
1251
- const adapter = new ${handlerClass}(client as any);
1252
-
1253
- export default async function handler(request: {
1254
- type: 'prompt-run' | 'dataset-run' | 'get-evals';
1255
- data: {
1256
- ast?: any;
1257
- customProps?: Record<string, unknown>;
1258
- options?: { shouldStream?: boolean };
1259
- experimentId?: string;
1260
- datasetPath?: string;
1261
- };
1262
- }) {
1263
- if (request.type === 'get-evals') {
1264
- return {
1265
- type: 'evals',
1266
- result: JSON.stringify(Object.keys(client.getEvalRegistry())),
1267
- traceId: '',
1268
- };
1269
- }
1270
-
1271
- if (request.type === 'prompt-run') {
1272
- return adapter.runPrompt(request.data.ast, {
1273
- shouldStream: request.data.options?.shouldStream,
1274
- customProps: request.data.customProps,
1275
- });
1276
- }
1277
-
1278
- if (request.type === 'dataset-run') {
1279
- return adapter.runExperiment(
1280
- request.data.ast,
1281
- request.data.experimentId ?? '',
1282
- request.data.datasetPath,
1283
- );
1284
- }
1285
-
1286
- throw new Error(\`Unknown request type: \${request.type}\`);
1287
- }
1288
- `;
1289
- const handlerPath = path2.join(targetPath, "handler.ts");
1290
- if (fs4.existsSync(handlerPath)) {
1291
- console.log("\u23ED\uFE0F Skipped handler.ts (already exists - preserving customizations)");
1292
- } else {
1293
- fs4.writeFileSync(handlerPath, handlerContent);
1294
- console.log(`\u2705 Created handler.ts for cloud deployment`);
1295
- }
1296
- }
1297
- console.log("Creating development server entry point...");
1298
- const adapterConfig = getAdapterConfig(adapter, modelProvider);
1299
- const { webhookHandler } = adapterConfig.classes;
1300
- const devEntryPath = path2.join(targetPath, "dev-entry.ts");
1301
- const devEntryContent = `// Development webhook server entry point
1302
- // This file is version controlled - customize as needed for your project
1303
-
1304
- import { createWebhookServer } from '@agentmark-ai/cli/runner-server';
1305
- import { ${webhookHandler} } from '${adapterConfig.package}/runner';
1306
- import { AgentMarkSDK } from '@agentmark-ai/sdk';
1307
- import path from 'path';
1308
-
1309
- async function main() {
1310
- const args = process.argv.slice(2);
1311
- const webhookPortArg = args.find(arg => arg.startsWith('--webhook-port='));
1312
- const apiServerPortArg = args.find(arg => arg.startsWith('--api-server-port='));
1313
-
1314
- const webhookPort = webhookPortArg ? parseInt(webhookPortArg.split('=')[1]) : 9417;
1315
- const apiServerPort = apiServerPortArg ? parseInt(apiServerPortArg.split('=')[1]) : 9418;
1316
- const apiServerUrl = \`http://localhost:\${apiServerPort}\`;
1317
-
1318
- // Set environment for development mode before importing client
1319
- process.env.NODE_ENV = 'development';
1320
- process.env.AGENTMARK_BASE_URL = apiServerUrl;
1321
-
1322
- // Now import client - it will pick up the dev environment
1323
- const { client } = await import('./agentmark.client.js');
1324
-
1325
- // Initialize OpenTelemetry tracing to export traces to the API server
1326
- const sdk = new AgentMarkSDK({
1327
- apiKey: '',
1328
- appId: '',
1329
- baseUrl: apiServerUrl,
1330
- });
1331
- sdk.initTracing({ disableBatch: true });
1332
-
1333
- const handler = new ${webhookHandler}(client as any);
1334
- const templatesDirectory = path.join(process.cwd(), 'agentmark');
1335
-
1336
- await createWebhookServer({
1337
- port: webhookPort,
1338
- handler,
1339
- apiServerUrl,
1340
- templatesDirectory
1341
- });
1342
- }
1343
-
1344
- main().catch((err) => {
1345
- console.error(err);
1346
- process.exit(1);
1347
- });
1348
- `;
1349
- if (fs4.existsSync(devEntryPath)) {
1350
- console.log("\u23ED\uFE0F Skipped dev-entry.ts (already exists - preserving customizations)");
1351
- } else {
1352
- fs4.writeFileSync(devEntryPath, devEntryContent);
1353
- console.log(`\u2705 Created dev-entry.ts at project root`);
1354
- }
1355
- const { installAgentmarkSkill: installAgentmarkSkill2 } = await Promise.resolve().then(() => (init_install_skill(), install_skill_exports));
1356
- installAgentmarkSkill2(targetPath);
1357
- console.log("\n\u2705 Agentmark initialization completed successfully!");
1358
- console.log(
1359
- `
1360
- \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557
1361
- \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2554\u255D
1362
- \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2554\u255D
1363
- \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2588\u2588\u2557
1364
- \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2557
1365
- \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D
1366
-
1367
- `
1368
- );
1369
- console.log("\n" + "\u2550".repeat(70));
1370
- console.log("Next Steps");
1371
- console.log("\u2550".repeat(70));
1372
- console.log("\n Get Started:");
1373
- if (folderName !== "." && folderName !== "./" && !isExistingProject) {
1374
- console.log(` $ cd ${folderName}`);
1375
- }
1376
- console.log(` $ npx agentmark dev
1377
- `);
1378
- console.log("\u2500".repeat(70));
1379
- console.log("Resources");
1380
- console.log("\u2500".repeat(70));
1381
- console.log(" Documentation: https://docs.agentmark.co");
1382
- console.log("\u2550".repeat(70) + "\n");
1383
- return usedModels;
1384
- } catch (error) {
1385
- console.error("Error creating example app:", error);
1386
- throw error;
1387
- }
1388
- };
1389
2
 
1390
- // src/utils/examples/create-python-app.ts
1391
- import fs5 from "fs-extra";
1392
- import * as path3 from "path";
1393
- var setupMCPServer2 = (client, targetPath) => {
1394
- if (client === "skip") {
1395
- console.log("Skipping MCP server setup.");
1396
- return;
3
+ // src/index.ts
4
+ import fs3 from "fs-extra";
5
+ import path3 from "path";
6
+ import prompts from "prompts";
7
+ import { pathToFileURL, fileURLToPath } from "url";
8
+
9
+ // src/utils/examples/mcp-config.ts
10
+ import fs from "fs-extra";
11
+ import * as path from "path";
12
+ var CLOUD_API_URL = "https://api.agentmark.co";
13
+ var LOCAL_DEV_URL = "http://localhost:9418";
14
+ var MCP_SERVER_PACKAGE = "@agentmark-ai/mcp-server";
15
+ function stdioEntry(apiUrl, includeType) {
16
+ const entry = {
17
+ command: "npx",
18
+ args: ["-y", MCP_SERVER_PACKAGE]
19
+ };
20
+ if (apiUrl !== CLOUD_API_URL) {
21
+ entry.env = { AGENTMARK_API_URL: apiUrl };
1397
22
  }
1398
- const folderName = targetPath;
23
+ if (includeType) entry.type = "stdio";
24
+ return entry;
25
+ }
26
+ function writeMcpConfig(client, targetPath, opts = {}) {
27
+ if (client === "skip") return null;
28
+ const cloudUrl = opts.customApiUrl ?? CLOUD_API_URL;
29
+ const docsEntry = { url: "https://docs.agentmark.co/mcp" };
1399
30
  if (client === "vscode") {
1400
- try {
1401
- console.log(`Setting up MCP server for VS Code in ${folderName}...`);
1402
- const vscodeDir = path3.join(targetPath, ".vscode");
1403
- fs5.ensureDirSync(vscodeDir);
1404
- const mcpConfig = {
1405
- servers: {
1406
- "agentmark-docs": {
1407
- url: "https://docs.agentmark.co/mcp"
1408
- }
1409
- }
1410
- };
1411
- fs5.writeJsonSync(path3.join(vscodeDir, "mcp.json"), mcpConfig, { spaces: 2 });
1412
- console.log(`MCP server configured for VS Code in ${folderName}/.vscode/mcp.json`);
1413
- } catch (error) {
1414
- console.warn(`Warning: Could not set up MCP server for VS Code:`, error);
1415
- }
1416
- return;
31
+ const vscodeDir = path.join(targetPath, ".vscode");
32
+ fs.ensureDirSync(vscodeDir);
33
+ const configPath = path.join(vscodeDir, "mcp.json");
34
+ const config = {
35
+ servers: {
36
+ "agentmark-docs": docsEntry,
37
+ "agentmark": stdioEntry(
38
+ cloudUrl,
39
+ /* includeType */
40
+ false
41
+ ),
42
+ "agentmark-local": stdioEntry(
43
+ LOCAL_DEV_URL,
44
+ /* includeType */
45
+ false
46
+ )
47
+ }
48
+ };
49
+ fs.writeJsonSync(configPath, config, { spaces: 2 });
50
+ return { configPath };
1417
51
  }
1418
52
  if (client === "zed") {
1419
- try {
1420
- console.log(`Setting up MCP server for Zed in ${folderName}...`);
1421
- const zedDir = path3.join(targetPath, ".zed");
1422
- fs5.ensureDirSync(zedDir);
1423
- const zedConfig = {
1424
- context_servers: {
1425
- "agentmark-docs": {
1426
- url: "https://docs.agentmark.co/mcp"
1427
- }
1428
- }
1429
- };
1430
- fs5.writeJsonSync(path3.join(zedDir, "settings.json"), zedConfig, { spaces: 2 });
1431
- console.log(`MCP server configured for Zed in ${folderName}/.zed/settings.json`);
1432
- } catch (error) {
1433
- console.warn(`Warning: Could not set up MCP server for Zed:`, error);
1434
- }
1435
- return;
53
+ const zedDir = path.join(targetPath, ".zed");
54
+ fs.ensureDirSync(zedDir);
55
+ const configPath = path.join(zedDir, "settings.json");
56
+ const config = {
57
+ context_servers: {
58
+ "agentmark-docs": docsEntry,
59
+ "agentmark": stdioEntry(
60
+ cloudUrl,
61
+ /* includeType */
62
+ false
63
+ ),
64
+ "agentmark-local": stdioEntry(
65
+ LOCAL_DEV_URL,
66
+ /* includeType */
67
+ false
68
+ )
69
+ }
70
+ };
71
+ fs.writeJsonSync(configPath, config, { spaces: 2 });
72
+ return { configPath };
1436
73
  }
1437
74
  if (client === "cursor") {
1438
- try {
1439
- console.log(`Setting up MCP server for Cursor in ${folderName}...`);
1440
- const cursorDir = path3.join(targetPath, ".cursor");
1441
- fs5.ensureDirSync(cursorDir);
1442
- const cursorConfig = {
1443
- mcpServers: {
1444
- "agentmark-docs": {
1445
- url: "https://docs.agentmark.co/mcp"
1446
- }
1447
- }
1448
- };
1449
- fs5.writeJsonSync(path3.join(cursorDir, "mcp.json"), cursorConfig, { spaces: 2 });
1450
- console.log(`MCP server configured for Cursor in ${folderName}/.cursor/mcp.json`);
1451
- } catch (error) {
1452
- console.warn(`Warning: Could not set up MCP server for Cursor:`, error);
1453
- }
1454
- return;
75
+ const cursorDir = path.join(targetPath, ".cursor");
76
+ fs.ensureDirSync(cursorDir);
77
+ const configPath = path.join(cursorDir, "mcp.json");
78
+ const config = {
79
+ mcpServers: {
80
+ "agentmark-docs": docsEntry,
81
+ "agentmark": stdioEntry(
82
+ cloudUrl,
83
+ /* includeType */
84
+ false
85
+ ),
86
+ "agentmark-local": stdioEntry(
87
+ LOCAL_DEV_URL,
88
+ /* includeType */
89
+ false
90
+ )
91
+ }
92
+ };
93
+ fs.writeJsonSync(configPath, config, { spaces: 2 });
94
+ return { configPath };
1455
95
  }
1456
96
  if (client === "claude-code") {
1457
- try {
1458
- console.log(`Setting up MCP server for Claude Code in ${folderName}...`);
1459
- const mcpConfig = {
1460
- mcpServers: {
1461
- "agentmark-docs": {
1462
- type: "http",
1463
- url: "https://docs.agentmark.co/mcp"
1464
- }
1465
- }
1466
- };
1467
- fs5.writeJsonSync(path3.join(targetPath, ".mcp.json"), mcpConfig, { spaces: 2 });
1468
- console.log(`MCP server configured for Claude Code in ${folderName}/.mcp.json`);
1469
- } catch (error) {
1470
- console.warn(`Warning: Could not set up MCP server for Claude Code:`, error);
1471
- }
1472
- return;
1473
- }
1474
- };
1475
- var getPyprojectContent = (projectName, adapter, deploymentMode) => {
1476
- const pyModules = deploymentMode === "cloud" ? `["agentmark_client", "main", "handler"]` : `["agentmark_client", "main"]`;
1477
- if (adapter === "claude-agent-sdk") {
1478
- return `[project]
1479
- name = "${projectName}"
1480
- version = "0.1.0"
1481
- description = "An AgentMark application using Claude Agent SDK"
1482
- requires-python = ">=3.12"
1483
- dependencies = [
1484
- "agentmark-sdk>=0.2.0",
1485
- "agentmark-claude-agent-sdk-v0>=0.1.4",
1486
- "agentmark-prompt-core>=0.1.2",
1487
- "python-dotenv>=1.0.0",
1488
- "claude-agent-sdk>=0.1.0",
1489
- ]
1490
-
1491
- [project.optional-dependencies]
1492
- dev = [
1493
- "pytest>=7.0",
1494
- "pytest-asyncio>=0.21",
1495
- "mypy>=1.0",
1496
- ]
1497
-
1498
- [build-system]
1499
- requires = ["setuptools>=61", "wheel"]
1500
- build-backend = "setuptools.build_meta"
1501
-
1502
- [tool.setuptools]
1503
- py-modules = ${pyModules}
1504
-
1505
- [tool.pytest.ini_options]
1506
- asyncio_mode = "auto"
1507
-
1508
- [tool.mypy]
1509
- strict = true
1510
- `;
1511
- }
1512
- return `[project]
1513
- name = "${projectName}"
1514
- version = "0.1.0"
1515
- description = "An AgentMark application using Pydantic AI"
1516
- requires-python = ">=3.12"
1517
- dependencies = [
1518
- "agentmark-sdk>=0.2.0",
1519
- "agentmark-pydantic-ai-v0>=0.1.4",
1520
- "agentmark-prompt-core>=0.1.2",
1521
- "python-dotenv>=1.0.0",
1522
- "pydantic-ai-slim[openai]>=1.0,<2.0",
1523
- ]
1524
-
1525
- [project.optional-dependencies]
1526
- dev = [
1527
- "pytest>=7.0",
1528
- "pytest-asyncio>=0.21",
1529
- "mypy>=1.0",
1530
- ]
1531
-
1532
- [build-system]
1533
- requires = ["setuptools>=61", "wheel"]
1534
- build-backend = "setuptools.build_meta"
1535
-
1536
- [tool.setuptools]
1537
- py-modules = ${pyModules}
1538
-
1539
- [tool.pytest.ini_options]
1540
- asyncio_mode = "auto"
1541
-
1542
- [tool.mypy]
1543
- strict = true
1544
- `;
1545
- };
1546
- var getHandlerPyContent = (adapter) => {
1547
- const webhookClass = adapter === "claude-agent-sdk" ? "ClaudeAgentWebhookHandler" : "PydanticAIWebhookHandler";
1548
- const webhookImport = adapter === "claude-agent-sdk" ? "from agentmark_claude_agent_sdk_v0 import ClaudeAgentWebhookHandler" : "from agentmark_pydantic_ai_v0 import PydanticAIWebhookHandler";
1549
- return `"""AgentMark handler for managed cloud deployments.
1550
-
1551
- This file is used by the AgentMark platform to execute prompts and experiments
1552
- on deployed infrastructure. It mirrors the TypeScript handler.ts pattern.
1553
- """
1554
-
1555
- import os
1556
-
1557
- from agentmark_sdk import AgentMarkSDK
1558
- ${webhookImport}
1559
- from agentmark_client import client
1560
-
1561
- # Initialize tracing
1562
- sdk = AgentMarkSDK(
1563
- api_key=os.environ.get("AGENTMARK_API_KEY", ""),
1564
- app_id=os.environ.get("AGENTMARK_APP_ID", ""),
1565
- base_url=os.environ.get("AGENTMARK_BASE_URL"),
1566
- )
1567
- sdk.init_tracing(disable_batch=True)
1568
-
1569
- adapter = ${webhookClass}(client)
1570
-
1571
-
1572
- async def handler(request: dict):
1573
- """Handle prompt-run, dataset-run, and get-evals requests from the platform."""
1574
- req_type = request.get("type")
1575
- data = request.get("data", {})
1576
-
1577
- if req_type == "get-evals":
1578
- import json
1579
- return {
1580
- "type": "evals",
1581
- "result": json.dumps(list(client.get_eval_registry().keys())),
1582
- "traceId": "",
1583
- }
1584
-
1585
- if req_type == "prompt-run":
1586
- return await adapter.run_prompt(data["ast"], {
1587
- "shouldStream": data.get("options", {}).get("shouldStream", True),
1588
- "customProps": data.get("customProps"),
1589
- })
1590
-
1591
- if req_type == "dataset-run":
1592
- return await adapter.run_experiment(
1593
- data["ast"],
1594
- data.get("experimentId", ""),
1595
- data.get("datasetPath"),
97
+ const configPath = path.join(targetPath, ".mcp.json");
98
+ const config = {
99
+ mcpServers: {
100
+ "agentmark-docs": { type: "http", ...docsEntry },
101
+ "agentmark": stdioEntry(
102
+ cloudUrl,
103
+ /* includeType */
104
+ true
105
+ ),
106
+ "agentmark-local": stdioEntry(
107
+ LOCAL_DEV_URL,
108
+ /* includeType */
109
+ true
1596
110
  )
1597
-
1598
- raise ValueError(f"Unknown request type: {req_type}")
1599
- `;
1600
- };
1601
- var getAgentmarkClientContent = (deploymentMode, adapter) => {
1602
- const isCloud = deploymentMode === "cloud";
1603
- const loaderImport = isCloud ? `from agentmark.prompt_core import ApiLoader` : `from agentmark.prompt_core import FileLoader`;
1604
- const loaderSetup = isCloud ? `# API loader for cloud deployment \u2014 fetches datasets from the AgentMark gateway
1605
- loader = ApiLoader.cloud()` : `# File loader for local development \u2014 reads pre-built prompts from the build output directory
1606
- loader = FileLoader("./dist/agentmark")`;
1607
- if (adapter === "claude-agent-sdk") {
1608
- return `"""AgentMark client configuration.
1609
-
1610
- This file configures the AgentMark client with Claude Agent SDK adapter.
1611
- Customize the model registry and eval registry as needed.
1612
- """
1613
-
1614
- import json
1615
- import os
1616
- from dotenv import load_dotenv
1617
-
1618
- ${loaderImport}
1619
- from agentmark.prompt_core import EvalRegistry
1620
- from agentmark_claude_agent_sdk_v0 import (
1621
- create_claude_agent_client,
1622
- ClaudeAgentModelRegistry,
1623
- )
1624
-
1625
- # Load environment variables
1626
- load_dotenv()
1627
-
1628
- # Register the model providers your prompts use.
1629
- # This maps "anthropic/claude-sonnet-4-20250514" in prompt files to the Claude Agent SDK.
1630
- model_registry = ClaudeAgentModelRegistry()
1631
- model_registry.register_providers({
1632
- "anthropic": "anthropic",
1633
- })
1634
-
1635
-
1636
- # Evaluation functions \u2014 used by experiments to score model outputs
1637
- def exact_match_json(params):
1638
- """Check if output matches expected output exactly."""
1639
- output = params.get("output")
1640
- expected_output = params.get("expectedOutput")
1641
- if not expected_output:
1642
- return {"score": 0, "label": "error", "reason": "No expected output provided", "passed": False}
1643
- try:
1644
- actual = json.loads(output) if isinstance(output, str) else output
1645
- expected = json.loads(expected_output) if isinstance(expected_output, str) else expected_output
1646
- ok = actual == expected
1647
- return {
1648
- "score": 1 if ok else 0,
1649
- "label": "correct" if ok else "incorrect",
1650
- "reason": "Exact match" if ok else "Mismatch",
1651
- "passed": ok,
1652
- }
1653
- except (json.JSONDecodeError, TypeError):
1654
- return {"score": 0, "label": "error", "reason": "Failed to parse JSON", "passed": False}
1655
-
1656
- evals: EvalRegistry = {
1657
- "exact_match_json": exact_match_json,
1658
- }
1659
-
1660
- ${loaderSetup}
1661
-
1662
- # Create the client
1663
- # Claude Agent SDK handles tools natively through the SDK
1664
- client = create_claude_agent_client(
1665
- model_registry=model_registry,
1666
- evals=evals,
1667
- loader=loader,
1668
- )
1669
-
1670
- __all__ = ["client"]
1671
- `;
111
+ }
112
+ };
113
+ fs.writeJsonSync(configPath, config, { spaces: 2 });
114
+ return { configPath };
1672
115
  }
1673
- return `"""AgentMark client configuration.
1674
-
1675
- This file configures the AgentMark client with Pydantic AI adapter.
1676
- Customize the model registry, tools, and eval registry as needed.
1677
- """
1678
-
1679
- import json
1680
- import os
1681
- from dotenv import load_dotenv
1682
-
1683
- ${loaderImport}
1684
- from agentmark.prompt_core import EvalRegistry
1685
- from agentmark_pydantic_ai_v0 import (
1686
- create_pydantic_ai_client,
1687
- PydanticAIModelRegistry,
1688
- )
1689
-
1690
- # Load environment variables
1691
- load_dotenv()
1692
-
1693
- # Register the model providers your prompts use.
1694
- # This maps "openai/gpt-4o" in prompt files to "openai:gpt-4o" for Pydantic AI.
1695
- model_registry = PydanticAIModelRegistry()
1696
- model_registry.register_providers({
1697
- "openai": "openai",
1698
- "anthropic": "anthropic",
1699
- })
1700
-
1701
- # Define tools as native pydantic-ai Tool objects or callables
1702
- # Example:
1703
- # def search(query: str) -> str:
1704
- # return f"Search results for: {query}"
1705
- # tools = [search]
1706
- tools = []
1707
-
1708
-
1709
- # Evaluation functions \u2014 used by experiments to score model outputs
1710
- def exact_match_json(params):
1711
- """Check if output matches expected output exactly."""
1712
- output = params.get("output")
1713
- expected_output = params.get("expectedOutput")
1714
- if not expected_output:
1715
- return {"score": 0, "label": "error", "reason": "No expected output provided", "passed": False}
1716
- try:
1717
- actual = json.loads(output) if isinstance(output, str) else output
1718
- expected = json.loads(expected_output) if isinstance(expected_output, str) else expected_output
1719
- ok = actual == expected
1720
- return {
1721
- "score": 1 if ok else 0,
1722
- "label": "correct" if ok else "incorrect",
1723
- "reason": "Exact match" if ok else "Mismatch",
1724
- "passed": ok,
1725
- }
1726
- except (json.JSONDecodeError, TypeError):
1727
- return {"score": 0, "label": "error", "reason": "Failed to parse JSON", "passed": False}
1728
-
1729
- evals: EvalRegistry = {
1730
- "exact_match_json": exact_match_json,
116
+ return null;
1731
117
  }
1732
118
 
1733
- ${loaderSetup}
1734
-
1735
- # Create the client
1736
- client = create_pydantic_ai_client(
1737
- model_registry=model_registry,
1738
- tools=tools,
1739
- evals=evals,
1740
- loader=loader,
1741
- )
1742
-
1743
- __all__ = ["client"]
1744
- `;
1745
- };
1746
- var getMainPyContent = (adapter, deploymentMode = "cloud") => {
1747
- const isCloud = deploymentMode === "cloud";
1748
- const cloudTracingInit = `
1749
- # Initialize tracing - traces will be sent to AgentMark Cloud
1750
- # To disable tracing, comment out sdk.init_tracing() below
1751
- sdk = AgentMarkSDK(
1752
- api_key=os.environ.get("AGENTMARK_API_KEY", ""),
1753
- app_id=os.environ.get("AGENTMARK_APP_ID", ""),
1754
- )
1755
- sdk.init_tracing(disable_batch=True)
1756
- `;
1757
- const staticTracingInit = `
1758
- # Initialize tracing - traces will be sent to local dev server
1759
- # Make sure to run "npx agentmark dev" in another terminal first
1760
- # To disable tracing, comment out sdk.init_tracing() below
1761
- sdk = AgentMarkSDK(
1762
- api_key="",
1763
- app_id="",
1764
- base_url="http://localhost:9418",
1765
- )
1766
- sdk.init_tracing(disable_batch=True)
1767
- `;
1768
- const tracingInit = isCloud ? cloudTracingInit : staticTracingInit;
1769
- if (adapter === "claude-agent-sdk") {
1770
- return `"""Example usage of AgentMark with Claude Agent SDK.
1771
-
1772
- Run with:
1773
- npx agentmark build # compile party-planner.prompt.mdx -> dist/agentmark/*.json
1774
- python main.py
1775
- """
1776
-
1777
- import asyncio
1778
- import os
1779
-
1780
- from agentmark_sdk import AgentMarkSDK
1781
- from agentmark_claude_agent_sdk_v0 import traced_query
1782
- from agentmark_client import client
1783
- ${tracingInit}
1784
-
1785
- async def main():
1786
- """Run the party planner prompt (object_config: extracts attendee names)."""
1787
- # \`agentmark build\` writes pre-compiled prompts to dist/agentmark/.
1788
- # The FileLoader reads them by name \u2014 extension is optional.
1789
- try:
1790
- prompt = await client.load_object_prompt("party-planner.prompt.mdx")
1791
- except FileNotFoundError:
1792
- print("Pre-built prompt not found. Run 'npx agentmark build' first.")
1793
- return
1794
-
1795
- adapted = await prompt.format(props={
1796
- "party_text": "We're having a party with Alice, Bob, and Carol.",
1797
- })
1798
-
1799
- # Execute via Claude Agent SDK (streamed) with automatic OTEL tracing.
1800
- # adapted.query.options.output_format is set to the object schema.
1801
- print("Running party planner prompt...")
1802
- print("=" * 50)
1803
- async for message in traced_query(adapted):
1804
- print(message)
1805
- print("=" * 50)
1806
-
1807
-
1808
- if __name__ == "__main__":
1809
- asyncio.run(main())
1810
- `;
1811
- }
1812
- return `"""Example usage of AgentMark with Pydantic AI.
1813
-
1814
- Run with:
1815
- npx agentmark build # compile party-planner.prompt.mdx -> dist/agentmark/*.json
1816
- python main.py
1817
- """
1818
- # To use a different LLM provider, install: pip install "pydantic-ai-slim[anthropic]" (or [google], [bedrock], etc.)
1819
-
1820
- import asyncio
1821
- import os
1822
-
1823
- from agentmark_sdk import AgentMarkSDK
1824
- from agentmark_pydantic_ai_v0 import run_object_prompt
1825
- from agentmark_client import client
1826
- ${tracingInit}
1827
-
1828
- async def main():
1829
- """Run the party planner prompt (object_config: extracts attendee names)."""
1830
- # \`agentmark build\` writes pre-compiled prompts to dist/agentmark/.
1831
- # The FileLoader reads them by name \u2014 extension is optional, and it
1832
- # extracts the inner AST from the { ast, metadata } wrapper for you.
1833
- try:
1834
- prompt = await client.load_object_prompt("party-planner.prompt.mdx")
1835
- except FileNotFoundError:
1836
- print("Pre-built prompt not found. Run 'npx agentmark build' first.")
1837
- return
1838
-
1839
- params = await prompt.format(props={
1840
- "party_text": "We're having a party with Alice, Bob, and Carol.",
1841
- })
1842
-
1843
- # Execute the prompt
1844
- print("Running party planner prompt...")
1845
- result = await run_object_prompt(params)
1846
-
1847
- print("\\n" + "=" * 50)
1848
- print("Extracted attendees:")
1849
- print("=" * 50)
1850
- # result.output is a Pydantic model instance with the schema's fields
1851
- print(result.output.names)
1852
- print("\\n" + "-" * 50)
1853
- print(f"Tokens used: {result.usage.total_tokens}")
1854
-
1855
-
1856
- if __name__ == "__main__":
1857
- asyncio.run(main())
1858
- `;
1859
- };
1860
- var getDevServerContent = (adapter) => {
1861
- const adapterPackage = adapter === "claude-agent-sdk" ? "agentmark_claude_agent_sdk_v0" : "agentmark_pydantic_ai_v0";
1862
- return `"""Auto-generated webhook server for AgentMark development.
1863
-
1864
- This server is started by 'npx agentmark dev' (agentmark dev) and handles
1865
- prompt execution requests from the CLI.
1866
- """
1867
-
1868
- import argparse
1869
- import sys
1870
- from pathlib import Path
1871
-
1872
- # Add parent directory to path for imports
1873
- sys.path.insert(0, str(Path(__file__).parent.parent))
1874
-
1875
- from ${adapterPackage} import create_webhook_server
1876
- from agentmark_client import client
1877
-
1878
-
1879
- if __name__ == "__main__":
1880
- parser = argparse.ArgumentParser()
1881
- parser.add_argument("--webhook-port", type=int, default=9417)
1882
- parser.add_argument("--api-server-port", type=int, default=9418)
1883
- args = parser.parse_args()
1884
-
1885
- create_webhook_server(client, args.webhook_port, args.api_server_port)
1886
- `;
1887
- };
1888
- var getEnvContent = (apiKey, adapter) => {
1889
- if (adapter === "claude-agent-sdk") {
1890
- return `# Anthropic API Key
1891
- ANTHROPIC_API_KEY=${apiKey}
1892
- `;
119
+ // src/utils/install-skill.ts
120
+ import { execFileSync } from "child_process";
121
+ var shouldSkip = () => process.env.VITEST === "true" || process.env.NODE_ENV === "test" || process.env.AGENTMARK_SKIP_SKILL_INSTALL === "1";
122
+ var installAgentmarkSkill = (targetPath) => {
123
+ if (shouldSkip()) {
124
+ console.log("\n\u23ED\uFE0F Skipping agent skill install (test environment detected).");
125
+ return;
1893
126
  }
1894
- return `# OpenAI API Key
1895
- OPENAI_API_KEY=${apiKey}
1896
-
1897
- # For Anthropic models, add:
1898
- # ANTHROPIC_API_KEY=your-key-here
1899
-
1900
- # For Google Gemini models, add:
1901
- # GOOGLE_API_KEY=your-key-here
1902
- `;
1903
- };
1904
- var getReadmeContent = (projectName, adapter) => {
1905
- const adapterName = adapter === "claude-agent-sdk" ? "Claude Agent SDK" : "Pydantic AI";
1906
- const apiKeyEnvVar = adapter === "claude-agent-sdk" ? "ANTHROPIC_API_KEY" : "OPENAI_API_KEY";
1907
- const directInstallCmd = adapter === "claude-agent-sdk" ? "pip install agentmark-sdk agentmark-claude-agent-sdk-v0 agentmark-prompt-core python-dotenv claude-agent-sdk" : 'pip install agentmark-sdk agentmark-pydantic-ai-v0 agentmark-prompt-core python-dotenv "pydantic-ai-slim[openai]>=1.0,<2.0"';
1908
- return `# ${projectName}
1909
-
1910
- An AgentMark application using ${adapterName}.
1911
-
1912
- ## Prerequisites
1913
-
1914
- - Python 3.12+
1915
- - **pip 26.1+** (older pip versions fail to resolve the dependency graph \u2014 see "Why pip 26.1?" below)
1916
-
1917
- ## Setup
1918
-
1919
- \`\`\`bash
1920
- # 1. Create and activate a virtual environment
1921
- python -m venv .venv
1922
- source .venv/bin/activate # On Windows: .venv\\Scripts\\activate
1923
-
1924
- # 2. Upgrade pip (REQUIRED \u2014 older pip cannot resolve pydantic-ai's transitive graph)
1925
- python -m pip install --upgrade "pip>=26.1"
1926
-
1927
- # 3. Install dependencies
1928
- ${directInstallCmd}
1929
-
1930
- # 4. Set your API key
1931
- echo "${apiKeyEnvVar}=your-key-here" > .env
1932
- \`\`\`
1933
-
1934
- ## Run
1935
-
1936
- \`\`\`bash
1937
- # Start the AgentMark dev server (in another terminal)
1938
- npx agentmark dev
1939
-
1940
- # Run the example prompt
1941
- python main.py
1942
- \`\`\`
1943
-
1944
- Then open [http://localhost:9418](http://localhost:9418) to view your traces.
1945
-
1946
- ## Why pip 26.1?
1947
-
1948
- The \`pydantic-ai-slim\` package transitively depends on \`mcp\`, \`fastmcp\`, and
1949
- \`logfire\`, which together produce a deep dependency graph. Pip versions before
1950
- 26.1 fall into long backtracking loops and abort with \`resolution-too-deep\`.
1951
- Pip 26.1's resolver handles this graph efficiently. If you skip the upgrade and
1952
- hit the error, run \`python -m pip install --upgrade pip\` and retry.
1953
-
1954
- ## Resources
1955
-
1956
- - [Documentation](https://docs.agentmark.co)
1957
- - [GitHub](https://github.com/agentmark-ai/agentmark)
1958
- `;
1959
- };
1960
- var getGitignoreContent = () => {
1961
- return `# Python
1962
- __pycache__/
1963
- *.py[cod]
1964
- *$py.class
1965
- .venv/
1966
- venv/
1967
- .env
1968
-
1969
- # AgentMark
1970
- *.agentmark-outputs/
1971
- .agentmark/
1972
-
1973
- # IDE
1974
- .idea/
1975
- .vscode/
1976
- *.swp
1977
-
1978
- # Build
1979
- dist/
1980
- build/
1981
- *.egg-info/
1982
-
1983
- # Testing
1984
- .pytest_cache/
1985
- .coverage
1986
- htmlcov/
1987
- `;
1988
- };
1989
- var createPythonApp = async (client, targetPath = ".", apiKey = "", deploymentMode = "cloud", adapter = "pydantic-ai", projectInfo = null, resolutions = []) => {
1990
127
  try {
1991
- const model = adapter === "claude-agent-sdk" ? "anthropic/claude-sonnet-4-20250514" : "openai/gpt-4o";
1992
- const adapterDisplayName = adapter === "claude-agent-sdk" ? "Claude Agent SDK" : "Pydantic AI";
1993
- const isExistingProject = projectInfo?.isExistingProject ?? false;
1994
- if (isExistingProject) {
1995
- console.log(`Adding AgentMark to existing Python project with ${adapterDisplayName}...`);
1996
- } else {
1997
- console.log(`Creating AgentMark Python app with ${adapterDisplayName}...`);
1998
- }
1999
- const folderName = targetPath;
2000
- fs5.ensureDirSync(`${targetPath}/agentmark`);
2001
- setupMCPServer2(client, targetPath);
2002
- const usedModels = createExamplePrompts(model, targetPath, adapter);
2003
- console.log(`Example prompts and datasets created in ${folderName}/agentmark/`);
2004
- if (!isExistingProject) {
2005
- const projectName = path3.basename(targetPath).replace(/[^a-zA-Z0-9_-]/g, "-");
2006
- fs5.writeFileSync(`${targetPath}/pyproject.toml`, getPyprojectContent(projectName, adapter, deploymentMode));
2007
- } else {
2008
- console.log("\u23ED\uFE0F Skipped pyproject.toml (existing project)");
2009
- }
2010
- fs5.writeFileSync(`${targetPath}/agentmark_client.py`, getAgentmarkClientContent(deploymentMode, adapter));
2011
- if (deploymentMode === "cloud") {
2012
- const handlerPath = path3.join(targetPath, "handler.py");
2013
- if (fs5.existsSync(handlerPath)) {
2014
- console.log("\u23ED\uFE0F Skipped handler.py (already exists - preserving customizations)");
2015
- } else {
2016
- fs5.writeFileSync(handlerPath, getHandlerPyContent(adapter));
2017
- console.log(`\u2705 Created handler.py for cloud deployment`);
2018
- }
2019
- }
2020
- if (!isExistingProject) {
2021
- fs5.writeFileSync(`${targetPath}/main.py`, getMainPyContent(adapter, deploymentMode));
2022
- } else {
2023
- console.log("\u23ED\uFE0F Skipped main.py (existing project)");
2024
- }
2025
- if (shouldMergeFile(".env", projectInfo, resolutions)) {
2026
- const envVars = {};
2027
- const apiKeyEnvVar = adapter === "claude-agent-sdk" ? "ANTHROPIC_API_KEY" : "OPENAI_API_KEY";
2028
- if (apiKey) {
2029
- envVars[apiKeyEnvVar] = apiKey;
2030
- } else {
2031
- envVars[apiKeyEnvVar] = adapter === "claude-agent-sdk" ? "your-anthropic-api-key" : "your-openai-api-key";
2032
- }
2033
- const result = appendEnv(targetPath, envVars);
2034
- if (result.added.length > 0) {
2035
- console.log(`\u2705 Added to .env: ${result.added.join(", ")}`);
2036
- }
2037
- if (result.skipped.length > 0) {
2038
- console.log(`\u23ED\uFE0F Skipped existing .env vars: ${result.skipped.join(", ")}`);
2039
- }
2040
- } else {
2041
- fs5.writeFileSync(`${targetPath}/.env`, getEnvContent(apiKey, adapter));
2042
- }
2043
- const gitignoreEntries = [
2044
- "__pycache__/",
2045
- "*.py[cod]",
2046
- "*$py.class",
2047
- ".venv/",
2048
- "venv/",
2049
- ".env",
2050
- "*.agentmark-outputs/",
2051
- ".agentmark/",
2052
- ".idea/",
2053
- ".vscode/",
2054
- "*.swp",
2055
- "dist/",
2056
- "build/",
2057
- "*.egg-info/",
2058
- ".pytest_cache/",
2059
- ".coverage",
2060
- "htmlcov/"
2061
- ];
2062
- if (shouldMergeFile(".gitignore", projectInfo, resolutions)) {
2063
- const result = appendGitignore(targetPath, gitignoreEntries);
2064
- if (result.added.length > 0) {
2065
- console.log(`\u2705 Added to .gitignore: ${result.added.join(", ")}`);
2066
- }
2067
- if (result.skipped.length > 0) {
2068
- console.log(`\u23ED\uFE0F Already in .gitignore: ${result.skipped.join(", ")}`);
2069
- }
2070
- } else {
2071
- fs5.writeFileSync(`${targetPath}/.gitignore`, getGitignoreContent());
2072
- }
2073
- if (!isExistingProject) {
2074
- const readmePath = path3.join(targetPath, "README.md");
2075
- if (!fs5.existsSync(readmePath)) {
2076
- const projectName = path3.basename(targetPath).replace(/[^a-zA-Z0-9_-]/g, "-");
2077
- fs5.writeFileSync(readmePath, getReadmeContent(projectName, adapter));
2078
- console.log(`\u2705 Created README.md`);
128
+ console.log("\n\u{1F4DA} Installing AgentMark agent skill...");
129
+ console.log(" (teaches Claude Code / Codex / Cursor / Copilot how to use AgentMark)");
130
+ execFileSync(
131
+ "npx",
132
+ ["--yes", "skills", "add", "agentmark-ai/skills"],
133
+ {
134
+ cwd: targetPath,
135
+ stdio: "inherit"
2079
136
  }
2080
- }
2081
- const agentmarkInternalDir = path3.join(targetPath, ".agentmark");
2082
- fs5.ensureDirSync(agentmarkInternalDir);
2083
- fs5.writeFileSync(path3.join(agentmarkInternalDir, "dev_server.py"), getDevServerContent(adapter));
2084
- const pythonVenv = projectInfo?.pythonVenv;
2085
- if (pythonVenv) {
2086
- console.log(`
2087
- \u{1F4E6} Detected existing Python venv: ${pythonVenv.name}`);
2088
- console.log(" Remember to activate it before running AgentMark commands.");
2089
- } else if (!isExistingProject) {
2090
- console.log("Setting up Python environment...");
2091
- console.log("Note: You'll need to set up a virtual environment and install dependencies.");
2092
- console.log("");
2093
- }
2094
- const { installAgentmarkSkill: installAgentmarkSkill2 } = await Promise.resolve().then(() => (init_install_skill(), install_skill_exports));
2095
- installAgentmarkSkill2(targetPath);
2096
- console.log("\n\u2705 AgentMark Python initialization completed successfully!");
2097
- console.log(
2098
- `
2099
- \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
2100
- \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
2101
- \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
2102
- \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
2103
- \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
2104
- \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
2105
- + AgentMark
2106
- `
2107
137
  );
2108
- console.log("\n" + "\u2550".repeat(70));
2109
- console.log("Next Steps");
2110
- console.log("\u2550".repeat(70));
2111
- console.log("\n Get Started:");
2112
- if (folderName !== "." && folderName !== "./" && !isExistingProject) {
2113
- console.log(` $ cd ${folderName}`);
2114
- }
2115
- const pipInstallCmd = adapter === "claude-agent-sdk" ? " $ pip install agentmark-sdk agentmark-claude-agent-sdk-v0 agentmark-prompt-core python-dotenv claude-agent-sdk" : ' $ pip install agentmark-sdk agentmark-pydantic-ai-v0 agentmark-prompt-core python-dotenv "pydantic-ai-slim[openai]>=1.0,<2.0"';
2116
- const pipUpgradeCmd = ' $ python -m pip install --upgrade "pip>=26.1"';
2117
- if (pythonVenv) {
2118
- const activateCmd = process.platform === "win32" ? `${pythonVenv.name}\\Scripts\\activate` : `source ${pythonVenv.name}/bin/activate`;
2119
- console.log(` $ ${activateCmd}`);
2120
- console.log(pipUpgradeCmd);
2121
- console.log(pipInstallCmd);
2122
- } else {
2123
- console.log(" $ python -m venv .venv");
2124
- console.log(" $ source .venv/bin/activate # On Windows: .venv\\Scripts\\activate");
2125
- console.log(pipUpgradeCmd);
2126
- console.log(pipInstallCmd);
2127
- }
2128
- console.log(" $ npx agentmark dev\n");
2129
- console.log("\u2500".repeat(70));
2130
- console.log("Resources");
2131
- console.log("\u2500".repeat(70));
2132
- console.log(" Documentation: https://docs.agentmark.co");
2133
- console.log("\u2550".repeat(70) + "\n");
2134
- return usedModels;
138
+ console.log("\u2705 Agent skill installed at ./.agents/skills/agentmark/");
2135
139
  } catch (error) {
2136
- console.error("Error creating Python app:", error);
2137
- throw error;
2138
- }
2139
- };
2140
-
2141
- // src/utils/project-detection.ts
2142
- import fs7 from "fs-extra";
2143
- import path5 from "path";
2144
-
2145
- // src/utils/package-manager.ts
2146
- import fs6 from "fs-extra";
2147
- import path4 from "path";
2148
- function detectPackageManager(targetPath) {
2149
- const lockFiles = ["yarn.lock", "pnpm-lock.yaml", "bun.lockb", "package-lock.json"];
2150
- for (const lockFile of lockFiles) {
2151
- if (fs6.existsSync(path4.join(targetPath, lockFile))) {
2152
- const config = PACKAGE_MANAGERS[lockFile];
2153
- if (config) {
2154
- return config;
2155
- }
2156
- }
2157
- }
2158
- return DEFAULT_PACKAGE_MANAGER;
2159
- }
2160
-
2161
- // src/utils/project-detection.ts
2162
- var IS_WINDOWS = process.platform === "win32";
2163
- function detectTypeScriptProject(targetPath) {
2164
- const indicators = ["package.json", "tsconfig.json", "node_modules"];
2165
- return indicators.some((file) => fs7.existsSync(path5.join(targetPath, file)));
2166
- }
2167
- function detectPythonProject(targetPath) {
2168
- const indicators = ["pyproject.toml", "requirements.txt", "setup.py", ".venv", "venv"];
2169
- return indicators.some((file) => fs7.existsSync(path5.join(targetPath, file)));
2170
- }
2171
- function detectPythonVenv(targetPath) {
2172
- const venvNames = [".venv", "venv"];
2173
- for (const name of venvNames) {
2174
- const venvPath = path5.join(targetPath, name);
2175
- if (fs7.existsSync(venvPath) && fs7.statSync(venvPath).isDirectory()) {
2176
- const binDir = IS_WINDOWS ? "Scripts" : "bin";
2177
- const binPath = path5.join(venvPath, binDir);
2178
- if (fs7.existsSync(binPath)) {
2179
- const pipExe = IS_WINDOWS ? "pip.exe" : "pip";
2180
- return {
2181
- path: venvPath,
2182
- name,
2183
- activateCmd: IS_WINDOWS ? `${name}\\Scripts\\activate` : `source ${name}/bin/activate`,
2184
- pipPath: path5.join(binPath, pipExe)
2185
- };
2186
- }
2187
- }
2188
- }
2189
- const envVenv = process.env.VIRTUAL_ENV;
2190
- if (envVenv && fs7.existsSync(envVenv)) {
2191
- const resolvedTarget = path5.resolve(targetPath);
2192
- const resolvedVenv = path5.resolve(envVenv);
2193
- const isInsideTarget = resolvedVenv.startsWith(resolvedTarget + path5.sep) || resolvedVenv === resolvedTarget;
2194
- if (!isInsideTarget) {
2195
- console.warn(
2196
- `\u26A0\uFE0F Note: VIRTUAL_ENV (${envVenv}) points outside the target directory. It will not be used for this initialization.`
2197
- );
2198
- return null;
2199
- }
2200
- const binDir = IS_WINDOWS ? "Scripts" : "bin";
2201
- const pipExe = IS_WINDOWS ? "pip.exe" : "pip";
2202
- const name = path5.basename(envVenv);
2203
- return {
2204
- path: envVenv,
2205
- name,
2206
- activateCmd: IS_WINDOWS ? `${name}\\Scripts\\activate` : `source ${name}/bin/activate`,
2207
- pipPath: path5.join(envVenv, binDir, pipExe)
2208
- };
2209
- }
2210
- return null;
2211
- }
2212
- function detectConflictingFiles(targetPath) {
2213
- const existingConflicts = [];
2214
- for (const conflictFile of CONFLICT_FILES) {
2215
- const fullPath = path5.join(targetPath, conflictFile.path);
2216
- if (fs7.existsSync(fullPath)) {
2217
- existingConflicts.push(conflictFile);
140
+ console.warn(
141
+ "\n\u26A0\uFE0F Could not install the AgentMark agent skill automatically."
142
+ );
143
+ console.warn(" You can install it later with:");
144
+ console.warn(" cd " + targetPath);
145
+ console.warn(" npx skills add agentmark-ai/skills");
146
+ if (error instanceof Error) {
147
+ console.warn(` Reason: ${error.message.split("\n")[0]}`);
2218
148
  }
2219
149
  }
2220
- return existingConflicts;
2221
- }
2222
- function detectProjectInfo(targetPath) {
2223
- const isTypeScript = detectTypeScriptProject(targetPath);
2224
- const isPython = detectPythonProject(targetPath);
2225
- const isExistingProject = isTypeScript || isPython;
2226
- let type = "unknown";
2227
- if (isTypeScript && !isPython) {
2228
- type = "typescript";
2229
- } else if (isPython && !isTypeScript) {
2230
- type = "python";
2231
- } else if (isTypeScript && isPython) {
2232
- type = "typescript";
2233
- }
2234
- const packageManager = detectPackageManager(targetPath);
2235
- const conflictingFiles = detectConflictingFiles(targetPath);
2236
- const hasAgentmarkDir = fs7.existsSync(path5.join(targetPath, "agentmark"));
2237
- const pythonVenv = detectPythonVenv(targetPath);
2238
- return {
2239
- isExistingProject,
2240
- type,
2241
- packageManager,
2242
- conflictingFiles,
2243
- hasAgentmarkDir,
2244
- pythonVenv
2245
- };
2246
- }
2247
- function isCurrentDirectory(folderName) {
2248
- return folderName === "." || folderName === "./" || folderName === ".\\";
2249
- }
150
+ };
2250
151
 
2251
152
  // src/utils/git-init.ts
2252
- import { execSync as execSync2 } from "child_process";
153
+ import { execSync } from "child_process";
2253
154
  function initGitRepo(targetPath) {
2254
155
  try {
2255
156
  try {
2256
- execSync2("git --version", { stdio: "ignore" });
157
+ execSync("git --version", { stdio: "ignore" });
2257
158
  } catch {
2258
159
  console.log("\u26A0\uFE0F git not found \u2014 skipping repository initialization");
2259
160
  return false;
2260
161
  }
2261
162
  try {
2262
- execSync2("git rev-parse --is-inside-work-tree", {
163
+ execSync("git rev-parse --is-inside-work-tree", {
2263
164
  cwd: targetPath,
2264
165
  stdio: "ignore"
2265
166
  });
2266
167
  return false;
2267
168
  } catch {
2268
169
  }
2269
- execSync2("git init", { cwd: targetPath, stdio: "ignore" });
2270
- execSync2("git add -A", { cwd: targetPath, stdio: "ignore" });
2271
- execSync2(
170
+ execSync("git init", { cwd: targetPath, stdio: "ignore" });
171
+ execSync("git add -A", { cwd: targetPath, stdio: "ignore" });
172
+ execSync(
2272
173
  'git -c user.name="create-agentmark" -c user.email="noreply" commit -m "Initial commit from create-agentmark"',
2273
174
  { cwd: targetPath, stdio: "ignore" }
2274
175
  );
@@ -2280,204 +181,200 @@ function initGitRepo(targetPath) {
2280
181
  }
2281
182
  }
2282
183
 
184
+ // src/utils/project-detection.ts
185
+ import fs2 from "fs-extra";
186
+ import path2 from "path";
187
+ var TYPESCRIPT_INDICATORS = ["package.json", "tsconfig.json", "node_modules"];
188
+ var PYTHON_INDICATORS = ["pyproject.toml", "requirements.txt", "setup.py", ".venv", "venv"];
189
+ function detectTypeScriptProject(targetPath) {
190
+ return TYPESCRIPT_INDICATORS.some((file) => fs2.existsSync(path2.join(targetPath, file)));
191
+ }
192
+ function detectPythonProject(targetPath) {
193
+ return PYTHON_INDICATORS.some((file) => fs2.existsSync(path2.join(targetPath, file)));
194
+ }
195
+ function detectProjectInfo(targetPath) {
196
+ return {
197
+ isExistingProject: detectTypeScriptProject(targetPath) || detectPythonProject(targetPath),
198
+ hasAgentmarkJson: fs2.existsSync(path2.join(targetPath, "agentmark.json")),
199
+ hasAgentmarkDir: fs2.existsSync(path2.join(targetPath, "agentmark"))
200
+ };
201
+ }
202
+ function isCurrentDirectory(folderName) {
203
+ return folderName === "." || folderName === "./" || folderName === ".\\";
204
+ }
205
+
2283
206
  // src/index.ts
2284
- var VALID_ADAPTERS_TS = ["ai-sdk", "claude-agent-sdk", "mastra"];
2285
- var VALID_ADAPTERS_PY = ["pydantic-ai", "claude-agent-sdk"];
2286
- var VALID_CLIENTS = ["claude-code", "cursor", "vscode", "zed", "skip"];
2287
- var parseArgs = () => {
2288
- const args = process.argv.slice(2);
207
+ var ALL_CLIENTS = ["claude-code", "cursor", "vscode", "zed"];
208
+ var AGENTMARK_JSON = {
209
+ $schema: "https://raw.githubusercontent.com/agentmark-ai/agentmark/refs/heads/main/packages/cli/agentmark.schema.json",
210
+ version: "2.0.0",
211
+ mdxVersion: "1.0",
212
+ agentmarkPath: ".",
213
+ // Seed one model so the dashboard prompt editor isn't an empty dropdown on
214
+ // first run. Add more with `npx agentmark pull-models` (writes provider/model
215
+ // entries here) — see https://docs.agentmark.co/configure/model-schemas.
216
+ builtInModels: ["openai/gpt-5.5"]
217
+ };
218
+ var parseArgs = (argv = process.argv.slice(2)) => {
2289
219
  const result = {};
2290
- for (let i = 0; i < args.length; i++) {
2291
- const arg = args[i];
2292
- switch (arg) {
2293
- case "--cloud":
2294
- result.deploymentMode = "cloud";
2295
- break;
2296
- case "--self-host":
2297
- result.deploymentMode = "static";
2298
- break;
2299
- case "--python":
2300
- result.language = "python";
2301
- break;
2302
- case "--typescript":
2303
- result.language = "typescript";
2304
- break;
2305
- case "--overwrite":
2306
- result.overwrite = true;
2307
- break;
2308
- case "--path":
2309
- result.path = args[++i];
2310
- break;
2311
- case "--adapter":
2312
- result.adapter = args[++i];
2313
- break;
2314
- case "--api-key":
2315
- result.apiKey = args[++i];
2316
- break;
2317
- case "--client":
2318
- result.client = args[++i];
2319
- break;
220
+ for (let i = 0; i < argv.length; i++) {
221
+ const arg = argv[i];
222
+ if (arg === "--path") {
223
+ result.path = argv[++i];
224
+ } else if (arg === "--client") {
225
+ const value = argv[++i];
226
+ if (!value) throw new Error("--client requires a value");
227
+ const ids = value === "all" ? [...ALL_CLIENTS] : value.split(",").map((s) => s.trim()).filter(Boolean);
228
+ result.clients = [...result.clients ?? [], ...ids];
229
+ } else if (arg === "--overwrite") {
230
+ result.overwrite = true;
231
+ } else if (arg === "--api-url") {
232
+ const value = argv[++i];
233
+ if (!value || !/^https?:\/\//.test(value)) {
234
+ throw new Error(`--api-url requires a full http(s) URL (got "${value}")`);
235
+ }
236
+ result.apiUrl = value;
237
+ } else if (arg && !arg.startsWith("--") && !result.path) {
238
+ result.path = arg;
2320
239
  }
2321
240
  }
2322
241
  return result;
2323
242
  };
2324
- var main = async () => {
2325
- const cliArgs = parseArgs();
2326
- const config = {
2327
- $schema: "https://raw.githubusercontent.com/agentmark-ai/agentmark/refs/heads/main/packages/cli/agentmark.schema.json",
2328
- version: "2.0.0",
2329
- mdxVersion: "1.0",
2330
- agentmarkPath: "."
2331
- };
2332
- console.log("Initializing project.");
2333
- let folderName = cliArgs.path;
243
+ var clientLabel = (id) => id === "vscode" ? "VS Code" : id === "zed" ? "Zed" : id === "cursor" ? "Cursor" : id === "claude-code" ? "Claude Code" : id;
244
+ var resolveTargetPath = async (cliPath) => {
245
+ let folderName = cliPath;
2334
246
  if (!folderName) {
2335
- const response = await prompts2({
247
+ const cwd = process.cwd();
248
+ const cwdHasProject = fs3.existsSync(path3.join(cwd, "package.json")) || fs3.existsSync(path3.join(cwd, "pyproject.toml"));
249
+ const response = await prompts({
2336
250
  name: "folderName",
2337
251
  type: "text",
2338
- message: "Where would you like to create your AgentMark app?",
2339
- initial: "my-agentmark-app"
252
+ message: "Where would you like to set up AgentMark?",
253
+ initial: cwdHasProject ? "." : "my-agentmark-app"
2340
254
  });
2341
255
  folderName = response.folderName;
2342
256
  }
257
+ if (!folderName) return null;
2343
258
  const isCurrentDir = isCurrentDirectory(folderName);
2344
- const targetPath = isCurrentDir ? process.cwd() : path6.resolve(folderName);
2345
- if (!isCurrentDir) {
2346
- fs8.ensureDirSync(targetPath);
259
+ const targetPath = isCurrentDir ? process.cwd() : path3.resolve(folderName);
260
+ if (!isCurrentDir) fs3.ensureDirSync(targetPath);
261
+ return { targetPath, isCurrentDir };
262
+ };
263
+ var resolveClients = async (cliClients) => {
264
+ if (cliClients && cliClients.length > 0) {
265
+ for (const c of cliClients) {
266
+ if (!ALL_CLIENTS.includes(c)) {
267
+ throw new Error(`Invalid client "${c}". Valid: ${ALL_CLIENTS.join(", ")}`);
268
+ }
269
+ }
270
+ return cliClients;
271
+ }
272
+ const response = await prompts({
273
+ name: "clients",
274
+ type: "multiselect",
275
+ message: "Wire AgentMark MCP into which IDE clients?",
276
+ instructions: false,
277
+ hint: "Space to toggle. Enter to submit. Skip all = empty selection.",
278
+ choices: ALL_CLIENTS.map((id) => ({
279
+ title: clientLabel(id),
280
+ value: id,
281
+ selected: true
282
+ }))
283
+ });
284
+ return response.clients ?? [];
285
+ };
286
+ var shouldWriteAgentmarkJson = async (filePath, overwrite) => {
287
+ if (!fs3.existsSync(filePath)) return true;
288
+ if (overwrite) return true;
289
+ const { action } = await prompts({
290
+ type: "select",
291
+ name: "action",
292
+ message: "agentmark.json already exists. What would you like to do?",
293
+ choices: [
294
+ { title: "Skip (keep existing)", value: "skip" },
295
+ { title: "Overwrite with default config", value: "overwrite" }
296
+ ],
297
+ initial: 0
298
+ });
299
+ return action === "overwrite";
300
+ };
301
+ var main = async () => {
302
+ const cliArgs = parseArgs();
303
+ const target = await resolveTargetPath(cliArgs.path);
304
+ if (!target) {
305
+ console.log("Aborted.");
306
+ return;
2347
307
  }
308
+ const { targetPath } = target;
2348
309
  const projectInfo = detectProjectInfo(targetPath);
2349
- if (projectInfo.isExistingProject) {
2350
- displayProjectDetectionSummary(projectInfo);
2351
- }
2352
- let resolutions;
2353
- if (cliArgs.overwrite) {
2354
- resolutions = projectInfo.conflictingFiles.map((f) => ({
2355
- path: f.path,
2356
- action: "overwrite"
2357
- }));
310
+ const clients = await resolveClients(cliArgs.clients);
311
+ console.log("");
312
+ const agentmarkJsonPath = path3.join(targetPath, "agentmark.json");
313
+ if (await shouldWriteAgentmarkJson(agentmarkJsonPath, cliArgs.overwrite)) {
314
+ fs3.writeJsonSync(agentmarkJsonPath, AGENTMARK_JSON, { spaces: 2 });
315
+ console.log("\u2705 agentmark.json");
2358
316
  } else {
2359
- resolutions = await promptForResolutions(projectInfo.conflictingFiles);
2360
- }
2361
- let language = cliArgs.language;
2362
- if (!language) {
2363
- const response = await prompts2({
2364
- name: "language",
2365
- type: "select",
2366
- message: "Which language would you like to use?",
2367
- choices: [
2368
- { title: "TypeScript", value: "typescript" },
2369
- { title: "Python", value: "python" }
2370
- ]
2371
- });
2372
- language = response.language;
2373
- }
2374
- let adapter = cliArgs.adapter;
2375
- if (!adapter) {
2376
- if (language === "python") {
2377
- const response = await prompts2({
2378
- name: "adapter",
2379
- type: "select",
2380
- message: "Which adapter would you like to use?",
2381
- choices: [
2382
- { title: "Pydantic AI", value: "pydantic-ai" },
2383
- { title: "Claude Agent SDK", value: "claude-agent-sdk" }
2384
- ]
2385
- });
2386
- adapter = response.adapter;
2387
- } else {
2388
- const response = await prompts2({
2389
- name: "adapter",
2390
- type: "select",
2391
- message: "Which adapter would you like to use?",
2392
- choices: [
2393
- { title: "AI SDK (Vercel)", value: "ai-sdk" },
2394
- { title: "Claude Agent SDK", value: "claude-agent-sdk" },
2395
- { title: "Mastra", value: "mastra" }
2396
- ]
2397
- });
2398
- adapter = response.adapter;
2399
- }
2400
- }
2401
- const validAdapters = language === "python" ? VALID_ADAPTERS_PY : VALID_ADAPTERS_TS;
2402
- if (!validAdapters.includes(adapter)) {
2403
- console.error(`Invalid adapter "${adapter}" for ${language}. Valid: ${validAdapters.join(", ")}`);
2404
- process.exit(1);
2405
- }
2406
- let apiKey = cliArgs.apiKey ?? "";
2407
- if (!cliArgs.apiKey && cliArgs.apiKey !== "") {
2408
- const apiKeyName = adapter === "claude-agent-sdk" ? "Anthropic" : "OpenAI";
2409
- const { providedApiKey } = await prompts2({
2410
- name: "providedApiKey",
2411
- type: "password",
2412
- message: `Enter your ${apiKeyName} API key (or press Enter to skip):`,
2413
- initial: ""
2414
- });
2415
- apiKey = providedApiKey || "";
2416
- }
2417
- let deploymentMode = cliArgs.deploymentMode;
2418
- if (!deploymentMode) {
2419
- const response = await prompts2({
2420
- name: "deploymentMode",
2421
- type: "select",
2422
- message: "Use AgentMark Cloud or manage yourself?",
2423
- choices: [
2424
- {
2425
- title: "AgentMark Cloud (recommended)",
2426
- value: "cloud",
2427
- description: "Have AgentMark cloud manage prompts, datasets, traces, experiments, alerts & more"
2428
- },
2429
- {
2430
- title: "Self-hosted",
2431
- value: "static",
2432
- description: "Self-manage your prompts, datasets, traces & experiments"
2433
- }
2434
- ]
2435
- });
2436
- deploymentMode = response.deploymentMode;
2437
- }
2438
- let client = cliArgs.client;
2439
- if (!client) {
2440
- const response = await prompts2({
2441
- name: "client",
2442
- type: "select",
2443
- message: "Make your IDE an AgentMark expert",
2444
- choices: [
2445
- { title: "Claude Code", value: "claude-code" },
2446
- { title: "Cursor", value: "cursor" },
2447
- { title: "VS Code", value: "vscode" },
2448
- { title: "Zed", value: "zed" },
2449
- { title: "Skip", value: "skip" }
2450
- ]
2451
- });
2452
- client = response.client;
2453
- }
2454
- if (!VALID_CLIENTS.includes(client)) {
2455
- console.error(`Invalid client "${client}". Valid: ${VALID_CLIENTS.join(", ")}`);
2456
- process.exit(1);
317
+ console.log("\u23ED\uFE0F agentmark.json (kept existing)");
2457
318
  }
2458
- let usedModels;
2459
- if (language === "python") {
2460
- usedModels = await createPythonApp(client, targetPath, apiKey, deploymentMode, adapter, projectInfo, resolutions);
319
+ const agentmarkDirPath = path3.join(targetPath, "agentmark");
320
+ if (!fs3.existsSync(agentmarkDirPath)) {
321
+ fs3.ensureDirSync(agentmarkDirPath);
322
+ fs3.writeFileSync(path3.join(agentmarkDirPath, ".gitkeep"), "");
323
+ console.log("\u2705 agentmark/ (empty, ready for your .prompt.mdx files)");
2461
324
  } else {
2462
- usedModels = await createExampleApp(client, targetPath, apiKey, adapter, deploymentMode, projectInfo, resolutions);
2463
- }
2464
- config.builtInModels = usedModels;
2465
- if (deploymentMode === "cloud") {
2466
- config.handler = language === "python" ? "handler.py" : "handler.ts";
325
+ console.log("\u23ED\uFE0F agentmark/ (kept existing)");
2467
326
  }
2468
- const agentmarkJsonPath = path6.join(targetPath, "agentmark.json");
2469
- const agentmarkJsonResolution = resolutions.find((r) => r.path === "agentmark.json");
2470
- if (!fs8.existsSync(agentmarkJsonPath) || agentmarkJsonResolution?.action === "overwrite") {
2471
- fs8.writeJsonSync(agentmarkJsonPath, config, { spaces: 2 });
2472
- } else if (agentmarkJsonResolution?.action === "skip") {
2473
- console.log("\u23ED\uFE0F Skipped agentmark.json (keeping existing file)");
327
+ for (const client of clients) {
328
+ try {
329
+ const result = writeMcpConfig(client, targetPath, { customApiUrl: cliArgs.apiUrl });
330
+ if (result) {
331
+ const rel = path3.relative(targetPath, result.configPath) || result.configPath;
332
+ console.log(`\u2705 MCP wired (${clientLabel(client)}): ${rel}`);
333
+ }
334
+ } catch (err) {
335
+ const message = err instanceof Error ? err.message : String(err);
336
+ console.warn(`\u26A0\uFE0F Could not write MCP config for ${clientLabel(client)}: ${message}`);
337
+ }
2474
338
  }
339
+ installAgentmarkSkill(targetPath);
2475
340
  if (!projectInfo.isExistingProject) {
2476
341
  initGitRepo(targetPath);
2477
342
  }
343
+ console.log("");
344
+ console.log("\u2728 AgentMark is wired up.");
345
+ console.log("");
346
+ console.log(" Next: open this project in Claude Code, Cursor, VS Code, or Zed and say:");
347
+ console.log("");
348
+ console.log(' "Set up AgentMark in this project."');
349
+ console.log("");
350
+ console.log(" The AgentMark skill will detect your stack, propose the wiring against");
351
+ console.log(" the docs MCP (https://docs.agentmark.co/mcp), and integrate adaptively.");
352
+ };
353
+ var isDirectlyInvoked = () => {
354
+ const entry = process.argv[1];
355
+ if (!entry) return false;
356
+ try {
357
+ const entryReal = pathToFileURL(fs3.realpathSync(entry)).href;
358
+ const selfReal = pathToFileURL(fs3.realpathSync(fileURLToPath(import.meta.url))).href;
359
+ return entryReal === selfReal;
360
+ } catch {
361
+ return false;
362
+ }
363
+ };
364
+ if (isDirectlyInvoked()) {
365
+ main().catch((error) => {
366
+ console.error("Error:", error);
367
+ process.exit(1);
368
+ });
369
+ }
370
+ export {
371
+ AGENTMARK_JSON,
372
+ ALL_CLIENTS,
373
+ clientLabel,
374
+ main,
375
+ parseArgs,
376
+ resolveClients,
377
+ resolveTargetPath,
378
+ shouldWriteAgentmarkJson
2478
379
  };
2479
- main().catch((error) => {
2480
- console.error("Error:", error);
2481
- process.exit(1);
2482
- });
2483
380
  //# sourceMappingURL=index.js.map