@mixrpay/agent-sdk 0.3.3 → 0.3.4
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.cjs +313 -0
- package/dist/index.d.cts +231 -1
- package/dist/index.d.ts +231 -1
- package/dist/index.js +313 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1616,6 +1616,319 @@ Timestamp: ${timestamp}`;
|
|
|
1616
1616
|
latencyMs: mixrpay.latencyMs
|
|
1617
1617
|
};
|
|
1618
1618
|
}
|
|
1619
|
+
// ===========================================================================
|
|
1620
|
+
// Agent Runtime API
|
|
1621
|
+
// ===========================================================================
|
|
1622
|
+
/**
|
|
1623
|
+
* Run an AI agent with LLM and tool execution.
|
|
1624
|
+
*
|
|
1625
|
+
* This method orchestrates a full agentic loop:
|
|
1626
|
+
* - Multi-turn reasoning with LLM
|
|
1627
|
+
* - Automatic tool execution
|
|
1628
|
+
* - Bundled billing (single charge at end)
|
|
1629
|
+
* - Optional streaming via SSE
|
|
1630
|
+
*
|
|
1631
|
+
* @param options - Agent run options
|
|
1632
|
+
* @returns Agent run result with response and cost breakdown
|
|
1633
|
+
*
|
|
1634
|
+
* @example Basic usage
|
|
1635
|
+
* ```typescript
|
|
1636
|
+
* const result = await wallet.runAgent({
|
|
1637
|
+
* sessionId: 'sess_abc123',
|
|
1638
|
+
* messages: [{ role: 'user', content: 'Find AI startups in SF' }],
|
|
1639
|
+
* });
|
|
1640
|
+
*
|
|
1641
|
+
* console.log(result.response);
|
|
1642
|
+
* console.log(`Cost: $${result.cost.totalUsd.toFixed(4)}`);
|
|
1643
|
+
* ```
|
|
1644
|
+
*
|
|
1645
|
+
* @example With custom config
|
|
1646
|
+
* ```typescript
|
|
1647
|
+
* const result = await wallet.runAgent({
|
|
1648
|
+
* sessionId: 'sess_abc123',
|
|
1649
|
+
* messages: [{ role: 'user', content: 'Research quantum computing' }],
|
|
1650
|
+
* config: {
|
|
1651
|
+
* model: 'gpt-4o',
|
|
1652
|
+
* maxIterations: 15,
|
|
1653
|
+
* tools: ['platform/exa-search', 'platform/firecrawl-scrape'],
|
|
1654
|
+
* systemPrompt: 'You are a research assistant.',
|
|
1655
|
+
* },
|
|
1656
|
+
* });
|
|
1657
|
+
* ```
|
|
1658
|
+
*
|
|
1659
|
+
* @example With streaming
|
|
1660
|
+
* ```typescript
|
|
1661
|
+
* await wallet.runAgent({
|
|
1662
|
+
* sessionId: 'sess_abc123',
|
|
1663
|
+
* messages: [{ role: 'user', content: 'Analyze this company' }],
|
|
1664
|
+
* stream: true,
|
|
1665
|
+
* onEvent: (event) => {
|
|
1666
|
+
* if (event.type === 'llm_chunk') {
|
|
1667
|
+
* process.stdout.write(event.delta);
|
|
1668
|
+
* } else if (event.type === 'tool_call') {
|
|
1669
|
+
* console.log(`Calling tool: ${event.tool}`);
|
|
1670
|
+
* }
|
|
1671
|
+
* },
|
|
1672
|
+
* });
|
|
1673
|
+
* ```
|
|
1674
|
+
*/
|
|
1675
|
+
async runAgent(options) {
|
|
1676
|
+
const {
|
|
1677
|
+
sessionId,
|
|
1678
|
+
messages,
|
|
1679
|
+
config = {},
|
|
1680
|
+
stream = false,
|
|
1681
|
+
idempotencyKey,
|
|
1682
|
+
onEvent
|
|
1683
|
+
} = options;
|
|
1684
|
+
this.logger.debug("runAgent", { sessionId, messageCount: messages.length, config, stream });
|
|
1685
|
+
const body = {
|
|
1686
|
+
session_id: sessionId,
|
|
1687
|
+
messages: messages.map((m) => ({ role: m.role, content: m.content })),
|
|
1688
|
+
config: {
|
|
1689
|
+
model: config.model,
|
|
1690
|
+
max_iterations: config.maxIterations,
|
|
1691
|
+
tools: config.tools,
|
|
1692
|
+
system_prompt: config.systemPrompt
|
|
1693
|
+
},
|
|
1694
|
+
stream,
|
|
1695
|
+
idempotency_key: idempotencyKey
|
|
1696
|
+
};
|
|
1697
|
+
const AGENT_RUN_TIMEOUT = 18e4;
|
|
1698
|
+
if (!stream) {
|
|
1699
|
+
const response = await fetch(`${this.baseUrl}/api/v2/agent/run`, {
|
|
1700
|
+
method: "POST",
|
|
1701
|
+
headers: {
|
|
1702
|
+
"Content-Type": "application/json",
|
|
1703
|
+
"X-Mixr-Session": sessionId
|
|
1704
|
+
},
|
|
1705
|
+
body: JSON.stringify(body),
|
|
1706
|
+
signal: AbortSignal.timeout(AGENT_RUN_TIMEOUT)
|
|
1707
|
+
});
|
|
1708
|
+
if (!response.ok) {
|
|
1709
|
+
const error = await response.json().catch(() => ({}));
|
|
1710
|
+
throw new MixrPayError(error.error || `Agent run failed: ${response.status}`);
|
|
1711
|
+
}
|
|
1712
|
+
const data = await response.json();
|
|
1713
|
+
if (data.cost?.total_usd > 0) {
|
|
1714
|
+
const payment = {
|
|
1715
|
+
amountUsd: data.cost.total_usd,
|
|
1716
|
+
recipient: "mixrpay-agent-run",
|
|
1717
|
+
txHash: data.tx_hash,
|
|
1718
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
1719
|
+
description: `Agent run: ${data.run_id}`,
|
|
1720
|
+
url: `${this.baseUrl}/api/v2/agent/run`
|
|
1721
|
+
};
|
|
1722
|
+
this.payments.push(payment);
|
|
1723
|
+
this.totalSpentUsd += data.cost.total_usd;
|
|
1724
|
+
this.logger.payment(data.cost.total_usd, "agent-run", data.run_id);
|
|
1725
|
+
if (this.onPayment) {
|
|
1726
|
+
this.onPayment(payment);
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
return {
|
|
1730
|
+
runId: data.run_id,
|
|
1731
|
+
status: data.status,
|
|
1732
|
+
response: data.response,
|
|
1733
|
+
iterations: data.iterations,
|
|
1734
|
+
toolsUsed: data.tools_used,
|
|
1735
|
+
cost: {
|
|
1736
|
+
llmUsd: data.cost.llm_usd,
|
|
1737
|
+
toolsUsd: data.cost.tools_usd,
|
|
1738
|
+
totalUsd: data.cost.total_usd
|
|
1739
|
+
},
|
|
1740
|
+
tokens: data.tokens,
|
|
1741
|
+
sessionRemainingUsd: data.session_remaining_usd,
|
|
1742
|
+
txHash: data.tx_hash
|
|
1743
|
+
};
|
|
1744
|
+
}
|
|
1745
|
+
return this.runAgentStreaming(sessionId, body, onEvent);
|
|
1746
|
+
}
|
|
1747
|
+
/**
|
|
1748
|
+
* Internal: Handle streaming agent run via SSE
|
|
1749
|
+
*/
|
|
1750
|
+
async runAgentStreaming(sessionId, body, onEvent) {
|
|
1751
|
+
const STREAMING_TIMEOUT = 3e5;
|
|
1752
|
+
const response = await fetch(`${this.baseUrl}/api/v2/agent/run`, {
|
|
1753
|
+
method: "POST",
|
|
1754
|
+
headers: {
|
|
1755
|
+
"Content-Type": "application/json",
|
|
1756
|
+
"X-Mixr-Session": sessionId
|
|
1757
|
+
},
|
|
1758
|
+
body: JSON.stringify(body),
|
|
1759
|
+
signal: AbortSignal.timeout(STREAMING_TIMEOUT)
|
|
1760
|
+
});
|
|
1761
|
+
if (!response.ok) {
|
|
1762
|
+
const error = await response.json().catch(() => ({}));
|
|
1763
|
+
throw new MixrPayError(error.error || `Agent run failed: ${response.status}`);
|
|
1764
|
+
}
|
|
1765
|
+
const reader = response.body?.getReader();
|
|
1766
|
+
if (!reader) {
|
|
1767
|
+
throw new MixrPayError("No response body for streaming");
|
|
1768
|
+
}
|
|
1769
|
+
const decoder = new TextDecoder();
|
|
1770
|
+
let buffer = "";
|
|
1771
|
+
let result = null;
|
|
1772
|
+
while (true) {
|
|
1773
|
+
const { done, value } = await reader.read();
|
|
1774
|
+
if (done) break;
|
|
1775
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1776
|
+
const lines = buffer.split("\n");
|
|
1777
|
+
buffer = lines.pop() || "";
|
|
1778
|
+
let currentEvent = "";
|
|
1779
|
+
for (const line of lines) {
|
|
1780
|
+
if (line.startsWith("event: ")) {
|
|
1781
|
+
currentEvent = line.slice(7).trim();
|
|
1782
|
+
} else if (line.startsWith("data: ") && currentEvent) {
|
|
1783
|
+
try {
|
|
1784
|
+
const data = JSON.parse(line.slice(6));
|
|
1785
|
+
const event = this.parseSSEEvent(currentEvent, data);
|
|
1786
|
+
if (event) {
|
|
1787
|
+
onEvent?.(event);
|
|
1788
|
+
if (currentEvent === "complete") {
|
|
1789
|
+
result = {
|
|
1790
|
+
runId: data.run_id,
|
|
1791
|
+
status: "completed",
|
|
1792
|
+
response: data.response,
|
|
1793
|
+
iterations: data.iterations,
|
|
1794
|
+
toolsUsed: data.tools_used,
|
|
1795
|
+
cost: {
|
|
1796
|
+
llmUsd: 0,
|
|
1797
|
+
// Not provided in streaming complete
|
|
1798
|
+
toolsUsd: 0,
|
|
1799
|
+
totalUsd: data.total_cost_usd
|
|
1800
|
+
},
|
|
1801
|
+
tokens: { prompt: 0, completion: 0 },
|
|
1802
|
+
sessionRemainingUsd: 0,
|
|
1803
|
+
txHash: data.tx_hash
|
|
1804
|
+
};
|
|
1805
|
+
if (data.total_cost_usd > 0) {
|
|
1806
|
+
const payment = {
|
|
1807
|
+
amountUsd: data.total_cost_usd,
|
|
1808
|
+
recipient: "mixrpay-agent-run",
|
|
1809
|
+
txHash: data.tx_hash,
|
|
1810
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
1811
|
+
description: `Agent run: ${data.run_id}`,
|
|
1812
|
+
url: `${this.baseUrl}/api/v2/agent/run`
|
|
1813
|
+
};
|
|
1814
|
+
this.payments.push(payment);
|
|
1815
|
+
this.totalSpentUsd += data.total_cost_usd;
|
|
1816
|
+
if (this.onPayment) {
|
|
1817
|
+
this.onPayment(payment);
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
if (currentEvent === "error") {
|
|
1822
|
+
throw new MixrPayError(data.error || "Agent run failed");
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
} catch (e) {
|
|
1826
|
+
if (e instanceof MixrPayError) throw e;
|
|
1827
|
+
this.logger.warn("Failed to parse SSE event:", e);
|
|
1828
|
+
}
|
|
1829
|
+
currentEvent = "";
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
if (!result) {
|
|
1834
|
+
throw new MixrPayError("Agent run completed without final result");
|
|
1835
|
+
}
|
|
1836
|
+
return result;
|
|
1837
|
+
}
|
|
1838
|
+
/**
|
|
1839
|
+
* Internal: Parse SSE event into typed event object
|
|
1840
|
+
*/
|
|
1841
|
+
parseSSEEvent(eventType, data) {
|
|
1842
|
+
switch (eventType) {
|
|
1843
|
+
case "run_start":
|
|
1844
|
+
return { type: "run_start", runId: data.run_id };
|
|
1845
|
+
case "iteration_start":
|
|
1846
|
+
return { type: "iteration_start", iteration: data.iteration };
|
|
1847
|
+
case "llm_chunk":
|
|
1848
|
+
return { type: "llm_chunk", delta: data.delta };
|
|
1849
|
+
case "tool_call":
|
|
1850
|
+
return { type: "tool_call", tool: data.tool, arguments: data.arguments };
|
|
1851
|
+
case "tool_result":
|
|
1852
|
+
return {
|
|
1853
|
+
type: "tool_result",
|
|
1854
|
+
tool: data.tool,
|
|
1855
|
+
success: data.success,
|
|
1856
|
+
costUsd: data.cost_usd,
|
|
1857
|
+
error: data.error
|
|
1858
|
+
};
|
|
1859
|
+
case "iteration_complete":
|
|
1860
|
+
return {
|
|
1861
|
+
type: "iteration_complete",
|
|
1862
|
+
iteration: data.iteration,
|
|
1863
|
+
tokens: data.tokens,
|
|
1864
|
+
costUsd: data.cost_usd
|
|
1865
|
+
};
|
|
1866
|
+
case "complete":
|
|
1867
|
+
return {
|
|
1868
|
+
type: "complete",
|
|
1869
|
+
runId: data.run_id,
|
|
1870
|
+
response: data.response,
|
|
1871
|
+
totalCostUsd: data.total_cost_usd,
|
|
1872
|
+
txHash: data.tx_hash,
|
|
1873
|
+
iterations: data.iterations,
|
|
1874
|
+
toolsUsed: data.tools_used
|
|
1875
|
+
};
|
|
1876
|
+
case "error":
|
|
1877
|
+
return {
|
|
1878
|
+
type: "error",
|
|
1879
|
+
error: data.error,
|
|
1880
|
+
partialCostUsd: data.partial_cost_usd
|
|
1881
|
+
};
|
|
1882
|
+
default:
|
|
1883
|
+
return null;
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
/**
|
|
1887
|
+
* Get the status of an agent run by ID.
|
|
1888
|
+
*
|
|
1889
|
+
* @param runId - The agent run ID
|
|
1890
|
+
* @param sessionId - The session ID (for authentication)
|
|
1891
|
+
* @returns Agent run status and results
|
|
1892
|
+
*
|
|
1893
|
+
* @example
|
|
1894
|
+
* ```typescript
|
|
1895
|
+
* const status = await wallet.getAgentRunStatus('run_abc123', 'sess_xyz789');
|
|
1896
|
+
* console.log(`Status: ${status.status}`);
|
|
1897
|
+
* if (status.status === 'completed') {
|
|
1898
|
+
* console.log(status.response);
|
|
1899
|
+
* }
|
|
1900
|
+
* ```
|
|
1901
|
+
*/
|
|
1902
|
+
async getAgentRunStatus(runId, sessionId) {
|
|
1903
|
+
this.logger.debug("getAgentRunStatus", { runId, sessionId });
|
|
1904
|
+
const response = await fetch(`${this.baseUrl}/api/v2/agent/run/${runId}`, {
|
|
1905
|
+
headers: {
|
|
1906
|
+
"X-Mixr-Session": sessionId
|
|
1907
|
+
}
|
|
1908
|
+
});
|
|
1909
|
+
if (!response.ok) {
|
|
1910
|
+
const error = await response.json().catch(() => ({}));
|
|
1911
|
+
throw new MixrPayError(error.error || `Failed to get run status: ${response.status}`);
|
|
1912
|
+
}
|
|
1913
|
+
const data = await response.json();
|
|
1914
|
+
return {
|
|
1915
|
+
runId: data.run_id,
|
|
1916
|
+
status: data.status,
|
|
1917
|
+
response: data.response,
|
|
1918
|
+
iterations: data.iterations,
|
|
1919
|
+
toolsUsed: data.tools_used,
|
|
1920
|
+
cost: {
|
|
1921
|
+
llmUsd: data.cost.llm_usd,
|
|
1922
|
+
toolsUsd: data.cost.tools_usd,
|
|
1923
|
+
totalUsd: data.cost.total_usd
|
|
1924
|
+
},
|
|
1925
|
+
tokens: data.tokens,
|
|
1926
|
+
txHash: data.tx_hash,
|
|
1927
|
+
error: data.error,
|
|
1928
|
+
startedAt: new Date(data.started_at),
|
|
1929
|
+
completedAt: data.completed_at ? new Date(data.completed_at) : void 0
|
|
1930
|
+
};
|
|
1931
|
+
}
|
|
1619
1932
|
/**
|
|
1620
1933
|
* Call an MCP tool using session authorization (pre-authorized spending limit).
|
|
1621
1934
|
*
|
package/dist/index.d.cts
CHANGED
|
@@ -808,6 +808,85 @@ declare class AgentWallet {
|
|
|
808
808
|
* ```
|
|
809
809
|
*/
|
|
810
810
|
callMCPTool(toolName: string, args?: Record<string, unknown>): Promise<MCPToolResult>;
|
|
811
|
+
/**
|
|
812
|
+
* Run an AI agent with LLM and tool execution.
|
|
813
|
+
*
|
|
814
|
+
* This method orchestrates a full agentic loop:
|
|
815
|
+
* - Multi-turn reasoning with LLM
|
|
816
|
+
* - Automatic tool execution
|
|
817
|
+
* - Bundled billing (single charge at end)
|
|
818
|
+
* - Optional streaming via SSE
|
|
819
|
+
*
|
|
820
|
+
* @param options - Agent run options
|
|
821
|
+
* @returns Agent run result with response and cost breakdown
|
|
822
|
+
*
|
|
823
|
+
* @example Basic usage
|
|
824
|
+
* ```typescript
|
|
825
|
+
* const result = await wallet.runAgent({
|
|
826
|
+
* sessionId: 'sess_abc123',
|
|
827
|
+
* messages: [{ role: 'user', content: 'Find AI startups in SF' }],
|
|
828
|
+
* });
|
|
829
|
+
*
|
|
830
|
+
* console.log(result.response);
|
|
831
|
+
* console.log(`Cost: $${result.cost.totalUsd.toFixed(4)}`);
|
|
832
|
+
* ```
|
|
833
|
+
*
|
|
834
|
+
* @example With custom config
|
|
835
|
+
* ```typescript
|
|
836
|
+
* const result = await wallet.runAgent({
|
|
837
|
+
* sessionId: 'sess_abc123',
|
|
838
|
+
* messages: [{ role: 'user', content: 'Research quantum computing' }],
|
|
839
|
+
* config: {
|
|
840
|
+
* model: 'gpt-4o',
|
|
841
|
+
* maxIterations: 15,
|
|
842
|
+
* tools: ['platform/exa-search', 'platform/firecrawl-scrape'],
|
|
843
|
+
* systemPrompt: 'You are a research assistant.',
|
|
844
|
+
* },
|
|
845
|
+
* });
|
|
846
|
+
* ```
|
|
847
|
+
*
|
|
848
|
+
* @example With streaming
|
|
849
|
+
* ```typescript
|
|
850
|
+
* await wallet.runAgent({
|
|
851
|
+
* sessionId: 'sess_abc123',
|
|
852
|
+
* messages: [{ role: 'user', content: 'Analyze this company' }],
|
|
853
|
+
* stream: true,
|
|
854
|
+
* onEvent: (event) => {
|
|
855
|
+
* if (event.type === 'llm_chunk') {
|
|
856
|
+
* process.stdout.write(event.delta);
|
|
857
|
+
* } else if (event.type === 'tool_call') {
|
|
858
|
+
* console.log(`Calling tool: ${event.tool}`);
|
|
859
|
+
* }
|
|
860
|
+
* },
|
|
861
|
+
* });
|
|
862
|
+
* ```
|
|
863
|
+
*/
|
|
864
|
+
runAgent(options: AgentRunOptions): Promise<AgentRunResult>;
|
|
865
|
+
/**
|
|
866
|
+
* Internal: Handle streaming agent run via SSE
|
|
867
|
+
*/
|
|
868
|
+
private runAgentStreaming;
|
|
869
|
+
/**
|
|
870
|
+
* Internal: Parse SSE event into typed event object
|
|
871
|
+
*/
|
|
872
|
+
private parseSSEEvent;
|
|
873
|
+
/**
|
|
874
|
+
* Get the status of an agent run by ID.
|
|
875
|
+
*
|
|
876
|
+
* @param runId - The agent run ID
|
|
877
|
+
* @param sessionId - The session ID (for authentication)
|
|
878
|
+
* @returns Agent run status and results
|
|
879
|
+
*
|
|
880
|
+
* @example
|
|
881
|
+
* ```typescript
|
|
882
|
+
* const status = await wallet.getAgentRunStatus('run_abc123', 'sess_xyz789');
|
|
883
|
+
* console.log(`Status: ${status.status}`);
|
|
884
|
+
* if (status.status === 'completed') {
|
|
885
|
+
* console.log(status.response);
|
|
886
|
+
* }
|
|
887
|
+
* ```
|
|
888
|
+
*/
|
|
889
|
+
getAgentRunStatus(runId: string, sessionId: string): Promise<AgentRunStatusResult>;
|
|
811
890
|
/**
|
|
812
891
|
* Call an MCP tool using session authorization (pre-authorized spending limit).
|
|
813
892
|
*
|
|
@@ -869,6 +948,157 @@ interface MCPToolResult {
|
|
|
869
948
|
/** Execution latency in milliseconds */
|
|
870
949
|
latencyMs?: number;
|
|
871
950
|
}
|
|
951
|
+
/**
|
|
952
|
+
* Message in an agent conversation
|
|
953
|
+
*/
|
|
954
|
+
interface AgentMessage {
|
|
955
|
+
/** Message role */
|
|
956
|
+
role: 'user' | 'assistant' | 'system' | 'tool';
|
|
957
|
+
/** Message content */
|
|
958
|
+
content: string;
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
* Configuration for an agent run
|
|
962
|
+
*/
|
|
963
|
+
interface AgentRunConfig {
|
|
964
|
+
/** LLM model to use (default: gpt-4o-mini) */
|
|
965
|
+
model?: string;
|
|
966
|
+
/** Maximum iterations before stopping (default: 10, max: 25) */
|
|
967
|
+
maxIterations?: number;
|
|
968
|
+
/** Specific tools to enable (e.g., ['platform/exa-search', 'platform/firecrawl-scrape']) */
|
|
969
|
+
tools?: string[];
|
|
970
|
+
/** Custom system prompt for the agent */
|
|
971
|
+
systemPrompt?: string;
|
|
972
|
+
}
|
|
973
|
+
/**
|
|
974
|
+
* Options for running an agent
|
|
975
|
+
*/
|
|
976
|
+
interface AgentRunOptions {
|
|
977
|
+
/** Session ID for authentication and billing */
|
|
978
|
+
sessionId: string;
|
|
979
|
+
/** Conversation messages */
|
|
980
|
+
messages: AgentMessage[];
|
|
981
|
+
/** Agent configuration */
|
|
982
|
+
config?: AgentRunConfig;
|
|
983
|
+
/** Enable SSE streaming (default: false) */
|
|
984
|
+
stream?: boolean;
|
|
985
|
+
/** Unique key for idempotency */
|
|
986
|
+
idempotencyKey?: string;
|
|
987
|
+
/** Callback for streaming events */
|
|
988
|
+
onEvent?: (event: AgentRunEvent) => void;
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Result from an agent run
|
|
992
|
+
*/
|
|
993
|
+
interface AgentRunResult {
|
|
994
|
+
/** Unique run ID */
|
|
995
|
+
runId: string;
|
|
996
|
+
/** Run status */
|
|
997
|
+
status: 'completed' | 'failed';
|
|
998
|
+
/** Final response from the agent */
|
|
999
|
+
response: string;
|
|
1000
|
+
/** Number of iterations performed */
|
|
1001
|
+
iterations: number;
|
|
1002
|
+
/** Tools used during the run */
|
|
1003
|
+
toolsUsed: string[];
|
|
1004
|
+
/** Cost breakdown */
|
|
1005
|
+
cost: {
|
|
1006
|
+
/** LLM cost in USD */
|
|
1007
|
+
llmUsd: number;
|
|
1008
|
+
/** Tool execution cost in USD */
|
|
1009
|
+
toolsUsd: number;
|
|
1010
|
+
/** Total cost in USD */
|
|
1011
|
+
totalUsd: number;
|
|
1012
|
+
};
|
|
1013
|
+
/** Token usage */
|
|
1014
|
+
tokens: {
|
|
1015
|
+
/** Prompt tokens used */
|
|
1016
|
+
prompt: number;
|
|
1017
|
+
/** Completion tokens used */
|
|
1018
|
+
completion: number;
|
|
1019
|
+
};
|
|
1020
|
+
/** Remaining session balance in USD */
|
|
1021
|
+
sessionRemainingUsd: number;
|
|
1022
|
+
/** On-chain transaction hash for payment */
|
|
1023
|
+
txHash?: string;
|
|
1024
|
+
}
|
|
1025
|
+
/**
|
|
1026
|
+
* Streaming events from an agent run
|
|
1027
|
+
*/
|
|
1028
|
+
type AgentRunEvent = {
|
|
1029
|
+
type: 'run_start';
|
|
1030
|
+
runId: string;
|
|
1031
|
+
} | {
|
|
1032
|
+
type: 'iteration_start';
|
|
1033
|
+
iteration: number;
|
|
1034
|
+
} | {
|
|
1035
|
+
type: 'llm_chunk';
|
|
1036
|
+
delta: string;
|
|
1037
|
+
} | {
|
|
1038
|
+
type: 'tool_call';
|
|
1039
|
+
tool: string;
|
|
1040
|
+
arguments: unknown;
|
|
1041
|
+
} | {
|
|
1042
|
+
type: 'tool_result';
|
|
1043
|
+
tool: string;
|
|
1044
|
+
success: boolean;
|
|
1045
|
+
costUsd: number;
|
|
1046
|
+
error?: string;
|
|
1047
|
+
} | {
|
|
1048
|
+
type: 'iteration_complete';
|
|
1049
|
+
iteration: number;
|
|
1050
|
+
tokens?: {
|
|
1051
|
+
prompt?: number;
|
|
1052
|
+
completion?: number;
|
|
1053
|
+
};
|
|
1054
|
+
costUsd?: number;
|
|
1055
|
+
} | {
|
|
1056
|
+
type: 'complete';
|
|
1057
|
+
runId: string;
|
|
1058
|
+
response: string;
|
|
1059
|
+
totalCostUsd: number;
|
|
1060
|
+
txHash?: string;
|
|
1061
|
+
iterations: number;
|
|
1062
|
+
toolsUsed: string[];
|
|
1063
|
+
} | {
|
|
1064
|
+
type: 'error';
|
|
1065
|
+
error: string;
|
|
1066
|
+
partialCostUsd?: number;
|
|
1067
|
+
};
|
|
1068
|
+
/**
|
|
1069
|
+
* Result from getting agent run status
|
|
1070
|
+
*/
|
|
1071
|
+
interface AgentRunStatusResult {
|
|
1072
|
+
/** Unique run ID */
|
|
1073
|
+
runId: string;
|
|
1074
|
+
/** Run status */
|
|
1075
|
+
status: 'running' | 'completed' | 'failed' | 'interrupted';
|
|
1076
|
+
/** Final response (if completed) */
|
|
1077
|
+
response?: string;
|
|
1078
|
+
/** Number of iterations performed */
|
|
1079
|
+
iterations: number;
|
|
1080
|
+
/** Tools used during the run */
|
|
1081
|
+
toolsUsed: string[];
|
|
1082
|
+
/** Cost breakdown */
|
|
1083
|
+
cost: {
|
|
1084
|
+
llmUsd: number;
|
|
1085
|
+
toolsUsd: number;
|
|
1086
|
+
totalUsd: number;
|
|
1087
|
+
};
|
|
1088
|
+
/** Token usage */
|
|
1089
|
+
tokens: {
|
|
1090
|
+
prompt: number;
|
|
1091
|
+
completion: number;
|
|
1092
|
+
};
|
|
1093
|
+
/** On-chain transaction hash */
|
|
1094
|
+
txHash?: string;
|
|
1095
|
+
/** Error message (if failed) */
|
|
1096
|
+
error?: string;
|
|
1097
|
+
/** When the run started */
|
|
1098
|
+
startedAt: Date;
|
|
1099
|
+
/** When the run completed */
|
|
1100
|
+
completedAt?: Date;
|
|
1101
|
+
}
|
|
872
1102
|
|
|
873
1103
|
/**
|
|
874
1104
|
* MixrPay Agent SDK - Custom Errors
|
|
@@ -1198,4 +1428,4 @@ declare class SessionRevokedError extends MixrPayError {
|
|
|
1198
1428
|
*/
|
|
1199
1429
|
declare function isMixrPayError(error: unknown): error is MixrPayError;
|
|
1200
1430
|
|
|
1201
|
-
export { AgentWallet, type AgentWalletConfig, type CallMerchantApiOptions, type ChargeResult, InsufficientBalanceError, InvalidSessionKeyError, MixrPayError, type PaymentEvent, PaymentFailedError, SDK_VERSION, type SessionAuthorization, SessionExpiredError, SessionKeyExpiredError, SessionLimitExceededError, SessionNotFoundError, SessionRevokedError, type SessionStats, SpendingLimitExceededError, type SpendingStats, isMixrPayError };
|
|
1431
|
+
export { type AgentMessage, type AgentRunConfig, type AgentRunEvent, type AgentRunOptions, type AgentRunResult, type AgentRunStatusResult, AgentWallet, type AgentWalletConfig, type CallMerchantApiOptions, type ChargeResult, InsufficientBalanceError, InvalidSessionKeyError, MixrPayError, type PaymentEvent, PaymentFailedError, SDK_VERSION, type SessionAuthorization, SessionExpiredError, SessionKeyExpiredError, SessionLimitExceededError, SessionNotFoundError, SessionRevokedError, type SessionStats, SpendingLimitExceededError, type SpendingStats, isMixrPayError };
|
package/dist/index.d.ts
CHANGED
|
@@ -808,6 +808,85 @@ declare class AgentWallet {
|
|
|
808
808
|
* ```
|
|
809
809
|
*/
|
|
810
810
|
callMCPTool(toolName: string, args?: Record<string, unknown>): Promise<MCPToolResult>;
|
|
811
|
+
/**
|
|
812
|
+
* Run an AI agent with LLM and tool execution.
|
|
813
|
+
*
|
|
814
|
+
* This method orchestrates a full agentic loop:
|
|
815
|
+
* - Multi-turn reasoning with LLM
|
|
816
|
+
* - Automatic tool execution
|
|
817
|
+
* - Bundled billing (single charge at end)
|
|
818
|
+
* - Optional streaming via SSE
|
|
819
|
+
*
|
|
820
|
+
* @param options - Agent run options
|
|
821
|
+
* @returns Agent run result with response and cost breakdown
|
|
822
|
+
*
|
|
823
|
+
* @example Basic usage
|
|
824
|
+
* ```typescript
|
|
825
|
+
* const result = await wallet.runAgent({
|
|
826
|
+
* sessionId: 'sess_abc123',
|
|
827
|
+
* messages: [{ role: 'user', content: 'Find AI startups in SF' }],
|
|
828
|
+
* });
|
|
829
|
+
*
|
|
830
|
+
* console.log(result.response);
|
|
831
|
+
* console.log(`Cost: $${result.cost.totalUsd.toFixed(4)}`);
|
|
832
|
+
* ```
|
|
833
|
+
*
|
|
834
|
+
* @example With custom config
|
|
835
|
+
* ```typescript
|
|
836
|
+
* const result = await wallet.runAgent({
|
|
837
|
+
* sessionId: 'sess_abc123',
|
|
838
|
+
* messages: [{ role: 'user', content: 'Research quantum computing' }],
|
|
839
|
+
* config: {
|
|
840
|
+
* model: 'gpt-4o',
|
|
841
|
+
* maxIterations: 15,
|
|
842
|
+
* tools: ['platform/exa-search', 'platform/firecrawl-scrape'],
|
|
843
|
+
* systemPrompt: 'You are a research assistant.',
|
|
844
|
+
* },
|
|
845
|
+
* });
|
|
846
|
+
* ```
|
|
847
|
+
*
|
|
848
|
+
* @example With streaming
|
|
849
|
+
* ```typescript
|
|
850
|
+
* await wallet.runAgent({
|
|
851
|
+
* sessionId: 'sess_abc123',
|
|
852
|
+
* messages: [{ role: 'user', content: 'Analyze this company' }],
|
|
853
|
+
* stream: true,
|
|
854
|
+
* onEvent: (event) => {
|
|
855
|
+
* if (event.type === 'llm_chunk') {
|
|
856
|
+
* process.stdout.write(event.delta);
|
|
857
|
+
* } else if (event.type === 'tool_call') {
|
|
858
|
+
* console.log(`Calling tool: ${event.tool}`);
|
|
859
|
+
* }
|
|
860
|
+
* },
|
|
861
|
+
* });
|
|
862
|
+
* ```
|
|
863
|
+
*/
|
|
864
|
+
runAgent(options: AgentRunOptions): Promise<AgentRunResult>;
|
|
865
|
+
/**
|
|
866
|
+
* Internal: Handle streaming agent run via SSE
|
|
867
|
+
*/
|
|
868
|
+
private runAgentStreaming;
|
|
869
|
+
/**
|
|
870
|
+
* Internal: Parse SSE event into typed event object
|
|
871
|
+
*/
|
|
872
|
+
private parseSSEEvent;
|
|
873
|
+
/**
|
|
874
|
+
* Get the status of an agent run by ID.
|
|
875
|
+
*
|
|
876
|
+
* @param runId - The agent run ID
|
|
877
|
+
* @param sessionId - The session ID (for authentication)
|
|
878
|
+
* @returns Agent run status and results
|
|
879
|
+
*
|
|
880
|
+
* @example
|
|
881
|
+
* ```typescript
|
|
882
|
+
* const status = await wallet.getAgentRunStatus('run_abc123', 'sess_xyz789');
|
|
883
|
+
* console.log(`Status: ${status.status}`);
|
|
884
|
+
* if (status.status === 'completed') {
|
|
885
|
+
* console.log(status.response);
|
|
886
|
+
* }
|
|
887
|
+
* ```
|
|
888
|
+
*/
|
|
889
|
+
getAgentRunStatus(runId: string, sessionId: string): Promise<AgentRunStatusResult>;
|
|
811
890
|
/**
|
|
812
891
|
* Call an MCP tool using session authorization (pre-authorized spending limit).
|
|
813
892
|
*
|
|
@@ -869,6 +948,157 @@ interface MCPToolResult {
|
|
|
869
948
|
/** Execution latency in milliseconds */
|
|
870
949
|
latencyMs?: number;
|
|
871
950
|
}
|
|
951
|
+
/**
|
|
952
|
+
* Message in an agent conversation
|
|
953
|
+
*/
|
|
954
|
+
interface AgentMessage {
|
|
955
|
+
/** Message role */
|
|
956
|
+
role: 'user' | 'assistant' | 'system' | 'tool';
|
|
957
|
+
/** Message content */
|
|
958
|
+
content: string;
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
* Configuration for an agent run
|
|
962
|
+
*/
|
|
963
|
+
interface AgentRunConfig {
|
|
964
|
+
/** LLM model to use (default: gpt-4o-mini) */
|
|
965
|
+
model?: string;
|
|
966
|
+
/** Maximum iterations before stopping (default: 10, max: 25) */
|
|
967
|
+
maxIterations?: number;
|
|
968
|
+
/** Specific tools to enable (e.g., ['platform/exa-search', 'platform/firecrawl-scrape']) */
|
|
969
|
+
tools?: string[];
|
|
970
|
+
/** Custom system prompt for the agent */
|
|
971
|
+
systemPrompt?: string;
|
|
972
|
+
}
|
|
973
|
+
/**
|
|
974
|
+
* Options for running an agent
|
|
975
|
+
*/
|
|
976
|
+
interface AgentRunOptions {
|
|
977
|
+
/** Session ID for authentication and billing */
|
|
978
|
+
sessionId: string;
|
|
979
|
+
/** Conversation messages */
|
|
980
|
+
messages: AgentMessage[];
|
|
981
|
+
/** Agent configuration */
|
|
982
|
+
config?: AgentRunConfig;
|
|
983
|
+
/** Enable SSE streaming (default: false) */
|
|
984
|
+
stream?: boolean;
|
|
985
|
+
/** Unique key for idempotency */
|
|
986
|
+
idempotencyKey?: string;
|
|
987
|
+
/** Callback for streaming events */
|
|
988
|
+
onEvent?: (event: AgentRunEvent) => void;
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Result from an agent run
|
|
992
|
+
*/
|
|
993
|
+
interface AgentRunResult {
|
|
994
|
+
/** Unique run ID */
|
|
995
|
+
runId: string;
|
|
996
|
+
/** Run status */
|
|
997
|
+
status: 'completed' | 'failed';
|
|
998
|
+
/** Final response from the agent */
|
|
999
|
+
response: string;
|
|
1000
|
+
/** Number of iterations performed */
|
|
1001
|
+
iterations: number;
|
|
1002
|
+
/** Tools used during the run */
|
|
1003
|
+
toolsUsed: string[];
|
|
1004
|
+
/** Cost breakdown */
|
|
1005
|
+
cost: {
|
|
1006
|
+
/** LLM cost in USD */
|
|
1007
|
+
llmUsd: number;
|
|
1008
|
+
/** Tool execution cost in USD */
|
|
1009
|
+
toolsUsd: number;
|
|
1010
|
+
/** Total cost in USD */
|
|
1011
|
+
totalUsd: number;
|
|
1012
|
+
};
|
|
1013
|
+
/** Token usage */
|
|
1014
|
+
tokens: {
|
|
1015
|
+
/** Prompt tokens used */
|
|
1016
|
+
prompt: number;
|
|
1017
|
+
/** Completion tokens used */
|
|
1018
|
+
completion: number;
|
|
1019
|
+
};
|
|
1020
|
+
/** Remaining session balance in USD */
|
|
1021
|
+
sessionRemainingUsd: number;
|
|
1022
|
+
/** On-chain transaction hash for payment */
|
|
1023
|
+
txHash?: string;
|
|
1024
|
+
}
|
|
1025
|
+
/**
|
|
1026
|
+
* Streaming events from an agent run
|
|
1027
|
+
*/
|
|
1028
|
+
type AgentRunEvent = {
|
|
1029
|
+
type: 'run_start';
|
|
1030
|
+
runId: string;
|
|
1031
|
+
} | {
|
|
1032
|
+
type: 'iteration_start';
|
|
1033
|
+
iteration: number;
|
|
1034
|
+
} | {
|
|
1035
|
+
type: 'llm_chunk';
|
|
1036
|
+
delta: string;
|
|
1037
|
+
} | {
|
|
1038
|
+
type: 'tool_call';
|
|
1039
|
+
tool: string;
|
|
1040
|
+
arguments: unknown;
|
|
1041
|
+
} | {
|
|
1042
|
+
type: 'tool_result';
|
|
1043
|
+
tool: string;
|
|
1044
|
+
success: boolean;
|
|
1045
|
+
costUsd: number;
|
|
1046
|
+
error?: string;
|
|
1047
|
+
} | {
|
|
1048
|
+
type: 'iteration_complete';
|
|
1049
|
+
iteration: number;
|
|
1050
|
+
tokens?: {
|
|
1051
|
+
prompt?: number;
|
|
1052
|
+
completion?: number;
|
|
1053
|
+
};
|
|
1054
|
+
costUsd?: number;
|
|
1055
|
+
} | {
|
|
1056
|
+
type: 'complete';
|
|
1057
|
+
runId: string;
|
|
1058
|
+
response: string;
|
|
1059
|
+
totalCostUsd: number;
|
|
1060
|
+
txHash?: string;
|
|
1061
|
+
iterations: number;
|
|
1062
|
+
toolsUsed: string[];
|
|
1063
|
+
} | {
|
|
1064
|
+
type: 'error';
|
|
1065
|
+
error: string;
|
|
1066
|
+
partialCostUsd?: number;
|
|
1067
|
+
};
|
|
1068
|
+
/**
|
|
1069
|
+
* Result from getting agent run status
|
|
1070
|
+
*/
|
|
1071
|
+
interface AgentRunStatusResult {
|
|
1072
|
+
/** Unique run ID */
|
|
1073
|
+
runId: string;
|
|
1074
|
+
/** Run status */
|
|
1075
|
+
status: 'running' | 'completed' | 'failed' | 'interrupted';
|
|
1076
|
+
/** Final response (if completed) */
|
|
1077
|
+
response?: string;
|
|
1078
|
+
/** Number of iterations performed */
|
|
1079
|
+
iterations: number;
|
|
1080
|
+
/** Tools used during the run */
|
|
1081
|
+
toolsUsed: string[];
|
|
1082
|
+
/** Cost breakdown */
|
|
1083
|
+
cost: {
|
|
1084
|
+
llmUsd: number;
|
|
1085
|
+
toolsUsd: number;
|
|
1086
|
+
totalUsd: number;
|
|
1087
|
+
};
|
|
1088
|
+
/** Token usage */
|
|
1089
|
+
tokens: {
|
|
1090
|
+
prompt: number;
|
|
1091
|
+
completion: number;
|
|
1092
|
+
};
|
|
1093
|
+
/** On-chain transaction hash */
|
|
1094
|
+
txHash?: string;
|
|
1095
|
+
/** Error message (if failed) */
|
|
1096
|
+
error?: string;
|
|
1097
|
+
/** When the run started */
|
|
1098
|
+
startedAt: Date;
|
|
1099
|
+
/** When the run completed */
|
|
1100
|
+
completedAt?: Date;
|
|
1101
|
+
}
|
|
872
1102
|
|
|
873
1103
|
/**
|
|
874
1104
|
* MixrPay Agent SDK - Custom Errors
|
|
@@ -1198,4 +1428,4 @@ declare class SessionRevokedError extends MixrPayError {
|
|
|
1198
1428
|
*/
|
|
1199
1429
|
declare function isMixrPayError(error: unknown): error is MixrPayError;
|
|
1200
1430
|
|
|
1201
|
-
export { AgentWallet, type AgentWalletConfig, type CallMerchantApiOptions, type ChargeResult, InsufficientBalanceError, InvalidSessionKeyError, MixrPayError, type PaymentEvent, PaymentFailedError, SDK_VERSION, type SessionAuthorization, SessionExpiredError, SessionKeyExpiredError, SessionLimitExceededError, SessionNotFoundError, SessionRevokedError, type SessionStats, SpendingLimitExceededError, type SpendingStats, isMixrPayError };
|
|
1431
|
+
export { type AgentMessage, type AgentRunConfig, type AgentRunEvent, type AgentRunOptions, type AgentRunResult, type AgentRunStatusResult, AgentWallet, type AgentWalletConfig, type CallMerchantApiOptions, type ChargeResult, InsufficientBalanceError, InvalidSessionKeyError, MixrPayError, type PaymentEvent, PaymentFailedError, SDK_VERSION, type SessionAuthorization, SessionExpiredError, SessionKeyExpiredError, SessionLimitExceededError, SessionNotFoundError, SessionRevokedError, type SessionStats, SpendingLimitExceededError, type SpendingStats, isMixrPayError };
|
package/dist/index.js
CHANGED
|
@@ -1582,6 +1582,319 @@ Timestamp: ${timestamp}`;
|
|
|
1582
1582
|
latencyMs: mixrpay.latencyMs
|
|
1583
1583
|
};
|
|
1584
1584
|
}
|
|
1585
|
+
// ===========================================================================
|
|
1586
|
+
// Agent Runtime API
|
|
1587
|
+
// ===========================================================================
|
|
1588
|
+
/**
|
|
1589
|
+
* Run an AI agent with LLM and tool execution.
|
|
1590
|
+
*
|
|
1591
|
+
* This method orchestrates a full agentic loop:
|
|
1592
|
+
* - Multi-turn reasoning with LLM
|
|
1593
|
+
* - Automatic tool execution
|
|
1594
|
+
* - Bundled billing (single charge at end)
|
|
1595
|
+
* - Optional streaming via SSE
|
|
1596
|
+
*
|
|
1597
|
+
* @param options - Agent run options
|
|
1598
|
+
* @returns Agent run result with response and cost breakdown
|
|
1599
|
+
*
|
|
1600
|
+
* @example Basic usage
|
|
1601
|
+
* ```typescript
|
|
1602
|
+
* const result = await wallet.runAgent({
|
|
1603
|
+
* sessionId: 'sess_abc123',
|
|
1604
|
+
* messages: [{ role: 'user', content: 'Find AI startups in SF' }],
|
|
1605
|
+
* });
|
|
1606
|
+
*
|
|
1607
|
+
* console.log(result.response);
|
|
1608
|
+
* console.log(`Cost: $${result.cost.totalUsd.toFixed(4)}`);
|
|
1609
|
+
* ```
|
|
1610
|
+
*
|
|
1611
|
+
* @example With custom config
|
|
1612
|
+
* ```typescript
|
|
1613
|
+
* const result = await wallet.runAgent({
|
|
1614
|
+
* sessionId: 'sess_abc123',
|
|
1615
|
+
* messages: [{ role: 'user', content: 'Research quantum computing' }],
|
|
1616
|
+
* config: {
|
|
1617
|
+
* model: 'gpt-4o',
|
|
1618
|
+
* maxIterations: 15,
|
|
1619
|
+
* tools: ['platform/exa-search', 'platform/firecrawl-scrape'],
|
|
1620
|
+
* systemPrompt: 'You are a research assistant.',
|
|
1621
|
+
* },
|
|
1622
|
+
* });
|
|
1623
|
+
* ```
|
|
1624
|
+
*
|
|
1625
|
+
* @example With streaming
|
|
1626
|
+
* ```typescript
|
|
1627
|
+
* await wallet.runAgent({
|
|
1628
|
+
* sessionId: 'sess_abc123',
|
|
1629
|
+
* messages: [{ role: 'user', content: 'Analyze this company' }],
|
|
1630
|
+
* stream: true,
|
|
1631
|
+
* onEvent: (event) => {
|
|
1632
|
+
* if (event.type === 'llm_chunk') {
|
|
1633
|
+
* process.stdout.write(event.delta);
|
|
1634
|
+
* } else if (event.type === 'tool_call') {
|
|
1635
|
+
* console.log(`Calling tool: ${event.tool}`);
|
|
1636
|
+
* }
|
|
1637
|
+
* },
|
|
1638
|
+
* });
|
|
1639
|
+
* ```
|
|
1640
|
+
*/
|
|
1641
|
+
async runAgent(options) {
|
|
1642
|
+
const {
|
|
1643
|
+
sessionId,
|
|
1644
|
+
messages,
|
|
1645
|
+
config = {},
|
|
1646
|
+
stream = false,
|
|
1647
|
+
idempotencyKey,
|
|
1648
|
+
onEvent
|
|
1649
|
+
} = options;
|
|
1650
|
+
this.logger.debug("runAgent", { sessionId, messageCount: messages.length, config, stream });
|
|
1651
|
+
const body = {
|
|
1652
|
+
session_id: sessionId,
|
|
1653
|
+
messages: messages.map((m) => ({ role: m.role, content: m.content })),
|
|
1654
|
+
config: {
|
|
1655
|
+
model: config.model,
|
|
1656
|
+
max_iterations: config.maxIterations,
|
|
1657
|
+
tools: config.tools,
|
|
1658
|
+
system_prompt: config.systemPrompt
|
|
1659
|
+
},
|
|
1660
|
+
stream,
|
|
1661
|
+
idempotency_key: idempotencyKey
|
|
1662
|
+
};
|
|
1663
|
+
const AGENT_RUN_TIMEOUT = 18e4;
|
|
1664
|
+
if (!stream) {
|
|
1665
|
+
const response = await fetch(`${this.baseUrl}/api/v2/agent/run`, {
|
|
1666
|
+
method: "POST",
|
|
1667
|
+
headers: {
|
|
1668
|
+
"Content-Type": "application/json",
|
|
1669
|
+
"X-Mixr-Session": sessionId
|
|
1670
|
+
},
|
|
1671
|
+
body: JSON.stringify(body),
|
|
1672
|
+
signal: AbortSignal.timeout(AGENT_RUN_TIMEOUT)
|
|
1673
|
+
});
|
|
1674
|
+
if (!response.ok) {
|
|
1675
|
+
const error = await response.json().catch(() => ({}));
|
|
1676
|
+
throw new MixrPayError(error.error || `Agent run failed: ${response.status}`);
|
|
1677
|
+
}
|
|
1678
|
+
const data = await response.json();
|
|
1679
|
+
if (data.cost?.total_usd > 0) {
|
|
1680
|
+
const payment = {
|
|
1681
|
+
amountUsd: data.cost.total_usd,
|
|
1682
|
+
recipient: "mixrpay-agent-run",
|
|
1683
|
+
txHash: data.tx_hash,
|
|
1684
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
1685
|
+
description: `Agent run: ${data.run_id}`,
|
|
1686
|
+
url: `${this.baseUrl}/api/v2/agent/run`
|
|
1687
|
+
};
|
|
1688
|
+
this.payments.push(payment);
|
|
1689
|
+
this.totalSpentUsd += data.cost.total_usd;
|
|
1690
|
+
this.logger.payment(data.cost.total_usd, "agent-run", data.run_id);
|
|
1691
|
+
if (this.onPayment) {
|
|
1692
|
+
this.onPayment(payment);
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
return {
|
|
1696
|
+
runId: data.run_id,
|
|
1697
|
+
status: data.status,
|
|
1698
|
+
response: data.response,
|
|
1699
|
+
iterations: data.iterations,
|
|
1700
|
+
toolsUsed: data.tools_used,
|
|
1701
|
+
cost: {
|
|
1702
|
+
llmUsd: data.cost.llm_usd,
|
|
1703
|
+
toolsUsd: data.cost.tools_usd,
|
|
1704
|
+
totalUsd: data.cost.total_usd
|
|
1705
|
+
},
|
|
1706
|
+
tokens: data.tokens,
|
|
1707
|
+
sessionRemainingUsd: data.session_remaining_usd,
|
|
1708
|
+
txHash: data.tx_hash
|
|
1709
|
+
};
|
|
1710
|
+
}
|
|
1711
|
+
return this.runAgentStreaming(sessionId, body, onEvent);
|
|
1712
|
+
}
|
|
1713
|
+
/**
|
|
1714
|
+
* Internal: Handle streaming agent run via SSE
|
|
1715
|
+
*/
|
|
1716
|
+
async runAgentStreaming(sessionId, body, onEvent) {
|
|
1717
|
+
const STREAMING_TIMEOUT = 3e5;
|
|
1718
|
+
const response = await fetch(`${this.baseUrl}/api/v2/agent/run`, {
|
|
1719
|
+
method: "POST",
|
|
1720
|
+
headers: {
|
|
1721
|
+
"Content-Type": "application/json",
|
|
1722
|
+
"X-Mixr-Session": sessionId
|
|
1723
|
+
},
|
|
1724
|
+
body: JSON.stringify(body),
|
|
1725
|
+
signal: AbortSignal.timeout(STREAMING_TIMEOUT)
|
|
1726
|
+
});
|
|
1727
|
+
if (!response.ok) {
|
|
1728
|
+
const error = await response.json().catch(() => ({}));
|
|
1729
|
+
throw new MixrPayError(error.error || `Agent run failed: ${response.status}`);
|
|
1730
|
+
}
|
|
1731
|
+
const reader = response.body?.getReader();
|
|
1732
|
+
if (!reader) {
|
|
1733
|
+
throw new MixrPayError("No response body for streaming");
|
|
1734
|
+
}
|
|
1735
|
+
const decoder = new TextDecoder();
|
|
1736
|
+
let buffer = "";
|
|
1737
|
+
let result = null;
|
|
1738
|
+
while (true) {
|
|
1739
|
+
const { done, value } = await reader.read();
|
|
1740
|
+
if (done) break;
|
|
1741
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1742
|
+
const lines = buffer.split("\n");
|
|
1743
|
+
buffer = lines.pop() || "";
|
|
1744
|
+
let currentEvent = "";
|
|
1745
|
+
for (const line of lines) {
|
|
1746
|
+
if (line.startsWith("event: ")) {
|
|
1747
|
+
currentEvent = line.slice(7).trim();
|
|
1748
|
+
} else if (line.startsWith("data: ") && currentEvent) {
|
|
1749
|
+
try {
|
|
1750
|
+
const data = JSON.parse(line.slice(6));
|
|
1751
|
+
const event = this.parseSSEEvent(currentEvent, data);
|
|
1752
|
+
if (event) {
|
|
1753
|
+
onEvent?.(event);
|
|
1754
|
+
if (currentEvent === "complete") {
|
|
1755
|
+
result = {
|
|
1756
|
+
runId: data.run_id,
|
|
1757
|
+
status: "completed",
|
|
1758
|
+
response: data.response,
|
|
1759
|
+
iterations: data.iterations,
|
|
1760
|
+
toolsUsed: data.tools_used,
|
|
1761
|
+
cost: {
|
|
1762
|
+
llmUsd: 0,
|
|
1763
|
+
// Not provided in streaming complete
|
|
1764
|
+
toolsUsd: 0,
|
|
1765
|
+
totalUsd: data.total_cost_usd
|
|
1766
|
+
},
|
|
1767
|
+
tokens: { prompt: 0, completion: 0 },
|
|
1768
|
+
sessionRemainingUsd: 0,
|
|
1769
|
+
txHash: data.tx_hash
|
|
1770
|
+
};
|
|
1771
|
+
if (data.total_cost_usd > 0) {
|
|
1772
|
+
const payment = {
|
|
1773
|
+
amountUsd: data.total_cost_usd,
|
|
1774
|
+
recipient: "mixrpay-agent-run",
|
|
1775
|
+
txHash: data.tx_hash,
|
|
1776
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
1777
|
+
description: `Agent run: ${data.run_id}`,
|
|
1778
|
+
url: `${this.baseUrl}/api/v2/agent/run`
|
|
1779
|
+
};
|
|
1780
|
+
this.payments.push(payment);
|
|
1781
|
+
this.totalSpentUsd += data.total_cost_usd;
|
|
1782
|
+
if (this.onPayment) {
|
|
1783
|
+
this.onPayment(payment);
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
if (currentEvent === "error") {
|
|
1788
|
+
throw new MixrPayError(data.error || "Agent run failed");
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
} catch (e) {
|
|
1792
|
+
if (e instanceof MixrPayError) throw e;
|
|
1793
|
+
this.logger.warn("Failed to parse SSE event:", e);
|
|
1794
|
+
}
|
|
1795
|
+
currentEvent = "";
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
if (!result) {
|
|
1800
|
+
throw new MixrPayError("Agent run completed without final result");
|
|
1801
|
+
}
|
|
1802
|
+
return result;
|
|
1803
|
+
}
|
|
1804
|
+
/**
|
|
1805
|
+
* Internal: Parse SSE event into typed event object
|
|
1806
|
+
*/
|
|
1807
|
+
parseSSEEvent(eventType, data) {
|
|
1808
|
+
switch (eventType) {
|
|
1809
|
+
case "run_start":
|
|
1810
|
+
return { type: "run_start", runId: data.run_id };
|
|
1811
|
+
case "iteration_start":
|
|
1812
|
+
return { type: "iteration_start", iteration: data.iteration };
|
|
1813
|
+
case "llm_chunk":
|
|
1814
|
+
return { type: "llm_chunk", delta: data.delta };
|
|
1815
|
+
case "tool_call":
|
|
1816
|
+
return { type: "tool_call", tool: data.tool, arguments: data.arguments };
|
|
1817
|
+
case "tool_result":
|
|
1818
|
+
return {
|
|
1819
|
+
type: "tool_result",
|
|
1820
|
+
tool: data.tool,
|
|
1821
|
+
success: data.success,
|
|
1822
|
+
costUsd: data.cost_usd,
|
|
1823
|
+
error: data.error
|
|
1824
|
+
};
|
|
1825
|
+
case "iteration_complete":
|
|
1826
|
+
return {
|
|
1827
|
+
type: "iteration_complete",
|
|
1828
|
+
iteration: data.iteration,
|
|
1829
|
+
tokens: data.tokens,
|
|
1830
|
+
costUsd: data.cost_usd
|
|
1831
|
+
};
|
|
1832
|
+
case "complete":
|
|
1833
|
+
return {
|
|
1834
|
+
type: "complete",
|
|
1835
|
+
runId: data.run_id,
|
|
1836
|
+
response: data.response,
|
|
1837
|
+
totalCostUsd: data.total_cost_usd,
|
|
1838
|
+
txHash: data.tx_hash,
|
|
1839
|
+
iterations: data.iterations,
|
|
1840
|
+
toolsUsed: data.tools_used
|
|
1841
|
+
};
|
|
1842
|
+
case "error":
|
|
1843
|
+
return {
|
|
1844
|
+
type: "error",
|
|
1845
|
+
error: data.error,
|
|
1846
|
+
partialCostUsd: data.partial_cost_usd
|
|
1847
|
+
};
|
|
1848
|
+
default:
|
|
1849
|
+
return null;
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
/**
|
|
1853
|
+
* Get the status of an agent run by ID.
|
|
1854
|
+
*
|
|
1855
|
+
* @param runId - The agent run ID
|
|
1856
|
+
* @param sessionId - The session ID (for authentication)
|
|
1857
|
+
* @returns Agent run status and results
|
|
1858
|
+
*
|
|
1859
|
+
* @example
|
|
1860
|
+
* ```typescript
|
|
1861
|
+
* const status = await wallet.getAgentRunStatus('run_abc123', 'sess_xyz789');
|
|
1862
|
+
* console.log(`Status: ${status.status}`);
|
|
1863
|
+
* if (status.status === 'completed') {
|
|
1864
|
+
* console.log(status.response);
|
|
1865
|
+
* }
|
|
1866
|
+
* ```
|
|
1867
|
+
*/
|
|
1868
|
+
async getAgentRunStatus(runId, sessionId) {
|
|
1869
|
+
this.logger.debug("getAgentRunStatus", { runId, sessionId });
|
|
1870
|
+
const response = await fetch(`${this.baseUrl}/api/v2/agent/run/${runId}`, {
|
|
1871
|
+
headers: {
|
|
1872
|
+
"X-Mixr-Session": sessionId
|
|
1873
|
+
}
|
|
1874
|
+
});
|
|
1875
|
+
if (!response.ok) {
|
|
1876
|
+
const error = await response.json().catch(() => ({}));
|
|
1877
|
+
throw new MixrPayError(error.error || `Failed to get run status: ${response.status}`);
|
|
1878
|
+
}
|
|
1879
|
+
const data = await response.json();
|
|
1880
|
+
return {
|
|
1881
|
+
runId: data.run_id,
|
|
1882
|
+
status: data.status,
|
|
1883
|
+
response: data.response,
|
|
1884
|
+
iterations: data.iterations,
|
|
1885
|
+
toolsUsed: data.tools_used,
|
|
1886
|
+
cost: {
|
|
1887
|
+
llmUsd: data.cost.llm_usd,
|
|
1888
|
+
toolsUsd: data.cost.tools_usd,
|
|
1889
|
+
totalUsd: data.cost.total_usd
|
|
1890
|
+
},
|
|
1891
|
+
tokens: data.tokens,
|
|
1892
|
+
txHash: data.tx_hash,
|
|
1893
|
+
error: data.error,
|
|
1894
|
+
startedAt: new Date(data.started_at),
|
|
1895
|
+
completedAt: data.completed_at ? new Date(data.completed_at) : void 0
|
|
1896
|
+
};
|
|
1897
|
+
}
|
|
1585
1898
|
/**
|
|
1586
1899
|
* Call an MCP tool using session authorization (pre-authorized spending limit).
|
|
1587
1900
|
*
|