Conversation
|
Thank you for your pull request and welcome to our community! To contribute, please sign the Oracle Contributor Agreement (OCA).
To sign the OCA, please create an Oracle account and sign the OCA in Oracle's Contributor Agreement Application. When signing the OCA, please provide your GitHub username. After signing the OCA and getting an OCA approval from Oracle, this PR will be automatically updated. If you are an Oracle employee, please make sure that you are a member of the main Oracle GitHub organization, and your membership in this organization is public. |
|
Thanks a lot @spichen for this big contribution! To be able to merge it, we would need you to sign the CLA. Would it be possible for you to have a look at that? |
There was a problem hiding this comment.
Pull request overview
This pull request introduces a comprehensive TypeScript SDK for the Oracle Open Agent Specification. The SDK provides a strongly-typed, developer-friendly API for defining AI agents, multi-agent systems, workflows, tools, and related components with full serialization/deserialization support.
Changes:
- Complete TypeScript SDK implementation with Zod schemas for validation
- Comprehensive test suite with 30+ test files covering all major features
- Full serialization/deserialization system supporting JSON/YAML with version gating
- 8 detailed examples demonstrating SDK usage patterns
Reviewed changes
Copilot reviewed 135 out of 136 changed files in this pull request and generated 22 comments.
Show a summary per file
| File | Description |
|---|---|
| package.json | Package configuration with dependencies (zod, yaml) and dev tooling |
| tsconfig.json | Strict TypeScript configuration with modern ES2022 target |
| tsup.config.ts | Build configuration for dual CJS/ESM output with type definitions |
| vitest.config.ts | Test configuration with v8 coverage |
| src/component.ts | Base component schemas and type system |
| src/agents/*.ts | Agent types: Agent, Swarm, ManagerWorkers, RemoteAgent, A2AAgent, SpecializedAgent |
| src/tools/*.ts | Tool types: ServerTool, ClientTool, RemoteTool, BuiltinTool, MCPTool, ToolBox |
| src/llms/*.ts | LLM configs: OpenAI, vLLM, Ollama, OCI GenAI |
| src/flows/*.ts | Flow system with nodes, edges, and FlowBuilder |
| src/mcp/*.ts | MCP tool and transport support |
| src/serialization/*.ts | Complete serialization system with plugins, version gating, and sensitive field exclusion |
| src/versioning.ts | Version tracking and comparison utilities |
| src/templating.ts | Template placeholder extraction from strings/objects |
| src/sensitive-field.ts | Security: marks fields for exclusion from serialization |
| tests/**/*.test.ts | Comprehensive test coverage for all components |
| examples/*.ts | 8 working examples demonstrating SDK usage |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Thank you for signing the OCA. |
9865d00 to
24ce2ca
Compare
sonleoracle
left a comment
There was a problem hiding this comment.
This is in mergeable shape for me if we keep the support contract narrow.
I do not want to make this package a broad compatibility gate for every historical fixture in the repo, but I do want one curated repository-fixture round-trip test so we have a stable CI contract for common Agent Spec shapes.
I locally validated a curated set of 61 configs that round-trip successfully with the current SDK when tested in the right mode:
- standalone current-format configs are tested as ordinary one-file round trips
howto_disaggregated_*is tested with the intended two-step API (importOnlyReferencedComponents+componentsRegistry)- the weather/ancestry adapter fixtures are tested from placeholder-resolved copies derived from the repo paths below
Please add a tests/repo-fixtures.test.ts-style test that round-trips these repo configs:
docs/pyagentspec/source/agentspec_config_examples/agentspec_oracle_it_assistant.jsondocs/pyagentspec/source/agentspec_config_examples/agentspec_oracle_it_assistant.yamlpyagentspec/tests/adapters/langgraph/configs/ancestry_agent_with_client_tool.yamldocs/pyagentspec/source/agentspec_config_examples/autogen_to_agentspec.jsondocs/pyagentspec/source/agentspec_config_examples/autogen_to_agentspec.yamldocs/pyagentspec/source/agentspec_config_examples/ext_christmas_greetings_tutorial.jsondocs/pyagentspec/source/agentspec_config_examples/ext_christmas_greetings_tutorial.yamldocs/pyagentspec/source/agentspec_config_examples/ext_code_assistant_tutorial.jsondocs/pyagentspec/source/agentspec_config_examples/ext_code_assistant_tutorial.yamldocs/pyagentspec/source/agentspec_config_examples/ext_ops_assistant_tutorial_agent.jsondocs/pyagentspec/source/agentspec_config_examples/ext_ops_assistant_tutorial_agent.yamldocs/pyagentspec/source/agentspec_config_examples/ext_ops_assistant_tutorial_flow.jsondocs/pyagentspec/source/agentspec_config_examples/ext_ops_assistant_tutorial_flow.yamldocs/pyagentspec/source/agentspec_config_examples/ext_tutorial_cybersecurity_flow.jsondocs/pyagentspec/source/agentspec_config_examples/ext_tutorial_cybersecurity_flow.yamlpyagentspec/tests/adapters/langgraph/configs/haiku_without_a_flow.jsondocs/pyagentspec/source/agentspec_config_examples/howto_ag_ui.jsondocs/pyagentspec/source/agentspec_config_examples/howto_ag_ui.yamldocs/pyagentspec/source/agentspec_config_examples/howto_agent_with_remote_tools.jsondocs/pyagentspec/source/agentspec_config_examples/howto_agent_with_remote_tools.yamldocs/pyagentspec/source/agentspec_config_examples/howto_agents.jsondocs/pyagentspec/source/agentspec_config_examples/howto_agents.yamldocs/pyagentspec/source/agentspec_config_examples/howto_catchexception.jsondocs/pyagentspec/source/agentspec_config_examples/howto_catchexception.yamldocs/pyagentspec/source/agentspec_config_examples/howto_disaggregated_component_config.jsondocs/pyagentspec/source/agentspec_config_examples/howto_disaggregated_component_config.yamldocs/pyagentspec/source/agentspec_config_examples/howto_disaggregated_main_config.jsondocs/pyagentspec/source/agentspec_config_examples/howto_disaggregated_main_config.yamldocs/pyagentspec/source/agentspec_config_examples/howto_flow_with_conditional_branches.jsondocs/pyagentspec/source/agentspec_config_examples/howto_flow_with_conditional_branches.yamldocs/pyagentspec/source/agentspec_config_examples/howto_flowbuilder.jsondocs/pyagentspec/source/agentspec_config_examples/howto_flowbuilder.yamldocs/pyagentspec/source/agentspec_config_examples/howto_managerworkers.jsondocs/pyagentspec/source/agentspec_config_examples/howto_managerworkers.yamldocs/pyagentspec/source/agentspec_config_examples/howto_mapnode.jsondocs/pyagentspec/source/agentspec_config_examples/howto_mapnode.yamldocs/pyagentspec/source/agentspec_config_examples/howto_mcp_agent.jsondocs/pyagentspec/source/agentspec_config_examples/howto_mcp_agent.yamldocs/pyagentspec/source/agentspec_config_examples/howto_mcp_flow.jsondocs/pyagentspec/source/agentspec_config_examples/howto_mcp_flow.yamldocs/pyagentspec/source/agentspec_config_examples/howto_parallelflownode.jsondocs/pyagentspec/source/agentspec_config_examples/howto_parallelflownode.yamldocs/pyagentspec/source/agentspec_config_examples/howto_structured_generation1.jsondocs/pyagentspec/source/agentspec_config_examples/howto_structured_generation1.yamldocs/pyagentspec/source/agentspec_config_examples/howto_structured_generation2.jsondocs/pyagentspec/source/agentspec_config_examples/howto_structured_generation2.yamldocs/pyagentspec/source/agentspec_config_examples/howto_structured_generation3.jsondocs/pyagentspec/source/agentspec_config_examples/howto_structured_generation3.yamldocs/pyagentspec/source/agentspec_config_examples/howto_summarization_transforms.jsondocs/pyagentspec/source/agentspec_config_examples/howto_summary_flow.jsondocs/pyagentspec/source/agentspec_config_examples/howto_summary_flow.yamldocs/pyagentspec/source/agentspec_config_examples/math_homework_agent.jsondocs/pyagentspec/source/agentspec_config_examples/math_homework_agent.yamldocs/pyagentspec/source/agentspec_config_examples/simple_agent_with_rag_tool.jsondocs/pyagentspec/source/agentspec_config_examples/simple_agent_with_rag_tool.yamlpyagentspec/tests/adapters/langgraph/configs/swarm_calculator.yamlpyagentspec/tests/adapters/langgraph/configs/weather_agent_client_tool.yamlpyagentspec/tests/adapters/langgraph/configs/weather_agent_remote_tool.yamlpyagentspec/tests/adapters/langgraph/configs/weather_agent_server_tool.yamlpyagentspec/tests/adapters/langgraph/configs/weather_agent_with_outputs.yamlpyagentspec/tests/adapters/langgraph/configs/weather_ollama_agent.yaml
Notes on that list:
- the
howto_disaggregated_*files should be exercised with the intended two-step API, not as naive single-file fixtures - the weather/ancestry adapter fixtures should be tested from placeholder-resolved copies derived from those repo paths, not from the raw YAML files with
[[...]]placeholders
The broader public-example compatibility follow-ups I would still like to see, but not as merge blockers, are:
docs/pyagentspec/source/agentspec_config_examples/howto_a2aagent.jsondocs/pyagentspec/source/agentspec_config_examples/howto_a2aagent.yamldocs/pyagentspec/source/agentspec_config_examples/howto_swarm.jsondocs/pyagentspec/source/agentspec_config_examples/howto_swarm.yaml
One more thing I would like cleaned up before merge:
npm ciandnpm run buildboth succeed locally, butnpm run buildemits a packaging warning becausepackage.jsondeclaresexports.typesafterimportandrequire, so thattypescondition is never usednpm audit --omit=dev --jsoncurrently reports a direct runtime vulnerability becausepackage-lock.jsonresolvesyamlto2.8.2; there is a fix available in>= 2.8.3
Please:
- bump
yamlto a non-vulnerable version and refresh the lockfile - fix the
exportsordering intsagentspec/package.jsonso thetypescondition is actually effective
These are not functional runtime failures in the current branch, but they are package-quality issues that are better fixed before merge.
Also please briefly document the intended supported surface so we do not imply that every historical/example fixture in this repo is guaranteed to round-trip in TS.
1543f93 to
762b3a1
Compare
…ation
Implements a complete TypeScript SDK providing the same core capabilities
as the Python SDK (pyagentspec) for authoring, validating, and
serializing/deserializing Agent Spec configurations.
Core features:
- All component types: Agent, Swarm, ManagerWorkers, Flow, 14 node types,
4 tool types, 6 LLM config types, edges, datastores, transforms
- Property system with JSON Schema mapping (9 typed property factories)
- Full serialization/deserialization with JSON and YAML support
- $component_ref referencing for shared components
- Template variable extraction from {{placeholder}} syntax
- Plugin architecture for custom component types
- Version-gated field serialization (agentspec_version 25.4.1+)
- camelCase/snake_case field name conversion for Python SDK interop
- FlowBuilder with ergonomic builder pattern API
Technical details:
- Zod schemas + factory functions (no class hierarchies)
- Discriminated unions on componentType for type-safe polymorphism
- Strict TypeScript with zero `any` types in public API
- ESM + CJS dual build via tsup
- 384 tests across 29 test files (vitest)
Signed-off-by: Salah <nh.salah@gmail.com>
|
Internal regression failed: Build ID #405 |
Alright, I've updated the README. |
|
Internal regression succeeded 🍏: Build ID #406 |
We will publish in a more official manner once we have put in place all the required automated checks to ensure that it has the same functionalities as the python one (no divergence in functionalities) as well as passes our internal requirements for security :) . |
|
Internal regression succeeded 🍏: Build ID #407 |
Shape-based detection (isComponent, isSerializedComponent) and recursive $component_ref resolution were applied to all nested objects, including user-controlled payload fields like metadata, data, headers, queryParams, and configuration. Any plain object in those fields that happened to carry id/name/componentType keys was incorrectly treated as a component child during serialization or deserialized as a component. Fix: derive the set of "opaque" fields per component type by introspecting the Zod schema (ZodRecord, ZodUnknown, ZodAny, unwrapping Optional/Default wrappers). During serialization the builtin plugin now sanitizes opaque fields (strip DANGEROUS_KEYS, enforce depth limit) without invoking isComponent or dumpField; the referencing traversal skips opaque fields entirely. During deserialization the builtin plugin preserves opaque field values verbatim (null/undefined omitted so Zod defaults apply). Results are cached per component type so schema introspection runs at most once per type. Adds regression tests covering metadata, ApiNode payload fields (data/headers/queryParams), and BuiltinTool configuration.
datastore on both summarization transforms was typed as z.record(z.unknown()), which accepted arbitrary JSON and caused component-shaped nested values to be traversed (or deserialized as components) instead of being treated as a real component field. Match pyagentspec's SupportedDatastores = InMemoryCollectionDatastore | OracleDatabaseDatastore | PostgresDatabaseDatastore discriminated union so the field is validated and deserialized correctly. Update the "should accept a custom datastore" tests to pass actual datastore instances instead of plain dicts.
|
Hi @spichen |
I merged main branch into this branch. |
|
Internal regression succeeded 🍏: Build ID #419 |
|
Merge Gate failed: Build ID #643 |
|
Merge Gate INPROGRESS |
|
Internal regression succeeded 🍏: Build ID #446 |
|
Merge Gate failed: Build ID #644 |
Resolves #97