Commit graph

667 commits

Author SHA1 Message Date
Renato Byrro
25718bbf77
Slack wrapper toolkit in Python with JSON definitions (#574)
finally!
2025-09-23 13:48:21 -03:00
Evan Tahler
92ae94fd38
skip PRs for pylon sync (#576) 2025-09-22 10:28:55 -07:00
Evan Tahler
2493d892d2
remove line on comment edit with pylon comment (#573) 2025-09-18 20:48:38 -07:00
Evan Tahler
56121820d3
Pylon comment thread (#571) 2025-09-18 18:41:18 -07:00
Evan Tahler
4e6b66cfe0
create pylon issue if not found (#568) 2025-09-18 18:28:04 -07:00
Evan Tahler
768d70ed79
Pylon Issue and Discussion Sync (#564)
We are going to use Pylon for support. This PR syncs all github issues
and discussions to pylon so we can manage them

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-18 17:44:15 -07:00
Eric Gustin
667495c389
Bump CLI's arcadepy dependency (#565) 2025-09-17 16:02:55 -07:00
Ray Smets
c7c485152f
[Mastra] example toolkit project updated (#561)
## Summary

Updated the Mastra example project to include leveraging multiple
toolkits into one Mastra agent. Additionally, the `package.json`
versions were pinned to the latest versions to avoid potential issues
with breaking changes as Mastra progresses through v0.x.x packages.
Also, by pinning the version, it demonstrates the latest confirmed
arcade-js compatibility version.

These changes were initiated when trying to debug an
[issue](https://github.com/ArcadeAI/arcade-ai/issues/560) using Arcade
toolkits with Mastra agents. Notably, I confirmed that there is no flaw
in arcade-js, which was suspected in the issue, by successfully using
the toolkits with the latest Mastra packages.

## Changes

* inboxTravelAgent created showcasing `GoogleFlights`, `GoogleHotels`,
and `Gmail` Arcade toolkits together
* package.json versions pinned to the latest working versions. 

## Testing

Ran the Mastra project locally and invoked the tools via the agent chat
interface.
2025-09-15 13:02:49 -03:00
Evan Tahler
766a262a25
MongoDB analytics toolkit (#548)
Design System: https://github.com/ArcadeAI/Design-System/pull/31
Docs: https://github.com/ArcadeAI/docs/pull/439

<img width="832" height="797" alt="Screenshot 2025-09-11 at 2 35 36 PM"
src="https://github.com/user-attachments/assets/198f194f-d41c-41a0-bedf-b77bccd70dfa"
/>
2025-09-12 18:41:23 -07:00
Eric Gustin
f50e05aa9b
Extra safe error adapters (#556)
Catching and logging all unexpected errors that occur in the error
adapters _**just in case**_
2025-09-10 14:51:18 -07:00
jottakka
9c1b2b9275
[Ready][toolkit/zendesk] Adding WhoAmI tool to zendesk (#544)
Zendesk who_am_i tool.

---------

Co-authored-by: Francisco Liberal <francisco@arcade.dev>
2025-09-10 18:22:09 -03:00
Eric Gustin
f4558ef3a8
Tool Error Handling (#539)
# Improvements to Arcade TDK Error Handling
I tried my very best to not make any breaking changes in this PR. So,
you will notice various "Deprecation" notices throughout.

### Instructions for PR reviewers
1. Pull down this PR's branch
2. Pull down the Engine's tool error handling PR's branch
3. Update your installed arcadepy to have the following:
- In `arcadepy/resources/tools/tools.py`, if you want to test out
including stacktraces, then you need to update `ToolsResource.execute`
to accept a `include_error_stacktrace` argument and also include the
"include_error_stacktrace" argument to the POST to the Engine inside of
the function's execute method's body.
- In `arcadepy/types/execute_tool_response.py` add the following enum
      ```py
      class ErrorKind(str, Enum):
          """Error kind that is comprised of
          - the who (toolkit, tool, upstream)
          - the when (load time, definition parsing time, runtime)
- the what (bad_definition, bad_input, bad_output, retry,
context_required, fatal, etc.)"""
      
          TOOLKIT_LOAD_FAILED = "TOOLKIT_LOAD_FAILED"
TOOL_DEFINITION_BAD_DEFINITION = "TOOL_DEFINITION_BAD_DEFINITION"
TOOL_DEFINITION_BAD_INPUT_SCHEMA = "TOOL_DEFINITION_BAD_INPUT_SCHEMA"
TOOL_DEFINITION_BAD_OUTPUT_SCHEMA = "TOOL_DEFINITION_BAD_OUTPUT_SCHEMA"
          TOOL_RUNTIME_BAD_INPUT_VALUE = "TOOL_RUNTIME_BAD_INPUT_VALUE"
TOOL_RUNTIME_BAD_OUTPUT_VALUE = "TOOL_RUNTIME_BAD_OUTPUT_VALUE"
          TOOL_RUNTIME_RETRY = "TOOL_RUNTIME_RETRY"
TOOL_RUNTIME_CONTEXT_REQUIRED = "TOOL_RUNTIME_CONTEXT_REQUIRED"
          TOOL_RUNTIME_FATAL = "TOOL_RUNTIME_FATAL"
          UPSTREAM_RUNTIME_BAD_REQUEST = "UPSTREAM_RUNTIME_BAD_REQUEST"
          UPSTREAM_RUNTIME_AUTH_ERROR = "UPSTREAM_RUNTIME_AUTH_ERROR"
          UPSTREAM_RUNTIME_NOT_FOUND = "UPSTREAM_RUNTIME_NOT_FOUND"
UPSTREAM_RUNTIME_VALIDATION_ERROR = "UPSTREAM_RUNTIME_VALIDATION_ERROR"
          UPSTREAM_RUNTIME_RATE_LIMIT = "UPSTREAM_RUNTIME_RATE_LIMIT"
UPSTREAM_RUNTIME_SERVER_ERROR = "UPSTREAM_RUNTIME_SERVER_ERROR"
          UPSTREAM_RUNTIME_UNMAPPED = "UPSTREAM_RUNTIME_UNMAPPED"
          UNKNOWN = "UNKNOWN"
      ```
- In `arcadepy/types/execute_tool_response.py` add the following fields
to OutputError:
      ```py
      kind: ErrorKind
      status_code: Optional[int] = None
      stacktrace: Optional[str] = None
      extra: Optional[dict[str, Any]] = None
      ```
### Example Client Usage
```py
# Example of handling an upstream rate limit
error = response.output.error
if  error and error.kind == ErrorKind.UPSTREAM_RUNTIME_RATE_LIMIT:
    sleep_time = error.retry_after_ms / 1000
    time.sleep(sleep_time)
    # and then execute again
```
```py
# Examples of determining what type of runtime error it is
error = response.output.error
if error:
    is_retryable_error = error.kind == ErrorKind.TOOL_RUNTIME_RETRY
    is_a_bug_in_the_tool = error.kind == ErrorKind.TOOL_RUNTIME_FATAL
    is_additional_context_required = error.kind == ErrorKind.TOOL_RUNTIME_CONTEXT_REQUIRED
```

### Example Tool Usage
```py
# EXAMPLE 1 letting Arcade handle upstream error handling for you
reddit_client.post(params) # Arcade's httpx adapter will handle error handling for you!

# ------------------------------------

# EXAMPLE 2 handling upstream bad request yourself, but letting Arcade handle the rest
try:
    reddit_client.post(params)
except httpx.HTTPStatusError as e:
    if e.status_code == 400:
        raise UpstreamError("My extra custom message) from e
    raise
```
```py
# EXAMPLE 1 letting Arcade handle it for you
risky_element = my_risky_list[42] # Arcade will raise a FatalToolError for you

# ------------------------------------

# EXAMPLE 2 handling it yourself for extra flexibility
try:
    risky_element = my_risky_list[42]
except IndexError as e:
    raise FatalToolError("My extra custom message") from e
```
### Non-runtime Error Message Examples
Example ToolkitLoadError Messages:
```
- [TOOLKIT_LOAD_FAILED] ToolkitLoadError when loading toolkit 'sample_tool': Could not import module mock_module. Reason: Mock import error
- [TOOLKIT_LOAD_FAILED] ToolkitLoadError when loading toolkit 'test_toolkit': Tool 'ValidTool' in toolkit 'test_toolkit' already exists in the catalog.
```
Example ToolDefinitionError Messages
```
- [TOOL_DEFINITION_BAD_DEFINITION] ToolDefinitionError in definition of tool 'tool_missing_description': Tool 'tool_missing_description' is missing a description
- [TOOL_DEFINITION_BAD_DEFINITION] ToolDefinitionError in definition of tool 'tool_with_invalid_secret_type': Secret keys must be strings (error in tool ToolWithInvalidSecretType).
- [TOOL_DEFINITION_BAD_DEFINITION] ToolDefinitionError in definition of tool 'tool_with_empty_secret': Secrets must have a non-empty key (error in tool ToolWithEmptySecret).
- [TOOL_DEFINITION_BAD_DEFINITION] ToolDefinitionError in definition of tool 'tool_with_invalid_metadata_type': Metadata must be strings (error in tool ToolWithInvalidMetadataType).
- [TOOL_DEFINITION_BAD_DEFINITION] ToolDefinitionError in definition of tool 'tool_with_metadata_requiring_auth_without_auth': Tool ToolWithMetadataRequiringAuthWithoutAuth declares metadata key 'client_id', which requires that the tool has an auth requirement, but no auth requirement was provided. Please specify an auth requirement.
- [TOOL_DEFINITION_BAD_DEFINITION] ToolDefinitionError in definition of tool 'tool_with_empty_metadata': Metadata must have a non-empty key (error in tool ToolWithEmptyMetadata).
- [TOOL_DEFINITION_BAD_DEFINITION] ToolDefinitionError in definition of tool 'tool_with_unsupported_param_type': Unsupported parameter type: <class 'test_catalog.MyFancyTestClass'>
```
Example ToolInputSchemaError Messages
```
- [TOOL_DEFINITION_BAD_INPUT_SCHEMA] ToolInputSchemaError in definition of tool 'tool_with_missing_input_parameter_annotation': Parameter 'input_text' is missing a description
- [TOOL_DEFINITION_BAD_INPUT_SCHEMA] ToolInputSchemaError in definition of tool 'tool_with_no_type_annotation': Parameter param has no type annotation.
- [TOOL_DEFINITION_BAD_INPUT_SCHEMA] ToolInputSchemaError in definition of tool 'tool_with_invalid_param_name': Invalid parameter name: '123invalid' is not a valid identifier. Identifiers must start with a letter or underscore, and can only contain letters, digits, or underscores.
- [TOOL_DEFINITION_BAD_INPUT_SCHEMA] ToolInputSchemaError in definition of tool 'tool_with_too_many_annotations': Parameter param: Annotated[str, 'name', 'desc', 'extra'] has too many string annotations. Expected 0, 1, or 2, got 3.
- [TOOL_DEFINITION_BAD_INPUT_SCHEMA] ToolInputSchemaError in definition of tool 'tool_with_required_union_param': Parameter param is a union type. Only optional types are supported.
- [TOOL_DEFINITION_BAD_INPUT_SCHEMA] ToolInputSchemaError in definition of tool 'tool_with_non_callable_default_factory': Default factory for parameter param: Annotated[str, 'Parameter'] = FieldInfo(annotation=NoneType, required=False, default_factory=str) is not callable.
- [TOOL_DEFINITION_BAD_INPUT_SCHEMA] ToolInputSchemaError in definition of tool 'tool_with_multiple_tool_contexts': Only one ToolContext parameter is supported, but tool tool_with_multiple_tool_contexts has multiple.
```
Example ToolOutputSchemaError Messages
```
- [TOOL_DEFINITION_BAD_OUTPUT_SCHEMA] ToolOutputSchemaError in definition of tool 'tool_missing_return_type_hint': Tool 'ToolMissingReturnTypeHint' must have a return type
- [TOOL_DEFINITION_BAD_OUTPUT_SCHEMA] ToolOutputSchemaError in definition of tool 'tool_with_unsupported_output_type': Unsupported output type '<class 'test_catalog.MyFancyTestClass'>'. Only built-in Python types, TypedDicts, Pydantic models, and standard collections are supported as tool output types.
```
### Runtime Error Message Examples
Example Tool Runtime Error Messages
```
- [TOOL_RUNTIME_FATAL] FatalToolError during execution of tool 'get_posts_in_subreddit': list index out of range
- [TOOL_RUNTIME_CONTEXT_REQUIRED] ContextRequiredToolError during execution of tool 'get_posts_in_subreddit': Ambiguous username. Please provide a more specific username
- [TOOL_RUNTIME_RETRY] RetryableToolError during execution of tool 'get_posts_in_subreddit': Retry with subreddit=learnpython or subreddit=learnprogramming
```

Example Upstream Runtime Error Messages
```
- [UPSTREAM_RUNTIME_RATE_LIMIT] UpstreamRateLimitError during execution of tool 'get_posts_in_subreddit': 429 Client Error: Too Many Requests
- [UPSTREAM_RUNTIME_BAD_REQUEST] UpstreamError during execution of tool 'get_posts_in_subreddit': 400 Client Error: Bad request. Missing 'id' parameter.
- [UPSTREAM_RUNTIME_BAD_REQUEST] UpstreamError during execution of tool 'search_files': Upstream Google API error: Invalid value '-23'. Values must be within the range: [value: 1\n, value: 1000\n]
```
2025-09-10 10:45:18 -07:00
Mateo Torres
a97450b3af
Mateo/lchainversion (#551) 2025-09-08 18:29:32 -03:00
Mateo Torres
a06b00ccc1
bump langchain arcade version (#550) 2025-09-08 16:49:19 -03:00
Mateo Torres
639f726b30
Mateo/lchain (#549)
The latest change to langchain-arcade was blocked becuase it still
relied on poetry, I moved that to uv
2025-09-08 13:55:06 -03:00
Mateo Torres
c481f1d677
upgraded langchain_arcade (#546)
This bumps the requirement version of the Arcade client to the latest
version (which supports the new function for the custom user verifier)
It also moves the tests to be compatible to our new tool names
2025-09-05 18:13:56 -03:00
Sam Partee
e188fc6ae9
Improve Typedict and Basemodel support (#523)
Improve Pydantic and Typedict support and add a bunch of tets.

1. Fixed the test failure where TypeDict was being serialized as a list
of tuples instead of a dict by:
- Adding proper handling for BaseModel instances in the output.py file
- Converting BaseModel results (from TypeDict conversion) to dicts using
model_dump()
    - Handling lists containing BaseModel objects
2. Fixed None handling to ensure None results are converted to empty
strings as expected
3. Updated the schema.py to allow dict and list types in
ToolCallOutput.value
  4. new tests
    - TypeDict output execution tests
    - Output factory tests
    - Executor tests with TypeDict support
    - Schema validation tests

  The key changes were:
- In ``arcade_core/output.py``: Added BaseModel conversion logic in the
success method
- In ``arcade_core/schema.py``: Changed ToolCallOutput.value type from
list[str] to list to support complex types


TODO
- [ ] Confirm engine compatibility without changes made to engine

---------

Co-authored-by: Eric Gustin <eric@arcade.dev>
2025-08-27 16:50:09 -07:00
Mateo Torres
e0ddc0ce90
added missing parameter to the usage example templates (#537)
Example templates were missing the `user_id` param, this was caught by
@evantahler, thanks!
2025-08-27 19:57:52 -03:00
Sergio Serrano
3c4c856842
Fix vulnerability (#536) 2025-08-19 14:47:24 -03:00
jottakka
b0c77a04e6
[PROD-186][ClickUp ToolKit][Auth] Update auth modules for ClickUp auth integration (#526)
[https://app.clickup.com/t/9014390315/PROD-186](PROD-186)

Small update for auth modules for ClickUp integration.

---------

Co-authored-by: Francisco Liberal <francisco@arcade.dev>
2025-08-13 14:39:01 -03:00
Renato Byrro
19c1e18a8a
arcade docs: add support for GPT-5 series; improve error handling (#529)
Adds support for GPT-5 series of models in `arcade docs`.

Improves error handling when the LLM does not generate a valid JSON for
a given tool sample inputs. Instead of raising an exception, the CLI
uses an empty input, moves on to the next tool, and prints a warning
message asking the user the fill in the input sample manually in
Javascript and Python files.

This PR also moves the Enumerations from a separate `reference.mdx` file
to the main toolkit file, as requested by @EricGustin to simplify the
docs structure.
2025-08-10 18:14:59 -05:00
Evan Tahler
a85fa76997
Clickhouse Toolkit (#527)
Generated from the postgres toolkit
2025-08-05 14:05:09 -07:00
Sterling Dreyer
7888dc505e
Fix venv files not being found (#525) 2025-08-01 12:12:35 -07:00
Renato Byrro
21f892c0a0
A couple of fixes for the docs generator (#524)
Display "This tool does not take any parameters." when the tool
interface has no arguments other than context.

Prevent the same Enum from being referenced multiple times in the
reference.mdx file.
2025-08-01 11:42:14 -03:00
Mateo Torres
02a0900846
optional github link in docs generation (#522)
This removes the github link to the toolkit code from the template
2025-07-29 14:51:34 -03:00
Eric Gustin
288ff61959
Update arcade new (#520)
This PR updates the `arcade new` CLI command.
* adds support for official arcade tools. 
* removes local libs sources for toolkits that are not a community or
official
* Stopped creating README for community toolkits
2025-07-29 10:35:36 -07:00
Sterling Dreyer
c97f2f7500
Bump CLI version (#521) 2025-07-28 16:22:05 -07:00
Sterling Dreyer
3f5c7aa6ba
Error on invalid toolkit file (#510)
Changes toolkit loading and deployments to error if there are syntax
errors in the file
2025-07-28 16:17:06 -07:00
Renato Byrro
ba8c3d3197
Rename auto-docs command to simply 'docs' and some other small improvements (#518)
Renames the `arcade generate-toolkit-docs` command to `arcade docs`. The
`arcade generate-toolkit-docs` command is preserved for backwards
compatibility, but it's now hidden.

Also some minor improvements to CLI help strings and better error
handling. Better error description when the toolkit is not installed
locally (also now mentioning this requirement in the command help).
2025-07-28 15:46:58 -03:00
Eric Gustin
7f26b83c19
Update examples (#516)
Update code examples to not use the deprecated Google toolkit (use Gmail
instead) and Web toolkit (use Firecrawl instead)
2025-07-28 09:49:00 -07:00
Eric Gustin
ca11ec9fa3
Add toolkits (#514)
Add Linkedin, Zendesk, Math, and Postgres toolkits
2025-07-25 15:44:06 -07:00
Sterling Dreyer
54da08f873
Disable Deployments (#513) 2025-07-24 16:51:53 -07:00
Eric Gustin
b50726d044
Remove Toolkits (#512)
As of today, Arcade's toolkits are moving to closed-source.  

Toolkit source code remains available upon request for our paying
customers. The history of this repository contains the toolkits as of
their most recent publication under their previous license terms.
2025-07-24 16:45:24 -07:00
Sam Partee
27a6cd31a3
Support Tool Output in ValueSchema of ToolDefinition (#487)
## Before

### Tool: ``GoogleNews.SearchNewsStories``

```python
@tool(requires_secrets=["SERP_API_KEY"])
async def search_news_stories(
    context: ToolContext,
    keywords: Annotated[
        str,
        "Keywords to search for news articles. E.g. 'Apple launches new iPhone'.",
    ],
    country_code: Annotated[
        CountryCode | None,
        "2-character country code to search for news articles. "
        "E.g. 'us' (United States). "
        f"Defaults to '{DEFAULT_GOOGLE_NEWS_COUNTRY}'.",
    ] = None,
    language_code: Annotated[
        LanguageCode,
        "2-character language code to search for news articles. E.g. 'en' (English). "
        f"Defaults to '{DEFAULT_GOOGLE_NEWS_LANGUAGE}'.",
    ] = DEFAULT_GOOGLE_NEWS_LANGUAGE,
    limit: Annotated[
        int | None,
        "Maximum number of news articles to return. Defaults to None "
        "(returns all results found by the API).",
    ] = None,
) -> Annotated[dict[str, Any]]:
    """Search for news articles related to a given query."""
    ...
```


### Tool Definition: ``GoogleNews.SearchNewsStories``
```
  {
    "name": "SearchNewsStories",
    "fully_qualified_name": "GoogleNews.SearchNewsStories",
    "description": "Search for news articles related to a given query.",
    "toolkit": {
      "name": "GoogleNews",
      "description": "Arcade.dev LLM tools for getting new via Google News",
      "version": "2.0.0"
    },
    "input": {
      "parameters": [
        {
          "name": "keywords",
          "required": true,
          "description": "Keywords to search for news articles. E.g. 'Apple launches new iPhone'.",
          "value_schema": {
            "val_type": "string",
            "inner_val_type": null,
            "enum": null,
          },
          "inferrable": true
        },
        {
          "name": "country_code",
          "required": false,
          "description": "2-character country code to search for news articles. E.g. 'us' (United States). Defaults to 'None'.",
          "value_schema": {
            "val_type": "string",
            "inner_val_type": null,
            "enum": null,
          },
          "inferrable": true
        },
        {
          "name": "language_code",
          "required": false,
          "description": "2-character language code to search for news articles. E.g. 'en' (English). Defaults to 'en'.",
          "value_schema": {
            "val_type": "string",
            "inner_val_type": null,
            "enum": null,
          },
          "inferrable": true
        },
        {
          "name": "limit",
          "required": false,
          "description": "Maximum number of news articles to return. Defaults to None (returns all results found by the API).",
          "value_schema": {
            "val_type": "integer",
            "inner_val_type": null,
            "enum": null,

          },
          "inferrable": true
        }
      ]
    },
    "output": {
      "description": "News search results with article details.",
      "available_modes": [
        "value",
        "error"
      ],
      "value_schema": {
        "val_type": "json"
      }
    },
    "requirements": {
      "authorization": null,
      "secrets": [
        {
          "key": "serp_api_key"
        }
      ],
      "metadata": null
    },
    "deprecation_message": null
  },
```

## After

### Enhanced Tool: ``GoogleNews.SearchNewsStories``

```python

"""Type definitions for Google News API responses and parameters."""

from typing_extensions import TypedDict

CountryCode = str
LanguageCode = str


class SearchNewsParams(TypedDict):
    """Input parameters for searching news articles."""

    keywords: str
    """Search query terms to find relevant news articles \
    (e.g., 'Apple launches new iPhone')."""

    country_code: CountryCode | None
    """Optional 2-letter country code to filter news by region \
    (e.g., 'us' for United States, 'uk' for United Kingdom)."""

    language_code: LanguageCode | None
    """Optional 2-letter language code to filter news by language \
    (e.g., 'en' for English, 'es' for Spanish)."""

    limit: int | None
    """Optional maximum number of news articles to return. \
    If not specified, returns all results from the API."""


class SourceInfo(TypedDict, total=False):
    """Information about the news source/publication."""

    name: str
    """Name of the publication (e.g., 'CNN', 'BBC News', 'The New York Times')."""

    icon: str
    """URL to the source's favicon or logo image."""

    authors: list[str]
    """List of author names for the article, if available."""


class NewsResult(TypedDict, total=False):
    """Individual news article from the Google News API response."""

    position: int
    """Ranking position of this result in the search results."""

    title: str
    """Headline or title of the news article."""

    link: str
    """Full URL to the original news article."""

    source: SourceInfo
    """Information about the publication source."""

    date: str
    """Publication date and time (e.g., '2 hours ago', 'Dec 15, 2023')."""

    snippet: str
    """Brief excerpt or summary from the article content."""

    thumbnail: str
    """URL to a high-resolution thumbnail image for the article."""

    thumbnail_small: str
    """URL to a low-resolution thumbnail image for the article."""

    story_token: str
    """Token for accessing full coverage of this news story across multiple sources."""

    stories: list["NewsResult"]
    """Related news stories from other sources covering the same topic."""

    highlight: dict
    """Additional highlighted information about the story."""


class SearchMetadata(TypedDict, total=False):
    """Metadata about the search request and processing."""

    id: str
    """Unique identifier for this search request within SerpApi."""

    status: str
    """Current processing status ('Processing', 'Success', or 'Error')."""

    json_endpoint: str
    """URL to retrieve the JSON results for this search."""

    created_at: str
    """Timestamp when the search request was created."""

    processed_at: str
    """Timestamp when the search request was processed."""

    google_news_url: str
    """Original Google News URL that would return these results."""

    total_time_taken: float
    """Total time in seconds taken to process this search."""


class SearchParameters(TypedDict, total=False):
    """Parameters used for the search request."""

    engine: str
    """Search engine used (always 'google_news' for this API)."""

    q: str
    """Search query string."""

    gl: str
    """Country code used for geographic filtering."""

    hl: str
    """Language code used for language filtering."""

    topic_token: str
    """Token for accessing specific news topics (e.g., 'World', 'Business', 'Technology')."""

    publication_token: str
    """Token for accessing news from specific publishers."""


class MenuLink(TypedDict):
    """Navigation link for news categories or topics."""

    title: str
    """Display text for the menu item (e.g., 'Technology', 'Sports', 'Business')."""

    topic_token: str
    """Token to access this specific topic or category."""

    serpapi_link: str
    """SerpApi URL to search within this topic."""


class TopStoriesLink(TypedDict):
    """Link to top stories section."""

    topic_token: str
    """Token to access top stories."""

    serpapi_link: str
    """SerpApi URL to retrieve top stories."""


class GoogleNewsResponse(TypedDict, total=False):
    """Complete response from the Google News API."""

    search_metadata: SearchMetadata
    """Metadata about the search request and processing."""

    search_parameters: SearchParameters
    """Parameters that were used for this search."""

    news_results: list[NewsResult]
    """List of news articles matching the search criteria."""

    menu_links: list[MenuLink]
    """Navigation links to different news categories and topics."""

    top_stories_link: TopStoriesLink
    """Link to access top stories."""

    title: str
    """Title of the page or topic being displayed."""


class SimplifiedNewsResult(TypedDict):
    """Simplified news article format for tool output."""

    title: str
    """Headline of the news article."""

    link: str
    """URL to the full article."""

    source: str | None
    """Name of the publication source."""

    date: str | None
    """When the article was published."""

    snippet: str | None
    """Brief excerpt from the article."""


class SearchNewsOutput(TypedDict):
    """Output format for the search_news_stories tool."""

    news_results: list[SimplifiedNewsResult]
    """List of news articles in simplified format."""

@tool(requires_secrets=["SERP_API_KEY"])
async def search_news_stories(
    context: ToolContext,
    keywords: Annotated[
        str,
        "Keywords to search for news articles. E.g. 'Apple launches new iPhone'.",
    ],
    country_code: Annotated[
        CountryCode | None,
        "2-character country code to search for news articles. "
        "E.g. 'us' (United States). "
        f"Defaults to '{DEFAULT_GOOGLE_NEWS_COUNTRY}'.",
    ] = None,
    language_code: Annotated[
        LanguageCode,
        "2-character language code to search for news articles. E.g. 'en' (English). "
        f"Defaults to '{DEFAULT_GOOGLE_NEWS_LANGUAGE}'.",
    ] = DEFAULT_GOOGLE_NEWS_LANGUAGE,
    limit: Annotated[
        int | None,
        "Maximum number of news articles to return. Defaults to None "
        "(returns all results found by the API).",
    ] = None,
) -> Annotated[SearchNewsOutput, "News search results with article details."]:
    """Search for news articles related to a given query."""
    ...

```

### Enhanced Tool Definition: ``GoogleNews.SearchNewsStories`` 

```json

  {
    "name": "SearchNewsStories",
    "fully_qualified_name": "GoogleNews.SearchNewsStories",
    "description": "Search for news articles related to a given query.",
    "toolkit": {
      "name": "GoogleNews",
      "description": "Arcade.dev LLM tools for getting new via Google News",
      "version": "2.0.0"
    },
    "input": {
      "parameters": [
        {
          "name": "keywords",
          "required": true,
          "description": "Keywords to search for news articles. E.g. 'Apple launches new iPhone'.",
          "value_schema": {
            "val_type": "string",
            "inner_val_type": null,
            "enum": null,
            "properties": null,
            "inner_properties": null,
            "description": null
          },
          "inferrable": true
        },
        {
          "name": "country_code",
          "required": false,
          "description": "2-character country code to search for news articles. E.g. 'us' (United States). Defaults to 'None'.",
          "value_schema": {
            "val_type": "string",
            "inner_val_type": null,
            "enum": null,
            "properties": null,
            "inner_properties": null,
            "description": null
          },
          "inferrable": true
        },
        {
          "name": "language_code",
          "required": false,
          "description": "2-character language code to search for news articles. E.g. 'en' (English). Defaults to 'en'.",
          "value_schema": {
            "val_type": "string",
            "inner_val_type": null,
            "enum": null,
            "properties": null,
            "inner_properties": null,
            "description": null
          },
          "inferrable": true
        },
        {
          "name": "limit",
          "required": false,
          "description": "Maximum number of news articles to return. Defaults to None (returns all results found by the API).",
          "value_schema": {
            "val_type": "integer",
            "inner_val_type": null,
            "enum": null,
            "properties": null,
            "inner_properties": null,
            "description": null
          },
          "inferrable": true
        }
      ]
    },
    "output": {
      "description": "News search results with article details.",
      "available_modes": [
        "value",
        "error"
      ],
      "value_schema": {
        "val_type": "json",
        "inner_val_type": null,
        "enum": null,
        "properties": {
          "news_results": {
            "val_type": "array",
            "inner_val_type": "json",
            "enum": null,
            "properties": null,
            "inner_properties": {
              "title": {
                "val_type": "string",
                "inner_val_type": null,
                "enum": null,
                "properties": null,
                "inner_properties": null,
                "description": "Headline of the news article."
              },
              "link": {
                "val_type": "string",
                "inner_val_type": null,
                "enum": null,
                "properties": null,
                "inner_properties": null,
                "description": "URL to the full article."
              },
              "source": {
                "val_type": "string",
                "inner_val_type": null,
                "enum": null,
                "properties": null,
                "inner_properties": null,
                "description": "Name of the publication source."
              },
              "date": {
                "val_type": "string",
                "inner_val_type": null,
                "enum": null,
                "properties": null,
                "inner_properties": null,
                "description": "When the article was published."
              },
              "snippet": {
                "val_type": "string",
                "inner_val_type": null,
                "enum": null,
                "properties": null,
                "inner_properties": null,
                "description": "Brief excerpt from the article."
              }
            },
            "description": "List of news articles in simplified format."
          }
        },
        "inner_properties": null,
        "description": null
      }
    },
    "requirements": {
      "authorization": null,
      "secrets": [
        {
          "key": "serp_api_key"
        }
      ],
      "metadata": null
    },
    "deprecation_message": null
  },

```

---------

Co-authored-by: Eric Gustin <eric@arcade.dev>
2025-07-24 15:32:35 -07:00
Evan Tahler
4144a42392
Make the postgres toolikit better (#509)
Per the discussions in the [blog
post](https://docs.google.com/document/d/1wZi1yKWKOyg1dpueA2eBvTtYlUjqqp7e_M1nuAoF8NY/edit?tab=t.0),
let's update the postgres toolkit!

<img width="2141" height="1364" alt="Screenshot 2025-07-22 at 5 28
06 PM"
src="https://github.com/user-attachments/assets/1b6a5e0a-9429-4c16-9a0c-ac36ea520bea"
/>
2025-07-23 15:28:57 -07:00
Renato Byrro
30739dc44a
Support for multiple Atlassian Clouds in the Jira Toolkit (#506)
Adds `Jira.GetAvailableAtlassianClouds` tool, which provides a list of
clouds available (checking which Clouds were actually authorized by the
current auth token).

Refactors the interface of every tool to accept an `atlassian_cloud_id`
argument (when not provided, try to get a unique cloud ID - if multiple
are available, raises a Retryable error with the list of Clouds
available instructing to select one).

Gets rid of all caching. Now storing the global semaphore to the context
object. The global semaphore is important because some tools depend on
others, and each tool instantiates its own Jira HTTP client. Storing the
semaphore in the context object ensures that all HTTP clients will
respect the concurrency limit.

Removes from tool responses the Atlassian URLs linking to objects in the
Jira GUI (users, projects, issues, etc. We do not keep track of the
cloud name anymore, which is required to build the objects' URLs.

Extends/refactors unit tests accordingly.

Evals checking LLM behavior when:

- a cloud ID is explicitly mentioned in the prompt;
- no cloud ID is mentioned;
- a "multiple clouds available" error is raised and the user is prompted
to pick one;
- user request triggers another tool call after having previously picked
a cloud ID (in the same chat context);
2025-07-23 18:09:54 -03:00
Sterling Dreyer
903340bb0c
Fix setuptools install (#508) 2025-07-22 17:38:40 -07:00
Sterling Dreyer
a4468d4426
Update setuptools (#507) 2025-07-22 15:03:48 -07:00
Sterling Dreyer
f4480c3945
Fix arcade worker list endpoints (#504)
We weren't checking that the engine version of the worker was the same
as the cloud version that we were comparing against and incorrectly
saying the URL was wrong

Before
<img width="1447" height="340" alt="Screenshot 2025-07-21 at 1 55 13 PM"
src="https://github.com/user-attachments/assets/cf39ce9f-0c86-45fd-a68e-c92369876292"
/>

After
<img width="1454" height="308" alt="Screenshot 2025-07-21 at 1 55 07 PM"
src="https://github.com/user-attachments/assets/efcfe6c8-b892-45f7-bf4c-71edc66c8325"
/>
2025-07-21 14:43:58 -07:00
Eric Gustin
4598e1e4d4
Updates to Notion toolkit (#476)
### Adds one new tool to the Notion toolkit
* **AppendContentToEndOfPage**: Append markdown content to the end of a
Notion page by its ID or title

### Fixes a bug
* The **CreatePage** would previously fail if the content provided was
broken into more than 100 blocks. I added 'chunking' logic to support >
100 blocks.
2025-07-18 17:35:12 -07:00
Mateo Torres
173cc6994e
bugfix: URL expansion in Twitter (#500)
This solves an edge case where the `"url"` entity does not have an
`"expanded_url"` case when expanding. The behavior for now is simply
don't replace the URL as it seems the display_url is NOT what we want to
keep as it's normally abbreviated

---------

Co-authored-by: Eric Gustin <34000337+EricGustin@users.noreply.github.com>
2025-07-18 18:20:06 -03:00
Shub
0b1f513826
Add Simplified Linear Toolkit (#465)
This PR adds a simplified Linear toolkit focused on core functionality:

## What's Included

**Tools:**
- `get_issue` - Get detailed information about Linear issues
- `get_teams` - Get team information and details

**Models:**
- `DateRange` enum with comprehensive date range support (TODAY,
YESTERDAY, THIS_WEEK, LAST_WEEK, THIS_MONTH, LAST_MONTH, THIS_YEAR,
LAST_YEAR, LAST_7_DAYS, LAST_30_DAYS)
- Timezone-aware datetime handling following Google toolkit patterns

## What's Simplified

This toolkit has been streamlined by removing:
- Cycles management tools
- Projects management tools  
- Users management tools
- Workflows management tools
- Corresponding tests and evaluations for removed features

## Quality Assurance

- All linting and formatting checks pass
- Comprehensive test coverage for included functionality
- Follows established patterns from Google toolkit

---------

Co-authored-by: Eric Gustin <34000337+EricGustin@users.noreply.github.com>
2025-07-18 14:08:58 -07:00
Eric Gustin
cb7b386a43
Add Linear as wellknown provider (#494)
Blocked by Engine PR
2025-07-18 13:44:26 -07:00
Renato Byrro
d5ae347801
Toolkit docs generator command for Arcade CLI (#414) 2025-07-18 11:22:21 -03:00
Lucas Petralli
1843e411f3
Add Zendesk Toolkit (#458)
This PR adds a new toolkit for integrating with Zendesk Help Center and
ticketing system.

  Features

- Search Articles: Search Help Center knowledge base with filters for
text, categories, labels, and dates
  - List Tickets: Retrieve all open support tickets
- Get Comments: Retrieve all comments for a specific ticket to
understand the context
  - Add Comments: Add public or internal comments to existing tickets
- Solve Tickets: Mark tickets as solved with optional internal
resolution comments

  Testing & Quality
  - Comprehensive test suite 
  - Evaluation scripts for real-world testing
  - All tests passing (make test)
  - Code quality checks passing (make check)
  - All evals passing

---------

Co-authored-by: “lgesuellip” <“lgesuellipinto@uade.edu.ar”>
Co-authored-by: lgesuellip <102637283+lgesuellip@users.noreply.github.com>
Co-authored-by: “lgesuellip” <lgesuellipinto@uade.edu.ar>
2025-07-17 13:34:26 -07:00
Evan Tahler
e1cf58fe1b
skip tests with GHA secrets on forks (#496) 2025-07-17 10:27:24 -07:00
Evan Tahler
b81bb86dfb
Skip tests that require secrets in forks (#495)
We know that forks won't have our secrets, so we separate those toolkits
out to new a new test group and skip them if you aren't in this main
repo. We know if a test suite has a secret via a magic comment

---------

Co-authored-by: Eric Gustin <34000337+EricGustin@users.noreply.github.com>
2025-07-16 16:53:26 -07:00
Eric Gustin
856606f38c
Remove arcade_ prefix requirement and add entry point toolkit discovery (#485)
## Summary
This PR removes the requirement that all toolkits must have the arcade_
prefix and introduces a more flexible toolkit discovery system using
Python entry points.

### 🏷️ Flexible Toolkit Naming
* Community toolkits: Only add arcade_ prefix when the user is in
arcade-ai/toolkits/ directory and explicitly chooses to create a
community contribution.
* External toolkits: No prefix requirement - developers can name their
toolkits however they want
* Toolkit names are now determined by user choice rather than enforced
automatically
### 🔍 Entry Point Discovery
* Added find_arcade_toolkits_from_entrypoints() method to discover
toolkits via entry points
* Entry point group: arcade_toolkits with name: toolkit_name
* Updated pyproject.toml template to include entry point configuration
* Entry point discovery takes precedence over prefix-based discovery for
deduplication
### 📦 Backward Compatibility
* Existing arcade_* prefixed toolkits continue to work via
find_arcade_toolkits_from_prefix()
find_all_arcade_toolkits() now combines both discovery methods
* Deduplication logic prefers entry point toolkits over prefix-based
ones when package names match
### 🛠️ `arcade new` Template Updates
* pyproject.toml template for `arcade new` now includes entry point
configuration: [project.entry-points.arcade_toolkits]
### 🔧 Minor Improvements
* Refactored _strip_arcade_prefix() into a separate method for
reusability
* Updated variable naming for clarity (community_toolkit →
is_community_toolkit)
### Benefits
* Developer Freedom: Toolkit developers are no longer forced to use the
arcade_ prefix. They are also no longer forced to use the package name
as the toolkit name.
* Cleaner Naming: External toolkits can use more natural names (e.g.,
my_company_toolkit instead of arcade_my_company_toolkit)
* Better Discovery: Entry points provide a more standard Python
mechanism for plugin discovery
* Flexible Distribution: Toolkits can be distributed with any package
name while still being discoverable
### Testing
* Added comprehensive tests for the new entry point functionality
* Tests cover edge cases like deduplication, error handling, and
backward compatibility
### Version Bumps
arcade-core: 2.0.0 → 2.1.0
arcade-ai: 2.0.5 → 2.1.0

This change makes the Arcade toolkit ecosystem more flexible and
developer-friendly while maintaining full backward compatibility with
existing toolkits.

---------

Co-authored-by: Mateo Torres <mateo@arcade.dev>
2025-07-16 09:51:21 -07:00
Sterling Dreyer
32292d4b39
Fix login callback (#489) 2025-07-15 11:21:33 -07:00
Renato Byrro
3f6c7a5595
Fix bug in Slack user processing (#488) 2025-07-15 14:52:52 -03:00