@llmnative/react 1.45.0 → 1.47.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.
@@ -355,6 +355,16 @@ export interface I18nDict {
355
355
  submit: string;
356
356
  noAnswer: string;
357
357
  answered: string;
358
+ /** CR-123 — ChatActivity: the work of an agent (`{count}` in activityCount, activityFailed, activityFiles). */
359
+ activityCount: string;
360
+ activityFailed: string;
361
+ activityCommands: string;
362
+ activityHide: string;
363
+ activityLog: string;
364
+ activitySteps: string;
365
+ activityFiles: string;
366
+ activityChanges: string;
367
+ activityEmpty: string;
358
368
  };
359
369
  /** CR-112 — the charts: empty state, totals, the scale of the heatmaps, the data table. */
360
370
  charts: {
@@ -83,6 +83,8 @@ export { default as ChatReasoning } from './widgets/chat/ChatReasoning';
83
83
  export type { ChatReasoningProps, ChatReasoningClassNames } from './widgets/chat/ChatReasoning';
84
84
  export { default as ChatQuestions } from './widgets/chat/ChatQuestions';
85
85
  export type { ChatQuestion, ChatQuestionOption, ChatQuestionAnswer, ChatQuestionsNumbering, ChatQuestionsProps, ChatQuestionsClassNames } from './widgets/chat/ChatQuestions';
86
+ export { default as ChatActivity } from './widgets/chat/ChatActivity';
87
+ export type { ChatActivityItem, ChatActivitySteps, ChatActivityProps, ChatActivityClassNames } from './widgets/chat/ChatActivity';
86
88
  export { repairStreamingMarkdown } from '../libs/streamingMarkdown';
87
89
  export { default as TabDynamic } from './widgets/TabDynamic';
88
90
  export { default as Component } from './Component';
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ /** One group of steps of an agent: what it did, how many times, what it touched; the lines under it on request. */
3
+ export interface ChatActivitySteps {
4
+ type: 'steps';
5
+ /** Icon name of the icon provider. Default `terminal`. */
6
+ icon?: string;
7
+ /** What the agent did, in a few words ("Reads files", "Runs the tests"). */
8
+ label: string;
9
+ /** How many steps the group has: shown from 2 on. */
10
+ count?: number;
11
+ /** Short details next to the label: the queries, the files, the commands. The first four, the rest on hover. */
12
+ detail?: readonly string[];
13
+ /** How many steps of the group failed: a warning badge. */
14
+ failed?: number;
15
+ /** The lines under the group (its commands, their errors), shown in a block opened by its button. */
16
+ lines?: readonly string[];
17
+ }
18
+ /** An item of the work of an agent: a group of steps, its own words (Markdown), or how it ended. */
19
+ export type ChatActivityItem = ChatActivitySteps | {
20
+ type: 'text';
21
+ text: string;
22
+ } | {
23
+ type: 'end';
24
+ ok: boolean;
25
+ text: string;
26
+ };
27
+ /** Classes for the parts of a `ChatActivity`, added to the defaults. */
28
+ export interface ChatActivityClassNames {
29
+ root?: string;
30
+ step?: string;
31
+ text?: string;
32
+ files?: string;
33
+ log?: string;
34
+ }
35
+ export interface ChatActivityProps {
36
+ items: readonly ChatActivityItem[];
37
+ /** The files the agent changed: listed at the end. */
38
+ files?: readonly string[];
39
+ /** Opens the changes of the files (a diff, a page of the repository): its button next to the list. */
40
+ onShowChanges?: () => void;
41
+ /** The whole raw log: with it, a switch to read it and back. */
42
+ log?: readonly string[];
43
+ className?: string;
44
+ classNames?: ChatActivityClassNames;
45
+ }
46
+ /**
47
+ * CR-123 — The work of an agent in a chat, as AI assistants show it: what it did, grouped (an icon, a label, how many
48
+ * steps, the queries or the files), its commands on request, its own words in between, how it ended, the files it
49
+ * changed with their changes on request; the whole raw log one click away. The consumer maps its own log to the items.
50
+ */
51
+ export default function ChatActivity({ items, files, onShowChanges, log, className, classNames }: ChatActivityProps): React.JSX.Element;
@@ -80,7 +80,7 @@ export { loadGoogleMaps } from './providers/googleMaps/loadGoogleMaps';
80
80
  export type { GoogleMapsConfig } from './providers/googleMaps/loadGoogleMaps';
81
81
  export { useEmailProvider, EmailProvider } from './providers/email/EmailProviderContext';
82
82
  export { GmailEmailProvider } from './providers/email/google/GmailEmailProvider';
83
- export type { AIRequestOptions, AIAttachment, AIProviderAdapter, AIKeyValidationResult, AIModelDescriptor, AIModelPricing, DiscoveredAIModel, AIProviderCapabilities, AIModelCatalog, AIProviderDefinition, AICompleteRequest, AICompleteResult, AIConversationTurn, AIToolDefinition, AIToolCall, AIToolResult, CloudflareProviderOptions, ServerAIProviderConnection, ServerAIConnection, ModelIdentity, ModelIdentityEntry, ModelIdentityIndex, ResolvedModel, ModelOffer, ModelCost, } from './providers/ai';
83
+ export type { AIRequestOptions, AIReasoningLevel, AIAttachment, AIProviderAdapter, AIKeyValidationResult, AIModelDescriptor, AIModelPricing, DiscoveredAIModel, AIProviderCapabilities, AIModelCatalog, AIProviderDefinition, AICompleteRequest, AICompleteResult, AIConversationTurn, AIToolDefinition, AIToolCall, AIToolResult, CloudflareProviderOptions, ServerAIProviderConnection, ServerAIConnection, ModelIdentity, ModelIdentityEntry, ModelIdentityIndex, ResolvedModel, ModelOffer, ModelCost, } from './providers/ai';
84
84
  export { createAIProviderRegistry, getAIModelCatalog, formatAIModelRef, parseAIModelRef, isFreeAIModel, AI_PROVIDER_DEFINITIONS, AI_PROVIDER_DESCRIPTORS, OPENAI_COMPATIBLE_PROVIDER_DESCRIPTOR, CLOUDFLARE_PROVIDER_DESCRIPTOR, createCloudflareProviderDefinition, toProviderDescriptor, createServerCredentialAIRegistry, serverCredential, SERVER_CREDENTIAL_PREFIX, AI_PROVIDER_HOSTS, isAIProviderTarget, canonicalModelName, buildModelIdentityIndex, resolveModel, modelOffers, loadModelIdentityIndex } from './providers/ai';
85
85
  export type { ProviderDescriptor, ProviderCredentialField } from './providers/ProviderDescriptor';
86
86
  export { useAIProvider, useAIProviderRegistry, AIProvider } from './providers/ai/AIProviderContext';
@@ -32,6 +32,8 @@ export interface AIAttachment {
32
32
  base64: string;
33
33
  name?: string;
34
34
  }
35
+ /** How much a model reasons before it answers (CR-122). */
36
+ export type AIReasoningLevel = 'low' | 'medium' | 'high' | 'max';
35
37
  export interface AIRequestOptions {
36
38
  language?: string;
37
39
  voice?: string;
@@ -40,6 +42,12 @@ export interface AIRequestOptions {
40
42
  model?: string;
41
43
  temperature?: number;
42
44
  attachments?: AIAttachment[];
45
+ /**
46
+ * How much the model reasons (CR-122), on the models that take it: Anthropic `output_config.effort`
47
+ * (Claude 4.6 and later), OpenAI `reasoning_effort` (o-series, GPT-5; `max` as `high`), OpenRouter
48
+ * `reasoning.effort`. Elsewhere (older models, Gemini) nothing is sent. Absent: the default of the model.
49
+ */
50
+ reasoning?: AIReasoningLevel;
43
51
  }
44
52
  /** Definizione di un tool che il modello può scegliere di invocare — la SDK del provider
45
53
  * riceve solo questa forma (JSON-serializzabile); l'implementazione vera resta lato
@@ -1,2 +1,2 @@
1
- import type { AIProviderDefinition } from './shared';
1
+ import { type AIProviderDefinition } from './shared';
2
2
  export declare const ANTHROPIC_PROVIDER_DEFINITION: AIProviderDefinition;
@@ -2,7 +2,7 @@ import type { AIConfig } from '../../Config';
2
2
  import type { ProviderDescriptor } from '../ProviderDescriptor';
3
3
  import type { AIProviderAdapter } from './AIProvider';
4
4
  import { type AIProviderDefinition, type BuiltInAIProviderId } from './shared';
5
- export type { AIProviderAdapter, AIKeyValidationResult, AIModelDescriptor, AIModelPricing, AIProviderCapabilities, AIRequestOptions, AIAttachment, AICompleteRequest, AICompleteResult, AIConversationTurn, AIToolDefinition, AIToolCall, AIToolResult, } from './AIProvider';
5
+ export type { AIProviderAdapter, AIKeyValidationResult, AIModelDescriptor, AIModelPricing, AIProviderCapabilities, AIRequestOptions, AIReasoningLevel, AIAttachment, AICompleteRequest, AICompleteResult, AIConversationTurn, AIToolDefinition, AIToolCall, AIToolResult, } from './AIProvider';
6
6
  export { formatAIModelRef, parseAIModelRef, isFreeAIModel } from './AIProvider';
7
7
  export type { DiscoveredAIModel } from './shared';
8
8
  export type { AIModelCatalog, AIProviderDefinition } from './shared';
@@ -17,6 +17,8 @@ type OpenAICompatibleDefinitionOptions = {
17
17
  validateApiKey?: AIProviderDefinition['validateApiKey'];
18
18
  /** Maps one `/models` entry — for providers whose listing also reports prices (OpenRouter). */
19
19
  mapModelEntry?: (entry: Record<string, unknown>) => string | DiscoveredAIModel | undefined;
20
+ /** How a reasoning level is sent (CR-122): `reasoning_effort` on the reasoning models of OpenAI, or OpenRouter's `reasoning.effort`. */
21
+ reasoningStyle?: 'openai' | 'openrouter';
20
22
  };
21
23
  /** Esportate per riuso da provider "chat completions"-simili ma non costruiti tramite
22
24
  * createOpenAICompatibleProviderDefinition (vedi opencode.ts) — stesso wire format OpenAI,
@@ -39,5 +41,5 @@ export declare function parseOpenAIResponse(response: {
39
41
  message?: Record<string, unknown>;
40
42
  }>;
41
43
  } | null): AICompleteResult | null;
42
- export declare const createOpenAICompatibleProviderDefinition: ({ id, label, description, configKey, requiredConfigKeys, defaultModel, fallbackModels, baseUrl, modelsUrl, chatCompletionsUrl, dashboardUrl, credentialsHint, validateApiKey: validateApiKeyOverride, mapModelEntry, }: OpenAICompatibleDefinitionOptions) => AIProviderDefinition;
44
+ export declare const createOpenAICompatibleProviderDefinition: ({ id, label, description, configKey, requiredConfigKeys, defaultModel, fallbackModels, baseUrl, modelsUrl, chatCompletionsUrl, dashboardUrl, credentialsHint, validateApiKey: validateApiKeyOverride, mapModelEntry, reasoningStyle, }: OpenAICompatibleDefinitionOptions) => AIProviderDefinition;
43
45
  export {};
@@ -1,6 +1,6 @@
1
1
  import { type ProviderConfigurationState } from '../ProviderConfiguration';
2
2
  import type { ProviderCredentialField } from '../ProviderDescriptor';
3
- import type { AICompleteRequest, AICompleteResult, AIKeyValidationResult, AIModelDescriptor, AIModelPricing, AIProviderAdapter, AIProviderCapabilities, AIRequestOptions } from './AIProvider';
3
+ import type { AICompleteRequest, AICompleteResult, AIKeyValidationResult, AIModelDescriptor, AIModelPricing, AIProviderAdapter, AIProviderCapabilities, AIReasoningLevel, AIRequestOptions } from './AIProvider';
4
4
  export type BuiltInAIProviderId = 'openai' | 'openrouter' | 'opencode' | 'opencode-go' | 'openai-compatible' | 'deepseek' | 'gemini' | 'anthropic' | 'mistral' | 'glm' | 'cloudflare' | 'groq';
5
5
  /** A discovered model carrying the price its provider listing already reports (OpenRouter,
6
6
  * Cloudflare). Models discovered as a bare id get their price from models.dev instead. */
@@ -41,6 +41,14 @@ export type AIModelCatalog = {
41
41
  modelsByProvider: Record<string, AIModelDescriptor[]>;
42
42
  capabilitiesByProvider: Record<string, AIProviderCapabilities>;
43
43
  };
44
+ /** What an Anthropic Messages request carries for a reasoning level (CR-122); nothing for a model that does not take it. */
45
+ export declare function anthropicReasoning(model: string | undefined, level: AIReasoningLevel | undefined): Record<string, unknown>;
46
+ /**
47
+ * What an OpenAI Chat Completions request carries for a reasoning level (CR-122): `reasoning_effort` on the
48
+ * reasoning models of OpenAI (`max` as `high`, their top); OpenRouter `reasoning.effort` on any model, which
49
+ * it maps itself. Nothing otherwise.
50
+ */
51
+ export declare function openAIReasoning(model: string | undefined, level: AIReasoningLevel | undefined, style?: 'openai' | 'openrouter'): Record<string, unknown>;
44
52
  export declare const extractProviderError: (err: unknown) => string;
45
53
  export declare const createBrowserTransportError: (label: string) => Error;
46
54
  export declare const parseTextResponse: (value: unknown) => string | null;
package/llms-full.txt CHANGED
@@ -1078,7 +1078,7 @@ moveItem(['a', 'b', 'c'], 0, 2) // ['b', 'c', 'a']
1078
1078
  />
1079
1079
  ```
1080
1080
 
1081
- ### Messaggi di chat: ChatMarkdown, ChatReasoning, ChatQuestions (CR-109)
1081
+ ### Messaggi di chat: ChatMarkdown, ChatReasoning, ChatQuestions (CR-109), ChatActivity (CR-123)
1082
1082
 
1083
1083
  Parti di un messaggio di un modello, da comporre nel proprio thread (anche accanto a `Chatbot`).
1084
1084
 
@@ -1122,6 +1122,20 @@ Parti di un messaggio di un modello, da comporre nel proprio thread (anche accan
1122
1122
  // Scelta singola: il click sceglie e passa alla domanda dopo. onSubmit che rifiuta lascia il form.
1123
1123
  // answers={[…]} mostra un insieme già risposto (sola lettura); disabled, autoFocus, submitLabel,
1124
1124
  // classNames={{ root, tabs, tab, panel, question, option, optionSelected, footer, summary }}
1125
+
1126
+ // Il lavoro di un agente (CR-123), come negli assistenti AI: gruppi di passi (icona, label, quanti,
1127
+ // dettagli brevi: query, file, comandi; quanti falliti) con le righe sotto aperte da "Comandi";
1128
+ // le parole dell'agente in Markdown; come è finito; i file cambiati con "Vedi le modifiche";
1129
+ // il registro grezzo a un clic. Il consumer traduce il suo log negli item.
1130
+ <ChatActivity
1131
+ items={[
1132
+ { type: 'steps', icon: 'search', label: 'Esplora il repository', count: 3, detail: ['git status'], lines: ['git status --short'] },
1133
+ { type: 'text', text: 'Aggiungo il comando e il suo test.' },
1134
+ { type: 'end', ok: true, text: 'success · 9 steps' },
1135
+ ]}
1136
+ files={['functions/src/catalog/index.js']} onShowChanges={() => openDiff()} log={rawLines}
1137
+ />
1138
+ // className, classNames={{ root, step, text, files, log }}
1125
1139
  ```
1126
1140
 
1127
1141
  ### ImageEditor
@@ -1165,6 +1179,13 @@ class MyAIProvider implements AIProviderAdapter {
1165
1179
  async array(prompt: string, options?: AIRequestOptions): Promise<string[]> { ... }
1166
1180
  }
1167
1181
 
1182
+ // Quanto ragiona il modello (CR-122): `reasoning: 'low' | 'medium' | 'high' | 'max'` (AIReasoningLevel) su
1183
+ // una richiesta. Anthropic: `output_config.effort` sui Claude 4.6 e successivi (+ thinking adaptive su Opus
1184
+ // 4.6-4.8 e Sonnet 4.6); OpenAI e compatibili (OpenCode, DeepSeek, Groq…): `reasoning_effort` solo sui modelli
1185
+ // di ragionamento di OpenAI (serie o, GPT-5; max = high); OpenRouter: `reasoning.effort` su ogni modello.
1186
+ // Altrove (modelli più vecchi, Gemini) non si manda nulla: il default del modello.
1187
+ await ai.complete({ prompt: 'Rivedi questo piano', model: 'claude-opus-5-5', reasoning: 'high' })
1188
+
1168
1189
  // Factory per registri esterni
1169
1190
  const registry = createAIProviderRegistry(definitions)
1170
1191
  // Azioni di Chatbot (CR-107): con `content` aprono un menu; senza, sono pulsanti con `onClick`.
package/llms.txt CHANGED
@@ -66,7 +66,7 @@ import '@llmnative/react/dist/index.css' // necessario una volta sola
66
66
  ui/ → primitivi stateless: Alert, Badge, Button, Card, DescriptionList, Image, Modal, Table, Gallery, Tab, Repeat, Icon, LocaleSwitcher, ThemeSwitcher, ProviderSwitcher, LayoutBuilder, ContextMenu
67
67
  ui/fields/ → campi form: Input, Select, UploadImage, UploadDocument, UploadCSV, CodeEditor, ImageField, RichText, Prompt, Crop, ContextMenu
68
68
  blocks/ → composizioni: Menu, Breadcrumbs, Notifications, Search, Carousel, Dropdown, Toolbar, SideNav, ListCard, AuthButton
69
- widgets/ → smart (hanno stato e provider): Grid, Form, MarkdownReader, ImageEditor, TabDynamic, Chatbot, ChatMarkdown, ChatReasoning, ChatQuestions
69
+ widgets/ → smart (hanno stato e provider): Grid, Form, MarkdownReader, ImageEditor, TabDynamic, Chatbot, ChatMarkdown, ChatReasoning, ChatQuestions, ChatActivity
70
70
  ```
71
71
 
72
72
  Tutti gli import da `'@llmnative/react'` — mai da sottodirectory.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llmnative/react",
3
- "version": "1.45.0",
3
+ "version": "1.47.0",
4
4
  "description": "LLM-native React framework for deterministic UI generation. Data-driven by default, schema-driven optional. Ultra-low token consumption — built for AI agents, not just humans.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",