Spirit Agent
Herunterladen

Erweiterungen

Paketstruktur, spiritExtension-Felder, Aktivierungs-API und Auflistung im offiziellen Registry.

Eine Erweiterung ist ein Ordner mit einer package.json, die das Feld spiritExtension enthält. Spirit installiert sie pro Benutzer und pro Host, nicht im .spirit/-Verzeichnis des Workspaces.

HostPfad
Desktop{spiritDataDir}/extensions/desktop/
CLI{spiritDataDir}/extensions/cli/

Das unterscheidet sich von Skills (SKILL.md-Ordner), MCP (externe Server) und Hooks (hooks.json-Skripte). contributes.cli.hooks gestaltet die CLI-TUI-Slots. Das ist nicht hooks.json.

Es gibt keinen pro Erweiterung deaktivierbaren Schalter. Nach der Installation trägt die Erweiterung bei. Der Schalter im CLI-Panel ist ein Platzhalter.

Paketstruktur

example-extension/
  package.json
  dist/index.js
  assets/icon.svg
  styles/desktop.css
  cli-hooks.json
{
  "name": "@example/spirit-extension",
  "version": "0.1.0",
  "description": "Example Spirit Agent extension.",
  "author": { "name": "example" },
  "homepage": "https://example.com/spirit-extension",
  "main": "dist/index.js",
  "spiritExtension": {
    "schemaVersion": 1,
    "displayName": "Example extension",
    "icon": "assets/icon.svg",
    "supportedHosts": ["cli", "desktop"],
    "activationEvents": ["onStartup", "onUserMessage"],
    "requestedCapabilities": [
      "tool-definitions",
      "tool-execution",
      "system-prompt",
      "settings",
      "secret-storage",
      "desktop-ui",
      "cli-ui"
    ],
    "contributes": {
      "tools": [
        {
          "name": "lookup_item",
          "description": "Look up an item by id.",
          "inputSchema": {
            "type": "object",
            "properties": {
              "id": { "type": "string" }
            },
            "required": ["id"]
          },
          "approvalMode": "allowed",
          "executionMode": "foreground"
        }
      ],
      "desktop": {
        "css": [{ "path": "styles/desktop.css" }],
        "settingsPage": { "title": "Example extension" }
      },
      "cli": {
        "hooks": { "path": "cli-hooks.json" }
      }
    },
    "settingsSchema": [
      {
        "key": "region",
        "type": "select",
        "title": "Region",
        "required": true,
        "defaultValue": "us",
        "options": [
          { "value": "us", "label": "US" },
          { "value": "eu", "label": "EU" }
        ]
      }
    ],
    "secretSlots": [
      {
        "key": "api_token",
        "title": "API token",
        "required": true
      }
    ]
  }
}

Der name in der package.json ist die Erweiterungs-ID. Er muss dem Muster ^(?:@[a-z0-9][a-z0-9._-]*/)?[a-z0-9][a-z0-9._-]*$ entsprechen.

Felder der package.json

FeldBeschreibung
nameErforderlich. npm-Paketname; wird als Erweiterungs-ID verwendet
versionErforderlich. Versionszeichenfolge
spiritExtensionErforderlich. Objekt. Siehe unten
descriptionOptional. Zeichenfolge
authorOptional. Zeichenfolge oder { name }
homepageOptional. Zeichenfolge
mainOptional. Relativer Pfad zum activate-Einstiegspunkt. Erforderlich, wenn die Erweiterung activationEvents, Werkzeugausführung oder einen Systemprompt verwendet

main, spiritExtension.icon, CSS-Pfade und CLI-Hook-Pfade müssen relativ sein und innerhalb des Pakets bleiben.

spiritExtension

