GenHTTP Lambda

So funktioniert es

Sie schreiben ein C#-Snippet. Was es zurückgibt, ist in wenigen Sekunden unter einer öffentlichen HTTPS-Adresse erreichbar. Hier steht alles Wichtige – in der Reihenfolge, in der Sie es brauchen.

Was ein Lambda ist

Ein Lambda ist ein Snippet, das einen GenHTTP-Handler zurückgibt. Die Plattform kompiliert es, lädt es und hängt das Ergebnis unter Ihrer eigenen Adresse ein. Kein Projekt, keine Build-Datei, keine using-Anweisungen: Alle GenHTTP-Module sind schon importiert.

return Content.From(Resource.FromString("hello"));

Das ist bereits ein vollständiges Lambda. Unter /lambda/your-key/ deployt, beantwortet es jeden Request mit „hello“.

Das Snippet besteht aus Anweisungen, nicht aus einer Klasse. Zum Schluss gibt es etwas zurück, das Requests beantworten kann: einen Handler oder einen Builder dafür.

Ihr erstes Lambda

  1. 1
    Klicken Sie auf Lambda erstellen. Sie bekommen eine öffentliche Adresse und einen Editor-Schlüssel. Der Schlüssel ist der einzige Weg zurück – heben Sie ihn auf. Niemand kann ihn für Sie wiederherstellen.
  2. 2
    Sie landen im Kontrollzentrum. Als erste Version ist schon ein kleiner REST-Dienst angelegt – nur als Startpunkt.
  3. 3
    Geben Sie den Editor-Schlüssel einem Agenten und sagen Sie ihm, was er bauen soll – er schreibt über MCP neue Versionen. Oder öffnen Sie Code und schreiben Sie selbst: Prüfen kompiliert, ohne etwas zu speichern, und zeigt die Meldungen des Compilers mit Datei und Zeile.
  4. 4
    Klicken Sie auf Deployen. Jetzt ist es online – vorher ist nichts erreichbar. Jedes weitere Deployment verlängert, wie lange es online bleibt.

Das Kontrollzentrum

Der Editor-Link öffnet ein Kontrollzentrum, kein Textfeld. Den meisten Code schreiben hier Agenten, also sehen Sie zuerst, wie es Ihrem Lambda geht. Die Seitenleiste zeigt, ob das Lambda online ist, seine Adresse und seine Bereiche. Wartet eine neuere Version darauf, online zu gehen, erscheint dort ein Button. Was Sie selten brauchen, etwa die Adresse ändern oder das Lambda löschen, steckt im Menü ⋯.

Übersicht
Was die App ist, ob sie online ist, wie viele Requests sie heute hatte und wie viele davon fehlschlugen, die letzte Änderung und wie viel Platz noch frei ist.
Dokumentation
Was die App ist, für wen sie gedacht ist und warum, und warum sie so gebaut ist, wie sie ist – von Agenten geschrieben, mit jeder Version gespeichert.
Ändern
Sagen Sie, was anders sein soll, und der Agent auf diesem Server setzt es um, während Sie zusehen. Er probiert die Änderung in einem Entwurf aus – einer Kopie mit eigener Adresse – und stellt sie online, sobald sie funktioniert. Schalten Sie Nach Abschluss online stellen aus, um den Entwurf zuerst selbst auszuprobieren. Er arbeitet nur an Ihrer App: Eine Bitte, die nichts mit ihr zu tun hat oder Schaden anrichten soll, lehnt er ab und sagt, warum.
Entwürfe
Änderungen, die ausprobiert werden, bevor sie online gehen, jede unter einer eigenen Adresse und mit eigenen Testdaten. Geöffnet hat ein Entwurf eigenen Code, eigene Testdaten und eigene Logs. Der Bereich erscheint, sobald es einen Entwurf gibt.
Dateien
Die Dateien einer Version: Code und Assets, das Programm selbst. Ein Schloss oder ein Globus zeigt, ob sie öffentlich erreichbar sind.
Daten
Was das Lambda zur Laufzeit aufbewahrt, für alle Versionen gemeinsam: die Datenbank, der Workspace und die Secrets, jeweils mit eigenem Reiter. In Tabellen und Dateien hineinsehen, Dateien hochladen, Secrets setzen oder eine Art ein- und ausschalten. Die einfache Ansicht zeigt den Bereich, sobald die App etwas aufbewahrt.
Versionen
Was jede Version geändert hat, worum gebeten wurde und der Diff zur vorherigen. Von hier aus deployen oder zurückrollen – oder aus jeder von ihnen einen Entwurf beginnen.
Deployments
Was wann online war und warum es offline ging.
Statistik
Requests, Fehler, Antwortzeiten und die meistgefragten Pfade der letzten Stunde oder des letzten Tages.
Logs
Requests, Ausgaben und Stacktraces von allem, was schiefging – live.
Code
Selbst schreiben. Prüfen kompiliert, Speichern legt eine Version an, Deployen stellt sie online. In einem Entwurf behält Speichern den Code im Entwurf und zeigt ihn unter der Adresse des Entwurfs. Strg+S speichert, F12 springt zur Deklaration.
Tests
Wie die App automatisch getestet wird, mit den Scripts und Testdaten dafür. Nur in der vollständigen Ansicht.

