create-agentmark 0.10.5 → 0.10.6

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
@@ -71,7 +71,7 @@ sdk.initTracing({ disableBatch: true });
71
71
  `;
72
72
  const staticTracingInit = `
73
73
  // Initialize tracing - traces will be sent to local dev server
74
- // Make sure to run "npm run agentmark dev" in another terminal first
74
+ // Make sure to run "npx agentmark dev" in another terminal first
75
75
  // To disable tracing, comment out sdk.initTracing() below
76
76
  const sdk = new AgentMarkSDK({
77
77
  apiKey: "",
@@ -242,7 +242,7 @@ AGENTMARK_APP_ID=your_agentmark_app_id
242
242
  `;
243
243
  return `${apiKeyName}=${apiKeyValue}
244
244
  ${cloudEnvVars}
245
- # Learn more: https://docs.agentmark.co/platform/getting_started/quickstart
245
+ # Learn more: https://docs.agentmark.co/getting-started/quickstart
246
246
  `;
247
247
  };
248
248
 
@@ -487,9 +487,10 @@ var setupPackageJson = (targetPath = ".", deploymentMode = "cloud", projectInfo
487
487
  console.log("Creating package.json...");
488
488
  execSync("npm init -y", { cwd: targetPath });
489
489
  }
490
+ const demoScript = deploymentMode === "static" ? "npx agentmark build --out dist/agentmark && npx tsx index.ts" : "npx tsx index.ts";
490
491
  if (isExistingProject && fs2.existsSync(packageJsonPath)) {
491
492
  const scriptsToAdd = {
492
- "demo": "npx tsx index.ts",
493
+ "demo": demoScript,
493
494
  "agentmark": "agentmark"
494
495
  };
495
496
  if (deploymentMode === "static") {
@@ -509,9 +510,12 @@ var setupPackageJson = (targetPath = ".", deploymentMode = "cloud", projectInfo
509
510
  const pkgJson = fs2.readJsonSync(packageJsonPath);
510
511
  pkgJson.name = pkgJson.name === "test" || !pkgJson.name ? "agentmark-example-app" : pkgJson.name;
511
512
  pkgJson.description = pkgJson.description || "A simple Node.js app using the Agentmark SDK";
513
+ if (pkgJson.type === "commonjs") {
514
+ delete pkgJson.type;
515
+ }
512
516
  const scripts = {
513
517
  ...pkgJson.scripts,
514
- "demo": "npx tsx index.ts",
518
+ "demo": demoScript,
515
519
  "agentmark": "agentmark"
516
520
  };
517
521
  if (deploymentMode === "static") {
@@ -641,7 +645,7 @@ object_config:
641
645
  - names
642
646
  test_settings:
643
647
  dataset: party.jsonl
644
- scores:
648
+ evals:
645
649
  - exact_match_json
646
650
  props:
647
651
  party_text: "We're having a party with Alice, Bob, and Carol."
@@ -757,12 +761,16 @@ var getClientConfigContent = (options) => {
757
761
  import { FileLoader } from "@agentmark-ai/loader-file";`;
758
762
  const loaderSetup = deploymentMode === "cloud" ? ` // ApiLoader works for both development and production
759
763
  // - Development: 'agentmark dev' sets AGENTMARK_BASE_URL to localhost
760
- // - Production: Set AGENTMARK_API_KEY and AGENTMARK_APP_ID for cloud
764
+ // - Production: Set AGENTMARK_API_KEY and AGENTMARK_APP_ID for cloud.
765
+ // AGENTMARK_BASE_URL overrides the default https://api.agentmark.co
766
+ // target \u2014 managed deployments use this to point back at the gateway
767
+ // that dispatched the job.
761
768
  const loader = process.env.NODE_ENV === 'development'
762
769
  ? ApiLoader.local({ baseUrl: process.env.AGENTMARK_BASE_URL || 'http://localhost:9418' })
763
770
  : ApiLoader.cloud({
764
771
  apiKey: process.env.AGENTMARK_API_KEY!,
765
772
  appId: process.env.AGENTMARK_APP_ID!,
773
+ baseUrl: process.env.AGENTMARK_BASE_URL,
766
774
  });` : ` const loader = process.env.NODE_ENV === 'development'
767
775
  ? ApiLoader.local({ baseUrl: process.env.AGENTMARK_BASE_URL || 'http://localhost:9418' })
768
776
  : new FileLoader('./dist/agentmark');`;
@@ -1136,6 +1144,19 @@ var createExampleApp = async (client, targetPath = ".", apiKey = "", adapter = "
1136
1144
  `${targetPath}/agentmark.client.ts`,
1137
1145
  getClientConfigContent({ provider: modelProvider, adapter, deploymentMode })
1138
1146
  );
1147
+ const gitignoreEntries = ["node_modules/", ".env", "*.agentmark-outputs/", "dist/"];
1148
+ if (shouldMergeFile(".gitignore", projectInfo, resolutions)) {
1149
+ const result = appendGitignore(targetPath, gitignoreEntries);
1150
+ if (result.added.length > 0) {
1151
+ console.log(`\u2705 Added to .gitignore: ${result.added.join(", ")}`);
1152
+ }
1153
+ if (result.skipped.length > 0) {
1154
+ console.log(`\u23ED\uFE0F Already in .gitignore: ${result.skipped.join(", ")}`);
1155
+ }
1156
+ } else {
1157
+ const gitignore = gitignoreEntries.join("\n");
1158
+ fs4.writeFileSync(`${targetPath}/.gitignore`, gitignore);
1159
+ }
1139
1160
  if (shouldMergeFile(".env", projectInfo, resolutions)) {
1140
1161
  const envVars = {};
1141
1162
  const apiKeyEnvVar = adapter === "claude-agent-sdk" ? "ANTHROPIC_API_KEY" : "OPENAI_API_KEY";
@@ -1158,19 +1179,6 @@ var createExampleApp = async (client, targetPath = ".", apiKey = "", adapter = "
1158
1179
  } else {
1159
1180
  fs4.writeFileSync(`${targetPath}/.env`, getEnvFileContent(modelProvider, apiKey, adapter, deploymentMode));
1160
1181
  }
1161
- const gitignoreEntries = ["node_modules/", ".env", "*.agentmark-outputs/", "dist/"];
1162
- if (shouldMergeFile(".gitignore", projectInfo, resolutions)) {
1163
- const result = appendGitignore(targetPath, gitignoreEntries);
1164
- if (result.added.length > 0) {
1165
- console.log(`\u2705 Added to .gitignore: ${result.added.join(", ")}`);
1166
- }
1167
- if (result.skipped.length > 0) {
1168
- console.log(`\u23ED\uFE0F Already in .gitignore: ${result.skipped.join(", ")}`);
1169
- }
1170
- } else {
1171
- const gitignore = gitignoreEntries.join("\n");
1172
- fs4.writeFileSync(`${targetPath}/.gitignore`, gitignore);
1173
- }
1174
1182
  if (!isExistingProject) {
1175
1183
  fs4.writeFileSync(
1176
1184
  `${targetPath}/index.ts`,
@@ -1219,15 +1227,23 @@ sdk.initTracing({ disableBatch: true });
1219
1227
  const adapter = new ${handlerClass}(client as any);
1220
1228
 
1221
1229
  export default async function handler(request: {
1222
- type: 'prompt-run' | 'dataset-run';
1230
+ type: 'prompt-run' | 'dataset-run' | 'get-evals';
1223
1231
  data: {
1224
- ast: any;
1232
+ ast?: any;
1225
1233
  customProps?: Record<string, unknown>;
1226
1234
  options?: { shouldStream?: boolean };
1227
1235
  experimentId?: string;
1228
1236
  datasetPath?: string;
1229
1237
  };
1230
1238
  }) {
1239
+ if (request.type === 'get-evals') {
1240
+ return {
1241
+ type: 'evals',
1242
+ result: JSON.stringify(Object.keys(client.getEvalRegistry())),
1243
+ traceId: '',
1244
+ };
1245
+ }
1246
+
1231
1247
  if (request.type === 'prompt-run') {
1232
1248
  return adapter.runPrompt(request.data.ast, {
1233
1249
  shouldStream: request.data.options?.shouldStream,
@@ -1327,20 +1343,11 @@ main().catch((err) => {
1327
1343
  console.log("\n" + "\u2550".repeat(70));
1328
1344
  console.log("Next Steps");
1329
1345
  console.log("\u2550".repeat(70));
1330
- const runCmd = packageManager?.runCmd ?? "npm run";
1331
- const pkgJsonPath = path2.join(targetPath, "package.json");
1332
- let agentmarkScriptName = "agentmark";
1333
- if (fs4.existsSync(pkgJsonPath)) {
1334
- const pkgJson = fs4.readJsonSync(pkgJsonPath);
1335
- if (pkgJson.scripts?.["agentmark:agentmark"]) {
1336
- agentmarkScriptName = "agentmark:agentmark";
1337
- }
1338
- }
1339
1346
  console.log("\n Get Started:");
1340
1347
  if (folderName !== "." && folderName !== "./" && !isExistingProject) {
1341
1348
  console.log(` $ cd ${folderName}`);
1342
1349
  }
1343
- console.log(` $ ${runCmd} ${agentmarkScriptName} dev
1350
+ console.log(` $ npx agentmark dev
1344
1351
  `);
1345
1352
  console.log("\u2500".repeat(70));
1346
1353
  console.log("Resources");
@@ -1467,7 +1474,8 @@ var setupMCPServer2 = (client, targetPath) => {
1467
1474
  return;
1468
1475
  }
1469
1476
  };
1470
- var getPyprojectContent = (projectName, adapter) => {
1477
+ var getPyprojectContent = (projectName, adapter, deploymentMode) => {
1478
+ const pyModules = deploymentMode === "cloud" ? `["agentmark_client", "main", "handler"]` : `["agentmark_client", "main"]`;
1471
1479
  if (adapter === "claude-agent-sdk") {
1472
1480
  return `[project]
1473
1481
  name = "${projectName}"
@@ -1475,9 +1483,9 @@ version = "0.1.0"
1475
1483
  description = "An AgentMark application using Claude Agent SDK"
1476
1484
  requires-python = ">=3.12"
1477
1485
  dependencies = [
1478
- "agentmark-sdk>=0.1.0",
1479
- "agentmark-claude-agent-sdk-v0>=0.1.0",
1480
- "agentmark-prompt-core>=0.1.0",
1486
+ "agentmark-sdk>=0.2.0",
1487
+ "agentmark-claude-agent-sdk-v0>=0.1.4",
1488
+ "agentmark-prompt-core>=0.1.2",
1481
1489
  "python-dotenv>=1.0.0",
1482
1490
  "claude-agent-sdk>=0.1.0",
1483
1491
  ]
@@ -1490,8 +1498,11 @@ dev = [
1490
1498
  ]
1491
1499
 
1492
1500
  [build-system]
1493
- requires = ["hatchling"]
1494
- build-backend = "hatchling.build"
1501
+ requires = ["setuptools>=61", "wheel"]
1502
+ build-backend = "setuptools.build_meta"
1503
+
1504
+ [tool.setuptools]
1505
+ py-modules = ${pyModules}
1495
1506
 
1496
1507
  [tool.pytest.ini_options]
1497
1508
  asyncio_mode = "auto"
@@ -1506,11 +1517,11 @@ version = "0.1.0"
1506
1517
  description = "An AgentMark application using Pydantic AI"
1507
1518
  requires-python = ">=3.12"
1508
1519
  dependencies = [
1509
- "agentmark-sdk>=0.1.0",
1510
- "agentmark-pydantic-ai-v0>=0.1.0",
1511
- "agentmark-prompt-core>=0.1.0",
1520
+ "agentmark-sdk>=0.2.0",
1521
+ "agentmark-pydantic-ai-v0>=0.1.4",
1522
+ "agentmark-prompt-core>=0.1.2",
1512
1523
  "python-dotenv>=1.0.0",
1513
- "pydantic-ai[openai]>=0.1.0",
1524
+ "pydantic-ai-slim[openai]>=1.0,<2.0",
1514
1525
  ]
1515
1526
 
1516
1527
  [project.optional-dependencies]
@@ -1519,12 +1530,13 @@ dev = [
1519
1530
  "pytest-asyncio>=0.21",
1520
1531
  "mypy>=1.0",
1521
1532
  ]
1522
- anthropic = ["pydantic-ai[anthropic]"]
1523
- gemini = ["pydantic-ai[gemini]"]
1524
1533
 
1525
1534
  [build-system]
1526
- requires = ["hatchling"]
1527
- build-backend = "hatchling.build"
1535
+ requires = ["setuptools>=61", "wheel"]
1536
+ build-backend = "setuptools.build_meta"
1537
+
1538
+ [tool.setuptools]
1539
+ py-modules = ${pyModules}
1528
1540
 
1529
1541
  [tool.pytest.ini_options]
1530
1542
  asyncio_mode = "auto"
@@ -1534,8 +1546,8 @@ strict = true
1534
1546
  `;
1535
1547
  };
1536
1548
  var getHandlerPyContent = (adapter) => {
1537
- const webhookClass = adapter === "claude-agent-sdk" ? "ClaudeAgentSDKWebhookHandler" : "PydanticAIWebhookHandler";
1538
- const webhookImport = adapter === "claude-agent-sdk" ? "from agentmark_claude_agent_sdk import ClaudeAgentSDKWebhookHandler" : "from agentmark_pydantic_ai_v0 import PydanticAIWebhookHandler";
1549
+ const webhookClass = adapter === "claude-agent-sdk" ? "ClaudeAgentWebhookHandler" : "PydanticAIWebhookHandler";
1550
+ const webhookImport = adapter === "claude-agent-sdk" ? "from agentmark_claude_agent_sdk_v0 import ClaudeAgentWebhookHandler" : "from agentmark_pydantic_ai_v0 import PydanticAIWebhookHandler";
1539
1551
  return `"""AgentMark handler for managed cloud deployments.
1540
1552
 
1541
1553
  This file is used by the AgentMark platform to execute prompts and experiments
@@ -1560,10 +1572,18 @@ adapter = ${webhookClass}(client)
1560
1572
 
1561
1573
 
1562
1574
  async def handler(request: dict):
1563
- """Handle prompt-run and dataset-run requests from the platform."""
1575
+ """Handle prompt-run, dataset-run, and get-evals requests from the platform."""
1564
1576
  req_type = request.get("type")
1565
1577
  data = request.get("data", {})
1566
1578
 
1579
+ if req_type == "get-evals":
1580
+ import json
1581
+ return {
1582
+ "type": "evals",
1583
+ "result": json.dumps(list(client.get_eval_registry().keys())),
1584
+ "traceId": "",
1585
+ }
1586
+
1567
1587
  if req_type == "prompt-run":
1568
1588
  return await adapter.run_prompt(data["ast"], {
1569
1589
  "shouldStream": data.get("options", {}).get("shouldStream", True),
@@ -1601,7 +1621,7 @@ from dotenv import load_dotenv
1601
1621
 
1602
1622
  ${loaderImport}
1603
1623
  from agentmark.prompt_core import EvalRegistry
1604
- from agentmark_claude_agent_sdk import (
1624
+ from agentmark_claude_agent_sdk_v0 import (
1605
1625
  create_claude_agent_client,
1606
1626
  ClaudeAgentModelRegistry,
1607
1627
  )
@@ -1741,7 +1761,7 @@ sdk.init_tracing(disable_batch=True)
1741
1761
  `;
1742
1762
  const staticTracingInit = `
1743
1763
  # Initialize tracing - traces will be sent to local dev server
1744
- # Make sure to run "npm run agentmark dev" in another terminal first
1764
+ # Make sure to run "npx agentmark dev" in another terminal first
1745
1765
  # To disable tracing, comment out sdk.init_tracing() below
1746
1766
  sdk = AgentMarkSDK(
1747
1767
  api_key="",
@@ -1754,49 +1774,40 @@ sdk.init_tracing(disable_batch=True)
1754
1774
  if (adapter === "claude-agent-sdk") {
1755
1775
  return `"""Example usage of AgentMark with Claude Agent SDK.
1756
1776
 
1757
- Run with: python main.py
1777
+ Run with:
1778
+ npx agentmark build # compile party-planner.prompt.mdx -> dist/agentmark/*.json
1779
+ python main.py
1758
1780
  """
1759
1781
 
1760
1782
  import asyncio
1761
- import json
1762
1783
  import os
1763
- from pathlib import Path
1764
1784
 
1765
1785
  from agentmark_sdk import AgentMarkSDK
1766
- from agentmark_claude_agent_sdk import run_text_prompt
1786
+ from agentmark_claude_agent_sdk_v0 import traced_query
1767
1787
  from agentmark_client import client
1768
1788
  ${tracingInit}
1769
1789
 
1770
1790
  async def main():
1771
- """Run the party planner prompt."""
1772
- # Load the prompt AST (in production, use the API loader)
1773
- prompt_path = Path("agentmark/party-planner.prompt.mdx.json")
1774
-
1775
- if not prompt_path.exists():
1776
- print("Prompt file not found. Run 'agentmark build' first.")
1791
+ """Run the party planner prompt (object_config: extracts attendee names)."""
1792
+ # \`agentmark build\` writes pre-compiled prompts to dist/agentmark/.
1793
+ # The FileLoader reads them by name \u2014 extension is optional.
1794
+ try:
1795
+ prompt = await client.load_object_prompt("party-planner.prompt.mdx")
1796
+ except FileNotFoundError:
1797
+ print("Pre-built prompt not found. Run 'npx agentmark build' first.")
1777
1798
  return
1778
1799
 
1779
- with open(prompt_path) as f:
1780
- ast = json.load(f)
1781
-
1782
- # Load and format the prompt
1783
- prompt = await client.load_text_prompt(ast)
1784
- params = await prompt.format(props={
1785
- "numberOfGuests": 10,
1786
- "theme": "80s disco",
1787
- "dietaryRestrictions": ["vegetarian", "gluten-free"],
1800
+ adapted = await prompt.format(props={
1801
+ "party_text": "We're having a party with Alice, Bob, and Carol.",
1788
1802
  })
1789
1803
 
1790
- # Execute the prompt
1804
+ # Execute via Claude Agent SDK (streamed) with automatic OTEL tracing.
1805
+ # adapted.query.options.output_format is set to the object schema.
1791
1806
  print("Running party planner prompt...")
1792
- result = await run_text_prompt(params)
1793
-
1794
- print("\\n" + "=" * 50)
1795
- print("Party Plan:")
1796
1807
  print("=" * 50)
1797
- print(result.output)
1798
- print("\\n" + "-" * 50)
1799
- print(f"Tokens used: {result.usage}")
1808
+ async for message in traced_query(adapted):
1809
+ print(message)
1810
+ print("=" * 50)
1800
1811
 
1801
1812
 
1802
1813
  if __name__ == "__main__":
@@ -1805,47 +1816,44 @@ if __name__ == "__main__":
1805
1816
  }
1806
1817
  return `"""Example usage of AgentMark with Pydantic AI.
1807
1818
 
1808
- Run with: python main.py
1819
+ Run with:
1820
+ npx agentmark build # compile party-planner.prompt.mdx -> dist/agentmark/*.json
1821
+ python main.py
1809
1822
  """
1823
+ # To use a different LLM provider, install: pip install "pydantic-ai-slim[anthropic]" (or [google], [bedrock], etc.)
1810
1824
 
1811
1825
  import asyncio
1812
- import json
1813
1826
  import os
1814
- from pathlib import Path
1815
1827
 
1816
1828
  from agentmark_sdk import AgentMarkSDK
1817
- from agentmark_pydantic_ai_v0 import run_text_prompt
1829
+ from agentmark_pydantic_ai_v0 import run_object_prompt
1818
1830
  from agentmark_client import client
1819
1831
  ${tracingInit}
1820
1832
 
1821
1833
  async def main():
1822
- """Run the party planner prompt."""
1823
- # Load the prompt AST (in production, use the API loader)
1824
- prompt_path = Path("agentmark/party-planner.prompt.mdx.json")
1825
-
1826
- if not prompt_path.exists():
1827
- print("Prompt file not found. Run 'agentmark build' first.")
1834
+ """Run the party planner prompt (object_config: extracts attendee names)."""
1835
+ # \`agentmark build\` writes pre-compiled prompts to dist/agentmark/.
1836
+ # The FileLoader reads them by name \u2014 extension is optional, and it
1837
+ # extracts the inner AST from the { ast, metadata } wrapper for you.
1838
+ try:
1839
+ prompt = await client.load_object_prompt("party-planner.prompt.mdx")
1840
+ except FileNotFoundError:
1841
+ print("Pre-built prompt not found. Run 'npx agentmark build' first.")
1828
1842
  return
1829
1843
 
1830
- with open(prompt_path) as f:
1831
- ast = json.load(f)
1832
-
1833
- # Load and format the prompt
1834
- prompt = await client.load_text_prompt(ast)
1835
1844
  params = await prompt.format(props={
1836
- "numberOfGuests": 10,
1837
- "theme": "80s disco",
1838
- "dietaryRestrictions": ["vegetarian", "gluten-free"],
1845
+ "party_text": "We're having a party with Alice, Bob, and Carol.",
1839
1846
  })
1840
1847
 
1841
1848
  # Execute the prompt
1842
1849
  print("Running party planner prompt...")
1843
- result = await run_text_prompt(params)
1850
+ result = await run_object_prompt(params)
1844
1851
 
1845
1852
  print("\\n" + "=" * 50)
1846
- print("Party Plan:")
1853
+ print("Extracted attendees:")
1847
1854
  print("=" * 50)
1848
- print(result.output)
1855
+ # result.output is a Pydantic model instance with the schema's fields
1856
+ print(result.output.names)
1849
1857
  print("\\n" + "-" * 50)
1850
1858
  print(f"Tokens used: {result.usage.total_tokens}")
1851
1859
 
@@ -1855,10 +1863,10 @@ if __name__ == "__main__":
1855
1863
  `;
1856
1864
  };
1857
1865
  var getDevServerContent = (adapter) => {
1858
- const adapterPackage = adapter === "claude-agent-sdk" ? "agentmark_claude_agent_sdk" : "agentmark_pydantic_ai_v0";
1866
+ const adapterPackage = adapter === "claude-agent-sdk" ? "agentmark_claude_agent_sdk_v0" : "agentmark_pydantic_ai_v0";
1859
1867
  return `"""Auto-generated webhook server for AgentMark development.
1860
1868
 
1861
- This server is started by 'npm run agentmark dev' (agentmark dev) and handles
1869
+ This server is started by 'npx agentmark dev' (agentmark dev) and handles
1862
1870
  prompt execution requests from the CLI.
1863
1871
  """
1864
1872
 
@@ -1898,6 +1906,62 @@ OPENAI_API_KEY=${apiKey}
1898
1906
  # GOOGLE_API_KEY=your-key-here
1899
1907
  `;
1900
1908
  };
1909
+ var getReadmeContent = (projectName, adapter) => {
1910
+ const adapterName = adapter === "claude-agent-sdk" ? "Claude Agent SDK" : "Pydantic AI";
1911
+ const apiKeyEnvVar = adapter === "claude-agent-sdk" ? "ANTHROPIC_API_KEY" : "OPENAI_API_KEY";
1912
+ 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"';
1913
+ return `# ${projectName}
1914
+
1915
+ An AgentMark application using ${adapterName}.
1916
+
1917
+ ## Prerequisites
1918
+
1919
+ - Python 3.12+
1920
+ - **pip 26.1+** (older pip versions fail to resolve the dependency graph \u2014 see "Why pip 26.1?" below)
1921
+
1922
+ ## Setup
1923
+
1924
+ \`\`\`bash
1925
+ # 1. Create and activate a virtual environment
1926
+ python -m venv .venv
1927
+ source .venv/bin/activate # On Windows: .venv\\Scripts\\activate
1928
+
1929
+ # 2. Upgrade pip (REQUIRED \u2014 older pip cannot resolve pydantic-ai's transitive graph)
1930
+ python -m pip install --upgrade "pip>=26.1"
1931
+
1932
+ # 3. Install dependencies
1933
+ ${directInstallCmd}
1934
+
1935
+ # 4. Set your API key
1936
+ echo "${apiKeyEnvVar}=your-key-here" > .env
1937
+ \`\`\`
1938
+
1939
+ ## Run
1940
+
1941
+ \`\`\`bash
1942
+ # Start the AgentMark dev server (in another terminal)
1943
+ npx agentmark dev
1944
+
1945
+ # Run the example prompt
1946
+ python main.py
1947
+ \`\`\`
1948
+
1949
+ Then open [http://localhost:9418](http://localhost:9418) to view your traces.
1950
+
1951
+ ## Why pip 26.1?
1952
+
1953
+ The \`pydantic-ai-slim\` package transitively depends on \`mcp\`, \`fastmcp\`, and
1954
+ \`logfire\`, which together produce a deep dependency graph. Pip versions before
1955
+ 26.1 fall into long backtracking loops and abort with \`resolution-too-deep\`.
1956
+ Pip 26.1's resolver handles this graph efficiently. If you skip the upgrade and
1957
+ hit the error, run \`python -m pip install --upgrade pip\` and retry.
1958
+
1959
+ ## Resources
1960
+
1961
+ - [Documentation](https://docs.agentmark.co)
1962
+ - [GitHub](https://github.com/agentmark-ai/agentmark)
1963
+ `;
1964
+ };
1901
1965
  var getGitignoreContent = () => {
1902
1966
  return `# Python
1903
1967
  __pycache__/
@@ -1944,7 +2008,7 @@ var createPythonApp = async (client, targetPath = ".", apiKey = "", deploymentMo
1944
2008
  console.log(`Example prompts and datasets created in ${folderName}/agentmark/`);
1945
2009
  if (!isExistingProject) {
1946
2010
  const projectName = path3.basename(targetPath).replace(/[^a-zA-Z0-9_-]/g, "-");
1947
- fs5.writeFileSync(`${targetPath}/pyproject.toml`, getPyprojectContent(projectName, adapter));
2011
+ fs5.writeFileSync(`${targetPath}/pyproject.toml`, getPyprojectContent(projectName, adapter, deploymentMode));
1948
2012
  } else {
1949
2013
  console.log("\u23ED\uFE0F Skipped pyproject.toml (existing project)");
1950
2014
  }
@@ -2011,6 +2075,14 @@ var createPythonApp = async (client, targetPath = ".", apiKey = "", deploymentMo
2011
2075
  } else {
2012
2076
  fs5.writeFileSync(`${targetPath}/.gitignore`, getGitignoreContent());
2013
2077
  }
2078
+ if (!isExistingProject) {
2079
+ const readmePath = path3.join(targetPath, "README.md");
2080
+ if (!fs5.existsSync(readmePath)) {
2081
+ const projectName = path3.basename(targetPath).replace(/[^a-zA-Z0-9_-]/g, "-");
2082
+ fs5.writeFileSync(readmePath, getReadmeContent(projectName, adapter));
2083
+ console.log(`\u2705 Created README.md`);
2084
+ }
2085
+ }
2014
2086
  const agentmarkInternalDir = path3.join(targetPath, ".agentmark");
2015
2087
  fs5.ensureDirSync(agentmarkInternalDir);
2016
2088
  fs5.writeFileSync(path3.join(agentmarkInternalDir, "dev_server.py"), getDevServerContent(adapter));
@@ -2043,16 +2115,20 @@ var createPythonApp = async (client, targetPath = ".", apiKey = "", deploymentMo
2043
2115
  if (folderName !== "." && folderName !== "./" && !isExistingProject) {
2044
2116
  console.log(` $ cd ${folderName}`);
2045
2117
  }
2118
+ 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"';
2119
+ const pipUpgradeCmd = ' $ python -m pip install --upgrade "pip>=26.1"';
2046
2120
  if (pythonVenv) {
2047
2121
  const activateCmd = process.platform === "win32" ? `${pythonVenv.name}\\Scripts\\activate` : `source ${pythonVenv.name}/bin/activate`;
2048
2122
  console.log(` $ ${activateCmd}`);
2049
- console.log(' $ pip install agentmark-pydantic-ai-v0 agentmark-prompt-core python-dotenv "pydantic-ai[openai]"');
2123
+ console.log(pipUpgradeCmd);
2124
+ console.log(pipInstallCmd);
2050
2125
  } else {
2051
2126
  console.log(" $ python -m venv .venv");
2052
2127
  console.log(" $ source .venv/bin/activate # On Windows: .venv\\Scripts\\activate");
2053
- console.log(' $ pip install -e ".[dev]"');
2128
+ console.log(pipUpgradeCmd);
2129
+ console.log(pipInstallCmd);
2054
2130
  }
2055
- console.log(" $ npm run agentmark dev\n");
2131
+ console.log(" $ npx agentmark dev\n");
2056
2132
  console.log("\u2500".repeat(70));
2057
2133
  console.log("Resources");
2058
2134
  console.log("\u2500".repeat(70));