FeldBeschreibung
schemaVersionOptional. Standardwert: 1. Nur 1 wird unterstützt
displayNameErforderlich. Sichtbarer Name
iconOptional. Pfad relativ zum Paketstamm
supportedHostsErforderlich. Nicht leeres Array mit cli und/oder desktop
activationEventsOptional. Siehe Aktivierungsereignisse
requestedCapabilitiesOptional. Siehe Fähigkeiten
contributesOptional. tools, desktop und/oder cli
settingsSchemaOptional. Definitionen von Einstellungen
secretSlotsOptional. Definitionen von Geheimnis-Slots

Fähigkeiten

WertLaufzeit
tool-definitionsErforderlich mit tool-execution, um contributes.tools für das Modell bereitzustellen
tool-executionErforderlich mit tool-definitions, um diese Werkzeuge auszuführen
system-promptErforderlich mit main, um einen Systemprompt-Fragment beizutragen
desktop-uiMuss mit contributes.desktop gepaart sein
cli-uiMuss mit contributes.cli gepaart sein
approval-flowNur deklariert. Die Genehmigung wird durch den approvalMode jedes Tools gesteuert
questions-flowNur deklariert. Fragen werden durch approvalMode: need-questions gesteuert
settingsNur deklariert. Einstellungen kommen aus settingsSchema
secret-storageWird mit secretSlots verwendet
structured-resultsNur deklariert

desktop-ui / cli-ui und der passende contributes-Block müssen entweder beide vorhanden oder beide nicht vorhanden sein.

Aktivierungsereignisse

EreignisWann es ausgelöst wird
onStartupHost-Aufwärmphase
onExtensionInstalledNach ZIP- oder Marketplace-Installation
onSessionOpenedSitzung wird aktiv
onSessionResetSitzung wird zurückgesetzt
onUserMessageBenutzer sendet eine Nachricht
onToolCallEin Tool wird gleich ausgeführt
onToolResultEin Tool-Ergebnis ist verfügbar
onApprovalResolvedEine Genehmigungsentscheidung ist aufgelöst

Der Host ruft activate auf, wenn die Erweiterung das Ereignis auflistet und eine lesbare main hat.

contributes.tools

FeldBeschreibung
nameErforderlich. [a-z0-9]+(?:[._-][a-z0-9]+)*
descriptionErforderlich. Wird dem Modell angezeigt
inputSchemaErforderlich. JSON-Schema-Objekt
outputSchemaOptional. JSON-Schema-Objekt
approvalModeOptional. allowed, need-approval oder need-questions
executionModeOptional. foreground oder background

Das Modell sieht name nicht unverändert. Der Host erstellt einen Aufrufnamen wie extension__{id}__{tool}__{hash}.

contributes.desktop

Erfordert desktop-ui.

FeldBeschreibung
css[].pathErforderlich. CSS-Datei relativ zum Paketstamm
css[].mediaOptional. CSS-Medienabfrage
settingsPageOptional. true, {} oder { title } – fügt einen Desktop-Einstellungseintrag hinzu

contributes.cli

Erfordert cli-ui. hooks ist ein Objekt mit path, kein Inline-Array:

{
  "hooks": { "path": "cli-hooks.json" }
}

Die Datei muss { "hooks": [ ... ] } sein.

FeldBeschreibung
slotErforderlich. Einer der folgenden Slots
variantOptional. default, accented, muted, warning, success, danger
tokensOptional. { foreground?, border?, accent? }
prefixOptional. String
suffixOptional. String

Slots: message.user, message.assistant, message.tool, assistant.thinking, input.frame, bottom_form, bottom_form.section, slash_suggestions, approval.panel, questions.panel.

Token-Rollen: default, primary, secondary, muted, accent, success, warning, danger.

{
  "hooks": [
    {
      "slot": "input.frame",
      "variant": "accented",
      "tokens": { "border": "accent" },
      "prefix": "[",
      "suffix": "]"
    }
  ]
}

settingsSchema

FeldBeschreibung
keyErforderlich. Gleiches Muster wie Tool-Namen
typeErforderlich. string, boolean, number oder select
titleErforderlich. UI-Label
descriptionOptional
placeholderOptional
requiredOptional. Boolean
defaultValueOptional. Muss mit type übereinstimmen
optionsErforderlich für select. Array von { value, label, description? }

