@llmnative/agentico 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +78 -0
  3. package/dist/index.js +18 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/index.mjs +1995 -0
  6. package/dist/index.mjs.map +1 -0
  7. package/dist/types/domain/agentDefinition.d.ts +83 -0
  8. package/dist/types/domain/cli/renderManifestCli.d.ts +7 -0
  9. package/dist/types/domain/crossAgentTools.d.ts +13 -0
  10. package/dist/types/domain/defineSubagent.d.ts +5 -0
  11. package/dist/types/domain/destinationRegistry.d.ts +5 -0
  12. package/dist/types/domain/entityChatStore.d.ts +48 -0
  13. package/dist/types/domain/extractErrorMessage.d.ts +1 -0
  14. package/dist/types/domain/extractJsonBlock.d.ts +1 -0
  15. package/dist/types/domain/jsonExportDestination.d.ts +3 -0
  16. package/dist/types/domain/mcpTool.d.ts +9 -0
  17. package/dist/types/domain/microPrompts.d.ts +20 -0
  18. package/dist/types/domain/orchestrator/agenticoOrchestratorAgent.d.ts +34 -0
  19. package/dist/types/domain/orchestrator/prompt.d.ts +17 -0
  20. package/dist/types/domain/prompts.d.ts +29 -0
  21. package/dist/types/domain/resultDestination.d.ts +24 -0
  22. package/dist/types/domain/subagentManifest.d.ts +172 -0
  23. package/dist/types/domain/subagentRegistry.d.ts +11 -0
  24. package/dist/types/domain/subagentUsageCard.d.ts +37 -0
  25. package/dist/types/i18n/de.d.ts +2 -0
  26. package/dist/types/i18n/en.d.ts +2 -0
  27. package/dist/types/i18n/index.d.ts +20 -0
  28. package/dist/types/i18n/it.d.ts +2 -0
  29. package/dist/types/i18n/types.d.ts +55 -0
  30. package/dist/types/index.d.ts +25 -0
  31. package/dist/types/presentation/AgentActivityLog.d.ts +9 -0
  32. package/dist/types/presentation/AgentControls.d.ts +26 -0
  33. package/dist/types/presentation/Agentico.d.ts +23 -0
  34. package/dist/types/presentation/AgenticoContext.d.ts +305 -0
  35. package/dist/types/presentation/AgenticoToggle.d.ts +17 -0
  36. package/dist/types/presentation/ManualEntryRunner.d.ts +22 -0
  37. package/dist/types/presentation/OrchestratorRunner.d.ts +12 -0
  38. package/dist/types/presentation/ResultDestinationPicker.d.ts +29 -0
  39. package/dist/types/presentation/SubagentRunner.d.ts +48 -0
  40. package/dist/types/presentation/deriveHistoryTitle.d.ts +10 -0
  41. package/dist/types/presentation/liveAnchorDestination.d.ts +10 -0
  42. package/dist/types/presentation/reports/GenericResultPreview.d.ts +11 -0
  43. package/dist/types/presentation/reports/subagentReportRegistry.d.ts +58 -0
  44. package/dist/types/presentation/useAIModelCatalog.d.ts +9 -0
  45. package/dist/types/presentation/useAgent.d.ts +140 -0
  46. package/dist/types/presentation/useAgenticoPageContext.d.ts +12 -0
  47. package/dist/types/presentation/useSubagentComponentContext.d.ts +44 -0
  48. package/llms.txt +35 -0
  49. package/package.json +79 -0
