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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .github/workflows/dify-cloud.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Dify cloud plugin

on:
pull_request:
paths:
- "dify_cloud/**"
- ".github/workflows/dify-cloud.yml"
push:
branches:
- main
paths:
- "dify_cloud/**"
- ".github/workflows/dify-cloud.yml"

permissions:
contents: read

concurrency:
group: dify-cloud-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
verify:
name: Verify source and package
runs-on: ubuntu-24.04
timeout-minutes: 15

steps:
- name: Check out source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"

- name: Install uv
run: python -m pip install --disable-pip-version-check uv==0.11.32

- name: Install locked dependencies
working-directory: dify_cloud
run: uv sync --frozen

- name: Lint
working-directory: dify_cloud
run: uv run --frozen ruff check .

- name: Test
working-directory: dify_cloud
run: uv run --frozen pytest

- name: Package with the official Dify CLI
working-directory: dify_cloud
env:
DIFY_CLI_SHA256: 0cef74bcae375a4337c2ff7d42e4787717981a795e1c23cf56bb27ec07ec8304 # pragma: allowlist secret
run: |
curl --fail --location --proto '=https' --tlsv1.2 \
--output "$RUNNER_TEMP/dify-plugin" \
https://github.com/langgenius/dify-plugin-daemon/releases/download/0.6.10/dify-plugin-linux-amd64
echo "$DIFY_CLI_SHA256 $RUNNER_TEMP/dify-plugin" | sha256sum --check --strict
chmod 755 "$RUNNER_TEMP/dify-plugin"
"$RUNNER_TEMP/dify-plugin" plugin package . \
--output_path "$RUNNER_TEMP/everos-cloud.difypkg"
unzip -Z1 "$RUNNER_TEMP/everos-cloud.difypkg"
uv export --frozen --format requirements.txt --no-group dev \
--no-emit-project --no-hashes --no-header --no-annotate \
> "$RUNNER_TEMP/expected-requirements.txt"
unzip -p "$RUNNER_TEMP/everos-cloud.difypkg" requirements.txt \
> "$RUNNER_TEMP/packaged-requirements.txt"
diff --unified "$RUNNER_TEMP/expected-requirements.txt" \
"$RUNNER_TEMP/packaged-requirements.txt"
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ app.
| [`hermes/`](./hermes) | [Hermes Agent](https://github.com/NousResearch/hermes-agent) | `hermes plugins install EverMind-AI/plugins/hermes` | 🧪 built — pre-release verification |
| [`dsh/`](./dsh) | [DeepSeek Harness](https://github.com/deepseek-ai/DeepSeek-Harness) | `dsh plugin --profile web add @evermind-ai/dsh-plugin` | 🧪 built — pre-release verification |
| [`dify/`](./dify) | [Dify](https://dify.ai) | Package with the Dify CLI, then upload the `.difypkg` in Dify | 🧪 built — Marketplace submission pending |
| [`dify_cloud/`](./dify_cloud) | [Dify](https://dify.ai) | Configure an EverOS Cloud API URL and API Key after installation | 🧪 built — Marketplace submission pending |

## Integration models

Expand Down
9 changes: 9 additions & 0 deletions dify_cloud/.difyignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.env*
!.env.example
.pytest_cache/
.ruff_cache/
.venv/
__pycache__/
*.py[cod]
*.difypkg
tests/
3 changes: 3 additions & 0 deletions dify_cloud/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
INSTALL_METHOD=remote
REMOTE_INSTALL_URL=debug.dify.ai:5003
REMOTE_INSTALL_KEY=replace-with-your-dify-debug-key
8 changes: 8 additions & 0 deletions dify_cloud/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.env*
!.env.example
.pytest_cache/
.ruff_cache/
.venv/
__pycache__/
*.py[cod]
*.difypkg
52 changes: 52 additions & 0 deletions dify_cloud/PRIVACY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Privacy Notice for EverOS Cloud for Dify

Last updated: 2026-08-25

## Data processed

When a Dify application invokes this plugin, it may send the following data to
the workspace-configured EverOS Cloud API URL:

- search queries;
- completed user and assistant messages selected by the workflow builder;
- domain-separated hashes derived from Dify runtime user, app, and conversation
identifiers;
- an internal project scope; and
- normal request metadata required for an HTTPS connection.

The EverOS Cloud API Key is sent only in the `Authorization: Bearer` request
header to the configured URL. The plugin does not ask for or receive the user's
LLM, embedding, rerank, or multimodal provider keys.

## Purpose and storage

The data is transmitted to search, store, and extract persistent memory. This
plugin itself does not create an independent telemetry or analytics store.
However, the operator of the configured EverOS Cloud service may process,
store, retain, or log the submitted data according to that operator's terms,
privacy notice, account configuration, and applicable law.

Before using the plugin, workspace administrators must verify that the
configured service is approved for the intended data and users. Do not send
secrets, credentials, regulated data, or personal data unless the organization
has authorized that use and appropriate notices and agreements are in place.

## Security controls

The plugin requires HTTPS, rejects local and non-public destinations, validates
DNS answers before a request, disables redirects, bounds response bodies, and
does not include upstream response bodies in Dify errors. These controls reduce
risk but do not replace service-operator security, workspace access controls,
data-loss prevention, or review of workflow inputs.

Credentials are stored by Dify using Dify's credential storage mechanism.
Access to plugin configuration should be restricted to authorized workspace
members. Removing the plugin does not by itself delete data previously stored
by the configured cloud service; use that service's deletion process.

## Support

Questions and privacy requests can be sent to <contact@evermind.ai>. Source and
issue tracking are available at
<https://github.com/EverMind-AI/plugins/tree/main/dify_cloud> and
<https://github.com/EverMind-AI/plugins/issues>.
91 changes: 91 additions & 0 deletions dify_cloud/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# EverOS Cloud for Dify

Connect Dify workflows and agents to persistent memory hosted by EverOS Cloud.
This is the cloud-service edition: users do not run an EverOS server alongside
Dify.

## What you need

- The EverOS Cloud API URL (the default is `https://api.evermind.ai`).
- An EverOS Cloud API Key for that service.
- A Dify LLM provider configured separately if the app itself calls an LLM.

The EverOS Cloud service manages its own LLM, embedding, rerank, and
multimodal configuration. Those provider keys are never entered into this
plugin. The plugin sends the EverOS Cloud API Key only to the configured HTTPS
service URL as an `Authorization: Bearer` header.

## Configure the credential

Open **Plugins -> EverOS Cloud -> Authorize** in Dify and enter:

| Field | Required | Value |
|---|---:|---|
| Credential name | Yes | Any label meaningful to your workspace. |
| EverOS Cloud API URL | Yes | Keep `https://api.evermind.ai` unless your account uses another approved HTTPS service root; do not include `/api/v2`. |
| EverOS Cloud API Key | Yes | The API key issued for that service. |

Saving the credential validates the URL, API Key format, and EverOS health
response. The first tool call confirms that the API Key is authorized. The URL
must use HTTPS and resolve only to public IP addresses. Redirects are not
followed.

## Tools

### Search EverOS Cloud memory

Searches persistent memory for the current Dify runtime user before the LLM
generates its answer. Inputs are the search query and an optional result limit.

### Add EverOS Cloud memory

Stores one completed user/assistant turn and asks EverOS Cloud to finalize
memory extraction. Add this after the LLM response in a workflow.

## Typical workflow

1. Start with the user's current message.
2. Call **Search EverOS Cloud memory** using that message as the query.
3. Pass the returned memory to the LLM as untrusted context.
4. Generate the final answer.
5. Call **Add EverOS Cloud memory** with the original user message and final
assistant answer.

Tool placement is explicit; installing the plugin does not automatically add
memory to every Dify app.

## Isolation and data flow

The plugin derives stable, domain-separated hashes from Dify's platform-owned
runtime user, app, and conversation identifiers. The LLM cannot choose those
scope identifiers. A fixed internal project scope is used, so users do not need
to configure project, user, app, or session IDs.

Search queries, completed conversation turns, and derived scope identifiers are
sent to the configured EverOS Cloud API URL. Do not store secrets or regulated
data unless your organization has approved that service and use case. See
[PRIVACY.md](./PRIVACY.md) for details.

## Security behavior

- HTTPS is mandatory.
- Localhost, private, link-local, reserved, and non-public DNS destinations are
rejected.
- Credentials in URLs, query strings, fragments, and redirects are rejected.
- Redirects are disabled so the authorization header is not forwarded.
- Response bodies are bounded to 2 MiB and upstream error bodies are not shown
in Dify errors.
- Memory content is untrusted input and must not be treated as instructions.

Because the destination URL is workspace-configurable, administrators should
allow only an approved EverOS Cloud endpoint and restrict who can edit plugin
credentials.

## Support

- Source: <https://github.com/EverMind-AI/plugins/tree/main/dify_cloud>
- Issues: <https://github.com/EverMind-AI/plugins/issues>
- Email: <contact@evermind.ai>
- EverOS: <https://github.com/EverMind-AI/EverOS>

Licensed under [Apache-2.0](https://github.com/EverMind-AI/plugins/blob/main/LICENSE).
5 changes: 5 additions & 0 deletions dify_cloud/_assets/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions dify_cloud/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from dify_plugin import DifyPluginEnv, Plugin

plugin = Plugin(DifyPluginEnv(MAX_REQUEST_TIMEOUT=600))


if __name__ == "__main__":
plugin.run()
50 changes: 50 additions & 0 deletions dify_cloud/manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
version: 0.0.1
type: plugin
author: evermind-ai
name: everos_cloud
label:
en_US: EverOS Cloud
zh_Hans: EverOS 云端版
description:
en_US: Search and store persistent agent memory through EverOS Cloud.
zh_Hans: 通过 EverOS 云端服务搜索和存储持久化 Agent 记忆。
icon: icon.svg
created_at: 2026-08-25T00:00:00Z
resource:
memory: 268435456
permission:
model:
enabled: false
llm: false
text_embedding: false
rerank: false
tts: false
speech2text: false
moderation: false
tool:
enabled: false
node:
enabled: false
endpoint:
enabled: false
app:
enabled: false
storage:
enabled: false
size: 1048576
plugins:
tools:
- provider/everos_cloud.yaml
meta:
version: 0.0.1
minimum_dify_version: "1.14.2"
arch:
- amd64
- arm64
runner:
language: python
version: "3.12"
entrypoint: main
privacy: PRIVACY.md
repo: https://github.com/EverMind-AI/plugins
verified: false
16 changes: 16 additions & 0 deletions dify_cloud/provider/everos_cloud.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from collections.abc import Mapping
from typing import Any

from dify_plugin import ToolProvider
from dify_plugin.errors.tool import ToolProviderCredentialValidationError

from utils.client import EverOSClient, EverOSError


class EverOSCloudProvider(ToolProvider):
def _validate_credentials(self, credentials: Mapping[str, Any]) -> None:
try:
with EverOSClient.from_credentials(credentials) as client:
client.health()
except (EverOSError, ValueError) as exc:
raise ToolProviderCredentialValidationError(str(exc)) from exc
44 changes: 44 additions & 0 deletions dify_cloud/provider/everos_cloud.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
identity:
author: evermind-ai
name: everos_cloud
label:
en_US: EverOS Cloud
zh_Hans: EverOS 云端版
description:
en_US: Persistent memory tools backed by your EverOS Cloud account.
zh_Hans: 由你的 EverOS 云端账户提供持久化记忆工具。
icon: icon.svg
tags:
- productivity
credentials_for_provider:
base_url:
type: text-input
required: true
default: https://api.evermind.ai
label:
en_US: EverOS Cloud API URL
zh_Hans: EverOS 云端 API 地址
placeholder:
en_US: https://api.evermind.ai
zh_Hans: https://api.evermind.ai
help:
en_US: EverOS Cloud service root. Keep the default unless your account uses another approved endpoint; do not include /api/v2.
zh_Hans: EverOS 云端服务根地址。除非账户使用其他获批端点,否则保留默认值;请勿包含 /api/v2。
api_key:
type: secret-input
required: true
label:
en_US: EverOS Cloud API Key
zh_Hans: EverOS 云端 API Key
placeholder:
en_US: Your EverOS Cloud API Key
zh_Hans: 你的 EverOS 云端 API Key
help:
en_US: Sent only to the configured URL as a Bearer token. This is not an LLM provider key.
zh_Hans: 仅作为 Bearer token 发送到上述地址;这不是大模型服务商的 Key。
tools:
- tools/search_memory.yaml
- tools/add_memory.yaml
extra:
python:
source: provider/everos_cloud.py
Loading