CommunityCodierung & Entwicklunggithub.com

aipoch/remote-compute-ssh

SSH-Remote-Compute bewerten und nutzen, bevor GPU, High-Memory, parallele, Batch-, Modell-Inferenz, Bioinformatik oder andere langlaufende wissenschaftliche Aufgaben ausgeführt werden; unterstützt kurze Remote-Befehle und asynchrone Jobs mit automatischer Ernte und Analyse.

Was ist remote-compute-ssh?

Diese Fähigkeit ermöglicht es KI-Agenten, über SSH auf entfernte Rechenressourcen zuzugreifen und diese zu verwalten. Sie deckt sowohl die direkte Ausführung von Befehlen auf einem entfernten Host als auch die Einreichung von Stapelverarbeitungsaufträgen (Slurm) ab. Der Agent kann Hosts auflisten, Kurzbefehle ausführen (`callCommand`), Wissensdokumente auf dem Host lesen und schreiben und den gesamten Lebenszyklus asynchroner Jobs verwalten: Einreichen, Job-ID speichern, Status-Snapshots lesen, Ergebnisse ernten, Analysen durchführen und Artefakte veröffentlichen. Die Fähigkeit läuft ausschließlich auf dem Control-Plane-REPL-Kernel (JavaScript) und ist von den Python/R-Datenkernels aus nicht verfügbar. Sie ist für Entwickler und Wissenschaftler gedacht, die GPU-, High-Memory-, Parallel-, Batch- oder andere rechenintensive Workloads effizient auf entfernten Infrastrukturen ausführen möchten, ohne die Sicherheit des Sandbox-Workspaces zu gefährden.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/aipoch/open-science/tree/HEAD/resources/skills/remote-compute-ssh

Installed? Explore more Codierung & Entwicklung skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Diese Fähigkeit umfasst Remote-Computing über SSH, einschließlich direkter Ausführung und Slurm-Einreichung: Auflisten von Hosts, Erstellen von Handles, Ausführen kurzer Remote-Befehle (callCommand), Lesen/Schreiben von Host-Wissensdokumenten und den vollständigen asynchronen Job-Lebenszyklus — Einreichen → Speichern der job_id → Lesen nicht-blockierender Snapshots anhand dieser ID → Ernten → Analyse-Durchlauf → Veröffentlichen von Artefakten.

Wo host.compute läuft: host.compute lebt NUR auf dem Control-Plane-REPL-Kernel — führen Sie jedes Beispiel unten mit dem repl_execute-Tool (JavaScript) aus, demselben Kernel, der auch host.mcp hostet. Die python/r-Datenkernel haben KEIN host.compute (SSH und Genehmigungen bleiben außerhalb des Sandbox-Workspace); ein Aufruf aus einer Python/r-Zelle schlägt mit host.compute ist nicht definiert fehl.

Wählen Sie einen Ausführungsort

Nur für diese Sitzung aktivierte Compute-Hosts sind sichtbar oder aufrufbar. Entdecken Sie sie in einem Katalog; jeder Eintrag hat die Rolle selected oder available. Ein nicht-leerer ausgewählter Pool ist eine Ausführungsanweisung: führen Sie Tool-gestützte Aufgabenarbeit auf einem oder mehreren ausgewählten Hosts durch, wie es die Aufgabe erfordert. Der Pool hat keine Priorität und impliziert keine automatische Multi-Host-Planung. Wenn kein Host ausgewählt ist, wählen Sie aus den verfügbaren Einträgen. Lesen Sie details() nur für Kandidaten, die eine genauere Bewertung benötigen.

Erraten oder verwenden Sie niemals eine Provider-ID, die nicht im Katalog vorhanden ist. Ein Benutzer, der einen deaktivierten Host nennt, macht ihn nicht aufrufbar; erklären Sie, dass er zuerst für diese Sitzung aktiviert werden muss. Wenn kein geeigneter Host verwendbar ist, erklären Sie die Blockade und fragen Sie den Benutzer, wie er fortfahren möchte.

const hosts = await host.compute.listHosts()
const selectedHosts = hosts.filter((host) => host.role === 'selected')
const candidates = selectedHosts.length > 0 ? selectedHosts : hosts