Alle Bereiche funktionieren gleich: oben der Titel, ein ⓘ mit Erklärung, rechts die Aktionen und – wo es mehrere Ansichten gibt – darunter eine Reihe von Tabs. Beim Code sind die Tabs seine Dateien. Die vollständige Ansicht fasst die Bereiche in Gruppen zusammen: wie Leute es finden, wo eine Änderung entsteht, das Programm und seine Daten und wie es läuft.

Traffic und Log liegen im Arbeitsspeicher. Sie sind zum Beobachten da, nicht zum Aufbewahren: Nach einem Neustart des Servers beginnen sie von vorn. Versionen und der Deployment-Verlauf werden gespeichert.

Das Warum festhalten

Eine Version ist der Code plus zwei optionale Notizen: die Spezifikation – was der Nutzer möchte und warum, möglichst in seinen Worten – und die Änderung, eine Zeile dazu, was die Version tut. Beide stehen im Versionsverlauf neben dem Diff. So bleibt das Warum neben dem Was erhalten – für Sie und für den nächsten Agenten, der den Verlauf liest, bevor er etwas ändert.

POST /api/v1/lambdas/{editorKey}/versions
{
  "files": [ { "name": "lambda.cs", "code": "..." } ],
  "specification": "Ein Gästebuch zum Eintragen; Einträge müssen einen Neustart überstehen",
  "change": "Speichert Einträge in der Datenbank, damit sie einen Neustart überstehen"
}

Agenten übergeben dieselben beiden Felder an write_code. Unter Code wird beim Speichern nach der Änderung gefragt. Beides ist optional. Zu lange Texte werden gekürzt statt abgelehnt: die Spezifikation nach 4000 Zeichen, die Änderung nach 500. Ein Entwurf hat seine eigenen beiden; wird er übernommen, gehen sie an die neue Version über.

Dokumentation und Tests

Jede Version bewahrt neben ihrem Programm auf, was über sie geschrieben ist: ihre Dokumentation – was die App ist, für wen sie gedacht ist und warum, und warum sie so gebaut ist, wie sie ist – und ihre Tests: wie sich automatisch prüfen lässt, dass sie funktioniert, mit den Scripts und Testdaten dafür. Agenten schreiben beides mit einem neuen Lambda und halten es mit jeder Änderung aktuell. Der nächste Agent, der das Lambda ändert, liest es zuerst – so weiß er, wofür die App da ist und was weiter funktionieren muss. Das sagt der Code allein nicht.

.lambda/docs/product.md
was die App ist, für wen sie gedacht ist, was Leute damit tun und warum
.lambda/docs/decisions.md
die technischen Entscheidungen und warum sie getroffen wurden
.lambda/tests/README.md
wie die App automatisch getestet wird und wie die Tests ausgeführt werden
.lambda/tests/…
die Scripts und Testdaten, die die Tests verwenden

