create-agentmark 0.9.0 → 0.10.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
@@ -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
 
@@ -594,15 +598,7 @@ text_config:
594
598
  model_name: ${model}
595
599
  max_calls: 2
596
600
  tools:
597
- search_knowledgebase:
598
- description: Search the company knowledgebase for information about shipping, warranty, and returns policies.
599
- parameters:
600
- type: object
601
- properties:
602
- query:
603
- type: string
604
- description: The search query to find relevant information
605
- required: [query]
601
+ - search_knowledgebase
606
602
  test_settings:
607
603
  dataset: customer-query.jsonl
608
604
  props:
@@ -752,8 +748,9 @@ var createExamplePrompts = (model, targetPath = ".", adapter = "ai-sdk") => {
752
748
  // src/utils/examples/templates/user-client-config.ts
753
749
  var getClientConfigContent = (options) => {
754
750
  const { provider, adapter, deploymentMode = "cloud" } = options;
751
+ const isMastra = adapter === "mastra";
755
752
  const adapterConfig = getAdapterConfig(adapter, provider);
756
- const { modelRegistry, toolRegistry } = adapterConfig.classes;
753
+ const { modelRegistry } = adapterConfig.classes;
757
754
  const isClaudeAgentSdk = adapter === "claude-agent-sdk";
758
755
  const providerImport = isClaudeAgentSdk ? "" : `import { ${provider} } from '@ai-sdk/${provider}';`;
759
756
  const loaderImport = deploymentMode === "cloud" ? `import { ApiLoader } from "@agentmark-ai/loader-api";` : `import { ApiLoader } from "@agentmark-ai/loader-api";
@@ -812,64 +809,98 @@ const adapterOptions = {
812
809
  // allowedTools: ['Read', 'Write', 'Glob'],
813
810
  // disallowedTools: ['Bash'],
814
811
  };` : "";
815
- const createClientCall = isClaudeAgentSdk ? `return createAgentMarkClient<AgentMarkTypes, typeof toolRegistry>({ loader, modelRegistry, toolRegistry, evalRegistry, adapterOptions });` : `return createAgentMarkClient<AgentMarkTypes, typeof toolRegistry>({ loader, modelRegistry, toolRegistry, evalRegistry });`;
812
+ const toolImport = isClaudeAgentSdk ? `import { tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
813
+ import { z } from 'zod';` : isMastra ? `import { tool } from 'ai';
814
+ import type { ToolsInput } from '@mastra/core/agent';
815
+ import { z } from 'zod';` : `import { tool } from 'ai';
816
+ import type { Tool } from 'ai';
817
+ import { z } from 'zod';`;
818
+ const createClientCall = isClaudeAgentSdk ? `return createAgentMarkClient<AgentMarkTypes>({ loader, modelRegistry, evalRegistry, adapterOptions, mcpServers: { 'customer-support': customerSupportTools } });` : `return createAgentMarkClient<AgentMarkTypes>({ loader, modelRegistry, tools, evalRegistry });`;
819
+ const toolSchemaField = isMastra ? `parameters: z.object({ query: z.string().describe('The search query') })` : `inputSchema: z.object({ query: z.string().describe('The search query') })`;
820
+ const toolsReturnType = isMastra ? "ToolsInput" : "Record<string, Tool>";
821
+ const toolsSetup = isClaudeAgentSdk ? `
822
+ // Custom tools exposed as an MCP server \u2014 the SDK's native tool mechanism.
823
+ // The server name is used in mcpServers config; tool names are used in prompt files.
824
+ const knowledgeBase = tool(
825
+ 'search_knowledgebase',
826
+ 'Search the knowledge base for relevant articles',
827
+ { query: z.string().describe('The search query') },
828
+ async ({ query }) => ({
829
+ content: [{ type: 'text' as const, text: JSON.stringify({
830
+ articles: [
831
+ { topic: 'shipping', content: 'Standard shipping takes 3\u20135 business days.' },
832
+ { topic: 'warranty', content: 'All products include a 1-year limited warranty.' },
833
+ { topic: 'returns', content: 'You can return items within 30 days of delivery.' },
834
+ ],
835
+ }) }],
836
+ })
837
+ );
838
+
839
+ const customerSupportTools = createSdkMcpServer({
840
+ name: 'customer-support',
841
+ tools: [knowledgeBase],
842
+ });` : `
843
+ function createTools(): ${toolsReturnType} {
844
+ return {
845
+ search_knowledgebase: tool({
846
+ description: 'Search the knowledge base for relevant articles',
847
+ ${toolSchemaField},
848
+ execute: async ({ query }) => {
849
+ // Simulate search delay
850
+ await new Promise(resolve => setTimeout(resolve, 500));
851
+
852
+ // Return all three knowledge base articles
853
+ // The LLM will select the relevant one based on the query
854
+ return {
855
+ articles: [
856
+ { topic: 'shipping', content: 'Standard shipping takes 3\u20135 business days.' },
857
+ { topic: 'warranty', content: 'All products include a 1-year limited warranty.' },
858
+ { topic: 'returns', content: 'You can return items within 30 days of delivery.' }
859
+ ]
860
+ };
861
+ },
862
+ }),
863
+ };
864
+ }`;
865
+ const toolsVariable = isClaudeAgentSdk ? "" : ` const tools = createTools();`;
816
866
  return `// agentmark.client.ts
817
867
  import path from 'node:path';
818
868
  import dotenv from 'dotenv';
819
869
  dotenv.config({ path: path.resolve(__dirname, '.env') });
820
- import { createAgentMarkClient, ${modelRegistry}, ${toolRegistry}, EvalRegistry } from "${adapterConfig.package}";
870
+ import { createAgentMarkClient, ${modelRegistry} } from "${adapterConfig.package}";
871
+ import type { EvalRegistry } from "${adapterConfig.package}";
821
872
  ${loaderImport}
822
- import AgentMarkTypes, { Tools } from './agentmark.types';
873
+ import AgentMarkTypes from './agentmark.types';
823
874
  ${providerImport}
875
+ ${toolImport}
824
876
  ${adapterOptionsImport}
825
877
 
826
878
  ${modelRegistrySetup}
879
+ ${toolsSetup}
827
880
 
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
881
+ const evalRegistry: EvalRegistry = {
882
+ exact_match_json: ({ output, expectedOutput }) => {
883
+ if (!expectedOutput) {
884
+ return { score: 0, label: 'error', reason: 'No expected output provided', passed: false };
885
+ }
886
+ try {
887
+ const ok = JSON.stringify(output) === JSON.stringify(JSON.parse(expectedOutput));
836
888
  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
- ]
889
+ score: ok ? 1 : 0,
890
+ label: ok ? 'correct' : 'incorrect',
891
+ reason: ok ? 'Exact match' : 'Mismatch',
892
+ passed: ok
842
893
  };
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
- }
894
+ } catch (e) {
895
+ return { score: 0, label: 'error', reason: 'Failed to parse expected output as JSON', passed: false };
896
+ }
897
+ },
898
+ };
867
899
 
868
900
  function createClient() {
869
901
  ${loaderSetup}
870
902
  const modelRegistry = createModelRegistry();
871
- const toolRegistry = createToolRegistry();
872
- const evalRegistry = createEvalRegistry();
903
+ ${toolsVariable}
873
904
  ${createClientCall}
874
905
  }
875
906
 
@@ -1113,6 +1144,10 @@ var createExampleApp = async (client, targetPath = ".", apiKey = "", adapter = "
1113
1144
  } else {
1114
1145
  envVars[apiKeyEnvVar] = adapter === "claude-agent-sdk" ? "your-anthropic-api-key" : "your-openai-api-key";
1115
1146
  }
1147
+ if (deploymentMode === "cloud") {
1148
+ envVars["AGENTMARK_API_KEY"] = "your_agentmark_api_key";
1149
+ envVars["AGENTMARK_APP_ID"] = "your_agentmark_app_id";
1150
+ }
1116
1151
  const result = appendEnv(targetPath, envVars);
1117
1152
  if (result.added.length > 0) {
1118
1153
  console.log(`\u2705 Added to .env: ${result.added.join(", ")}`);
@@ -1121,7 +1156,7 @@ var createExampleApp = async (client, targetPath = ".", apiKey = "", adapter = "
1121
1156
  console.log(`\u23ED\uFE0F Skipped existing .env vars: ${result.skipped.join(", ")}`);
1122
1157
  }
1123
1158
  } else {
1124
- fs4.writeFileSync(`${targetPath}/.env`, getEnvFileContent(modelProvider, apiKey, adapter));
1159
+ fs4.writeFileSync(`${targetPath}/.env`, getEnvFileContent(modelProvider, apiKey, adapter, deploymentMode));
1125
1160
  }
1126
1161
  const gitignoreEntries = ["node_modules/", ".env", "*.agentmark-outputs/", "dist/"];
1127
1162
  if (shouldMergeFile(".gitignore", projectInfo, resolutions)) {
@@ -1166,6 +1201,59 @@ var createExampleApp = async (client, targetPath = ".", apiKey = "", adapter = "
1166
1201
  export default interface AgentmarkTypes {}
1167
1202
  `);
1168
1203
  }