@@ -0,0 +1,83 @@
1
+ import type { z } from 'zod';
2
+ import type { AIAttachment } from '@llmnative/react';
3
+ /** Rif mutabile, sempre aggiornato da useAgent.ts all'inizio di ogni turno (roundTrip 0) con
4
+ * gli allegati grezzi (base64) di QUESTO turno — mai un valore statico catturato una volta:
5
+ * un tool creato da getTools() (chiamato una sola volta per sessione) deve comunque vedere gli
6
+ * allegati dell'ULTIMO messaggio, non quelli del primo. Esiste per un solo motivo: un allegato
7
+ * testuale grande (es. un CSV da alcuni MB) non può essere incollato per intero nel messaggio
8
+ * al modello — supererebbe qualunque finestra di contesto — ma un tool (es.
9
+ * extract_csv_column) può leggerlo direttamente da qui, bypassando quel limite. `undefined` =
10
+ * nessun allegato in questo turno. */
11
+ export interface LatestAttachmentsRef {
12
+ current: AIAttachment[] | undefined;
13
+ }
14
+ /** Tool che il modello può scegliere di invocare durante la conversazione — `execute` è
15
+ * l'implementazione VERA, mai inviata al provider (solo name/description/inputSchema lo sono,
16
+ * via useAgent, convertito in JSON Schema in quel punto — vedi mcpTool.ts). Tipicamente
17
+ * chiude su `params`/`context` dell'agente per rieseguire il controller con argomenti
18
+ * diversi suggeriti dall'utente in un messaggio di follow-up. */
19
+ export interface AgentTool {
20
+ name: string;
21
+ description: string;
22
+ /** Zod, non JSON Schema — sorgente unica di validazione/tipi. Serializzato a JSON
23
+ * Schema solo al bordo del provider AI (useAgent.ts), mai qui. */
24
+ inputSchema: z.ZodType;
25
+ execute: (input: Record<string, unknown>) => Promise<unknown>;
26
+ /** Etichetta human-friendly per la UI mentre il tool gira (es. "Ricontrollo
27
+ * https://example.com/about…") — puramente deterministica/locale, MAI generata
28
+ * chiedendo al modello di narrare se stesso (inaffidabile, spreca token, e duplica
29
+ * un'informazione — name+input — già strutturata nella risposta del provider). Assente =
30
+ * la UI mostra un'etichetta generica col solo nome del tool. */
31
+ describeInvocation?: (input: Record<string, unknown>) => string;
32
+ /** Frase completa e discorsiva sullo scopo GENERALE del tool (es. "Sto ricontrollando il
33
+ * sito per aggiornare branding e stile…"), SENZA i parametri della singola chiamata —
34
+ * quelli li mostra già la riga della tool call sotto, via describeInvocation. Usata SOLO
35
+ * per il turno "sto pensando" che ha richiesto questo tool senza scrivere testo libero
36
+ * (vedi useAgent.ts/thinkingDisplayLabel): senza questo campo, quella riga ripeterebbe
37
+ * parola per parola l'etichetta della tool call subito sotto — la stessa informazione
38
+ * scritta due volte una sopra l'altra. Assente = ripiega su describeInvocation (meglio
39
+ * di niente, ma con la ripetizione). */
40
+ describeIntent?: string;
41
+ }
42
+ export interface AgentDefinition<TParams, TContext, TResult> {
43
+ /** Gira sempre, con o senza AI — estrazione/parsing deterministico dei dati grezzi. */
44
+ buildContext(params: TParams): Promise<TContext> | TContext;
45
+ /** Prompt finale da inviare al provider — già completamente renderizzato (nessuna
46
+ * sostituzione ulteriore lato hook). */
47
+ buildPrompt(params: TParams, context: TContext): string;
48
+ /** Incorpora un messaggio libero dell'utente in un turno di follow-up (conversazione già
49
+ * avviata da run(), vedi useAgent.sendMessage) — DEVE ripetere il contratto di output
50
+ * (schema atteso) di buildPrompt: il modello tende a rispondere in prosa libera dopo
51
+ * qualche turno se non gli si ricorda il formato, e un fallimento di parseResponse a
52
+ * quel punto farebbe silenziosamente perdere il risultato del turno all'utente. */
53
+ buildFollowUpPrompt(userText: string, params: TParams, context: TContext): string;
54
+ /** Valida/interpreta la risposta grezza dell'AI. `null` = risposta non valida → fallback. */
55
+ parseResponse(raw: string, params: TParams, context: TContext): TResult | null;
56
+ /** Risultato deterministico usato quando l'AI è disabilitata, non disponibile, o la sua
57
+ * risposta non è valida. */
58
+ fallback(params: TParams, context: TContext): TResult;
59
+ /** Frase da mostrare nel log di attività quando l'utente preme "Continua senza AI" (vedi
60
+ * useAgent.runFallback) — descrive COSA rappresenta il risultato appena prodotto per
61
+ * QUESTO agente specifico, perché runFallback (generico per costruzione, non conosce la
62
+ * forma di TResult) non può saperlo da solo. Per un agente il cui fallback produce un
63
+ * output azionabile (import HTML, tema, redirect) basta una conferma breve ("pronto per la
64
+ * revisione qui sotto"); per l'orchestratore è FONDAMENTALE: il suo fallback non è un vero
65
+ * handoff (non può indovinare l'intento dell'utente senza AI), è SOLO un messaggio da
66
+ * leggere — a differenza di un turno AI riuscito, il cui testo libero è già visibile di suo
67
+ * nel log "sto pensando", qui non esiste un turno equivalente che lo mostri, quindi senza
68
+ * questo hook il messaggio sparirebbe nel nulla (bug osservato: click su "Continua senza
69
+ * AI", nessun feedback, l'utente non sa se l'import è riuscito o no). Assente = etichetta
70
+ * generica ("Continuo senza AI — uso il risultato deterministico."). */
71
+ describeFallback?(result: TResult): string;
72
+ /** Tool disponibili al modello durante l'intera conversazione (primo turno e ogni
73
+ * messaggio di follow-up) — assente o [] = nessun tool per questo agente.
74
+ * `attachmentsRef` — vedi LatestAttachmentsRef: solo i tool che ne hanno davvero bisogno
75
+ * (oggi extract_csv_column) lo leggono, tutti gli altri lo ignorano tranquillamente
76
+ * (parametro opzionale, retrocompatibile con ogni getTools già scritto). */
77
+ getTools?(params: TParams, context: TContext, attachmentsRef?: LatestAttachmentsRef): AgentTool[];
78
+ /** Id di micro-prompt trasversali (vedi microPrompts.ts) da aggiungere in coda a
79
+ * buildPrompt/buildFollowUpPrompt — applicati centralmente da useAgent, non da questo
80
+ * agente: qui si dichiara solo QUALI si vogliono, mai il loro testo. Assente o [] =
81
+ * nessuno. */
82
+ microPromptIds?: string[];
83
+ }
@@ -0,0 +1,7 @@
1
+ import type { SubagentManifest } from '../subagentManifest';
2
+ /** Help completo di UN subagent — tutte le sue command, la sua descrizione. */
3
+ export declare function renderSubagentCli<TParams, TContext, TResult>(manifest: SubagentManifest<TParams, TContext, TResult>): string;
4
+ /** Indice sintetico di TUTTI i subagent registrati — una riga per subagent, i suoi comandi
5
+ * elencati per nome. Questa è la vista che l'orchestratore Agentico usa come punto di partenza
6
+ * ("cosa esiste") prima di approfondire un singolo subagent con renderSubagentCli(). */
7
+ export declare function renderRegistryCli(registry: ReadonlyArray<SubagentManifest<any, any, any>>): string;
@@ -0,0 +1,13 @@
1
+ import type { AgentTool, LatestAttachmentsRef } from './agentDefinition';
2
+ export interface CrossAgentToolContext {
3
+ /** Raw attachments of the current turn — for tools that read files too big for the prompt. */
4
+ attachmentsRef: LatestAttachmentsRef | undefined;
5
+ /** Per-conversation scratchpad shared with the subagent manifests (see withCollected). */
6
+ collected: Record<string, unknown>;
7
+ /** CORS-safe fetch of the host app (the framework's proxyFetch). */
8
+ proxyFetch: typeof fetch;
9
+ }
10
+ export type CrossAgentToolFactory = (context: CrossAgentToolContext) => AgentTool[];
11
+ /** Registers the host's cross-agent tools. Called once at startup; a later call replaces the set. */
12
+ export declare function registerCrossAgentTools(...toolFactories: CrossAgentToolFactory[]): void;
13
+ export declare function createCrossAgentTools(context: CrossAgentToolContext): AgentTool[];
@@ -0,0 +1,5 @@
1
+ import type { AgentDefinition } from './agentDefinition';
2
+ import type { SubagentManifest } from './subagentManifest';
3
+ export declare function defineSubagent<TParams, TContext, TResult>(config: Omit<SubagentManifest<TParams, TContext, TResult>, 'definition'> & {
4
+ definition: AgentDefinition<TParams, TContext, TResult>;
5
+ }): SubagentManifest<TParams, TContext, TResult>;
@@ -0,0 +1,5 @@
1
+ import type { ResultDestination } from './resultDestination';
2
+ /** Chiamata dall'host UNA VOLTA, a livello di modulo — un secondo giro SOSTITUISCE il registro
3
+ * precedente, stesso principio di registerSubagents. */
4
+ export declare function registerDestinations(destinations: Record<string, ResultDestination<any>>): void;
5
+ export declare function getDestinationRegistry(): Record<string, ResultDestination<any>>;
@@ -0,0 +1,48 @@
1
+ import type { AIConversationTurn } from '@llmnative/react';
2
+ /** Stessa forma di AgentActivityEntry (agentico/presentation/useAgent.ts) — ridefinita qui invece
3
+ * di importata: il domain layer non dipende dal presentation layer, e questi campi sono
4
+ * semplici dati (mai funzioni), quindi TypeScript accetta un AgentActivityEntry[] ovunque sia
5
+ * richiesto questo tipo per compatibilità strutturale, senza bisogno di un cast esplicito. */
6
+ export interface EntityChatActivityEntry {
7
+ id: string;
8
+ kind: 'user' | 'thinking' | 'tool';
9
+ label: string;
10
+ status: 'running' | 'done' | 'error' | 'stopped';
11
+ detail?: string;
12
+ toolNames?: string[];
13
+ }
14
+ export interface EntityChatSnapshot {
15
+ /** Host scope (tenant, company…) the chat belongs to — see AgenticoScope. */
16
+ scopeId: string;
17
+ subagentId: string;
18
+ entityId: string;
19
+ /** TParams grezzo (pre-manifest.toParams, es. `{ url }` per theme) con cui la sessione
20
+ * originale era stata avviata — necessario per ricostruire context/tools al resume (vedi
21
+ * useAgent.resume/SubagentRunner.resumeSeed): senza, `manifest.toParams` non avrebbe nulla
22
+ * da validare/convertire per riavviare la sessione. */
23
+ params: Record<string, unknown>;
24
+ history: AIConversationTurn[];
25
+ activity: EntityChatActivityEntry[];
26
+ savedAt: number;
27
+ /** Etichetta human-friendly dell'entità (es. il nome del tema) — usata dallo storico chat
28
+ * di Agentico (vedi Agentico.tsx) per mostrare "cosa" senza dover rileggere l'entità stessa
29
+ * dal suo DataProviderAdapter (che questo store, domain-side, non possiede). */
30
+ title: string;
31
+ }
32
+ /** Sets the localStorage key of the chat store — call once at startup, before any read. */
33
+ export declare function configureEntityChatStore(options: {
34
+ storageKey: string;
35
+ }): void;
36
+ /** La chat attualmente associata a un'entità — `null` se non ne è mai stata salvata una (o è
37
+ * stata rimossa, vedi removeEntityChat). */
38
+ export declare function getEntityChat(scopeId: string, subagentId: string, entityId: string): EntityChatSnapshot | null;
39
+ /** Sovrascrive (o crea) la chat associata a questa entità — vedi il commento in testa al file
40
+ * per perché è sempre un overwrite, mai un accumulo. */
41
+ export declare function saveEntityChat(snapshot: Omit<EntityChatSnapshot, 'savedAt'>): void;
42
+ /** Rimuove la chat di un'entità — chiamata quando l'entità stessa viene eliminata, altrimenti
43
+ * resterebbe un'entry orfana senza nulla a cui riattaccarsi. */
44
+ export declare function removeEntityChat(scopeId: string, subagentId: string, entityId: string): void;
45
+ /** Tutte le chat salvate di uno scope, più recenti prima — per lo storico di Agentico
46
+ * (Agentico.tsx), che le mescola across subagent (theme, redirects, html-to-liquid) in un'unica
47
+ * lista ordinata per data. */
48
+ export declare function listEntityChats(scopeId: string): EntityChatSnapshot[];
@@ -0,0 +1 @@
1
+ export declare function extractErrorMessage(err: unknown): string;
@@ -0,0 +1 @@
1
+ export declare function extractJsonBlock(raw: string): string;
@@ -0,0 +1,3 @@
1
+ import type { ResultDestination } from './resultDestination';
2
+ export declare const JSON_EXPORT_DESTINATION_ID = "json-export";
3
+ export declare const jsonExportDestination: ResultDestination<unknown>;
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ export interface McpTool {
3
+ name: string;
4
+ description: string;
5
+ inputSchema: Record<string, unknown>;
6
+ outputSchema?: Record<string, unknown>;
7
+ }
8
+ export declare function toJsonSchema(schema: z.ZodType): Record<string, unknown>;
9
+ export declare function toMcpTool(name: string, description: string, inputSchema: z.ZodType, outputSchema?: z.ZodType): McpTool;
@@ -0,0 +1,20 @@
1
+ export interface MicroPrompt {
2
+ id: string;
3
+ text: string;
4
+ }
5
+ /** Chiede al modello di chiudere SEMPRE la propria risposta testuale con un riepilogo
6
+ * conciso di cosa ha fatto — utile perché l'utente altrimenti vede solo il log delle tool
7
+ * call/turni "sto pensando" (già deterministico, mai narrato dal modello) ma nessuna sintesi
8
+ * finale in linguaggio naturale di cosa è stato effettivamente ottenuto.
9
+ *
10
+ * Il riepilogo va DOPO il blocco ```json — mai prima, mai a comporlo — cosi
11
+ * extractJsonBlock() lo trova comunque cercando il fence ovunque nel testo, e il riepilogo
12
+ * stesso resta visibile all'utente come testo libero accanto al JSON (vedi DetailContent in
13
+ * AgentActivityLog.tsx, che già sa render testo + blocco codice misti nello stesso turno). */
14
+ export declare const SUMMARY_MICRO_PROMPT: MicroPrompt;
15
+ /** Registro dei micro-prompt disponibili, per id. */
16
+ export declare const MICRO_PROMPT_REGISTRY: Record<string, MicroPrompt>;
17
+ /** Applica in coda al prompt verticale i micro-prompt richiesti per id — no-op se l'agente
18
+ * non ne richiede nessuno (o richiede un id sconosciuto, ignorato silenziosamente: un id
19
+ * scritto male non deve far fallire l'intero prompt). */
20
+ export declare function applyMicroPrompts(prompt: string, ids: string[] | undefined): string;
@@ -0,0 +1,34 @@
1
+ import type { AgentDefinition } from '../agentDefinition';
2
+ import { type OrchestratorHandoff, type OrchestratorResult } from './prompt';
3
+ export interface OrchestratorAgentParams {
4
+ /** The opening message — the user's free request, or a goal pre-seeded from a subagent card. */
5
+ userGoal: string;
6
+ /** "Where the user is now" (see useAgenticoPageContext), captured once at run(). */
7
+ pageContext: string | null;
8
+ /** Subagent the starting page is pinned to, `null` for a generic chat. Restricts the
9
+ * cross-agent tools to the ones that subagent declares (SubagentManifest.crossAgentToolIds). */
10
+ scopedSubagentId: string | null;
11
+ }
12
+ export interface OrchestratorAgentContext {
13
+ cliCatalog: string;
14
+ /** Written by the execute() of the handoff tool invoked in this turn and read by parseResponse:
15
+ * the only way a tool call outcome reaches parseResponse, which only sees the final text.
16
+ * Reset every turn — a handoff is valid only for the turn that invoked it. */
17
+ handoff: {
18
+ current: OrchestratorHandoff | null;
19
+ };
20
+ /** Complete outputs of the cross-agent tools of this conversation (see crossAgentTools.ts). */
21
+ collected: Record<string, unknown>;
22
+ }
23
+ /** User-facing labels of the orchestrator (from the `agentico` i18n namespace). */
24
+ export interface OrchestratorLabels {
25
+ /** Chat message used when the AI is not available. */
26
+ unavailable: string;
27
+ /** Log line of "continue without AI". */
28
+ continueWithoutAi: string;
29
+ /** Tool call label while a handoff is prepared — `{label}` = subagent label. */
30
+ preparing: string;
31
+ /** "Thinking" label of the turn that requested the handoff — `{label}` = subagent label. */
32
+ collecting: string;
33
+ }
34
+ export declare function createOrchestratorAgentDefinition(labels: OrchestratorLabels): AgentDefinition<OrchestratorAgentParams, OrchestratorAgentContext, OrchestratorResult>;
@@ -0,0 +1,17 @@
1
+ export interface OrchestratorHandoff {
2
+ subagentId: string;
3
+ command: string;
4
+ params: Record<string, unknown>;
5
+ }
6
+ export type OrchestratorResult = {
7
+ kind: 'chat';
8
+ message: string;
9
+ } | ({
10
+ kind: 'handoff';
11
+ } & OrchestratorHandoff);
12
+ export declare function describeOrchestratorResponseContract(): string;
13
+ export declare function buildOrchestratorPrompt(userGoal: string, cliCatalog: string, pageContext?: string | null): string;
14
+ /** `handoff` arriva dal context della sessione (settato dall'execute() del tool invocato in
15
+ * questo turno, vedi agenticoOrchestratorAgent.ts) — se presente ha sempre priorità sul testo
16
+ * libero del modello, che a quel punto è solo un commento discorsivo sul tool appena invocato. */
17
+ export declare function parseOrchestratorResponse(raw: string, handoff: OrchestratorHandoff | null): OrchestratorResult;
@@ -0,0 +1,29 @@
1
+ export interface AgenticoPrompts {
2
+ /** First paragraph of the orchestrator prompt: who the orchestrator is and what it does. */
3
+ orchestratorIntro: string;
4
+ /** Bullet rules of the orchestrator response contract (generic ones first, host ones after). */
5
+ responseRules: string[];
6
+ responseRulesHeading: string;
7
+ toolsHeading: string;
8
+ pageContextHeading: string;
9
+ pageContextIntro: string;
10
+ userRequestHeading: string;
11
+ /** CLI catalog shown when no subagent is registered. */
12
+ noToolsAvailable: string;
13
+ /** Sent to the model when it keeps calling tools past the round-trip limit. */
14
+ stopCallingTools: string;
15
+ /** Returned to the model by a handoff tool: the work is queued, not done. `{label}` = subagent. */
16
+ handoffQueued: string;
17
+ /** Closing-summary micro-prompt (see microPrompts.ts). */
18
+ closingSummary: string;
19
+ /** Page context preamble when several subagents are anchored on the same page. */
20
+ multipleCandidates: string;
21
+ }
22
+ export declare const agenticoPromptsEn: AgenticoPrompts;
23
+ export declare const agenticoPromptsIt: AgenticoPrompts;
24
+ /** Sets the model-facing pack once at startup — e.g. `configureAgenticoPrompts({ ...agenticoPromptsIt,
25
+ * responseRules: [...agenticoPromptsIt.responseRules, ...hostRules] })`. Fields left out keep their value. */
26
+ export declare function configureAgenticoPrompts(prompts: Partial<AgenticoPrompts>): void;
27
+ export declare function getAgenticoPrompts(): AgenticoPrompts;
28
+ /** Restores the English defaults (tests). */
29
+ export declare function resetAgenticoPrompts(): void;
@@ -0,0 +1,24 @@
1
+ import type { DataProviderAdapter, StorageProviderAdapter } from '@llmnative/react';
2
+ export interface DestinationContext {
3
+ /** Id of the host scope the result is saved into (a tenant, a company…) — see AgenticoScope. */
4
+ scopeId: string;
5
+ dataProvider: DataProviderAdapter;
6
+ storageProvider: StorageProviderAdapter | null;
7
+ proxyFetch: typeof fetch;
8
+ }
9
+ /** Esito opzionale di un apply — `id` (usato da destinazioni tenant-wide come
10
+ * componentLibraryDestination per far sapere al chiamante l'id della risorsa creata/aggiornata,
11
+ * un'informazione che una destinazione generica non può conoscere da sola: vedi
12
+ * ResultDestinationPicker.commitEntityChat). `void` per le destinazioni che non hanno nulla da
13
+ * restituire — non un cambio breaking, tutte le destinazioni esistenti restano valide. */
14
+ export type ResultDestinationOutcome = {
15
+ id?: string;
16
+ } | void;
17
+ export interface ResultDestination<TResult = unknown> {
18
+ id: string;
19
+ label: string;
20
+ /** `meta` è il TParams con cui il subagent è stato lanciato (es. `{ url }` per theme) —
21
+ * alcuni risultati non si bastano da soli (es. ThemeExtractResult non porta l'URL
22
+ * sorgente, servito solo per nominare il tema). */
23
+ apply(result: TResult, ctx: DestinationContext, meta: Record<string, unknown>): Promise<ResultDestinationOutcome>;
24
+ }
@@ -0,0 +1,172 @@
1
+ import type { z } from 'zod';
2
+ import type { AgentDefinition } from './agentDefinition';
3
+ /** Una singola capability offerta dal subagent (oggi quasi sempre una sola per manifest). */
4
+ export interface SubagentCommand {
5
+ /** Nome del comando, snake_case, univoco nel subagent — es. "extract", "import". */
6
+ name: string;
7
+ /** Una riga — cosa fa questo comando. */
8
+ summary: string;
9
+ /** Zod, non JSON Schema — sorgente unica di validazione/tipi dei parametri del RUN
10
+ * primario (buildContext/buildPrompt), non di un tool di follow-up a metà conversazione
11
+ * (quelli sono AgentTool.inputSchema). Serializzato a JSON Schema solo ai bordi (render
12
+ * CLI, futuro MCP tool) via mcpTool.ts — mai qui. */
13
+ inputSchema: z.ZodType;
14
+ /** Zod dei dati che compongono il TResult — opzionale: oggi la forma del risultato è
15
+ * documentata solo in prosa da describeOutput(); questo schema serve a un futuro
16
+ * consumer machine-readable (es. la CLI) che debba validare/tipizzare l'output, non al
17
+ * prompt AI né al CLI help testuale. */
18
+ outputSchema?: z.ZodType;
19
+ /** Testo che descrive la forma della risposta — quasi sempre un riuso diretto della
20
+ * describe<Feature>ResponseContract() già scritta per il prompt AI (domain/prompts/<feature>.ts):
21
+ * nessuna duplicazione, la stessa stringa serve sia da contratto per il modello sia da
22
+ * sezione OUTPUT del CLI help. */
23
+ describeOutput(): string;
24
+ /** Un invocazione realistica, mostrata nella sezione EXAMPLE del CLI help. */
25
+ example?: string;
26
+ /** Riassunto in una riga per un UMANO che guarda la card di Agentico (SubagentUsageCardView,
27
+ * Agentico.tsx) — NON per il modello/CLI, quelli restano su `summary` (che può permettersi
28
+ * di essere tecnico/preciso perché è machine-facing). Assente = la card ripiega su `summary`
29
+ * (comportamento di oggi, invariato per i subagent che non ne hanno ancora bisogno). Due
30
+ * pubblici diversi per lo stesso comando: un LLM ha bisogno di casi limite ed enumerazioni
31
+ * per non sbagliare la chiamata, un umano ha bisogno di una frase che si legge in un
32
+ * secondo — mai lo stesso testo per entrambi. */
33
+ humanSummary?: string;
34
+ /** Come `humanSummary` ma per-campo (chiave = nome campo in `inputSchema`) — sostituisce SOLO
35
+ * nella card umana la `.describe()` Zod di quel campo (che resta la fonte tecnica per JSON
36
+ * Schema/prompt/CLI, invariata). Un campo assente da questa mappa mostra comunque la
37
+ * descrizione tecnica nella card — non è un obbligo compilare tutti i campi qui, solo quelli
38
+ * la cui descrizione tecnica è troppo densa per un umano di passaggio. Ignorato quando
39
+ * `humanSummaryOnly` è true (vedi sotto). */
40
+ humanFieldHints?: Record<string, string>;
41
+ /** Quando true, la card umana mostra SOLO `humanSummary` (che allora deve raccontare da solo,
42
+ * in prosa naturale, cosa serve e come recuperarlo) — niente elenco di campi con badge
43
+ * richiesto/opzionale, niente esempio in sintassi CLI. Serve per comandi il cui schema
44
+ * tecnico (N campi separati) non rispecchia come un umano pensa l'input — es. redirects:
45
+ * lo schema ha 4 campi (incomingPaths/destinationPaths/trafficByPath/siteHostname) ma un
46
+ * umano ragiona in termini di "cosa mando" (un CSV, l'accesso a Search Console, una sitemap),
47
+ * non di quei 4 nomi — un elenco a campi separati implicherebbe erroneamente che vadano
48
+ * forniti come input distinti, quando in realtà UNA fonte sola (es. un CSV con status code)
49
+ * può bastare da sola per riempirli entrambi. Assente/false = comportamento di oggi (elenco
50
+ * campi), corretto per un comando i cui campi SONO l'input diretto dell'utente (es. `url` di
51
+ * theme). */
52
+ humanSummaryOnly?: boolean;
53
+ /** Regola/i decisionale/i ad alta visibilità per l'ORCHESTRATORE Agentico — iniettata nel
54
+ * "Contesto pagina" (vedi useAgenticoPageContext/agentico-orchestrator.ts, che istruisce
55
+ * esplicitamente il modello a controllare quella sezione PRIMA di chiedere qualunque
56
+ * parametro), non nella `.describe()` Zod dei campi. Le due cose sembrano ridondanti ma non
57
+ * lo sono: la `.describe()` di un campo il modello la vede solo quando ha già deciso di
58
+ * ispezionare/chiamare quel tool specifico — un contesto profondo, letto in modo
59
+ * inconsistente (bug osservato: la stessa regola, "un URL/sitemap di un sito live è SEMPRE
60
+ * destinationPaths", a volte veniva dedotta correttamente e a volte no, nella stessa
61
+ * conversazione). Il Contesto pagina invece è la PRIMA cosa che il modello controlla per
62
+ * istruzione esplicita — la stessa regola lì è affidabile. Non duplicare qui la spiegazione
63
+ * completa dei campi (quella resta nella card/nello schema): solo le regole che altrimenti
64
+ * richiederebbero al modello di "scoprire" una logica che invece va data per scontata subito. */
65
+ orchestratorHint?: string;
66
+ }
67
+ /** Descrizione pubblica e discoverable via CLI (nessuna chiamata LLM) di un subagent —
68
+ * un modulo per cartella (es. domain/subagents/theme/manifest.ts), esportato
69
+ * dal barrel della cartella ed elencato in subagentRegistry.ts. */
70
+ export interface SubagentManifest<TParams = any, TContext = any, TResult = any> {
71
+ /** Id stabile, usato come chiave del registry e prefisso dei tool generati dall'orchestratore
72
+ * Agentico (`${id}_${command.name}`) — mai esposto all'utente, solo a modello/codice. */
73
+ id: string;
74
+ /** Etichetta human-friendly, mostrata nella grid di /tools. */
75
+ label: string;
76
+ /** Nome icona del framework (@llmnative/react Icon), usato da grid e CLI header. */
77
+ icon: string;
78
+ /** Prosa più lunga — cosa fa e come, sezione DESCRIPTION del CLI help. */
79
+ description: string;
80
+ /** Le capability offerte — oggi tipicamente un solo comando primario per subagent. */
81
+ commands: SubagentCommand[];
82
+ /** Route dell'indice DUREVOLE di questo subagent — dove vivono le entità che ha prodotto/
83
+ * modificato. Contratto condiviso a livello di ROUTING, non di componente React: le entità
84
+ * di ogni subagent hanno esigenze reali diverse (redirects ha un indice leggero custom
85
+ * scritto per questo, theme/html-to-liquid riusano le pagine già esistenti e più ricche —
86
+ * ThemesPage/LibraryComponentsPage via Grid — invece di duplicarle in una lista povera solo
87
+ * per uniformità visiva). Ogni subagent DEVE dichiararlo: `ToolsPage` naviga sempre qui al
88
+ * click sulla card (non esiste un fallback generico allo storico-run — vedi menu.ts). */
89
+ indexPath: string;
90
+ /** Id dei ResultDestination (vedi destinationRegistry.ts) che accettano il TResult di
91
+ * questo subagent — 'json-export' è sempre valido per qualunque TResult e non va elencato
92
+ * qui esplicitamente (vedi ResultDestinationPicker). */
93
+ destinationIds: string[];
94
+ /** Sottoinsieme di `destinationIds` applicato AUTOMATICAMENTE (da SubagentRunner) a ogni
95
+ * risultato/aggiornamento — non richiede un click su ResultDestinationPicker. Per subagent
96
+ * dove il risultato stesso È il dato definitivo (oggi solo redirects: vedi
97
+ * redirectsSaveDestination/docs/30-redirects-system.md), non un export opzionale che
98
+ * l'utente sceglie se e quando applicare. Assente/vuoto = comportamento invariato (solo
99
+ * apply manuale via picker). */
100
+ autoApplyDestinationIds?: string[];
101
+ /** Sottoinsieme dei tool cross-agent condivisi (domain/services/tools/ — read_sitemap,
102
+ * scrape_page, list_csv_columns, extract_csv_column) che QUESTO subagent usa davvero, per
103
+ * nome (`AgentTool.name`). L'orchestratore Agentico (agenticoOrchestratorAgent.ts) li
104
+ * espone TUTTI quando la conversazione non è ancora scoped a un subagent specifico (chat
105
+ * generica — non si sa ancora quale servirà), ma li RESTRINGE a questo elenco quando la
106
+ * pagina di partenza è pinnata a un subagent (vedi useAgenticoPageContext + `usageCard`) —
107
+ * un subagent vede solo il proprio sottoinsieme, mai tutti gli strumenti disponibili
108
+ * nell'app. Assente/vuoto = nessun tool di raccolta dati condiviso (es. theme/
109
+ * html-to-liquid: i loro parametri arrivano già di mano dall'utente — url, markup — senza
110
+ * bisogno di leggere una sitemap o un CSV). */
111
+ crossAgentToolIds?: string[];
112
+ /** Merges what the cross-agent tools collected in this conversation (see crossAgentTools.ts,
113
+ * `collected`) into the command input right before the handoff — the collected values are
114
+ * complete, while the copy the model passed may be truncated. Absent = input used as is. */
115
+ withCollected?(input: Record<string, unknown>, collected: Record<string, unknown>): Record<string, unknown>;
116
+ /** Il vero esecutore — lo stesso AgentDefinition consumato da useAgent altrove nell'app. */
117
+ definition: AgentDefinition<TParams, TContext, TResult>;
118
+ /** Converte l'input validato di un comando (raccolto in conversazione dall'orchestratore, o
119
+ * passato da un futuro chiamante CLI) nei TParams che l'AgentDefinition si aspetta. */
120
+ toParams(input: Record<string, unknown>): TParams;
121
+ /** Percorso "senza AI" alternativo all'intera conversazione orchestratore — solo per un
122
+ * subagent il cui INTERO input primario è un unico blob di testo grezzo (oggi solo
123
+ * html-to-liquid: `markup`), mai per uno con più parametri distinti da raccogliere (theme
124
+ * ha bisogno di un `url`, redirects di due liste di path — un singolo testo non basta a
125
+ * riempirli, un form vero servirebbe, fuori scope per ora). Usato SOLO quando la
126
+ * conversazione è già scoped a QUESTO subagent (vedi AgenticoContext.startOrchestrator
127
+ * `scopedSubagentId`, un solo target possibile, niente da instradare) E l'orchestratore
128
+ * stesso non riesce a partire (AI giù) — l'utente incolla il testo direttamente, zero
129
+ * round-trip di rete, mai un tentativo AI (vedi ManualEntryRunner). `prompt` è il messaggio
130
+ * statico mostrato in chat al posto del solito hint; `fromRawText` converte quel testo nei
131
+ * TParams — può lanciare (es. testo vuoto), il chiamante lo mostra come errore. Assente =
132
+ * nessun percorso manuale (comportamento invariato: serve comunque l'orchestratore). */
133
+ manualEntry?: {
134
+ prompt: string;
135
+ fromRawText(rawText: string): TParams;
136
+ };
137
+ /** Titolo breve per l'header di Agentico/lo storico chat, derivato dai parametri RAW di
138
+ * QUESTO subagent (lo stesso `Record<string, unknown>` grezzo passato a `toParams`, non il
139
+ * TParams già convertito — SubagentRunner lo ha disponibile senza doverlo ri-convertire) —
140
+ * es. theme: hostname da `params.url`; redirects: `params.siteHostname`. Agentico
141
+ * (SubagentRunner) non conosce la forma dei parametri di nessun subagent specifico, quindi
142
+ * non può indovinare quale campo mostrare: il manifest lo dichiara esplicitamente. Assente =
143
+ * ripiega su `label` (comportamento corretto anche per subagent il cui unico campo (es.
144
+ * html-to-liquid: `markup`, il testo incollato dall'utente) non è mai un titolo leggibile). */
145
+ deriveHistoryTitle?(params: Record<string, unknown>): string | undefined;
146
+ /** Punti di ancoraggio semantico subagent↔componente — keyed per nome componente scelto
147
+ * liberamente dall'autore del subagent, ma per coerenza tra subagent (oggi solo `theme`,
148
+ * futuri: redirects/html-to-liquid) usare la convenzione: 'indexList' per il componente che
149
+ * elenca le entità (naviga verso un editor nuovo pre-compilato quando riceve un risultato) e
150
+ * 'editor' per il componente che ne modifica una aperta (si popola da solo). Un consumer
151
+ * indipendente che ascolta solo una fetta del risultato (es. SiteEditorPage per i soli campi
152
+ * di site-branding) usa una chiave propria, descrittiva del suo ruolo (es. 'siteBranding'),
153
+ * non una delle due sopra. Letto da
154
+ * useSubagentComponentContext (presentation/hooks), chiamato DAL componente React stesso al
155
+ * mount, mai dalla pagina che lo ospita: chi monta il componente ottiene il contesto
156
+ * Agentico corretto gratis, senza ricostruirlo pagina per pagina (vedi SubagentCommand.
157
+ * orchestratorHint/humanSummary* per il vecchio meccanismo a livello di pagina, ancora usato
158
+ * da redirects/html-to-liquid finché non vengono migrati). */
159
+ componentContexts?: Record<string, SubagentComponentContext>;
160
+ }
161
+ /** Coppia di messaggi per UN punto di ancoraggio componente↔subagent (vedi
162
+ * SubagentManifest.componentContexts) — due pubblici diversi per lo stesso aggancio, mai lo
163
+ * stesso testo per entrambi (stesso principio di SubagentCommand.humanSummary vs summary). */
164
+ export interface SubagentComponentContext {
165
+ /** Per il prompt dell'orchestratore LLM — iniettato nel "Contesto pagina" quando questo
166
+ * componente è montato (vedi AgenticoContext.componentAnchors). */
167
+ agenticoHint: string;
168
+ /** Mostrato in chat all'utente quando Agentico si aggancia a questo componente — sostituisce
169
+ * la card a campi (SubagentUsageCardView) per gli anchor component-based: una frase, non un
170
+ * modulo da compilare. */
171
+ userMessage: string;
172
+ }
@@ -0,0 +1,11 @@
1
+ import type { SubagentManifest } from './subagentManifest';
2
+ /** Chiamata dall'host UNA VOLTA, a livello di modulo (non dentro un componente React) — un
3
+ * secondo giro SOSTITUISCE il registro precedente, non lo somma: niente doppie registrazioni
4
+ * accidentali (es. da un hot-reload) da dover deduplicare a valle. */
5
+ export declare function registerSubagents(manifests: ReadonlyArray<SubagentManifest<any, any, any>>): void;
6
+ /** Letto da codice che ha bisogno dell'INTERO elenco (es. la Grid di ToolsPage, il catalogo CLI
7
+ * dell'orchestratore) — mai per costruzione statica a import-time: se questo ritorna `[]` è
8
+ * quasi sempre perché `registerSubagents` non è ancora stato chiamato (o il modulo che lo chiama
9
+ * non è ancora stato importato) prima di questo punto, non un progetto senza subagent. */
10
+ export declare function getSubagentRegistry(): ReadonlyArray<SubagentManifest<any, any, any>>;
11
+ export declare function findSubagentManifest(id: string): SubagentManifest<any, any, any> | undefined;
@@ -0,0 +1,37 @@
1
+ import type { SubagentCommand, SubagentManifest } from './subagentManifest';
2
+ export interface SubagentUsageField {
3
+ key: string;
4
+ type: string;
5
+ required: boolean;
6
+ /** Tecnica, machine-facing — la `.describe()` Zod tale e quale, stessa fonte del JSON
7
+ * Schema/CLI help. Verbosa ed enumerativa per progettazione: un LLM sbaglia meno con casi
8
+ * limite espliciti, un umano di passaggio no. */
9
+ description: string;
10
+ /** Human-facing, per la card di Agentico — `command.humanFieldHints[key]` se presente,
11
+ * altrimenti ripiega su `description` (mai vuota, mai un secondo giro di scrittura
12
+ * obbligato per ogni subagent). */
13
+ humanDescription: string;
14
+ }
15
+ export interface SubagentUsageCard {
16
+ subagentId: string;
17
+ label: string;
18
+ commandName: string;
19
+ /** Tecnica, machine-facing — vedi SubagentCommand.summary. */
20
+ summary: string;
21
+ /** Human-facing — `command.humanSummary` se presente, altrimenti ripiega su `summary`. */
22
+ humanSummary: string;
23
+ fields: SubagentUsageField[];
24
+ example?: string;
25
+ /** Quando true, il consumer UI (SubagentUsageCardView) mostra SOLO `humanSummary` — niente
26
+ * `fields`/`example` (pensati per l'occhio tecnico) — vedi SubagentCommand.humanSummaryOnly
27
+ * per il perché. */
28
+ humanSummaryOnly: boolean;
29
+ }
30
+ /** Estrae la lista di campi (nome/tipo/obbligatorietà/descrizione) dallo z.ZodType di un
31
+ * comando — riusata sia qui sia da renderManifestCli.ts, che altrimenti duplicherebbe la stessa
32
+ * lettura di `properties`/`required` dal JSON Schema. */
33
+ export declare function describeCommandFields(command: SubagentCommand): SubagentUsageField[];
34
+ /** Il comando primario di un manifest (oggi quasi sempre l'unico, vedi SubagentManifest.commands)
35
+ * proiettato in una card — `null` solo se un manifest non ne dichiara nessuno (non dovrebbe
36
+ * succedere per un subagent registrato, ma il chiamante UI non deve crashare se succede). */
37
+ export declare function buildSubagentUsageCard(manifest: SubagentManifest<any, any, any>): SubagentUsageCard | null;
@@ -0,0 +1,2 @@
1
+ import type { AgenticoDict } from './types';
2
+ export declare const agenticoDe: AgenticoDict;
@@ -0,0 +1,2 @@
1
+ import type { AgenticoDict } from './types';
2
+ export declare const agenticoEn: AgenticoDict;
@@ -0,0 +1,20 @@
1
+ import { agenticoDe } from './de';
2
+ import { agenticoEn } from './en';
3
+ import { agenticoIt } from './it';
4
+ import type { AgenticoDict } from './types';
5
+ export type { AgenticoDict } from './types';
6
+ export { agenticoDe, agenticoEn, agenticoIt };
7
+ /** Merge into <App i18n={{ translations }}> — e.g. `it: { ...locales.it, ...agenticoTranslations.it, ...yourIt }`. */
8
+ export declare const agenticoTranslations: {
9
+ en: {
10
+ agentico: AgenticoDict;
11
+ };
12
+ it: {
13
+ agentico: AgenticoDict;
14
+ };
15
+ de: {
16
+ agentico: AgenticoDict;
17
+ };
18
+ };
19
+ /** Agentico strings for the active locale: what the host registered, on top of English. */
20
+ export declare function useAgenticoI18n(): AgenticoDict;
@@ -0,0 +1,2 @@
1
+ import type { AgenticoDict } from './types';
2
+ export declare const agenticoIt: AgenticoDict;