Hoppa till innehållet

Devportalen /portal/dev

Startsideportalens ekosystem för människa och agent

Dokumentationen / Paket

@startsidan/module-sdk

dok · module-sdk
id: module-sdk
namn: @startsidan/module-sdk
sammanfattning: Kontraktet mellan skalet och modulerna, plus urvalsfunktionerna skalet använder för att komponera dem.
uppdaterad: 2026-10-07

ansvar:
- Definiera ModuleManifest, UserContext och de typer modulerna fyller.
- Göra urvalet: filtrera på roll, sortera på order, aggregera actions.
- Äga den samlade uppgiftslistan: uppgifterFor läser alla modulers uppgifter, öppna och hanterade, med källan ifylld – vid varje anrop, utan lager.
- Låta aggregerande moduler nå registret utan att skalet skickar det som prop.
- Beskriva redaktionella sidor och deras innehåll som block, oberoende av källa.
- Bära flödestyperna tills motorn lyfts till packages/flow-engine i M4.

filer:
- packages/module-sdk/src/types.ts — ModuleManifest, UserContext, Widget (med label för flyttknapparna, ADR-018), ActionItem, ModuleRoute (focus, standard, full) och RouteComponent (ADR-019, ADR-025), Genvag (ADR-025), Notification och NotificationsProvider (ADR-020), FokusItem och FokusProvider (ADR-021), IntentHandler.
- packages/module-sdk/src/select.ts — widgetsFor, actionsFor, uppgifterFor, navFor, genvagarFor, mergeNav, routeFor (med parametrar), matchaVag, suggestionsFor.
- packages/module-sdk/src/define.ts — defineModule: typkontroll utan annotering.
- packages/module-sdk/src/provide.ts — provideRegistry och currentRegistry (ADR-007).
- packages/module-sdk/src/page.ts — PageManifest, PageContent, ContentBlock och Inline (ADR-016).
- packages/module-sdk/src/pages.ts — findPage, pageTrail, pageHref, hubsInSection, articlesUnder, resolveContent, pageProblems.
- packages/module-sdk/src/flow.ts — FlowDefinition, turkontraktets zod-schema, farSkapas.
- packages/module-sdk/src/prompt.ts — byggSystemprompt: systemprompten ur flödesdefinitionen, inklusive blocket med redan fastställda fält (ADR-013).

api:
- defineModule: (manifest: ModuleManifest) => ModuleManifest
  Identitetsfunktion som ger typkontroll på manifestet.
- widgetsFor: (modules, slot, ctx) => Widget[]
  Widgets i en slot som rollen ska se, i ordning. Widgetens roles är snävare än modulens.
- actionsFor: (modules, ctx) => Promise<ActionItem[]>
  Aggregatet bakom "Att agera på": de öppna uppgifterna. En modul som fallerar tar inte ned kortet.
- uppgifterFor: (modules, ctx) => Promise<Uppgift[]>
  Den samlade uppgiftslistan bakom Mina uppgifter och AI-assistentens verktyg: öppna i ordning, sedan hanterade, senast hanterade först. Varje uppgift får modul, kalla (modulens namn om modulen inte satt en) och lage (öppen om inget sattes).
- routeFor: (modules, path, ctx) => { route, module, params } | undefined
  Slår upp en modulrutt, med parametrar ur mönster som /verktyg/personal/:id. En exakt väg går före ett mönster (ADR-019).
- fokusFor: (modules, ctx) => Promise<FokusItem[]>
  Fokusytornas innehåll, nyast först. Skalet visar den första som inte är stängd (ADR-021).
- genvagarFor: (modules, ctx) => Genvag[]
  Knapparna bredvid hälsningen på startsidan, rollfiltrerade och sorterade på order (ADR-025).
- notificationsFor: (modules, ctx) => Promise<Notification[]>
  Klockans notiser från alla moduler, nyast först. En modul som fallerar tar inte ned de andras (ADR-020).
- matchaVag: (monster: string, path: string) => Record<string, string> | undefined
  Mönstermatchningen bakom routeFor. ":namn" fångar ett segment.
