feat: add test agent, python sdk, and external traffic validator
Some checks failed
Deploy to 110 WOOO Server / deploy (push) Failing after 9s
Some checks failed
Deploy to 110 WOOO Server / deploy (push) Failing after 9s
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -33,5 +33,9 @@ build
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Python
|
||||
venv/
|
||||
.venv/
|
||||
|
||||
# E2B / MCP specific
|
||||
.e2b
|
||||
|
||||
88
apps/test-agent/index.ts
Normal file
88
apps/test-agent/index.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { VibeWorkAgentSDK } from '@vibework/agent-sdk';
|
||||
import { ClaimTaskResponse, SubmitSolutionRequest, TaskBounty } from '@vibework/agent-sdk';
|
||||
import 'dotenv/config';
|
||||
|
||||
function resolveEnv(name: string, fallback: string): string {
|
||||
return process.env[name]?.trim() || fallback;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log("🤖 Starting VibeWork Test Agent...");
|
||||
|
||||
const baseUrl = resolveEnv('VIBEWORK_API_URL', 'http://localhost:3000');
|
||||
const apiKey = process.env.VIBEWORK_API_KEY;
|
||||
const agentId = resolveEnv('VIBEWORK_AGENT_ID', 'test-hunter-bot-001');
|
||||
const wallet = resolveEnv('VIBEWORK_AGENT_WALLET', '0x1234567890abcdef1234567890abcdef12345678');
|
||||
const githubPrUrl = resolveEnv(
|
||||
'VIBEWORK_PR_URL',
|
||||
'https://github.com/agent-bounty-protocol/pr/123'
|
||||
);
|
||||
const iterationLimit = Number(process.env.VIBEWORK_MAX_ITERATIONS ?? '1');
|
||||
const sleepMs = Number(process.env.VIBEWORK_SIMULATE_WORK_MS ?? '3000');
|
||||
|
||||
const sdk = new VibeWorkAgentSDK({
|
||||
baseUrl,
|
||||
apiKey,
|
||||
});
|
||||
|
||||
try {
|
||||
console.log("📝 Registering Agent Identity...");
|
||||
const registerResult = await sdk.identity.registerAgent({
|
||||
agent_id: agentId,
|
||||
name: resolveEnv("VIBEWORK_AGENT_NAME", "HunterBot-Test"),
|
||||
description:
|
||||
"A test agent built with @vibework/agent-sdk to hunt for bounties autonomously.",
|
||||
supported_models: ["gpt-4o"],
|
||||
skills: ["typescript", "javascript", "react", "testing"],
|
||||
max_concurrent_tasks: 3,
|
||||
x402_wallet_address: wallet,
|
||||
});
|
||||
console.log(`✅ Registered successfully: ${registerResult.message}`);
|
||||
|
||||
let iteration = 0;
|
||||
while (iteration < iterationLimit) {
|
||||
iteration += 1;
|
||||
console.log(`\n[Cycle ${iteration}] 🔍 Scanning for open bounties...`);
|
||||
const openBounties = await sdk.tasks.listOpenBounties(5);
|
||||
console.log(`🎯 Found ${openBounties.length} open bounties.`);
|
||||
|
||||
if (!openBounties.length) {
|
||||
console.log("😴 No open bounties found. Exit.");
|
||||
return;
|
||||
}
|
||||
|
||||
const targetTask = openBounties[0] as TaskBounty;
|
||||
console.log(
|
||||
`📌 Target: [${targetTask.task_id}] ${targetTask.title} (Reward: ${
|
||||
targetTask.reward?.display_amount ?? targetTask.reward_display ?? 'n/a'
|
||||
})`
|
||||
);
|
||||
|
||||
const claimResult: ClaimTaskResponse = await sdk.tasks.claimBounty(targetTask.task_id, agentId, wallet);
|
||||
console.log(`✅ Bounty claimed. Claim token prefix: ${claimResult.claim_token.slice(0, 10)}...`);
|
||||
|
||||
console.log(`⏳ Working on task ${targetTask.task_id}...`);
|
||||
await new Promise((resolve) => setTimeout(resolve, sleepMs));
|
||||
|
||||
const submitPayload: SubmitSolutionRequest = {
|
||||
task_id: targetTask.task_id,
|
||||
claim_token: claimResult.claim_token,
|
||||
deliverables: {
|
||||
'README.md': 'Completed the task from the automated test agent.',
|
||||
'solution.diff': 'noop',
|
||||
},
|
||||
github_pr_url: githubPrUrl,
|
||||
};
|
||||
const submitResult = await sdk.tasks.submitWork(submitPayload);
|
||||
console.log(`🎉 Submit done. Status: ${submitResult.status}, submission_id=${submitResult.submission_id}`);
|
||||
}
|
||||
|
||||
console.log("🤖 Agent cycles complete.");
|
||||
} catch (err: any) {
|
||||
console.error("❌ Agent encountered an error:", err?.response?.data || err.message || err);
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
23
apps/test-agent/package.json
Normal file
23
apps/test-agent/package.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "test-agent",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "tsx index.ts",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"packageManager": "pnpm@10.32.1",
|
||||
"dependencies": {
|
||||
"@vibework/agent-sdk": "workspace:*",
|
||||
"dotenv": "^17.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.9.2",
|
||||
"tsx": "^4.22.4",
|
||||
"typescript": "^6.0.3"
|
||||
}
|
||||
}
|
||||
49
packages/agent-sdk-python/README.md
Normal file
49
packages/agent-sdk-python/README.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# @vibework/agent-sdk (Python)
|
||||
|
||||
This package helps external AI Agents integrate with VibeWork without directly touching MCP or X402 details.
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
pip install .
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```python
|
||||
from vibework_agent_sdk.client import VibeWorkAgentSDK
|
||||
|
||||
sdk = VibeWorkAgentSDK(
|
||||
base_url="https://agent.wooo.work",
|
||||
api_key="YOUR_API_KEY",
|
||||
)
|
||||
|
||||
# 1) Register / update agent profile
|
||||
sdk.identity.register_agent(
|
||||
agent_id="agent-001",
|
||||
name="MyAgent",
|
||||
description="Auto coder for bounty tasks.",
|
||||
skills=["python", "backend", "testing"],
|
||||
)
|
||||
|
||||
# 2) Find open bounties
|
||||
tasks = sdk.tasks.list_open_bounties(limit=5)
|
||||
print(len(tasks), "tasks")
|
||||
|
||||
# 3) Claim and submit
|
||||
if tasks:
|
||||
claim = sdk.tasks.claim_bounty(task_id=tasks[0].task_id, agent_id="agent-001")
|
||||
sdk.tasks.submit_solution(
|
||||
task_id=tasks[0].task_id,
|
||||
claim_token=claim.claim_token,
|
||||
deliverables={"README.md": "done"},
|
||||
github_pr_url="https://github.com/example/repo/pull/123",
|
||||
)
|
||||
```
|
||||
|
||||
## API Surface
|
||||
|
||||
- `identity.register_agent(...)`
|
||||
- `tasks.list_open_bounties(limit=10, skills=None, difficulty=None)`
|
||||
- `tasks.claim_bounty(task_id, agent_id, developer_wallet)`
|
||||
- `tasks.submit_solution(task_id, claim_token, deliverables, github_pr_url=None)`
|
||||
32
packages/agent-sdk-python/pyproject.toml
Normal file
32
packages/agent-sdk-python/pyproject.toml
Normal file
@@ -0,0 +1,32 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>=64", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "vibework-agent-sdk"
|
||||
version = "0.1.0"
|
||||
description = "Official SDK for AI agents to interact with VibeWork A2A workflow APIs."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
license = "ISC"
|
||||
authors = [{ name = "VibeWork Team" }]
|
||||
dependencies = [
|
||||
"requests>=2.31,<3.0",
|
||||
"pydantic>=2.6,<3.0",
|
||||
]
|
||||
classifiers = [
|
||||
"License :: OSI Approved :: ISC License (ISCL)",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://agent.wooo.work"
|
||||
Repository = "https://github.com/agent-bounty-protocol"
|
||||
|
||||
[tool.setuptools]
|
||||
package-dir = {"" = "."}
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
where = ["."]
|
||||
20
packages/agent-sdk-python/vibework_agent_sdk/__init__.py
Normal file
20
packages/agent-sdk-python/vibework_agent_sdk/__init__.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from .client import VibeWorkAgentSDK, VibeWorkApiError
|
||||
from .models import (
|
||||
AgentCard,
|
||||
ClaimTaskResponse,
|
||||
ClaimTaskRequest,
|
||||
SubmitSolutionRequest,
|
||||
SubmitSolutionResponse,
|
||||
TaskBounty,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"VibeWorkAgentSDK",
|
||||
"VibeWorkApiError",
|
||||
"AgentCard",
|
||||
"ClaimTaskRequest",
|
||||
"ClaimTaskResponse",
|
||||
"SubmitSolutionRequest",
|
||||
"SubmitSolutionResponse",
|
||||
"TaskBounty",
|
||||
]
|
||||
127
packages/agent-sdk-python/vibework_agent_sdk/client.py
Normal file
127
packages/agent-sdk-python/vibework_agent_sdk/client.py
Normal file
@@ -0,0 +1,127 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
import requests
|
||||
|
||||
from .models import (
|
||||
AgentCard,
|
||||
ClaimTaskRequest,
|
||||
ClaimTaskResponse,
|
||||
SubmitSolutionRequest,
|
||||
SubmitSolutionResponse,
|
||||
TaskBounty,
|
||||
)
|
||||
|
||||
|
||||
class VibeWorkApiError(RuntimeError):
|
||||
def __init__(self, message: str, status_code: int | None = None, payload: object | None = None):
|
||||
super().__init__(message)
|
||||
self.status_code = status_code
|
||||
self.payload = payload
|
||||
|
||||
|
||||
@dataclass
|
||||
class IdentityModule:
|
||||
client: "VibeWorkAgentSDK"
|
||||
|
||||
def register_agent(self, card: AgentCard) -> Dict[str, str]:
|
||||
payload = card.model_dump(exclude_none=True)
|
||||
response = self.client._request("post", "/api/mcp/agent_card", payload={"card": payload})
|
||||
return response
|
||||
|
||||
|
||||
@dataclass
|
||||
class TasksModule:
|
||||
client: "VibeWorkAgentSDK"
|
||||
|
||||
def list_open_bounties(
|
||||
self,
|
||||
limit: int = 10,
|
||||
skills: Optional[List[str]] = None,
|
||||
difficulty: Optional[str] = None,
|
||||
) -> List[TaskBounty]:
|
||||
response = self.client._request(
|
||||
"get",
|
||||
"/api/open-tasks",
|
||||
params={"limit": str(min(max(limit, 1), 20))} if limit else None,
|
||||
)
|
||||
tasks = response.get("tasks", [])
|
||||
return [TaskBounty.model_validate(item) for item in tasks]
|
||||
|
||||
def claim_bounty(
|
||||
self,
|
||||
task_id: str,
|
||||
agent_id: str,
|
||||
developer_wallet: str,
|
||||
) -> ClaimTaskResponse:
|
||||
payload = ClaimTaskRequest(
|
||||
task_id=task_id,
|
||||
agent_id=agent_id,
|
||||
developer_wallet=developer_wallet,
|
||||
).model_dump()
|
||||
response = self.client._request("post", "/api/mcp/claim_task", payload=payload)
|
||||
return ClaimTaskResponse.model_validate(response)
|
||||
|
||||
def submit_solution(
|
||||
self,
|
||||
task_id: str,
|
||||
claim_token: str,
|
||||
deliverables: Dict[str, str],
|
||||
github_pr_url: Optional[str] = None,
|
||||
) -> SubmitSolutionResponse:
|
||||
payload = SubmitSolutionRequest(
|
||||
task_id=task_id,
|
||||
claim_token=claim_token,
|
||||
deliverables=deliverables,
|
||||
github_pr_url=github_pr_url,
|
||||
)
|
||||
response = self.client._request("post", "/api/mcp/submit_solution", payload=payload.model_dump())
|
||||
return SubmitSolutionResponse.model_validate(response)
|
||||
|
||||
|
||||
class VibeWorkAgentSDK:
|
||||
def __init__(self, base_url: str = "https://agent.wooo.work", api_key: str | None = None):
|
||||
self.base_url = base_url.rstrip("/")
|
||||
self.http = requests.Session()
|
||||
self.http.headers.update({"Content-Type": "application/json"})
|
||||
|
||||
if api_key:
|
||||
self.http.headers.update({"Authorization": f"Bearer {api_key}"})
|
||||
|
||||
self.identity = IdentityModule(self)
|
||||
self.tasks = TasksModule(self)
|
||||
|
||||
def _request(
|
||||
self,
|
||||
method: str,
|
||||
path: str,
|
||||
payload: Optional[dict] = None,
|
||||
params: Optional[dict] = None,
|
||||
) -> dict:
|
||||
url = f"{self.base_url}{path}"
|
||||
headers = {"x-request-id": str(uuid.uuid4())}
|
||||
request_method = self.http.request
|
||||
response = request_method(
|
||||
method=method.upper(),
|
||||
url=url,
|
||||
json=payload,
|
||||
params=params,
|
||||
headers=headers,
|
||||
timeout=30,
|
||||
)
|
||||
|
||||
if response.status_code < 200 or response.status_code >= 300:
|
||||
try:
|
||||
body = response.json()
|
||||
except ValueError:
|
||||
body = response.text
|
||||
raise VibeWorkApiError(
|
||||
f"{method.upper()} {path} failed with status {response.status_code}",
|
||||
status_code=response.status_code,
|
||||
payload=body,
|
||||
)
|
||||
|
||||
return response.json()
|
||||
66
packages/agent-sdk-python/vibework_agent_sdk/models.py
Normal file
66
packages/agent-sdk-python/vibework_agent_sdk/models.py
Normal file
@@ -0,0 +1,66 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Dict, List, Literal, Optional
|
||||
|
||||
from pydantic import BaseModel, Field, HttpUrl
|
||||
|
||||
SupportedCurrency = Literal["USD", "TWD", "USDC"]
|
||||
|
||||
|
||||
class AgentCard(BaseModel):
|
||||
agent_id: str = Field(min_length=1)
|
||||
name: str = Field(min_length=2, max_length=100)
|
||||
description: Optional[str] = Field(default=None, max_length=1000)
|
||||
supported_models: List[str] = Field(default_factory=lambda: ["gpt-4o"])
|
||||
skills: List[str] = Field(min_length=1)
|
||||
max_concurrent_tasks: int = Field(default=5, ge=1, le=100)
|
||||
x402_wallet_address: Optional[str] = None
|
||||
|
||||
|
||||
class TaskReward(BaseModel):
|
||||
amount: int
|
||||
currency: SupportedCurrency
|
||||
display_amount: Optional[str] = None
|
||||
|
||||
|
||||
class TaskBounty(BaseModel):
|
||||
task_id: str
|
||||
title: str
|
||||
description: Optional[str] = None
|
||||
description_preview: Optional[str] = None
|
||||
reward_amount_cents: Optional[int] = None
|
||||
reward_display: Optional[str] = None
|
||||
reward: Optional[TaskReward] = None
|
||||
status: str
|
||||
required_stack: List[str] = Field(default_factory=list)
|
||||
difficulty: Optional[str] = None
|
||||
scope_clarity_score: Optional[float] = None
|
||||
|
||||
|
||||
class ClaimTaskRequest(BaseModel):
|
||||
task_id: str
|
||||
agent_id: str
|
||||
developer_wallet: str
|
||||
|
||||
|
||||
class ClaimTaskResponse(BaseModel):
|
||||
task_id: str
|
||||
status: Literal["EXECUTING"]
|
||||
held_amount: int
|
||||
held_currency: Literal["USD", "TWD"]
|
||||
claim_token: str
|
||||
expires_at: str
|
||||
|
||||
|
||||
class SubmitSolutionRequest(BaseModel):
|
||||
task_id: str
|
||||
claim_token: str
|
||||
deliverables: Dict[str, str]
|
||||
github_pr_url: Optional[HttpUrl] = None
|
||||
|
||||
|
||||
class SubmitSolutionResponse(BaseModel):
|
||||
task_id: str
|
||||
submission_id: str
|
||||
status: Literal["VERIFYING"]
|
||||
estimated_judge_complete_at: Optional[str] = None
|
||||
@@ -1,5 +1,5 @@
|
||||
import { VibeWorkClient } from '../client';
|
||||
import { AgentProfile } from '../types';
|
||||
import { AgentCard, RegisterAgentResponse } from '../types';
|
||||
|
||||
export class IdentityModule {
|
||||
private client: VibeWorkClient;
|
||||
@@ -11,23 +11,8 @@ export class IdentityModule {
|
||||
/**
|
||||
* Register or update an Agent Card
|
||||
*/
|
||||
async registerAgent(card: {
|
||||
agent_id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
model_provider?: string;
|
||||
capabilities: string[];
|
||||
x402_wallet_address?: string;
|
||||
}): Promise<AgentProfile> {
|
||||
const response = await this.client.http.post('/api/mcp/agent_card', card);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an Agent Profile by ID
|
||||
*/
|
||||
async getProfile(agentId: string): Promise<AgentProfile> {
|
||||
const response = await this.client.http.get(`/api/mcp/agent_card?agent_id=${agentId}`);
|
||||
async registerAgent(card: AgentCard): Promise<RegisterAgentResponse> {
|
||||
const response = await this.client.http.post<{ status: string; message: string }>('/api/mcp/agent_card', { card });
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { VibeWorkClient } from '../client';
|
||||
import { TaskBounty, PagedResponse } from '../types';
|
||||
import { ClaimTaskRequest, ClaimTaskResponse, SubmitSolutionRequest, SubmitSolutionResponse, TaskBounty } from '../types';
|
||||
|
||||
export class TasksModule {
|
||||
private client: VibeWorkClient;
|
||||
@@ -11,33 +11,29 @@ export class TasksModule {
|
||||
/**
|
||||
* List all open bounties in the IntentPool
|
||||
*/
|
||||
async listOpenBounties(): Promise<PagedResponse<TaskBounty>> {
|
||||
const response = await this.client.http.get('/api/open-tasks');
|
||||
return {
|
||||
data: response.data,
|
||||
total: response.data.length
|
||||
};
|
||||
async listOpenBounties(limit = 10): Promise<TaskBounty[]> {
|
||||
const response = await this.client.http.get<{ tasks: TaskBounty[] }>('/api/open-tasks');
|
||||
return response.data.tasks.slice(0, limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Claim a bounty task
|
||||
*/
|
||||
async claimBounty(taskId: string, agentId: string): Promise<TaskBounty> {
|
||||
const response = await this.client.http.post(`/api/mcp/claim_task`, {
|
||||
taskId,
|
||||
agentId
|
||||
});
|
||||
async claimBounty(taskId: string, agentId: string, developerWallet: string = "0x0000000000000000000000000000000000000000"): Promise<ClaimTaskResponse> {
|
||||
const request: ClaimTaskRequest = {
|
||||
task_id: taskId,
|
||||
agent_id: agentId,
|
||||
developer_wallet: developerWallet
|
||||
};
|
||||
const response = await this.client.http.post<ClaimTaskResponse>('/api/mcp/claim_task', request);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit work for a bounty
|
||||
*/
|
||||
async submitWork(taskId: string, pullRequestUrl: string): Promise<TaskBounty> {
|
||||
const response = await this.client.http.post(`/api/mcp/submit_work`, {
|
||||
taskId,
|
||||
pullRequestUrl
|
||||
});
|
||||
async submitWork(options: SubmitSolutionRequest): Promise<SubmitSolutionResponse> {
|
||||
const response = await this.client.http.post<SubmitSolutionResponse>('/api/mcp/submit_solution', options);
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,82 @@ export interface PagedResponse<T> {
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface TaskReward {
|
||||
amount: number;
|
||||
currency: 'USD' | 'TWD' | 'USDC';
|
||||
display_amount?: string;
|
||||
}
|
||||
|
||||
export interface TaskBounty {
|
||||
id: string;
|
||||
task_id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
reward_amount: number;
|
||||
reward_currency: string;
|
||||
status: 'OPEN' | 'ASSIGNED' | 'IN_REVIEW' | 'COMPLETED' | 'CANCELLED';
|
||||
requirements: string[];
|
||||
description?: string;
|
||||
description_preview?: string;
|
||||
reward_amount_cents?: number;
|
||||
reward_display?: string;
|
||||
reward?: TaskReward;
|
||||
status:
|
||||
| 'DRAFT'
|
||||
| 'OPEN'
|
||||
| 'EXECUTING'
|
||||
| 'VERIFYING'
|
||||
| 'COMPLETED'
|
||||
| 'FAILED'
|
||||
| 'FAILED_RETRYABLE'
|
||||
| 'CANCELLED'
|
||||
| 'DISPUTED'
|
||||
| 'REFUND_PENDING'
|
||||
| 'PAYOUT_READY'
|
||||
| 'PAYOUT_SETTLED'
|
||||
| 'ARCHIVED'
|
||||
| 'IN_REVIEW';
|
||||
required_stack: string[];
|
||||
difficulty?: string;
|
||||
scope_clarity_score?: number;
|
||||
}
|
||||
|
||||
export interface AgentCard {
|
||||
agent_id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
supported_models?: string[];
|
||||
skills: string[];
|
||||
max_concurrent_tasks?: number;
|
||||
x402_wallet_address?: string;
|
||||
}
|
||||
|
||||
export interface RegisterAgentResponse {
|
||||
status: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface ClaimTaskRequest {
|
||||
task_id: string;
|
||||
agent_id: string;
|
||||
developer_wallet: string;
|
||||
}
|
||||
|
||||
export interface ClaimTaskResponse {
|
||||
task_id: string;
|
||||
status: 'EXECUTING';
|
||||
held_amount: number;
|
||||
held_currency: 'USD' | 'TWD';
|
||||
claim_token: string;
|
||||
expires_at: string;
|
||||
}
|
||||
|
||||
export interface SubmitSolutionRequest {
|
||||
task_id: string;
|
||||
claim_token: string;
|
||||
deliverables: Record<string, string>;
|
||||
github_pr_url?: string;
|
||||
}
|
||||
|
||||
export interface SubmitSolutionResponse {
|
||||
task_id: string;
|
||||
submission_id: string;
|
||||
status: 'VERIFYING';
|
||||
estimated_judge_complete_at?: string;
|
||||
}
|
||||
|
||||
export interface AgentProfile {
|
||||
|
||||
928
pnpm-lock.yaml
generated
928
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -4,12 +4,16 @@
|
||||
# This script simulates an external AI agent discovering the network via the Beta Promo token.
|
||||
|
||||
API_URL=${1:-"https://agent.wooo.work"}
|
||||
API_KEY="vw_beta_promo_2026"
|
||||
AGENT_ID="test_agent_$(date +%s)"
|
||||
API_KEY="${MCP_API_KEY:-vw_beta_promo_2026}"
|
||||
AGENT_ID="${MCP_AGENT_ID:-test_agent_$(date +%s)}"
|
||||
DEVELOPER_WALLET="${MCP_DEVELOPER_WALLET:-acct_demoagent001}"
|
||||
SUBMIT="${MCP_DO_SUBMIT:-0}"
|
||||
SUBMIT_DELAY_MS="${MCP_SUBMIT_DELAY_MS:-1500}"
|
||||
|
||||
echo "🚀 Simulating External AI Agent connecting to $API_URL"
|
||||
echo "🔑 Using Public Beta Token: $API_KEY"
|
||||
echo "🤖 Agent ID: $AGENT_ID"
|
||||
echo "💳 Wallet: $DEVELOPER_WALLET"
|
||||
echo "---------------------------------------------------"
|
||||
|
||||
# 1. Fetch Open Tasks
|
||||
@@ -48,10 +52,12 @@ CLAIM_RESPONSE=$(curl -s -X POST "$API_URL/api/mcp/claim_task" \
|
||||
-d '{
|
||||
"task_id": "'"$TASK_ID"'",
|
||||
"agent_id": "'"$AGENT_ID"'",
|
||||
"developer_wallet": "0xTestWalletExternalAgent999"
|
||||
"developer_wallet": "'"$DEVELOPER_WALLET"'"
|
||||
}')
|
||||
|
||||
CLAIM_STATUS=$(echo $CLAIM_RESPONSE | grep -o '"status":"[^"]*"' | cut -d'"' -f4)
|
||||
CLAIM_TOKEN=$(echo $CLAIM_RESPONSE | grep -o '"claim_token":"[^"]*"' | cut -d'"' -f4)
|
||||
CLAIM_STATUS=$(echo $CLAIM_RESPONSE | grep -o '"status":"[^"]*"' | head -n 1 | cut -d'"' -f4)
|
||||
TASK_LOCK_STATUS=$(echo $CLAIM_RESPONSE | grep -o '"status":"[^"]*"' | cut -d'"' -f4)
|
||||
ERROR_MSG=$(echo $CLAIM_RESPONSE | grep -o '"error":"[^"]*"' | cut -d'"' -f4)
|
||||
|
||||
if [ -n "$ERROR_MSG" ]; then
|
||||
@@ -59,7 +65,51 @@ if [ -n "$ERROR_MSG" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Task claimed successfully! Status: $CLAIM_STATUS"
|
||||
if [ -n "$ERROR_MSG" ] || [ -z "$CLAIM_TOKEN" ]; then
|
||||
echo "❌ Claim failed. Status=$CLAIM_STATUS Error=$ERROR_MSG"
|
||||
echo "📄 Response: $CLAIM_RESPONSE"
|
||||
if [ "$SUBMIT" = "1" ]; then
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "✅ Task claimed successfully! Status: $CLAIM_STATUS, token=$CLAIM_TOKEN"
|
||||
|
||||
if [ "$SUBMIT" = "1" ]; then
|
||||
if [ -z "$CLAIM_TOKEN" ]; then
|
||||
echo "❌ Skip submit: claim_token missing."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "👉 3. Submitting Solution (submit_solution)..."
|
||||
if [ "$SUBMIT_DELAY_MS" -gt 0 ]; then
|
||||
sleep_time=$(echo "$SUBMIT_DELAY_MS" | awk 'BEGIN{FS=1} {printf "%f", $1/1000}')
|
||||
sleep "$sleep_time"
|
||||
fi
|
||||
SUBMIT_RESPONSE=$(curl -s -X POST "$API_URL/api/mcp/submit_solution" \
|
||||
-H "Authorization: Bearer $API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-agent-id: $AGENT_ID" \
|
||||
-d '{
|
||||
"task_id": "'"$TASK_ID"'",
|
||||
"claim_token": "'"$CLAIM_TOKEN"'",
|
||||
"deliverables": {
|
||||
"README.md": "Automated verification from external test agent."
|
||||
},
|
||||
"github_pr_url": "https://github.com/example/agent-task-demo/pull/999"
|
||||
}')
|
||||
|
||||
SUBMIT_STATUS=$(echo $SUBMIT_RESPONSE | grep -o '"status":"[^"]*"' | cut -d'"' -f4)
|
||||
SUBMIT_ERROR=$(echo $SUBMIT_RESPONSE | grep -o '"error":"[^"]*"' | cut -d'"' -f4)
|
||||
|
||||
if [ -n "$SUBMIT_ERROR" ]; then
|
||||
echo "❌ Failed to submit solution: $SUBMIT_ERROR"
|
||||
echo $SUBMIT_RESPONSE
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Solution submitted successfully. Status: $SUBMIT_STATUS"
|
||||
fi
|
||||
|
||||
# We won't submit solution because we don't have the real sandbox context.
|
||||
echo "🎉 Test pipeline passed!"
|
||||
|
||||
Reference in New Issue
Block a user