1204
+ if (deploymentMode === "cloud") {
1205
+ const handlerAdapterConfig = getAdapterConfig(adapter, modelProvider);
1206
+ const { webhookHandler: handlerClass } = handlerAdapterConfig.classes;
1207
+ const handlerContent = `import { ${handlerClass} } from '${handlerAdapterConfig.package}/runner';
1208
+ import { AgentMarkSDK } from '@agentmark-ai/sdk';
1209
+ import { client } from './agentmark.client';
1210
+
1211
+ // Initialize tracing \u2014 sends traces to AgentMark Cloud
1212
+ const sdk = new AgentMarkSDK({
1213
+ apiKey: process.env.AGENTMARK_API_KEY ?? '',
1214
+ appId: process.env.AGENTMARK_APP_ID ?? '',
1215
+ baseUrl: process.env.AGENTMARK_BASE_URL,
1216
+ });
1217
+ sdk.initTracing({ disableBatch: true });
1218
+
1219
+ const adapter = new ${handlerClass}(client as any);
1220
+
1221
+ export default async function handler(request: {
1222
+ type: 'prompt-run' | 'dataset-run';
1223
+ data: {
1224
+ ast: any;
1225
+ customProps?: Record<string, unknown>;
1226
+ options?: { shouldStream?: boolean };
1227
+ experimentId?: string;
1228
+ datasetPath?: string;
1229
+ };
1230
+ }) {
1231
+ if (request.type === 'prompt-run') {
1232
+ return adapter.runPrompt(request.data.ast, {
1233
+ shouldStream: request.data.options?.shouldStream,
1234
+ customProps: request.data.customProps,
1235
+ });
1236
+ }
1237
+
1238
+ if (request.type === 'dataset-run') {
1239
+ return adapter.runExperiment(
1240
+ request.data.ast,
1241
+ request.data.experimentId ?? '',
1242
+ request.data.datasetPath,
1243
+ );
1244
+ }
1245
+
1246
+ throw new Error(\`Unknown request type: \${request.type}\`);
1247
+ }
1248
+ `;
1249
+ const handlerPath = path2.join(targetPath, "handler.ts");
1250
+ if (fs4.existsSync(handlerPath)) {
1251
+ console.log("\u23ED\uFE0F Skipped handler.ts (already exists - preserving customizations)");
1252
+ } else {
1253
+ fs4.writeFileSync(handlerPath, handlerContent);
1254
+ console.log(`\u2705 Created handler.ts for cloud deployment`);
1255
+ }
1256
+ }
1169
1257
  console.log("Creating development server entry point...");
