diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 89d5a1d..56ea4e9 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: git fetch --depth=1 origin "$GITHUB_SHA" git checkout -q FETCH_HEAD - # The fai-module-sdk dependency is a git dep against a repo + # The chain-module-sdk dependency is a git dep against a repo # that lives in another Forgejo org. The repo-scoped # GITHUB_TOKEN cannot read it, and the Forgejo instance has # REQUIRE_SIGNIN_VIEW=true so anonymous read is also denied. diff --git a/.forgejo/workflows/sign.yml b/.forgejo/workflows/sign.yml new file mode 100644 index 0000000..b4d6387 --- /dev/null +++ b/.forgejo/workflows/sign.yml @@ -0,0 +1,223 @@ +# F∆I module bundle signing workflow (cosign key-pinning model). +# +# Drop-in template for any module repo under chain-modules/. +# Triggers on tag push (vX.Y.Z) — builds the module, packs the +# .fai bundle, signs the bundle bytes with the Flemming.AI +# signing key (ECDSA P-256), and attaches bundle + .sig sidecar +# to the matching Forgejo Release. +# +# The hub-side verifier ships in 0.12.0+: when an operator sets +# `require_signatures: true`, install downloads the .sig sidecar +# from `.sig` and verifies it against the pinned store +# public key (built-in for `bundled` / `official`, per-store +# config for everything else). +# +# Adopt by copying this file to `.forgejo/workflows/sign.yml` in +# the module repo and replacing the MODULE_NAME placeholder. +# Add the signing key to Forgejo secrets as FAI_SIGNING_KEY (PEM, +# unencrypted, ECDSA P-256). Rotation is a 5-minute key-roll + +# binary re-release; see infra/cosign/README.md. + +name: sign-bundle + +on: + push: + tags: + - 'v*.*.*' + +env: + CARGO_TERM_COLOR: always + RUST_TOOLCHAIN: "1.86" + CARGO_NET_GIT_FETCH_WITH_CLI: "true" + +jobs: + sign: + runs-on: ubuntu-latest + permissions: + contents: write # attach signature to release + + env: + # The canonical module name as written in module.yaml. + # Used in the bundle filename + wasm path. + MODULE_NAME: text-translate + + steps: + # See fai/platform CI for background on the manual external + # checkout: the DinD runner cannot resolve forgejo:3000, so + # we clone via the external URL with $GITHUB_TOKEN. + - name: Checkout via external URL + run: | + set -eu + mkdir -p "$GITHUB_WORKSPACE" + cd "$GITHUB_WORKSPACE" + git init -q + git remote add origin \ + "https://x-access-token:${GITHUB_TOKEN}@git.flemming.ai/${GITHUB_REPOSITORY}.git" + git fetch --depth=1 origin "$GITHUB_SHA" + git checkout -q FETCH_HEAD + + # The chain-module-sdk dependency lives in another Forgejo org + # behind REQUIRE_SIGNIN_VIEW. MODULE_SDK_PAT (org-level + # secret, read-only on fai/module-sdk) authenticates cargo's + # git fetch via insteadOf. + - name: Configure git URL rewrite for SDK fetch + env: + SDK_PAT: ${{ secrets.MODULE_SDK_PAT }} + run: | + git config --global \ + "url.https://x-access-token:${SDK_PAT}@git.flemming.ai/.insteadOf" \ + "https://git.flemming.ai/" + + - name: Install system dependencies + run: | + apt-get update -qq + apt-get install -y --no-install-recommends \ + curl \ + ca-certificates \ + build-essential \ + pkg-config \ + libssl-dev \ + git \ + jq \ + openssl + + - name: Install Rust toolchain + run: | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \ + | sh -s -- -y \ + --profile minimal \ + --default-toolchain "$RUST_TOOLCHAIN" \ + --target wasm32-wasip2 + echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" + + - name: Build module (wasm32-wasip2) + run: cargo build --release --target wasm32-wasip2 + + - name: Install fai CLI + # Pinned to the production channel; signing requires the + # `fai pack` command. Override FAI_VERSION when bundle + # format compatibility matters. + run: | + curl -fsSL https://get.chain.flemming.ai | sh -s -- --no-bootstrap + # The installer drops fai at $HOME/.local/bin + echo "$HOME/.local/bin" >> "$GITHUB_PATH" + export PATH="$HOME/.local/bin:$PATH" + fai --version + + - name: Stage bundle inputs + # The wasm artefact is named after the Cargo package + # (underscored), which may differ from the module name + # in module.yaml (dashed). Resolve it from Cargo.toml so + # the template stays agnostic to the project's naming + # convention. + run: | + set -eu + CARGO_NAME=$(grep -E '^name *= *"' Cargo.toml \ + | head -1 | sed 's/.*"\(.*\)".*/\1/') + mkdir -p staging + cp module.yaml staging/ + cp "target/wasm32-wasip2/release/${CARGO_NAME}.wasm" staging/module.wasm + if [ -f sbom.cdx.json ]; then cp sbom.cdx.json staging/; fi + if [ -f MODULE.md ]; then cp MODULE.md staging/; fi + if [ -f MODULE.de.md ]; then cp MODULE.de.md staging/; fi + + - name: Pack bundle + id: pack + run: | + export PATH="$HOME/.local/bin:$PATH" + BUNDLE="${{ env.MODULE_NAME }}-${{ github.ref_name }}.fai" + fai pack staging --output "$BUNDLE" + echo "bundle=$BUNDLE" >> "$GITHUB_OUTPUT" + ls -la "$BUNDLE" + + - name: Sign bundle (Flemming.AI signing key) + env: + FAI_SIGNING_KEY_PEM: ${{ secrets.FAI_SIGNING_KEY }} + run: | + if [ -z "${FAI_SIGNING_KEY_PEM:-}" ]; then + cat >&2 <<'EOF' + + FAI_SIGNING_KEY secret is empty or undefined. + + This workflow signs module bundles with the Flemming.AI + module-signing key (ECDSA P-256, PKCS#8 PEM, unencrypted). + The matching public key is pinned in the fai-hub binary at + infra/cosign/official.pub — hubs that require_signatures + will reject anything not signed with this key. + + To configure: + 1. Forgejo -> chain-modules org -> Settings -> Secrets + 2. Add secret FAI_SIGNING_KEY (org-level recommended) + 3. Paste the unencrypted PEM (BEGIN PRIVATE KEY ...) + The encrypted source-of-truth lives on Stefan's Mac at + ~/.fai-secrets/flemming-ai-signing.key (passphrase in + mSecure under "Ch∆In — Module Signing Key (Private)"). + + See fai/platform infra/cosign/OPERATOR-HANDOFF.md for the + full setup runbook and rotation process. + EOF + exit 1 + fi + umask 077 + echo "$FAI_SIGNING_KEY_PEM" > /tmp/signing-key.pem + openssl dgst -sha256 \ + -sign /tmp/signing-key.pem \ + -out "${{ steps.pack.outputs.bundle }}.sig.raw" \ + "${{ steps.pack.outputs.bundle }}" + base64 < "${{ steps.pack.outputs.bundle }}.sig.raw" \ + > "${{ steps.pack.outputs.bundle }}.sig" + rm "${{ steps.pack.outputs.bundle }}.sig.raw" + shred -u /tmp/signing-key.pem || rm -f /tmp/signing-key.pem + ls -la "${{ steps.pack.outputs.bundle }}.sig" + + - name: Round-trip verify + # Sanity-check: the freshly-signed bundle must verify + # against the well-known public key before we publish it. + run: | + curl -fsSL https://git.flemming.ai/fai/platform/raw/branch/main/infra/cosign/official.pub \ + -o /tmp/official.pub + openssl dgst -sha256 \ + -verify /tmp/official.pub \ + -signature <(base64 -d < "${{ steps.pack.outputs.bundle }}.sig") \ + "${{ steps.pack.outputs.bundle }}" + + - name: Attach bundle + signature to Forgejo Release + run: | + set -eu + BUNDLE="${{ steps.pack.outputs.bundle }}" + SIG="$BUNDLE.sig" + REL_JSON=$(curl -sS \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + "https://git.flemming.ai/api/v1/repos/${GITHUB_REPOSITORY}/releases/tags/${GITHUB_REF_NAME}") + REL_ID=$(echo "$REL_JSON" | jq -r '.id // empty') + if [ -z "$REL_ID" ] || [ "$REL_ID" = "null" ]; then + REL_ID=$(curl -sS -X POST \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "Content-Type: application/json" \ + "https://git.flemming.ai/api/v1/repos/${GITHUB_REPOSITORY}/releases" \ + -d "{\"tag_name\":\"${GITHUB_REF_NAME}\",\"name\":\"${GITHUB_REF_NAME}\",\"draft\":false,\"prerelease\":false,\"body\":\"Auto-generated by sign-bundle workflow\"}" \ + | jq -r '.id') + fi + upload_one() { + local asset_path="$1" asset + asset=$(basename "$asset_path") + EXISTING=$(curl -sS \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + "https://git.flemming.ai/api/v1/repos/${GITHUB_REPOSITORY}/releases/${REL_ID}/assets" \ + | jq -r ".[] | select(.name==\"${asset}\") | .id") + if [ -n "$EXISTING" ]; then + curl -sS -X DELETE \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + "https://git.flemming.ai/api/v1/repos/${GITHUB_REPOSITORY}/releases/${REL_ID}/assets/${EXISTING}" \ + || true + fi + curl -sS -X POST \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -F "attachment=@${asset_path}" \ + "https://git.flemming.ai/api/v1/repos/${GITHUB_REPOSITORY}/releases/${REL_ID}/assets?name=${asset}" \ + > /dev/null + echo "uploaded $asset" + } + upload_one "$BUNDLE" + upload_one "$SIG" + echo "release ${GITHUB_REF_NAME} ready: https://git.flemming.ai/${GITHUB_REPOSITORY}/releases/tag/${GITHUB_REF_NAME}" diff --git a/Cargo.lock b/Cargo.lock index 56fd0b3..7cc11da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,17 +39,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "fai-module-sdk" +name = "chain-module-sdk" version = "0.1.2" -source = "git+https://git.flemming.ws/fai/module-sdk.git?branch=main#f209fbc86f531b53e576f3cdbdf75750eef3b07a" +source = "git+https://git.flemming.ai/fai/chain-module-sdk-rust.git?branch=main#98e98e9371f7409560a1ef08bc0923d9a2506449" dependencies = [ - "fai-module-sdk-macros", + "chain-module-sdk-macros", "serde", "serde_json", "thiserror", @@ -57,15 +51,21 @@ dependencies = [ ] [[package]] -name = "fai-module-sdk-macros" +name = "chain-module-sdk-macros" version = "0.1.2" -source = "git+https://git.flemming.ws/fai/module-sdk.git?branch=main#f209fbc86f531b53e576f3cdbdf75750eef3b07a" +source = "git+https://git.flemming.ai/fai/chain-module-sdk-rust.git?branch=main#98e98e9371f7409560a1ef08bc0923d9a2506449" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -267,7 +267,7 @@ dependencies = [ name = "text_translate" version = "0.1.0" dependencies = [ - "fai-module-sdk", + "chain-module-sdk", "serde", "serde_json", "thiserror", diff --git a/Cargo.toml b/Cargo.toml index 6bb96f1..97a6aa9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ description = "F∆I module providing text.translate" crate-type = ["cdylib", "rlib"] [dependencies] -fai-module-sdk = { git = "https://git.flemming.ws/fai/module-sdk.git", branch = "main" } +chain-module-sdk = { git = "https://git.flemming.ai/fai/chain-module-sdk-rust.git", branch = "main" } serde = { version = "1", features = ["derive"] } serde_json = "1" thiserror = "2" diff --git a/LICENSE b/LICENSE index 9536d06..cdde5b2 100644 --- a/LICENSE +++ b/LICENSE @@ -58,7 +58,7 @@ APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright 2026 fai-modules +Copyright 2026 Flemming.AI Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/MODULE.de.md b/MODULE.de.md new file mode 100644 index 0000000..532120b --- /dev/null +++ b/MODULE.de.md @@ -0,0 +1,94 @@ +# text.translate + +Ollama-basierte Übersetzung zwischen Sprachen. Sendet Quelltext +an einen konfigurierten LLM-Endpunkt mit einem +Übersetzungs-System-Prompt und liefert die Übersetzung plus +audit-taugliche Modell-Herkunfts-Felder. + +## Capability + +- `text.translate@0.1.0` + +## Eingaben + +| Name | Typ | Beschreibung | +| ----------------- | ---- | ------------------------------------------------------------------------- | +| `text` | text | Quelltext. | +| `target_language` | text | Zielsprache in einfachem Englisch (z.B. `German`, `French`, `ja-JP`). | +| `source_language` | text | Optionaler Hinweis auf die Ausgangssprache. Leer = Modell erkennt selbst. | +| `endpoint` | text | Ollama-förmiger `/api/chat`-Endpunkt. | +| `model` | text | Modell-ID am Endpunkt (z.B. `qwen2.5:14b`). | +| `api_key` | text | Optionaler Bearer-Token für Cloud-Endpunkte. | + +## Ausgaben + +| Name | Typ | Beschreibung | +| ----------------- | ---- | ------------------------------------------------------------------ | +| `translation` | text | Die Übersetzung. | +| `source_language` | text | Echo der Eingabe (oder erkannte Sprache bei Auto). | +| `target_language` | text | Echo der Eingabe. | +| `model_endpoint` | text | URL, gegen die übersetzt wurde. | +| `model_name` | text | Modell-ID wie an die LLM-API gesendet. | +| `model_digest` | text | SHA-256-Digest des bedienenden Ollama-Modells (wenn erreichbar). | + +Die drei `model_*`-Ausgaben sind das Audit-Primitiv: jede +Übersetzung im Flow-Log lässt sich auch Monate später dem exakten +Modell-Hash zuordnen, der sie erzeugt hat. + +## Berechtigungen + +```yaml +permissions: + - "net: localhost" + - "net: 127.0.0.1" + - "net: api.openai.com" + - "net: api.anthropic.com" +``` + +Default-Policy erlaubt lokales Ollama und die zwei großen +Hosted-Anbieter. Mit privatem LLM-Endpunkt: Hostname in die +Operator-Policy-Ceiling aufnehmen; das Modul prüft seine +Berechtigungen gegen diese Ceiling bei der Installation. + +## Für regulierte Umgebungen gebaut + +Der Ollama-Endpunkt steht per Default auf einem lokalen Daemon +— Quelltext verlässt nie den Rechner. Cloud-Anbieter sind +Opt-in über die URL + Operator-Policy. Das `model_digest`-Feld +ist der kryptographische Vertrauensanker für die +Übersetzungs-Herkunft: zwei Ausgaben mit gleichem Digest +stammen vom selben Modell-Gewicht, Punkt. + +## Grenzen in v0.1.0 + +- Single-Shot. Lange Dokumente mit Chunking + Überlapp- + Stitching folgt in v0.2.0. +- Keine Glossar-/Terminologie-Listen. Aktuell verlässt sich das + Modul auf das Allgemeinwissen des Modells; ein `glossary`- + Input ist auf der v0.2.0-Roadmap. + +## Beispiel-Flow + +```yaml +name: translate-to-german +inputs: + source: text +steps: + - id: translate + use: text.translate@^0 + with: + text: $inputs.source + target_language: "German" + endpoint: "http://localhost:11434/api/chat" + model: "qwen2.5:14b" +outputs: + translation: $translate.translation + audit_model: $translate.model_digest +``` + +## Build + +```bash +cargo build --release --target wasm32-wasip2 +# Ausgabe: target/wasm32-wasip2/release/text_translate.wasm +``` diff --git a/MODULE.md b/MODULE.md new file mode 100644 index 0000000..f9d462b --- /dev/null +++ b/MODULE.md @@ -0,0 +1,94 @@ +# text.translate + +Ollama-backed translation between languages. Sends source text +to a configured LLM endpoint with a translation system prompt +and emits the translated text plus audit-grade +model-provenance fields. + +## Capability + +- `text.translate@0.1.0` + +## Inputs + +| Name | Type | Description | +| ----------------- | ---- | ---------------------------------------------------------------------- | +| `text` | text | Source text to translate. | +| `target_language` | text | Target language in plain English (e.g. `German`, `French`, `ja-JP`). | +| `source_language` | text | Optional source-language hint. Empty = let the model auto-detect. | +| `endpoint` | text | Ollama-shaped `/api/chat` endpoint URL. | +| `model` | text | Model identifier the endpoint serves (e.g. `qwen2.5:14b`). | +| `api_key` | text | Optional bearer token for cloud-hosted endpoints. | + +## Outputs + +| Name | Type | Description | +| ----------------- | ---- | -------------------------------------------------------------------- | +| `translation` | text | The translated text. | +| `source_language` | text | Echo of the input value (or detected language when auto). | +| `target_language` | text | Echo of the input value. | +| `model_endpoint` | text | URL the translation was generated against. | +| `model_name` | text | Model identifier as supplied to the LLM API. | +| `model_digest` | text | SHA-256 digest of the served Ollama model (when reachable). | + +The three `model_*` outputs are the audit primitive: every +translation in the flow log can be matched to the exact model +hash that produced it, even months later. + +## Permissions + +```yaml +permissions: + - "net: localhost" + - "net: 127.0.0.1" + - "net: api.openai.com" + - "net: api.anthropic.com" +``` + +The default policy allows local Ollama and the two major +hosted providers. Operators with a private LLM endpoint add +their hostname to the operator-policy ceiling; the module's +permissions are enforced against that ceiling at install time. + +## Built for regulated environments + +The Ollama endpoint defaults to a local daemon — source text +never leaves the host. Cloud providers are opt-in via the +endpoint URL + operator policy. The `model_digest` field is +the cryptographic root-of-trust for translation provenance: +two outputs with the same digest came from the same model +weights, period. + +## Limits in v0.1.0 + +- Single-shot translation. Long-document chunked translation + with overlap-stitching is the v0.2.0 plan. +- No glossary / terminology-list support. Operators currently + rely on the model's general knowledge; a `glossary` input + is on the v0.2.0 roadmap. + +## Example flow + +```yaml +name: translate-to-german +inputs: + source: text +steps: + - id: translate + use: text.translate@^0 + with: + text: $inputs.source + target_language: "German" + endpoint: "http://localhost:11434/api/chat" + model: "qwen2.5:14b" +outputs: + translation: $translate.translation + audit_model: $translate.model_digest +``` + +## Build + +```bash +cargo build --release --target wasm32-wasip2 +# Output: target/wasm32-wasip2/release/text_translate.wasm +``` diff --git a/README.md b/README.md index 1859a4b..df866f8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # text-translate -Provides the `text.translate` capability for F∆I Platform. +Provides the `text.translate` capability for Ch∆In. ## Build @@ -15,7 +15,7 @@ cargo test # host-side unit + integration tests fai test . # load the wasm component in the runtime sandbox ``` -## Authoring with fai-module-sdk +## Authoring with chain-module-sdk The module body is one decorated function: @@ -29,12 +29,12 @@ pub fn invoke(_ctx: Context, inputs: Inputs) -> Result { The macro hides the wit_bindgen call, the Guest impl, the Payload variant matching, and the `wit_bindgen::export!` -invocation. See `fai-module-sdk` documentation for the full +invocation. See `chain-module-sdk` documentation for the full surface. ## SDK source -The Cargo.toml git-deps `fai-module-sdk` from +The Cargo.toml git-deps `chain-module-sdk` from `https://git.flemming.ws/fai/module-sdk.git`. If your environment requires authentication for that host (e.g. Forgejo with `REQUIRE_SIGNIN_VIEW=true`), set up `git config insteadOf` with diff --git a/module.wasm b/module.wasm new file mode 100644 index 0000000..3cfd457 Binary files /dev/null and b/module.wasm differ diff --git a/module.yaml b/module.yaml index aedf093..4044ada 100644 --- a/module.yaml +++ b/module.yaml @@ -1,46 +1,85 @@ -schema_version: 1 +schema_version: 3 +provider: chain name: text-translate version: 0.1.0 -# Capability provided by this module. provides: - capability: text.translate version: 0.1.0 -# Inputs the invoke function accepts. inputs: - # Source text to translate. - text: text - # Target language name in plain English (e.g. "German", - # "French", "ja-JP" — anything the configured LLM - # understands). - target_language: text - # Optional source language hint. Empty string lets the model - # auto-detect. - source_language: text - # Ollama-shaped /api/chat endpoint. - endpoint: text - # Model identifier (e.g. "qwen2.5:14b"). - model: text - # Optional bearer token for cloud-hosted endpoints. - api_key: text + text: + type: text + description: + en: Source text to translate. + de: Quelltext, der übersetzt werden soll. + target_language: + type: text + description: + en: | + Target language name in plain English (e.g. "German", + "French", "ja-JP" — anything the configured LLM + understands). + de: | + Zielsprache in Klartext (z. B. "German", "French", + "ja-JP" — alles was das konfigurierte LLM versteht). + source_language: + type: text + description: + en: | + Optional source language hint. Empty = let the model + auto-detect. + de: | + Optionaler Hinweis zur Quellsprache. Leer = das Modell + erkennt sie selbst. + endpoint: + type: text + description: + en: Ollama-shaped /api/chat endpoint. + de: Ollama-kompatibler /api/chat-Endpunkt. + model: + type: text + description: + en: Model identifier (e.g. "qwen2.5:14b"). + de: Modell-Identifier (z. B. "qwen2.5:14b"). + api_key: + type: text + description: + en: Optional bearer token for cloud-hosted endpoints. + de: Optionaler Bearer-Token für Cloud-Endpunkte. -# Outputs produced. outputs: - # The translated text. - translation: text - # Echo of the source-language input for downstream audit. - source_language: text - # Echo of the target-language input. - target_language: text - # Endpoint the translation was generated against. - model_endpoint: text - # Model identifier as supplied to the LLM API. - model_name: text - # SHA-256 digest of the served Ollama model (when reachable). - model_digest: text + translation: + type: text + description: + en: The translated text. + de: Der übersetzte Text. + source_language: + type: text + description: + en: Echo of the source-language input for downstream audit. + de: Echo des source_language-Inputs für Downstream-Audit. + target_language: + type: text + description: + en: Echo of the target-language input. + de: Echo des target_language-Inputs. + model_endpoint: + type: text + description: + en: Endpoint the translation was generated against. + de: Endpunkt, gegen den die Übersetzung erzeugt wurde. + model_name: + type: text + description: + en: Model identifier as supplied to the LLM API. + de: An die LLM-API übergebenes Modell. + model_digest: + type: text + description: + en: SHA-256 digest of the served Ollama model (when reachable). + de: SHA-256-Digest des bedienten Ollama-Modells (wenn erreichbar). -# Permissions required. permissions: - "net: localhost" - "net: 127.0.0.1" diff --git a/src/lib.rs b/src/lib.rs index 44962d4..d32493b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,7 @@ mod llm; -use fai_module_sdk::prelude::*; +use chain_module_sdk::prelude::*; const SYSTEM_PROMPT: &str = "You are a faithful translation engine. \ Translate the user's text into the requested target language. \