@circuitorg/agent-sdk 1.0.12 → 1.1.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/README.md CHANGED
@@ -8,7 +8,7 @@ A TypeScript SDK for building automated agents to deploy on Circuit. Features a
8
8
 
9
9
  ## ✨ Features
10
10
 
11
- - **🎯 Simple API**: Only 2 main methods - `addMessage()` and `signAndSend()`
11
+ - **🎯 Simple API**: Only 2 main methods - `sendLog()` and `signAndSend()`
12
12
  - **🔒 Type Safety**: Network parameter determines valid request shapes automatically
13
13
  - **🚀 Cross-Chain**: Unified interface for EVM and Solana networks
14
14
 
@@ -36,10 +36,10 @@ const sdk = new AgentSdk({
36
36
 
37
37
  ## 🎯 Core SDK API (Only 2 Methods!)
38
38
 
39
- ### 1. Add Messages to Timeline
39
+ ### 1. Add Logs to Timeline
40
40
 
41
41
  ```typescript
42
- await sdk.addMessage({
42
+ await sdk.sendLog({
43
43
  type: "observe",
44
44
  shortMessage: "Starting swap operation"
45
45
  });
@@ -104,14 +104,14 @@ const executionFunction: ExecutionFunctionContract = async (request) => {
104
104
  // Get user's wallet address (use vitalik.eth for demo if no address provided)
105
105
  const userAddress = request.sessionWalletAddress
106
106
 
107
- await sdk.addMessage({
107
+ await sdk.sendLog({
108
108
  type: "observe",
109
109
  shortMessage: `🚀 Agent SDK v1.0 demo - Hello ${userAddress}`
110
110
  });
111
111
 
112
112
  return { success: true};
113
113
  } catch (error) {
114
- await sdk.addMessage({
114
+ await sdk.sendLog({
115
115
  type: "error",
116
116
  shortMessage: `Agent execution error: ${error instanceof Error ? error.message : 'Unknown error'}`
117
117
  });
@@ -126,7 +126,7 @@ const stopFunction: StopFunctionContract = async (request) => {
126
126
  });
127
127
 
128
128
  try {
129
- await sdk.addMessage({
129
+ await sdk.sendLog({
130
130
  type: "observe",
131
131
  shortMessage: "🛑 Agent stopping with new SDK v1.0"
132
132
  });
@@ -287,7 +287,7 @@ const executionFunction: ExecutionFunctionContract = async (request) => {
287
287
  });
288
288
 
289
289
  try {
290
- await sdk.addMessage({
290
+ await sdk.sendLog({
291
291
  type: "observe",
292
292
  shortMessage:
293
293
  "🚀 Starting Agent SDK v1.0 comprehensive demo -- live test",
@@ -305,7 +305,7 @@ const executionFunction: ExecutionFunctionContract = async (request) => {
305
305
  pepeBalance.decimals
306
306
  );
307
307
 
308
- await sdk.addMessage({
308
+ await sdk.sendLog({
309
309
  type: "observe",
310
310
  shortMessage: `PEPE Balance (Arbitrum): ${pepeBalanceFormatted} PEPE`,
311
311
  });
@@ -334,7 +334,7 @@ const executionFunction: ExecutionFunctionContract = async (request) => {
334
334
  });
335
335
 
336
336
 
337
- await sdk.addMessage({
337
+ await sdk.sendLog({
338
338
  type: "observe",
339
339
  shortMessage:
340
340
  "✅ Agent SDK v1.0 comprehensive demo completed successfully!",
@@ -344,7 +344,7 @@ const executionFunction: ExecutionFunctionContract = async (request) => {
344
344
  } catch (error) {
345
345
  console.error("💥 Agent execution error:", error);
346
346
 
347
- await sdk.addMessage({
347
+ await sdk.sendLog({
348
348
  type: "error",
349
349
  shortMessage: `Agent execution error: ${
350
350
  error instanceof Error ? error.message : "Unknown error"
@@ -375,7 +375,7 @@ const stopFunction: StopFunctionContract = async (request) => {
375
375
  });
376
376
 
377
377
  try {
378
- await sdk.addMessage({
378
+ await sdk.sendLog({
379
379
  type: "observe",
380
380
  shortMessage: "🛑 Agent stopping with new SDK v1.0",
381
381
  });
package/index.d.ts CHANGED
@@ -33,12 +33,22 @@ type SignAndSendRequest = {
33
33
  * Standard response from signAndSend operations
34
34
  */
35
35
  type SignAndSendResponse = {
36
- /** Internal transaction ID for tracking */
37
- internalTransactionId: number;
38
- /** Transaction hash once broadcast */
39
- txHash: string;
40
- /** Optional transaction URL (explorer link) */
36
+ /** Whether the operation was successful */
37
+ success: boolean;
38
+ /** Internal transaction ID for tracking (only present on success) */
39
+ internalTransactionId?: number;
40
+ /** Transaction hash once broadcast (only present on success) */
41
+ txHash?: string;
42
+ /** Optional transaction URL (explorer link) (only present on success) */
41
43
  transactionUrl?: string;
44
+ /** Error message (only present on failure) */
45
+ error?: string;
46
+ /** Detailed error information (only present on failure) */
47
+ errorDetails?: {
48
+ message: string;
49
+ status?: number;
50
+ statusText?: string;
51
+ };
42
52
  };
43
53
  /**
44
54
  * EIP712 TypedData schema for typed message signing
@@ -136,6 +146,19 @@ interface SDKConfig {
136
146
  baseUrl?: string;
137
147
  }
138
148
 
149
+ /**
150
+ * Job status tracking types for Event invocation support
151
+ */
152
+ interface UpdateJobStatusRequest {
153
+ jobId: string;
154
+ status: "pending" | "success" | "failed";
155
+ errorMessage?: string;
156
+ }
157
+ interface UpdateJobStatusResponse {
158
+ status: number;
159
+ message: string;
160
+ }
161
+
139
162
  /**
140
163
  * Main AgentSdk class with simplified API surface
141
164
  */
@@ -295,6 +318,13 @@ declare class AgentSdk {
295
318
  * Send logs to the agent timeline (migrated from AgentToolset)
296
319
  */
297
320
  private _sendLog;
321
+ /**
322
+ * Internal method to update job status. Used by the Agent wrapper for automatic tracking.
323
+ *
324
+ * This method is not intended for direct use by agent developers - job status tracking
325
+ * is handled automatically by the Agent wrapper.
326
+ */
327
+ _updateJobStatus(request: UpdateJobStatusRequest): Promise<UpdateJobStatusResponse>;
298
328
  }
299
329
 
300
330
  /**
@@ -358,6 +388,7 @@ declare class APIClient {
358
388
  declare const AgentRequestSchema: z.ZodObject<{
359
389
  sessionId: z.ZodNumber;
360
390
  sessionWalletAddress: z.ZodString;
391
+ jobId: z.ZodOptional<z.ZodString>;
361
392
  otherParameters: z.ZodOptional<z.ZodObject<{}, z.core.$strip>>;
362
393
  }, z.core.$strip>;
363
394
  /**
@@ -505,7 +536,7 @@ interface AgentConfig {
505
536
  *
506
537
  * Exposes the following endpoints:
507
538
  * - `POST /execute` — required, calls your execution function
508
- * - `POST /stop` and `DELETE /` optional, when a `stopFunction` is provided
539
+ * - `POST /stop` always available, uses provided or default stop function
509
540
  * - `GET /health` — always available, uses provided or default health check
510
541
  */
511
542
  declare class Agent {
@@ -518,6 +549,18 @@ declare class Agent {
518
549
  * @param config - Execution function is required; chat/stop/health are optional.
519
550
  */
520
551
  constructor(config: AgentConfig);
552
+ /**
553
+ * Default stop function when no custom stop function is provided.
554
+ */
555
+ private defaultStopFunction;
556
+ /**
557
+ * Execute a function with automatic job status tracking.
558
+ */
559
+ private executeWithJobTracking;
560
+ /**
561
+ * Update job status using the AgentSdk.
562
+ */
563
+ private updateJobStatus;
521
564
  private setupRoutes;
522
565
  private getPortFromPackageJson;
523
566
  run(port?: number): {
package/index.js CHANGED
@@ -1 +1 @@
1
- var __getOwnPropNames=Object.getOwnPropertyNames,__require=(t=>"undefined"!=typeof require?require:"undefined"!=typeof Proxy?new Proxy(t,{get:(t,e)=>("undefined"!=typeof require?require:t)[e]}):t)(function(t){if("undefined"!=typeof require)return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')}),__commonJS=(t,e)=>function(){return e||(0,t[__getOwnPropNames(t)[0]])((e={exports:{}}).exports,e),e.exports},require_auth_loader=__commonJS({"src/utils/auth-loader.cjs"(exports,module){function loadAuthFromFileSystem(){try{if("undefined"==typeof process||!process.env?.HOME)return;const fs=eval("require")("fs"),path=eval("require")("path"),authPath=path.join(process.env.HOME,".config","circuit","auth.json");if(!fs.existsSync(authPath))return;const authContent=fs.readFileSync(authPath,"utf-8");return JSON.parse(authContent)}catch(t){return}}module.exports={loadAuthFromFileSystem:loadAuthFromFileSystem}}}),API_BASE_URL_LOCAL="https://agents.circuit.org",APIClient=class{config;baseUrl;isCloudflareWorker(){return"undefined"!=typeof globalThis&&void 0!==globalThis.Cloudflare}hasServiceBinding(){let t=!1;return this.isCloudflareWorker()&&(void 0!==globalThis.AGENTS_TO_API_PROXY||void 0!==globalThis.__AGENT_ENV__&&globalThis.__AGENT_ENV__?.AGENTS_TO_API_PROXY)&&(t=!0),this.config.verbose,t}constructor(t){this.config=t,this.baseUrl=t.baseUrl||API_BASE_URL_LOCAL}getAgentSlug(){return"undefined"!=typeof process&&process.env?.CIRCUIT_AGENT_SLUG?process.env.CIRCUIT_AGENT_SLUG:void 0!==globalThis.CIRCUIT_AGENT_SLUG?globalThis.CIRCUIT_AGENT_SLUG:void 0}getAuthHeaders(){const t={};t["X-Session-Id"]=this.config.sessionId.toString();const e=this.getAgentSlug();if(e&&(t["X-Agent-Slug"]=e),!this.hasServiceBinding())try{const e=this.loadAuthConfig();e?.sessionToken&&(t.Authorization=`Bearer ${e.sessionToken}`)}catch(t){}return t}loadAuthConfig(){try{const{loadAuthFromFileSystem:t}=require_auth_loader();return t()}catch(t){this.config.verbose}}logging(t,e){this.config.verbose}async makeRequest(t,e={}){const s={...{"Content-Type":"application/json",...this.getAuthHeaders()},...e.headers};let r;if(this.logging("=== REQUEST DETAILS ==="),this.logging("Endpoint:",t),this.logging("Method:",e.method||"GET"),this.logging("Headers:",s),this.logging("Body:",e.body),this.logging("Session ID:",this.config.sessionId),this.logging("Agent Slug:",this.getAgentSlug()||"not set"),this.logging("Using Service Binding:",this.hasServiceBinding()),this.logging("====================="),this.hasServiceBinding()){let n;if(void 0!==globalThis.AGENTS_TO_API_PROXY)n=globalThis.AGENTS_TO_API_PROXY;else{if(void 0===globalThis.__AGENT_ENV__||!globalThis.__AGENT_ENV__?.AGENTS_TO_API_PROXY)throw new Error("Service binding detected but not accessible");n=globalThis.__AGENT_ENV__.AGENTS_TO_API_PROXY}this.logging("Using service binding AGENTS_TO_API_PROXY"),this.logging("Service binding type:",typeof n);const o={...e,headers:s},i=`https://agents-to-api-proxy.circuit-0bc.workers.dev${t}`;r=await n.fetch(i,o)}else{this.logging("Using HTTP fallback to:",this.baseUrl);const n=`${this.baseUrl}${t}`,o={...e,headers:s};r=await fetch(n,o)}if(this.logging("=== RESPONSE DETAILS ==="),this.logging("Status:",r.status),this.logging("Status Text:",r.statusText),this.logging("Response Headers:",Object.fromEntries(r.headers.entries())),this.logging("======================"),!r.ok){const t=await r.json().catch(()=>({}));throw this.logging("=== ERROR RESPONSE ==="),this.logging("Error Data:",t),this.logging("===================="),new Error(t.message||`HTTP ${r.status}: ${r.statusText}`)}const n=await r.json();return this.logging("=== SUCCESS RESPONSE ==="),this.logging("Response Data:",n),this.logging("======================"),n}async get(t){return this.makeRequest(t,{method:"GET"})}async post(t,e){return this.makeRequest(t,{method:"POST",body:e?JSON.stringify(e):void 0})}};function isEthereumNetwork(t){return t.startsWith("ethereum:")}function isSolanaNetwork(t){return"solana"===t}function getChainIdFromNetwork(t){return Number(t.split(":")[1])}var AgentSdk=class{client;config;constructor(t){this.config=t,this.client=new APIClient(t)}logging(t,e){this.config.verbose}async sendLog(t){this.logging("=== ADD MESSAGE ==="),this.logging("Message:",t),this.logging("==================="),await this.t([t])}async signAndSend(t){if(this.logging("=== SIGN AND SEND ==="),this.logging("Request:",t),this.logging("Testing mode:",this.config.testing),this.logging("===================="),this.config.testing)return{internalTransactionId:123,txHash:isEthereumNetwork(t.network)?"0xTEST":"TEST_SOL_TX",transactionUrl:void 0};if(isEthereumNetwork(t.network)){const e=getChainIdFromNetwork(t.network);if("toAddress"in t.request)return this.handleEvmTransaction({chainId:e,toAddress:t.request.toAddress,data:t.request.data,valueWei:t.request.value,message:t.message})}if(isSolanaNetwork(t.network)&&"hexTransaction"in t.request)return this.handleSolanaTransaction({hexTransaction:t.request.hexTransaction,message:t.message});throw new Error(`Unsupported network: ${t.network}`)}async signMessage(t){if(this.logging("=== SIGN MESSAGE ==="),this.logging("Request:",t),this.logging("Testing mode:",this.config.testing),this.logging("===================="),this.config.testing)return{v:27,r:"0xTEST_R",s:"0xTEST_S",formattedSignature:"0xTEST_FORMATTED",type:"evm"};if(isEthereumNetwork(t.network))return this.handleEvmSignMessage(t);throw new Error(`Unsupported network: ${t.network}`)}async handleEvmTransaction(t){const e=await this.client.post("/v1/transactions/evm",t),s=await this.client.post(`/v1/transactions/evm/${e.internalTransactionId}/broadcast`);return{internalTransactionId:e.internalTransactionId,txHash:s.txHash,transactionUrl:s.transactionUrl}}async handleSolanaTransaction(t){const e=await this.client.post("/v1/transactions/solana",t),s=await this.client.post(`/v1/transactions/solana/${e.internalTransactionId}/broadcast`);return{internalTransactionId:e.internalTransactionId,txHash:s.txHash,transactionUrl:s.transactionUrl}}async handleEvmSignMessage(t){return await this.client.post("/v1/messages/evm",{messageType:t.request.messageType,data:t.request.data,chainId:t.request.chainId})}async t(t){return this.config.testing?{status:200,message:"Logs added successfully (TESTING)"}:this.client.post("/v1/logs",t)}};import{zValidator}from"@hono/zod-validator";import{Hono}from"hono";import{cors}from"hono/cors";import{z}from"zod";var AgentRequestSchema=z.object({sessionId:z.number(),sessionWalletAddress:z.string(),otherParameters:z.object().optional()}),AgentResponseSchema=z.object({success:z.boolean(),error:z.string().optional(),message:z.string().optional()}),HealthResponseSchema=z.object({status:z.string()}),Agent=class{app;executionFunction;stopFunction;healthCheckFunction;constructor(t){this.app=new Hono,this.executionFunction=t.executionFunction,this.stopFunction=t.stopFunction,this.healthCheckFunction=t.healthCheckFunction||(async()=>({status:"healthy"})),this.app.use("*",cors()),this.setupRoutes()}setupRoutes(){this.app.post("/execute",zValidator("json",AgentRequestSchema),async t=>{try{const e=t.req.valid("json"),s=await this.executionFunction(e);return t.json(s)}catch(e){return t.json({success:!1,error:e instanceof Error?e.message:"Unknown error",message:"Execution failed"},500)}}),this.stopFunction&&(this.app.post("/stop",zValidator("json",AgentRequestSchema),async t=>{try{const e=t.req.valid("json"),s=await(this.stopFunction?.(e));return t.json(s)}catch(e){return t.json({success:!1,error:e instanceof Error?e.message:"Unknown error",message:"Stop operation failed"},500)}}),this.app.delete("/",zValidator("json",AgentRequestSchema),async t=>{try{const e=t.req.valid("json"),s=await(this.stopFunction?.(e));return t.json(s)}catch(e){return t.json({success:!1,error:e instanceof Error?e.message:"Unknown error",message:"Stop operation failed"},500)}})),this.app.get("/health",async t=>{try{const e=await(this.healthCheckFunction?.());return t.json(e)}catch(e){return t.json({status:"unhealthy",error:e instanceof Error?e.message:"Unknown error",timestamp:(new Date).toISOString()},500)}})}getPortFromPackageJson(){try{const t=__require("fs"),e=__require("path").join(process.cwd(),"package.json");if(t.existsSync(e)){const s=JSON.parse(t.readFileSync(e,"utf-8"));if(s.circuit?.port)return Number.parseInt(s.circuit.port,10)}}catch(t){}return null}run(port){const isCloudflareWorker="undefined"!=typeof globalThis&&void 0!==globalThis.Cloudflare;if(isCloudflareWorker)return this.getWorkerExport();const bunEnv=globalThis.Bun?.env,envPort=process.env.AGENT_PORT||bunEnv?.AGENT_PORT,packageJsonPort=this.getPortFromPackageJson();let finalPort=port;!finalPort&&envPort&&(finalPort=Number.parseInt(envPort,10)),!finalPort&&packageJsonPort&&(finalPort=packageJsonPort),finalPort||(finalPort=3e3);try{const req=eval("require"),{serve:serve}=req("@hono/node-server");serve({fetch:this.app.fetch,port:finalPort})}catch(t){process.exit(1)}}getWorkerExport(){return{fetch:async(t,e,s)=>(e&&"undefined"!=typeof globalThis&&(globalThis.__AGENT_ENV__=e),this.app.fetch(t,e,s))}}};function createAgentHandler(t,e,s){return new Agent({executionFunction:t,stopFunction:e,healthCheckFunction:s})}export{APIClient,Agent,AgentSdk,getChainIdFromNetwork,isEthereumNetwork,isSolanaNetwork};
1
+ var __getOwnPropNames=Object.getOwnPropertyNames,__require=(t=>"undefined"!=typeof require?require:"undefined"!=typeof Proxy?new Proxy(t,{get:(t,e)=>("undefined"!=typeof require?require:t)[e]}):t)(function(t){if("undefined"!=typeof require)return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')}),__commonJS=(t,e)=>function(){return e||(0,t[__getOwnPropNames(t)[0]])((e={exports:{}}).exports,e),e.exports},require_auth_loader=__commonJS({"src/utils/auth-loader.cjs"(exports,module){function loadAuthFromFileSystem(){try{if("undefined"==typeof process)return;const fs=eval("require")("fs"),path=eval("require")("path"),os=eval("require")("os"),homeDir=os.homedir();let authPath=path.join(homeDir,".config","circuit","auth.json");if(!fs.existsSync(authPath)&&(authPath=path.join(homeDir,".circuit","auth.json"),!fs.existsSync(authPath)))return;const authContent=fs.readFileSync(authPath,"utf-8");return JSON.parse(authContent)}catch(t){return}}module.exports={loadAuthFromFileSystem:loadAuthFromFileSystem}}}),API_BASE_URL_LOCAL="https://agents.circuit.org",APIClient=class{config;baseUrl;isCloudflareWorker(){return"undefined"!=typeof globalThis&&void 0!==globalThis.Cloudflare}hasServiceBinding(){let t=!1;return this.isCloudflareWorker()&&(void 0!==globalThis.AGENTS_TO_API_PROXY||void 0!==globalThis.__AGENT_ENV__&&globalThis.__AGENT_ENV__?.AGENTS_TO_API_PROXY)&&(t=!0),this.config.verbose,t}constructor(t){this.config=t,this.baseUrl=t.baseUrl||API_BASE_URL_LOCAL}getAgentSlug(){return"undefined"!=typeof process&&process.env?.CIRCUIT_AGENT_SLUG?process.env.CIRCUIT_AGENT_SLUG:void 0!==globalThis.CIRCUIT_AGENT_SLUG?globalThis.CIRCUIT_AGENT_SLUG:void 0}getAuthHeaders(){const t={};t["X-Session-Id"]=this.config.sessionId.toString();const e=this.getAgentSlug();if(e&&(t["X-Agent-Slug"]=e),!this.hasServiceBinding())try{const e=this.loadAuthConfig();e?.sessionToken&&(t.Authorization=`Bearer ${e.sessionToken}`)}catch(t){}return t}loadAuthConfig(){try{const{loadAuthFromFileSystem:t}=require_auth_loader();return t()}catch(t){this.config.verbose}}logging(t,e){this.config.verbose}async makeRequest(t,e={}){const s={...{"Content-Type":"application/json",...this.getAuthHeaders()},...e.headers};let r;if(this.logging("=== REQUEST DETAILS ==="),this.logging("Endpoint:",t),this.logging("Method:",e.method||"GET"),this.logging("Headers:",s),this.logging("Body:",e.body),this.logging("Session ID:",this.config.sessionId),this.logging("Agent Slug:",this.getAgentSlug()||"not set"),this.logging("Using Service Binding:",this.hasServiceBinding()),this.logging("====================="),this.hasServiceBinding()){let n;if(void 0!==globalThis.AGENTS_TO_API_PROXY)n=globalThis.AGENTS_TO_API_PROXY;else{if(void 0===globalThis.__AGENT_ENV__||!globalThis.__AGENT_ENV__?.AGENTS_TO_API_PROXY)throw new Error("Service binding detected but not accessible");n=globalThis.__AGENT_ENV__.AGENTS_TO_API_PROXY}this.logging("Using service binding AGENTS_TO_API_PROXY"),this.logging("Service binding type:",typeof n);const i={...e,headers:s},o=`https://agents-to-api-proxy.circuit-0bc.workers.dev${t}`;r=await n.fetch(o,i)}else{this.logging("Using HTTP fallback to:",this.baseUrl);const n=`${this.baseUrl}${t}`,i={...e,headers:s};r=await fetch(n,i)}if(this.logging("=== RESPONSE DETAILS ==="),this.logging("Status:",r.status),this.logging("Status Text:",r.statusText),this.logging("Response Headers:",Object.fromEntries(r.headers.entries())),this.logging("======================"),!r.ok){const t=await r.json().catch(()=>({}));throw this.logging("=== ERROR RESPONSE ==="),this.logging("Error Data:",t),this.logging("===================="),new Error(t.message||`HTTP ${r.status}: ${r.statusText}`)}const n=await r.json();return this.logging("=== SUCCESS RESPONSE ==="),this.logging("Response Data:",n),this.logging("======================"),n}async get(t){return this.makeRequest(t,{method:"GET"})}async post(t,e){return this.makeRequest(t,{method:"POST",body:e?JSON.stringify(e):void 0})}};function isEthereumNetwork(t){return t.startsWith("ethereum:")}function isSolanaNetwork(t){return"solana"===t}function getChainIdFromNetwork(t){return Number(t.split(":")[1])}var AgentSdk=class{client;config;constructor(t){this.config=t,this.client=new APIClient(t)}logging(t,e){this.config.verbose}async sendLog(t){this.logging("=== ADD MESSAGE ==="),this.logging("Message:",t),this.logging("===================");try{await this._sendLog([t])}catch(t){this.logging("=== SEND LOG ERROR ==="),this.logging("Error:",t),this.logging("======================")}}async signAndSend(t){this.logging("=== SIGN AND SEND ==="),this.logging("Request:",t),this.logging("Testing mode:",this.config.testing),this.logging("====================");try{if(this.config.testing)return{success:!0,internalTransactionId:123,txHash:isEthereumNetwork(t.network)?"0xTEST":"TEST_SOL_TX",transactionUrl:void 0};if(isEthereumNetwork(t.network)){const e=getChainIdFromNetwork(t.network);if("toAddress"in t.request)return await this.handleEvmTransaction({chainId:e,toAddress:t.request.toAddress,data:t.request.data,valueWei:t.request.value,message:t.message})}return isSolanaNetwork(t.network)&&"hexTransaction"in t.request?await this.handleSolanaTransaction({hexTransaction:t.request.hexTransaction,message:t.message}):{success:!1,error:`Unsupported network: ${t.network}`,errorDetails:{message:`Unsupported network: ${t.network}`}}}catch(t){return this.logging("=== SIGN AND SEND ERROR ==="),this.logging("Error:",t),this.logging("==========================="),{success:!1,error:t instanceof Error?t.message:"Unknown error",errorDetails:{message:t instanceof Error?t.message:"Unknown error"}}}}async signMessage(t){this.logging("=== SIGN MESSAGE ==="),this.logging("Request:",t),this.logging("Testing mode:",this.config.testing),this.logging("====================");try{return this.config.testing?{v:27,r:"0xTEST_R",s:"0xTEST_S",formattedSignature:"0xTEST_FORMATTED",type:"evm"}:isEthereumNetwork(t.network)?await this.handleEvmSignMessage(t):{v:0,r:"0x0",s:"0x0",formattedSignature:"0x0",type:"evm"}}catch(t){return this.logging("=== SIGN MESSAGE ERROR ==="),this.logging("Error:",t),this.logging("=========================="),{v:0,r:"0x0",s:"0x0",formattedSignature:"0x0",type:"evm"}}}async handleEvmTransaction(t){try{const e=await this.client.post("/v1/transactions/evm",t),s=await this.client.post(`/v1/transactions/evm/${e.internalTransactionId}/broadcast`);return{success:!0,internalTransactionId:e.internalTransactionId,txHash:s.txHash,transactionUrl:s.transactionUrl}}catch(t){this.logging("=== EVM TRANSACTION ERROR ==="),this.logging("Error:",t),this.logging("=============================");let e,s,r,n="Unknown error";if(t instanceof Error){n=t.message;const i=t.message.match(/HTTP (\d+): (.+)/);i&&(e=Number.parseInt(i[1]),s=i[2]),t.message.includes("Failed to estimate gas")&&(r=t.message)}return{success:!1,error:n,errorDetails:{message:r||n,status:e,statusText:s}}}}async handleSolanaTransaction(t){try{const e=await this.client.post("/v1/transactions/solana",t),s=await this.client.post(`/v1/transactions/solana/${e.internalTransactionId}/broadcast`);return{success:!0,internalTransactionId:e.internalTransactionId,txHash:s.txHash,transactionUrl:s.transactionUrl}}catch(t){this.logging("=== SOLANA TRANSACTION ERROR ==="),this.logging("Error:",t),this.logging("================================");let e,s,r="Unknown error";if(t instanceof Error){r=t.message;const n=t.message.match(/HTTP (\d+): (.+)/);n&&(e=Number.parseInt(n[1]),s=n[2])}return{success:!1,error:r,errorDetails:{message:r,status:e,statusText:s}}}}async handleEvmSignMessage(t){try{return await this.client.post("/v1/messages/evm",{messageType:t.request.messageType,data:t.request.data,chainId:t.request.chainId})}catch(t){return this.logging("=== EVM SIGN MESSAGE ERROR ==="),this.logging("Error:",t),this.logging("=============================="),{v:0,r:"0x0",s:"0x0",formattedSignature:"0x0",type:"evm"}}}async _sendLog(t){return this.config.testing?{status:200,message:"Logs added successfully (TESTING)"}:this.client.post("/v1/logs",t)}async _updateJobStatus(t){if(this.logging("UPDATE_JOB_STATUS",t),this.config.testing)return{status:200,message:"Job status updated successfully (TESTING)"};try{return await this.client.post(`/v1/jobs/${t.jobId}/status`,t)}catch(t){return this.logging("=== UPDATE JOB STATUS ERROR ==="),this.logging("Error:",t),this.logging("==============================="),{status:400,message:`Failed to update job status: ${t instanceof Error?t.message:"Unknown error"}`}}}};import{zValidator}from"@hono/zod-validator";import{Hono}from"hono";import{cors}from"hono/cors";import{z}from"zod";var AgentRequestSchema=z.object({sessionId:z.number(),sessionWalletAddress:z.string(),jobId:z.string().optional(),otherParameters:z.object().optional()}),AgentResponseSchema=z.object({success:z.boolean(),error:z.string().optional(),message:z.string().optional()}),HealthResponseSchema=z.object({status:z.string()}),Agent=class{app;executionFunction;stopFunction;healthCheckFunction;constructor(t){this.app=new Hono,this.executionFunction=t.executionFunction,this.stopFunction=t.stopFunction,this.healthCheckFunction=t.healthCheckFunction||(async()=>({status:"healthy"})),this.app.use("*",cors()),this.setupRoutes()}defaultStopFunction=async t=>({success:!0,message:`Agent stopped for session ${t.sessionId}`});async executeWithJobTracking(t,e){try{const s=await e(t);if(t.jobId&&s.success)try{await this.updateJobStatus(t.sessionId,t.jobId,"success")}catch(t){}else if(t.jobId&&!s.success)try{const e=s.error||s.message||"Function returned failure";await this.updateJobStatus(t.sessionId,t.jobId,"failed",e)}catch(t){}return s}catch(e){if(t.jobId)try{const s=e instanceof Error?e.message:"Unknown error";await this.updateJobStatus(t.sessionId,t.jobId,"failed",s)}catch(t){}return{success:!1,error:e instanceof Error?e.message:"Unknown error",message:"Function execution failed"}}}async updateJobStatus(t,e,s,r){try{const n=new AgentSdk({sessionId:t}),i={jobId:e,status:s,...r&&{errorMessage:r}};await n._updateJobStatus(i)}catch(t){}}setupRoutes(){this.app.post("/execute",zValidator("json",AgentRequestSchema),async t=>{try{const e=t.req.valid("json"),s=await this.executeWithJobTracking(e,this.executionFunction);return t.json(s)}catch(e){return t.json({success:!1,error:e instanceof Error?e.message:"Unknown error",message:"Execution failed"},500)}}),this.app.post("/stop",zValidator("json",AgentRequestSchema),async t=>{try{const e=t.req.valid("json"),s=this.stopFunction||this.defaultStopFunction,r=await this.executeWithJobTracking(e,s);return t.json(r)}catch(e){return t.json({success:!1,error:e instanceof Error?e.message:"Unknown error",message:"Stop operation failed"},500)}}),this.app.get("/health",async t=>{try{const e=await(this.healthCheckFunction?.());return t.json(e)}catch(e){return t.json({status:"unhealthy",error:e instanceof Error?e.message:"Unknown error",timestamp:(new Date).toISOString()},500)}})}getPortFromPackageJson(){try{const t=__require("fs"),e=__require("path").join(process.cwd(),"package.json");if(t.existsSync(e)){const s=JSON.parse(t.readFileSync(e,"utf-8"));if(s.circuit?.port)return Number.parseInt(s.circuit.port,10)}}catch(t){}return null}run(port){const isCloudflareWorker="undefined"!=typeof globalThis&&void 0!==globalThis.Cloudflare;if(isCloudflareWorker)return this.getWorkerExport();const bunEnv=globalThis.Bun?.env,envPort=process.env.AGENT_PORT||bunEnv?.AGENT_PORT,packageJsonPort=this.getPortFromPackageJson();let finalPort=port;!finalPort&&envPort&&(finalPort=Number.parseInt(envPort,10)),!finalPort&&packageJsonPort&&(finalPort=packageJsonPort),finalPort||(finalPort=3e3);try{const req=eval("require"),{serve:serve}=req("@hono/node-server");serve({fetch:this.app.fetch,port:finalPort})}catch(t){process.exit(1)}}getWorkerExport(){return{fetch:async(t,e,s)=>(e&&"undefined"!=typeof globalThis&&(globalThis.__AGENT_ENV__=e),this.app.fetch(t,e,s))}}};function createAgentHandler(t,e,s){return new Agent({executionFunction:t,stopFunction:e,healthCheckFunction:s})}export{APIClient,Agent,AgentSdk,getChainIdFromNetwork,isEthereumNetwork,isSolanaNetwork};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@circuitorg/agent-sdk",
3
- "version": "1.0.12",
3
+ "version": "1.1.0",
4
4
  "description": "typescript sdk for the Agent Toolset Service",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -65,6 +65,6 @@
65
65
  },
66
66
  "repository": {
67
67
  "type": "git",
68
- "url": "git+https://github.com/circuitorg/agents-sdk.git"
68
+ "url": "git+https://github.com/circuitorg/agent-sdk-typescript.git"
69
69
  }
70
70
  }
@@ -4,18 +4,28 @@
4
4
  function loadAuthFromFileSystem() {
5
5
  try {
6
6
  // Check if we're in a Node.js environment
7
- if (typeof process === 'undefined' || !process.env?.HOME) {
7
+ if (typeof process === 'undefined') {
8
8
  return undefined;
9
9
  }
10
10
 
11
11
  // Use dynamic require to avoid bundler processing
12
12
  const fs = eval("require")('fs');
13
13
  const path = eval("require")('path');
14
+ const os = eval("require")('os');
14
15
 
15
- const authPath = path.join(process.env.HOME, '.config', 'circuit', 'auth.json');
16
+ // Use os.homedir() for cross-platform compatibility (works on Windows, Mac, Linux)
17
+ const homeDir = os.homedir();
18
+
19
+ // Try main config directory first (matches CLI behavior)
20
+ let authPath = path.join(homeDir, '.config', 'circuit', 'auth.json');
16
21
 
17
22
  if (!fs.existsSync(authPath)) {
18
- return undefined;
23
+ // Try fallback directory (matches CLI fallback behavior)
24
+ authPath = path.join(homeDir, '.circuit', 'auth.json');
25
+
26
+ if (!fs.existsSync(authPath)) {
27
+ return undefined;
28
+ }
19
29
  }
20
30
 
21
31
  const authContent = fs.readFileSync(authPath, 'utf-8');