Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 15 additions & 45 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,29 @@
# Changelog
All notable changes to this project's latest version.

## [0.1.24] - 2025-11-06
## [0.1.25] - 2025-11-12

### Bug Fixes

- Fixed examples on run cmd
- Init command fixing wip

### Documentation

- Sdk folder removed
- Added explanation folder
- Removed example folder
- Removed frameworks folder
- Removed get started folder
- Added how to folder
- Added resources folder
- Added new snippet
- Added tutorials
- Added reference
- Added new api reference
- Added cli overview
- Added new docs.json
- Added agent ID to all templates json ([#76](https://github.com/your-org/your-repo/issues/76))
- Add shorthand option for confirmation skip in teardown command
- Update console output formatting for extra parameters in run and run_stream commands

### Features

- Removed deploy-local command
- Deploy-local fully removed
- Updated same upload_agent function names
- Fingerprint feature added back to db
- Added git validation & efficient connectivity check
- Agent run cli working for remote+local
- Run-stream working locally, proper json format.
- Improved langgarph default template
- URL prefix working > rest+socket
- Debug option fixed
- Auth test fixed with updated endpoint
- Runagent deploy working
- Moved user_data json ro sqlite db approach
- Init coomand interactive
- Fixed & improved template downloading
- Split cli cmds into seperate files
- Express login [device-browser code flow] added
- Persistent agent id working
- Cleaned emojis form output
- Added whoami command
- Standardized local agent execution logging
- Auto rewload suported in local server
- Removed replacing agent id
- Muted db replace agent option
- Improved debug log
- Removed capacity tracking of local agents
- Improve init message
- Enhance error handling and suggestions in deployment and upload commands
- Enhanced init command
- Update deployment and initialization to include dashboard URLs and enhance agent configuration
- Add structured serialization and deserialization methods to CoreSerializer

### Miscellaneous Tasks

- Bump version to v0.1.24
- Bump version to v0.1.25

### Refactor

- Improve error handling and messaging in WebSocket and REST client

<!-- generated by git-cliff -->
20 changes: 20 additions & 0 deletions docs/cli/commands/run.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,26 @@ The input must be valid JSON:
}
```

## Response Format

The CLI and SDK now return a minimal payload when the execution completes:

```json
{
"success": true,
"data": "{\"type\": \"string\", \"payload\": \"...\"}",
"message": "Agent execution completed successfully",
"error": null,
"timestamp": "2025-11-12T22:23:35.216480",
"request_id": "adffa696-6273-4c5b-a933-883d830fd72c"
}
```

- `data` contains the agent output encoded with `serialize_object_to_structured`, so the CLI/SDK can deterministically decode every result type.
- Full execution metadata (runtime, VM, invocation ID, etc.) remains available through the local invocation history endpoints and the RunAgent dashboard/middleware.

Error responses keep the same envelope but include an `error` object with diagnostic fields.

## See Also

- [`runagent deploy`](/cli/commands/deploy) - Deploy an agent first
Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ build-backend = "hatchling.build"

[project]
name = "runagent"
version = "0.1.25"
version = "0.1.26"
description = "A command-line tool and SDK for deploying, managing, and interacting with AI agents"
readme = "README.md"
requires-python = ">=3.9"
Expand Down Expand Up @@ -103,7 +103,7 @@ line_length = 88
skip = ["docs"]

[tool.mypy]
python_version = "0.1.25"
python_version = "0.1.26"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
Expand Down Expand Up @@ -159,7 +159,7 @@ fail_under = 80

[tool.ruff]
line-length = 88
target-version = "0.1.25"
target-version = "0.1.26"
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
Expand Down
54 changes: 52 additions & 2 deletions runagent-go/runagent/pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"io"
"net/http"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -241,9 +242,23 @@ func (c *Client) Run(ctx context.Context, input map[string]interface{}) (interfa
}
}

// Return output_data if it exists, otherwise return the whole response
// Handle data field (simplified structured output or legacy execution payload)
if dataField, exists := response["data"]; exists {
switch data := dataField.(type) {
case string:
return c.serializer.DeserializeStructuredString(data), nil
case map[string]interface{}:
if resultData, ok := data["result_data"].(map[string]interface{}); ok {
if output, ok := resultData["data"]; ok {
return c.serializer.DeserializeObject(output, false), nil
}
}
}
}

// Legacy fallback: return output_data if it exists
if outputData, exists := response["output_data"]; exists {
return outputData, nil
return c.serializer.DeserializeObject(outputData, false), nil
}

return response, nil
Expand Down Expand Up @@ -446,6 +461,38 @@ func NewCoreSerializer() *CoreSerializer {
return &CoreSerializer{}
}

// DeserializeStructuredString converts structured serializer output to native Go types
func (s *CoreSerializer) DeserializeStructuredString(structured string) interface{} {
var structuredMap map[string]interface{}
if err := json.Unmarshal([]byte(structured), &structuredMap); err != nil {
if unquoted, err2 := strconv.Unquote(structured); err2 == nil {
return unquoted
}
return structured
}

payload, payloadExists := structuredMap["payload"]
if !payloadExists {
return structuredMap
}

switch p := payload.(type) {
case string:
if len(p) > 0 {
var decoded interface{}
if err := json.Unmarshal([]byte(p), &decoded); err == nil {
return decoded
}
if unquoted, err := strconv.Unquote(p); err == nil {
return unquoted
}
}
return p
default:
return p
}
}

// SerializeMessage serializes a WebSocket message
func (s *CoreSerializer) SerializeMessage(message WebSocketMessage) (string, error) {
messageDict := map[string]interface{}{
Expand Down Expand Up @@ -504,5 +551,8 @@ func (s *CoreSerializer) DeserializeMessage(jsonStr string) (*WebSocketMessage,

// DeserializeObject deserializes a JSON object
func (s *CoreSerializer) DeserializeObject(jsonResp interface{}, reconstruct bool) interface{} {
if str, ok := jsonResp.(string); ok {
return s.DeserializeStructuredString(str)
}
return jsonResp // Simple pass-through for now
}
2 changes: 1 addition & 1 deletion runagent-go/runagent/version.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package runagent

// Version represents the current version of the RunAgent Go SDK
const Version = "0.1.25"
const Version = "0.1.26"
2 changes: 1 addition & 1 deletion runagent-rust/runagent/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "runagent"
version = "0.1.25"
version = "0.1.26"
edition = "2021"
description = "RunAgent SDK for Rust - Client SDK for interacting with deployed AI agents"
license = "MIT"
Expand Down
12 changes: 11 additions & 1 deletion runagent-rust/runagent/src/client/runagent_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,18 @@ impl RunAgentClient {
.await?;

if response.get("success").and_then(|s| s.as_bool()).unwrap_or(false) {
// Handle new response format with nested data (matching Python SDK)
if let Some(data) = response.get("data") {
// Simplified payload: data is a structured output string
if let Some(data_str) = data.as_str() {
if let Ok(parsed) = serde_json::from_str::<Value>(data_str) {
return self.serializer.deserialize_object(parsed);
}
return self
.serializer
.deserialize_object(Value::String(data_str.to_string()));
}

// Legacy detailed execution payload
if let Some(result_data) = data.get("result_data") {
if let Some(output_data) = result_data.get("data") {
// Check if the output contains a generator object string
Expand Down
4 changes: 2 additions & 2 deletions runagent-ts/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion runagent-ts/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "runagent",
"version": "0.1.25",
"version": "0.1.26",
"type": "module",
"files": [
"dist"
Expand Down
35 changes: 31 additions & 4 deletions runagent-ts/src/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,38 @@ export class RunAgentClient {
);

if (response.success !== false) {
const responseData = response.output_data;
return this.serializer.deserializeObject(responseData as JsonValue);
} else {
throw new Error(response.error || 'Agent execution failed');
let payload: unknown = null;

if (typeof response.data === 'string') {
payload = this.serializer.deserializeObject(response.data);
} else if (
response.data &&
typeof response.data === 'object' &&
'result_data' in (response.data as Record<string, unknown>)
) {
const resultData = (response.data as Record<string, unknown>)['result_data'];
if (
resultData &&
typeof resultData === 'object' &&
'data' in (resultData as Record<string, unknown>)
) {
payload = this.serializer.deserializeObject(
(resultData as Record<string, unknown>)['data'] as JsonValue
);
}
} else if (response.output_data !== undefined) {
payload = this.serializer.deserializeObject(response.output_data as JsonValue);
}

return payload ?? null;
}

const errorMessage =
typeof response.error === 'string'
? response.error
: (response.error as { message?: string })?.message ?? 'Agent execution failed';

throw new Error(errorMessage);
}

private async *_runStream(
Expand Down
22 changes: 22 additions & 0 deletions runagent-ts/src/serializer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,28 @@ export class CoreSerializer {
try {
const deserializedData = typeof jsonResp === 'string' ? JSON.parse(jsonResp) : jsonResp;

if (
deserializedData &&
typeof deserializedData === 'object' &&
deserializedData !== null &&
'type' in (deserializedData as Record<string, unknown>) &&
'payload' in (deserializedData as Record<string, unknown>)
) {
const structured = deserializedData as { type?: string; payload?: unknown };
const payload = structured.payload;

if (typeof payload === 'string') {
try {
const parsedPayload = JSON.parse(payload);
return this._reconstructNestedJson(parsedPayload);
} catch {
return payload;
}
}

return this._reconstructNestedJson(payload);
}

if (!reconstruct) {
return this._reconstructNestedJson(
(deserializedData as Record<string, unknown>)?.content || deserializedData
Expand Down
22 changes: 16 additions & 6 deletions runagent-ts/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,22 @@ export interface RunAgentConfig {
apiPrefix?: string;
}

export interface ApiResponse<T = unknown> {
success: boolean;
output_data?: T;
error?: string;
data?: T;
}
export interface ApiResponse<T = JsonValue> {
success: boolean;
data?: T;
output_data?: T;
error?:
| string
| {
code?: string;
message?: string;
details?: unknown;
field?: string | null;
};
message?: string | null;
timestamp?: string | null;
request_id?: string | null;
}

export interface WebSocketMessage<T = unknown> {
id: string;
Expand Down
2 changes: 1 addition & 1 deletion runagent/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
built with frameworks like LangGraph, LangChain, and LlamaIndex.
"""

__version__ = "0.1.25"
__version__ = "0.1.26"

from .client import RunAgentClient

Expand Down
2 changes: 1 addition & 1 deletion runagent/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.1.25"
__version__ = "0.1.26"
Loading
Loading