Jedes Listenelement ist eine kompakte Zusammenfassung mit provider_id, display_name, shape, execution_mode, status und role (last_probe_ok, probe_failed oder not_probed). last_probe_ok bedeutet, dass die letzte persistierte Probe erfolgreich war; es bestätigt keine Live-Konnektivität. Wissensdokumente und Resource-Probe-Snapshots werden absichtlich aus den Discovery-Ergebnissen ausgeschlossen.

API-Referenz

// Liste der für diese Sitzung aktivierten Hosts als kompakter Katalog mit Rollen
const hosts = await host.compute.listHosts()

// Kompatibilitäts-Discovery-Namen bleiben verfügbar; beide verbergen weiterhin deaktivierte Hosts.
const visibleHosts = await host.compute.listRegistered()
const selectedHosts = await host.compute.listPreferred()

// Erstellen Sie einen Handle für einen bestimmten Host (kein Netzwerkaufruf)
const c = host.compute.create('ssh:<alias>')

// Führen Sie einen kurzen Remote-Befehl aus (löst bei approval_denied / host_unreachable / timeout aus)
const result = await c.callCommand('<Shell-Befehl>', '<einzeiliger Zweck für die Genehmigungskarte>', {
  loginShell: true, // Standard: true — führt Login-Profile aus, dann lesbares ~/.bashrc, vor diesem Befehl
  timeoutSeconds: 60 // optional — der Host wendet seinen eigenen Standard (60s) an, wenn nicht angegeben
})
// result → { exit_code, stdout, stderr, truncated }

// Lesen Sie die persistierten Operationsanweisungen und den unabhängigen Resource-Probe-Snapshot.
// doc ist immer der exakte gespeicherte Text (einschließlich '' bevor Anweisungen gespeichert werden).
// probe ist explizit null, wenn dieser Host noch nie geprobt wurde.
const info = await host.compute.details('ssh:<alias>', { mode: 'read' })

// Fügen Sie eine Notiz zum persistierten Host-Wissensdokument hinzu (Agent schreibt; 32 KB-Grenze wird erzwungen).
// Append ändert nur doc; es kopiert oder ändert nie Probe-Beobachtungen.
await host.compute.details('ssh:<alias>', {
  mode: 'append',
  text: '\n## Notiz\ngelernt X am <Datum>'
})

// Alternativ das gesamte Host-Wissensdokument ersetzen. Lesen Sie vor dem Ersetzen erneut,
// besonders wenn Sie oben angehängt haben: oldText muss exakt mit dem persistierten doc übereinstimmen.
const latest = await host.compute.details('ssh:<alias>', { mode: 'read' })
await host.compute.details('ssh:<alias>', {
  mode: 'replace',
  text: '<neues vollständiges doc>',
  oldText: latest.doc
})

Behandeln Sie doc als Operationsanweisungen und dauerhaftes Host-Wissen. Behandeln Sie probe als datierte Beobachtung: Ressourcenwerte können sich ändern, und das Erkennen eines Schedulers autorisiert nicht zum Einreichen eines Jobs oder zur Auswahl eines Kontos, einer Partition oder einer Warteschlange. Bei einem Dokumentenkonflikt oder einem details_conflict-Fehler lesen Sie erneut und führen Sie Ihren Entwurf mit dem neuesten Dokument zusammen, bevor Sie es erneut versuchen. Eine reine Resource-Probe-Aktualisierung ändert doc nicht und verursacht keinen Ersetzungskonflikt. Nach dem Schreiben lesen Sie erneut, um den gespeicherten Inhalt zu überprüfen. Ein erfolgreiches Append- oder Replace-Ergebnis ist nur { ok: true }. Das Schreibergebnis enthält kein doc oder probe; lesen Sie immer erneut, um das exakte persistierte doc zu überprüfen, anstatt Felder aus dem Schreibergebnis zu lesen.

Mit loginShell: true werden zuerst die Remote-Bash-Login-Profile ausgeführt, und dann versucht Open-Science, ~/.bashrc zu laden, wenn es lesbar ist. Eine .bashrc kann für nicht-interaktive Shells absichtlich früh zurückkehren, sodass nach einer solchen Wächtervariable deklarierten Variablen nicht verfügbar sind. Eine fehlende .bashrc ist ein No-Op. Setzen Sie loginShell: false, um den Befehl ohne Initialisierungsschritte auszuführen. Initialisierungsfehler werden durch das normale Befehls-ergebnis/-fehlerverhalten gemeldet.

