Dart SDK release#105
Conversation
WalkthroughThis PR introduces a complete Dart/Flutter SDK for RunAgent with REST and WebSocket clients, comprehensive error handling, and type definitions. It adds a journalist agent example with Dart support and updates core documentation to reflect Dart availability across all SDKs. Changes
Sequence Diagram(s)sequenceDiagram
participant App
participant RunAgentClient
participant RestClient
participant SocketClient
participant RemoteAgent
App->>RunAgentClient: create(config)
activate RunAgentClient
alt config.local == false (Remote)
RunAgentClient->>RestClient: new(baseUrl, apiKey, isLocal=false)
RunAgentClient->>SocketClient: new(baseSocketUrl, apiKey, isLocal=false)
else config.local == true (Local)
RunAgentClient->>RestClient: new(baseUrl, apiKey, isLocal=true)
RunAgentClient->>SocketClient: new(baseSocketUrl, apiKey, isLocal=true)
end
RunAgentClient->>RestClient: getAgentArchitecture(agentId)
RestClient->>RemoteAgent: GET /agents/{agentId}/architecture
RestClient-->>RunAgentClient: AgentArchitecture
RunAgentClient->>RunAgentClient: validate entrypointTag exists
deactivate RunAgentClient
RunAgentClient-->>App: RunAgentClient instance
App->>RunAgentClient: run(inputKwargs)
activate RunAgentClient
RunAgentClient->>RestClient: runAgent(agentId, entrypointTag, args, kwargs, timeout)
RestClient->>RemoteAgent: POST /run<br/>(with auth header if remote)
RestClient->>RestClient: _translateHttpError if error
RestClient-->>RunAgentClient: response payload
RunAgentClient->>RunAgentClient: _deserializeObject(payload)
deactivate RunAgentClient
RunAgentClient-->>App: dynamic result
App->>RunAgentClient: runStream(inputKwargs)
activate RunAgentClient
RunAgentClient->>SocketClient: runStream(agentId, entrypointTag, args, kwargs)
activate SocketClient
SocketClient->>RemoteAgent: WebSocket upgrade<br/>(ws/wss with auth if remote)
SocketClient->>RemoteAgent: send {entrypoint_tag, input_args, input_kwargs}
loop stream messages
RemoteAgent->>SocketClient: {type: 'data', payload: chunk}
SocketClient->>SocketClient: _deserializeChunk(payload)
SocketClient-->>RunAgentClient: yield deserialized chunk
RunAgentClient-->>App: yield to Stream
end
RemoteAgent->>SocketClient: {type: 'status', status: 'stream_completed'}
SocketClient->>SocketClient: close stream
deactivate SocketClient
deactivate RunAgentClient
sequenceDiagram
participant Client as RestClient
participant HTTP as HTTP Layer
participant Server as Remote Server
Client->>Client: runAgent(...payload)
alt Remote Mode (isLocal=false)
Client->>Client: verify apiKey exists
Client->>Client: throw AuthenticationError if missing
end
Client->>Client: build headers<br/>(Content-Type, User-Agent, Auth if remote)
Client->>HTTP: POST baseUrl/run
alt Success (200)
HTTP-->>Client: response body
Client->>Client: JSON decode response
Client-->>Client: return Map<String, dynamic>
else 401/403
HTTP-->>Client: error response
Client->>Client: _translateHttpError → AuthenticationError
else 500+
HTTP-->>Client: error response
Client->>Client: _translateHttpError → ServerError
else 4xx
HTTP-->>Client: error response
Client->>Client: _translateHttpError → ValidationError
else Timeout
HTTP-->>Client: TimeoutException
Client->>Client: throw ConnectionError
else Connection Error
HTTP-->>Client: exception
Client->>Client: throw ConnectionError
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Tip 📝 Customizable high-level summaries are now available in beta!You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.
Example instruction:
Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 12
♻️ Duplicate comments (1)
examples/journalist_agent/dart_sdk/.dart_tool/package_config.json (1)
1-106: Exclude generated .dart_tool files and avoid exposing local paths.This auto-generated file should not be committed to version control. Additionally, it exposes local file system paths (e.g.,
/home/azureuser/) which could be a privacy concern.
🧹 Nitpick comments (12)
examples/journalist_agent/dart_sdk/Readme.md (1)
34-34: Add explicit host/port defaults documentation.Line 34 states the defaults are
127.0.0.1:8451, but these should be validated against the actual RunAgent local server implementation and explicitly documented in the Dart SDK example code for clarity.Consider adding a code comment or configuration example showing exactly how these defaults are overridden in
test_dart/lib/main.dart:// Example: Set host/port for local development final client = RunAgentClient.create( host: '127.0.0.1', port: 8451, local: true, // Overrides cloud authentication );examples/journalist_agent/agent/requirements.txt (2)
1-1: Remove trailing whitespace.Lines 1 and 4 contain trailing whitespace after the package names. This should be removed for consistency and to avoid potential issues with some tooling.
Also applies to: 4-4
1-6: Consider pinning dependency versions for reproducibility.Most dependencies lack version constraints, which can lead to non-reproducible builds and potential breakage from incompatible updates. Consider using exact versions or at minimum version ranges for all dependencies.
runagent-dart/lib/src/types/types.dart (2)
44-67: Consider removing the redundant factory method.The
RunAgentClientConfig.create()factory method has an identical signature and implementation to the default constructor. In Dart, this duplication is unnecessary unless the factory adds value (validation, defaults computation, etc.).- /// Create a config with required fields - factory RunAgentClientConfig.create({ - required String agentId, - required String entrypointTag, - bool? local, - String? host, - int? port, - String? apiKey, - String? baseUrl, - Map<String, dynamic>? extraParams, - bool? enableRegistry, - }) { - return RunAgentClientConfig( - agentId: agentId, - entrypointTag: entrypointTag, - local: local, - host: host, - port: port, - apiKey: apiKey, - baseUrl: baseUrl, - extraParams: extraParams, - enableRegistry: enableRegistry, - ); - }Alternatively, if the factory is needed for API consistency with other SDKs, keep it but add a comment explaining why it exists.
138-146: RefactortoJson()to acceptentrypointTagas a parameter.The
toJson()method includes a placeholder empty string forentrypoint_tagwith a comment indicating it will be set by the client. This design is fragile and error-prone, as it's easy to forget to update the map after serialization.Refactor to accept the tag as a parameter:
- Map<String, dynamic> toJson() { + Map<String, dynamic> toJson(String entrypointTag) { return { - 'entrypoint_tag': '', // Will be set by client + 'entrypoint_tag': entrypointTag, 'input_args': inputArgs, 'input_kwargs': inputKwargs, 'timeout_seconds': timeoutSeconds, 'async_execution': asyncExecution, }; }This makes the required parameter explicit and prevents serialization with incomplete data.
test_scripts/dart/test_agno/.dart_tool/package_graph.json (1)
1-124: Consider whether.dart_tool/files should be committed.The
package_graph.jsonfile is generated by Dart tooling and resides in the.dart_tool/directory, which is typically listed in.gitignore. While some projects commit these files for reproducibility, the standard practice is to exclude them and let developers regenerate them locally viadart pub get.Verify whether
.dart_tool/is already in.gitignore:#!/bin/bash # Description: Check if .dart_tool is gitignored # Check for .gitignore entries rg -n '\.dart_tool' .gitignoreIf not present, consider adding
.dart_tool/to.gitignoreto follow Dart conventions.runagent-dart/example/basic_example.dart (1)
7-13: Consider explicit null handling for the API key.The
Platform.environment['RUNAGENT_API_KEY']can returnnull, which is passed to theapiKeyparameter. While this may be intentional (relying on SDK defaults or alternative auth mechanisms), consider adding an explicit null check with a helpful error message for clarity.Optional improvement:
final client = await RunAgentClient.create( RunAgentClientConfig.create( agentId: 'YOUR_AGENT_ID', entrypointTag: 'generic', - apiKey: Platform.environment['RUNAGENT_API_KEY'], + apiKey: Platform.environment['RUNAGENT_API_KEY'] ?? + (throw StateError('RUNAGENT_API_KEY environment variable is required')), ), );examples/journalist_agent/dart_sdk/lib/main.dart (1)
6-12: Add trailing comma for consistent Dart formatting.Dart style guidelines recommend adding trailing commas to function arguments for better formatting and readability, especially in nested constructor calls.
Apply this diff:
final client = await RunAgentClient.create( RunAgentClientConfig.create( agentId: '9fac4988-d88e-4d6c-994c-7495c11de8b9', - entrypointTag: 'create_article' + entrypointTag: 'create_article', // local: true, host: '127.0.0.1', port: 8451, ), );test_scripts/dart/test_agno/lib/main.dart (1)
1-31: Consider removing the commented-out code.The large commented-out non-streaming example (lines 1-31) adds clutter. If this alternative implementation is needed for reference, consider moving it to a separate example file or documenting it in the README instead.
Apply this diff to remove the commented block:
-// // async version non-streaming -// import 'dart:io'; -// import 'package:runagent/runagent.dart'; - -// Future<void> main() async { -// try { -// // Direct config construction -// final client = await RunAgentClient.create( -// RunAgentClientConfig.create( -// agentId: 'ae29bd73-b3d3-42c8-a98f-5d7aec7ee919', -// entrypointTag: 'agno_print_response', -// ), -// ); - -// final response = await client.run({ -// 'prompt': 'which is better toyota or land rover', -// }); - -// // Response is a Map, not a String -// print('Response: $response'); // <-- Added semicolon here -// } catch (e) { -// if (e is RunAgentError) { -// print('Error: ${e.message}'); -// if (e.suggestion != null) { -// print('Suggestion: ${e.suggestion}'); -// } -// } else { -// print('Unexpected error: $e'); -// } -// } -// } - // ******************************Streaming Part with agno**************************************** // async version streaming (Flutter/Dart idiomatic approach)runagent-dart/lib/src/utils/constants.dart (1)
35-36: Avoid hard‑coding SDK version inuserAgent()Hard‑coding
runagent-dart/0.1.0here will drift from the package version over time. Consider centralizing the SDK version in a single constant and reusing it (or wiring it from build/pubspec metadata) so bumping the package version doesn’t require hunting this string.class RunAgentConstants { + /// SDK version (keep in sync with pubspec.yaml) + static const String sdkVersion = '0.1.0'; @@ /// User agent string - static String userAgent() => 'runagent-dart/0.1.0'; + static String userAgent() => 'runagent-dart/$sdkVersion'; }runagent-dart/lib/src/errors/errors.dart (1)
31-48: Deduplicate error-code strings between subclasses andErrorCodes
AuthenticationError,PermissionError, etc. each hard‑code their code strings, whileErrorCodesdefines the same values again. This duplication can easily drift if codes are ever renamed.Using
ErrorCodesdirectly in the subclass constructors keeps everything in one place and avoids subtle mismatches.class AuthenticationError extends RunAgentError { AuthenticationError({ required super.message, super.suggestion, super.details, - }) : super(code: 'AUTHENTICATION_ERROR'); + }) : super(code: ErrorCodes.authenticationError); } @@ class PermissionError extends RunAgentError { PermissionError({ required super.message, super.suggestion, super.details, - }) : super(code: 'PERMISSION_ERROR'); + }) : super(code: ErrorCodes.permissionError); } @@ class ConnectionError extends RunAgentError { ConnectionError({ required super.message, super.suggestion, super.details, - }) : super(code: 'CONNECTION_ERROR'); + }) : super(code: ErrorCodes.connectionError); } @@ class ValidationError extends RunAgentError { ValidationError({ required super.message, super.suggestion, super.details, - }) : super(code: 'VALIDATION_ERROR'); + }) : super(code: ErrorCodes.validationError); } @@ class ServerError extends RunAgentError { ServerError({ required super.message, super.suggestion, super.details, - }) : super(code: 'SERVER_ERROR'); + }) : super(code: ErrorCodes.serverError); } @@ class UnknownError extends RunAgentError { UnknownError({ required super.message, super.suggestion, super.details, - }) : super(code: 'UNKNOWN_ERROR'); + }) : super(code: ErrorCodes.unknownError); }Also applies to: 85-98
runagent-dart/lib/src/client/runagent_client.dart (1)
183-214: Factor out shared architecture-loading logic to avoid duplication
_initializeArchitecture()andgetAgentArchitecture()both implement nearly identical logic for callingrestClient.getAgentArchitecture, handling the envelope/legacy formats, and populating_architecture. This duplication is easy to drift if you tweak one path and forget the other.Consider extracting a single private helper that loads and normalizes the architecture once, and reuse it from both places; then
_initializeArchitecture()can focus purely on entrypoint validation.class RunAgentClient { @@ - Future<void> _initializeArchitecture() async { - final architectureJson = await restClient.getAgentArchitecture(agentId); - - // Handle envelope format - if (architectureJson.containsKey('success')) { - final success = architectureJson['success'] as bool?; - if (success == false) { - final error = architectureJson['error']; - if (error is Map<String, dynamic>) { - final errorMessage = error['message']; - final errorCode = error['code']; - throw RunAgentExecutionError( - code: errorCode is String ? errorCode : ErrorCodes.serverError, - message: errorMessage is String ? errorMessage : 'Failed to retrieve agent architecture', - suggestion: error['suggestion'] is String ? error['suggestion'] : null, - details: error['details'] is Map<String, dynamic> ? error['details'] : null, - ); - } - final message = architectureJson['message']; - throw ServerError( - message: message is String ? message : 'Failed to retrieve agent architecture', - ); - } - - final data = architectureJson['data'] as Map<String, dynamic>?; - if (data != null) { - _architecture = AgentArchitecture.fromJson(data); - } - } else { - // Legacy format - _architecture = AgentArchitecture.fromJson(architectureJson); - } - - // Validate entrypoint exists + Future<void> _loadArchitectureIfNeeded() async { + if (_architecture != null) return; + + final architectureJson = await restClient.getAgentArchitecture(agentId); + + if (architectureJson.containsKey('success')) { + final success = architectureJson['success'] as bool?; + if (success == false) { + final error = architectureJson['error']; + if (error is Map<String, dynamic>) { + final errorMessage = error['message']; + final errorCode = error['code']; + throw RunAgentExecutionError( + code: errorCode is String ? errorCode : ErrorCodes.serverError, + message: errorMessage is String ? errorMessage : 'Failed to retrieve agent architecture', + suggestion: error['suggestion'] is String ? error['suggestion'] : null, + details: error['details'] is Map<String, dynamic> ? error['details'] : null, + ); + } + final message = architectureJson['message']; + throw ServerError( + message: message is String ? message : 'Failed to retrieve agent architecture', + ); + } + + final data = architectureJson['data'] as Map<String, dynamic>?; + if (data != null) { + _architecture = AgentArchitecture.fromJson(data); + } + } else { + _architecture = AgentArchitecture.fromJson(architectureJson); + } + if (_architecture == null || _architecture!.entrypoints.isEmpty) { throw ValidationError( message: 'Architecture missing entrypoints', suggestion: 'Redeploy the agent with entrypoints configured', ); } - + } + + Future<void> _initializeArchitecture() async { + await _loadArchitectureIfNeeded(); + + // Validate entrypoint exists final found = _architecture!.entrypoints.any( (ep) => ep.tag == entrypointTag, ); @@ Future<AgentArchitecture> getAgentArchitecture() async { - if (_architecture != null) { - return _architecture!; - } - - final architectureJson = await restClient.getAgentArchitecture(agentId); - - // Handle envelope format - if (architectureJson.containsKey('success')) { - final success = architectureJson['success'] as bool?; - if (success == false) { - final error = architectureJson['error']; - if (error is Map<String, dynamic>) { - final errorMessage = error['message']; - final errorCode = error['code']; - throw RunAgentExecutionError( - code: errorCode is String ? errorCode : ErrorCodes.serverError, - message: errorMessage is String ? errorMessage : 'Failed to retrieve agent architecture', - suggestion: error['suggestion'] is String ? error['suggestion'] : null, - details: error['details'] is Map<String, dynamic> ? error['details'] : null, - ); - } - final message = architectureJson['message']; - throw ServerError( - message: message is String ? message : 'Failed to retrieve agent architecture', - ); - } - - final data = architectureJson['data'] as Map<String, dynamic>?; - if (data != null) { - _architecture = AgentArchitecture.fromJson(data); - } - } else { - // Legacy format - _architecture = AgentArchitecture.fromJson(architectureJson); - } - - if (_architecture == null || _architecture!.entrypoints.isEmpty) { - throw ValidationError( - message: 'Architecture missing entrypoints', - suggestion: 'Redeploy the agent with entrypoints configured', - ); - } - + await _loadArchitectureIfNeeded(); return _architecture!; }Also applies to: 381-411
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (35)
.gitignore(0 hunks)README.md(5 hunks)examples/journalist_agent/agent/main.py(1 hunks)examples/journalist_agent/agent/requirements.txt(1 hunks)examples/journalist_agent/agent/runagent.config.json(1 hunks)examples/journalist_agent/dart_sdk/.dart_tool/package_config.json(1 hunks)examples/journalist_agent/dart_sdk/.dart_tool/package_graph.json(1 hunks)examples/journalist_agent/dart_sdk/Readme.md(1 hunks)examples/journalist_agent/dart_sdk/lib/main.dart(1 hunks)examples/journalist_agent/dart_sdk/pubspec.yaml(1 hunks)runagent-dart/.dart_tool/package_config.json(1 hunks)runagent-dart/.dart_tool/package_graph.json(1 hunks)runagent-dart/CHANGELOG.md(1 hunks)runagent-dart/LICENSE(1 hunks)runagent-dart/PUBLISH.md(1 hunks)runagent-dart/README.md(1 hunks)runagent-dart/example/basic_example.dart(1 hunks)runagent-dart/example/local_example.dart(1 hunks)runagent-dart/example/streaming_example.dart(1 hunks)runagent-dart/lib/runagent.dart(1 hunks)runagent-dart/lib/src/client/rest_client.dart(1 hunks)runagent-dart/lib/src/client/runagent_client.dart(1 hunks)runagent-dart/lib/src/client/socket_client.dart(1 hunks)runagent-dart/lib/src/errors/errors.dart(1 hunks)runagent-dart/lib/src/types/types.dart(1 hunks)runagent-dart/lib/src/utils/config.dart(1 hunks)runagent-dart/lib/src/utils/constants.dart(1 hunks)runagent-dart/pubspec.yaml(1 hunks)runagent-dart/test/runagent_types_test.dart(1 hunks)test/runagent_types_test.dart(1 hunks)test_scripts/dart/test_agno/.dart_tool/package_config.json(1 hunks)test_scripts/dart/test_agno/.dart_tool/package_graph.json(1 hunks)test_scripts/dart/test_agno/README.md(1 hunks)test_scripts/dart/test_agno/lib/main.dart(1 hunks)test_scripts/dart/test_agno/pubspec.yaml(1 hunks)
💤 Files with no reviewable changes (1)
- .gitignore
🔇 Additional comments (24)
examples/journalist_agent/dart_sdk/Readme.md (1)
63-73: No issues found — Dart SDK method signatures verified.The
run()andrunStream()methods exist and their signatures correctly match the documented examples:
run()(line 246) acceptsMap<String, dynamic>?and returnsFuture<dynamic>, supporting theawait client.run({'topic': 'AI developments'})pattern.runStream()(line 350) acceptsMap<String, dynamic>?and returnsStream<dynamic>, supporting theawait forpattern shown in the documentation.README.md (3)
29-29: LGTM!The Dart SDK badge additions are properly structured and consistent with the existing Python, JavaScript, Rust, and Go SDK columns. The pub.dev badge URLs follow the correct format and will display automatically once the package is published.
Also applies to: 54-58, 75-79
233-233: LGTM!The description correctly includes Dart in the list of supported SDK languages.
237-242: LGTM!The Dart SDK code example is well-structured and demonstrates key features:
- Client initialization with configuration
- Non-streaming execution using
run()- Streaming execution using
runStream()withawait forThe code uses idiomatic Dart patterns and is consistent with the other SDK examples. The API design is clean and follows Dart conventions.
Also applies to: 397-430
runagent-dart/example/streaming_example.dart (1)
1-33: LGTM!This streaming example demonstrates best practices:
- Uses environment variables for sensitive data (API key)
- Appropriate placeholder for agent ID
- Proper error handling with specific
RunAgentErrorcatching- Clear demonstration of the
runStream()API withawait for- Helpful comment about the
_streamsuffix conventionThe code is clean, idiomatic Dart, and serves as a good reference for SDK users.
runagent-dart/pubspec.yaml (1)
9-15: Consider updating dependencies within their allowed constraints.Pub uses the GitHub Advisory Database for publishing security advisories for Dart and Flutter packages. Your version constraints are working as intended with the caret operator (^), but there are newer compatible versions available:
http: 1.1.0 → 1.6.0 (compatible)test: 1.24.0 → 1.28.0 (compatible)
web_socket_channel(2.4.0 → 3.0.3) andlints(3.0.0 → 6.0.0) have major version updates available but would require explicit constraint changes. If you intend to stay current on patch/minor updates, rundart pub upgradeto pull in compatible versions. If no security advisories are reported duringdart pub get, your current versions are acceptable.runagent-dart/PUBLISH.md (2)
1-105: LGTM! Clear and comprehensive publishing guide.The publishing workflow is well-structured and follows Dart/pub.dev best practices. The step-by-step instructions with command examples will be helpful for maintainers.
42-45: All example files are present and correctly referenced.Verification confirms that the three example files referenced in lines 42-45 of PUBLISH.md exist and are properly located in
runagent-dart/example/. Thedart runcommands will execute as documented.examples/journalist_agent/agent/main.py (3)
1-9: LGTM! Clean imports and model configuration.The imports and model string format are appropriate for the agno framework.
11-50: LGTM! Well-structured multi-agent team.The journalist team configuration is well-designed with clear role separation between Researcher and Writer agents. The instructions are detailed and appropriate for each role.
67-70: LGTM! Streaming implementation handles chunk variations appropriately.The streaming function correctly yields chunks and includes defensive handling for chunks with or without a
contentattribute.examples/journalist_agent/agent/runagent.config.json (1)
13-32: LGTM! Entrypoints correctly reference the Python functions.The entrypoints configuration correctly maps to the
create_articleandcreate_article_streamfunctions defined in main.py, and the auth settings are properly configured.test_scripts/dart/test_agno/pubspec.yaml (1)
1-10: LGTM! Proper dependency declaration.The pubspec correctly uses a version constraint for the
runagentdependency, making it portable and suitable for published use. The version constraint^0.1.41aligns with the SDK version mentioned in the PR objectives.runagent-dart/CHANGELOG.md (1)
10-26: LGTM! Comprehensive changelog entries.The changelog clearly documents all major features and capabilities added in the initial release, following the Keep a Changelog format.
runagent-dart/README.md (1)
1-228: LGTM! Comprehensive SDK documentation.The README provides clear, well-organized documentation covering all essential aspects: installation options, configuration precedence, local vs remote usage, streaming, error handling, and troubleshooting. The examples are practical and the error taxonomy table is particularly helpful.
runagent-dart/example/local_example.dart (1)
1-34: LGTM! Well-structured local agent example.The example clearly demonstrates local agent usage with appropriate configuration (local flag, host, port) and proper error handling.
test_scripts/dart/test_agno/README.md (1)
1-44: LGTM! Clear test script documentation.The README provides straightforward setup and usage instructions with helpful configuration examples for both remote and local agents.
runagent-dart/test/runagent_types_test.dart (1)
4-74: Type tests look consistent and well‑targetedThe coverage for
RunAgentClientConfig.create,AgentArchitecture.fromJson, andRunInput.toJsonmatches the described semantics and asserts the right normalization and JSON keys/values. No issues spotted here.runagent-dart/lib/runagent.dart (1)
1-11: Public SDK facade is clean and cohesiveThe
runagentlibrary declaration plus consolidated exports of client, errors, types, config, and constants make for a straightforward public entrypoint. Looks good.runagent-dart/lib/src/utils/config.dart (1)
4-69: Env configuration helpers are straightforward and side‑effect freeThe getters and helper functions (
resolveBool,firstNonEmpty,firstNonZero) handle nulls and precedence cleanly, and the behavior matches the inline docs. No issues from a correctness standpoint.runagent-dart/lib/src/client/socket_client.dart (1)
19-216: Streaming client logic and cleanup look solidURL construction, authentication checks, message routing (
error/status/data/fallback), and thefinally‑based channel close are all wired up coherently. Error paths correctly surfaceRunAgentExecutionErrorvs connection issues. Looks good overall.runagent-dart/lib/src/client/rest_client.dart (1)
19-188: REST client behavior and error mapping are consistent
getAgentArchitecture,runAgent, andhealthCheckall follow a clear pattern, and_translateHttpError/_parseApiErrorgive you predictable, typed errors for non‑200 responses while treating transport/timeout issues as connection errors. The auth guard for remoterunAgentalso prevents silent 401s. No blocking issues here.test/runagent_types_test.dart (1)
76-150: Duplicate test suite and secondmain()definition must be removedThis file contains a full duplicate copy of the test suite, including a second
main()function. That will fail to compile and is redundant even if it did.Recommend keeping only one copy of the tests and a single
main():@@ -} -import 'package:runagent/runagent.dart'; -import 'package:test/test.dart'; - -void main() { - group('RunAgentClientConfig', () { - test('create factory mirrors constructor arguments', () { - final config = RunAgentClientConfig.create( - agentId: 'agent-123', - entrypointTag: 'article_create', - local: true, - host: '127.0.0.1', - port: 8451, - apiKey: 'secret', - baseUrl: 'https://example.com', - extraParams: {'foo': 'bar'}, - enableRegistry: false, - ); - - expect(config.agentId, 'agent-123'); - expect(config.entrypointTag, 'article_create'); - expect(config.local, isTrue); - expect(config.host, '127.0.0.1'); - expect(config.port, 8451); - expect(config.apiKey, 'secret'); - expect(config.baseUrl, 'https://example.com'); - expect(config.extraParams, {'foo': 'bar'}); - expect(config.enableRegistry, isFalse); - }); - }); - - group('AgentArchitecture', () { - test('fromJson normalizes agentId and entrypoints', () { - final architecture = AgentArchitecture.fromJson({ - 'agent_id': 42, - 'entrypoints': [ - { - 'tag': 'article_create', - 'file': 'main.py', - 'description': 'Create article', - }, - { - 'tag': 123, - 'module': 'agents.writer', - }, - ], - }); - - expect(architecture.agentId, '42'); - expect(architecture.entrypoints, hasLength(2)); - expect(architecture.entrypoints.first.tag, 'article_create'); - expect(architecture.entrypoints.first.file, 'main.py'); - expect(architecture.entrypoints.last.tag, '123'); - expect(architecture.entrypoints.last.module, 'agents.writer'); - }); - }); - - group('RunInput', () { - test('toJson includes defaults and provided values', () { - final runInput = RunInput( - inputArgs: ['foo'], - inputKwargs: {'bar': 1}, - timeoutSeconds: 120, - asyncExecution: true, - ); - - final json = runInput.toJson(); - - expect(json['entrypoint_tag'], ''); - expect(json['input_args'], ['foo']); - expect(json['input_kwargs'], {'bar': 1}); - expect(json['timeout_seconds'], 120); - expect(json['async_execution'], isTrue); - }); - }); -} +}Likely an incorrect or invalid review comment.
runagent-dart/lib/src/client/runagent_client.dart (1)
246-373: Run vs. runStream guardrails and payload handling look solidThe split between
run/runWithArgsandrunStream/runStreamWithArgs, keyed off the_streamsuffix, plus the generator‑object detection and structured payload deserialization, is well thought out. The failure modes produce meaningfulValidationError/RunAgentExecutionErrorinstances with suggestions, which should make debugging SDK usage much easier.
| def create_article(topic: str): | ||
| """ | ||
| Create a high-quality news article on a given topic | ||
|
|
||
| Args: | ||
| topic: The topic to write about | ||
| """ | ||
| response = journalist_team.run(topic, stream=False) | ||
| return { | ||
| "article": response.content, | ||
| "success": True | ||
| } |
There was a problem hiding this comment.
Consider removing hardcoded success=True or add error handling.
The success field is always set to True, even if journalist_team.run() might encounter issues. While exceptions would still propagate, this could mislead API consumers who check the success flag.
Consider one of these approaches:
Option 1: Remove the success field entirely (simpler)
def create_article(topic: str):
"""
Create a high-quality news article on a given topic
Args:
topic: The topic to write about
"""
response = journalist_team.run(topic, stream=False)
- return {
- "article": response.content,
- "success": True
- }
+ return {"article": response.content}Option 2: Add proper error handling (if success flag is needed by clients)
def create_article(topic: str):
"""
Create a high-quality news article on a given topic
Args:
topic: The topic to write about
"""
+ try:
- response = journalist_team.run(topic, stream=False)
- return {
- "article": response.content,
- "success": True
- }
+ response = journalist_team.run(topic, stream=False)
+ return {
+ "article": response.content,
+ "success": True
+ }
+ except Exception as e:
+ return {
+ "article": "",
+ "success": False,
+ "error": str(e)
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def create_article(topic: str): | |
| """ | |
| Create a high-quality news article on a given topic | |
| Args: | |
| topic: The topic to write about | |
| """ | |
| response = journalist_team.run(topic, stream=False) | |
| return { | |
| "article": response.content, | |
| "success": True | |
| } | |
| def create_article(topic: str): | |
| """ | |
| Create a high-quality news article on a given topic | |
| Args: | |
| topic: The topic to write about | |
| """ | |
| response = journalist_team.run(topic, stream=False) | |
| return {"article": response.content} |
| def create_article(topic: str): | |
| """ | |
| Create a high-quality news article on a given topic | |
| Args: | |
| topic: The topic to write about | |
| """ | |
| response = journalist_team.run(topic, stream=False) | |
| return { | |
| "article": response.content, | |
| "success": True | |
| } | |
| def create_article(topic: str): | |
| """ | |
| Create a high-quality news article on a given topic | |
| Args: | |
| topic: The topic to write about | |
| """ | |
| try: | |
| response = journalist_team.run(topic, stream=False) | |
| return { | |
| "article": response.content, | |
| "success": True | |
| } | |
| except Exception as e: | |
| return { | |
| "article": "", | |
| "success": False, | |
| "error": str(e) | |
| } |
🤖 Prompt for AI Agents
In examples/journalist_agent/agent/main.py around lines 53 to 64, the returned
dict always sets "success": True which can mislead callers if
journalist_team.run() fails; either remove the success field entirely, or wrap
the call in a try/except that returns {"article": response.content, "success":
True} on success and {"article": None, "success": False, "error": str(e)} (or
similar minimal error info) on exception (or re-raise after logging) so the
success flag accurately reflects outcome.
| "template_source": { | ||
| "repo_url": "https://github.com/runagent-dev/runagent.git", | ||
| "author": "runagent-cli", | ||
| "path": "/home/azureuser/runagent/examples/journalist_agent/agent" | ||
| }, |
There was a problem hiding this comment.
Remove hardcoded absolute path from template_source.
The path field contains a hardcoded absolute path /home/azureuser/runagent/... that is specific to one development environment. This breaks portability and won't work for other users or in CI/CD environments.
Apply this diff to use a relative path or remove the hardcoded path:
"template_source": {
"repo_url": "https://github.com/runagent-dev/runagent.git",
"author": "runagent-cli",
- "path": "/home/azureuser/runagent/examples/journalist_agent/agent"
+ "path": "examples/journalist_agent/agent"
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "template_source": { | |
| "repo_url": "https://github.com/runagent-dev/runagent.git", | |
| "author": "runagent-cli", | |
| "path": "/home/azureuser/runagent/examples/journalist_agent/agent" | |
| }, | |
| "template_source": { | |
| "repo_url": "https://github.com/runagent-dev/runagent.git", | |
| "author": "runagent-cli", | |
| "path": "examples/journalist_agent/agent" | |
| }, |
🤖 Prompt for AI Agents
In examples/journalist_agent/agent/runagent.config.json around lines 8 to 12,
the template_source.path is a hardcoded absolute path
(/home/azureuser/runagent/...), which breaks portability; replace it with a
relative path (e.g., path relative to the repository root or the examples
directory) or remove the path field entirely so the repo_url and path resolution
logic can use defaults; update the JSON to use a relative value like
"./examples/journalist_agent/agent" or omit the path key, and ensure any code
that consumes this config resolves paths relative to the config file or repo
root.
| { | ||
| "roots": [ | ||
| "test_journalist" | ||
| ], | ||
| "packages": [ | ||
| { | ||
| "name": "test_journalist", | ||
| "version": "0.1.0", | ||
| "dependencies": [ | ||
| "runagent" | ||
| ], | ||
| "devDependencies": [] | ||
| }, | ||
| { | ||
| "name": "runagent", | ||
| "version": "0.1.0", | ||
| "dependencies": [ | ||
| "http", | ||
| "web_socket_channel" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "web_socket_channel", | ||
| "version": "2.4.5", | ||
| "dependencies": [ | ||
| "async", | ||
| "crypto", | ||
| "stream_channel", | ||
| "web" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "web", | ||
| "version": "0.5.1", | ||
| "dependencies": [] | ||
| }, | ||
| { | ||
| "name": "stream_channel", | ||
| "version": "2.1.4", | ||
| "dependencies": [ | ||
| "async" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "crypto", | ||
| "version": "3.0.7", | ||
| "dependencies": [ | ||
| "typed_data" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "typed_data", | ||
| "version": "1.4.0", | ||
| "dependencies": [ | ||
| "collection" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "collection", | ||
| "version": "1.19.1", | ||
| "dependencies": [] | ||
| }, | ||
| { | ||
| "name": "http", | ||
| "version": "1.6.0", | ||
| "dependencies": [ | ||
| "async", | ||
| "http_parser", | ||
| "meta", | ||
| "web" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "http_parser", | ||
| "version": "4.1.2", | ||
| "dependencies": [ | ||
| "collection", | ||
| "source_span", | ||
| "string_scanner", | ||
| "typed_data" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "string_scanner", | ||
| "version": "1.4.1", | ||
| "dependencies": [ | ||
| "source_span" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "source_span", | ||
| "version": "1.10.1", | ||
| "dependencies": [ | ||
| "collection", | ||
| "path", | ||
| "term_glyph" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "term_glyph", | ||
| "version": "1.2.2", | ||
| "dependencies": [] | ||
| }, | ||
| { | ||
| "name": "path", | ||
| "version": "1.9.1", | ||
| "dependencies": [] | ||
| }, | ||
| { | ||
| "name": "async", | ||
| "version": "2.13.0", | ||
| "dependencies": [ | ||
| "collection", | ||
| "meta" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "meta", | ||
| "version": "1.17.0", | ||
| "dependencies": [] | ||
| } | ||
| ], | ||
| "configVersion": 1 | ||
| } No newline at end of file |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Consider excluding generated .dart_tool files from version control.
The .dart_tool/ directory contains auto-generated Dart tooling files that are typically excluded from version control via .gitignore. These files are regenerated by dart pub get and including them can cause merge conflicts and unnecessary diff noise.
Add .dart_tool/ to your .gitignore and remove these files from the repository:
# Add to .gitignore
echo ".dart_tool/" >> .gitignore
# Remove from git
git rm -r examples/journalist_agent/dart_sdk/.dart_tool/🤖 Prompt for AI Agents
In examples/journalist_agent/dart_sdk/.dart_tool/package_graph.json (lines
1-124): this file lives under the generated .dart_tool/ directory which should
not be versioned; update the repo by adding ".dart_tool/" to the repository
.gitignore, remove the examples/journalist_agent/dart_sdk/.dart_tool/ directory
from git tracking (so it is no longer committed), and commit the changes so
future runs of dart tooling regenerate those files locally without causing diffs
or merge conflicts.
| dependencies: | ||
| runagent: | ||
| path: /home/azureuser/runagent/runagent-dart No newline at end of file |
There was a problem hiding this comment.
Replace absolute path with relative path for portability.
The runagent dependency uses a hardcoded absolute path /home/azureuser/runagent/runagent-dart that is specific to one development environment. This prevents the project from working on other systems.
Apply this diff to use a relative path from the project root:
dependencies:
runagent:
- path: /home/azureuser/runagent/runagent-dart
+ path: ../../../runagent-dartOr, if this is intended for published use, reference the pub.dev package:
dependencies:
- runagent:
- path: /home/azureuser/runagent/runagent-dart
+ runagent: ^0.1.41📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| dependencies: | |
| runagent: | |
| path: /home/azureuser/runagent/runagent-dart | |
| dependencies: | |
| runagent: | |
| path: ../../../runagent-dart |
| dependencies: | |
| runagent: | |
| path: /home/azureuser/runagent/runagent-dart | |
| dependencies: | |
| runagent: ^0.1.41 |
🤖 Prompt for AI Agents
In examples/journalist_agent/dart_sdk/pubspec.yaml around lines 8 to 10, the
runagent dependency uses an absolute path
(/home/azureuser/runagent/runagent-dart) which breaks portability; change it to
a relative path from the project root (e.g., path: ../../runagent/runagent-dart
or the correct relative location within the repo) or, if this package is
intended to be published/consumed from pub.dev, replace the path dependency with
the published package name and version. Ensure the chosen path resolves
correctly from the pubspec.yaml location and update any .gitignore or repo
layout if needed.
| After deployment, you'll get an `agent_id`. Update this in: | ||
| - `backend/app.py` (both client instances) | ||
| - `test_dart/lib/main.dart` | ||
|
|
||
| ### 2.1 Local vs Cloud Runs | ||
|
|
||
| - **Local:** Keep the `local` flag in `test_dart/lib/main.dart` (or your Dart sample) and make sure `host`/`port` point to your `runagent serve` process (defaults: `127.0.0.1:8451`). | ||
| - **Cloud:** Comment out the `local` override, then authenticate once per shell: | ||
|
|
||
| ```bash | ||
| export RUNAGENT_API_KEY="your-runagent-api-key" | ||
| ``` | ||
|
|
||
| Use the cloud agent ID returned from the dashboard when you deploy remotely. |
There was a problem hiding this comment.
🧩 Analysis chain
Clarify agent_id acquisition and local vs cloud configuration.
The instructions reference updating the agent_id in multiple files but don't clearly explain:
- Where/how to find the agent_id from
runagent serveoutput - What the
localflag does and how it's implemented in the Dart code - Whether the default host
127.0.0.1:8451matches the RunAgent local server defaults
Consider adding explicit pointers or example agent_id values, and briefly document how the local flag overrides configuration.
🏁 Script executed:
#!/bin/bash
# Find Dart SDK implementation files
fd -e dart -p 'dart.*sdk|sdk.*dart' --type f | head -20Length of output: 48
🏁 Script executed:
#!/bin/bash
# Search for Dart client implementation with run/runStream methods
rg -n "runStream|\.run\(" --type dart -C 3 | head -50Length of output: 3376
🏁 Script executed:
#!/bin/bash
# Find backend app.py and search for API endpoints
fd -e py 'backend.*app|app.*backend' --type f | head -10Length of output: 0
🏁 Script executed:
#!/bin/bash
# Search for /api/article endpoints in Python files
rg -n "api/article|api.*article" --type py -C 2 | head -50Length of output: 0
🏁 Script executed:
#!/bin/bash
# Find test_dart directory and main.dart file
fd 'test_dart' --type dLength of output: 0
🏁 Script executed:
#!/bin/bash
# Search for configuration with host and port 8451
rg -n "8451|127.0.0.1.*8451" -C 2 | head -50Length of output: 2871
🏁 Script executed:
#!/bin/bash
# Look for runagent configuration or defaults
rg -n "local.*flag|host.*port.*default" --type dart --type py -C 2 | head -50Length of output: 1782
🏁 Script executed:
#!/bin/bash
# List all files in examples/journalist_agent/ to see actual structure
fd . examples/journalist_agent/ --type f | head -30Length of output: 283
🏁 Script executed:
#!/bin/bash
# Search for Python files in examples/journalist_agent/
fd -e py examples/journalist_agent/ --type fLength of output: 409
🏁 Script executed:
#!/bin/bash
# Search for Dart files in examples/journalist_agent/ (excluding dart_sdk/Readme.md)
fd -e dart examples/journalist_agent/ --type fLength of output: 409
🏁 Script executed:
#!/bin/bash
# Search for any backend or app files in examples/ directory
fd -e py examples/ --type f | grep -E "app|backend|server" | head -20Length of output: 341
🏁 Script executed:
#!/bin/bash
# Look for /api/ or article references in all Python files in examples/
rg -n "api.*article|article.*api" --type py examples/ -C 2Length of output: 0
🏁 Script executed:
#!/bin/bash
# Check runagent-dart client implementation for run() method signature
rg -n "Future.*run\(" --type dart runagent-dart/lib/src/ -C 3 | head -40Length of output: 544
🏁 Script executed:
#!/bin/bash
# Read the actual backend agent file
cat examples/journalist_agent/agent/main.pyLength of output: 2587
🏁 Script executed:
#!/bin/bash
# Read the actual Dart example file
cat examples/journalist_agent/dart_sdk/lib/main.dartLength of output: 993
🏁 Script executed:
#!/bin/bash
# Read the config file
cat examples/journalist_agent/agent/runagent.config.jsonLength of output: 799
🏁 Script executed:
#!/bin/bash
# Search for any Flask/FastAPI route decorators and endpoints
rg -n "@app\.|@.*route|@.*post|@.*get" --type py examples/journalist_agent/ -A 2Length of output: 0
🏁 Script executed:
#!/bin/bash
# Search for any article-related code in agent files
rg -n "article" --type py -i examples/journalist_agent/Length of output: 1115
Update file path references to match actual codebase locations.
The README contains incorrect file path references that will prevent developers from following the instructions:
backend/app.py→ should beagent/main.py(though note thatagent/main.pyis the agent definition itself, not a client application—there are no "client instances" to update there)test_dart/lib/main.dart→ should bedart_sdk/lib/main.dart
The correct location for updating the agent_id is in examples/journalist_agent/dart_sdk/lib/main.dart (the hardcoded agentId: '9fac4988-d88e-4d6c-994c-7495c11de8b9'). The reference to updating client instances in backend/app.py does not apply to the actual codebase structure, since agent/main.py contains the agent definition, not client code. Clarify or remove the backend reference to avoid confusion.
| { | ||
| "roots": [ | ||
| "runagent" | ||
| ], | ||
| "packages": [ | ||
| { | ||
| "name": "runagent", | ||
| "version": "0.1.41", | ||
| "dependencies": [ | ||
| "http", | ||
| "web_socket_channel" | ||
| ], | ||
| "devDependencies": [ | ||
| "lints", | ||
| "test" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "lints", | ||
| "version": "3.0.0", | ||
| "dependencies": [] | ||
| }, | ||
| { | ||
| "name": "test", | ||
| "version": "1.28.0", | ||
| "dependencies": [ | ||
| "analyzer", | ||
| "async", | ||
| "boolean_selector", | ||
| "collection", | ||
| "coverage", | ||
| "http_multi_server", | ||
| "io", | ||
| "matcher", | ||
| "node_preamble", | ||
| "package_config", | ||
| "path", | ||
| "pool", | ||
| "shelf", | ||
| "shelf_packages_handler", | ||
| "shelf_static", | ||
| "shelf_web_socket", | ||
| "source_span", | ||
| "stack_trace", | ||
| "stream_channel", | ||
| "test_api", | ||
| "test_core", | ||
| "typed_data", | ||
| "web_socket_channel", | ||
| "webkit_inspection_protocol", | ||
| "yaml" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "web_socket_channel", | ||
| "version": "2.4.5", | ||
| "dependencies": [ | ||
| "async", | ||
| "crypto", | ||
| "stream_channel", | ||
| "web" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "http", | ||
| "version": "1.6.0", | ||
| "dependencies": [ | ||
| "async", | ||
| "http_parser", | ||
| "meta", | ||
| "web" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "yaml", | ||
| "version": "3.1.3", | ||
| "dependencies": [ | ||
| "collection", | ||
| "source_span", | ||
| "string_scanner" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "webkit_inspection_protocol", | ||
| "version": "1.2.1", | ||
| "dependencies": [ | ||
| "logging" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "typed_data", | ||
| "version": "1.4.0", | ||
| "dependencies": [ | ||
| "collection" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "test_core", | ||
| "version": "0.6.14", | ||
| "dependencies": [ | ||
| "analyzer", | ||
| "args", | ||
| "async", | ||
| "boolean_selector", | ||
| "collection", | ||
| "coverage", | ||
| "frontend_server_client", | ||
| "glob", | ||
| "io", | ||
| "meta", | ||
| "package_config", | ||
| "path", | ||
| "pool", | ||
| "source_map_stack_trace", | ||
| "source_maps", | ||
| "source_span", | ||
| "stack_trace", | ||
| "stream_channel", | ||
| "test_api", | ||
| "vm_service", | ||
| "yaml" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "test_api", | ||
| "version": "0.7.8", | ||
| "dependencies": [ | ||
| "async", | ||
| "boolean_selector", | ||
| "collection", | ||
| "meta", | ||
| "source_span", | ||
| "stack_trace", | ||
| "stream_channel", | ||
| "string_scanner", | ||
| "term_glyph" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "stream_channel", | ||
| "version": "2.1.4", | ||
| "dependencies": [ | ||
| "async" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "stack_trace", | ||
| "version": "1.12.1", | ||
| "dependencies": [ | ||
| "path" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "source_span", | ||
| "version": "1.10.1", | ||
| "dependencies": [ | ||
| "collection", | ||
| "path", | ||
| "term_glyph" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "shelf_web_socket", | ||
| "version": "3.0.0", | ||
| "dependencies": [ | ||
| "shelf", | ||
| "stream_channel", | ||
| "web_socket_channel" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "shelf_static", | ||
| "version": "1.1.3", | ||
| "dependencies": [ | ||
| "convert", | ||
| "http_parser", | ||
| "mime", | ||
| "path", | ||
| "shelf" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "shelf_packages_handler", | ||
| "version": "3.0.2", | ||
| "dependencies": [ | ||
| "path", | ||
| "shelf", | ||
| "shelf_static" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "shelf", | ||
| "version": "1.4.2", | ||
| "dependencies": [ | ||
| "async", | ||
| "collection", | ||
| "http_parser", | ||
| "path", | ||
| "stack_trace", | ||
| "stream_channel" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "pool", | ||
| "version": "1.5.2", | ||
| "dependencies": [ | ||
| "async", | ||
| "stack_trace" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "path", | ||
| "version": "1.9.1", | ||
| "dependencies": [] | ||
| }, | ||
| { | ||
| "name": "package_config", | ||
| "version": "2.2.0", | ||
| "dependencies": [ | ||
| "path" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "node_preamble", | ||
| "version": "2.0.2", | ||
| "dependencies": [] | ||
| }, | ||
| { | ||
| "name": "matcher", | ||
| "version": "0.12.18", | ||
| "dependencies": [ | ||
| "async", | ||
| "meta", | ||
| "stack_trace", | ||
| "term_glyph", | ||
| "test_api" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "io", | ||
| "version": "1.0.5", | ||
| "dependencies": [ | ||
| "meta", | ||
| "path", | ||
| "string_scanner" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "http_multi_server", | ||
| "version": "3.2.2", | ||
| "dependencies": [ | ||
| "async" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "coverage", | ||
| "version": "1.15.0", | ||
| "dependencies": [ | ||
| "args", | ||
| "cli_config", | ||
| "glob", | ||
| "logging", | ||
| "meta", | ||
| "package_config", | ||
| "path", | ||
| "source_maps", | ||
| "stack_trace", | ||
| "vm_service", | ||
| "yaml" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "collection", | ||
| "version": "1.19.1", | ||
| "dependencies": [] | ||
| }, | ||
| { | ||
| "name": "boolean_selector", | ||
| "version": "2.1.2", | ||
| "dependencies": [ | ||
| "source_span", | ||
| "string_scanner" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "async", | ||
| "version": "2.13.0", | ||
| "dependencies": [ | ||
| "collection", | ||
| "meta" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "analyzer", | ||
| "version": "9.0.0", | ||
| "dependencies": [ | ||
| "_fe_analyzer_shared", | ||
| "collection", | ||
| "convert", | ||
| "crypto", | ||
| "glob", | ||
| "meta", | ||
| "package_config", | ||
| "path", | ||
| "pub_semver", | ||
| "source_span", | ||
| "watcher", | ||
| "yaml" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "web", | ||
| "version": "0.5.1", | ||
| "dependencies": [] | ||
| }, | ||
| { | ||
| "name": "crypto", | ||
| "version": "3.0.7", | ||
| "dependencies": [ | ||
| "typed_data" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "meta", | ||
| "version": "1.17.0", | ||
| "dependencies": [] | ||
| }, | ||
| { | ||
| "name": "http_parser", | ||
| "version": "4.1.2", | ||
| "dependencies": [ | ||
| "collection", | ||
| "source_span", | ||
| "string_scanner", | ||
| "typed_data" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "string_scanner", | ||
| "version": "1.4.1", | ||
| "dependencies": [ | ||
| "source_span" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "logging", | ||
| "version": "1.3.0", | ||
| "dependencies": [] | ||
| }, | ||
| { | ||
| "name": "vm_service", | ||
| "version": "15.0.2", | ||
| "dependencies": [] | ||
| }, | ||
| { | ||
| "name": "source_maps", | ||
| "version": "0.10.13", | ||
| "dependencies": [ | ||
| "source_span" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "source_map_stack_trace", | ||
| "version": "2.1.2", | ||
| "dependencies": [ | ||
| "path", | ||
| "source_maps", | ||
| "stack_trace" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "glob", | ||
| "version": "2.1.3", | ||
| "dependencies": [ | ||
| "async", | ||
| "collection", | ||
| "file", | ||
| "path", | ||
| "string_scanner" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "frontend_server_client", | ||
| "version": "4.0.0", | ||
| "dependencies": [ | ||
| "async", | ||
| "path" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "args", | ||
| "version": "2.7.0", | ||
| "dependencies": [] | ||
| }, | ||
| { | ||
| "name": "term_glyph", | ||
| "version": "1.2.2", | ||
| "dependencies": [] | ||
| }, | ||
| { | ||
| "name": "mime", | ||
| "version": "2.0.0", | ||
| "dependencies": [] | ||
| }, | ||
| { | ||
| "name": "convert", | ||
| "version": "3.1.2", | ||
| "dependencies": [ | ||
| "typed_data" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "cli_config", | ||
| "version": "0.2.0", | ||
| "dependencies": [ | ||
| "args", | ||
| "yaml" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "watcher", | ||
| "version": "1.1.4", | ||
| "dependencies": [ | ||
| "async", | ||
| "path" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "pub_semver", | ||
| "version": "2.2.0", | ||
| "dependencies": [ | ||
| "collection" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "_fe_analyzer_shared", | ||
| "version": "92.0.0", | ||
| "dependencies": [ | ||
| "meta" | ||
| ] | ||
| }, | ||
| { | ||
| "name": "file", | ||
| "version": "7.0.1", | ||
| "dependencies": [ | ||
| "meta", | ||
| "path" | ||
| ] | ||
| } | ||
| ], | ||
| "configVersion": 1 | ||
| } No newline at end of file |
There was a problem hiding this comment.
Remove generated .dart_tool files from version control.
The .dart_tool/ directory contains auto-generated files that should not be committed to version control. These files are regenerated by Dart's pub tool on each machine and can cause merge conflicts. Add .dart_tool/ to your .gitignore file.
Apply this change to your .gitignore:
+# Dart tool files
+.dart_tool/
+.packagesCommittable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In runagent-dart/.dart_tool/package_graph.json lines 1-452: the committed
.dart_tool directory is generated and should be removed from version control;
update .gitignore to add a line ".dart_tool/" (or ".dart_tool" ), then remove
the tracked files and directory from git (e.g. git rm -r --cached .dart_tool &&
git commit -m "Remove generated .dart_tool files and add to .gitignore") so the
folder remains local and untracked on future commits.
| The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), | ||
| and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||
|
|
||
| ## [0.1.41] - 2024-XX-XX |
There was a problem hiding this comment.
Update placeholder date before release.
The release date is set to 2024-XX-XX as a placeholder. Ensure this is updated to the actual release date before publishing to pub.dev.
-## [0.1.41] - 2024-XX-XX
+## [0.1.41] - 2025-XX-XXNote: The year should be 2025 based on the PR creation date (2025-11-24 from PR objectives).
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ## [0.1.41] - 2024-XX-XX | |
| ## [0.1.41] - 2025-XX-XX |
🤖 Prompt for AI Agents
In runagent-dart/CHANGELOG.md around line 8, the release entry uses a
placeholder date "2024-XX-XX"; update this to the actual release date (replace
"2024-XX-XX" with the real YYYY-MM-DD) and make sure the year is 2025 per the PR
creation date; commit the updated CHANGELOG.md with the correct ISO-style date
for the release.
| factory AgentArchitecture.fromJson(Map<String, dynamic> json) { | ||
| final agentIdValue = json['agent_id'] ?? json['agentId']; | ||
| final entrypointsValue = json['entrypoints']; | ||
|
|
||
| return AgentArchitecture( | ||
| agentId: agentIdValue is String ? agentIdValue : (agentIdValue?.toString() ?? ''), | ||
| entrypoints: entrypointsValue is List | ||
| ? entrypointsValue | ||
| .whereType<Map<String, dynamic>>() | ||
| .map((e) => EntryPoint.fromJson(e)) | ||
| .toList() | ||
| : [], | ||
| ); | ||
| } |
There was a problem hiding this comment.
Consider validation for required agentId field.
The fromJson method tolerantly converts missing or invalid agentId values to an empty string (line 85). While this defensive parsing prevents exceptions, it allows invalid AgentArchitecture objects to be created with an empty required field. Consider whether validation should be stricter here.
If agentId is truly required, consider throwing an exception for missing/invalid values:
factory AgentArchitecture.fromJson(Map<String, dynamic> json) {
final agentIdValue = json['agent_id'] ?? json['agentId'];
final entrypointsValue = json['entrypoints'];
+
+ if (agentIdValue == null || agentIdValue.toString().isEmpty) {
+ throw FormatException('agentId is required in AgentArchitecture');
+ }
return AgentArchitecture(
agentId: agentIdValue is String ? agentIdValue : (agentIdValue?.toString() ?? ''),
entrypoints: entrypointsValue is List
? entrypointsValue
.whereType<Map<String, dynamic>>()
.map((e) => EntryPoint.fromJson(e))
.toList()
: [],
);
}Alternatively, if silent fallback is intentional (e.g., for partial data scenarios), add a comment explaining the design decision.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| factory AgentArchitecture.fromJson(Map<String, dynamic> json) { | |
| final agentIdValue = json['agent_id'] ?? json['agentId']; | |
| final entrypointsValue = json['entrypoints']; | |
| return AgentArchitecture( | |
| agentId: agentIdValue is String ? agentIdValue : (agentIdValue?.toString() ?? ''), | |
| entrypoints: entrypointsValue is List | |
| ? entrypointsValue | |
| .whereType<Map<String, dynamic>>() | |
| .map((e) => EntryPoint.fromJson(e)) | |
| .toList() | |
| : [], | |
| ); | |
| } | |
| factory AgentArchitecture.fromJson(Map<String, dynamic> json) { | |
| final agentIdValue = json['agent_id'] ?? json['agentId']; | |
| final entrypointsValue = json['entrypoints']; | |
| if (agentIdValue == null || agentIdValue.toString().isEmpty) { | |
| throw FormatException('agentId is required in AgentArchitecture'); | |
| } | |
| return AgentArchitecture( | |
| agentId: agentIdValue is String ? agentIdValue : (agentIdValue?.toString() ?? ''), | |
| entrypoints: entrypointsValue is List | |
| ? entrypointsValue | |
| .whereType<Map<String, dynamic>>() | |
| .map((e) => EntryPoint.fromJson(e)) | |
| .toList() | |
| : [], | |
| ); | |
| } |
🤖 Prompt for AI Agents
In runagent-dart/lib/src/types/types.dart around lines 80 to 93, the factory
currently converts a missing or invalid agentId to an empty string which permits
creating invalid AgentArchitecture instances; update the factory to validate
agentId: read agentIdValue (from 'agent_id' or 'agentId'), convert to String if
present, then if the resulting string is null or empty throw a descriptive
FormatException (or ArgumentError) indicating agentId is required; if the
project intentionally allows empty agentId, instead add a clear comment above
the factory describing that silent fallback behavior and why it is acceptable.
| factory EntryPoint.fromJson(Map<String, dynamic> json) { | ||
| final tagValue = json['tag']; | ||
| return EntryPoint( | ||
| tag: tagValue is String ? tagValue : (tagValue?.toString() ?? ''), | ||
| file: json['file'] is String ? json['file'] : null, | ||
| module: json['module'] is String ? json['module'] : null, | ||
| extractor: json['extractor'] is String ? json['extractor'] : null, | ||
| description: json['description'] is String ? json['description'] : null, | ||
| ); | ||
| } |
There was a problem hiding this comment.
Consider validation for required tag field.
Similar to AgentArchitecture, the fromJson method converts missing or invalid tag values to an empty string (line 115). This allows invalid EntryPoint objects with empty required fields.
Consider adding validation:
factory EntryPoint.fromJson(Map<String, dynamic> json) {
final tagValue = json['tag'];
+
+ if (tagValue == null || tagValue.toString().isEmpty) {
+ throw FormatException('tag is required in EntryPoint');
+ }
+
return EntryPoint(
tag: tagValue is String ? tagValue : (tagValue?.toString() ?? ''),
file: json['file'] is String ? json['file'] : null,
module: json['module'] is String ? json['module'] : null,
extractor: json['extractor'] is String ? json['extractor'] : null,
description: json['description'] is String ? json['description'] : null,
);
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| factory EntryPoint.fromJson(Map<String, dynamic> json) { | |
| final tagValue = json['tag']; | |
| return EntryPoint( | |
| tag: tagValue is String ? tagValue : (tagValue?.toString() ?? ''), | |
| file: json['file'] is String ? json['file'] : null, | |
| module: json['module'] is String ? json['module'] : null, | |
| extractor: json['extractor'] is String ? json['extractor'] : null, | |
| description: json['description'] is String ? json['description'] : null, | |
| ); | |
| } | |
| factory EntryPoint.fromJson(Map<String, dynamic> json) { | |
| final tagValue = json['tag']; | |
| if (tagValue == null || tagValue.toString().isEmpty) { | |
| throw FormatException('tag is required in EntryPoint'); | |
| } | |
| return EntryPoint( | |
| tag: tagValue is String ? tagValue : (tagValue?.toString() ?? ''), | |
| file: json['file'] is String ? json['file'] : null, | |
| module: json['module'] is String ? json['module'] : null, | |
| extractor: json['extractor'] is String ? json['extractor'] : null, | |
| description: json['description'] is String ? json['description'] : null, | |
| ); | |
| } |
🤖 Prompt for AI Agents
In runagent-dart/lib/src/types/types.dart around lines 112 to 121, the
EntryPoint.fromJson factory silently converts a missing or invalid tag into an
empty string which allows construction of invalid EntryPoint instances; change
the method to validate that json['tag'] exists and is a non-empty String and if
not throw a FormatException (or return null/throw) instead of coercing to '',
and keep other optional fields as-is—this ensures required tag is enforced and
invalid input fails fast.
| { | ||
| "configVersion": 2, | ||
| "packages": [ | ||
| { | ||
| "name": "async", | ||
| "rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/async-2.13.0", | ||
| "packageUri": "lib/", | ||
| "languageVersion": "3.4" | ||
| }, | ||
| { | ||
| "name": "collection", | ||
| "rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/collection-1.19.1", | ||
| "packageUri": "lib/", | ||
| "languageVersion": "3.4" | ||
| }, | ||
| { | ||
| "name": "crypto", | ||
| "rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/crypto-3.0.7", | ||
| "packageUri": "lib/", | ||
| "languageVersion": "3.4" | ||
| }, | ||
| { | ||
| "name": "http", | ||
| "rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/http-1.6.0", | ||
| "packageUri": "lib/", | ||
| "languageVersion": "3.4" | ||
| }, | ||
| { | ||
| "name": "http_parser", | ||
| "rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/http_parser-4.1.2", | ||
| "packageUri": "lib/", | ||
| "languageVersion": "3.4" | ||
| }, | ||
| { | ||
| "name": "meta", | ||
| "rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/meta-1.17.0", | ||
| "packageUri": "lib/", | ||
| "languageVersion": "3.5" | ||
| }, | ||
| { | ||
| "name": "path", | ||
| "rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/path-1.9.1", | ||
| "packageUri": "lib/", | ||
| "languageVersion": "3.4" | ||
| }, | ||
| { | ||
| "name": "runagent", | ||
| "rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/runagent-0.1.41", | ||
| "packageUri": "lib/", | ||
| "languageVersion": "3.0" | ||
| }, | ||
| { | ||
| "name": "source_span", | ||
| "rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/source_span-1.10.1", | ||
| "packageUri": "lib/", | ||
| "languageVersion": "3.1" | ||
| }, | ||
| { | ||
| "name": "stream_channel", | ||
| "rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/stream_channel-2.1.4", | ||
| "packageUri": "lib/", | ||
| "languageVersion": "3.3" | ||
| }, | ||
| { | ||
| "name": "string_scanner", | ||
| "rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/string_scanner-1.4.1", | ||
| "packageUri": "lib/", | ||
| "languageVersion": "3.1" | ||
| }, | ||
| { | ||
| "name": "term_glyph", | ||
| "rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/term_glyph-1.2.2", | ||
| "packageUri": "lib/", | ||
| "languageVersion": "3.1" | ||
| }, | ||
| { | ||
| "name": "typed_data", | ||
| "rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/typed_data-1.4.0", | ||
| "packageUri": "lib/", | ||
| "languageVersion": "3.5" | ||
| }, | ||
| { | ||
| "name": "web", | ||
| "rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/web-0.5.1", | ||
| "packageUri": "lib/", | ||
| "languageVersion": "3.3" | ||
| }, | ||
| { | ||
| "name": "web_socket_channel", | ||
| "rootUri": "file:///home/azureuser/.pub-cache/hosted/pub.dev/web_socket_channel-2.4.5", | ||
| "packageUri": "lib/", | ||
| "languageVersion": "3.3" | ||
| }, | ||
| { | ||
| "name": "test_agno", | ||
| "rootUri": "../", | ||
| "packageUri": "lib/", | ||
| "languageVersion": "3.0" | ||
| } | ||
| ], | ||
| "generator": "pub", | ||
| "generatorVersion": "3.10.0", | ||
| "flutterRoot": "file:///home/azureuser/snap/flutter/common/flutter", | ||
| "flutterVersion": "3.38.2", | ||
| "pubCache": "file:///home/azureuser/.pub-cache" | ||
| } |
There was a problem hiding this comment.
Remove generated configuration file with absolute paths.
This file contains machine-specific absolute paths (e.g., /home/azureuser/.pub-cache) that will not work on other machines. As a generated file in the .dart_tool/ directory, it should not be committed to version control.
Ensure .dart_tool/ is in your .gitignore to prevent committing generated files:
+# Dart tool files
+.dart_tool/
+.packagesCommittable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In test_scripts/dart/test_agno/.dart_tool/package_config.json lines 1-106: this
is a generated file containing machine-specific absolute paths and must not be
committed; remove the file from the repository, add .dart_tool/ to .gitignore
(or ensure it is present), commit the .gitignore change, and then delete the
tracked package_config.json from git (git rm --cached or equivalent) so it is no
longer versioned; developers can recreate it locally by running pub get/flutter
pub get when needed.
Summary
Adds the RunAgent Dart SDK to the main README, including badges and code examples alongside the existing Python, JavaScript, Rust, and Go SDKs.
Changes
runagent-dart)RunAgentClient.create()client.run()client.runStream()Badge Status
The pub.dev badges will display automatically once the package is published to pub.dev. The badge URLs are correct and will work after publishing
runagentversion0.1.41.Related
runagent-dart(version 0.1.41)