Werte sind string, number, boolean oder null. null löscht eine nicht erforderliche Einstellung.

secretSlots

FeldBeschreibung
keyErforderlich
titleErforderlich
descriptionOptional
requiredOptional. Boolean

Desktop speichert Geheimnisse im OS-Keyring. Beim CLI-Daemon-Pfad sind secrets.set / secrets.delete möglicherweise nicht verfügbar.

activate

main wird mit dynamischem import geladen. Exportieren Sie eines von:

  • export function activate(ctx) { ... }
  • export default function activate(ctx) { ... }
  • export default { activate }

ctx

FeldBeschreibung
extension{ id, name, version, directoryPath, manifestPath, main }
hostHost-API. Desktop implementiert showMessageBox. CLI ist {}
log(message: string) => void
settingsget(key), getAll(), set(key, value), setAll(values)
secretsget(key), has(key), set(key, value), delete(key) — Schlüssel müssen in secretSlots deklariert sein
activationEventOptional. { type, detail? }

Rückgabewert

Geben Sie ein Objekt zurück oder exportieren Sie dieselben Felder aus dem Modul.

FeldBeschreibung
toolsRecord<string, (ctx) => unknown>. Schlüssel sind Manifest-Toolnamen
invokeTool(ctx) => unknown. Wird anstelle von tools[name] verwendet, wenn vorhanden
systemPromptStatisches Systemfragment
getSystemPrompt() => string | Promise<string>. Wird anstelle von systemPrompt verwendet, wenn vorhanden
onEvent(event) => void
dispose() => void. Wird beim Entfernen oder Neuladen aufgerufen

Tool-Handler ctx

FeldBeschreibung
extensionGleiche Laufzeitinformationen wie activate
hostGleiche Host-API
toolNameManifest-Toolname
argumentsObjekt vom Modell
logGleicher Logger
settingsGleicher Settings-Zugriff
secretsGleicher Secrets-Zugriff
toolCallIdOptional
questionsResultOptional. Festgelegt, wenn approvalMode need-questions ist

Ein string-Ergebnis wird durchgereicht. Andere Werte werden JSON.stringify(value, null, 2). undefined wird zu "".

Desktop host.showMessageBox

FeldBeschreibung
titleErforderlich. Zeichenkette
messageErforderlich. Zeichenkette
detailOptional. Zeichenkette
buttonsOptional. Zeichenkettenarray
cancelIdOptional. Zahl
defaultIdOptional. Zahl
noLinkOptional. Boolesch
typeOptional. none, info, error, question, warning
export function activate(ctx) {
  return {
    systemPrompt: "Use lookup_item when the user asks for an item by id.",
    async invokeTool({ toolName, arguments: args, settings, secrets }) {
      if (toolName !== "lookup_item") {
        throw new Error(`Unknown tool: ${toolName}`);
      }
      const region = await settings.get("region");
      const token = await secrets.get("api_token");
      return { id: args.id, region, hasToken: Boolean(token) };
    },
    dispose() {
      ctx.log("example-extension disposed");
    },
  };
}

Installation

  • ZIP — Das Archiv muss genau eine package.json enthalten (sie darf in einem Unterverzeichnis liegen). Importieren Sie mit spirit extension import ./extension.zip oder über Einstellungen → Erweiterungen.
  • Marktplatz-Tarball — Das Archivstammverzeichnis muss ein package/-Verzeichnis enthalten.

supportedHosts muss den aktuellen Host enthalten. Eine zweite Installation derselben ID ersetzt standardmäßig nicht die vorhandene Kopie. Siehe Marktplatz für Kanäle und die Installationsoberfläche.

Im offiziellen Registry veröffentlichen

Das SpiritAgents/registry-Repository ist ein Marktplatzindex. Es hostet keine Erweiterungsquellen, dist, ZIP-Dateien oder Tarballs.

