create-agentmark 0.10.0 → 0.10.2
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
|
@@ -34,7 +34,7 @@ var createAdapterConfig = (provider) => {
|
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
36
|
"claude-agent-sdk": {
|
|
37
|
-
package: "@agentmark-ai/claude-agent-sdk-adapter",
|
|
37
|
+
package: "@agentmark-ai/claude-agent-sdk-v0-adapter",
|
|
38
38
|
dependencies: ["@anthropic-ai/claude-agent-sdk@^0.1.0"],
|
|
39
39
|
classes: {
|
|
40
40
|
modelRegistry: "ClaudeAgentModelRegistry",
|
|
@@ -84,7 +84,7 @@ sdk.initTracing({ disableBatch: true });
|
|
|
84
84
|
if (adapter === "claude-agent-sdk") {
|
|
85
85
|
return `import "dotenv/config";
|
|
86
86
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
87
|
-
import { withTracing } from "@agentmark-ai/claude-agent-sdk-adapter";
|
|
87
|
+
import { withTracing } from "@agentmark-ai/claude-agent-sdk-v0-adapter";
|
|
88
88
|
${tracingImport}import { client } from "./agentmark.client";
|
|
89
89
|
${tracingInit}
|
|
90
90
|
const telemetry = {
|
|
@@ -598,15 +598,7 @@ text_config:
|
|
|
598
598
|
model_name: ${model}
|
|
599
599
|
max_calls: 2
|
|
600
600
|
tools:
|
|
601
|
-
search_knowledgebase
|
|
602
|
-
description: Search the company knowledgebase for information about shipping, warranty, and returns policies.
|
|
603
|
-
parameters:
|
|
604
|
-
type: object
|
|
605
|
-
properties:
|
|
606
|
-
query:
|
|
607
|
-
type: string
|
|
608
|
-
description: The search query to find relevant information
|
|
609
|
-
required: [query]
|
|
601
|
+
- search_knowledgebase
|
|
610
602
|
test_settings:
|
|
611
603
|
dataset: customer-query.jsonl
|
|
612
604
|
props:
|
|
@@ -649,7 +641,7 @@ object_config:
|
|
|
649
641
|
- names
|
|
650
642
|
test_settings:
|
|
651
643
|
dataset: party.jsonl
|
|
652
|
-
|
|
644
|
+
scores:
|
|
653
645
|
- exact_match_json
|
|
654
646
|
props:
|
|
655
647
|
party_text: "We're having a party with Alice, Bob, and Carol."
|
|
@@ -823,7 +815,7 @@ import type { ToolsInput } from '@mastra/core/agent';
|
|
|
823
815
|
import { z } from 'zod';` : `import { tool } from 'ai';
|
|
824
816
|
import type { Tool } from 'ai';
|
|
825
817
|
import { z } from 'zod';`;
|
|
826
|
-
const createClientCall = isClaudeAgentSdk ? `return createAgentMarkClient<AgentMarkTypes>({ loader, modelRegistry,
|
|
818
|
+
const createClientCall = isClaudeAgentSdk ? `return createAgentMarkClient<AgentMarkTypes>({ loader, modelRegistry, scores, adapterOptions, mcpServers: { 'customer-support': customerSupportTools } });` : `return createAgentMarkClient<AgentMarkTypes>({ loader, modelRegistry, tools, scores });`;
|
|
827
819
|
const toolSchemaField = isMastra ? `parameters: z.object({ query: z.string().describe('The search query') })` : `inputSchema: z.object({ query: z.string().describe('The search query') })`;
|
|
828
820
|
const toolsReturnType = isMastra ? "ToolsInput" : "Record<string, Tool>";
|
|
829
821
|
const toolsSetup = isClaudeAgentSdk ? `
|
|
@@ -876,7 +868,7 @@ import path from 'node:path';
|
|
|
876
868
|
import dotenv from 'dotenv';
|
|
877
869
|
dotenv.config({ path: path.resolve(__dirname, '.env') });
|
|
878
870
|
import { createAgentMarkClient, ${modelRegistry} } from "${adapterConfig.package}";
|
|
879
|
-
import type {
|
|
871
|
+
import type { ScoreRegistry } from "@agentmark-ai/prompt-core";
|
|
880
872
|
${loaderImport}
|
|
881
873
|
import AgentMarkTypes from './agentmark.types';
|
|
882
874
|
${providerImport}
|
|
@@ -886,22 +878,26 @@ ${adapterOptionsImport}
|
|
|
886
878
|
${modelRegistrySetup}
|
|
887
879
|
${toolsSetup}
|
|
888
880
|
|
|
889
|
-
const
|
|
890
|
-
exact_match_json:
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
881
|
+
const scores: ScoreRegistry = {
|
|
882
|
+
exact_match_json: {
|
|
883
|
+
schema: { type: 'boolean' },
|
|
884
|
+
description: 'Whether output matches expected JSON exactly',
|
|
885
|
+
eval: ({ output, expectedOutput }) => {
|
|
886
|
+
if (!expectedOutput) {
|
|
887
|
+
return { score: 0, label: 'error', reason: 'No expected output provided', passed: false };
|
|
888
|
+
}
|
|
889
|
+
try {
|
|
890
|
+
const ok = JSON.stringify(output) === JSON.stringify(JSON.parse(expectedOutput));
|
|
891
|
+
return {
|
|
892
|
+
score: ok ? 1 : 0,
|
|
893
|
+
label: ok ? 'correct' : 'incorrect',
|
|
894
|
+
reason: ok ? 'Exact match' : 'Mismatch',
|
|
895
|
+
passed: ok
|
|
896
|
+
};
|
|
897
|
+
} catch (e) {
|
|
898
|
+
return { score: 0, label: 'error', reason: 'Failed to parse expected output as JSON', passed: false };
|
|
899
|
+
}
|
|
900
|
+
},
|
|
905
901
|
},
|
|
906
902
|
};
|
|
907
903
|
|
|
@@ -1229,7 +1225,7 @@ const adapter = new ${handlerClass}(client as any);
|
|
|
1229
1225
|
export default async function handler(request: {
|
|
1230
1226
|
type: 'prompt-run' | 'dataset-run';
|
|
1231
1227
|
data: {
|
|
1232
|
-
ast:
|
|
1228
|
+
ast: any;
|
|
1233
1229
|
customProps?: Record<string, unknown>;
|
|
1234
1230
|
options?: { shouldStream?: boolean };
|
|
1235
1231
|
experimentId?: string;
|
|
@@ -1484,7 +1480,7 @@ description = "An AgentMark application using Claude Agent SDK"
|
|
|
1484
1480
|
requires-python = ">=3.12"
|
|
1485
1481
|
dependencies = [
|
|
1486
1482
|
"agentmark-sdk>=0.1.0",
|
|
1487
|
-
"agentmark-claude-agent-sdk>=0.1.0",
|
|
1483
|
+
"agentmark-claude-agent-sdk-v0>=0.1.0",
|
|
1488
1484
|
"agentmark-prompt-core>=0.1.0",
|
|
1489
1485
|
"python-dotenv>=1.0.0",
|
|
1490
1486
|
"claude-agent-sdk>=0.1.0",
|
|
@@ -1515,7 +1511,7 @@ description = "An AgentMark application using Pydantic AI"
|
|
|
1515
1511
|
requires-python = ">=3.12"
|
|
1516
1512
|
dependencies = [
|
|
1517
1513
|
"agentmark-sdk>=0.1.0",
|
|
1518
|
-
"agentmark-pydantic-ai>=0.1.0",
|
|
1514
|
+
"agentmark-pydantic-ai-v0>=0.1.0",
|
|
1519
1515
|
"agentmark-prompt-core>=0.1.0",
|
|
1520
1516
|
"python-dotenv>=1.0.0",
|
|
1521
1517
|
"pydantic-ai[openai]>=0.1.0",
|
|
@@ -1541,40 +1537,122 @@ asyncio_mode = "auto"
|
|
|
1541
1537
|
strict = true
|
|
1542
1538
|
`;
|
|
1543
1539
|
};
|
|
1544
|
-
var
|
|
1540
|
+
var getHandlerPyContent = (adapter) => {
|
|
1541
|
+
const webhookClass = adapter === "claude-agent-sdk" ? "ClaudeAgentSDKWebhookHandler" : "PydanticAIWebhookHandler";
|
|
1542
|
+
const webhookImport = adapter === "claude-agent-sdk" ? "from agentmark_claude_agent_sdk import ClaudeAgentSDKWebhookHandler" : "from agentmark_pydantic_ai_v0 import PydanticAIWebhookHandler";
|
|
1543
|
+
return `"""AgentMark handler for managed cloud deployments.
|
|
1544
|
+
|
|
1545
|
+
This file is used by the AgentMark platform to execute prompts and experiments
|
|
1546
|
+
on deployed infrastructure. It mirrors the TypeScript handler.ts pattern.
|
|
1547
|
+
"""
|
|
1548
|
+
|
|
1549
|
+
import os
|
|
1550
|
+
|
|
1551
|
+
from agentmark_sdk import AgentMarkSDK
|
|
1552
|
+
${webhookImport}
|
|
1553
|
+
from agentmark_client import client
|
|
1554
|
+
|
|
1555
|
+
# Initialize tracing
|
|
1556
|
+
sdk = AgentMarkSDK(
|
|
1557
|
+
api_key=os.environ.get("AGENTMARK_API_KEY", ""),
|
|
1558
|
+
app_id=os.environ.get("AGENTMARK_APP_ID", ""),
|
|
1559
|
+
base_url=os.environ.get("AGENTMARK_BASE_URL"),
|
|
1560
|
+
)
|
|
1561
|
+
sdk.init_tracing(disable_batch=True)
|
|
1562
|
+
|
|
1563
|
+
adapter = ${webhookClass}(client)
|
|
1564
|
+
|
|
1565
|
+
|
|
1566
|
+
async def handler(request: dict):
|
|
1567
|
+
"""Handle prompt-run and dataset-run requests from the platform."""
|
|
1568
|
+
req_type = request.get("type")
|
|
1569
|
+
data = request.get("data", {})
|
|
1570
|
+
|
|
1571
|
+
if req_type == "prompt-run":
|
|
1572
|
+
return await adapter.run_prompt(data["ast"], {
|
|
1573
|
+
"shouldStream": data.get("options", {}).get("shouldStream", True),
|
|
1574
|
+
"customProps": data.get("customProps"),
|
|
1575
|
+
})
|
|
1576
|
+
|
|
1577
|
+
if req_type == "dataset-run":
|
|
1578
|
+
return await adapter.run_experiment(
|
|
1579
|
+
data["ast"],
|
|
1580
|
+
data.get("experimentId", ""),
|
|
1581
|
+
data.get("datasetPath"),
|
|
1582
|
+
)
|
|
1583
|
+
|
|
1584
|
+
raise ValueError(f"Unknown request type: {req_type}")
|
|
1585
|
+
`;
|
|
1586
|
+
};
|
|
1587
|
+
var getAgentmarkClientContent = (deploymentMode, adapter) => {
|
|
1588
|
+
const isCloud = deploymentMode === "cloud";
|
|
1589
|
+
const loaderImport = isCloud ? `from agentmark.prompt_core import ApiLoader` : `from agentmark.prompt_core import FileLoader`;
|
|
1590
|
+
const loaderSetup = isCloud ? `# API loader for cloud deployment \u2014 fetches datasets from the AgentMark gateway
|
|
1591
|
+
loader = ApiLoader.cloud()` : `# File loader for local development
|
|
1592
|
+
project_root = Path(__file__).parent.resolve()
|
|
1593
|
+
loader = FileLoader(base_dir=str(project_root))`;
|
|
1545
1594
|
if (adapter === "claude-agent-sdk") {
|
|
1546
1595
|
return `"""AgentMark client configuration.
|
|
1547
1596
|
|
|
1548
1597
|
This file configures the AgentMark client with Claude Agent SDK adapter.
|
|
1549
|
-
Customize the model registry as needed.
|
|
1598
|
+
Customize the model registry and eval registry as needed.
|
|
1550
1599
|
"""
|
|
1551
1600
|
|
|
1601
|
+
import json
|
|
1552
1602
|
import os
|
|
1553
1603
|
from pathlib import Path
|
|
1554
1604
|
from dotenv import load_dotenv
|
|
1555
1605
|
|
|
1556
|
-
|
|
1606
|
+
${loaderImport}
|
|
1557
1607
|
from agentmark_claude_agent_sdk import (
|
|
1558
1608
|
create_claude_agent_client,
|
|
1559
|
-
|
|
1609
|
+
ClaudeAgentModelRegistry,
|
|
1560
1610
|
)
|
|
1561
1611
|
|
|
1562
1612
|
# Load environment variables
|
|
1563
1613
|
load_dotenv()
|
|
1564
1614
|
|
|
1565
|
-
#
|
|
1566
|
-
#
|
|
1567
|
-
model_registry =
|
|
1615
|
+
# Register the model providers your prompts use.
|
|
1616
|
+
# This maps "anthropic/claude-sonnet-4-20250514" in prompt files to the Claude Agent SDK.
|
|
1617
|
+
model_registry = ClaudeAgentModelRegistry()
|
|
1618
|
+
model_registry.register_providers({
|
|
1619
|
+
"anthropic": "anthropic",
|
|
1620
|
+
})
|
|
1621
|
+
|
|
1622
|
+
|
|
1623
|
+
# Eval registry \u2014 define evaluation functions for experiments
|
|
1624
|
+
# TODO: Update to use scores (ScoreRegistry) once the Python SDK supports it.
|
|
1625
|
+
# The TypeScript SDK already uses scores with schema definitions.
|
|
1626
|
+
def exact_match_json(params):
|
|
1627
|
+
"""Check if output matches expected output exactly."""
|
|
1628
|
+
output = params.get("output")
|
|
1629
|
+
expected_output = params.get("expectedOutput")
|
|
1630
|
+
if not expected_output:
|
|
1631
|
+
return {"score": 0, "label": "error", "reason": "No expected output provided", "passed": False}
|
|
1632
|
+
try:
|
|
1633
|
+
actual = json.loads(output) if isinstance(output, str) else output
|
|
1634
|
+
expected = json.loads(expected_output) if isinstance(expected_output, str) else expected_output
|
|
1635
|
+
ok = actual == expected
|
|
1636
|
+
return {
|
|
1637
|
+
"score": 1 if ok else 0,
|
|
1638
|
+
"label": "correct" if ok else "incorrect",
|
|
1639
|
+
"reason": "Exact match" if ok else "Mismatch",
|
|
1640
|
+
"passed": ok,
|
|
1641
|
+
}
|
|
1642
|
+
except (json.JSONDecodeError, TypeError):
|
|
1643
|
+
return {"score": 0, "label": "error", "reason": "Failed to parse JSON", "passed": False}
|
|
1568
1644
|
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1645
|
+
eval_registry = {
|
|
1646
|
+
"exact_match_json": exact_match_json,
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
${loaderSetup}
|
|
1573
1650
|
|
|
1574
1651
|
# Create the client
|
|
1575
1652
|
# Claude Agent SDK handles tools natively through the SDK
|
|
1576
1653
|
client = create_claude_agent_client(
|
|
1577
1654
|
model_registry=model_registry,
|
|
1655
|
+
eval_registry=eval_registry,
|
|
1578
1656
|
loader=loader,
|
|
1579
1657
|
)
|
|
1580
1658
|
|
|
@@ -1584,25 +1662,30 @@ __all__ = ["client"]
|
|
|
1584
1662
|
return `"""AgentMark client configuration.
|
|
1585
1663
|
|
|
1586
1664
|
This file configures the AgentMark client with Pydantic AI adapter.
|
|
1587
|
-
Customize the model registry and
|
|
1665
|
+
Customize the model registry, tools, and eval registry as needed.
|
|
1588
1666
|
"""
|
|
1589
1667
|
|
|
1668
|
+
import json
|
|
1590
1669
|
import os
|
|
1591
1670
|
from pathlib import Path
|
|
1592
1671
|
from dotenv import load_dotenv
|
|
1593
1672
|
|
|
1594
|
-
|
|
1673
|
+
${loaderImport}
|
|
1595
1674
|
from agentmark_pydantic_ai_v0 import (
|
|
1596
1675
|
create_pydantic_ai_client,
|
|
1597
|
-
|
|
1676
|
+
PydanticAIModelRegistry,
|
|
1598
1677
|
)
|
|
1599
1678
|
|
|
1600
1679
|
# Load environment variables
|
|
1601
1680
|
load_dotenv()
|
|
1602
1681
|
|
|
1603
|
-
#
|
|
1604
|
-
#
|
|
1605
|
-
model_registry =
|
|
1682
|
+
# Register the model providers your prompts use.
|
|
1683
|
+
# This maps "openai/gpt-4o" in prompt files to "openai:gpt-4o" for Pydantic AI.
|
|
1684
|
+
model_registry = PydanticAIModelRegistry()
|
|
1685
|
+
model_registry.register_providers({
|
|
1686
|
+
"openai": "openai",
|
|
1687
|
+
"anthropic": "anthropic",
|
|
1688
|
+
})
|
|
1606
1689
|
|
|
1607
1690
|
# Define tools as native pydantic-ai Tool objects or callables
|
|
1608
1691
|
# Example:
|
|
@@ -1611,15 +1694,40 @@ model_registry = create_default_model_registry()
|
|
|
1611
1694
|
# tools = [search]
|
|
1612
1695
|
tools = []
|
|
1613
1696
|
|
|
1614
|
-
|
|
1615
|
-
#
|
|
1616
|
-
|
|
1617
|
-
|
|
1697
|
+
|
|
1698
|
+
# Eval registry \u2014 define evaluation functions for experiments
|
|
1699
|
+
# TODO: Update to use scores (ScoreRegistry) once the Python SDK supports it.
|
|
1700
|
+
# The TypeScript SDK already uses scores with schema definitions.
|
|
1701
|
+
def exact_match_json(params):
|
|
1702
|
+
"""Check if output matches expected output exactly."""
|
|
1703
|
+
output = params.get("output")
|
|
1704
|
+
expected_output = params.get("expectedOutput")
|
|
1705
|
+
if not expected_output:
|
|
1706
|
+
return {"score": 0, "label": "error", "reason": "No expected output provided", "passed": False}
|
|
1707
|
+
try:
|
|
1708
|
+
actual = json.loads(output) if isinstance(output, str) else output
|
|
1709
|
+
expected = json.loads(expected_output) if isinstance(expected_output, str) else expected_output
|
|
1710
|
+
ok = actual == expected
|
|
1711
|
+
return {
|
|
1712
|
+
"score": 1 if ok else 0,
|
|
1713
|
+
"label": "correct" if ok else "incorrect",
|
|
1714
|
+
"reason": "Exact match" if ok else "Mismatch",
|
|
1715
|
+
"passed": ok,
|
|
1716
|
+
}
|
|
1717
|
+
except (json.JSONDecodeError, TypeError):
|
|
1718
|
+
return {"score": 0, "label": "error", "reason": "Failed to parse JSON", "passed": False}
|
|
1719
|
+
|
|
1720
|
+
eval_registry = {
|
|
1721
|
+
"exact_match_json": exact_match_json,
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
${loaderSetup}
|
|
1618
1725
|
|
|
1619
1726
|
# Create the client
|
|
1620
1727
|
client = create_pydantic_ai_client(
|
|
1621
1728
|
model_registry=model_registry,
|
|
1622
1729
|
tools=tools,
|
|
1730
|
+
eval_registry=eval_registry,
|
|
1623
1731
|
loader=loader,
|
|
1624
1732
|
)
|
|
1625
1733
|
|
|
@@ -1847,6 +1955,15 @@ var createPythonApp = async (client, targetPath = ".", apiKey = "", deploymentMo
|
|
|
1847
1955
|
console.log("\u23ED\uFE0F Skipped pyproject.toml (existing project)");
|
|
1848
1956
|
}
|
|
1849
1957
|
fs5.writeFileSync(`${targetPath}/agentmark_client.py`, getAgentmarkClientContent(deploymentMode, adapter));
|
|
1958
|
+
if (deploymentMode === "cloud") {
|
|
1959
|
+
const handlerPath = path3.join(targetPath, "handler.py");
|
|
1960
|
+
if (fs5.existsSync(handlerPath)) {
|
|
1961
|
+
console.log("\u23ED\uFE0F Skipped handler.py (already exists - preserving customizations)");
|
|
1962
|
+
} else {
|
|
1963
|
+
fs5.writeFileSync(handlerPath, getHandlerPyContent(adapter));
|
|
1964
|
+
console.log(`\u2705 Created handler.py for cloud deployment`);
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1850
1967
|
if (!isExistingProject) {
|
|
1851
1968
|
fs5.writeFileSync(`${targetPath}/main.py`, getMainPyContent(adapter, deploymentMode));
|
|
1852
1969
|
} else {
|
|
@@ -1935,7 +2052,7 @@ var createPythonApp = async (client, targetPath = ".", apiKey = "", deploymentMo
|
|
|
1935
2052
|
if (pythonVenv) {
|
|
1936
2053
|
const activateCmd = process.platform === "win32" ? `${pythonVenv.name}\\Scripts\\activate` : `source ${pythonVenv.name}/bin/activate`;
|
|
1937
2054
|
console.log(` $ ${activateCmd}`);
|
|
1938
|
-
console.log(' $ pip install agentmark-pydantic-ai agentmark-prompt-core python-dotenv "pydantic-ai[openai]"');
|
|
2055
|
+
console.log(' $ pip install agentmark-pydantic-ai-v0 agentmark-prompt-core python-dotenv "pydantic-ai[openai]"');
|
|
1939
2056
|
} else {
|
|
1940
2057
|
console.log(" $ python -m venv .venv");
|
|
1941
2058
|
console.log(" $ source .venv/bin/activate # On Windows: .venv\\Scripts\\activate");
|
|
@@ -2097,22 +2214,45 @@ function initGitRepo(targetPath) {
|
|
|
2097
2214
|
}
|
|
2098
2215
|
|
|
2099
2216
|
// src/index.ts
|
|
2217
|
+
var VALID_ADAPTERS_TS = ["ai-sdk", "claude-agent-sdk", "mastra"];
|
|
2218
|
+
var VALID_ADAPTERS_PY = ["pydantic-ai", "claude-agent-sdk"];
|
|
2219
|
+
var VALID_CLIENTS = ["claude-code", "cursor", "vscode", "zed", "skip"];
|
|
2100
2220
|
var parseArgs = () => {
|
|
2101
2221
|
const args = process.argv.slice(2);
|
|
2102
|
-
|
|
2103
|
-
let
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2222
|
+
const result = {};
|
|
2223
|
+
for (let i = 0; i < args.length; i++) {
|
|
2224
|
+
const arg = args[i];
|
|
2225
|
+
switch (arg) {
|
|
2226
|
+
case "--cloud":
|
|
2227
|
+
result.deploymentMode = "cloud";
|
|
2228
|
+
break;
|
|
2229
|
+
case "--self-host":
|
|
2230
|
+
result.deploymentMode = "static";
|
|
2231
|
+
break;
|
|
2232
|
+
case "--python":
|
|
2233
|
+
result.language = "python";
|
|
2234
|
+
break;
|
|
2235
|
+
case "--typescript":
|
|
2236
|
+
result.language = "typescript";
|
|
2237
|
+
break;
|
|
2238
|
+
case "--overwrite":
|
|
2239
|
+
result.overwrite = true;
|
|
2240
|
+
break;
|
|
2241
|
+
case "--path":
|
|
2242
|
+
result.path = args[++i];
|
|
2243
|
+
break;
|
|
2244
|
+
case "--adapter":
|
|
2245
|
+
result.adapter = args[++i];
|
|
2246
|
+
break;
|
|
2247
|
+
case "--api-key":
|
|
2248
|
+
result.apiKey = args[++i];
|
|
2249
|
+
break;
|
|
2250
|
+
case "--client":
|
|
2251
|
+
result.client = args[++i];
|
|
2252
|
+
break;
|
|
2113
2253
|
}
|
|
2114
2254
|
}
|
|
2115
|
-
return
|
|
2255
|
+
return result;
|
|
2116
2256
|
};
|
|
2117
2257
|
var main = async () => {
|
|
2118
2258
|
const cliArgs = parseArgs();
|
|
@@ -2123,12 +2263,16 @@ var main = async () => {
|
|
|
2123
2263
|
agentmarkPath: "."
|
|
2124
2264
|
};
|
|
2125
2265
|
console.log("Initializing project.");
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2266
|
+
let folderName = cliArgs.path;
|
|
2267
|
+
if (!folderName) {
|
|
2268
|
+
const response = await prompts2({
|
|
2269
|
+
name: "folderName",
|
|
2270
|
+
type: "text",
|
|
2271
|
+
message: "Where would you like to create your AgentMark app?",
|
|
2272
|
+
initial: "my-agentmark-app"
|
|
2273
|
+
});
|
|
2274
|
+
folderName = response.folderName;
|
|
2275
|
+
}
|
|
2132
2276
|
const isCurrentDir = isCurrentDirectory(folderName);
|
|
2133
2277
|
const targetPath = isCurrentDir ? process.cwd() : path6.resolve(folderName);
|
|
2134
2278
|
if (!isCurrentDir) {
|
|
@@ -2138,7 +2282,15 @@ var main = async () => {
|
|
|
2138
2282
|
if (projectInfo.isExistingProject) {
|
|
2139
2283
|
displayProjectDetectionSummary(projectInfo);
|
|
2140
2284
|
}
|
|
2141
|
-
|
|
2285
|
+
let resolutions;
|
|
2286
|
+
if (cliArgs.overwrite) {
|
|
2287
|
+
resolutions = projectInfo.conflictingFiles.map((f) => ({
|
|
2288
|
+
path: f.path,
|
|
2289
|
+
action: "overwrite"
|
|
2290
|
+
}));
|
|
2291
|
+
} else {
|
|
2292
|
+
resolutions = await promptForResolutions(projectInfo.conflictingFiles);
|
|
2293
|
+
}
|
|
2142
2294
|
let language = cliArgs.language;
|
|
2143
2295
|
if (!language) {
|
|
2144
2296
|
const response = await prompts2({
|
|
@@ -2152,40 +2304,49 @@ var main = async () => {
|
|
|
2152
2304
|
});
|
|
2153
2305
|
language = response.language;
|
|
2154
2306
|
}
|
|
2155
|
-
let adapter;
|
|
2156
|
-
if (
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2307
|
+
let adapter = cliArgs.adapter;
|
|
2308
|
+
if (!adapter) {
|
|
2309
|
+
if (language === "python") {
|
|
2310
|
+
const response = await prompts2({
|
|
2311
|
+
name: "adapter",
|
|
2312
|
+
type: "select",
|
|
2313
|
+
message: "Which adapter would you like to use?",
|
|
2314
|
+
choices: [
|
|
2315
|
+
{ title: "Pydantic AI", value: "pydantic-ai" },
|
|
2316
|
+
{ title: "Claude Agent SDK", value: "claude-agent-sdk" }
|
|
2317
|
+
]
|
|
2318
|
+
});
|
|
2319
|
+
adapter = response.adapter;
|
|
2320
|
+
} else {
|
|
2321
|
+
const response = await prompts2({
|
|
2322
|
+
name: "adapter",
|
|
2323
|
+
type: "select",
|
|
2324
|
+
message: "Which adapter would you like to use?",
|
|
2325
|
+
choices: [
|
|
2326
|
+
{ title: "AI SDK (Vercel)", value: "ai-sdk" },
|
|
2327
|
+
{ title: "Claude Agent SDK", value: "claude-agent-sdk" },
|
|
2328
|
+
{ title: "Mastra", value: "mastra" }
|
|
2329
|
+
]
|
|
2330
|
+
});
|
|
2331
|
+
adapter = response.adapter;
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
const validAdapters = language === "python" ? VALID_ADAPTERS_PY : VALID_ADAPTERS_TS;
|
|
2335
|
+
if (!validAdapters.includes(adapter)) {
|
|
2336
|
+
console.error(`Invalid adapter "${adapter}" for ${language}. Valid: ${validAdapters.join(", ")}`);
|
|
2337
|
+
process.exit(1);
|
|
2338
|
+
}
|
|
2339
|
+
let apiKey = cliArgs.apiKey ?? "";
|
|
2340
|
+
if (!cliArgs.apiKey && cliArgs.apiKey !== "") {
|
|
2341
|
+
const apiKeyName = adapter === "claude-agent-sdk" ? "Anthropic" : "OpenAI";
|
|
2342
|
+
const { providedApiKey } = await prompts2({
|
|
2343
|
+
name: "providedApiKey",
|
|
2344
|
+
type: "password",
|
|
2345
|
+
message: `Enter your ${apiKeyName} API key (or press Enter to skip):`,
|
|
2346
|
+
initial: ""
|
|
2177
2347
|
});
|
|
2178
|
-
|
|
2179
|
-
}
|
|
2180
|
-
const apiKeyName = adapter === "claude-agent-sdk" ? "Anthropic" : "OpenAI";
|
|
2181
|
-
let apiKey = "";
|
|
2182
|
-
const { providedApiKey } = await prompts2({
|
|
2183
|
-
name: "providedApiKey",
|
|
2184
|
-
type: "password",
|
|
2185
|
-
message: `Enter your ${apiKeyName} API key (or press Enter to skip):`,
|
|
2186
|
-
initial: ""
|
|
2187
|
-
});
|
|
2188
|
-
apiKey = providedApiKey || "";
|
|
2348
|
+
apiKey = providedApiKey || "";
|
|
2349
|
+
}
|
|
2189
2350
|
let deploymentMode = cliArgs.deploymentMode;
|
|
2190
2351
|
if (!deploymentMode) {
|
|
2191
2352
|
const response = await prompts2({
|
|
@@ -2207,18 +2368,26 @@ var main = async () => {
|
|
|
2207
2368
|
});
|
|
2208
2369
|
deploymentMode = response.deploymentMode;
|
|
2209
2370
|
}
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2371
|
+
let client = cliArgs.client;
|
|
2372
|
+
if (!client) {
|
|
2373
|
+
const response = await prompts2({
|
|
2374
|
+
name: "client",
|
|
2375
|
+
type: "select",
|
|
2376
|
+
message: "Make your IDE an AgentMark expert",
|
|
2377
|
+
choices: [
|
|
2378
|
+
{ title: "Claude Code", value: "claude-code" },
|
|
2379
|
+
{ title: "Cursor", value: "cursor" },
|
|
2380
|
+
{ title: "VS Code", value: "vscode" },
|
|
2381
|
+
{ title: "Zed", value: "zed" },
|
|
2382
|
+
{ title: "Skip", value: "skip" }
|
|
2383
|
+
]
|
|
2384
|
+
});
|
|
2385
|
+
client = response.client;
|
|
2386
|
+
}
|
|
2387
|
+
if (!VALID_CLIENTS.includes(client)) {
|
|
2388
|
+
console.error(`Invalid client "${client}". Valid: ${VALID_CLIENTS.join(", ")}`);
|
|
2389
|
+
process.exit(1);
|
|
2390
|
+
}
|
|
2222
2391
|
let usedModels;
|
|
2223
2392
|
if (language === "python") {
|
|
2224
2393
|
usedModels = await createPythonApp(client, targetPath, apiKey, deploymentMode, adapter, projectInfo, resolutions);
|
|
@@ -2227,7 +2396,7 @@ var main = async () => {
|
|
|
2227
2396
|
}
|
|
2228
2397
|
config.builtInModels = usedModels;
|
|
2229
2398
|
if (deploymentMode === "cloud") {
|
|
2230
|
-
config.handler = "handler.ts";
|
|
2399
|
+
config.handler = language === "python" ? "handler.py" : "handler.ts";
|
|
2231
2400
|
}
|
|
2232
2401
|
const agentmarkJsonPath = path6.join(targetPath, "agentmark.json");
|
|
2233
2402
|
const agentmarkJsonResolution = resolutions.find((r) => r.path === "agentmark.json");
|