API-Referenz (asynchrone Jobs)

Verwenden Sie submitJob für langlaufende Berechnungen (Minuten bis Stunden). Es kehrt sofort mit einer job_id zurück; der Job läuft auf dem Remote-Host im Hintergrund. Wenn der Job abgeschlossen ist, erntet die App automatisch die Ausgaben und initiiert einen neuen Analysedurchlauf, wenn Sie das terminale Ergebnis noch nicht gelesen haben. Speichern Sie die exakte job_id aus dem Einreichungsergebnis in Ihrem Arbeitskontext; es gibt absichtlich keinen historischen Job-Scan, um sie wiederzuentdecken. Status- und Ergebnislesevorgänge verwenden nur diese gespeicherte ID und geben nicht-blockierende lokale Snapshots zurück.

Für eine lokale Eingabe ist src relativ zum Agent-Session-Arbeitsbereich – demselben Arbeitsbereich, der von Dateischreibtools verwendet wird. Schreiben Sie ein Skript oder eine kleine generierte Eingabe dorthin und übergeben Sie dann seinen relativen Pfad. Open-Science snapshotet akzeptierte Eingaben vor Genehmigung und Versand. Übergeben Sie keine beliebigen absoluten lokalen Pfade oder kopieren Sie Dateien in von der App verwaltete Verzeichnisse notebooks/.... Ein absolutes src ist nur gültig, wenn es der exakte Pfad ist, der von host.artifactPath(versionId) zurückgegeben wird, oder ein exakter registrierter Session-Eingabepfad, der bereits im Notebook-Kontext bereitgestellt wurde.

// Verwenden Sie die oben aus dem Session-Katalog ausgewählten `candidates` wieder.

// Reichen Sie einen nicht-blockierenden Job ein — kehrt sofort zurück, nachdem der Benutzer genehmigt hat.
// Der konfigurierte Ausführungsmodus des Compute-Hosts wählt zwischen direktem SSH oder Slurm.
const c = host.compute.create('ssh:<alias>')
const job = await c.submitJob(
  '<einzeiliger Zweck für die Genehmigungskarte>', // wird in der Genehmigungskarte angezeigt
  '<Shell-Befehl>', // Befehl, der remote ausgeführt werden soll
  {
    environment: 'protein-gpu', // optionaler logischer Name; siehe Environment-Aktivierung unten
    timeoutSeconds: 3600, // optional; Standard 24 h, maximal 7 Tage
    inputs: [
      { src: 'in.dat', dstFilename: 'in.dat' }, // eine Datei aus dem Agent-Session-Arbeitsbereich bereitstellen
      { remotePath: 'ssh:<alias>/<abs_pfad>' } // eine Remote-Datei verlinken (kein Transfer)
    ],
    outputs: [
      '*.result', // hervorgehoben (Standard-Sichtbarkeit)
      { glob: '*.json', visibility: 'featured' }, // explizit hervorgehoben
      { glob: '*.log', visibility: 'hidden' }, // versteckt (diagnostisch, nicht in Karte gezeigt)
      { glob: 'checkpoints/**', residency: 'remote' } // auf Remote belassen — in left_on_remote aufgezeichnet
    ],
    harvest: {
      exclude: ['work/**'], // diese Pfade nie ernten
      maxFileMb: 100, // hartes Maximum pro Datei (100 MiB)
      maxTotalMb: 500 // hartes Maximum pro Job, einschl. stdout/stderr (500 MiB)
    }
  }
)
// job → { job_id, provider_id, status: 'submitted' | 'queued', remote_workdir }
const savedJobId = job.job_id // Diese exakte ID für den späteren abhängigen Schritt aufbewahren
return { ...job, job_id: savedJobId }

Einen gespeicherten Job-Snapshot lesen