1170
1258
  const adapterConfig = getAdapterConfig(adapter, modelProvider);
1171
1259
  const { webhookHandler } = adapterConfig.classes;
@@ -1450,7 +1538,7 @@ var getAgentmarkClientContent = (_deploymentMode, adapter) => {
1450
1538
  return `"""AgentMark client configuration.
1451
1539
 
1452
1540
  This file configures the AgentMark client with Claude Agent SDK adapter.
1453
- Customize the model registry and tool registry as needed.
1541
+ Customize the model registry as needed.
1454
1542
  """
1455
1543
 
1456
1544
  import os
@@ -1461,7 +1549,6 @@ from agentmark.prompt_core import FileLoader
1461
1549
  from agentmark_claude_agent_sdk import (
1462
1550
  create_claude_agent_client,
1463
1551
  create_default_model_registry,
1464
- ClaudeAgentToolRegistry,
1465
1552
  )
1466
1553
 
1467
1554
  # Load environment variables
@@ -1471,26 +1558,15 @@ load_dotenv()
1471
1558
  # Supports: claude-* models
1472
1559
  model_registry = create_default_model_registry()
1473
1560
 
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
1561
  # Create file loader for local development
1486
1562
  # Uses the project root as base directory for resolving relative paths
1487
1563
  project_root = Path(__file__).parent.resolve()
1488
1564
  loader = FileLoader(base_dir=str(project_root))
1489
1565
 
1490
1566
  # Create the client
1567
+ # Claude Agent SDK handles tools natively through the SDK
1491
1568
  client = create_claude_agent_client(
1492
1569
  model_registry=model_registry,
1493
- tool_registry=tool_registry,
1494
1570
  loader=loader,
1495
1571
  )
1496
1572
 
@@ -1500,7 +1576,7 @@ __all__ = ["client"]
1500
1576
  return `"""AgentMark client configuration.
1501
1577
 
1502
1578
  This file configures the AgentMark client with Pydantic AI adapter.
1503
- Customize the model registry and tool registry as needed.
1579
+ Customize the model registry and tools as needed.
1504
1580
  """
1505
1581
 
1506
1582
  import os
@@ -1511,7 +1587,6 @@ from agentmark.prompt_core import FileLoader
1511
1587
  from agentmark_pydantic_ai_v0 import (
1512
1588
  create_pydantic_ai_client,
1513
1589
  create_default_model_registry,
1514
- PydanticAIToolRegistry,
1515
1590
  )
1516
1591
 
1517
1592
  # Load environment variables
@@ -1521,14 +1596,12 @@ load_dotenv()
1521
1596
  # Supports: gpt-*, claude-*, gemini-*, etc.
1522
1597
  model_registry = create_default_model_registry()
1523
1598
 
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"]
1599
+ # Define tools as native pydantic-ai Tool objects or callables
1600
+ # Example:
1601
+ # def search(query: str) -> str:
1531
1602
  # return f"Search results for: {query}"
1603
+ # tools = [search]
1604
+ tools = []
1532
1605
 
1533
1606
  # Create file loader for local development
1534
1607
  # Uses the project root as base directory for resolving relative paths
@@ -1538,7 +1611,7 @@ loader = FileLoader(base_dir=str(project_root))
1538
1611
  # Create the client
1539
1612
  client = create_pydantic_ai_client(
1540
1613
  model_registry=model_registry,
1541
- tool_registry=tool_registry,
1614
+ tools=tools,
1542
1615
  loader=loader,
1543
1616
  )
1544
1617
 
@@ -2145,6 +2218,9 @@ var main = async () => {
2145
2218
  usedModels = await createExampleApp(client, targetPath, apiKey, adapter, deploymentMode, projectInfo, resolutions);
2146
2219
  }
2147
2220
  config.builtInModels = usedModels;
2221
+ if (deploymentMode === "cloud") {
2222
+ config.handler = "handler.ts";
2223
+ }
2148
2224
  const agentmarkJsonPath = path6.join(targetPath, "agentmark.json");
2149
2225
  const agentmarkJsonResolution = resolutions.find((r) => r.path === "agentmark.json");
2150
2226
  if (!fs8.existsSync(agentmarkJsonPath) || agentmarkJsonResolution?.action === "overwrite") {