- intentsFor / matchaAvsikt: (modules, ctx) => IntentHandler[] / (intents, fraga) => IntentHandler | undefined
  Avsikterna rollen når, och den första vars mönster står i frågan – gemener, delsträng. AI-fältet använder dem före modellen.
- provideRegistry / currentRegistry: (all: ModuleManifest[]) => void / () => ModuleManifest[]
  Registret för aggregerande moduler (ADR-007).
- findPage: (modules, segments: string[]) => PageManifest | undefined
  Slår upp en sida på URL-segmenten under /sidor: [sektion, ingång] eller [sektion, ingång, artikel].
- pageTrail / pageHref: (modules, page) => PageManifest[] / (page) => string
  Brödsmulorna från ingången ned till sidan, och sidans väg.
- resolveContent: (page, ctx) => Promise<PageContent>
  Statiskt innehåll eller källa – skalet behöver inte veta vilket.
- topPagesInSection: (modules, section) => PageManifest[]
  Sektionens sidor utan parent – ingångar och inramade sidor. En webbplats meny.
- pageProblems: (modules) => string[]
  Registrets invarianter: unika slugar, artikelns parent är en ingång i samma sektion. Körs i test.
- byggSystemprompt: (flow, profil, faltHittills?) => string
  Prompten ur flödet. faltHittills förankrar värdena så att modellen återger dem ordagrant i stället för att formulera om sig varje tur.
- buildTurnSchema: (flow: FlowDefinition) => ZodObject
  Turkontraktet byggt ur flödet: reply, fields, complete, create.
- farSkapas: (flow, turCreate, varden, antalAnvandarsvar) => boolean
  Tre villkor samtidigt: modellen har begärt det, allt obligatoriskt finns, och användaren har sett en sammanfattning.

kontrakt:
Kontraktet ska hållas tunt. Ett nytt fält gör det tyngre för alla moduler och ska bäras av minst två innan det blir permanent.

Rollfiltreringens tre nivåer – den snävaste vinner:
```
roles på modulen        gäller allt modulen bidrar med
roles på widgeten      snävare än modulens
roles på nav-posten    snävare än modulens
```

PageManifest och innehållsblocken (page.ts):
```
interface PageManifest {
  slug: string;            // unik i registret, blir ctx.page
  section: string;         // sektions-id ur skalets "Sidor"
  parent?: string;         // ingångens slug – bara för en artikel
  layout: "hub" | "article";
  title: string; lede?: string; kicker?: string;
  quickLinks?: QuickLink[];          // bara ingång
  article?: ArticleMeta;             // bara artikel
  ai?: { suggestions?: (ctx) => Suggestion[] };
  content?: PageContent | ((ctx) => Promise<PageContent>);
}

type ContentBlock =
  | { type: "heading"; level: 2 | 3 | 4; text: string }
  | { type: "paragraph"; inlines: Inline[] }
  | { type: "list"; ordered: boolean; items: Inline[][] }
  | { type: "image"; src: string; alt: string; caption?: string };
// Aldrig HTML: en adapter översätter källan till block (ADR-016).

  | { type: "details"; summary: string; chip?: { label; tone }; blocks: ContentBlock[] }   // ADR-022

PageManifest.slots?: { main?: Widget[]; side?: Widget[] }   // bara ingång: modulens egna kort
PageContent.cards?: { title: string; blocks: ContentBlock[] }[]   // fler redaktionella kort
QuickLink.cta?: string                                       // knapptext på snabbvägskortet

interface PageLink { title: string; href: string; external: boolean; children?: PageLink[] }
// layout "embed" + embed: { src } = en extern sida i ram (ADR-017). https, ingen parent.
// children = en hopfälld nivå; så blir en webbkarta en länklista, inte en sidtyp.
```

beroenden: ui
beslut: ADR-004, ADR-006, ADR-007, ADR-016, ADR-017, ADR-018, ADR-019, ADR-020, ADR-021, ADR-022

kvarstår:
- IntentHandler matchas med enkla mönster (matchaAvsikt) av AI-fältet; LLM-matchning av avsikter finns inte.
- Sidor rollfiltreras inte – de är gemensamma enligt ADR-003. Behövs det, är det ett nytt fält och en ny ADR.
- Flödestyperna ligger här i väntan på M4. ADR-005 skrivs när motorn lyfts.