Sie sind Dateien der Version wie alle anderen, im Ordner .lambda: Der Verlauf zeigt, was eine Version daran geändert hat, Zurückrollen bringt die Dokumentation zurück, die für diese Version galt, und ein Entwurf hat eine eigene Kopie, die mit ihm online geht. Sie werden nie kompiliert und nie ausgeliefert und zählen zu dem, was die Assets einer Version umfassen dürfen.

Im Kontrollzentrum zeigt Dokumentation die Seiten zum Lesen und Tests, wie die App getestet wird, samt den Dateien daneben; die Version wählen Sie wie bei ihren Dateien. Eine Seite lässt sich dort auch bearbeiten – das speichert die nächste Version. Die einfache Ansicht nennt die Dokumentation Über die App und zeigt nur, wofür die App da ist. Um das zu korrigieren, sagen Sie es dem Agenten.

Sie sind in der Sprache geschrieben, in der Sie mit dem Agenten sprechen – für den, der die App als Nächstes ändert, ob Mensch oder Agent. Keine Kopie des Codes, sondern wofür die App da ist und warum.

Gefahrlos ändern

Eine Version ändert sich nie mehr, sobald sie gespeichert ist – und genau deshalb lohnt es sich, jede aufzuheben: Jede lässt sich vergleichen und genau so wieder online stellen, wie sie war. Um ein Lambda zu ändern, das Leute nutzen, beginnen Sie stattdessen einen Entwurf.

  1. 1
    Beginnen Sie ihn aus einer beliebigen Version unter Versionen, oder lassen Sie den Agenten einen beginnen. Er ist eine Kopie von Code, Assets, Dokumentation und Tests dieser Version und der Daten des Lambdas.
  2. 2
    Ändern Sie ihn so oft wie nötig – unter Code oder indem Sie den Agenten darum bitten. Seine Vorschau antwortet unter einer eigenen Adresse, /features/…/, mit eigenen Testdaten. Besucher des Lambdas sehen nichts davon, und nichts, was er schreibt, erreicht die Daten des Lambdas.
  3. 3
    Klicken Sie auf Online stellen, sobald alles passt: Der Entwurf wird zur nächsten Version, mit seinen Notizen, und geht online. Dabei verschwindet er – samt seiner Vorschau und seinen Testdaten.
POST /api/v1/lambdas/{editorKey}/features
{ "name": "Bestenliste" }

PUT  /api/v1/lambdas/{editorKey}/features/{feature}/files?deploy=true
POST /api/v1/lambdas/{editorKey}/features/{feature}/merge
{ "deploy": true }

An mehreren Entwürfen kann gleichzeitig gearbeitet werden. Nur ein Entwurf, der auf dem neuesten Stand der Version ist, kann online gehen – damit er nie eine Version rückgängig macht, die nach seinem Beginn gespeichert wurde. Ging zuerst ein anderer online, holen Sie dessen Änderungen herein – oder bitten Sie den Agenten darum – und markieren Sie den Entwurf als aktuell. Nichts geht von selbst online; das ist Absicht. Die API nennt einen Entwurf „feature“ und das Online-Stellen „merge“.

Mehrere Dateien

Typen müssen nicht unter dem Code stehen, der sie nutzt. Klicken Sie unter Code neben den Dateien auf +: Die neue Datei wird zusammen mit dem Snippet im selben Namespace kompiliert, also müssen Sie nichts importieren. Ein Name ohne Endung gilt als C#.

lambda.cs
var shelf = new Shelf();

return Inline.Create()
             .Get(() => shelf.All())
             .Post((Book book) => shelf.Add(book));
Shelf.cs
public sealed class Shelf
{
    private readonly List<Book> _books = [];

    public IEnumerable<Book> All() => _books;

    public Book Add(Book book)
    {
        _books.Add(book);
        return book;
    }
}

public record Book(string Title, string Author);