Verwenden Sie die gespeicherte ID, wenn der Zustand oder das Ergebnis des Jobs relevant ist. .status() und .result() sind nicht-blockierende lokale Lesevorgänge in jedem Zustand; keiner wartet auf Abschluss, löst SSH aus oder startet eine weitere Ernte. .result() enthält auch geerntete Dateilisten. Beide Aufrufe melden follow_up_delivery. Ein finaler .result()-Lesevorgang gibt suppressed zurück, wenn er den Fallback verhindert, oder committed, wenn dieser Fallback bereits seine Versandgrenze überschritten hat. Ein .status()-Snapshot bleibt pending, weil er geerntete Dateilisten auslässt. Verwenden Sie die exakte ID der Einreichung, anstatt alte Jobs zu durchsuchen.

const snapshot = await c.attachJob(savedJobId).result()
if (!snapshot.result_final) {
  return {
    job_id: savedJobId,
    status: snapshot.status,
    result_final: false,
    follow_up_delivery: snapshot.follow_up_delivery
  }
}
return snapshot

Behandeln Sie nur result_final: true als endgültiges Ergebnis. Es bedeutet, dass die automatische Antwort bereit ist: success, failed und timeout können noch auf die lokale Ernte warten, während cancelled und error endgültig sind, ohne auf die partielle Ausgabesammlung zu warten. output_files enthält nur Dateien, die lokal tatsächlich verfügbar sind; eine leere Liste beweist nicht, dass es keine Remote-Ausgaben gibt. Die App übernimmt das Provider-Polling und die Ernte im Hintergrund. Ein ungelesenes endgültiges Ergebnis wird in einem späteren Agent-Turn zugestellt. Ein finaler .result()-Snapshot meldet follow_up_delivery: 'suppressed', wenn er diesen Fallback unterdrückt, oder committed, wenn die automatische Lieferung bereits das Rennen gewonnen hat und maßgeblich bleibt. .status() verbraucht nie das vollständige Ergebnis.

Direktes SSH oder Slurm

Der konfigurierte Ausführungsmodus des Compute-Hosts wählt aus, wie jeder Job gestartet wird. direct_ssh führt den Befehl als abgetrennten Prozess auf dem SSH-Ziel aus. slurm reicht ihn mit sbatch ein; fügen Sie die erforderlichen #SBATCH-Direktiven des Clusters oben im command ein. Open-Science übernimmt die Einreichung, das Scheduler-Status-Polling, die Stornierung und die Ernte. Rufen Sie sbatch, squeue oder scancel nicht selbst im Rahmen von submitJob auf.

Lesen Sie bei einem Slurm-Statusfehler oder einer fehlgeschlagenen Stornierung die Slurm-Fehlerbehebung. Auf diesem außergewöhnlichen Pfad kann compute.callCommand denselben Job und seine Ausgaben überprüfen und eine Wiederherstellung innerhalb der bestehenden Aufgabenautorisierung des Benutzers durchführen. Behalten Sie die normale Einreichung auf der Compute-API.

Lesen Sie listHosts() für den konfigurierten Modus und details() für provider-spezifische Direktiven; versuchen Sie nicht, den Modus pro Job zu überschreiben oder ihn nur aus der Arbeitslast abzuleiten. Wenn Slurm nicht verfügbar ist oder das Skript ablehnt, melden Sie den zurückgegebenen Fehler und den konkreten nächsten Schritt (z. B. ein Konto oder eine Partitionsdirektive hinzufügen). Führen Sie die Arbeitslast nicht stillschweigend direkt auf einem Login-Knoten aus.

Open-Science akzeptiert gewöhnliche Single-Job-Direktiven wie Partition, Konto, CPUs, Arbeitsspeicher und GPUs. Setzen Sie timeoutSeconds für die Laufzeit der Arbeitslast. Sie können das Scheduler-Allokationslimit mit einer #SBATCH --time=Wert-Direktive festlegen; wenn sie fehlt, leitet Open-Science ein Standard-Allokationslimit aus timeoutSeconds ab. Open-Science übernimmt die Jobname-, Arbeitsverzeichnis-, stdout- und stderr-Direktiven. Vermeiden Sie Job-Arrays, da ein Open-Science-Job einen Scheduler-Job und eine Ausgabeernte verfolgt. Reichen Sie unabhängige Arbeiten als separate Jobs ein und verwenden Sie bei Bedarf das Session-Gleichzeitigkeitslimit.

