npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@edugate/authoring

v0.8.0

Published

Gli strumenti con cui un modello compone contenuto Edugate: il flusso guidato, la tela, i prefab, il builder su MCP e gli specialisti.

Readme

@edugate/authoring

Ciò che serve a un modello per comporre contenuto per Edugate — una sorgente sola, tre host.

Questi tool vivevano dentro un gateway fuori dal monorepo. Copiarli dentro apps/api avrebbe risolto la richiesta e ne avrebbe creata una peggiore: due copie da modificare insieme per sempre, e la prima volta che qualcuno ne tocca una sola divergono in silenzio — perché nessun compilatore le mette a confronto.

Qui non sono una copia: sono la sorgente.

packages/authoring/
        ├── ./flow      i quindici tool: dodici `activity_*` (2D e 3D) e tre `builder_*`
        ├── ./canvas    le operazioni della tela e il loro vocabolario
        ├── ./prefabs   i quarantanove blocchi preconfezionati
        ├── ./builder   i tre tool che aprono e modificano un'attività esistente
        └── ./agents    prompt, allowlist e card dei sette specialisti
        │
        ├── apps/api          li monta in processo (POST /mcp)
        └── edugate-agents    l'ospite per Dify

⚠️ Non c'è un export root: si importa sempre un sottopercorso. L'esecutore degli specialisti non è qui — sta in @edugate/ai-engine; qui ci sono le loro DEFINIZIONI.

Montarlo

import { createAuthoringTools, InMemoryDraftStore } from "@edugate/authoring/flow";

const tools = createAuthoringTools({
  clientFor: async (ctx) => clientBoundTo(ctx),  // ← l'identità è tua
  drafts: new InMemoryDraftStore(),
  searchImages,                                  // ← opzionale
});

for (const tool of tools) {
  server.registerTool(tool.name, {
    title: tool.title,
    description: tool.description,
    inputSchema: tool.inputSchema,
  }, async (params) => {
    const envelope = await tool.run(params, ctx);
    return {
      structuredContent: envelope,
      content: [{ type: "text", text: envelopeToText(envelope) }],
    };
  });
}

Il pacchetto restituisce dati. structuredContent è il contratto tipizzato per il modello, il testo è per gli host che leggono ancora content[0].text, e disegnarli su una tela è una decisione dell'host — non una di queste.

Le porte, e perché sono porte

ports.ts le documenta per esteso. In breve:

| porta | cosa decide | perché non è nel pacchetto | |---|---|---| | clientFor(ctx) | con quale identità si scrive su Edugate | nel gateway si scambia un token OAuth; nell'API il chiamante è già noto e non c'è nulla da scambiare | | drafts | dove vivono i documenti fra activity_draft e activity_save | un processo solo può tenerli in memoria; più repliche no | | searchImages | come si cercano le immagini | è una capacità pura, e vive in @edugate/media: la si passa, non la si incorpora | | sceneRuntimes | quali motori sanno disegnare una scena | è l'ELENCO, e sta nel registro. L'ORDINE in cui provarli è una politica e sta qui, in scene/engines.ts | | sceneDrafts | dove vivono i documenti fra activity_draft3d e activity_save3d | stessa ragione di drafts, e per il 3D è stata aggiunta DOPO: senza, un ospite che ricostruisce i tool a ogni richiesta perdeva ogni bozza | | mirrorImages | dove finiscono le immagini copiate dentro Edugate | il pacchetto sa DECIDERE cosa copiare e sa scaricarlo; dove si depositi è di chi lo ospita |

Assente searchImages, activity_images risponde «capacità non configurata» — una diagnosi, mai zero risultati in silenzio, che somiglia a «non esiste nulla su questo argomento» ed è una risposta diversa e falsa.

I nomi dei tool sono un contratto

2D: activity_mode, activity_catalog, activity_create, activity_draft, activity_images, activity_save. 3D: activity_create3d, activity_templates3d, activity_models3d, activity_textures3d, activity_draft3d, activity_save3d. Builder: builder_open, builder_tools, builder_apply.

Un modello che ha imparato activity_create smette di trovarlo se lo si rinomina, quindi questi nomi non si toccano alla leggera. È già successo una volta di proposito: configure_quiz_poll è diventato configure_quiz perché Poll non è un tipo di blocco della piattaforma e il vecchio nome prometteva a un modello una cosa che non esiste. Ogni configurazione Dify già costruita è andata cambiata a mano.

Cosa NON fa

Non pubblica. Salva bozze private e si ferma lì. La pubblicazione di Edugate non è gated sulla moderazione — è il proprietario che rende pubblica la propria attività — e proprio per questo un tool non può farla: uno schema valido non è un fatto vero, e un quiz con una data sbagliata passa ogni validazione e arriva a una classe.

Non valida. parseContent e checkConsumes vivono in @edugate/types e sono l'unica implementazione; qui si chiama l'host. Senza validazione raggiungibile non si inventa un «valido» locale: si dice che non è disponibile e non si offre il salvataggio.

Non ha un LLM dentro. Il modello è quello del client. Qui arrivano dati.