Eine Seite ausliefern

Für eine Seite gibt es zwei Wege – und einen weiteren für das, was Leute daneben hochladen.

Eine Seite, direkt im Code

Gut für Kleines. Die Seite ist Teil des Snippets.

var page = Resource.FromString("""
                              <!doctype html>
                              <title>Mine</title>
                              <h1>It works</h1>
                              """)
                   .Type(new ContentType("text/html; charset=utf-8"));

return Content.From(page);

Ein Ordner mit echten Dateien

Das Richtige für alles mit Stylesheet und Script. Die Dateien legen Sie genauso an wie eine C#-Datei. Sie werden ausgeliefert, wie sie sind – nichts wird kompiliert.

return Layout.Create()
             .Add("api", api)
             .Add(Assets.App("site"));

Hochgeladene Dateien, aus den Daten

Für das, was Leute hochladen oder das Lambda erzeugt – Bilder, Dokumente –, ausgeliefert neben der App. Nicht für die Seiten der App selbst: Die gehören in einen Ordner mit Dateien, damit sie in derselben Version stecken wie der Code, der sie braucht.

return Layout.Create()
             .Add("api", api)
             .Add("uploads", Workspace.Files("uploads"))
             .Add(Assets.App("site"));

Ein Frontend, Schritt für Schritt

Der zweite Weg im Detail. Jede Demo liefert ihre Seite so aus, aus einem Ordner namens web – öffnen Sie zum Beispiel demo-crud. Demos sind schreibgeschützt; ihr Editor-Schlüssel ist ihr Name.

  1. 1
    Klicken Sie unter Code neben den Dateien auf + und geben Sie site/index.html ein. Ein Schrägstrich im Namen legt die Datei in einen Ordner. Eine Endung sagt, was für eine Datei es ist.
  2. 2
    Legen Sie site/app.css und site/app.js genauso an. Ihre Seite verweist über den Namen auf sie, etwa mit href="app.css". Denn der Ordner ist die Wurzel dessen, was ausgeliefert wird – kein Teil der Adresse.
  3. 3
    Für alles, was kein Text ist, etwa Bilder oder Schriften, öffnen Sie eine Datei in site und klicken neben den Dateien auf den Upload-Button: Die Datei landet im selben Ordner. Ein PNG kann man nicht in einen Texteditor tippen – das hier ist der Weg.
  4. 4
    Liefern Sie den Ordner in lambda.cs aus:
    return Layout.Create().Add(Assets.App("site"));
  5. 5
    Klicken Sie auf Deployen. site/index.html antwortet unter /, site/app.css unter /app.css. Jede Adresse ohne passende Datei bekommt die Seite. So funktioniert ein Frontend mit eigenem Routing auch, wenn jemand einen Deep Link neu lädt.
  6. 6
    Mit einer API daneben hat die Seite auch einen Gesprächspartner:
    var api = Inline.Create().Get("notes", () => notes);
    
    return Layout.Create()
                 .Add("api", api)
                 .Add(Assets.App("site"));

Zwei Orte für Dateien

Ein Lambda hat Dateien an zwei Orten, und der Editor zeigt sie getrennt: Dateien enthält die Dateien einer Version – das Programm –, Daten den Workspace – was das Programm aufbewahrt. Der Unterschied ist, wem sie gehören. Die Dateien einer Version gehören zu dieser Version; die Daten gehören dem Lambda, und alle Versionen teilen sie.

In einer VersionIn den Daten
InhaltCode und Assets: das Programm, samt Frontend – und seine Dokumentation und Testsalles, was das Lambda schreibt oder jemand hochlädt
Ändert sichnie – eine Änderung ist eine neue Versionsobald etwas hineingeschrieben wird
Ein Deploymentstellt genau diese Dateien onlinelässt sie unberührt
Zurückrollenbringt die alten Dateien zurückkeine Wirkung: Alle Versionen teilen sie
Ein Entwurfbeginnt als Kopie davonarbeitet mit einer Kopie davon
Wird gelöschtmit alten Versionen, sobald das Limit überschritten istmit dem Lambda oder wenn Sie sie ausschalten
im Code erreichbar alsAssetsWorkspace

