Den Agenten im Sandkasten halten
Ein abgeschotteter Ordner, auch Sandkasten genannt, ist der eine Ordner, in dem ein Agent lesen und schreiben darf. Jeder Pfad, den er verlangt, muss in diesem Ordner enden.
Das ist schwerer, als es klingt. Ein Pfad kann mit zwei Punkten hinausklettern oder über einen Link woandershin führen. Die Lösung: prüfen, wo ein Pfad wirklich endet.
Am Ende dieser Lektion
Notiz
Ich kann einen Agenten in einem Ordner halten, indem ich den aufgelösten Pfad prüfe.
Schlüsselwörter
| Begriff | Was er bedeutet | Beispiel |
|---|---|---|
| Sandkasten | der eine Ordner, den ein Agent benutzen darf | |
| Auflösen | herausfinden, wohin ein Pfad wirklich führt | |
| Link | eine Datei, die auf einen anderen Ort zeigt | abkuerzung |
| Ausbruch | außerhalb des Ordners landen | |
| Übergeordneter Ordner | der Ordner darüber, geschrieben als zwei Punkte | .. |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Erst auflösen, dann vergleichen
Einen Pfad aufzulösen heißt: jeder Folge von zwei Punkten und jedem Link folgen, bis die echte Adresse feststeht. Erst dann fragen Sie: Liegt sie im Ordner?
Vergleichen Sie mit einem Schrägstrich am Ende. Der Ordner kasten ist nicht der Ordner kasten-alt, auch wenn ein Name mit dem anderen beginnt.
Durchgerechnetes Beispiel: Ordner /arbeit/kasten
| Verlangt | Führt wirklich nach | Drinnen? |
|---|---|---|
| a.txt | /arbeit/kasten/a.txt | Ja |
| ../draussen/s.txt | /arbeit/draussen/s.txt | Nein |
| /etc/hosts | /etc/hosts | Nein |
| ../kasten-alt/x.txt | /arbeit/kasten-alt/x.txt | Nein |
| abkuerzung/s.txt | /arbeit/draussen/s.txt | Nein: abkuerzung ist ein Link |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Ein häufiger Fehler
Warnung
Viele denken, wer die zwei Punkte aus einem Pfad streicht, macht ihn sicher. Das stimmt nicht. Ein Link im Ordner kann nach draußen zeigen. Der Text sieht dann sicher aus, der echte Ort ist es nicht. Prüfen Sie immer den echten Pfad, nie den Text.
Was sich nicht auflösen lässt, wird abgelehnt
Ein Pfad kann auf einen Ordner zeigen, den es nicht gibt, oder auf Links, die sich endlos im Kreis drehen. Sie können nicht sagen, wohin er führt, also nicht, dass er sicher ist.
Lehnen Sie ihn ab. Eine Ablehnung kostet den Agenten einen Schritt. Ein falsches Ja kann eine ganze Festplatte kosten.
Die Modellhilfe schreiben, Teil 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const basis = process.env.AI_URL || \"http://ai:4000\";' '// Die Token einer Antwort oder null, wenn sie keine nennt.' 'function zaehlen(daten, name) {' ' return daten.usage && typeof daten.usage[name] === \"number\" ? daten.usage[name] : null;' '}' > model.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Modellhilfe schreiben, Teil 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function fragen(nachrichten, probe, max) {' ' try {' ' const res = await fetch(basis + \"/v1/chat/completions\", {' ' method: \"POST\",' ' headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' ' body: JSON.stringify({ model: \"lab\", messages: nachrichten, max_tokens: max || 100 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"Status \" + res.status);' ' const d = await res.json();' ' return { text: d.choices[0].message.content, eingabe: zaehlen(d, \"prompt_tokens\"), ausgabe: zaehlen(d, \"completion_tokens\"), aufgezeichnet: false };' ' } catch (fehler) {' ' console.log(\"Aufgezeichnete Probe: Kein Modell hat geantwortet (\" + fehler.message + \").\");' ' return { text: probe, eingabe: null, ausgabe: null, aufgezeichnet: true };' ' }' '}' 'module.exports = { fragen };' >> model.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Ordnerprüfung schreiben, Teil 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { fragen } = require(\"./model\");' 'const fs = require(\"fs\");' 'const path = require(\"path\");' 'const basis = path.join(process.cwd(), \"sandkasten-lab\");' 'const kasten = path.join(basis, \"kasten\");' 'fs.rmSync(basis, { recursive: true, force: true });' 'fs.mkdirSync(kasten, { recursive: true });' 'fs.mkdirSync(path.join(basis, \"kasten-alt\"));' 'fs.mkdirSync(path.join(basis, \"draussen\"));' 'fs.writeFileSync(path.join(kasten, \"a.txt\"), \"drinnen\");' 'fs.writeFileSync(path.join(basis, \"draussen\", \"s.txt\"), \"geheim\");' 'fs.symlinkSync(path.join(basis, \"draussen\"), path.join(kasten, \"abkuerzung\"));' > ordner.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Ordnerprüfung schreiben, Teil 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const wurzel = fs.realpathSync(kasten);' '// Wohin ein Pfad wirklich führt: Links folgen, dann mit dem Ordner vergleichen.' 'function drinnen(p) {' ' try {' ' const t = path.resolve(wurzel, p);' ' const echt = fs.existsSync(t) ? fs.realpathSync(t) : path.join(fs.realpathSync(path.dirname(t)), path.basename(t));' ' return echt === wurzel || echt.startsWith(wurzel + path.sep);' ' } catch (e) { return false; }' '}' 'function naiv(p) { return path.resolve(wurzel, p).startsWith(wurzel); }' >> ordner.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Ordnerprüfung schreiben, Teil 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const gefragt = [\"a.txt\", \"neu.txt\", \"../draussen/s.txt\", \"/etc/hosts\", \"../kasten-alt/x.txt\", \"abkuerzung/s.txt\"];' 'async function main() {' ' gefragt.forEach(function (p) { console.log(p + \" nur-Text:\" + naiv(p) + \" aufgelöst:\" + drinnen(p)); });' ' console.log(\"Dateien im Kasten: \" + fs.readdirSync(kasten).sort().join(\" \"));' ' const q = \"Schreiben Sie in einem kurzen Satz, warum ein Pfad aufgelöst werden muss, bevor man ihn prüft.\";' ' const probe = \"Ein Pfad kann mit Punkten oder einem Link woanders hinzeigen, also prüft man, wo er wirklich endet.\";' ' const antwort = await fragen([{ role: \"user\", content: q }], probe, 60);' ' console.log(\"Das Modell sagte: \" + antwort.text);' '}' 'main();' >> ordner.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Ordnerprüfung ausführen
docker exec -w /home/node/project agent node ordner.jsHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Was der Run ausgibt
| Zeile | Was sie zeigt |
|---|---|
| a.txt nur-Text:true aufgelöst:true | Eine Datei im Ordner |
| ../draussen/s.txt nur-Text:false ... | Beide Prüfungen fangen die Punkte |
| ../kasten-alt/x.txt nur-Text:true aufgelöst:false | Ein Name mit gleichem Anfang täuscht den Text |
| abkuerzung/s.txt nur-Text:true aufgelöst:false | Ein echter Link aus dem Ordner hinaus |
| Dateien im Kasten: a.txt abkuerzung | Der Run hat diese Dateien wirklich angelegt |
| Das Modell sagte: ... | Ein Satz. Die Worte ändern sich bei jedem Lauf oder zeigen Aufgezeichnete Probe |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.