From f899660a40e914b2a712fa4f745fca24a767b435 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 19:24:06 +0200 Subject: [PATCH] i18n - docs translations (#21237) Created by Github action Co-authored-by: github-actions --- .../developers/extend/apps/config/roles.mdx | 10 +-- .../extend/apps/logic/logic-functions.mdx | 27 ++++++++ .../extend/apps/logic/skills-and-agents.mdx | 69 +++++++++++++++++++ .../developers/extend/apps/config/roles.mdx | 10 +-- .../extend/apps/logic/logic-functions.mdx | 27 ++++++++ .../extend/apps/logic/skills-and-agents.mdx | 69 +++++++++++++++++++ .../developers/extend/apps/config/roles.mdx | 10 +-- .../extend/apps/logic/logic-functions.mdx | 27 ++++++++ .../extend/apps/logic/skills-and-agents.mdx | 69 +++++++++++++++++++ .../developers/extend/apps/config/roles.mdx | 10 +-- .../extend/apps/logic/logic-functions.mdx | 27 ++++++++ .../extend/apps/logic/skills-and-agents.mdx | 69 +++++++++++++++++++ .../developers/extend/apps/config/roles.mdx | 10 +-- .../extend/apps/logic/logic-functions.mdx | 27 ++++++++ .../extend/apps/logic/skills-and-agents.mdx | 69 +++++++++++++++++++ .../developers/extend/apps/config/roles.mdx | 10 +-- .../extend/apps/logic/logic-functions.mdx | 27 ++++++++ .../extend/apps/logic/skills-and-agents.mdx | 69 +++++++++++++++++++ 18 files changed, 606 insertions(+), 30 deletions(-) diff --git a/packages/twenty-docs/l/de/developers/extend/apps/config/roles.mdx b/packages/twenty-docs/l/de/developers/extend/apps/config/roles.mdx index 1735a4690a..27783ce09b 100644 --- a/packages/twenty-docs/l/de/developers/extend/apps/config/roles.mdx +++ b/packages/twenty-docs/l/de/developers/extend/apps/config/roles.mdx @@ -9,8 +9,8 @@ Eine **Rolle** ist ein Berechtigungssatz: welche Objekte eine App lesen oder sch ```ts src/roles/restricted-company-role.ts import { defineRole, - PermissionFlag, STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS, + SystemPermissionFlag, } from 'twenty-sdk/define'; export default defineRole({ @@ -46,7 +46,7 @@ export default defineRole({ canUpdateFieldValue: false, }, ], - permissionFlags: [PermissionFlag.APPLICATIONS], + permissionFlagUniversalIdentifiers: [SystemPermissionFlag.APPLICATIONS], }); ``` @@ -55,7 +55,7 @@ export default defineRole({ Wenn Sie eine neue App erzeugen, erstellt die CLI eine Datei für die Standardrolle, die mit `defineApplicationRole()` deklariert ist: ```ts src/roles/default-role.ts -import { defineApplicationRole, PermissionFlag } from 'twenty-sdk/define'; +import { defineApplicationRole } from 'twenty-sdk/define'; export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER = 'b648f87b-1d26-4961-b974-0908fd991061'; @@ -74,7 +74,7 @@ export default defineApplicationRole({ canBeAssignedToApiKeys: false, objectPermissions: [], fieldPermissions: [], - permissionFlags: [], + permissionFlagUniversalIdentifiers: [], }); ``` @@ -90,5 +90,5 @@ Notizen: * Beginnen Sie mit der vorgegebenen Rolle und schränken Sie sie dann schrittweise ein – standardmäßig wird umfangreicher Lesezugriff gewährt, was selten das ist, was Sie in Produktionsumgebungen möchten. * Ersetzen Sie `objectPermissions` und `fieldPermissions` durch die genauen Objekte und Felder, die Ihre Funktionen tatsächlich benötigen. -* `permissionFlags` steuern den Zugriff auf Funktionen auf Plattformebene. Halten Sie sie minimal. +* `permissionFlagUniversalIdentifiers` steuern den Zugriff auf Funktionen auf Plattformebene. Halten Sie sie minimal. * Ein funktionierendes Beispiel finden Sie unter: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). diff --git a/packages/twenty-docs/l/de/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/de/developers/extend/apps/logic/logic-functions.mdx index 1464c196e3..0a471c7d19 100644 --- a/packages/twenty-docs/l/de/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/de/developers/extend/apps/logic/logic-functions.mdx @@ -144,6 +144,33 @@ const handler = async (event: RoutePayload) => { Header-Namen werden in Kleinbuchstaben normalisiert. Greifen Sie mit Schlüsseln in Kleinbuchstaben darauf zu (z. B. `event.headers['content-type']`). +#### Benutzerdefinierte HTTP-Antwort + +Standardmäßig sendet das Zurückgeben eines einfachen Werts aus Ihrem Handler diesen als `200`-Antwort zurück (JSON für Objekte, `text/plain` für Zeichenketten). Um den Statuscode und die Antwort-Header zu steuern, geben Sie eine `Response` aus `twenty-sdk/logic-function` zurück: + +```ts +import { Response } from 'twenty-sdk/logic-function'; + +const handler = async (event: RoutePayload) => { + return new Response('

Hello

', { + status: 201, + headers: { 'content-type': 'text/html' }, + }); +}; +``` + +Aus Sicherheitsgründen sind Antwort-Header auf eine Allowlist beschränkt. Jeder Header, der nicht auf der Liste steht (z. B. `Set-Cookie`, CORS-Header wie `Access-Control-Allow-Origin` oder benutzerdefinierte `X-*`-Header), wird stillschweigend verworfen, bevor die Antwort gesendet wird. Die erlaubten Antwort-Header sind: + +* `content-type` +* `content-language` +* `content-disposition` +* `cache-control` +* `retry-after` + + +Der Statuscode muss ein gültiger HTTP-Statuscode sein (zwischen 100 und 599). Antwort-Header-Namen werden ohne Beachtung der Groß-/Kleinschreibung verglichen. + + #### Datenbank-Event-Trigger-Payload Wenn ein Datenbank-Event-Trigger Ihre Logic Function aufruft, erhält sie eine `DatabaseEventPayload` pro geändertem Datensatz. Die Payload kombiniert Metadaten über den Quell-Workspace und das Objekt mit dem Ereignis auf Datensatzebene. diff --git a/packages/twenty-docs/l/de/developers/extend/apps/logic/skills-and-agents.mdx b/packages/twenty-docs/l/de/developers/extend/apps/logic/skills-and-agents.mdx index 70b4ae7ac4..1cab1273a4 100644 --- a/packages/twenty-docs/l/de/developers/extend/apps/logic/skills-and-agents.mdx +++ b/packages/twenty-docs/l/de/developers/extend/apps/logic/skills-and-agents.mdx @@ -64,6 +64,75 @@ Hauptpunkte: * `description` (optional) liefert Kontext dazu, was der Agent tut. * `icon` (optional) legt das in der UI angezeigte Symbol fest. * `modelId` (optional) überschreibt das vom Agenten verwendete Standard-KI-Modell. +* `responseFormat` (optional) steuert die Form der Ausgabe des Agenten. Standardmäßig ist `{ type: 'text' }` für Freitext. Verwenden Sie `{ type: 'json', schema }`, um eine strukturierte JSON-Ausgabe zu erzwingen. + +Standardmäßig gibt ein Agent freien Text zurück. Um eine strukturierte Ausgabe zu erhalten, setzen Sie `responseFormat` auf `{ type: 'json' }` und geben Sie ein `schema` an: + +```ts src/agents/structured-agent.ts +import { defineAgent } from 'twenty-sdk/define'; + +export default defineAgent({ + universalIdentifier: 'c4d5e6f7-a8b9-0123-cdef-456789012345', + name: 'lead-scorer', + label: 'Lead Scorer', + prompt: 'Score the lead and explain your reasoning.', + responseFormat: { + type: 'json', + schema: { + type: 'object', + properties: { + score: { type: 'number', description: 'Lead score from 0 to 100' }, + summary: { type: 'string', description: 'Short reasoning for the score' }, + }, + required: ['score', 'summary'], + additionalProperties: false, + }, + }, +}); +``` + +Schema-Hinweise: +* Das Schema ist ein flaches Objekt: Der `type` jeder Eigenschaft muss ein primitiver Typ sein (`string`, `number` oder `boolean`). Verschachtelte Objekte und Arrays werden nicht unterstützt. +* `description` (optional) an jeder Eigenschaft leitet das Modell an, was dort eingetragen werden soll. +* `required` (optional) listet die Eigenschaften auf, die das Modell immer zurückgeben muss. +* `additionalProperties: false` (optional) verbietet alle Eigenschaften, die nicht in `properties` deklariert sind. + + + + +`runAgent()` ermöglicht es einer Logikfunktion, einen der Agenten Ihrer App auszuführen (mit seinen Fähigkeiten und Tools). Identifizieren Sie den Agenten über den `universalIdentifier`, den Sie an `defineAgent()` übergeben haben: + +```ts src/logic-functions/run-enricher.ts +import { runAgent } from 'twenty-sdk/logic-function'; + +const { result, error, success } = await runAgent({ + agentUniversalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123', + prompt: 'Enrich House Ad : fill empty fields from its listing URL.', +}); +``` + +Hauptpunkte: +* Der Agent wird **synchron** ausgeführt und kann selbst Datensätze über seine eigenen Tools lesen/aktualisieren — `runAgent()` wird aufgelöst, sobald die Ausführung abgeschlossen ist. +* Eine App kann nur ihre eigenen Agenten ausführen. +* Die [Standardrolle](/l/de/developers/extend/apps/config/roles) der App muss das Berechtigungsflag `AI` gewähren — fügen Sie `SystemPermissionFlag.AI` zu ihren `permissionFlagUniversalIdentifiers` hinzu (oder setzen Sie `canAccessAllTools: true`). + Ohne dieses Flag schlägt `runAgent()` mit einem Berechtigungsfehler fehl. +* Setzen Sie ein großzügiges `timeoutSeconds` für die Logikfunktion — Agentenläufe können mehrere Sekunden dauern. +* `success` ist `true` und `result` ist nicht null, wenn der Lauf abgeschlossen ist; bei einem Fehler ist `success` `false`, `result` ist `null` und `error` enthält den Grund (zum Beispiel, wenn dem Workspace während des Laufs die AI-Credits ausgehen). + +```ts src/roles/default-role.ts +import { defineApplicationRole, SystemPermissionFlag } from 'twenty-sdk/define'; + +export default defineApplicationRole({ + universalIdentifier: 'b648f87b-1d26-4961-b974-0908fd991061', + label: 'Default function role', + // runAgent() requires the AI permission flag on the app's default role. + permissionFlagUniversalIdentifiers: [SystemPermissionFlag.AI], +}); +``` + + + **Vermeiden Sie Schleifen:** Wenn Sie `runAgent()` von einem `*.updated`-Datenbankereignis-Trigger aus aufrufen und der Agent denselben Datensatz aktualisiert, schränken Sie den Trigger mit `updatedFields` auf ein Feld ein, das der Agent niemals beschreibt (z. B. die Quell-URL), oder prüfen Sie, ob eines der Zielfelder noch leer ist, bevor Sie `runAgent()` aufrufen. + diff --git a/packages/twenty-docs/l/pt/developers/extend/apps/config/roles.mdx b/packages/twenty-docs/l/pt/developers/extend/apps/config/roles.mdx index 26ab0bb876..fb6dd1f4aa 100644 --- a/packages/twenty-docs/l/pt/developers/extend/apps/config/roles.mdx +++ b/packages/twenty-docs/l/pt/developers/extend/apps/config/roles.mdx @@ -9,8 +9,8 @@ Um **papel** é um conjunto de permissões: quais objetos um app pode ler ou gra ```ts src/roles/restricted-company-role.ts import { defineRole, - PermissionFlag, STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS, + SystemPermissionFlag, } from 'twenty-sdk/define'; export default defineRole({ @@ -46,7 +46,7 @@ export default defineRole({ canUpdateFieldValue: false, }, ], - permissionFlags: [PermissionFlag.APPLICATIONS], + permissionFlagUniversalIdentifiers: [SystemPermissionFlag.APPLICATIONS], }); ``` @@ -55,7 +55,7 @@ export default defineRole({ Ao criar um novo app com o scaffold, a CLI cria um arquivo de papel padrão declarado com `defineApplicationRole()`: ```ts src/roles/default-role.ts -import { defineApplicationRole, PermissionFlag } from 'twenty-sdk/define'; +import { defineApplicationRole } from 'twenty-sdk/define'; export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER = 'b648f87b-1d26-4961-b974-0908fd991061'; @@ -74,7 +74,7 @@ export default defineApplicationRole({ canBeAssignedToApiKeys: false, objectPermissions: [], fieldPermissions: [], - permissionFlags: [], + permissionFlagUniversalIdentifiers: [], }); ``` @@ -90,5 +90,5 @@ Notas: * Comece a partir do papel gerado pelo scaffold e, em seguida, restrinja-o progressivamente — o padrão concede amplo acesso de leitura, o que raramente é o que você quer em produção. * Substitua `objectPermissions` e `fieldPermissions` pelos objetos e campos de que suas funções realmente precisam. -* `permissionFlags` controlam o acesso a recursos em nível de plataforma. Mantenha-os no mínimo necessário. +* `permissionFlagUniversalIdentifiers` controlam o acesso a recursos em nível de plataforma. Mantenha-os no mínimo necessário. * Veja um exemplo funcional: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). diff --git a/packages/twenty-docs/l/pt/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/pt/developers/extend/apps/logic/logic-functions.mdx index 4e751072cd..a9f092a1c7 100644 --- a/packages/twenty-docs/l/pt/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/pt/developers/extend/apps/logic/logic-functions.mdx @@ -144,6 +144,33 @@ const handler = async (event: RoutePayload) => { Os nomes dos cabeçalhos são normalizados para minúsculas. Acesse-os usando chaves em minúsculas (por exemplo, `event.headers['content-type']`). +#### Resposta HTTP personalizada + +Por padrão, retornar um valor simples do seu handler o envia de volta como uma resposta `200` (JSON para objetos, `text/plain` para strings). Para controlar o código de status e os cabeçalhos da resposta, retorne um `Response` de `twenty-sdk/logic-function`: + +```ts +import { Response } from 'twenty-sdk/logic-function'; + +const handler = async (event: RoutePayload) => { + return new Response('

Hello

', { + status: 201, + headers: { 'content-type': 'text/html' }, + }); +}; +``` + +Por motivos de segurança, os cabeçalhos de resposta são restringidos a uma lista de permissões. Qualquer cabeçalho que não esteja na lista (por exemplo, `Set-Cookie`, cabeçalhos CORS como `Access-Control-Allow-Origin` ou cabeçalhos personalizados `X-*`) é silenciosamente descartado antes de a resposta ser enviada. Os cabeçalhos de resposta permitidos são: + +* `content-type` +* `content-language` +* `content-disposition` +* `cache-control` +* `retry-after` + + +O código de status deve ser um código de status HTTP válido (entre 100 e 599). Os nomes dos cabeçalhos de resposta são comparados sem distinção entre maiúsculas e minúsculas. + + #### Payload do gatilho de evento do banco de dados Quando um gatilho de evento do banco de dados invoca sua função lógica, ela recebe um `DatabaseEventPayload` por registro alterado. O payload combina metadados sobre o workspace e o objeto de origem com o evento em nível de registro. diff --git a/packages/twenty-docs/l/pt/developers/extend/apps/logic/skills-and-agents.mdx b/packages/twenty-docs/l/pt/developers/extend/apps/logic/skills-and-agents.mdx index fd45bc8879..14e6783d91 100644 --- a/packages/twenty-docs/l/pt/developers/extend/apps/logic/skills-and-agents.mdx +++ b/packages/twenty-docs/l/pt/developers/extend/apps/logic/skills-and-agents.mdx @@ -64,6 +64,75 @@ Pontos-chave: * `description` (opcional) fornece contexto sobre o que o agente faz. * `icon` (opcional) define o ícone exibido na UI. * `modelId` (opcional) substitui o modelo de IA padrão usado pelo agente. +* `responseFormat` (opcional) controla o formato da saída do agente. O padrão é `{ type: 'text' }` para texto em formato livre. Use `{ type: 'json', schema }` para forçar a saída em JSON estruturado. + +Por padrão, um agente retorna texto em formato livre. Para obter saída estruturada, defina `responseFormat` como `{ type: 'json' }` e forneça um `schema`: + +```ts src/agents/structured-agent.ts +import { defineAgent } from 'twenty-sdk/define'; + +export default defineAgent({ + universalIdentifier: 'c4d5e6f7-a8b9-0123-cdef-456789012345', + name: 'lead-scorer', + label: 'Lead Scorer', + prompt: 'Score the lead and explain your reasoning.', + responseFormat: { + type: 'json', + schema: { + type: 'object', + properties: { + score: { type: 'number', description: 'Lead score from 0 to 100' }, + summary: { type: 'string', description: 'Short reasoning for the score' }, + }, + required: ['score', 'summary'], + additionalProperties: false, + }, + }, +}); +``` + +Observações sobre o esquema: +* O esquema é um objeto plano: o `type` de cada propriedade deve ser um primitivo (`string`, `number` ou `boolean`). Objetos aninhados e arrays não são suportados. +* `description` (opcional) em cada propriedade orienta o modelo sobre o que colocar ali. +* `required` (opcional) lista as propriedades que o modelo deve sempre retornar. +* `additionalProperties: false` (opcional) proíbe qualquer propriedade não declarada em `properties`. + + + + +`runAgent()` permite que uma função de lógica execute um dos agentes do seu app (com suas habilidades e ferramentas). Identifique o agente pelo `universalIdentifier` que você passou para `defineAgent()`: + +```ts src/logic-functions/run-enricher.ts +import { runAgent } from 'twenty-sdk/logic-function'; + +const { result, error, success } = await runAgent({ + agentUniversalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123', + prompt: 'Enrich House Ad : fill empty fields from its listing URL.', +}); +``` + +Pontos-chave: +* O agente é executado sincronamente e pode ler/atualizar registros por conta própria por meio de suas próprias ferramentas — `runAgent()` é resolvido quando a execução é concluída. +* Um app só pode executar os seus próprios agentes. +* O [papel padrão](/l/pt/developers/extend/apps/config/roles) do app deve conceder o sinalizador de permissão `AI` — adicione `SystemPermissionFlag.AI` ao seu `permissionFlagUniversalIdentifiers` (ou defina `canAccessAllTools: true`). + Sem isso, `runAgent()` falha com um erro de permissão. +* Defina um valor generoso de `timeoutSeconds` na função de lógica — execuções de agentes podem levar vários segundos. +* `success` é `true` e `result` é diferente de nulo quando a execução é concluída; em caso de falha `success` é `false`, `result` é nulo e `error` contém o motivo (por exemplo, quando o espaço de trabalho fica sem créditos de IA no meio da execução). + +```ts src/roles/default-role.ts +import { defineApplicationRole, SystemPermissionFlag } from 'twenty-sdk/define'; + +export default defineApplicationRole({ + universalIdentifier: 'b648f87b-1d26-4961-b974-0908fd991061', + label: 'Default function role', + // runAgent() requires the AI permission flag on the app's default role. + permissionFlagUniversalIdentifiers: [SystemPermissionFlag.AI], +}); +``` + + + **Evite loops:** se você chamar `runAgent()` a partir de um gatilho de evento de banco de dados `*.updated` e o agente atualizar o mesmo registro, delimite o gatilho com `updatedFields` para um campo que o agente nunca escreve (por exemplo, a URL de origem) ou verifique se algum campo de destino ainda está vazio antes de chamar `runAgent()`. + diff --git a/packages/twenty-docs/l/ro/developers/extend/apps/config/roles.mdx b/packages/twenty-docs/l/ro/developers/extend/apps/config/roles.mdx index b0871dff36..1ccf6ead01 100644 --- a/packages/twenty-docs/l/ro/developers/extend/apps/config/roles.mdx +++ b/packages/twenty-docs/l/ro/developers/extend/apps/config/roles.mdx @@ -9,8 +9,8 @@ Un **rol** este un set de permisiuni: ce obiecte poate citi sau scrie o aplicaț ```ts src/roles/restricted-company-role.ts import { defineRole, - PermissionFlag, STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS, + SystemPermissionFlag, } from 'twenty-sdk/define'; export default defineRole({ @@ -46,7 +46,7 @@ export default defineRole({ canUpdateFieldValue: false, }, ], - permissionFlags: [PermissionFlag.APPLICATIONS], + permissionFlagUniversalIdentifiers: [SystemPermissionFlag.APPLICATIONS], }); ``` @@ -55,7 +55,7 @@ export default defineRole({ Când generați o aplicație nouă, CLI creează un fișier de rol implicit declarat cu `defineApplicationRole()`: ```ts src/roles/default-role.ts -import { defineApplicationRole, PermissionFlag } from 'twenty-sdk/define'; +import { defineApplicationRole } from 'twenty-sdk/define'; export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER = 'b648f87b-1d26-4961-b974-0908fd991061'; @@ -74,7 +74,7 @@ export default defineApplicationRole({ canBeAssignedToApiKeys: false, objectPermissions: [], fieldPermissions: [], - permissionFlags: [], + permissionFlagUniversalIdentifiers: [], }); ``` @@ -90,5 +90,5 @@ Notițe: * Porniți de la rolul generat de scaffolding, apoi restrângeți-l progresiv — rolul implicit acordă acces larg la citire, ceea ce rareori este de dorit în producție. * Înlocuiți `objectPermissions` și `fieldPermissions` cu obiectele și câmpurile de care au nevoie efectiv funcțiile dvs. -* `permissionFlags` controlează accesul la capabilități la nivelul platformei. Mențineți-le la minimum. +* `permissionFlagUniversalIdentifiers` controlează accesul la capabilități la nivelul platformei. Mențineți-le la minimum. * Vedeți un exemplu funcțional: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). diff --git a/packages/twenty-docs/l/ro/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/ro/developers/extend/apps/logic/logic-functions.mdx index 2252ed3ea3..08e9a51530 100644 --- a/packages/twenty-docs/l/ro/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/ro/developers/extend/apps/logic/logic-functions.mdx @@ -145,6 +145,33 @@ const handler = async (event: RoutePayload) => { Numele anteturilor sunt normalizate la litere mici. Accesați-le folosind chei cu litere mici (de exemplu, `event.headers['content-type']`). +#### Răspuns HTTP personalizat + +În mod implicit, returnarea unei valori simple din handler trimite înapoi un răspuns `200` (JSON pentru obiecte, `text/plain` pentru șiruri). Pentru a controla codul de stare și antetele răspunsului, returnează un `Response` din `twenty-sdk/logic-function`: + +```ts +import { Response } from 'twenty-sdk/logic-function'; + +const handler = async (event: RoutePayload) => { + return new Response('

Hello

', { + status: 201, + headers: { 'content-type': 'text/html' }, + }); +}; +``` + +Din motive de securitate, anteturile de răspuns sunt limitate la o listă de antete permise. Orice antet care nu se află pe listă (de exemplu, `Set-Cookie`, anteturi CORS precum `Access-Control-Allow-Origin` sau anteturi personalizate `X-*`) este eliminat în mod silențios înainte ca răspunsul să fie trimis. Anteturile de răspuns permise sunt: + +* `content-type` +* `content-language` +* `content-disposition` +* `cache-control` +* `retry-after` + + +Codul de stare trebuie să fie un cod de stare HTTP valid (între 100 și 599). Numele anteturilor de răspuns sunt comparate fără a ține cont de majuscule și minuscule. + + #### Payload-ul declanșatorului de eveniment al bazei de date Când un declanșator de eveniment al bazei de date apelează funcția dvs. logică, aceasta primește un `DatabaseEventPayload` pentru fiecare înregistrare modificată. Payload-ul combină metadatele despre spațiul de lucru și obiectul sursă cu evenimentul la nivel de înregistrare. diff --git a/packages/twenty-docs/l/ro/developers/extend/apps/logic/skills-and-agents.mdx b/packages/twenty-docs/l/ro/developers/extend/apps/logic/skills-and-agents.mdx index 5ad98dd4c2..a915e1b76a 100644 --- a/packages/twenty-docs/l/ro/developers/extend/apps/logic/skills-and-agents.mdx +++ b/packages/twenty-docs/l/ro/developers/extend/apps/logic/skills-and-agents.mdx @@ -64,6 +64,75 @@ Puncte cheie: * `description` (opțional) oferă context despre ce face agentul. * `icon` (opțional) setează pictograma afișată în UI. * `modelId` (opțional) suprascrie modelul AI implicit utilizat de agent. +* `responseFormat` (opțional) controlează forma ieșirii agentului. Valoarea implicită este `{ type: 'text' }` pentru text liber. Folosește `{ type: 'json', schema }` pentru a impune ieșire JSON structurată. + +În mod implicit, un agent returnează text liber. Pentru a obține o ieșire structurată, setează `responseFormat` la `{ type: 'json' }` și furnizează `schema`: + +```ts src/agents/structured-agent.ts +import { defineAgent } from 'twenty-sdk/define'; + +export default defineAgent({ + universalIdentifier: 'c4d5e6f7-a8b9-0123-cdef-456789012345', + name: 'lead-scorer', + label: 'Lead Scorer', + prompt: 'Score the lead and explain your reasoning.', + responseFormat: { + type: 'json', + schema: { + type: 'object', + properties: { + score: { type: 'number', description: 'Lead score from 0 to 100' }, + summary: { type: 'string', description: 'Short reasoning for the score' }, + }, + required: ['score', 'summary'], + additionalProperties: false, + }, + }, +}); +``` + +Note despre schemă: +* Schema este un obiect plat: `type` al fiecărei proprietăți trebuie să fie un tip primitiv (`string`, `number` sau `boolean`). Obiectele îmbricate și tablourile nu sunt acceptate. +* `description` (opțional) pe fiecare proprietate ghidează modelul cu privire la ce să pună acolo. +* `required` (opțional) enumeră proprietățile pe care modelul trebuie să le returneze întotdeauna. +* `additionalProperties: false` (opțional) interzice orice proprietate care nu este declarată în `properties`. + + + + +`runAgent()` permite unei funcții logice să ruleze unul dintre agenții aplicației tale (cu abilitățile și instrumentele sale). Identifică agentul prin `universalIdentifier` pe care l-ai transmis către `defineAgent()`: + +```ts src/logic-functions/run-enricher.ts +import { runAgent } from 'twenty-sdk/logic-function'; + +const { result, error, success } = await runAgent({ + agentUniversalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123', + prompt: 'Enrich House Ad : fill empty fields from its listing URL.', +}); +``` + +Puncte cheie: +* Agentul rulează **sincron** și poate citi/actualiza direct înregistrări prin propriile sale instrumente — `runAgent()` este rezolvat după ce rularea se încheie. +* O aplicație poate rula doar propriii săi agenți. +* [Rolul implicit](/l/ro/developers/extend/apps/config/roles) al aplicației trebuie să acorde indicatorul de permisiune `AI` — adaugă `SystemPermissionFlag.AI` la `permissionFlagUniversalIdentifiers` (sau setează `canAccessAllTools: true`). + Fără acesta, `runAgent()` eșuează cu o eroare de permisiune. +* Setează un `timeoutSeconds` generos pentru funcția logică — rulările agentului pot dura câteva secunde. +* `success` este `true` și `result` este nenul când rularea se încheie; în caz de eșec `success` este `false`, `result` este `null`, iar `error` conține motivul (de exemplu, când spațiul de lucru rămâne fără credite AI în timpul rulării). + +```ts src/roles/default-role.ts +import { defineApplicationRole, SystemPermissionFlag } from 'twenty-sdk/define'; + +export default defineApplicationRole({ + universalIdentifier: 'b648f87b-1d26-4961-b974-0908fd991061', + label: 'Default function role', + // runAgent() requires the AI permission flag on the app's default role. + permissionFlagUniversalIdentifiers: [SystemPermissionFlag.AI], +}); +``` + + + **Evită buclele:** dacă apelezi `runAgent()` dintr-un declanșator de tip eveniment de bază de date `*.updated`, iar agentul actualizează aceeași înregistrare, restrânge declanșatorul cu `updatedFields` la un câmp pe care agentul nu îl scrie niciodată (de exemplu, URL-ul sursă) sau verifică dacă vreun câmp țintă este încă gol înainte de a apela `runAgent()`. + diff --git a/packages/twenty-docs/l/ru/developers/extend/apps/config/roles.mdx b/packages/twenty-docs/l/ru/developers/extend/apps/config/roles.mdx index 9d9843590b..9fdb7635ee 100644 --- a/packages/twenty-docs/l/ru/developers/extend/apps/config/roles.mdx +++ b/packages/twenty-docs/l/ru/developers/extend/apps/config/roles.mdx @@ -9,8 +9,8 @@ icon: shield-halved ```ts src/roles/restricted-company-role.ts import { defineRole, - PermissionFlag, STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS, + SystemPermissionFlag, } from 'twenty-sdk/define'; export default defineRole({ @@ -46,7 +46,7 @@ export default defineRole({ canUpdateFieldValue: false, }, ], - permissionFlags: [PermissionFlag.APPLICATIONS], + permissionFlagUniversalIdentifiers: [SystemPermissionFlag.APPLICATIONS], }); ``` @@ -55,7 +55,7 @@ export default defineRole({ Когда вы создаёте новое приложение с помощью шаблона, CLI создаёт файл роли по умолчанию, объявленный с помощью `defineApplicationRole()`: ```ts src/roles/default-role.ts -import { defineApplicationRole, PermissionFlag } from 'twenty-sdk/define'; +import { defineApplicationRole } from 'twenty-sdk/define'; export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER = 'b648f87b-1d26-4961-b974-0908fd991061'; @@ -74,7 +74,7 @@ export default defineApplicationRole({ canBeAssignedToApiKeys: false, objectPermissions: [], fieldPermissions: [], - permissionFlags: [], + permissionFlagUniversalIdentifiers: [], }); ``` @@ -90,5 +90,5 @@ export default defineApplicationRole({ * Начните с сгенерированной роли и постепенно ограничивайте её — роль по умолчанию предоставляет широкий доступ на чтение, что редко подходит для продакшена. * Замените `objectPermissions` и `fieldPermissions` на точные объекты и поля, которые действительно нужны вашим функциям. -* `permissionFlags` управляют доступом к возможностям на уровне платформы. Сведите их к минимуму. +* `permissionFlagUniversalIdentifiers` управляют доступом к возможностям на уровне платформы. Сведите их к минимуму. * См. рабочий пример: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). diff --git a/packages/twenty-docs/l/ru/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/ru/developers/extend/apps/logic/logic-functions.mdx index 2712d17108..8d960e8e6a 100644 --- a/packages/twenty-docs/l/ru/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/ru/developers/extend/apps/logic/logic-functions.mdx @@ -144,6 +144,33 @@ const handler = async (event: RoutePayload) => { Имена заголовков приводятся к нижнему регистру. Обращайтесь к ним, используя ключи в нижнем регистре (например, `event.headers['content-type']`). +#### Пользовательский HTTP-ответ + +По умолчанию возврат простого значения из обработчика отправляет его обратно как ответ `200` (JSON для объектов, `text/plain` для строк). Чтобы управлять статус-кодом и заголовками ответа, верните `Response` из `twenty-sdk/logic-function`: + +```ts +import { Response } from 'twenty-sdk/logic-function'; + +const handler = async (event: RoutePayload) => { + return new Response('

Hello

', { + status: 201, + headers: { 'content-type': 'text/html' }, + }); +}; +``` + +По соображениям безопасности заголовки ответа ограничены списком разрешенных заголовков. Любой заголовок, которого нет в этом списке (например, `Set-Cookie`, CORS-заголовки, такие как `Access-Control-Allow-Origin`, или пользовательские заголовки `X-*`), молчаливо удаляется перед отправкой ответа. Разрешенные заголовки ответа: + +* `content-type` +* `content-language` +* `content-disposition` +* `cache-control` +* `retry-after` + + +Код состояния должен быть допустимым кодом состояния HTTP (в диапазоне от 100 до 599). Имена заголовков ответа сравниваются без учета регистра. + + #### Полезная нагрузка триггера события базы данных Когда триггер события базы данных вызывает вашу функцию логики, она получает по одному `DatabaseEventPayload` на каждую изменённую запись. Полезная нагрузка объединяет метаданные о рабочем пространстве-источнике и объекте с событием на уровне записи. diff --git a/packages/twenty-docs/l/ru/developers/extend/apps/logic/skills-and-agents.mdx b/packages/twenty-docs/l/ru/developers/extend/apps/logic/skills-and-agents.mdx index bf9be23fe4..b7a8c2632a 100644 --- a/packages/twenty-docs/l/ru/developers/extend/apps/logic/skills-and-agents.mdx +++ b/packages/twenty-docs/l/ru/developers/extend/apps/logic/skills-and-agents.mdx @@ -64,6 +64,75 @@ export default defineAgent({ * `description` (необязательно) предоставляет контекст о том, что делает агент. * `icon` (необязательно) задаёт значок, отображаемый в UI. * `modelId` (необязательно) переопределяет модель ИИ по умолчанию, используемую агентом. +* `responseFormat` (необязательно) определяет форму вывода агента. По умолчанию для свободного текста используется `{ type: 'text' }`. Используйте `{ type: 'json', schema }`, чтобы принудительно получать структурированный JSON-вывод. + +По умолчанию агент возвращает свободный текст. Чтобы получить структурированный вывод, установите для `responseFormat` значение `{ type: 'json' }` и укажите `schema`: + +```ts src/agents/structured-agent.ts +import { defineAgent } from 'twenty-sdk/define'; + +export default defineAgent({ + universalIdentifier: 'c4d5e6f7-a8b9-0123-cdef-456789012345', + name: 'lead-scorer', + label: 'Lead Scorer', + prompt: 'Score the lead and explain your reasoning.', + responseFormat: { + type: 'json', + schema: { + type: 'object', + properties: { + score: { type: 'number', description: 'Lead score from 0 to 100' }, + summary: { type: 'string', description: 'Short reasoning for the score' }, + }, + required: ['score', 'summary'], + additionalProperties: false, + }, + }, +}); +``` + +Примечания к схеме: +* Схема — это плоский объект: `type` каждого свойства должен быть примитивом (`string`, `number` или `boolean`). Вложенные объекты и массивы не поддерживаются. +* `description` (необязательно) для каждого свойства подсказывает модели, что туда нужно поместить. +* `required` (необязательно) перечисляет свойства, которые модель всегда должна возвращать. +* `additionalProperties: false` (необязательно) запрещает любые свойства, не объявленные в `properties`. + + + + +`runAgent()` позволяет логической функции запустить одного из агентов вашего приложения (с его навыками и инструментами). Идентифицируйте агента по `universalIdentifier`, который вы передали в `defineAgent()`: + +```ts src/logic-functions/run-enricher.ts +import { runAgent } from 'twenty-sdk/logic-function'; + +const { result, error, success } = await runAgent({ + agentUniversalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123', + prompt: 'Enrich House Ad : fill empty fields from its listing URL.', +}); +``` + +Основные моменты: +* Агент выполняется **синхронно** и может самостоятельно читать и обновлять записи с помощью собственных инструментов — `runAgent()` возвращает результат после завершения выполнения. +* Приложение может запускать только собственных агентов. +* [Роль по умолчанию](/l/ru/developers/extend/apps/config/roles) приложения должна предоставлять флаг разрешения `AI` — добавьте `SystemPermissionFlag.AI` в `permissionFlagUniversalIdentifiers` (или установите `canAccessAllTools: true`). + Без этого `runAgent()` завершится с ошибкой прав доступа. +* Установите достаточно большое значение `timeoutSeconds` для логической функции — выполнение агента может занимать несколько секунд. +* `success` имеет значение `true`, а `result` — не `null`, когда запуск завершается; при ошибке `success` равно `false`, `result` равно `null`, а в `error` содержится причина (например, если в рабочем пространстве закончились AI-кредиты во время запуска). + +```ts src/roles/default-role.ts +import { defineApplicationRole, SystemPermissionFlag } from 'twenty-sdk/define'; + +export default defineApplicationRole({ + universalIdentifier: 'b648f87b-1d26-4961-b974-0908fd991061', + label: 'Default function role', + // runAgent() requires the AI permission flag on the app's default role. + permissionFlagUniversalIdentifiers: [SystemPermissionFlag.AI], +}); +``` + + + **Избегайте циклов:** если вы вызываете `runAgent()` из триггера события базы данных `*.updated`, и агент обновляет ту же запись, ограничьте триггер, указав в `updatedFields` поле, которое агент никогда не изменяет (например, исходный URL), или добавьте проверку, что хотя бы одно целевое поле всё ещё пусто, прежде чем вызывать `runAgent()`. + diff --git a/packages/twenty-docs/l/tr/developers/extend/apps/config/roles.mdx b/packages/twenty-docs/l/tr/developers/extend/apps/config/roles.mdx index 01066d4ff9..06d1f36263 100644 --- a/packages/twenty-docs/l/tr/developers/extend/apps/config/roles.mdx +++ b/packages/twenty-docs/l/tr/developers/extend/apps/config/roles.mdx @@ -9,8 +9,8 @@ Bir **rol**, bir izin kümesidir: bir uygulamanın hangi nesneleri okuyup yazabi ```ts src/roles/restricted-company-role.ts import { defineRole, - PermissionFlag, STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS, + SystemPermissionFlag, } from 'twenty-sdk/define'; export default defineRole({ @@ -46,7 +46,7 @@ export default defineRole({ canUpdateFieldValue: false, }, ], - permissionFlags: [PermissionFlag.APPLICATIONS], + permissionFlagUniversalIdentifiers: [SystemPermissionFlag.APPLICATIONS], }); ``` @@ -55,7 +55,7 @@ export default defineRole({ Yeni bir uygulama iskeleti oluşturduğunuzda, CLI `defineApplicationRole()` ile bildirilen varsayılan bir rol dosyası oluşturur: ```ts src/roles/default-role.ts -import { defineApplicationRole, PermissionFlag } from 'twenty-sdk/define'; +import { defineApplicationRole } from 'twenty-sdk/define'; export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER = 'b648f87b-1d26-4961-b974-0908fd991061'; @@ -74,7 +74,7 @@ export default defineApplicationRole({ canBeAssignedToApiKeys: false, objectPermissions: [], fieldPermissions: [], - permissionFlags: [], + permissionFlagUniversalIdentifiers: [], }); ``` @@ -90,5 +90,5 @@ Notlar: * Oluşturulmuş (scaffolded) rolden başlayın ve ardından giderek kısıtlayın — varsayılan rol geniş okuma erişimi verir; bu ise üretim ortamında nadiren isteyeceğiniz bir şeydir. * `objectPermissions` ve `fieldPermissions` değerlerini, fonksiyonlarınızın gerçekten ihtiyaç duyduğu nesne ve alanlarla değiştirin. -* `permissionFlags`, platform düzeyindeki yeteneklere erişimi kontrol eder. Bunları asgari düzeyde tutun. +* `permissionFlagUniversalIdentifiers`, platform düzeyindeki yeteneklere erişimi kontrol eder. Bunları asgari düzeyde tutun. * Çalışan bir örnek için bkz.: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts). diff --git a/packages/twenty-docs/l/tr/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/tr/developers/extend/apps/logic/logic-functions.mdx index c790d60324..f740eb34dd 100644 --- a/packages/twenty-docs/l/tr/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/tr/developers/extend/apps/logic/logic-functions.mdx @@ -145,6 +145,33 @@ const handler = async (event: RoutePayload) => { Başlık adları küçük harfe normalize edilir. Onlara küçük harfli anahtarlarla erişin (örneğin, `event.headers['content-type']`). +#### Özel HTTP yanıtı + +Varsayılan olarak, işleyicinizden düz bir değer döndürmek, onu `200` yanıtı olarak geri gönderir (nesneler için JSON, stringler için `text/plain`). Durum kodunu ve yanıt üstbilgilerini kontrol etmek için, `twenty-sdk/logic-function` içinden bir `Response` döndürün: + +```ts +import { Response } from 'twenty-sdk/logic-function'; + +const handler = async (event: RoutePayload) => { + return new Response('

Hello

', { + status: 201, + headers: { 'content-type': 'text/html' }, + }); +}; +``` + +Güvenlik nedenleriyle, yanıt üstbilgileri bir izin listesiyle sınırlandırılmıştır. Listede yer almayan herhangi bir üstbilgi (örneğin `Set-Cookie`, `Access-Control-Allow-Origin` gibi CORS üstbilgileri veya özel `X-*` üstbilgileri), yanıt gönderilmeden önce sessizce yok sayılır. İzin verilen yanıt üstbilgileri şunlardır: + +* `content-type` +* `content-language` +* `content-disposition` +* `cache-control` +* `retry-after` + + +Durum kodu geçerli bir HTTP durum kodu olmalıdır (100 ile 599 arasında). Yanıt üstbilgisi adları büyük/küçük harfe duyarsız olarak eşleştirilir. + + #### Veritabanı olay tetikleyicisi yükü Bir veritabanı olay tetikleyicisi mantık fonksiyonunuzu çağırdığında, değişen her kayıt için bir `DatabaseEventPayload` alır. Yük, kaynak çalışma alanı ve nesne hakkındaki üstveriyi, kayıt düzeyindeki olayla birleştirir. diff --git a/packages/twenty-docs/l/tr/developers/extend/apps/logic/skills-and-agents.mdx b/packages/twenty-docs/l/tr/developers/extend/apps/logic/skills-and-agents.mdx index a4141ce8d2..ccf37fc669 100644 --- a/packages/twenty-docs/l/tr/developers/extend/apps/logic/skills-and-agents.mdx +++ b/packages/twenty-docs/l/tr/developers/extend/apps/logic/skills-and-agents.mdx @@ -64,6 +64,75 @@ export default defineAgent({ * `description` (isteğe bağlı), ajanın ne yaptığı hakkında bağlam sağlar. * `icon` (isteğe bağlı), UI'de gösterilen simgeyi ayarlar. * `modelId` (isteğe bağlı), ajanın kullandığı varsayılan yapay zekâ modelini geçersiz kılar. +* `responseFormat` (isteğe bağlı), ajan çıktısının şeklini kontrol eder. Serbest biçimli metin için varsayılan olarak `{ type: 'text' }` kullanılır. Yapılandırılmış JSON çıktısını zorunlu kılmak için `{ type: 'json', schema }` kullanın. + +Varsayılan olarak bir ajan serbest biçimli metin döndürür. Yapılandırılmış çıktı almak için, `responseFormat` değerini `{ type: 'json' }` yapın ve bir `schema` sağlayın: + +```ts src/agents/structured-agent.ts +import { defineAgent } from 'twenty-sdk/define'; + +export default defineAgent({ + universalIdentifier: 'c4d5e6f7-a8b9-0123-cdef-456789012345', + name: 'lead-scorer', + label: 'Lead Scorer', + prompt: 'Score the lead and explain your reasoning.', + responseFormat: { + type: 'json', + schema: { + type: 'object', + properties: { + score: { type: 'number', description: 'Lead score from 0 to 100' }, + summary: { type: 'string', description: 'Short reasoning for the score' }, + }, + required: ['score', 'summary'], + additionalProperties: false, + }, + }, +}); +``` + +Şema notları: +* Şema düz bir nesnedir: her özelliğin `type` değeri, ilkel bir tür (`string`, `number` veya `boolean`) olmalıdır. İç içe nesneler ve diziler desteklenmez. +* Her özellik üzerindeki `description` (isteğe bağlı), modele oraya ne koyması gerektiği konusunda yol gösterir. +* `required` (isteğe bağlı), modelin her zaman döndürmesi gereken özellikleri listeler. +* `additionalProperties: false` (isteğe bağlı), `properties` içinde tanımlanmamış herhangi bir özelliği yasaklar. + + + + +`runAgent()`, bir mantık işlevinin uygulamanızın ajanlarından birini (kendi yetenekleri ve araçlarıyla) çalıştırmasına olanak tanır. Ajanı, `defineAgent()` işlevine ilettiğiniz `universalIdentifier` ile belirleyin: + +```ts src/logic-functions/run-enricher.ts +import { runAgent } from 'twenty-sdk/logic-function'; + +const { result, error, success } = await runAgent({ + agentUniversalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123', + prompt: 'Enrich House Ad : fill empty fields from its listing URL.', +}); +``` + +Önemli noktalar: +* Ajan **senkron** olarak çalışır ve kendi araçları aracılığıyla kayıtları kendisi okuyup/güncelleyebilir — işlem tamamlandığında `runAgent()` çözümlenir. +* Bir uygulama yalnızca kendi ajanlarını çalıştırabilir. +* Uygulamanın [varsayılan rolü](/l/tr/developers/extend/apps/config/roles), `AI` izin bayrağını vermelidir — `permissionFlagUniversalIdentifiers` içine `SystemPermissionFlag.AI` ekleyin (veya `canAccessAllTools: true` olarak ayarlayın). + Bu olmadan, `runAgent()` bir izin hatasıyla başarısız olur. +* Mantık işlevi için cömert bir `timeoutSeconds` değeri ayarlayın — ajan çalışmaları birkaç saniye sürebilir. +* Çalışma tamamlandığında `success` değeri `true` olur ve `result` boş olmayan bir değerdir; başarısızlık durumunda `success` değeri `false` olur, `result` değeri `null` olur ve `error` nedenini tutar (örneğin, çalışma ortasında çalışma alanının AI kredileri bittiğinde). + +```ts src/roles/default-role.ts +import { defineApplicationRole, SystemPermissionFlag } from 'twenty-sdk/define'; + +export default defineApplicationRole({ + universalIdentifier: 'b648f87b-1d26-4961-b974-0908fd991061', + label: 'Default function role', + // runAgent() requires the AI permission flag on the app's default role. + permissionFlagUniversalIdentifiers: [SystemPermissionFlag.AI], +}); +``` + + + **Döngülerden kaçının:** Bir `*.updated` veritabanı olayı tetikleyicisinden `runAgent()` çağırırsanız ve ajan aynı kaydı güncelliyorsa, tetikleyiciyi, ajan tarafından asla yazılmayan bir alana (örneğin kaynak URL) göre `updatedFields` ile kapsamlandırın veya `runAgent()` çağırmadan önce herhangi bir hedef alanın hâlâ boş olup olmadığına göre koruma ekleyin. + diff --git a/packages/twenty-docs/l/zh/developers/extend/apps/config/roles.mdx b/packages/twenty-docs/l/zh/developers/extend/apps/config/roles.mdx index 379df0b319..17384006b5 100644 --- a/packages/twenty-docs/l/zh/developers/extend/apps/config/roles.mdx +++ b/packages/twenty-docs/l/zh/developers/extend/apps/config/roles.mdx @@ -9,8 +9,8 @@ icon: shield-halved ```ts src/roles/restricted-company-role.ts import { defineRole, - PermissionFlag, STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS, + SystemPermissionFlag, } from 'twenty-sdk/define'; export default defineRole({ @@ -46,7 +46,7 @@ export default defineRole({ canUpdateFieldValue: false, }, ], - permissionFlags: [PermissionFlag.APPLICATIONS], + permissionFlagUniversalIdentifiers: [SystemPermissionFlag.APPLICATIONS], }); ``` @@ -55,7 +55,7 @@ export default defineRole({ 当你使用脚手架创建新应用时,CLI 会创建一个使用 `defineApplicationRole()` 声明的默认角色文件: ```ts src/roles/default-role.ts -import { defineApplicationRole, PermissionFlag } from 'twenty-sdk/define'; +import { defineApplicationRole } from 'twenty-sdk/define'; export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER = 'b648f87b-1d26-4961-b974-0908fd991061'; @@ -74,7 +74,7 @@ export default defineApplicationRole({ canBeAssignedToApiKeys: false, objectPermissions: [], fieldPermissions: [], - permissionFlags: [], + permissionFlagUniversalIdentifiers: [], }); ``` @@ -90,5 +90,5 @@ export default defineApplicationRole({ * 从脚手架生成的角色开始,然后逐步收紧它的权限——默认角色授予广泛的读取访问权限,而这在生产环境中很少是你想要的。 * 将 `objectPermissions` 和 `fieldPermissions` 替换为你的函数实际需要的精确对象和字段。 -* `permissionFlags` 控制对平台级能力的访问。 尽量保持最小化。 +* `permissionFlagUniversalIdentifiers` 控制对平台级能力的访问。 尽量保持最小化。 * 查看一个可运行示例:[`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts)。 diff --git a/packages/twenty-docs/l/zh/developers/extend/apps/logic/logic-functions.mdx b/packages/twenty-docs/l/zh/developers/extend/apps/logic/logic-functions.mdx index af524c96ab..8aa82a6036 100644 --- a/packages/twenty-docs/l/zh/developers/extend/apps/logic/logic-functions.mdx +++ b/packages/twenty-docs/l/zh/developers/extend/apps/logic/logic-functions.mdx @@ -145,6 +145,33 @@ const handler = async (event: RoutePayload) => { 请求头名称会被规范化为小写。 请使用小写键访问它们(例如,`event.headers['content-type']`)。 +#### 自定义 HTTP 响应 + +默认情况下,从处理程序返回一个普通值会以 `200` 响应返回该值(对象为 JSON,字符串为 `text/plain`)。 要控制状态码和响应头,请从 `twenty-sdk/logic-function` 返回一个 `Response`: + +```ts +import { Response } from 'twenty-sdk/logic-function'; + +const handler = async (event: RoutePayload) => { + return new Response('

Hello

', { + status: 201, + headers: { 'content-type': 'text/html' }, + }); +}; +``` + +出于安全原因,响应头被限制在一个允许列表中。 任何不在该列表中的响应头(例如 `Set-Cookie`、CORS 响应头(如 `Access-Control-Allow-Origin`),或自定义的 `X-*` 响应头)都会在发送响应之前被静默丢弃。 允许的响应头包括: + +* `content-type` +* `content-language` +* `content-disposition` +* `cache-control` +* `retry-after` + + +状态码必须是有效的 HTTP 状态码(介于 100 和 599 之间)。 响应头名称的匹配不区分大小写。 + + #### 数据库事件触发器有效负载 当数据库事件触发器调用你的逻辑函数时,每条被更改的记录都会对应一个 `DatabaseEventPayload`。 该负载将关于源工作区和对象的元数据与记录级事件组合在一起。 diff --git a/packages/twenty-docs/l/zh/developers/extend/apps/logic/skills-and-agents.mdx b/packages/twenty-docs/l/zh/developers/extend/apps/logic/skills-and-agents.mdx index c904bfd334..fd02916ac5 100644 --- a/packages/twenty-docs/l/zh/developers/extend/apps/logic/skills-and-agents.mdx +++ b/packages/twenty-docs/l/zh/developers/extend/apps/logic/skills-and-agents.mdx @@ -64,6 +64,75 @@ export default defineAgent({ * `description`(可选)提供有关智能体功能的上下文。 * `icon`(可选)设置在 UI 中显示的图标。 * `modelId`(可选)会覆盖该智能体使用的默认 AI 模型。 +* `responseFormat`(可选)控制代理输出的结构形式。 对于自由格式文本,默认值为 `{ type: 'text' }`。 使用 `{ type: 'json', schema }` 来强制生成结构化 JSON 输出。 + +默认情况下,代理返回自由格式文本。 要获取结构化输出,将 `responseFormat` 设置为 `{ type: 'json' }`,并提供一个 `schema`: + +```ts src/agents/structured-agent.ts +import { defineAgent } from 'twenty-sdk/define'; + +export default defineAgent({ + universalIdentifier: 'c4d5e6f7-a8b9-0123-cdef-456789012345', + name: 'lead-scorer', + label: 'Lead Scorer', + prompt: 'Score the lead and explain your reasoning.', + responseFormat: { + type: 'json', + schema: { + type: 'object', + properties: { + score: { type: 'number', description: 'Lead score from 0 to 100' }, + summary: { type: 'string', description: 'Short reasoning for the score' }, + }, + required: ['score', 'summary'], + additionalProperties: false, + }, + }, +}); +``` + +架构说明: +* 该架构是一个扁平对象:每个属性的 `type` 必须是原始类型(`string`、`number` 或 `boolean`)。 不支持嵌套对象和数组。 +* 每个属性上的 `description`(可选)用于引导模型应在此处填入什么内容。 +* `required`(可选)列出模型必须始终返回的属性。 +* `additionalProperties: false`(可选)禁止任何未在 `properties` 中声明的属性。 + + + + +`runAgent()` 允许逻辑函数运行你的应用的某个代理(及其技能和工具)。 通过你传递给 `defineAgent()` 的 `universalIdentifier` 来标识该代理: + +```ts src/logic-functions/run-enricher.ts +import { runAgent } from 'twenty-sdk/logic-function'; + +const { result, error, success } = await runAgent({ + agentUniversalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123', + prompt: 'Enrich House Ad : fill empty fields from its listing URL.', +}); +``` + +关键点: +* 代理以**同步**方式运行,并且可以通过其自身的工具读取/更新记录 —— `runAgent()` 会在运行完成后才 resolve。 +* 一个应用只能运行它自己的代理。 +* 应用的[默认角色](/l/zh/developers/extend/apps/config/roles)必须授予 `AI` 权限标记 —— 在其 `permissionFlagUniversalIdentifiers` 中添加 `SystemPermissionFlag.AI`(或设置 `canAccessAllTools: true`)。 + 否则,`runAgent()` 会因权限错误而失败。 +* 在逻辑函数上设置较大的 `timeoutSeconds` 值 —— 代理运行可能需要数秒时间。 +* 当运行完成时,`success` 为 `true` 且 `result` 为非空;失败时,`success` 为 `false`,`result` 为 `null`,并且 `error` 保存失败原因(例如,当工作区在运行过程中耗尽 AI 额度时)。 + +```ts src/roles/default-role.ts +import { defineApplicationRole, SystemPermissionFlag } from 'twenty-sdk/define'; + +export default defineApplicationRole({ + universalIdentifier: 'b648f87b-1d26-4961-b974-0908fd991061', + label: 'Default function role', + // runAgent() requires the AI permission flag on the app's default role. + permissionFlagUniversalIdentifiers: [SystemPermissionFlag.AI], +}); +``` + + + \*\*避免循环:\*\*如果你从 `*.updated` 数据库事件触发器中调用 `runAgent()`,而代理又会更新同一条记录,请将触发器的 `updatedFields` 限定为代理永远不会写入的字段(例如来源 URL),或者在调用 `runAgent()` 之前检查任何目标字段是否仍为空。 +