Ein gemeinsamer Ort geht nicht. Sonst würde ein Deployment entweder alles löschen, was Ihr Lambda seitdem geschrieben hat – oder aus dem, was es ausliefert, ließe sich nie etwas entfernen. Ein Spiel mit Bestenliste braucht das Zweite, die Seite dazu das Erste. Also gehört die Seite in die Version und die Bestenliste in die Daten.

Datensätze speichern

Datensätze – Einträge, Konten, Bestellungen, Stimmen – gehören in die Datenbank: eine eigene SQLite-Datenbank des Lambdas, die Sie unter Daten einschalten. Der Code öffnet mit Database.GetConnection() eine Verbindung und liest und schreibt über Entity Framework Core, mit einem eigenen Kontext, der die Tabellen abbildet:

// migrations/V1__Create_notes.sql:
//   CREATE TABLE notes (id INTEGER PRIMARY KEY, text TEXT NOT NULL);

using (var connection = Database.GetConnection())
{
    new Evolve(connection) { Locations = [Assets.Root + "migrations"] }.Migrate();
}

return Inline.Create()
             .Get("notes", () =>
             {
                 using var db = new Notes(Database.GetConnection());

                 return db.Entries.OrderBy(n => n.Id).Select(n => n.Text).ToList();
             })
             .Post("notes", (NoteInput input) =>
             {
                 using var db = new Notes(Database.GetConnection());

                 db.Entries.Add(new Note { Text = input.Text });

                 return db.SaveChanges();
             });

record NoteInput(string Text);

class Note
{
    public long Id { get; set; }

    public string Text { get; set; }
}

// maps the table the migration made, on the connection it is handed
class Notes(SqliteConnection connection) : DbContext
{
    public DbSet<Note> Entries => Set<Note>();

    protected override void OnConfiguring(DbContextOptionsBuilder options)
        => options.UseSqlite(connection, contextOwnsConnection: true);

    protected override void OnModelCreating(ModelBuilder model)
        => model.Entity<Note>().ToTable("notes");
}

Ihre Tabellen legen Migrationen an: SQL-Dateien in migrations/, die zur Version gehören und beim Start des Lambdas von Evolve der Reihe nach angewendet werden – jede genau einmal, eine neue Version führt also nur aus, was neu ist. Ändern Sie nie eine Migration, die schon angewendet wurde; eine Änderung an einer Tabelle ist die nächste Datei.

Wie alle Daten teilen sich alle Versionen die Datenbank, Deployments und Zurückrollen lassen sie unberührt, und ein Entwurf arbeitet mit einer Kopie. Unter Daten sehen Sie ihre Tabellen und was darin steht – die einfache Ansicht nennt sie Einträge. Als .NET-Projekt herunterladen nimmt sie als gewöhnliche SQLite-Datei mit.

Legen Sie einen Kontext dort an, wo Sie ihn brauchen, geben Sie ihn danach wieder frei, und verwenden Sie ihn synchron – ToList und SaveChanges, nicht ToListAsync und SaveChangesAsync. Die Tabellen legen die Migrationen an, nie Entity Framework. Die Demo demo-crud zeigt all das.

Dateien speichern

Workspace ist ein privates Verzeichnis, in dem Ihr Lambda lesen und schreiben darf: der Ort für Dateien – Bilder, die jemand hochlädt, ein Dokument, das es erzeugt, ein Modell, das es lädt. Datensätze gehören in die Datenbank, und auch was man über eine Datei weiß – wer sie hochgeladen hat und wann –, ist ein Datensatz.

// uploads go into a folder of their own, served as they are
Workspace.CreateFolder("photos");

return Layout.Create()
             .Add("photos", Workspace.Files("photos"))
             .Add("upload", Inline.Create().Post(async (Stream body) =>
             {
                 using var content = new MemoryStream();

                 await body.CopyToAsync(content);

                 Workspace.WriteBytes($"photos/{Guid.NewGuid():N}.jpg", content.ToArray());
             }));