Führen Sie diese Schritte in der angegebenen Reihenfolge aus:

  1. Veröffentlichen Sie ein öffentliches npm-Paket.
  2. Erstellen Sie einen Pull-Request, der dieses Paket auflistet.

1. Veröffentlichen Sie das npm-Paket

Das veröffentlichte package.json ist die Quelle der Wahrheit, insbesondere spiritExtension. Der Registry-Builder erfordert:

  • spiritExtension.schemaVersion
  • spiritExtension.displayName
  • spiritExtension.supportedHosts
  • spiritExtension.requestedCapabilities

Es liest auch name, version, description, author, repository, homepage, keywords und optional spiritExtension.icon. Wenn Sie icon festlegen, fügen Sie diese Datei in das veröffentlichte Paket ein. Ein fehlendes spiritExtension-Objekt führt dazu, dass der Registry-Build für diese Version fehlschlägt.

Offizielles Beispiel: @spiritagent/extension-system-message-demo (spiritagent.system-message-demo).

2. Paket auflisten

Erstellen Sie registry/extensions/<extension-id>/ mit:

DateiBeschreibung
entry.jsonMarktplatz-Governance
README.mdMarktplatz-Detailtexte

Bearbeiten Sie diese nicht von Hand (generieren Sie sie neu):

  • registry/catalog.json
  • registry/extensions/<extension-id>/detail.json

extensionId benötigt mindestens zwei durch Punkte getrennte Segmente, Kleinbuchstaben und Ziffern, mit Punkten oder Bindestrichen innerhalb eines Segments. Beispiele: spiritagent.system-message-demo, yourteam.some-extension. packageName und extensionId müssen im Repository eindeutig sein.

entry.json

FeldBeschreibung
schemaVersionErforderlich. 1
extensionIdErforderlich. Siehe die obigen Regeln
packageNameErforderlich. npm-Paketname
statusErforderlich. listed, hidden, deprecated oder blocked
featuredErforderlich. Boolescher Wert
defaultVersionErforderlich. Standardversionszeichenfolge
defaultReviewStatusErforderlich. unverified, verified oder revoked
versionsErforderlich. Mindestens ein Element

Jedes versions[]-Element:

FeldBeschreibung
versionErforderlich
channelErforderlich. stable, preview oder experimental
reviewStatusErforderlich. unverified, verified oder revoked
changelogOptional. { summary, body } – beide erforderlich, wenn vorhanden
{
  "schemaVersion": 1,
  "extensionId": "example.spirit-extension",
  "packageName": "@example/spirit-extension",
  "status": "listed",
  "featured": false,
  "defaultVersion": "0.1.0",
  "defaultReviewStatus": "unverified",
  "versions": [
    {
      "version": "0.1.0",
      "channel": "stable",
      "reviewStatus": "unverified",
      "changelog": {
        "summary": "Initial public release.",
        "body": "- Initial public release."
      }
    }
  ]
}

Die Marktplatz-README sollte abdecken, was die Erweiterung tut, den Paketnamen, die standardmäßig genehmigte Version, die Kompatibilität von Host und Fähigkeiten sowie Hinweise für Marktplatz-Leser.

Generierte abgeleitete Dateien lokal neu erzeugen:

./scripts/build-registry.ps1

Das Skript ruft die npm-Metadaten für die aufgeführten Versionen ab, baut catalog.json und jede detail.json neu auf und validiert dann die Konsistenz.

Pull request

Fügen Sie entry.json, die Marktplatz-README.md sowie das neu generierte catalog.json / detail.json hinzu. Listen Sie nur Versionen auf, die bereits öffentlich auf npm verfügbar sind. Setzen Sie reviewStatus und channel genau. Neue Versionen starten typischerweise als unverified.

Committen Sie keine Extension-Source-Trees, dist, ZIP-Dateien, Tarballs oder andere Binärartefakte.

Das Eröffnen eines Pull Requests garantiert keine Auflistung. Die Überprüfung kann Änderungen anfordern, bevor eine Version genehmigt oder verifiziert wird.