create-agentmark 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -17,7 +17,6 @@ var createAdapterConfig = (provider) => {
17
17
  dependencies: ["ai@^5", `@ai-sdk/${provider}@^2`],
18
18
  classes: {
19
19
  modelRegistry: "VercelAIModelRegistry",
20
- toolRegistry: "VercelAIToolRegistry",
21
20
  webhookHandler: "VercelAdapterWebhookHandler"
22
21
  }
23
22
  },
@@ -26,11 +25,11 @@ var createAdapterConfig = (provider) => {
26
25
  dependencies: [
27
26
  "@mastra/core@<0.20.0",
28
27
  "@mastra/mcp@<0.13.4",
29
- `@ai-sdk/${provider}@<2`
28
+ `@ai-sdk/${provider}@<2`,
29
+ "ai@^4"
30
30
  ],
31
31
  classes: {
32
32
  modelRegistry: "MastraModelRegistry",
33
- toolRegistry: "MastraToolRegistry",
34
33
  webhookHandler: "MastraAdapterWebhookHandler"
35
34
  }
36
35
  },
@@ -39,7 +38,6 @@ var createAdapterConfig = (provider) => {
39
38
  dependencies: ["@anthropic-ai/claude-agent-sdk@^0.1.0"],
40
39
  classes: {
41
40
  modelRegistry: "ClaudeAgentModelRegistry",
42
- toolRegistry: "ClaudeAgentToolRegistry",
43
41
  webhookHandler: "ClaudeAgentWebhookHandler"
44
42
  }
45
43
  }
@@ -229,16 +227,22 @@ main();
229
227
  };
230
228
 
231
229
  // src/utils/examples/templates/env.ts