Dazu gibt es ReadBytes, WriteBytes, Delete, List, CreateFolder und zum Ausliefern Tree/Files/App. Sonst ist nichts im Dateisystem erreichbar.

Schlüssel und Passwörter

Ein API-Schlüssel, ein Passwort oder ein Token gehört in die Secrets, nicht in den Code – dort hätte ihn jede Version, jeder Download und jeder, der die Historie liest. Der Code liest ein Secret über seinen Namen:

var weather = new System.Net.Http.HttpClient();

weather.DefaultRequestHeaders.Add("X-Api-Key", Secret.Read("WEATHER_API_KEY"));

return Inline.Create()
             .Get("today", async () => await weather.GetStringAsync("https://weather.example/today"));

Schalten Sie Secrets unter Daten ein und setzen Sie den Wert dort. Einmal gespeichert, wird er nie wieder angezeigt – weder Ihnen noch einem Agenten; Sie können ihn nur ersetzen. Die Liste zeigt, welche Namen der Code liest, für die noch kein Wert gesetzt ist, und die Übersicht fragt danach. Secret.Exists sagt, ob eines gesetzt ist – für Code, der auch ohne auskommt. Wie alle Daten teilen sich alle Versionen die Secrets, und ein Entwurf arbeitet mit einer Kopie.

Sie werden verschlüsselt gespeichert, mit einem Schlüssel, der nicht in der Datenbank liegt. In einem heruntergeladenen Projekt liest Secret.Read("NAME") die Umgebungsvariable NAME – die Werte selbst bleiben hier.

Websockets

Unterstützt – und von Anfang an mitgedacht. Die Demo demo-game bringt Spieler zusammen und führt jede Partie auf dem Server aus. Die einfachste Form sind drei Callbacks:

var room = new ConcurrentDictionary<IReactiveConnection, string>();

var socket = Websocket.Functional()
                      .OnOpen(c => { room[c] = "someone"; return ValueTask.CompletedTask; })
                      .OnMessage(async (c, text) =>
                      {
                          foreach (var other in room.Keys)
                          {
                              await other.WritePayloadAsync(text);
                          }
                      })
                      .OnClose((c, _) => { room.TryRemove(c, out _); return ValueTask.CompletedTask; });

return Layout.Create().Add("chat", socket);

Wenn die Seite nur zuhört – ein Zähler, ein Feed, eine Rangliste –, sind Server-Sent Events einfacher: eine lange Antwort, in die der Server fortlaufend schreibt und die der Browser selbstständig wieder aufbaut. Die Demo demo-live schickt auf diese Weise jede Stimme an alle, die gerade zusehen. In beiden Fällen schickt der Server, was sich geändert hat. Eine Seite, die alle paar Sekunden erneut nachfragt, sendet jedes Mal eine Anfrage, ob sich etwas geändert hat oder nicht, und kommt trotzdem zu spät.

In diese Falle tappt jeder: Browser können beim Websocket-Handshake keine Header setzen. Übergeben Sie, was der Handler braucht, in der Query – er liest sie aus connection.Request.Header.Query. Secrets schicken Sie als erste Nachricht.

Was nicht erlaubt ist

Ihr Code läuft auf einem gemeinsam genutzten Server. Deshalb wird manches in C# schon vor dem Kompilieren abgelehnt: Prozesse starten, eigene Sockets öffnen, Assemblies laden, auf das Dateisystem außerhalb Ihres Workspace zugreifen – und Reflection, die all das umgehen soll. Ebenso das Warten auf einen Task mit .Result oder .Wait() statt await: Anfragen laufen auf einem Thread pro Kern, und der Task müsste genau auf dem Thread fertig werden, der auf ihn wartet.

Alles andere ist da, auch die komplette API der GenHTTP-Module. Wird etwas abgelehnt, sehen Sie, in welcher Zeile und warum – nicht nur, dass es fehlschlug.

