@qfei-design/make-ai-assistant 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.
@@ -0,0 +1,72 @@
1
+ import type { ArtifactCapabilities, MakeAiArtifact, MakeAssistantHostContext } from "./types.js";
2
+ export interface AssistantRunRequest {
3
+ threadId?: string;
4
+ message: {
5
+ id: string;
6
+ content: string;
7
+ };
8
+ context: MakeAssistantHostContext;
9
+ capabilities: ArtifactCapabilities;
10
+ }
11
+ export interface AssistantTransportOptions {
12
+ signal?: AbortSignal;
13
+ }
14
+ export interface AssistantTransport {
15
+ run(request: AssistantRunRequest, options?: AssistantTransportOptions): AsyncIterable<AssistantEvent>;
16
+ }
17
+ export type AssistantEvent = {
18
+ type: "message.start";
19
+ runId: string;
20
+ messageId: string;
21
+ } | {
22
+ type: "message.delta";
23
+ messageId: string;
24
+ delta: string;
25
+ } | {
26
+ type: "artifact";
27
+ messageId: string;
28
+ artifact: MakeAiArtifact;
29
+ } | {
30
+ type: "message.complete";
31
+ messageId: string;
32
+ } | {
33
+ type: "error";
34
+ code: string;
35
+ message: string;
36
+ retryable: boolean;
37
+ requestId?: string;
38
+ } | {
39
+ type: "run.cancelled";
40
+ runId?: string;
41
+ } | {
42
+ type: "run.complete";
43
+ runId: string;
44
+ threadId: string;
45
+ };
46
+ export declare const parseAssistantEvent: (value: unknown) => AssistantEvent;
47
+ export interface AssistantMessage {
48
+ id: string;
49
+ role: "assistant" | "user";
50
+ content: string;
51
+ artifacts: MakeAiArtifact[];
52
+ status: "complete" | "streaming";
53
+ }
54
+ export interface AssistantConversationError {
55
+ code: string;
56
+ message: string;
57
+ retryable: boolean;
58
+ requestId?: string;
59
+ }
60
+ export interface AssistantConversationState {
61
+ activeRunId?: string;
62
+ error?: AssistantConversationError;
63
+ messages: AssistantMessage[];
64
+ status: "idle" | "streaming" | "error";
65
+ threadId?: string;
66
+ }
67
+ export declare const createAssistantConversationState: () => AssistantConversationState;
68
+ export declare const appendUserMessage: (state: AssistantConversationState, message: {
69
+ id: string;
70
+ content: string;
71
+ }) => AssistantConversationState;
72
+ export declare const reduceAssistantEvent: (state: AssistantConversationState, event: AssistantEvent) => AssistantConversationState;
@@ -0,0 +1,4 @@
1
+ export * from "./conversation.js";
2
+ export * from "./registry.js";
3
+ export * from "./types.js";
4
+ export * from "./validation.js";
@@ -0,0 +1,19 @@
1
+ import { type ArtifactCapabilities, type ArtifactKind, type MakeAiArtifact, type MakeAssistantHostContext } from "./types.js";
2
+ export interface ArtifactTemplate<Output = unknown, Runtime = undefined> {
3
+ id: string;
4
+ kinds: ReadonlyArray<ArtifactKind>;
5
+ priority?: number;
6
+ canRender?: (artifact: MakeAiArtifact, context: MakeAssistantHostContext) => boolean;
7
+ render: (artifact: MakeAiArtifact, context: MakeAssistantHostContext, runtime: Runtime) => Output;
8
+ }
9
+ export interface ArtifactTemplateRegistry<Output = unknown, Runtime = undefined> {
10
+ readonly templates: ReadonlyArray<ArtifactTemplate<Output, Runtime>>;
11
+ }
12
+ export interface ResolvedArtifactTemplate<Output = unknown, Runtime = undefined> {
13
+ template: ArtifactTemplate<Output, Runtime>;
14
+ reason: "requested" | "priority";
15
+ }
16
+ export declare const createArtifactTemplateRegistry: <Output = unknown, Runtime = undefined>(templates?: ReadonlyArray<ArtifactTemplate<Output, Runtime>>) => ArtifactTemplateRegistry<Output, Runtime>;
17
+ export declare const extendArtifactTemplateRegistry: <Output, Runtime>(registry: ArtifactTemplateRegistry<Output, Runtime>, templates: ReadonlyArray<ArtifactTemplate<Output, Runtime>>) => ArtifactTemplateRegistry<Output, Runtime>;
18
+ export declare const resolveArtifactTemplate: <Output, Runtime>(registry: ArtifactTemplateRegistry<Output, Runtime>, artifact: MakeAiArtifact, context: MakeAssistantHostContext) => ResolvedArtifactTemplate<Output, Runtime> | undefined;
19
+ export declare const createArtifactCapabilities: <Output, Runtime>(registry: ArtifactTemplateRegistry<Output, Runtime>) => ArtifactCapabilities;
@@ -0,0 +1,40 @@
1
+ import { type AssistantTransport } from "./conversation.js";
2
+ export type SseRequestCredentials = "include" | "omit" | "same-origin";
3
+ export interface SseHeaderCollection {
4
+ forEach(callback: (value: string, key: string) => void): void;
5
+ }
6
+ export type SseHeadersInit = Readonly<Record<string, string>> | ReadonlyArray<readonly [string, string]> | SseHeaderCollection;
7
+ export interface SseReaderResult {
8
+ done: boolean;
9
+ value?: Uint8Array;
10
+ }
11
+ export interface SseResponseReader {
12
+ read(): Promise<SseReaderResult>;
13
+ cancel(reason?: unknown): Promise<void>;
14
+ releaseLock(): void;
15
+ }
16
+ export interface SseResponseBody {
17
+ getReader(): SseResponseReader;
18
+ }
19
+ export interface SseFetchResponse {
20
+ readonly body: SseResponseBody | null;
21
+ readonly ok: boolean;
22
+ readonly status: number;
23
+ }
24
+ export interface SseFetchRequestInit {
25
+ body: string;
26
+ credentials: SseRequestCredentials;
27
+ headers: Record<string, string>;
28
+ method: "POST";
29
+ signal?: AbortSignal;
30
+ }
31
+ export type SseFetch = (input: string, init: SseFetchRequestInit) => Promise<SseFetchResponse>;
32
+ export declare const DEFAULT_MAX_SSE_EVENT_CHARACTERS = 1000000;
33
+ export interface SseAssistantTransportOptions {
34
+ endpoint: string | ((request: Parameters<AssistantTransport["run"]>[0]) => string);
35
+ fetch?: SseFetch;
36
+ headers?: SseHeadersInit | (() => SseHeadersInit | Promise<SseHeadersInit>);
37
+ credentials?: SseRequestCredentials;
38
+ maxEventCharacters?: number;
39
+ }
40
+ export declare const createSseAssistantTransport: (options: SseAssistantTransportOptions) => AssistantTransport;
@@ -0,0 +1 @@
1
+ export declare const countCodePointsUpTo: (value: string, maximum: number) => number;
@@ -0,0 +1,167 @@
1
+ export type JsonPrimitive = boolean | null | number | string;
2
+ export type JsonValue = JsonPrimitive | JsonValue[] | {
3
+ [key: string]: JsonValue;
4
+ };
5
+ export declare const MAKE_AI_ARTIFACT_SCHEMA_VERSION: "1.0";
6
+ export declare const MAKE_AI_ARTIFACT_LIMITS: {
7
+ readonly actions: 10;
8
+ readonly comparisonItems: 24;
9
+ readonly jsonCharacters: 1000000;
10
+ readonly jsonDepth: 64;
11
+ readonly jsonNodes: 10000;
12
+ readonly rankingItems: 50;
13
+ readonly recordColumns: 20;
14
+ readonly recordListRecords: 100;
15
+ readonly recordValues: 100;
16
+ readonly textCharacters: 20000;
17
+ readonly trendPointsPerSeries: 120;
18
+ readonly trendSeries: 8;
19
+ readonly validationIssues: 100;
20
+ };
21
+ export declare const MAKE_AI_CONVERSATION_LIMITS: {
22
+ readonly artifactsPerRun: 50;
23
+ readonly assistantMessagesPerRun: 20;
24
+ readonly identifierCharacters: 1000;
25
+ readonly messageCharacters: 100000;
26
+ };
27
+ export declare const MAKE_AI_ARTIFACT_KINDS: readonly ["metric", "comparison", "trend", "ranking", "record-list", "notice"];
28
+ export type ArtifactKind = (typeof MAKE_AI_ARTIFACT_KINDS)[number];
29
+ export interface ArtifactNumberFormat {
30
+ style?: "decimal" | "currency" | "percent";
31
+ currency?: string;
32
+ precision?: number;
33
+ unit?: string;
34
+ }
35
+ export interface ArtifactAction {
36
+ id: string;
37
+ label: string;
38
+ intent: "navigate" | "open-record" | "open-list" | "invoke";
39
+ target: Record<string, JsonValue>;
40
+ appearance?: "primary" | "secondary" | "link";
41
+ }
42
+ export interface ArtifactPresentation {
43
+ template?: string;
44
+ density?: "compact" | "comfortable";
45
+ }
46
+ export interface BaseArtifact {
47
+ schemaVersion: typeof MAKE_AI_ARTIFACT_SCHEMA_VERSION;
48
+ id: string;
49
+ title?: string;
50
+ summary?: string;
51
+ presentation?: ArtifactPresentation;
52
+ actions?: ReadonlyArray<ArtifactAction>;
53
+ meta?: Record<string, JsonValue>;
54
+ }
55
+ export interface MetricArtifact extends BaseArtifact {
56
+ kind: "metric";
57
+ data: {
58
+ value: number | string;
59
+ format?: ArtifactNumberFormat;
60
+ delta?: {
61
+ value: number;
62
+ format?: "decimal" | "percent";
63
+ direction?: "up" | "down" | "flat";
64
+ label?: string;
65
+ };
66
+ context?: string;
67
+ };
68
+ }
69
+ export interface ComparisonArtifact extends BaseArtifact {
70
+ kind: "comparison";
71
+ data: {
72
+ items: ReadonlyArray<{
73
+ id: string;
74
+ label: string;
75
+ value: number | string;
76
+ format?: ArtifactNumberFormat;
77
+ hint?: string;
78
+ }>;
79
+ };
80
+ }
81
+ export interface TrendArtifact extends BaseArtifact {
82
+ kind: "trend";
83
+ data: {
84
+ series: ReadonlyArray<{
85
+ id: string;
86
+ label: string;
87
+ points: ReadonlyArray<{
88
+ x: number | string;
89
+ y: number;
90
+ }>;
91
+ format?: ArtifactNumberFormat;
92
+ }>;
93
+ };
94
+ }
95
+ export interface RankingArtifact extends BaseArtifact {
96
+ kind: "ranking";
97
+ data: {
98
+ items: ReadonlyArray<{
99
+ id: string;
100
+ label: string;
101
+ value: number;
102
+ format?: ArtifactNumberFormat;
103
+ description?: string;
104
+ }>;
105
+ };
106
+ }
107
+ export interface RecordListArtifact extends BaseArtifact {
108
+ kind: "record-list";
109
+ data: {
110
+ entity: {
111
+ key: string;
112
+ label?: string;
113
+ };
114
+ columns: ReadonlyArray<{
115
+ key: string;
116
+ label: string;
117
+ format?: ArtifactNumberFormat;
118
+ }>;
119
+ records: ReadonlyArray<{
120
+ id: string;
121
+ title?: string;
122
+ values: Record<string, JsonPrimitive>;
123
+ action?: ArtifactAction;
124
+ }>;
125
+ total?: number;
126
+ };
127
+ }
128
+ export interface NoticeArtifact extends BaseArtifact {
129
+ kind: "notice";
130
+ data: {
131
+ tone: "info" | "success" | "warning" | "danger";
132
+ body: string;
133
+ };
134
+ }
135
+ export type MakeAiArtifact = ComparisonArtifact | MetricArtifact | NoticeArtifact | RankingArtifact | RecordListArtifact | TrendArtifact;
136
+ export interface MakeAssistantHostContext {
137
+ app: {
138
+ id: string;
139
+ name?: string;
140
+ };
141
+ location: {
142
+ pathname: string;
143
+ routeId?: string;
144
+ };
145
+ resource?: {
146
+ entityKey?: string;
147
+ recordId?: string;
148
+ viewKey?: string;
149
+ };
150
+ selection?: {
151
+ recordIds: ReadonlyArray<string>;
152
+ };
153
+ locale: string;
154
+ timezone: string;
155
+ extensions?: Record<string, JsonValue>;
156
+ }
157
+ export interface ArtifactCapabilities {
158
+ artifactSchemaVersions: ReadonlyArray<typeof MAKE_AI_ARTIFACT_SCHEMA_VERSION>;
159
+ artifactKinds: ReadonlyArray<ArtifactKind>;
160
+ templates: ReadonlyArray<string>;
161
+ }
162
+ export interface ArtifactActionContext {
163
+ artifact: MakeAiArtifact;
164
+ context: MakeAssistantHostContext;
165
+ }
166
+ export type ArtifactActionHandler = (action: ArtifactAction, actionContext: ArtifactActionContext) => void | Promise<void>;
167
+ export type ArtifactActionErrorHandler = (error: unknown, action: ArtifactAction, actionContext: ArtifactActionContext) => void | Promise<void>;
@@ -0,0 +1,14 @@
1
+ import { type MakeAiArtifact } from "./types.js";
2
+ export interface ArtifactValidationIssue {
3
+ path: string;
4
+ message: string;
5
+ }
6
+ export type ArtifactValidationResult = {
7
+ success: true;
8
+ artifact: MakeAiArtifact;
9
+ } | {
10
+ success: false;
11
+ issues: ArtifactValidationIssue[];
12
+ };
13
+ export declare const validateArtifact: (value: unknown) => ArtifactValidationResult;
14
+ export declare const parseArtifact: (value: unknown) => MakeAiArtifact;
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./conversation-DpYszfVd.cjs"),p=r=>{const e=new Set;for(const t of r){if(!t.id.trim())throw new Error("Artifact template id must not be empty");if(e.has(t.id))throw new Error(`Duplicate artifact template id: ${t.id}`);if(t.kinds.length===0)throw new Error(`Artifact template must support at least one kind: ${t.id}`);if(t.kinds.some(n=>!i.MAKE_AI_ARTIFACT_KINDS.includes(n)))throw new Error(`Unsupported Artifact template kind: ${t.id}`);if(t.priority!==void 0&&!Number.isFinite(t.priority))throw new Error(`Artifact template priority must be finite: ${t.id}`);if(typeof t.render!="function")throw new Error(`Artifact template render must be a function: ${t.id}`);if(t.canRender!==void 0&&typeof t.canRender!="function")throw new Error(`Artifact template canRender must be a function: ${t.id}`);e.add(t.id)}},c=(r=[])=>{p(r);const e=r.map(t=>Object.freeze({...t,kinds:Object.freeze([...t.kinds])}));return Object.freeze({templates:Object.freeze(e)})},d=(r,e)=>c([...r.templates,...e]),A=(r,e,t)=>r.kinds.includes(e.kind)&&(r.canRender?.(e,t)??!0),f=(r,e,t)=>{const n=e.presentation?.template;if(n){const a=r.templates.find(s=>s.id===n&&A(s,e,t));if(a)return{template:a,reason:"requested"}}const o=r.templates.map((a,s)=>({template:a,registrationIndex:s})).filter(({template:a})=>A(a,e,t)).sort((a,s)=>(s.template.priority??0)-(a.template.priority??0)||a.registrationIndex-s.registrationIndex);return o[0]?{template:o[0].template,reason:"priority"}:void 0},l=r=>({artifactSchemaVersions:[i.MAKE_AI_ARTIFACT_SCHEMA_VERSION],artifactKinds:Array.from(new Set(r.templates.flatMap(e=>e.kinds))).sort(),templates:r.templates.map(e=>e.id).sort()});exports.MAKE_AI_ARTIFACT_KINDS=i.MAKE_AI_ARTIFACT_KINDS;exports.MAKE_AI_ARTIFACT_LIMITS=i.MAKE_AI_ARTIFACT_LIMITS;exports.MAKE_AI_ARTIFACT_SCHEMA_VERSION=i.MAKE_AI_ARTIFACT_SCHEMA_VERSION;exports.MAKE_AI_CONVERSATION_LIMITS=i.MAKE_AI_CONVERSATION_LIMITS;exports.appendUserMessage=i.appendUserMessage;exports.createAssistantConversationState=i.createAssistantConversationState;exports.parseArtifact=i.parseArtifact;exports.parseAssistantEvent=i.parseAssistantEvent;exports.reduceAssistantEvent=i.reduceAssistantEvent;exports.validateArtifact=i.validateArtifact;exports.createArtifactCapabilities=l;exports.createArtifactTemplateRegistry=c;exports.extendArtifactTemplateRegistry=d;exports.resolveArtifactTemplate=f;
@@ -0,0 +1 @@
1
+ export * from "./core/index.js";
package/dist/index.mjs ADDED
@@ -0,0 +1,64 @@
1
+ import { f as p, d } from "./conversation-B5kECJz8.js";
2
+ import { e as E, M as T, b, c as _, g as R, p as y, r as M, v as S } from "./conversation-B5kECJz8.js";
3
+ const c = (r) => {
4
+ const e = /* @__PURE__ */ new Set();
5
+ for (const t of r) {
6
+ if (!t.id.trim()) throw new Error("Artifact template id must not be empty");
7
+ if (e.has(t.id))
8
+ throw new Error(`Duplicate artifact template id: ${t.id}`);
9
+ if (t.kinds.length === 0)
10
+ throw new Error(`Artifact template must support at least one kind: ${t.id}`);
11
+ if (t.kinds.some((s) => !d.includes(s)))
12
+ throw new Error(`Unsupported Artifact template kind: ${t.id}`);
13
+ if (t.priority !== void 0 && !Number.isFinite(t.priority))
14
+ throw new Error(`Artifact template priority must be finite: ${t.id}`);
15
+ if (typeof t.render != "function")
16
+ throw new Error(`Artifact template render must be a function: ${t.id}`);
17
+ if (t.canRender !== void 0 && typeof t.canRender != "function")
18
+ throw new Error(`Artifact template canRender must be a function: ${t.id}`);
19
+ e.add(t.id);
20
+ }
21
+ }, f = (r = []) => {
22
+ c(r);
23
+ const e = r.map(
24
+ (t) => Object.freeze({
25
+ ...t,
26
+ kinds: Object.freeze([...t.kinds])
27
+ })
28
+ );
29
+ return Object.freeze({ templates: Object.freeze(e) });
30
+ }, l = (r, e) => f([...r.templates, ...e]), o = (r, e, t) => r.kinds.includes(e.kind) && (r.canRender?.(e, t) ?? !0), A = (r, e, t) => {
31
+ const s = e.presentation?.template;
32
+ if (s) {
33
+ const i = r.templates.find(
34
+ (a) => a.id === s && o(a, e, t)
35
+ );
36
+ if (i) return { template: i, reason: "requested" };
37
+ }
38
+ const n = r.templates.map((i, a) => ({ template: i, registrationIndex: a })).filter(({ template: i }) => o(i, e, t)).sort(
39
+ (i, a) => (a.template.priority ?? 0) - (i.template.priority ?? 0) || i.registrationIndex - a.registrationIndex
40
+ );
41
+ return n[0] ? { template: n[0].template, reason: "priority" } : void 0;
42
+ }, u = (r) => ({
43
+ artifactSchemaVersions: [p],
44
+ artifactKinds: Array.from(
45
+ new Set(r.templates.flatMap((e) => e.kinds))
46
+ ).sort(),
47
+ templates: r.templates.map((e) => e.id).sort()
48
+ });
49
+ export {
50
+ d as MAKE_AI_ARTIFACT_KINDS,
51
+ E as MAKE_AI_ARTIFACT_LIMITS,
52
+ p as MAKE_AI_ARTIFACT_SCHEMA_VERSION,
53
+ T as MAKE_AI_CONVERSATION_LIMITS,
54
+ b as appendUserMessage,
55
+ u as createArtifactCapabilities,
56
+ f as createArtifactTemplateRegistry,
57
+ _ as createAssistantConversationState,
58
+ l as extendArtifactTemplateRegistry,
59
+ R as parseArtifact,
60
+ y as parseAssistantEvent,
61
+ M as reduceAssistantEvent,
62
+ A as resolveArtifactTemplate,
63
+ S as validateArtifact
64
+ };
@@ -0,0 +1,12 @@
1
+ import type { ReactNode } from "react";
2
+ import { type ArtifactActionErrorHandler, type ArtifactActionHandler, type ArtifactTemplateRegistry, type MakeAiArtifact, type MakeAssistantHostContext } from "../core/index.js";
3
+ import type { ArtifactTemplateRenderContext } from "./artifact-templates.js";
4
+ export interface ArtifactRendererProps {
5
+ artifact: MakeAiArtifact;
6
+ context: MakeAssistantHostContext;
7
+ registry: ArtifactTemplateRegistry<ReactNode, ArtifactTemplateRenderContext>;
8
+ onAction?: ArtifactActionHandler;
9
+ onActionError?: ArtifactActionErrorHandler;
10
+ fallback?: (artifact: MakeAiArtifact) => ReactNode;
11
+ }
12
+ export declare function ArtifactRenderer({ artifact, context, fallback, onAction, onActionError, registry, }: ArtifactRendererProps): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react").JSX.Element | null | undefined;
@@ -0,0 +1,11 @@
1
+ import type { ReactNode } from "react";
2
+ import { type ArtifactActionErrorHandler, type ArtifactActionHandler, type ArtifactTemplate, type ArtifactTemplateRegistry, type MakeAssistantHostContext } from "../core/index.js";
3
+ export interface ArtifactTemplateRenderContext {
4
+ context: MakeAssistantHostContext;
5
+ onAction?: ArtifactActionHandler;
6
+ onActionError?: ArtifactActionErrorHandler;
7
+ }
8
+ export type ReactArtifactTemplate = ArtifactTemplate<ReactNode, ArtifactTemplateRenderContext>;
9
+ export type ReactArtifactTemplateRegistry = ArtifactTemplateRegistry<ReactNode, ArtifactTemplateRenderContext>;
10
+ export declare const platformArtifactTemplates: ReadonlyArray<ReactArtifactTemplate>;
11
+ export declare const createPlatformArtifactRegistry: (templates?: ReadonlyArray<ReactArtifactTemplate>) => ReactArtifactTemplateRegistry;
@@ -0,0 +1,2 @@
1
+ import type { ArtifactNumberFormat, JsonPrimitive } from "../core/index.js";
2
+ export declare const formatArtifactValue: (value: JsonPrimitive | undefined, format: ArtifactNumberFormat | undefined, locale: string) => string;
@@ -0,0 +1,5 @@
1
+ export * from "../core/index.js";
2
+ export * from "./artifact-renderer.js";
3
+ export * from "./artifact-templates.js";
4
+ export * from "./format.js";
5
+ export * from "./make-ai-assistant.js";
@@ -0,0 +1,27 @@
1
+ import { type ReactNode } from "react";
2
+ import { type ArtifactActionHandler, type ArtifactActionErrorHandler, type AssistantTransport, type MakeAssistantHostContext } from "../core/index.js";
3
+ import { type ReactArtifactTemplateRegistry } from "./artifact-templates.js";
4
+ export interface AssistantPanelProps {
5
+ context: MakeAssistantHostContext;
6
+ transport: AssistantTransport;
7
+ registry?: ReactArtifactTemplateRegistry;
8
+ title?: string;
9
+ subtitle?: string;
10
+ suggestions?: string[];
11
+ onAction?: ArtifactActionHandler;
12
+ onActionError?: ArtifactActionErrorHandler;
13
+ onClose?: () => void;
14
+ onNewConversation?: () => void;
15
+ }
16
+ export declare function AssistantPanel({ context, onAction, onActionError, onClose, onNewConversation, registry: registryProp, subtitle, suggestions, title, transport, }: AssistantPanelProps): import("react").JSX.Element;
17
+ export interface MakeAiAssistantProps extends Omit<AssistantPanelProps, "onClose"> {
18
+ open?: boolean;
19
+ defaultOpen?: boolean;
20
+ onOpenChange?: (open: boolean) => void;
21
+ launcher?: (options: {
22
+ open: boolean;
23
+ toggle: () => void;
24
+ }) => ReactNode;
25
+ hideLauncher?: boolean;
26
+ }
27
+ export declare function MakeAiAssistant({ defaultOpen, hideLauncher, launcher, onOpenChange, open: controlledOpen, ...panelProps }: MakeAiAssistantProps): import("react").JSX.Element;
@@ -0,0 +1,5 @@
1
+ export interface NumberExtent {
2
+ min: number;
3
+ max: number;
4
+ }
5
+ export declare const getNumberExtent: (values: Iterable<number>) => NumberExtent;
package/dist/react.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),y=require("./index.cjs"),h=require("react"),c=require("./conversation-DpYszfVd.cjs");function W({artifact:a,context:t,fallback:s,onAction:o,onActionError:n,registry:r}){const m=y.resolveArtifactTemplate(r,a,t);if(!m)return s?s(a):e.jsxs("section",{className:"make-ai-artifact make-ai-artifact--unsupported",role:"status",children:[e.jsx("strong",{children:"暂不支持展示此结果"}),e.jsxs("span",{children:["结果类型:",a.kind]})]});const u={context:t,onAction:o,onActionError:n};return m.template.render(a,t,u)}const v=(a,t,s)=>{if(a==null||a==="")return"—";if(typeof a=="boolean")return a?"是":"否";if(typeof a!="number")return`${a}${t?.unit??""}`;const o=t?.precision,n={maximumFractionDigits:o??2,minimumFractionDigits:o};t?.style==="currency"&&t.currency?(n.style="currency",n.currency=t.currency):t?.style==="percent"&&(n.style="percent");try{const r=t?.style==="percent"?a/100:a;return`${new Intl.NumberFormat(s,n).format(r)}${t?.unit??""}`}catch{return`${a}${t?.unit??""}`}},X=a=>{let t=Number.POSITIVE_INFINITY,s=Number.NEGATIVE_INFINITY;for(const o of a)t=Math.min(t,o),s=Math.max(s,o);return Number.isFinite(t)&&Number.isFinite(s)?{min:t,max:s}:{min:0,max:0}},ee=(a,t,s)=>{if(!s.onAction)return;const o=r=>{console.error("[make-ai-assistant] host action error handler failed",{actionId:a.id,artifactId:t.artifact.id,errorType:r instanceof Error?r.name:typeof r,intent:a.intent})},n=r=>{if(s.onActionError){try{Promise.resolve(s.onActionError(r,a,t)).catch(o)}catch(m){o(m)}return}console.error("[make-ai-assistant] host action failed",{actionId:a.id,artifactId:t.artifact.id,errorType:r instanceof Error?r.name:typeof r,intent:a.intent})};try{Promise.resolve(s.onAction(a,t)).catch(n)}catch(r){n(r)}},R=(a,t)=>a.actions?.length&&t.onAction?e.jsx("div",{className:"make-ai-artifact__actions",children:a.actions.map(s=>e.jsxs("button",{className:`make-ai-artifact__action make-ai-artifact__action--${s.appearance??"link"}`,type:"button",onClick:()=>ee(s,{artifact:a,context:t.context},t),children:[s.label,e.jsx("span",{"aria-hidden":"true",children:"→"})]},s.id))}):null,C=(a,t,s="")=>e.jsxs("section",{"aria-label":a.title??`${a.kind} result`,className:`make-ai-artifact ${s}`.trim(),"data-artifact-density":a.presentation?.density,"data-artifact-kind":a.kind,children:[a.title?e.jsx("h4",{className:"make-ai-artifact__title",children:a.title}):null,a.summary?e.jsx("p",{className:"make-ai-artifact__summary",children:a.summary}):null,t]}),de=({artifact:a,renderContext:t})=>{const s=a.data.delta,o=s?v(s.value,s.format==="percent"?{style:"percent"}:void 0,t.context.locale):void 0;return C(a,e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"make-ai-artifact__metric-value",children:v(a.data.value,a.data.format,t.context.locale)}),s?e.jsxs("div",{className:`make-ai-artifact__delta make-ai-artifact__delta--${s.direction??"flat"}`,children:[e.jsx("span",{"aria-hidden":"true",children:s.direction==="up"?"↗":s.direction==="down"?"↘":"→"}),e.jsx("span",{children:o}),s.label?e.jsx("span",{children:s.label}):null]}):null,a.data.context?e.jsx("p",{className:"make-ai-artifact__context",children:a.data.context}):null,R(a,t)]}),"make-ai-artifact--metric")},me=({artifact:a,renderContext:t})=>C(a,e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"make-ai-artifact__comparison",children:a.data.items.map(s=>e.jsxs("div",{className:"make-ai-artifact__comparison-item",children:[e.jsx("span",{children:s.label}),e.jsx("strong",{children:v(s.value,s.format,t.context.locale)}),s.hint?e.jsx("small",{children:s.hint}):null]},s.id))}),R(a,t)]}),"make-ai-artifact--comparison"),ue=({artifact:a,renderContext:t})=>{const s=a.data.series.flatMap(m=>m.points.map(u=>u.y)),{max:o,min:n}=X(s),r=o-n||1;return C(a,e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"make-ai-artifact__trend",children:a.data.series.map(m=>e.jsxs("div",{className:"make-ai-artifact__trend-series",children:[e.jsx("div",{className:"make-ai-artifact__trend-label",children:m.label}),e.jsx("div",{className:"make-ai-artifact__trend-bars",children:m.points.map((u,g)=>{const f=18+(u.y-n)/r*70;return e.jsxs("div",{className:"make-ai-artifact__trend-point",children:[e.jsx("span",{"aria-label":`${u.x}: ${v(u.y,m.format,t.context.locale)}`,className:"make-ai-artifact__trend-bar",role:"img",style:{height:`${f}%`},title:`${u.x}: ${v(u.y,m.format,t.context.locale)}`}),e.jsx("small",{children:u.x})]},`${u.x}-${g}`)})})]},m.id))}),R(a,t)]}),"make-ai-artifact--trend")},pe=({artifact:a,renderContext:t})=>{const{max:s}=X(a.data.items.map(n=>Math.abs(n.value))),o=Math.max(s,1);return C(a,e.jsxs(e.Fragment,{children:[e.jsx("ol",{className:"make-ai-artifact__ranking",children:a.data.items.map((n,r)=>e.jsxs("li",{children:[e.jsx("span",{className:"make-ai-artifact__rank",children:r+1}),e.jsxs("span",{className:"make-ai-artifact__ranking-label",children:[e.jsx("span",{children:n.label}),n.description?e.jsx("small",{children:n.description}):null]}),e.jsx("span",{className:"make-ai-artifact__ranking-track","aria-hidden":"true",children:e.jsx("span",{style:{width:`${Math.abs(n.value)/o*100}%`}})}),e.jsx("strong",{children:v(n.value,n.format,t.context.locale)})]},n.id))}),R(a,t)]}),"make-ai-artifact--ranking")},he=(a,t)=>t.action??{id:`open-${t.id}`,label:t.title??t.id,intent:"open-record",target:{entityKey:a.data.entity.key,recordId:t.id}},fe=({artifact:a,renderContext:t})=>C(a,e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"make-ai-artifact__record-list",children:a.data.records.length===0?e.jsx("p",{className:"make-ai-artifact__empty",children:"没有符合条件的记录"}):a.data.records.map(s=>{const o=he(a,s),n=e.jsxs(e.Fragment,{children:[e.jsx("strong",{children:s.title??s.id}),e.jsx("span",{className:"make-ai-artifact__record-values",children:a.data.columns.map(r=>e.jsxs("span",{children:[e.jsx("small",{children:r.label}),v(s.values[r.key],r.format,t.context.locale)]},r.key))}),t.onAction?e.jsx("span",{"aria-hidden":"true",children:"›"}):null]});return t.onAction?e.jsx("button",{className:"make-ai-artifact__record",type:"button",onClick:()=>ee(o,{artifact:a,context:t.context},t),children:n},s.id):e.jsx("div",{className:"make-ai-artifact__record",children:n},s.id)})}),a.data.total!==void 0?e.jsxs("p",{className:"make-ai-artifact__record-total",children:["共 ",a.data.total," 条"]}):null,R(a,t)]}),"make-ai-artifact--record-list"),_e=({artifact:a,renderContext:t})=>C(a,e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:`make-ai-artifact__notice make-ai-artifact__notice--${a.data.tone}`,children:[e.jsx("span",{"aria-hidden":"true",children:a.data.tone==="success"?"✓":a.data.tone==="warning"?"!":a.data.tone==="danger"?"×":"i"}),e.jsx("p",{children:a.data.body})]}),R(a,t)]}),"make-ai-artifact--notice"),S=(a,t,s)=>({id:a,kinds:[t],priority:0,render:s}),Ae=[S("platform.metric.default","metric",(a,t,s)=>e.jsx(de,{artifact:a,renderContext:s})),S("platform.comparison.default","comparison",(a,t,s)=>e.jsx(me,{artifact:a,renderContext:s})),S("platform.trend.default","trend",(a,t,s)=>e.jsx(ue,{artifact:a,renderContext:s})),S("platform.ranking.default","ranking",(a,t,s)=>e.jsx(pe,{artifact:a,renderContext:s})),S("platform.record-list.default","record-list",(a,t,s)=>e.jsx(fe,{artifact:a,renderContext:s})),S("platform.notice.default","notice",(a,t,s)=>e.jsx(_e,{artifact:a,renderContext:s}))],ae=y.createArtifactTemplateRegistry(Ae).templates,te=(a=ae)=>y.createArtifactTemplateRegistry(a),xe=a=>`${a}-${Date.now()}-${Math.random().toString(36).slice(2,9)}`;class p extends Error{}const Q=a=>{try{const t=a?.return?.();if(!t)return;Promise.resolve(t).catch(s=>{console.error("[make-ai-assistant] transport iterator close failed",{errorType:s instanceof Error?s.name:typeof s})})}catch(t){console.error("[make-ai-assistant] transport iterator close failed",{errorType:t instanceof Error?t.name:typeof t})}},se=()=>e.jsxs("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:[e.jsx("path",{d:"M12 2.8c.5 4.4 2.8 6.8 7.2 7.2-4.4.5-6.8 2.8-7.2 7.2-.5-4.4-2.8-6.8-7.2-7.2 4.4-.5 6.8-2.8 7.2-7.2Z"}),e.jsx("path",{d:"M18.3 16.1c.2 1.8 1.2 2.8 3 3-1.8.2-2.8 1.2-3 3-.2-1.8-1.2-2.8-3-3 1.8-.2 2.8-1.2 3-3Z"})]}),je=()=>e.jsx("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:e.jsx("path",{d:"m6 6 12 12M18 6 6 18"})}),Ie=()=>e.jsx("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:e.jsx("path",{d:"M12 5v14M5 12h14"})}),ke=()=>e.jsxs("svg",{"aria-hidden":"true",viewBox:"0 0 24 24",children:[e.jsx("path",{d:"m4 4 17 8-17 8 3-8-3-8Z"}),e.jsx("path",{d:"M7 12h14"})]}),B=()=>e.jsx("span",{className:"make-ai-assistant__avatar","aria-hidden":"true",children:e.jsx(se,{})}),ve=(a,t,s,o,n)=>a.messages.map(r=>e.jsxs("article",{className:`make-ai-assistant__message make-ai-assistant__message--${r.role}`,children:[r.role==="assistant"?e.jsx(B,{}):null,e.jsxs("div",{className:"make-ai-assistant__message-stack",children:[r.content?e.jsx("div",{className:"make-ai-assistant__bubble",children:r.content}):r.status==="streaming"?e.jsxs("div",{className:"make-ai-assistant__typing","aria-label":"AI 正在思考",children:[e.jsx("span",{}),e.jsx("span",{}),e.jsx("span",{})]}):null,r.artifacts.map(m=>e.jsx(W,{artifact:m,context:t,onAction:o,onActionError:n,registry:s},m.id))]})]},r.id));function re({context:a,onAction:t,onActionError:s,onClose:o,onNewConversation:n,registry:r,subtitle:m,suggestions:u=[],title:g="Make AI 助手",transport:f}){const[j,b]=h.useState(""),[d,I]=h.useState(c.createAssistantConversationState),[$,F]=h.useState(void 0),T=h.useRef(void 0),E=h.useRef(void 0),M=h.useRef(0),P=h.useRef(null),D=h.useRef(!0),U=h.useMemo(()=>r??te(),[r]),q=i=>{M.current+=1;const A=T.current,k=E.current?.iterator;return T.current=void 0,E.current=void 0,!A&&!k?!1:(console.info("[make-ai-assistant] local run cancellation requested",{reason:i}),A?.abort(),Q(k),!0)};h.useEffect(()=>()=>{q("unmount")},[]),h.useEffect(()=>{const i=P.current;if(!i||!D.current)return;const A=requestAnimationFrame(()=>{if(!D.current)return;const k=d.status==="streaming"||window.matchMedia?.("(prefers-reduced-motion: reduce)").matches?"auto":"smooth";typeof i.scrollTo=="function"?i.scrollTo({top:i.scrollHeight,behavior:k}):i.scrollTop=i.scrollHeight});return()=>cancelAnimationFrame(A)},[d.messages,d.status]);const ne=()=>{const i=P.current;i&&(D.current=i.scrollHeight-i.scrollTop-i.clientHeight<=48)},H=async i=>{const A=i.trim();if(!A||d.status==="streaming"||T.current)return;if(c.countCodePointsUpTo(A,c.MAKE_AI_CONVERSATION_LIMITS.messageCharacters)>c.MAKE_AI_CONVERSATION_LIMITS.messageCharacters){F(`输入内容过长,请控制在 ${c.MAKE_AI_CONVERSATION_LIMITS.messageCharacters} 个字符以内`);return}const k={id:xe("user"),content:A},O=new AbortController,w=M.current+1;M.current=w,T.current=O,F(void 0),b(""),I(x=>c.appendUserMessage(x,k));try{let x=!1,_,Z=0,Y=0,K=0;const z=new Set,G=new Set([...d.messages.map(L=>L.id),k.id]),V=new Set,J=f.run({threadId:d.threadId,message:k,context:a,capabilities:y.createArtifactCapabilities(U)},{signal:O.signal})[Symbol.asyncIterator]();for(E.current={iterator:J,requestVersion:w};;){const L=await J.next();if(M.current!==w||L.done)break;let l;try{l=c.parseAssistantEvent(L.value)}catch(N){throw new p(N instanceof Error?N.message:"Invalid assistant event")}if(l.type==="message.start"){if(_!==void 0&&_!==l.runId)throw new p("AI 助手响应 run id 不一致");if(_??=l.runId,Y+=1,Y>c.MAKE_AI_CONVERSATION_LIMITS.assistantMessagesPerRun)throw new p("AI 助手单次响应消息数量超过限制");if(G.has(l.messageId))throw new p("AI 助手响应包含重复的 message id");G.add(l.messageId),V.add(l.messageId)}if(l.type==="message.delta"){if(!V.has(l.messageId))throw new p("AI 助手响应事件顺序无效");const N=c.countCodePointsUpTo(l.delta,c.MAKE_AI_CONVERSATION_LIMITS.messageCharacters-K);if(K+N>c.MAKE_AI_CONVERSATION_LIMITS.messageCharacters)throw new p("AI 助手响应文本超过大小限制");if(K+=N,K>c.MAKE_AI_CONVERSATION_LIMITS.messageCharacters)throw new p("AI 助手响应文本超过大小限制")}if(l.type==="artifact"){if(!V.has(l.messageId))throw new p("AI 助手响应事件顺序无效");if(Z+=1,Z>c.MAKE_AI_CONVERSATION_LIMITS.artifactsPerRun)throw new p("AI 助手单次响应 Artifact 数量超过限制");if(z.has(l.artifact.id))throw new p("AI 助手响应包含重复的 Artifact id");z.add(l.artifact.id)}if(l.type==="message.complete"&&!V.delete(l.messageId))throw new p("AI 助手响应事件顺序无效");if(l.type==="run.complete"&&_!==void 0&&_!==l.runId)throw new p("AI 助手响应 run id 不一致");if(l.type==="run.cancelled"&&l.runId!==void 0&&_!==void 0&&_!==l.runId)throw new p("AI 助手响应 run id 不一致");if(I(N=>c.reduceAssistantEvent(N,l)),l.type==="error"||l.type==="run.cancelled"||l.type==="run.complete"){x=!0;break}}if(!x)throw new p("AI 助手流式响应在终止事件前结束")}catch(x){if(M.current!==w)return;if(O.signal.aborted){I(_=>c.reduceAssistantEvent(_,{type:"run.cancelled"}));return}console.error("[make-ai-assistant] assistant run failed",{appId:a.app.id,errorType:x instanceof Error?x.name:typeof x}),I(_=>c.reduceAssistantEvent(_,{type:"error",code:"TRANSPORT_ERROR",message:x instanceof p?x.message:"连接失败,请重试",retryable:!0}))}finally{M.current===w&&T.current===O&&(T.current=void 0),E.current?.requestVersion===w&&(Q(E.current.iterator),E.current=void 0)}},ie=i=>{i.preventDefault(),H(j)},ce=i=>{i.key==="Enter"&&!i.shiftKey&&!i.nativeEvent.isComposing&&(i.preventDefault(),H(j))},oe=()=>{q("stop")&&I(i=>c.reduceAssistantEvent(i,{type:"run.cancelled"}))},le=()=>{q("new-conversation"),b(""),F(void 0),I(c.createAssistantConversationState()),n?.()};return e.jsxs("section",{className:"make-ai-assistant make-ai-assistant__panel",children:[e.jsxs("header",{className:"make-ai-assistant__header",children:[e.jsx(B,{}),e.jsxs("div",{children:[e.jsx("h2",{children:g}),e.jsxs("p",{children:[e.jsx("span",{className:"make-ai-assistant__online-dot"}),m??a.app.name??"当前应用"]})]}),e.jsxs("div",{className:"make-ai-assistant__header-actions",children:[e.jsx("button",{"aria-label":"新建对话",className:"make-ai-assistant__icon-button",type:"button",onClick:le,children:e.jsx(Ie,{})}),o?e.jsx("button",{"aria-label":"关闭 Make AI 助手",className:"make-ai-assistant__icon-button",type:"button",onClick:o,children:e.jsx(je,{})}):null]})]}),e.jsxs("div",{className:"make-ai-assistant__privacy-note",role:"note",children:[e.jsx("span",{"aria-hidden":"true",children:"◇"}),"当前页面上下文会随请求发送,数据权限以宿主服务端校验结果为准"]}),e.jsxs("div",{className:"make-ai-assistant__body","aria-live":"polite",ref:P,onScroll:ne,children:[d.messages.length===0?e.jsxs("div",{className:"make-ai-assistant__empty",children:[e.jsx(B,{}),e.jsx("h3",{children:"有什么可以帮你?"}),e.jsx("p",{children:"我会结合当前 App 和页面上下文理解问题,并用适合的方式展示结果。"})]}):ve(d,a,U,t,s),d.error?e.jsxs("div",{className:"make-ai-assistant__error",role:"alert",children:[e.jsx("strong",{children:"暂时无法完成"}),e.jsx("span",{children:d.error.message})]}):null]}),e.jsxs("footer",{className:"make-ai-assistant__composer-region",children:[u.length>0&&d.messages.length===0?e.jsx("div",{className:"make-ai-assistant__suggestions","aria-label":"推荐问题",children:u.map((i,A)=>e.jsx("button",{type:"button",onClick:()=>{H(i)},children:i},`${A}-${i}`))}):null,e.jsxs("form",{className:"make-ai-assistant__composer",onSubmit:ie,children:[e.jsx("textarea",{"aria-label":"向 Make AI 助手提问","aria-describedby":$?"make-ai-composer-error":void 0,"aria-invalid":$?!0:void 0,autoFocus:!0,disabled:d.status==="streaming",placeholder:`询问当前 ${a.app.name??"App"} 中的数据…`,rows:2,value:j,onChange:i=>{b(i.currentTarget.value),F(void 0)},onKeyDown:ce}),d.status==="streaming"?e.jsx("button",{"aria-label":"停止生成",className:"make-ai-assistant__send make-ai-assistant__send--stop",type:"button",onClick:oe,children:e.jsx("span",{"aria-hidden":"true"})}):e.jsx("button",{"aria-label":"发送",className:"make-ai-assistant__send",disabled:!j.trim(),type:"submit",children:e.jsx(ke,{})})]}),$?e.jsx("p",{id:"make-ai-composer-error",role:"alert",children:$}):null,e.jsx("p",{children:"AI 生成的结果可能存在偏差,重要数据请核对明细。"})]})]})}function ye({defaultOpen:a=!1,hideLauncher:t=!1,launcher:s,onOpenChange:o,open:n,...r}){const[m,u]=h.useState(a),g=h.useRef(null),f=n??m,j=d=>{n===void 0&&u(d),o?.(d),d||requestAnimationFrame(()=>g.current?.focus())},b=()=>j(!f);return h.useEffect(()=>{if(!f)return;const d=I=>{I.key==="Escape"&&(j(!1),requestAnimationFrame(()=>g.current?.focus()))};return document.addEventListener("keydown",d),()=>document.removeEventListener("keydown",d)},[o,f]),e.jsxs("div",{className:"make-ai-assistant","data-open":f||void 0,children:[!t&&(!f||s)?s?s({open:f,toggle:b}):e.jsxs("button",{"aria-label":f?"关闭 Make AI 助手":"打开 Make AI 助手","aria-expanded":f,className:"make-ai-assistant__launcher",ref:g,type:"button",onClick:b,children:[e.jsx("span",{className:"make-ai-assistant__launcher-orbit","aria-hidden":"true"}),e.jsx(se,{})]}):null,f?e.jsx("aside",{"aria-label":"Make AI 助手","aria-modal":"false",className:"make-ai-assistant__drawer",role:"dialog",children:e.jsx(re,{...r,onClose:()=>j(!1)})}):null]})}exports.createArtifactCapabilities=y.createArtifactCapabilities;exports.createArtifactTemplateRegistry=y.createArtifactTemplateRegistry;exports.extendArtifactTemplateRegistry=y.extendArtifactTemplateRegistry;exports.resolveArtifactTemplate=y.resolveArtifactTemplate;exports.MAKE_AI_ARTIFACT_KINDS=c.MAKE_AI_ARTIFACT_KINDS;exports.MAKE_AI_ARTIFACT_LIMITS=c.MAKE_AI_ARTIFACT_LIMITS;exports.MAKE_AI_ARTIFACT_SCHEMA_VERSION=c.MAKE_AI_ARTIFACT_SCHEMA_VERSION;exports.MAKE_AI_CONVERSATION_LIMITS=c.MAKE_AI_CONVERSATION_LIMITS;exports.appendUserMessage=c.appendUserMessage;exports.createAssistantConversationState=c.createAssistantConversationState;exports.parseArtifact=c.parseArtifact;exports.parseAssistantEvent=c.parseAssistantEvent;exports.reduceAssistantEvent=c.reduceAssistantEvent;exports.validateArtifact=c.validateArtifact;exports.ArtifactRenderer=W;exports.AssistantPanel=re;exports.MakeAiAssistant=ye;exports.createPlatformArtifactRegistry=te;exports.formatArtifactValue=v;exports.platformArtifactTemplates=ae;