Fordern Sie für Slurm Ressourcen mit einer #SBATCH --option=Wert-Direktive pro Zeile an (oder einem wertfreien Flag wie #SBATCH --exclusive). Das veraltete resources-Feld ist beschreibende Metadaten; es alloziert keine CPUs, Arbeitsspeicher oder GPUs. timeoutSeconds begrenzt die Laufzeit der Arbeitslast, nicht die Wartezeit in der Warteschlange; #SBATCH --time legt das Scheduler-Allokationslimit fest. Keines ist eine Garantie für die Startzeit in der Warteschlange.

Die nicht-blockierenden Job-status()- und result()-Snapshots enthalten scheduler_job_id, wenn bekannt, error: { code, message } bei einem Job-Fehler und last_poll_error, wenn Beobachtung oder Einreichungswiederherstellung Aufmerksamkeit erfordert. Ein ausstehender Grund oder eine verzögerte Buchhaltungszeile bedeutet nicht, dass die Arbeitslast fehlgeschlagen ist. Wenn eine Einreichung unbestätigt ist, verwenden Sie die gemeldete Job-Identität und Provider-Diagnose, bevor Sie entscheiden, ob Sie erneut einreichen; Open-Science reicht nicht automatisch ein Duplikat ein.

Environment-Aktivierung

Der optionale environment-Wert ist ein logischer Name, kein Shell-Befehl. Open-Science lädt ~/.open-science/environments/<name>.sh vor der Arbeitslast für direkte und Slurm-Jobs. Namen sind 1–64 Buchstaben, Ziffern, Punkte, Unterstriche oder Bindestriche und müssen mit einem Buchstaben oder einer Ziffer beginnen. Die Datei und jeder von ihr referenzierte Software-/Cache-Pfad müssen auf dem Ausführungsknoten sichtbar sein.

Wenn eine Einreichung meldet, dass diese Aktivierungsdatei fehlt, laden Sie die Compute-Environment-Setup-Fähigkeit, um genaue Setup-, Reparatur- und Entfernungsanweisungen für den Benutzer oder Host-Administrator zu erstellen, die außerhalb von Open-Science ausgeführt werden sollen. Validieren Sie die benutzerverwaltete Aktivierung, nachdem sie den Plan angewendet haben, und versuchen Sie es dann erneut. Erraten Sie keinen Conda-Namen, fügen Sie keine Inline-Installation zum Wissenschaftsjob hinzu oder verstecken Sie die Aktivierung in .bashrc. Lassen Sie environment weg, wenn der Befehl absichtlich die Standard-Umgebung des Hosts verwendet.

Erntesicherheitsgrenzen

  • Deklarierte Ausgabedateien werden vor stdout und stderr ausgewählt; Protokolle verwenden das verbleibende Budget pro Job.
  • Die App lehnt vom Modell gelieferte Grenzwerte über 100 MiB pro Datei oder 500 MiB pro Job ab.
  • Die Ernte bewahrt auch feste 2 GiB freien lokalen Festplattenspeicher. Dateien, die nicht passen, bleiben remote.

Verhaltensgrenzen

  • Während der Job läuft: die Konversation ist offen. Der Benutzer kann Nachrichten senden; Sie können andere Aufgaben bearbeiten. Jede Status-/Ergebnisabfrage kehrt sofort mit dem aktuellen lokalen Snapshot zurück.
  • Wenn der Job abgeschlossen ist: wenn Sie sein terminales Ergebnis nicht aktiv gelesen haben, initiiert die App automatisch einen neuen Analysedurchlauf. Sie lösen diesen Fallback nicht aus.

Job-Status prüfen (nicht-blockierender Lesevorgang, zu Informationszwecken)

// Nicht-blockierender DB-Lesevorgang — kein SSH. Verwenden Sie dies, wenn Sie mitten in der Konversation einen
// Status-Snapshot benötigen.
const handle = c.attachJob(job.job_id)
const s = await handle.status()
// s → {
//   job_id, scheduler_job_id?, status, result_final, cancellation?, exit_code,
//   error?, last_poll_error?, scheduler_pending_reason?, follow_up_delivery?,
//   output_files?, left_on_remote?
// }

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Verwandte Skills