Alles mitnehmen

Mit Als .NET-Projekt herunterladen im Editor bekommen Sie alles als Solution, die Sie öffnen, mit dotnet run starten und behalten können. Sie braucht nur das GenHTTP-Paket und bringt ein Dockerfile mit, um sie als Container zu bauen und zu betreiben.

Ihr Snippet wird zu Project.cs, und Program.cs liefert aus, was es zurückgibt. Ihre anderen Dateien kommen genau so mit, wie Sie sie geschrieben haben. Workspace und Assets werden zu zwei Ordnern neben dem Programm, mit denselben Methoden, getrennt in einem Ordner Platform – an Ihrem Code ändert sich nichts. Secret liest dort gleichnamige Umgebungsvariablen; die Werte bleiben hier. Die Dokumentation und die Tests kommen in docs und tests mit. Database öffnet database/database.db, die der Download samt den Datensätzen enthält, die Ihre App aufbewahrt hat.

Gut zu wissen, bevor Sie hier etwas bauen: Was Sie schreiben, gehört Ihnen, und Sie können es komplett mitnehmen. Dass es auf unserem Server läuft, bindet es nicht an unseren Server.

Den Code veröffentlichen

Wenn das, was Sie gebaut haben, anderen helfen könnte, veröffentlichen Sie den Code: Öffnen Sie im Kontrollzentrum Open Source, wählen Sie eine Lizenz – MIT, sofern Sie keine andere möchten – und schalten Sie die Veröffentlichung ein. Der Code bekommt eine eigene Seite unter den Open-Source-Apps. Dort kann ihn jeder lesen, mit einem Stern versehen und jede Version als dasselbe Projekt herunterladen, das Ihnen Als .NET-Projekt herunterladen liefert – mit der Lizenz daneben.

Veröffentlicht wird jede Version, auch die früheren, mit ihrer Dokumentation, ihren Tests und der Änderung, die sie gemacht hat. Was die App aufbewahrt, wird nie veröffentlicht – ihre Datensätze, die Dateien, die sie gespeichert hat, die Werte ihrer Schlüssel und Passwörter –, ebenso wenig wie das, worum Sie in Ihren eigenen Worten gebeten haben, oder wer die App nutzt. Schalten Sie die Veröffentlichung aus, ist die Seite weg; ihre Sterne bleiben erhalten, falls Sie den Code wieder veröffentlichen.

Alles im Code wird öffentlich, auch die früheren Versionen. Ein Schlüssel oder Passwort gehört zu den Schlüsseln und Passwörtern unter Daten, nie in den Code – ob veröffentlicht oder nicht.

Mit einem Agenten arbeiten

Unter /mcp gibt es einen MCP-Endpunkt. Verbinden Sie einen Agenten damit, und er kann alles, was der Editor kann: die Anleitung lesen, eine Demo komplett lesen, Dateien schreiben, kompilieren und deployen. Darunter liegt dieselbe API.

Dabei sagt er, warum er etwas tut – write_code nimmt Spezifikation und Änderung entgegen. Und er kann prüfen, was er deployt hat: read_logs liefert die letzten Requests des Lambdas, seine Ausgaben und die Stacktraces aller Exceptions. So weiß ein Agent, dass sein Code funktioniert, statt es nur anzunehmen. Dasselbe sehen Sie im Kontrollzentrum. Er schreibt dabei auch die Dokumentation und die Tests, liest sie, bevor er etwas ändert, und führt die Tests gegen die Adresse eines Entwurfs aus, bevor er den Entwurf online stellt. Eine Seite, die gefunden werden soll, bekommt einen Titel, eine Beschreibung, ein Icon und eine Vorschau für den Fall, dass jemand ihren Link teilt. Am Ende der Seiten, die er baut, fügt er eine kleine Zeile hinzu, dass sie mit GenHTTP Lambda erstellt wurden – sagen Sie ihm, wenn Sie das nicht möchten, dann entfernt er sie.

Mehr dazu →