232
- var getEnvFileContent = (_modelProvider, apiKey = "", adapter = "ai-sdk") => {
230
+ var getEnvFileContent = (_modelProvider, apiKey = "", adapter = "ai-sdk", deploymentMode = "cloud") => {
233
231
  const apiKeyValue = apiKey || "your_api_key_here";
234
232
  const apiKeyName = adapter === "claude-agent-sdk" ? "ANTHROPIC_API_KEY" : "OPENAI_API_KEY";
235
- return `# Cloud deployment: Set these environment variables
233
+ const cloudEnvVars = deploymentMode === "cloud" ? `
234
+ # AgentMark Cloud \u2014 required for managed deployments
235
+ AGENTMARK_API_KEY=your_agentmark_api_key
236
+ AGENTMARK_APP_ID=your_agentmark_app_id
237
+ ` : `
238
+ # Cloud deployment: Set these environment variables
236
239
  # AGENTMARK_BASE_URL=https://api.agentmark.co
237
240
  # AGENTMARK_API_KEY=your_agentmark_api_key
238
241
  # AGENTMARK_APP_ID=your_agentmark_app_id
242
+ `;
243
+ return `${apiKeyName}=${apiKeyValue}
244
+ ${cloudEnvVars}
239
245
  # Learn more: https://docs.agentmark.co/platform/getting_started/quickstart
240
-
241
- ${apiKeyName}=${apiKeyValue}
242
246
  `;
243
247
  };
244
248
 
@@ -752,8 +756,9 @@ var createExamplePrompts = (model, targetPath = ".", adapter = "ai-sdk") => {
752
756
  // src/utils/examples/templates/user-client-config.ts
753
757
  var getClientConfigContent = (options) => {
754
758
  const { provider, adapter, deploymentMode = "cloud" } = options;
759
+ const isMastra = adapter === "mastra";
755
760
  const adapterConfig = getAdapterConfig(adapter, provider);
756
- const { modelRegistry, toolRegistry } = adapterConfig.classes;
761
+ const { modelRegistry } = adapterConfig.classes;
757
762
  const isClaudeAgentSdk = adapter === "claude-agent-sdk";
758
763
  const providerImport = isClaudeAgentSdk ? "" : `import { ${provider} } from '@ai-sdk/${provider}';`;
759
764
  const loaderImport = deploymentMode === "cloud" ? `import { ApiLoader } from "@agentmark-ai/loader-api";` : `import { ApiLoader } from "@agentmark-ai/loader-api";
@@ -812,64 +817,98 @@ const adapterOptions = {
812
817
  // allowedTools: ['Read', 'Write', 'Glob'],
813
818
  // disallowedTools: ['Bash'],
814
819
  };` : "";
815
- const createClientCall = isClaudeAgentSdk ? `return createAgentMarkClient<AgentMarkTypes, typeof toolRegistry>({ loader, modelRegistry, toolRegistry, evalRegistry, adapterOptions });` : `return createAgentMarkClient<AgentMarkTypes, typeof toolRegistry>({ loader, modelRegistry, toolRegistry, evalRegistry });`;
820
+ const toolImport = isClaudeAgentSdk ? `import { tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
821
+ import { z } from 'zod';` : isMastra ? `import { tool } from 'ai';
822
+ import type { ToolsInput } from '@mastra/core/agent';
823
+ import { z } from 'zod';` : `import { tool } from 'ai';
824
+ import type { Tool } from 'ai';
825
+ import { z } from 'zod';`;
826
+ const createClientCall = isClaudeAgentSdk ? `return createAgentMarkClient<AgentMarkTypes>({ loader, modelRegistry, evalRegistry, adapterOptions, mcpServers: { 'customer-support': customerSupportTools } });` : `return createAgentMarkClient<AgentMarkTypes>({ loader, modelRegistry, tools, evalRegistry });`;
827
+ const toolSchemaField = isMastra ? `parameters: z.object({ query: z.string().describe('The search query') })` : `inputSchema: z.object({ query: z.string().describe('The search query') })`;
828
+ const toolsReturnType = isMastra ? "ToolsInput" : "Record<string, Tool>";
829
+ const toolsSetup = isClaudeAgentSdk ? `
830
+ // Custom tools exposed as an MCP server \u2014 the SDK's native tool mechanism.
831
+ // The server name is used in mcpServers config; tool names are used in prompt files.
832
+ const knowledgeBase = tool(
833
+ 'search_knowledgebase',
834
+ 'Search the knowledge base for relevant articles',
835
+ { query: z.string().describe('The search query') },
836
+ async ({ query }) => ({
837
+ content: [{ type: 'text' as const, text: JSON.stringify({
838
+ articles: [
839
+ { topic: 'shipping', content: 'Standard shipping takes 3\u20135 business days.' },
840
+ { topic: 'warranty', content: 'All products include a 1-year limited warranty.' },
841
+ { topic: 'returns', content: 'You can return items within 30 days of delivery.' },
842
+ ],
843
+ }) }],
844
+ })
845
+ );
846
+
847
+ const customerSupportTools = createSdkMcpServer({
848
+ name: 'customer-support',
849
+ tools: [knowledgeBase],
850
+ });` : `
851
+ function createTools(): ${toolsReturnType} {
852
+ return {
853
+ search_knowledgebase: tool({
854
+ description: 'Search the knowledge base for relevant articles',
855
+ ${toolSchemaField},
856
+ execute: async ({ query }) => {
857
+ // Simulate search delay
858
+ await new Promise(resolve => setTimeout(resolve, 500));
859
+
860
+ // Return all three knowledge base articles
861
+ // The LLM will select the relevant one based on the query
862
+ return {
863
+ articles: [
864
+ { topic: 'shipping', content: 'Standard shipping takes 3\u20135 business days.' },
865
+ { topic: 'warranty', content: 'All products include a 1-year limited warranty.' },
866
+ { topic: 'returns', content: 'You can return items within 30 days of delivery.' }
867
+ ]
868
+ };
869
+ },
870
+ }),
871
+ };
872
+ }`;
873
+ const toolsVariable = isClaudeAgentSdk ? "" : ` const tools = createTools();`;
816
874
  return `// agentmark.client.ts
817
875
  import path from 'node:path';
818
876
  import dotenv from 'dotenv';
819
877
  dotenv.config({ path: path.resolve(__dirname, '.env') });
820
- import { createAgentMarkClient, ${modelRegistry}, ${toolRegistry}, EvalRegistry } from "${adapterConfig.package}";
878
+ import { createAgentMarkClient, ${modelRegistry} } from "${adapterConfig.package}";
879
+ import type { EvalRegistry } from "${adapterConfig.package}";
821
880
  ${loaderImport}
822
- import AgentMarkTypes, { Tools } from './agentmark.types';
881
+ import AgentMarkTypes from './agentmark.types';
823
882
  ${providerImport}
883
+ ${toolImport}
824
884
  ${adapterOptionsImport}
825
885
 
826
886
  ${modelRegistrySetup}
887
+ ${toolsSetup}
827
888
 
828
- function createToolRegistry() {
829
- const toolRegistry = new ${toolRegistry}<Tools>()
830
- .register('search_knowledgebase', async ({ query }) => {
831
- // Simulate search delay
832
- await new Promise(resolve => setTimeout(resolve, 500));
833
-
834
- // Return all three knowledge base articles
835
- // The LLM will select the relevant one based on the query
889
+ const evalRegistry: EvalRegistry = {
890
+ exact_match_json: ({ output, expectedOutput }) => {
891
+ if (!expectedOutput) {
892
+ return { score: 0, label: 'error', reason: 'No expected output provided', passed: false };
893
+ }
894
+ try {
895
+ const ok = JSON.stringify(output) === JSON.stringify(JSON.parse(expectedOutput));
836
896
  return {
837
- articles: [
838
- { topic: 'shipping', content: 'Standard shipping takes 3\u20135 business days.' },
839
- { topic: 'warranty', content: 'All products include a 1-year limited warranty.' },
840
- { topic: 'returns', content: 'You can return items within 30 days of delivery.' }
841
- ]
897
+ score: ok ? 1 : 0,
898
+ label: ok ? 'correct' : 'incorrect',
899
+ reason: ok ? 'Exact match' : 'Mismatch',
900
+ passed: ok
842
901
  };
843
- });
844
- return toolRegistry;
845
- }
846
-
847
- function createEvalRegistry() {
848
- const evalRegistry = new EvalRegistry()
849
- .register('exact_match_json', ({ output, expectedOutput }) => {
850
- if (!expectedOutput) {
851
- return { score: 0, label: 'error', reason: 'No expected output provided', passed: false };
852
- }
853
- try {
854
- const ok = JSON.stringify(output) === JSON.stringify(JSON.parse(expectedOutput));
855
- return {
856
- score: ok ? 1 : 0,
857
- label: ok ? 'correct' : 'incorrect',
858
- reason: ok ? 'Exact match' : 'Mismatch',
859
- passed: ok
860
- };
861
- } catch (e) {
862
- return { score: 0, label: 'error', reason: 'Failed to parse expected output as JSON', passed: false };
863
- }
864
- });
865
- return evalRegistry;
866
- }
902
+ } catch (e) {
903
+ return { score: 0, label: 'error', reason: 'Failed to parse expected output as JSON', passed: false };
904
+ }
905
+ },
906
+ };
867
907
 
868
908
  function createClient() {
869
909
  ${loaderSetup}
870
910
  const modelRegistry = createModelRegistry();
871
- const toolRegistry = createToolRegistry();
872
- const evalRegistry = createEvalRegistry();
911
+ ${toolsVariable}
873
912
  ${createClientCall}
874
913
  }
875
914
 
@@ -1113,6 +1152,10 @@ var createExampleApp = async (client, targetPath = ".", apiKey = "", adapter = "
1113
1152
  } else {
1114
1153
  envVars[apiKeyEnvVar] = adapter === "claude-agent-sdk" ? "your-anthropic-api-key" : "your-openai-api-key";
1115
1154
  }
1155
+ if (deploymentMode === "cloud") {
1156
+ envVars["AGENTMARK_API_KEY"] = "your_agentmark_api_key";
1157
+ envVars["AGENTMARK_APP_ID"] = "your_agentmark_app_id";
1158
+ }
1116
1159
  const result = appendEnv(targetPath, envVars);
1117
1160
  if (result.added.length > 0) {
1118
1161
  console.log(`\u2705 Added to .env: ${result.added.join(", ")}`);
@@ -1121,7 +1164,7 @@ var createExampleApp = async (client, targetPath = ".", apiKey = "", adapter = "
1121
1164
  console.log(`\u23ED\uFE0F Skipped existing .env vars: ${result.skipped.join(", ")}`);
1122
1165
  }
1123
1166
  } else {
1124
- fs4.writeFileSync(`${targetPath}/.env`, getEnvFileContent(modelProvider, apiKey, adapter));
1167
+ fs4.writeFileSync(`${targetPath}/.env`, getEnvFileContent(modelProvider, apiKey, adapter, deploymentMode));
1125
1168
  }
1126
1169
  const gitignoreEntries = ["node_modules/", ".env", "*.agentmark-outputs/", "dist/"];
1127
1170
  if (shouldMergeFile(".gitignore", projectInfo, resolutions)) {
@@ -1166,6 +1209,59 @@ var createExampleApp = async (client, targetPath = ".", apiKey = "", adapter = "
1166
1209
  export default interface AgentmarkTypes {}
1167
1210
  `);
1168
1211
  }
1212
+ if (deploymentMode === "cloud") {
1213
+ const handlerAdapterConfig = getAdapterConfig(adapter, modelProvider);
1214
+ const { webhookHandler: handlerClass } = handlerAdapterConfig.classes;
1215
+ const handlerContent = `import { ${handlerClass} } from '${handlerAdapterConfig.package}/runner';
1216
+ import { AgentMarkSDK } from '@agentmark-ai/sdk';
1217
+ import { client } from './agentmark.client';
1218
+
1219
+ // Initialize tracing \u2014 sends traces to AgentMark Cloud
1220
+ const sdk = new AgentMarkSDK({
1221
+ apiKey: process.env.AGENTMARK_API_KEY ?? '',
1222
+ appId: process.env.AGENTMARK_APP_ID ?? '',
1223
+ baseUrl: process.env.AGENTMARK_BASE_URL,
1224
+ });
1225
+ sdk.initTracing({ disableBatch: true });
1226
+
1227
+ const adapter = new ${handlerClass}(client as any);
1228
+
1229
+ export default async function handler(request: {
1230
+ type: 'prompt-run' | 'dataset-run';
1231
+ data: {
1232
+ ast: unknown;
1233
+ customProps?: Record<string, unknown>;
1234
+ options?: { shouldStream?: boolean };
1235
+ experimentId?: string;
1236
+ datasetPath?: string;
1237
+ };
1238
+ }) {
1239
+ if (request.type === 'prompt-run') {
1240
+ return adapter.runPrompt(request.data.ast, {
1241
+ shouldStream: request.data.options?.shouldStream,
1242
+ customProps: request.data.customProps,
1243
+ });
1244
+ }
1245
+
1246
+ if (request.type === 'dataset-run') {
1247
+ return adapter.runExperiment(
1248
+ request.data.ast,
1249
+ request.data.experimentId ?? '',
1250
+ request.data.datasetPath,
1251
+ );
1252
+ }
1253
+
1254
+ throw new Error(\`Unknown request type: \${request.type}\`);
1255
+ }
1256
+ `;
1257
+ const handlerPath = path2.join(targetPath, "handler.ts");
1258
+ if (fs4.existsSync(handlerPath)) {
1259
+ console.log("\u23ED\uFE0F Skipped handler.ts (already exists - preserving customizations)");
1260
+ } else {
1261
+ fs4.writeFileSync(handlerPath, handlerContent);
1262
+ console.log(`\u2705 Created handler.ts for cloud deployment`);
1263
+ }
1264
+ }
1169
1265
  console.log("Creating development server entry point...");
1170
1266
  const adapterConfig = getAdapterConfig(adapter, modelProvider);
1171
1267
  const { webhookHandler } = adapterConfig.classes;
@@ -1450,7 +1546,7 @@ var getAgentmarkClientContent = (_deploymentMode, adapter) => {
1450
1546
  return `"""AgentMark client configuration.
1451
1547
 
1452
1548
  This file configures the AgentMark client with Claude Agent SDK adapter.
1453
- Customize the model registry and tool registry as needed.
1549
+ Customize the model registry as needed.
1454
1550
  """
1455
1551
 
1456
1552
  import os
@@ -1461,7 +1557,6 @@ from agentmark.prompt_core import FileLoader
1461
1557
  from agentmark_claude_agent_sdk import (
1462
1558
  create_claude_agent_client,
1463
1559
  create_default_model_registry,
1464
- ClaudeAgentToolRegistry,
1465
1560
  )
1466
1561
 
1467
1562
  # Load environment variables
@@ -1471,26 +1566,15 @@ load_dotenv()
1471
1566
  # Supports: claude-* models
1472
1567
  model_registry = create_default_model_registry()
1473
1568
 
1474
- # Configure tool registry for custom tools
1475
- tool_registry = ClaudeAgentToolRegistry()
1476
-
1477
- # Example tool registration:
1478
- # tool_registry.register(
1479
- # "search",
1480
- # lambda args, ctx: f"Search results for: {args['query']}",
1481
- # description="Search the web",
1482
- # parameters={"type": "object", "properties": {"query": {"type": "string"}}, "required": ["query"]},
1483
- # )
1484
-
1485
1569
  # Create file loader for local development
1486
1570
  # Uses the project root as base directory for resolving relative paths
1487
1571
  project_root = Path(__file__).parent.resolve()
1488
1572
  loader = FileLoader(base_dir=str(project_root))
1489
1573
 
1490
1574
  # Create the client
1575
+ # Claude Agent SDK handles tools natively through the SDK
1491
1576
  client = create_claude_agent_client(
1492
1577
  model_registry=model_registry,
1493
- tool_registry=tool_registry,
1494
1578
  loader=loader,
1495
1579
  )
1496
1580
 
@@ -1500,7 +1584,7 @@ __all__ = ["client"]
1500
1584
  return `"""AgentMark client configuration.
1501
1585
 
1502
1586
  This file configures the AgentMark client with Pydantic AI adapter.
1503
- Customize the model registry and tool registry as needed.
1587
+ Customize the model registry and tools as needed.
1504
1588
  """
1505
1589
 
1506
1590
  import os
@@ -1511,7 +1595,6 @@ from agentmark.prompt_core import FileLoader
1511
1595
  from agentmark_pydantic_ai_v0 import (
1512
1596
  create_pydantic_ai_client,
1513
1597
  create_default_model_registry,
1514
- PydanticAIToolRegistry,
1515
1598
  )
1516
1599
 
1517
1600
  # Load environment variables
@@ -1521,14 +1604,12 @@ load_dotenv()
1521
1604
  # Supports: gpt-*, claude-*, gemini-*, etc.
1522
1605
  model_registry = create_default_model_registry()
1523
1606
 
1524
- # Configure tool registry for custom tools
1525
- tool_registry = PydanticAIToolRegistry()
1526
-
1527
- # Example tool registration:
1528
- # @tool_registry.register("search")
1529
- # async def search_web(args: dict, ctx: dict | None) -> str:
1530
- # query = args["query"]
1607
+ # Define tools as native pydantic-ai Tool objects or callables
1608
+ # Example:
1609
+ # def search(query: str) -> str:
1531
1610
  # return f"Search results for: {query}"
1611
+ # tools = [search]
1612
+ tools = []
1532
1613
 
1533
1614
  # Create file loader for local development
1534
1615
  # Uses the project root as base directory for resolving relative paths
@@ -1538,7 +1619,7 @@ loader = FileLoader(base_dir=str(project_root))
1538
1619
  # Create the client
1539
1620
  client = create_pydantic_ai_client(
1540
1621
  model_registry=model_registry,
1541
- tool_registry=tool_registry,
1622
+ tools=tools,
1542
1623
  loader=loader,
1543
1624
  )
1544
1625
 
@@ -2145,6 +2226,9 @@ var main = async () => {
2145
2226
  usedModels = await createExampleApp(client, targetPath, apiKey, adapter, deploymentMode, projectInfo, resolutions);
2146
2227
  }
2147
2228
  config.builtInModels = usedModels;
2229
+ if (deploymentMode === "cloud") {
2230
+ config.handler = "handler.ts";
2231
+ }
2148
2232
  const agentmarkJsonPath = path6.join(targetPath, "agentmark.json");
2149
2233
  const agentmarkJsonResolution = resolutions.find((r) => r.path === "agentmark.json");
2150
2234
  if (!fs8.existsSync(agentmarkJsonPath) || agentmarkJsonResolution?.action === "overwrite") {