@salsita-ai/sdk 0.50.0-develop.a926ccd94f → 0.50.0-develop.aabb56df09
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.
- package/dist/application-spec/parse-application-files/spec/sections/assistant/assistant-schema.js +1 -1
- package/dist/configurator/application-runtime/extensions/selectors.js +1 -1
- package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.d.ts +146 -13
- package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.js +1 -1
- package/dist/configurator/application-runtime/extensions/systems/assistant-system/change-recorder.d.ts +85 -0
- package/dist/configurator/application-runtime/extensions/systems/assistant-system/change-recorder.js +1 -0
- package/dist/configurator/application-runtime/extensions/systems/assistant-system/graphql-tools.d.ts +8 -3
- package/dist/configurator/application-runtime/extensions/systems/assistant-system/graphql-tools.js +1 -1
- package/dist/configurator/application-runtime/extensions/systems/graphql-system/entity-meta.d.ts +4 -0
- package/dist/configurator/application-runtime/extensions/systems/graphql-system/entity-meta.js +1 -1
- package/dist/configurator/application-runtime/extensions/systems/graphql-system/graphql-system.d.ts +16 -1
- package/dist/configurator/application-runtime/extensions/systems/graphql-system/graphql-system.js +1 -1
- package/dist/configurator/application-runtime/extensions/systems/graphql-system/side-effects.d.ts +9 -0
- package/dist/configurator/application-runtime/extensions/systems/graphql-system/side-effects.js +1 -0
- package/dist/configurator/application-runtime/extensions/systems/index.d.ts +1 -1
- package/dist/configurator/index.d.ts +0 -1
- package/dist/configurator/index.js +1 -1
- package/dist/configurator/pages/LoadedConfiguratorDetailPage.js +1 -1
- package/dist/configurator/ui/assistant/AssistantComposer.d.ts +1 -6
- package/dist/configurator/ui/assistant/AssistantComposer.js +1 -1
- package/dist/configurator/ui/assistant/AssistantPanel.js +1 -1
- package/dist/configurator/ui/assistant/AssistantThread.d.ts +1 -6
- package/dist/configurator/ui/assistant/AssistantThread.js +1 -1
- package/dist/configurator/ui/assistant/index.d.ts +1 -1
- package/dist/configurator/ui/assistant/index.js +1 -1
- package/dist/configurator/ui/assistant/thread-items.d.ts +1 -1
- package/dist/configurator/ui/assistant/use-is-assistant-panel-open.d.ts +5 -0
- package/dist/configurator/ui/assistant/use-is-assistant-panel-open.js +1 -0
- package/dist/configurator/ui/configurator-layout/universal/DesktopLayout.js +2 -2
- package/dist/configurator/ui/configurator-layout/universal/Layout.js +1 -1
- package/dist/configurator/ui/configurator-layout/universal/MobileLayout.js +4 -4
- package/dist/configurator/ui/phoenix-layout-elements/AssistantToolbarButton.d.ts +2 -2
- package/dist/configurator/ui/phoenix-layout-elements/AssistantToolbarButton.js +1 -1
- package/dist/docs/index.json +1 -1
- package/dist/docs/layouts/toolbar.mdx +3 -1
- package/dist/docs/other-features/side-effects.mdx +26 -0
- package/dist/domain/components/updates.d.ts +16 -0
- package/dist/domain/domain-context/store-system/store-system.js +1 -1
- package/dist/editor/graphql/GraphQLPanel.js +1 -1
- package/dist/phoenix/application-spec/generate-assistant-prompt.d.ts +3 -2
- package/dist/phoenix/application-spec/generate-assistant-prompt.js +1 -1
- package/dist/ui-sdk/common/use-viewport-size.d.ts +4 -1
- package/dist/ui-sdk/common/use-viewport-size.js +1 -1
- package/package.json +4 -4
- package/dist/configurator/assistant/index.d.ts +0 -1
- package/dist/configurator/assistant/index.js +0 -1
- package/dist/configurator/assistant/use-assistant-chat.d.ts +0 -30
- package/dist/configurator/assistant/use-assistant-chat.js +0 -1
- package/dist/configurator/ui/assistant/AssistantPanelProvider.d.ts +0 -42
- package/dist/configurator/ui/assistant/AssistantPanelProvider.js +0 -1
package/dist/configurator/application-runtime/extensions/systems/graphql-system/side-effects.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Localizable } from '@salsita-ai/common/utils';
|
|
2
|
+
import type { DataUpdate, DomainEntity } from '#package/domain';
|
|
3
|
+
/**
|
|
4
|
+
* What the updates of an emission tell the assistant agent the configurator did beyond what was
|
|
5
|
+
* asked, in applied order with duplicates kept, the way the user gets them as snackbars. An update's
|
|
6
|
+
* `agentHint` replaces its user-facing `hint` for the agent, `null` keeps the update from the agent,
|
|
7
|
+
* and an update with neither says nothing. Empty text counts as none, as it does for the snackbar.
|
|
8
|
+
*/
|
|
9
|
+
export declare const readSideEffects: (updates: ReadonlyArray<DataUpdate<DomainEntity<string>, DomainEntity<string>>>, resolveLocalizable: (message: Localizable) => string) => readonly string[];
|
package/dist/configurator/application-runtime/extensions/systems/graphql-system/side-effects.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const readSideEffects=(e,t)=>e.flatMap(({hint:e,agentHint:a})=>null===a?[]:void 0!==a?a?[a]:[]:e?[t(e)]:[]);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { AnimationSystem, type AnimationSystemContext } from './animation-system.js';
|
|
2
|
-
export { type AssistantClientTool, AssistantSystem, type AssistantSystemContext, } from './assistant-system/assistant-system.js';
|
|
2
|
+
export { type AssistantChatSnapshot, type AssistantClientTool, type AssistantPanelSnapshot, AssistantSystem, type AssistantSystemContext, } from './assistant-system/assistant-system.js';
|
|
3
3
|
export { CameraControlSystem, CameraControlType } from './camera-control-system/camera-control-system.js';
|
|
4
4
|
export { type AnyCameraSystem, CameraSystem, type CameraSystemContext } from './camera-control-system/camera-system.js';
|
|
5
5
|
export { createCameraControls } from './camera-control-system/create-camera-controls.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{ConfiguratorApp}from"./ConfiguratorApp.js";export*from"./application-runtime/index.js";export*from"./
|
|
1
|
+
export{ConfiguratorApp}from"./ConfiguratorApp.js";export*from"./application-runtime/index.js";export*from"./common/index.js";export*from"./configurator-context/index.js";export*from"./pages/index.js";export*from"./scene/index.js";export*from"./ui/index.js";export*from"./integration/index.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as
|
|
1
|
+
import{jsx as e,jsxs as o,Fragment as i}from"react/jsx-runtime";import r from"mui-modal-provider";import{memo as n,useCallback as t,useEffect as a,useMemo as d}from"react";import{match as s}from"ts-pattern";import{InvalidAccessKeyError as l}from"#package/client";import{BuiltInLoadingPhase as u,CommonAnalyticsFactory as m,DomainLifecycleBoundary as c,LoadedDataProvider as f,useAccessService as p,useAnalyticsService as g,useAuthorizedClient as v,useConfiguratorDomainFactory as w,useConfiguratorLoadStatus as y,useConfiguratorRawLoadedData as h,useExpectPhase as I,useLoadedDataActions as j,useLoadingError as x,useLoadingPhase as C,useLogger as b,useRoutingService as k,useSpecAssistant as L}from"#package/react-sdk";import{useConfigurator as U}from"../application-runtime/index.js";import{IntegrationSubscription as M,OnConfiguratorReadyProvider as S,ViewportStateSync as E,useLayoutSystemConfig as F}from"../configurator-context/index.js";import{Layout as R,Legacy as D}from"../ui/index.js";import{LayoutCustomOwnerUi as T,LayoutCustomReadUi as P,LayoutDialog as A}from"../ui/phoenix-layout-elements/index.js";import{ConfiguratorNotFoundPage as O}from"./ConfiguratorNotFoundPage.js";import{DevContextFallback as V}from"./error-boundaries/DevContextFallback.js";import{DevLoadingFallback as q}from"./error-boundaries/DevLoadingFallback.js";import{LoadingErrorBoundary as z}from"./error-boundaries/LoadingErrorBoundary.js";import{useLoad as B}from"./use-load.js";let G=n(n=>{let{viewMode:t}=n,l=F();(()=>{let{assistantSystem:e}=U(),o=null!=L();a(()=>{if(o)return e.activate()},[e,o])})();let{ownerUi:u,readUi:m}=d(()=>s(l.layout).with("simple",()=>({ownerUi:e(D.SimpleOwnerLayout,{}),readUi:e(D.SummaryReadLayout,{})})).with("tabs",()=>({ownerUi:e(D.TabsOwnerLayout,{}),readUi:e(D.SummaryReadLayout,{})})).with("steps",()=>({ownerUi:e(D.StepsOwnerLayout,{}),readUi:e(D.SummaryReadLayout,{})})).with("universal",()=>({ownerUi:e(R,{}),readUi:e(R,{})})).with("custom",()=>({ownerUi:e(T,{}),readUi:e(P,{})})).exhaustive(),[l.layout]);return e(r,{children:o(S,{children:[t?m:u,"universal"===l.layout&&o(i,{children:[e(D.CommonFinalizePage,{}),e(A,{})]})]})})});export const LoadedConfiguratorDetailPage=()=>{I(u.SceneAssets);let{configurationId:i,accessInfo:r}=p(),n=v(),a=k(),d=b(),s=g(),{startConfiguratorLoad:L,completeConfiguratorLoad:U,failConfiguratorLoad:S,resetConfiguratorLoad:F}=j(),{isLoading:R,isError:D}=y(),T=h(),P=w(),A=t(()=>r.viewMode&&void 0!==r.revisionId?n.getConfigurationRevision(i,r.revisionId):n.getConfiguration(i),[r.revisionId,r.viewMode,n,i]),N=t(()=>{L()},[L]),H=t(e=>{U({initialRevisionId:e.revisionId,initialEntities:e.data,modelVersion:e.modelVersion,rootEntityType:e.rootEntityType,schemaIdentity:P}),s.push(m.ConfigurationLoaded(e.configurationId,e.revisionId,r.viewMode?"read":"owner")),d.appendToGlobalContext({configurationId:e.configurationId,revisionId:e.revisionId,mode:r.viewMode}),d.info("Configuration loaded.")},[r.viewMode,s,U,P,d]),J=t(e=>{if(S(e),e instanceof l)return void a.rejectAccessToken(i,r.raw);let o=e instanceof Error?e:Error("Configuration loading failed with an unknown error.",{cause:e});d.error("Configuration loading failed because the API request did not succeed. Verify the configuration ID and access token.",{configurationId:i},o)},[r.raw,i,S,d,a]),K=t(()=>{F()},[F]);return(B({key:[n,i,r.revisionId,r.viewMode],load:A,onStart:N,onSuccess:H,onError:J,onCleanup:K}),C({id:u.DataFetch,label:"Loading configuration…"},R),x(D),D)?e(O,{}):null===T?null:e(f,{value:T,children:e(z,{fallbackRender:o=>e(q,{...o}),children:e(c,{type:"configurator",children:e(z,{FallbackComponent:V,children:o(M,{children:[e(E,{}),e(G,{viewMode:r.viewMode})]})})})})})};
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
import type { AssistantChatState } from '../../assistant/index.js';
|
|
2
|
-
export interface AssistantComposerProps {
|
|
3
|
-
readonly chat: AssistantChatState | undefined;
|
|
4
|
-
readonly onFocusChange: (isFocused: boolean) => void;
|
|
5
|
-
}
|
|
6
1
|
/**
|
|
7
2
|
* The message input of the panel. Enter sends and Shift+Enter adds a line. While a reply runs the
|
|
8
3
|
* send control is a Stop control and the input stays editable, so the next message can be written.
|
|
9
4
|
* A thread this session may not continue disables the input and says why.
|
|
10
5
|
*/
|
|
11
|
-
export declare const AssistantComposer: (
|
|
6
|
+
export declare const AssistantComposer: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as e,jsxs as a}from"react/jsx-runtime";import{Trans as
|
|
1
|
+
import{jsx as e,jsxs as a}from"react/jsx-runtime";import{Trans as i}from"@lingui/react";import{IconButton as o,InputBase as r,Tooltip as t,styled as n}from"@mui/material";import{useCallback as s,useRef as d,useState as l}from"react";import{useEagerObservableSelector as m,useLocalizable as c}from"#package/react-sdk";import{PhxIcon as p,useResponsive as u}from"#package/ui-sdk";import{useConfigurator as b}from"../../application-runtime/index.js";import{AssistantPanelName as g}from"./theme.js";let h={id:"sdk.assistant.composer.placeholder",message:"Ask or tell me what to change…"},k={id:"sdk.assistant.composer.send.label",message:"Send"},f={id:"sdk.assistant.composer.stop.label",message:"Stop"},x=n("form",{name:g,slot:"composer"})(({theme:{palette:e,spacing:a}})=>({borderBlockStart:`1px solid ${e.divider}`,display:"grid",gap:a(.75),paddingBlock:a(1.25),paddingInline:`var(--phx-sidebar-padding, ${a(2)})`})),y=n("div",{name:g,slot:"inputFrame"})(({theme:{palette:e,spacing:a}})=>({alignItems:"flex-end",border:`1px solid ${e.divider}`,borderRadius:12,display:"flex",gap:a(1),paddingBlock:a(.5),paddingInline:`${a(1.5)} ${a(.5)}`,"&:focus-within":{borderColor:e.primary.main},"&:has(textarea:disabled)":{background:e.action.disabledBackground}})),v=n(r,{name:g,slot:"input"})(({theme:{spacing:e,typography:a}})=>({...a.body2,flex:1,paddingBlock:e(.75)})),B=n(o,{name:g,slot:"sendButton"})(({theme:{palette:e}})=>({background:e.primary.main,borderRadius:8,color:e.primary.contrastText,"&:hover":{background:e.primary.dark},"&.Mui-disabled":{background:e.action.disabledBackground,color:e.action.disabled}})),C=n(o,{name:g,slot:"stopButton"})(({theme:{palette:e}})=>({background:e.text.primary,borderRadius:8,color:e.background.paper,"&:hover":{background:e.text.secondary}})),R=n("span")({background:"currentColor",blockSize:10,borderRadius:2,inlineSize:10,margin:5}),S=n("div",{name:g,slot:"hint"})(({theme:{palette:e,typography:a}})=>({...a.caption,color:e.text.secondary}));export const AssistantComposer=()=>{let{assistantSystem:o}=b(),[r,n]=l(""),g=d(null),{isDesktop:I}=u(),$=c(h),j=c(k),w=c(f),{isReplying:z,isContinuable:F}=m(o.chat$,e=>({isReplying:e.isLoading,isContinuable:e.isContinuable}),[]),A=r.trim(),D=F&&!z&&A.length>0,P=s(()=>{D&&(n(""),o.send(A),I||g.current?.blur())},[o,D,A,I]),T=s(e=>{e.preventDefault(),P()},[P]),E=s(e=>{"Enter"!==e.key||e.shiftKey||e.nativeEvent.isComposing||(e.preventDefault(),P())},[P]),K=s(()=>{o.stop()},[o]);return a(x,{onSubmit:T,children:[!F&&e(S,{role:"status",children:e(i,{id:"sdk.assistant.composer.notContinuable",message:"This conversation can be read here, but it can no longer be continued."})}),a(y,{children:[e(v,{multiline:!0,maxRows:6,placeholder:$,value:r,disabled:!F,inputRef:g,onChange:e=>n(e.target.value),onKeyDown:E,onFocus:()=>o.setInputFocused(!0),onBlur:()=>o.setInputFocused(!1),inputProps:{"aria-label":$}}),z?e(t,{title:w,placement:"top",children:e(C,{size:"small","aria-label":w,onClick:K,children:e(R,{})})}):e(t,{title:j,placement:"top",children:e("span",{children:e(B,{type:"submit",size:"small","aria-label":j,disabled:!D,children:e(p,{name:"PaperPlaneRightBold",fontSize:"small"})})})})]}),e(S,{children:e(i,{id:"sdk.assistant.composer.disclaimer",message:"AI can be wrong. Check the result."})})]})};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{IconButton as
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{IconButton as s,Tooltip as a,Typography as i,styled as n}from"@mui/material";import{useCallback as r}from"react";import{useLocalizable as o}from"#package/react-sdk";import{PhxIcon as l}from"#package/ui-sdk";import{useConfigurator as m}from"../../application-runtime/index.js";import{AssistantComposer as d}from"./AssistantComposer.js";import{AssistantThread as p}from"./AssistantThread.js";import{AssistantPanelName as c}from"./theme.js";import{useIsAssistantPanelOpen as u}from"./use-is-assistant-panel-open.js";let b={id:"sdk.assistant.panel.title",message:"Assistant"},f={id:"sdk.assistant.panel.close.label",message:"Close assistant"};export const ASSISTANT_PANEL_SLOT="slot[assistant]";let g=n("section",{name:c,slot:"root"})(({theme:{palette:e}})=>({background:`var(--phx-sidebar-background, ${e.background.paper})`,border:"var(--phx-sidebar-border, 0)",borderRadius:"inherit",display:"grid",gridTemplateColumns:"minmax(0, 1fr)",gridTemplateRows:"min-content minmax(0, 1fr) min-content",inset:0,overflow:"hidden",position:"absolute",zIndex:1})),h=n("header",{name:c,slot:"header"})(({theme:{palette:e,spacing:t}})=>({alignItems:"center",borderBlockEnd:`1px solid ${e.divider}`,display:"flex",gap:t(1),justifyContent:"space-between",paddingBlock:t(1),paddingInline:`var(--phx-sidebar-padding, ${t(2)}) ${t(1)}`})),x=n(i,{name:c,slot:"title"})({fontWeight:600}),k=n(s,{name:c,slot:"closeButton"})({}),j=e=>{e.target instanceof Element&&e.target.closest("button")&&e.preventDefault()};export const AssistantPanel=()=>{let{assistantSystem:s}=m(),i=u(),n=o(b),c=o(f),v=r(()=>{s.setOpen(!1)},[s]);return i?t(g,{"data-sidebar":"slot[assistant]","aria-label":n,onMouseDown:j,children:[t(h,{children:[e(x,{variant:"subtitle1",component:"h2",children:n}),e(a,{title:c,placement:"top",children:e(k,{size:"small","aria-label":c,onClick:v,children:e(l,{name:"X"})})})]}),e(p,{}),e(d,{})]}):null};
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
import type { AssistantChatState } from '../../assistant/index.js';
|
|
2
|
-
export interface AssistantThreadProps {
|
|
3
|
-
readonly chat: AssistantChatState | undefined;
|
|
4
|
-
readonly onRetry: () => void;
|
|
5
|
-
}
|
|
6
1
|
/**
|
|
7
2
|
* The conversation: user bubbles, assistant Markdown, tool chips, and what the panel
|
|
8
3
|
* has to say itself, which is a greeting for an empty thread, a "Thinking…" line and a failure with
|
|
9
4
|
* its way out. It follows a streaming reply until the user scrolls up.
|
|
10
5
|
*/
|
|
11
|
-
export declare const AssistantThread: (
|
|
6
|
+
export declare const AssistantThread: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as e,jsxs as i}from"react/jsx-runtime";import{Trans as a}from"@lingui/react";import{Button as
|
|
1
|
+
import{jsx as e,jsxs as i}from"react/jsx-runtime";import{Trans as a}from"@lingui/react";import{Button as t,styled as s}from"@mui/material";import{useMemo as r}from"react";import{match as n}from"ts-pattern";import{useEagerObservableValue as o}from"#package/react-sdk";import{PhxIcon as l}from"#package/ui-sdk";import{useConfigurator as d}from"../../application-runtime/index.js";import{AssistantToolChips as m}from"./AssistantChips.js";import{AssistantMarkdown as p}from"./AssistantMarkdown.js";import{describeAssistantFailure as c}from"./assistant-failure.js";import{AssistantPanelName as h}from"./theme.js";import{buildThreadView as g}from"./thread-items.js";import{useFollowStream as u}from"./use-follow-stream.js";let f=s("div",{name:h,slot:"thread"})({display:"grid",position:"relative"}),k=s("div",{name:h,slot:"messages"})(({theme:{spacing:e,typography:i}})=>({...i.body2,display:"flex",flexDirection:"column",gap:e(1.5),overflowY:"auto",overscrollBehavior:"contain",paddingBlock:e(2),paddingInline:`var(--phx-sidebar-padding, ${e(2)})`,"& > :first-child":{marginBlockStart:"auto"}})),v=s("div",{name:h,slot:"userMessage"})(({theme:{palette:e,spacing:i}})=>({alignSelf:"flex-end",background:`hsl(from ${e.primary.main} h s l / 12%)`,borderRadius:"14px 14px 4px 14px",maxInlineSize:"85%",overflowWrap:"anywhere",paddingBlock:i(1),paddingInline:i(1.5),whiteSpace:"pre-wrap"})),w=s("div",{name:h,slot:"greeting"})({}),b=s("div",{name:h,slot:"status"})(({theme:{palette:e,typography:i}})=>({...i.caption,color:e.text.secondary})),x=s("div",{name:h,slot:"notice"})(({theme:{palette:e,shape:i,spacing:a}})=>({alignItems:"center",background:e.action.hover,borderRadius:i.borderRadius,display:"flex",flexWrap:"wrap",gap:a(1),justifyContent:"space-between",paddingBlock:a(1),paddingInline:a(1.5)})),y=s(t,{name:h,slot:"newReplyButton"})(({theme:{palette:e,spacing:i}})=>({background:e.text.primary,borderRadius:"calc(infinity * 1px)",color:e.background.paper,insetBlockEnd:i(1),insetInlineStart:"50%",position:"absolute",translate:"-50% 0","&:hover":{background:e.text.secondary}})),j=({item:i,isActive:a})=>n(i).with({kind:"user"},({text:i})=>e(v,{children:i})).with({kind:"text"},({markdown:i,isStreaming:a})=>e(p,{markdown:i,isStreaming:a})).with({kind:"tools"},({tools:i})=>e(m,{tools:i,isActive:a})).exhaustive();export const AssistantThread=()=>{let{assistantSystem:s}=d(),m=o(s.chat$),{messages:p,isLoading:h}=m,{items:v,isThinking:T}=r(()=>g(p,h),[p,h]),I=r(()=>v.filter(({kind:e})=>"user"===e).length,[v]),S=m.error?c(m.failedStatus):void 0,{scrollerRef:A,hasUnseenContent:B,handleScroll:R,scrollToEnd:C}=u(r(()=>({messages:p,isThinking:T,failure:S?.kind}),[p,T,S?.kind]),I);return i(f,{children:[i(k,{ref:A,onScroll:R,role:"log","aria-live":"polite",children:[m.isLoaded&&0===v.length&&!h&&!S&&e(w,{children:e(a,{id:"sdk.assistant.thread.greeting",message:"Hi. I can answer questions about this design and change it with you. Tell me what you need."})}),v.map(i=>e(j,{item:i,isActive:h&&i===v.at(-1)},i.id)),T&&e(b,{children:e(a,{id:"sdk.assistant.thread.thinking",message:"Thinking…"})}),S&&i(x,{role:"alert",children:[e("span",{children:n(S.kind).with("notAvailable",()=>e(a,{id:"sdk.assistant.failure.notAvailable",message:"The assistant is not available here."})).with("busy",()=>e(a,{id:"sdk.assistant.failure.busy",message:"The assistant is still working on an earlier message."})).with("unavailable",()=>e(a,{id:"sdk.assistant.failure.unavailable",message:"The assistant is unavailable right now."})).exhaustive()}),S.canRetry&&e(t,{size:"small",variant:"outlined",color:"inherit",onClick:s.reloadThread,children:e(a,{id:"sdk.assistant.failure.retry.label",message:"Try again"})})]})]}),B&&e(y,{size:"small",onClick:C,endIcon:e(l,{name:"CaretDown"}),children:e(a,{id:"sdk.assistant.thread.newReply.label",message:"New reply"})})]})};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { AssistantPanel, ASSISTANT_PANEL_SLOT } from './AssistantPanel.js';
|
|
2
|
-
export {
|
|
2
|
+
export { useIsAssistantPanelOpen } from './use-is-assistant-panel-open.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{AssistantPanel,ASSISTANT_PANEL_SLOT}from"./AssistantPanel.js";export{
|
|
1
|
+
export{AssistantPanel,ASSISTANT_PANEL_SLOT}from"./AssistantPanel.js";export{useIsAssistantPanelOpen}from"./use-is-assistant-panel-open.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { UIMessage } from '@tanstack/ai-
|
|
1
|
+
import type { UIMessage } from '@tanstack/ai-client';
|
|
2
2
|
import { type AssistantToolChip } from './tool-chip.js';
|
|
3
3
|
/** A tool call of the thread, with what its chip shows and what a click on the chip logs. */
|
|
4
4
|
export interface AssistantToolItem {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{useEagerObservableSelector as e,useSpecAssistant as n}from"#package/react-sdk";import{useConfigurator as t}from"../../application-runtime/index.js";export const useIsAssistantPanelOpen=()=>{let{assistantSystem:p}=t(),r=n();return e(p.panel$,e=>e.open,[])&&null!=r};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{jsx as a,jsxs as t,Fragment as o}from"react/jsx-runtime";import{keyframes as e,paperClasses as r,snackbarClasses as d,styled as i,useTheme as n,useThemeProps as s}from"@mui/material";import{AnimatePresence as l,motion as p}from"motion/react";import{useCallback as b,useRef as u}from"react";import{useAccessService as c,useIsFullscreenActive as m}from"#package/react-sdk";import{attrf as h,commonStyles as y,numToPx as g,useInvalidateScrollTimeline as f,useIsEmpty as x,useResponsive as k}from"#package/ui-sdk";import{usePreview as v}from"../../../configurator-context/index.js";import{ASSISTANT_PANEL_SLOT as S,AssistantPanel as E,
|
|
1
|
+
import{jsx as a,jsxs as t,Fragment as o}from"react/jsx-runtime";import{keyframes as e,paperClasses as r,snackbarClasses as d,styled as i,useTheme as n,useThemeProps as s}from"@mui/material";import{AnimatePresence as l,motion as p}from"motion/react";import{useCallback as b,useRef as u}from"react";import{useAccessService as c,useIsFullscreenActive as m}from"#package/react-sdk";import{attrf as h,commonStyles as y,numToPx as g,useInvalidateScrollTimeline as f,useIsEmpty as x,useResponsive as k}from"#package/ui-sdk";import{usePreview as v}from"../../../configurator-context/index.js";import{ASSISTANT_PANEL_SLOT as S,AssistantPanel as E,useIsAssistantPanelOpen as w}from"../../assistant/index.js";import{LayoutSlots as R}from"../slots/index.js";import{DesktopPreview as $}from"./DesktopPreview.js";import{useSceneSafeArea as B}from"./use-scene-safe-area.js";let C="PhxDesktopSidebar",D="minimalist",T="split",I="visible",A="hidden",P="assistant",F={Root:i("div",{name:C,slot:"root",shouldForwardProp:a=>"ownerState"!==a})(({ownerState:a})=>[`
|
|
2
2
|
--phx-sidebar-background: ${a.background};
|
|
3
3
|
--phx-sidebar-border: ${a.border};
|
|
4
4
|
--phx-sidebar-filter: ${a.filter};
|
|
@@ -46,4 +46,4 @@ import{jsx as a,jsxs as t,Fragment as o}from"react/jsx-runtime";import{keyframes
|
|
|
46
46
|
180deg,
|
|
47
47
|
hsl(from black h s l / 12%),
|
|
48
48
|
hsl(from black h s l / 0%) 8px
|
|
49
|
-
)`}=s({props:{},name:C}),{hasMiniSidebar:N,hasSplitSidebar:V}=R.useSidebarContent(),X=w()
|
|
49
|
+
)`}=s({props:{},name:C}),{hasMiniSidebar:N,hasSplitSidebar:V}=R.useSidebarContent(),X=w(),{accessInfo:G}=c(),J=m(),{isPreview:K,isHidden:O}=v(),Q=!O&&!K,U=!J,{setCanvasPadding:Y,setAnimating:Z}=k(),{containerRef:_,safeAreaRef:aa,update:at}=B(Y,N&&!X,Q),ao=b(()=>{Z(!0)},[Z]),ae=b(()=>{Z(!1),at()},[Z,at]),ar=Q&&U,ad=x(e,{disabled:!ar}),ai=x(r,{disabled:!ar});f(r,{disabled:!ar});let an={background:g,border:S,borderRadius:L,filter:W,isHeaderEmpty:ad,isContentEmpty:ai,padding:q,scrollableIndicatorBackground:M,width:y};return a(o,{children:t(l,{mode:"wait",children:[!O&&K&&a($,{},"preview-layout"),Q&&t(z,{layoutId:"ui-layout",layout:!0,ownerState:{sidebarWidth:y},"data-layout":h({state:{initial:!J,fullscreen:J}}),onLayoutAnimationStart:ao,onLayoutAnimationComplete:ae,children:[a(H,{ref:_}),a("header",{"data-layout":"slot[header]",children:a(R.DesktopHeader,{})}),t("main",{"data-layout":"slot[body]",children:[a("div",{"data-layout":"slot[body.top] interactive",children:a(R.DesktopCallToAction,{})}),a("div",{ref:aa,"data-layout":"slot[body.safeSceneArea]"}),t("div",{"data-layout":"slot[body.bottom] interactive",children:[a("div",{"data-layout":"slot[body.toolbar]",children:a(R.DesktopToolbar,{})}),a("div",{"data-layout":"slot[body.toolControls]",children:!J&&a(R.DesktopToolControls,{})}),a("div",{"data-layout":"slot[body.viewControls]",children:a(R.DesktopViewControls,{})}),a("div",{"data-layout":"slot[body.logo]",children:a(R.DesktopPoweredBy,{})}),a("div",{"data-layout":"slot[body.sideEffects]",children:a(R.DesktopSnackbarsRoot,{})})]})]}),a("aside",{"data-layout":"slot[sidebar]",children:t(F.Root,{ownerState:an,"data-sidebar":h({variant:{[`${D}`]:N,[`${T}`]:V},state:{[`${I}`]:U,[`${A}`]:!U,[`${P}`]:X}}),inert:U?void 0:"",children:[a(F.Tabs,{ownerState:an,"data-sidebar":"slot[tabs]",children:a(R.DesktopSidebarTabs,{})}),a(F.Header,{ref:e,ownerState:an,"data-sidebar":"slot[header]",children:a(R.DesktopSidebarBackButton,{})}),a(F.Body,{ownerState:an,"data-sidebar":"slot[body]",children:a(F.Content,{ref:r,ownerState:an,"data-sidebar":"slot[content]",children:a(R.DesktopSidebarContent,{})})}),a(F.Footer,{ownerState:an,"data-sidebar":"slot[footer]",children:a(R.DesktopSidebarFooter,{})}),a(E,{})]})}),t("footer",{"data-layout":"slot[footer] interactive",children:[G.viewMode&&!J&&a(R.DesktopReadonlyBanner,{}),a(R.DesktopFooter,{})]})]},"interface-layout")]})})};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as r,jsxs as
|
|
1
|
+
import{jsx as r,jsxs as o,Fragment as s}from"react/jsx-runtime";import{useResponsive as t}from"#package/ui-sdk";import{LayoutSlots as e}from"../slots/index.js";import{DesktopLayout as a}from"./DesktopLayout.js";import{MobileLayout as m}from"./MobileLayout.js";export const Layout=()=>{let{isDesktop:i}=t();return o(s,{children:[r(e.Services,{}),r(e.SharedCanvas,{}),i?r(a,{}):r(m,{})]})};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import{jsx as t,jsxs as a,Fragment as e}from"react/jsx-runtime";import{snackbarClasses as o,styled as i,useTheme as r,useThemeProps as n}from"@mui/material";import d from"lodash/noop.js";import{AnimatePresence as s}from"motion/react";import{useRef as l}from"react";import{useAccessService as m,useIsFullscreenActive as
|
|
1
|
+
import{jsx as t,jsxs as a,Fragment as e}from"react/jsx-runtime";import{snackbarClasses as o,styled as i,useTheme as r,useThemeProps as n}from"@mui/material";import d from"lodash/noop.js";import{AnimatePresence as s}from"motion/react";import{useRef as l}from"react";import{useAccessService as m,useEagerObservableSelector as c,useIsFullscreenActive as p}from"#package/react-sdk";import{attrf as u,commonStyles as b,numToPx as h,useIsEmpty as g,useResponsive as f,useViewportSize as y}from"#package/ui-sdk";import{useConfigurator as x}from"../../../application-runtime/index.js";import{usePreview as v}from"../../../configurator-context/index.js";import{ASSISTANT_PANEL_SLOT as w,AssistantPanel as S,useIsAssistantPanelOpen as $}from"../../assistant/index.js";import{LayoutSlots as k}from"../slots/index.js";import{MobileHeader as C}from"../slots/slots.js";import{MobilePreview as F}from"./MobilePreview.js";import{useSceneSafeArea as M}from"./use-scene-safe-area.js";let T="visible",I="hidden",R=i("div",{name:"PhxMobileHeader",slot:"root"})(({theme:{spacing:t}})=>({...b.transition.fadeInFrom,alignItems:"center",display:"flex",gap:t(1),justifyContent:"space-between",position:"relative","@container style(--inspect: on)":{background:"hsl(from tomato h s l / 50%)"},'[data-header*="slot"]':{display:"flex",gap:t(2),"& > *":{pointerEvents:"auto"}},'[data-header="slot[center]"]':{display:"grid",inset:0,placeItems:"center",position:"absolute"},[`&[data-header*="${T}"]`]:{opacity:1,transitionDuration:"200ms, 300ms",transitionTimingFunction:"linear, ease-out",translate:"0 0"},[`&[data-header*="${I}"]`]:{opacity:0,transitionDuration:"100ms, 100ms",transitionTimingFunction:"linear, ease-in",translate:"0 -60%"}})),B="visible",E="hidden",P=i("div",{name:"PhxMobileControls",slot:"root"})(({theme:{spacing:t}})=>({alignItems:"end",display:"flex",position:"relative","@container style(--inspect: on)":{background:"hsl(from tomato h s l / 50%)"},'[data-controls*="slot"]':{"& > *":{pointerEvents:"auto"}},'[data-controls="slot[toolControls]"]':{...b.transition.fadeInFrom,"&:not(:empty)":{marginInlineEnd:t(2)},"& > *":{...b.transition.fadeIn,transitionDelay:"300ms",transitionDuration:"300ms"}},'[data-controls="slot[viewControls]"]':{...b.transition.fadeInFrom,marginInlineStart:"auto"},'[data-controls="slot[toolbar]"]':{"&:not(:empty)":{marginInlineStart:t(2)}},[`&[data-controls*="${B}"]`]:{'[data-controls="slot[toolControls]"], [data-controls="slot[viewControls]"]':{opacity:1,transitionDuration:"200ms, 300ms",transitionTimingFunction:"linear, ease-out",translate:"0 0"}},[`&[data-controls*="${E}"]`]:{'[data-controls="slot[toolControls]"], [data-controls="slot[viewControls]"]':{opacity:0,transitionDuration:"100ms, 100ms",transitionTimingFunction:"linear, ease-in",translate:"0 60%"}}})),D="PhxMobileSidebar",j="visible",A="hidden",z="assistant",H={Root:i("div",{name:D,slot:"root",shouldForwardProp:t=>"ownerState"!==t})(({ownerState:t})=>[`
|
|
2
2
|
--phx-sidebar-background: ${t.background};
|
|
3
3
|
--phx-sidebar-padding: ${t.padding};
|
|
4
4
|
--phx-sidebar-radius: ${t.borderRadius}px;
|
|
5
|
-
`,{...
|
|
5
|
+
`,{...b.transition.fadeInFrom,background:"var(--phx-sidebar-background)",borderStartStartRadius:"var(--phx-sidebar-radius)",borderStartEndRadius:"var(--phx-sidebar-radius)",display:"grid",gridTemplateColumns:"minmax(0, 1fr)",gridTemplateRows:"min-content minmax(0, 1fr) min-content",position:"relative","& > *":{pointerEvents:"auto"},"@container style(--inspect: on)":{background:"hsl(from gold h s l / 50%)"},'&:has([data-sidebar*="slot[content]"])':{...t.isContentEmpty&&{"--phx-sidebar-radius":0,'[data-sidebar*="slot[header]"]':{paddingBlock:0,"& > *":{display:"none"}}}},[`&[data-sidebar*="${j}"]`]:{opacity:1,transitionDuration:"200ms, 300ms",transitionTimingFunction:"linear, ease-out",translate:"0 0"},[`&[data-sidebar*="${A}"]`]:{opacity:0,transitionDuration:"100ms, 100ms",transitionTimingFunction:"linear, ease-in",translate:"0 60%"},[`&[data-sidebar*="${z}"] > :not([data-sidebar="${w}"])`]:{visibility:"hidden"}}]),Header:i("header",{name:D,slot:"header",shouldForwardProp:t=>"ownerState"!==t})(({theme:{spacing:t}})=>({alignItems:"center",borderStartStartRadius:"inherit",borderStartEndRadius:"inherit",display:"grid",gap:t(1),gridTemplateColumns:"repeat(2, minmax(0, 1fr))",paddingBlock:"calc(var(--phx-sidebar-padding) * 0.5)",paddingInline:"var(--phx-sidebar-padding)","& > *":{...b.transition.fadeIn,transitionDelay:"100ms",transitionDuration:"300ms"},'[data-sidebar="slot[header.start]"]':{},'[data-sidebar="slot[header.end]"]':{justifySelf:"end"}})),Body:i("div",{name:D,slot:"body",shouldForwardProp:t=>"ownerState"!==t})({display:"grid",gridTemplateRows:"minmax(0, 1fr)"}),Content:i("div",{name:D,slot:"content",shouldForwardProp:t=>"ownerState"!==t})(({theme:{spacing:t}})=>({...b.layout.normalizeScrollableContainer,display:"grid",gap:t(2),gridAutoRows:"min-content",paddingBlock:"calc(var(--phx-sidebar-padding) * 0.5)",paddingInline:"var(--phx-sidebar-padding)","&:empty":{paddingBlock:0}})),Tabs:i("div",{name:D,slot:"tabs",shouldForwardProp:t=>"ownerState"!==t})(({theme:{palette:t}})=>({borderBlockStart:`1px solid ${t.divider}`,paddingBlock:"calc(var(--phx-sidebar-padding) * 0.5)",paddingInline:"calc(var(--phx-sidebar-padding) * 0.75)","&:is(:empty)":{border:0,padding:0}})),Footer:i("footer",{name:D,slot:"footer",shouldForwardProp:t=>"ownerState"!==t})(({theme:{palette:t}})=>({borderBlockStart:`1px solid ${t.divider}`,paddingBlock:"calc(var(--phx-sidebar-padding) * 0.5)",paddingInline:"var(--phx-sidebar-padding)","&:is(:empty)":{borderColor:"transparent",paddingBlock:0}}))};export const PhxMobileLayoutName="PhxMobileLayout";let L="initial",q="fullscreen",N="min(480px, 50cqb)",V=["auto","min-content","max-content","fit-content"],G=i("div",{name:"PhxMobileLayout",slot:"root",shouldForwardProp:t=>"ownerState"!==t})(({ownerState:t,theme:{spacing:a}})=>[`
|
|
6
6
|
--inspect: off; // 🕹️ inspection mode toggle
|
|
7
7
|
|
|
8
|
-
--phx-layout-sidebar-track-size: ${
|
|
8
|
+
--phx-layout-sidebar-track-size: ${h(t.sidebarHeight)};
|
|
9
9
|
--phx-layout-gutter: ${a(2)};
|
|
10
10
|
`,{display:"grid",gridTemplateColumns:`
|
|
11
11
|
[full-start]
|
|
@@ -39,4 +39,4 @@ import{jsx as t,jsxs as a,Fragment as e}from"react/jsx-runtime";import{snackbarC
|
|
|
39
39
|
[footer-end]
|
|
40
40
|
var(--phx-layout-gutter)
|
|
41
41
|
[full-end]
|
|
42
|
-
`},'[data-layout*="slot[body.header]"]':{gridArea:"header-start / main-start / header-end / main-end"},'[data-layout*="slot[body.footer]"]':{gridArea:"footer-start / main-start / footer-end / main-end",position:"relative"},'[data-layout*="slot[body.safeSceneArea]"]':{gridArea:"full","@container style(--inspect: on)":{background:"hsl(from lime h s l / 50%)"}},'[data-layout="slot[body.sideEffects]"]':{insetBlockEnd:`calc(100% + ${a(2)})`,position:"absolute"},'[data-layout*="slot[sidebar]"]':{display:"grid",gridArea:"sidebar-start / full-start / sidebar-end / full-end",gridTemplateColumns:"minmax(0, 1fr)",gridTemplateRows:"minmax(0, auto)"},'[data-layout*="slot[footer]"]':{gridArea:"footer-start / full-start / footer-end / full-end",zIndex:1},'&:has([data-sidebar*="slot[content]"])':{...t.isContentEmpty&&{"--phx-layout-sidebar-track-size":"min-content"}},[`&[data-layout*="${
|
|
42
|
+
`},'[data-layout*="slot[body.header]"]':{gridArea:"header-start / main-start / header-end / main-end"},'[data-layout*="slot[body.footer]"]':{gridArea:"footer-start / main-start / footer-end / main-end",position:"relative"},'[data-layout*="slot[body.safeSceneArea]"]':{gridArea:"full","@container style(--inspect: on)":{background:"hsl(from lime h s l / 50%)"}},'[data-layout="slot[body.sideEffects]"]':{insetBlockEnd:`calc(100% + ${a(2)})`,position:"absolute"},'[data-layout*="slot[sidebar]"]':{display:"grid",gridArea:"sidebar-start / full-start / sidebar-end / full-end",gridTemplateColumns:"minmax(0, 1fr)",gridTemplateRows:"minmax(0, auto)"},'[data-layout*="slot[footer]"]':{gridArea:"footer-start / full-start / footer-end / full-end",zIndex:1},'&:has([data-sidebar*="slot[content]"])':{...t.isContentEmpty&&{"--phx-layout-sidebar-track-size":"min-content"}},[`&[data-layout*="${L}"]`]:{transitionDelay:"200ms",transitionDuration:"300ms"},[`&[data-layout*="${q}"]`]:{transitionDelay:"0ms",transitionDuration:"300ms"},[`&:has([data-sidebar*="${A}"])[class]`]:{"--phx-layout-sidebar-track-size":0}},null!=t.assistantFocusHeight&&{'[data-layout*="slot[sidebar]"]':{alignSelf:"start",blockSize:`min(100%, ${t.assistantFocusHeight}px)`,gridRow:"full-start / full-end",zIndex:2}}]),J=i("div")({gridArea:"1 / 1 / -1 / -1"}),K=t=>({inert:t?"":void 0});export const MobileLayout=()=>{let o=l(null),{palette:i,shape:b,spacing:h}=r(),{sidebarHeight:w=N}=n({props:{},name:"PhxMobileLayout"}),{background:O=i.background.paper,borderRadius:Q=b.sidebarBorderRadius??b.borderRadius,padding:U=h(2)}=n({props:{},name:D}),{accessInfo:W}=m(),X=p(),{isPreview:Y,isHidden:Z}=v(),_=!Z&&!Y,tt=!X&&_,ta=!X&&_,te=!X,{setCanvasPadding:to}=f(),{containerRef:ti,safeAreaRef:tr}=M(_?to:d,!1),tn=g(o,{disabled:!te}),{assistantSystem:td}=x(),ts=$(),tl=c(td.panel$,t=>t.isInputFocused,[]),tm=ts&&te&&tl,tc=y(tm),tp=tn&&!ts,tu={isContentEmpty:tp,sidebarHeight:ts?V.includes(w)?N:w:w,assistantFocusHeight:tm?tc?.[1]:void 0},tb={background:O,borderRadius:Q,padding:U,isContentEmpty:tp};return a(e,{children:[t(s,{initial:!1,children:!Z&&Y&&t(F,{})}),a(G,{ownerState:tu,"data-layout":u({state:{[`${L}`]:!X,[`${q}`]:X}}),...K(!_),children:[t(J,{ref:ti}),t("div",{"data-layout":"slot[sideEffects]",children:t(k.MobileSnackbarsRoot,{})}),a("main",{"data-layout":"slot[body]",children:[t("header",{"data-layout":"slot[body.header]",children:a(R,{"data-header":u({state:{[`${T}`]:tt,[`${I}`]:!tt}}),...K(!tt),children:[t("div",{"data-header":"slot[start]",children:t(C,{})}),t("div",{"data-header":"slot[center]",children:t(k.MobileCallToAction,{})}),a("div",{"data-header":"slot[end]",children:[W.viewMode&&!X&&t(k.MobileReadonlyBanner,{}),t(k.MobileHamburgerMenu,{})]})]})}),t("div",{ref:tr,"data-layout":"slot[body.safeSceneArea]"}),t("div",{"data-layout":"slot[body.footer] interactive",children:a(P,{"data-controls":u({state:{[`${B}`]:ta,[`${E}`]:!ta}}),children:[t("div",{"data-controls":"slot[toolControls]",...K(!ta),children:t(k.MobileToolControls,{})}),t("div",{"data-controls":"slot[viewControls]",...K(!ta),children:t(k.MobileViewControls,{})}),t("div",{"data-controls":"slot[toolbar]",children:_&&t(k.MobileToolbar,{})})]})})]}),t("aside",{"data-layout":"slot[sidebar]",children:a(H.Root,{ownerState:tb,"data-sidebar":u({state:{[`${j}`]:te,[`${A}`]:!te,[`${z}`]:ts}}),...K(!te),children:[a(H.Header,{ownerState:tb,"data-sidebar":"slot[header]",children:[t("div",{"data-sidebar":"slot[header.start]",children:t(k.MobileSidebarBackButton,{})}),t("div",{"data-sidebar":"slot[header.end]",children:t(k.MobilePoweredBy,{})})]}),t(H.Body,{ownerState:tb,"data-sidebar":"slot[body]",children:t(H.Content,{ref:o,ownerState:tb,"data-sidebar":"slot[content]",children:t(k.MobileSidebarContent,{})})}),t(H.Tabs,{ownerState:tb,"data-sidebar":"slot[tabs]",children:t(k.MobileTabs,{})}),t(H.Footer,{ownerState:tb,"data-sidebar":"slot[footer]",children:t(k.MobileSidebarFooter,{})}),t(S,{})]})}),t("footer",{"data-layout":"slot[footer] interactive",children:t(k.MobileFooter,{})})]})]})};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Opens and closes the assistant panel. It renders nothing
|
|
3
|
-
*
|
|
2
|
+
* Opens and closes the assistant panel. It renders nothing in a project without an assistant. A
|
|
3
|
+
* layout that lists the button is expected to carry the panel; the button does not check for it.
|
|
4
4
|
*/
|
|
5
5
|
export declare const AssistantToolbarButton: import("react").FunctionComponent<{
|
|
6
6
|
readonly showTitle?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as t}from"react/jsx-runtime";import{Badge as r}from"@mui/material";import{memo as
|
|
1
|
+
import{jsx as t}from"react/jsx-runtime";import{Badge as r}from"@mui/material";import{memo as o,useCallback as a}from"react";import{assistantToolbarButtonSchema as i,createPhoenixLayoutElement as e}from"#package/domain";import{useEagerObservableValue as s,useLocalizable as n,useSpecAssistant as m}from"#package/react-sdk";import{DesktopToolbar as l,PhxIcon as p,useResponsive as c}from"#package/ui-sdk";import{useConfigurator as d}from"../../application-runtime/index.js";let u={id:"sdk.assistant.toolbarButton.label",message:"Assistant"};export const AssistantToolbarButton=e({schema:i,component:o(o=>{let{icon:i,showTitle:e=!0}=o,{assistantSystem:k}=d(),f=m(),{open:A,hasUnreadReply:b}=s(k.panel$),g=n(u),{isPhone:x,isTablet:h}=c(),B=a(()=>{k.setOpen(!A)},[k,A]);return f?t(l.Button,{title:g,onClick:B,showTitle:e&&!x&&!h,"aria-pressed":A,sx:{'&[aria-pressed="true"]':{backgroundColor:"action.selected"}},children:t(r,{color:"primary",variant:"dot",overlap:"circular",invisible:!b,children:t(p,{name:i??(A?"CustomAiAssistantBold":"CustomAiAssistant")})})}):null})});
|
package/dist/docs/index.json
CHANGED
|
@@ -84,7 +84,9 @@ Phoenix provides built-in toolbar buttons for common operations:
|
|
|
84
84
|
- `assistantToolbarButton` - Open and close the built-in assistant panel. It renders only in a project whose
|
|
85
85
|
application spec has an `assistant` section. `props.showTitle` defaults to `true`; the label shows on a
|
|
86
86
|
desktop-sized layout only. The default toolbar includes it, in a group of its own, when the spec has an
|
|
87
|
-
`assistant` section.
|
|
87
|
+
`assistant` section. Only the universal layout carries the panel, and the button does not hide itself in a
|
|
88
|
+
layout without it. A custom layout that renders the toolbar therefore defines a `toolbar` component without the
|
|
89
|
+
button, because the default toolbar would add it.
|
|
88
90
|
|
|
89
91
|
### Mobile Toolbar Configuration
|
|
90
92
|
|
|
@@ -102,6 +102,32 @@ configuratorBuilder
|
|
|
102
102
|
.buildConfig()
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
+
### Hints and the AI assistant
|
|
106
|
+
|
|
107
|
+
In a configurator with the AI assistant, the assistant is told the same hints: they arrive as
|
|
108
|
+
`sideEffects` with the result of its changes and in the dry-runs of recipes and options, so it can
|
|
109
|
+
tell the user what else happened. The hints also explain what the user changed between two messages:
|
|
110
|
+
every message carries a change record of the configuration, and each of its lines ends with the hint
|
|
111
|
+
of the last update that touched it, or with the `updateTag` when the update has none. Set `agentHint`
|
|
112
|
+
beside `hint` when the assistant needs different wording, for example with ids or values a snackbar
|
|
113
|
+
would not show:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
phx.frontend.updates.DomainEntityModification({
|
|
117
|
+
entityId: oldPlate.id,
|
|
118
|
+
stateDelta: { finish: validMaterial.finish },
|
|
119
|
+
updateTag: 'fix.finish',
|
|
120
|
+
hint: msg`Material finish was adjusted`,
|
|
121
|
+
agentHint: `The finish of ${oldPlate.id} was changed to ${validMaterial.finish}, the only one this material comes in.`,
|
|
122
|
+
})
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
- `agentHint` is a plain string, never shown to the user and not localized.
|
|
126
|
+
- `agentHint: null` keeps the wording from the assistant while the user still gets the `hint`: the
|
|
127
|
+
update is left out of `sideEffects`, and the change record explains its line by the `updateTag`. It
|
|
128
|
+
does not hide the change itself, which the assistant can always read from the configuration.
|
|
129
|
+
- `agentHint` without a `hint` tells only the assistant.
|
|
130
|
+
|
|
105
131
|
## Example
|
|
106
132
|
|
|
107
133
|
Here you can see the live example!
|
|
@@ -7,6 +7,8 @@ export interface ComponentModification<COMPONENT_TYPE extends SystemComponentTyp
|
|
|
7
7
|
entityId: EntityId;
|
|
8
8
|
updateTag: string;
|
|
9
9
|
hint?: Localizable;
|
|
10
|
+
/** What the assistant agent is told about this update instead of `hint`; `null` keeps the wording from it, and its change record then explains the change by `updateTag`. Never shown to the user. */
|
|
11
|
+
agentHint?: string | null;
|
|
10
12
|
componentInstance: ComponentInstance<COMPONENT_TYPE>;
|
|
11
13
|
writableState: WritableStateOfComponent<COMPONENT_TYPE>;
|
|
12
14
|
metadata?: Record<string, unknown>;
|
|
@@ -17,6 +19,8 @@ export interface EphemeralRecordModification<COMPONENT_TYPE extends SystemCompon
|
|
|
17
19
|
entityId: EntityId;
|
|
18
20
|
updateTag: string;
|
|
19
21
|
hint?: Localizable;
|
|
22
|
+
/** What the assistant agent is told about this update instead of `hint`; `null` keeps the wording from it, and its change record then explains the change by `updateTag`. Never shown to the user. */
|
|
23
|
+
agentHint?: string | null;
|
|
20
24
|
componentInstance: ComponentInstance<COMPONENT_TYPE>;
|
|
21
25
|
writableState: WritableStateOfComponent<COMPONENT_TYPE>;
|
|
22
26
|
}
|
|
@@ -25,6 +29,8 @@ export interface EphemeralRecordCreation<COMPONENT_TYPE extends SystemComponentT
|
|
|
25
29
|
entityId: EntityId;
|
|
26
30
|
updateTag: string;
|
|
27
31
|
hint?: Localizable;
|
|
32
|
+
/** What the assistant agent is told about this update instead of `hint`; `null` keeps the wording from it, and its change record then explains the change by `updateTag`. Never shown to the user. */
|
|
33
|
+
agentHint?: string | null;
|
|
28
34
|
componentInstance: ComponentInstance<COMPONENT_TYPE>;
|
|
29
35
|
initialState: StateOfComponent<COMPONENT_TYPE>;
|
|
30
36
|
}
|
|
@@ -34,6 +40,8 @@ export interface EphemeralRecordDeletion<COMPONENT_TYPE extends SystemComponentT
|
|
|
34
40
|
componentInstance: ComponentInstance<COMPONENT_TYPE>;
|
|
35
41
|
updateTag: string;
|
|
36
42
|
hint?: Localizable;
|
|
43
|
+
/** What the assistant agent is told about this update instead of `hint`; `null` keeps the wording from it, and its change record then explains the change by `updateTag`. Never shown to the user. */
|
|
44
|
+
agentHint?: string | null;
|
|
37
45
|
}
|
|
38
46
|
export type DomainEntityStateDelta<ENTITY extends DomainEntity<string>> = Partial<Omit<ENTITY, 'id' | 'type'>>;
|
|
39
47
|
export interface DomainEntityModification<ENTITY extends DomainEntity<string> = DomainEntity<string>> {
|
|
@@ -41,6 +49,8 @@ export interface DomainEntityModification<ENTITY extends DomainEntity<string> =
|
|
|
41
49
|
entityId: ENTITY['id'];
|
|
42
50
|
updateTag: string;
|
|
43
51
|
hint?: Localizable;
|
|
52
|
+
/** What the assistant agent is told about this update instead of `hint`; `null` keeps the wording from it, and its change record then explains the change by `updateTag`. Never shown to the user. */
|
|
53
|
+
agentHint?: string | null;
|
|
44
54
|
stateDelta: DomainEntityStateDelta<ENTITY>;
|
|
45
55
|
origin?: ComponentModification<SystemComponentTypeConstraint>;
|
|
46
56
|
}
|
|
@@ -55,6 +65,8 @@ export interface DomainEntityCreation<ENTITY extends DomainEntity<string>, PAREN
|
|
|
55
65
|
collection?: string;
|
|
56
66
|
parentId: PARENT['id'];
|
|
57
67
|
hint?: Localizable;
|
|
68
|
+
/** What the assistant agent is told about this update instead of `hint`; `null` keeps the wording from it, and its change record then explains the change by `updateTag`. Never shown to the user. */
|
|
69
|
+
agentHint?: string | null;
|
|
58
70
|
}
|
|
59
71
|
export interface DomainEntityReplacement<ENTITY extends DomainEntity<string>> {
|
|
60
72
|
kind: 'replaceDomainEntity';
|
|
@@ -63,12 +75,16 @@ export interface DomainEntityReplacement<ENTITY extends DomainEntity<string>> {
|
|
|
63
75
|
updateTag: string;
|
|
64
76
|
keepChildren: boolean;
|
|
65
77
|
hint?: Localizable;
|
|
78
|
+
/** What the assistant agent is told about this update instead of `hint`; `null` keeps the wording from it, and its change record then explains the change by `updateTag`. Never shown to the user. */
|
|
79
|
+
agentHint?: string | null;
|
|
66
80
|
}
|
|
67
81
|
export interface EntityDeletion<ENTITY extends DomainEntity<string>> {
|
|
68
82
|
kind: 'deleteEntity';
|
|
69
83
|
entityId: EntityId<ENTITY>;
|
|
70
84
|
updateTag: string;
|
|
71
85
|
hint?: Localizable;
|
|
86
|
+
/** What the assistant agent is told about this update instead of `hint`; `null` keeps the wording from it, and its change record then explains the change by `updateTag`. Never shown to the user. */
|
|
87
|
+
agentHint?: string | null;
|
|
72
88
|
}
|
|
73
89
|
export type DataUpdate<ENTITY extends DomainEntity<string>, PARENT extends DomainEntity<string>> = EphemeralRecordModification | EphemeralRecordCreation | EphemeralRecordDeletion | DomainEntityModification<ENTITY> | DomainEntityCreation<ENTITY, PARENT> | DomainEntityReplacement<ENTITY> | EntityDeletion<ENTITY>;
|
|
74
90
|
export type StateUpdate<ENTITY extends DomainEntity<string>, PARENT extends DomainEntity<string>> = ComponentModification<SystemComponentTypeConstraint> | DataUpdate<ENTITY, PARENT>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{CompositeKeyMap as e,assertExistence as t,isEqualArray as i}from"@salsita-ai/common/utils";import{dragStateComponent as o}from"../../components/drag-state-component.js";import{hoverStateComponent as r}from"../../components/hover-state-component.js";import{selectionStateComponent as s}from"../../components/selection-state-component.js";import{getComponentSystemFilterState as n}from"../../components/system-component-filter.js";import{systemVirtualEntityId as a}from"../../components/system-virtual-entity.js";import{systemUpdateFactory as d}from"../../components/updates.js";import{isSystemViewportStateComponentSnapshot as m}from"../../components/viewport-state-component.js";import{isEqualComponentInstance as l}from"../../core/component.js";import{domainEntityTypeFromId as c,isVirtualEntityId as p}from"../../core/model.js";import{projectedEntitiesComponent as h}from"../../system-components/index.js";import{cloneEvalCache as f,createEvalCacheToken as v,getEvalCache as g,setEvalCache as u}from"../../utils/eval-cache.js";import{createCascadeDeletesTransformer as y}from"../relation-transformers/cascade-deletes.js";import{createCascadeRefPruningTransformer as S}from"../relation-transformers/cascade-ref-pruning.js";import{applyUpdates as I}from"./apply-updates.js";import{LifecycleStateSlice as _}from"./lifecycle-state-slice.js";import{mergeReconciliationsUpdates as x,reconcileProjectedEntities as T}from"./reconcile-projected-entities.js";let E={uninitializedError:"StoreSystem is not initialized."},k=v({clone:e=>e}),w=class InvalidInitialStateError extends Error{emission;childError;constructor(e,t,i){let o="";"uncaught"===e.validity.severity&&(o=`: ${e.validity.error.message}`),("fatal"===e.validity.severity||"fixable"===e.validity.severity)&&(o=`: ${e.validity.entityViolations.map(e=>{let i=e.violation.message;return null!=i?t(i):e.violation.type}).join(", ")}`),super(`Initial state is not valid! Severity: ${e.validity.severity}, Cause: ${o}`),this.emission=e,this.childError=i,this.name="InvalidInitialStateError"}},b=(e,t)=>{try{return e()}catch(e){throw t(e),e}};export class StoreSystem{_context;stateSlices;get isInitialized(){return this.committed.isInitialized}_onBeforeCommitHooks=[];committed=new _(E);potentiallyInvalid=new _(E);rendered=new _(E);stagedUpdates=void 0;transformToDataUpdates=(e,t)=>{let i=!1,o=e.map(e=>"modifyComponent"===e.kind?(i=!0,this.componentModificationToDataUpdate(e,t)):e);return i?o:e};createInitialTransformPipe=()=>[{transformer:this.transformToDataUpdates,priority:1/0,registrationToken:{},name:"TransformToDataUpdates"}];transformPipe=this.createInitialTransformPipe();_cascadeDeletesTransformer=(...e)=>(this._cascadeDeletesTransformerMemo??=y(this._context.selectors.getCompositionProjections()))(...e);_cascadeDeletesTransformerMemo;_refPruningTransformer=(...e)=>(this._refPruningTransformerMemo??=S(this._context.selectors.getComponentReader()))(...e);_refPruningTransformerMemo;_deselectOnDeleteTransformer=(e,t)=>{let i=new Set(e.filter(e=>"deleteEntity"===e.kind).map(e=>e.entityId));if(0===i.size)return e;let o=n(t).selectedEntityId;return o&&i.has(o)?[...e,d.EphemeralRecordModification({componentInstance:{entityId:a,componentType:s},updateTag:"AutoDeselectRemovedProjectedEntity",writableState:{selectedEntityId:t.rootEntityId}})]:e};constructor(e){this._context=e,this.stateSlices={committed:this.committed.observable,rendered:this.rendered.observable,potentiallyInvalid:this.potentiallyInvalid.observable}}_validateState=e=>this._context.selectors.getValidationProjections().validateState(e);initialize=()=>{let e=this._context.selectors.getInitialDomainState();this.stagedUpdates=void 0;let t=this._validateState(e),i={kind:"reset",state:e,validity:t,tag:void 0,transformationLog:void 0},o=i;if(!o.validity.valid&&"fatal"===o.validity.severity||"fixable"===o.validity.severity){this._context.domainServicesSelectors.getLogger().debug("Trying to fix initial emission:",o);let e=o.state,{transformedUpdates:t,transformationLog:i}=this.applyTransformers([],e,"committed"),r=I(this.transformToDataUpdates(t,e),e);f(e,r),o={kind:"reset",state:r,validity:this._validateState(r),tag:"fixed",transformationLog:i}}if(!o.validity.valid){if(this._context.domainServicesSelectors.getLogger().error("Invalid initial emission:",{initialEmission:i,fixedEmission:o}),"uncaught"===o.validity.severity)throw new w(o,this._context.domainServicesSelectors.getResolveLocalizable(),o.validity.error??void 0);throw new w(o,this._context.domainServicesSelectors.getResolveLocalizable())}this.committed.next(o),this.rendered.next(o),this.potentiallyInvalid.next(o)};registerTransformer(e,i,o){let r={};return((e,i,o)=>{let r=0;for(;r<e.length&&0>=o(t(e[r]),i);)r++;e.splice(r,0,i)})(this.transformPipe,{registrationToken:r,transformer:i,priority:e,name:o},(e,t)=>e.priority===t.priority?0:e.priority<t.priority?-1:1),()=>{let e=this.transformPipe.findIndex(e=>e.registrationToken===r);-1!==e&&this.transformPipe.splice(e,1)}}onBeforeCommit(e){return this._onBeforeCommitHooks.push(e),()=>{this._onBeforeCommitHooks=this._onBeforeCommitHooks.filter(t=>t!==e)}}componentModificationToDataUpdate=(e,t)=>{let i=e.entityId;if(!p(i)){let t=this._context.selectors.getComponentReaderIndexes().opticMap.get(c(i))?.get(e.componentInstance.componentType)?.get(e.componentInstance.instanceName);if(t?.kind==="simple"){let o=t.write(e.writableState);return{kind:"modifyDomainEntity",entityId:i,updateTag:e.updateTag,stateDelta:o,hint:e.hint,origin:e}}}let o=t.ephemeralRecords.find(t=>l(t.componentInstance,e.componentInstance));if(o)return{kind:"modifyEphemeralRecord",entityId:e.entityId,updateTag:e.updateTag,componentInstance:o.componentInstance,writableState:e.writableState,hint:e.hint};throw Error(`Component ${e.componentInstance.componentType.name} is not attached on entity #${e.entityId}`)};getNewState=(e,t)=>{let i=I(this.transformToDataUpdates(e,t),t);return f(this.rendered.isInitialized?this.rendered.value.state:t,i),i};applyTransformers(e,t,i){let o=this._context.environmentSelectors.getEnvironmentIsDev()?[]:void 0;return{transformedUpdates:this.transformPipe.reduce((e,{transformer:r,name:s})=>{let n,a=o?[]:void 0,d=a?(e,t,i)=>{n=e,a.push({phase:e,message:t,data:i})}:void 0,m=b(()=>r(e,t,i,d),r=>{this._context.domainServicesSelectors.getLogger().error("Error while applying transformer!",{name:s,updates:e,previousState:t,kind:i,transformationLog:o},r instanceof Error?r:Error(String(r)))});return a&&o&&o.push({name:s,status:n??(m===e?"no-event":"apply"),entries:a,updatesIn:e,updatesOut:m}),m},e),transformationLog:o}}_updateProjectedEntities(e,t,o){if(!e.validity.valid)return e;let r=this._context.selectors.getComponentReader().readManyComponents({componentTypes:[h]},e.state),s=g(e.previousState,k);if(s&&i(s,r))return e;let n=0,a=e,d=[];for(;a.validity.valid;){n++;let i=T(a.state.entities,r,t);if(0===i.length)break;if(n>10)throw Error(`Maximum number of reconciliation rounds reached: 10. Projected entities seem to be recursively depending on themselves.
|
|
1
|
+
import{CompositeKeyMap as e,assertExistence as t,isEqualArray as i}from"@salsita-ai/common/utils";import{dragStateComponent as o}from"../../components/drag-state-component.js";import{hoverStateComponent as r}from"../../components/hover-state-component.js";import{selectionStateComponent as s}from"../../components/selection-state-component.js";import{getComponentSystemFilterState as n}from"../../components/system-component-filter.js";import{systemVirtualEntityId as a}from"../../components/system-virtual-entity.js";import{systemUpdateFactory as d}from"../../components/updates.js";import{isSystemViewportStateComponentSnapshot as m}from"../../components/viewport-state-component.js";import{isEqualComponentInstance as l}from"../../core/component.js";import{domainEntityTypeFromId as c,isVirtualEntityId as p}from"../../core/model.js";import{projectedEntitiesComponent as h}from"../../system-components/index.js";import{cloneEvalCache as f,createEvalCacheToken as v,getEvalCache as g,setEvalCache as u}from"../../utils/eval-cache.js";import{createCascadeDeletesTransformer as y}from"../relation-transformers/cascade-deletes.js";import{createCascadeRefPruningTransformer as S}from"../relation-transformers/cascade-ref-pruning.js";import{applyUpdates as I}from"./apply-updates.js";import{LifecycleStateSlice as _}from"./lifecycle-state-slice.js";import{mergeReconciliationsUpdates as x,reconcileProjectedEntities as T}from"./reconcile-projected-entities.js";let E={uninitializedError:"StoreSystem is not initialized."},k=v({clone:e=>e}),w=class InvalidInitialStateError extends Error{emission;childError;constructor(e,t,i){let o="";"uncaught"===e.validity.severity&&(o=`: ${e.validity.error.message}`),("fatal"===e.validity.severity||"fixable"===e.validity.severity)&&(o=`: ${e.validity.entityViolations.map(e=>{let i=e.violation.message;return null!=i?t(i):e.violation.type}).join(", ")}`),super(`Initial state is not valid! Severity: ${e.validity.severity}, Cause: ${o}`),this.emission=e,this.childError=i,this.name="InvalidInitialStateError"}},b=(e,t)=>{try{return e()}catch(e){throw t(e),e}};export class StoreSystem{_context;stateSlices;get isInitialized(){return this.committed.isInitialized}_onBeforeCommitHooks=[];committed=new _(E);potentiallyInvalid=new _(E);rendered=new _(E);stagedUpdates=void 0;transformToDataUpdates=(e,t)=>{let i=!1,o=e.map(e=>"modifyComponent"===e.kind?(i=!0,this.componentModificationToDataUpdate(e,t)):e);return i?o:e};createInitialTransformPipe=()=>[{transformer:this.transformToDataUpdates,priority:1/0,registrationToken:{},name:"TransformToDataUpdates"}];transformPipe=this.createInitialTransformPipe();_cascadeDeletesTransformer=(...e)=>(this._cascadeDeletesTransformerMemo??=y(this._context.selectors.getCompositionProjections()))(...e);_cascadeDeletesTransformerMemo;_refPruningTransformer=(...e)=>(this._refPruningTransformerMemo??=S(this._context.selectors.getComponentReader()))(...e);_refPruningTransformerMemo;_deselectOnDeleteTransformer=(e,t)=>{let i=new Set(e.filter(e=>"deleteEntity"===e.kind).map(e=>e.entityId));if(0===i.size)return e;let o=n(t).selectedEntityId;return o&&i.has(o)?[...e,d.EphemeralRecordModification({componentInstance:{entityId:a,componentType:s},updateTag:"AutoDeselectRemovedProjectedEntity",writableState:{selectedEntityId:t.rootEntityId}})]:e};constructor(e){this._context=e,this.stateSlices={committed:this.committed.observable,rendered:this.rendered.observable,potentiallyInvalid:this.potentiallyInvalid.observable}}_validateState=e=>this._context.selectors.getValidationProjections().validateState(e);initialize=()=>{let e=this._context.selectors.getInitialDomainState();this.stagedUpdates=void 0;let t=this._validateState(e),i={kind:"reset",state:e,validity:t,tag:void 0,transformationLog:void 0},o=i;if(!o.validity.valid&&"fatal"===o.validity.severity||"fixable"===o.validity.severity){this._context.domainServicesSelectors.getLogger().debug("Trying to fix initial emission:",o);let e=o.state,{transformedUpdates:t,transformationLog:i}=this.applyTransformers([],e,"committed"),r=I(this.transformToDataUpdates(t,e),e);f(e,r),o={kind:"reset",state:r,validity:this._validateState(r),tag:"fixed",transformationLog:i}}if(!o.validity.valid){if(this._context.domainServicesSelectors.getLogger().error("Invalid initial emission:",{initialEmission:i,fixedEmission:o}),"uncaught"===o.validity.severity)throw new w(o,this._context.domainServicesSelectors.getResolveLocalizable(),o.validity.error??void 0);throw new w(o,this._context.domainServicesSelectors.getResolveLocalizable())}this.committed.next(o),this.rendered.next(o),this.potentiallyInvalid.next(o)};registerTransformer(e,i,o){let r={};return((e,i,o)=>{let r=0;for(;r<e.length&&0>=o(t(e[r]),i);)r++;e.splice(r,0,i)})(this.transformPipe,{registrationToken:r,transformer:i,priority:e,name:o},(e,t)=>e.priority===t.priority?0:e.priority<t.priority?-1:1),()=>{let e=this.transformPipe.findIndex(e=>e.registrationToken===r);-1!==e&&this.transformPipe.splice(e,1)}}onBeforeCommit(e){return this._onBeforeCommitHooks.push(e),()=>{this._onBeforeCommitHooks=this._onBeforeCommitHooks.filter(t=>t!==e)}}componentModificationToDataUpdate=(e,t)=>{let i=e.entityId;if(!p(i)){let t=this._context.selectors.getComponentReaderIndexes().opticMap.get(c(i))?.get(e.componentInstance.componentType)?.get(e.componentInstance.instanceName);if(t?.kind==="simple"){let o=t.write(e.writableState);return{kind:"modifyDomainEntity",entityId:i,updateTag:e.updateTag,stateDelta:o,hint:e.hint,agentHint:e.agentHint,origin:e}}}let o=t.ephemeralRecords.find(t=>l(t.componentInstance,e.componentInstance));if(o)return{kind:"modifyEphemeralRecord",entityId:e.entityId,updateTag:e.updateTag,componentInstance:o.componentInstance,writableState:e.writableState,hint:e.hint,agentHint:e.agentHint};throw Error(`Component ${e.componentInstance.componentType.name} is not attached on entity #${e.entityId}`)};getNewState=(e,t)=>{let i=I(this.transformToDataUpdates(e,t),t);return f(this.rendered.isInitialized?this.rendered.value.state:t,i),i};applyTransformers(e,t,i){let o=this._context.environmentSelectors.getEnvironmentIsDev()?[]:void 0;return{transformedUpdates:this.transformPipe.reduce((e,{transformer:r,name:s})=>{let n,a=o?[]:void 0,d=a?(e,t,i)=>{n=e,a.push({phase:e,message:t,data:i})}:void 0,m=b(()=>r(e,t,i,d),r=>{this._context.domainServicesSelectors.getLogger().error("Error while applying transformer!",{name:s,updates:e,previousState:t,kind:i,transformationLog:o},r instanceof Error?r:Error(String(r)))});return a&&o&&o.push({name:s,status:n??(m===e?"no-event":"apply"),entries:a,updatesIn:e,updatesOut:m}),m},e),transformationLog:o}}_updateProjectedEntities(e,t,o){if(!e.validity.valid)return e;let r=this._context.selectors.getComponentReader().readManyComponents({componentTypes:[h]},e.state),s=g(e.previousState,k);if(s&&i(s,r))return e;let n=0,a=e,d=[];for(;a.validity.valid;){n++;let i=T(a.state.entities,r,t);if(0===i.length)break;if(n>10)throw Error(`Maximum number of reconciliation rounds reached: 10. Projected entities seem to be recursively depending on themselves.
|
|
2
2
|
If expressions populating 'projectedEntities' components rely on other projected entities, make sure that the dependencies do not have cycles.`);let s=(d=x(d,i)).map(e=>e.dataUpdate),m=this._cascadeDeletesTransformer(s,e.previousState,o,void 0,t),l=this._refPruningTransformer(m,e.previousState,o,void 0,t),c=this._deselectOnDeleteTransformer(l,e.previousState,o,void 0,t);if(!(a=this.prepareStateEmissionWithoutTransformation([...t,...c],e.previousState,o)).validity.valid)return this._context.domainServicesSelectors.getLogger().error("Reconciliation of projected entities led to an invalid state! Reconciliation skipped.",{emission:a}),e;r=this._context.selectors.getComponentReader().readManyComponents({componentTypes:[h]},a.state)}return u(a.state,k,r),a}prepareStateEmission(e,t,i){let{transformedUpdates:o,transformationLog:r}=this.applyTransformers(e,t,i),s=this.prepareStateEmissionWithoutTransformation(o,t,i);return{...this._updateProjectedEntities(s,o,i),transformationLog:r}}emissionCache=new e([Map,WeakMap,WeakMap,WeakMap,WeakMap]);getEmissionCacheKey=(e,t,i)=>[e,t,i,this._context.selectors.getStoreRuntimeDependencies(),this._context.selectors.getExpressionContext()];prepareStateEmissionWithoutTransformation=(e,t,i)=>{let o=this.getEmissionCacheKey(i,t,e),r=this.emissionCache.get(o);if(r)return r;let s=b(()=>this.transformToDataUpdates(e,t),o=>{this._context.domainServicesSelectors.getLogger().error("Error while transforming updates to data updates!",{updates:e,previousState:t,kind:i},o instanceof Error?o:Error(String(o)))}),n=b(()=>I(s,t),o=>{this._context.domainServicesSelectors.getLogger().error("Error while applying updates!",{updates:e,previousState:t,kind:i,dataUpdates:s},o instanceof Error?o:Error(String(o)))});f(this.rendered.isInitialized?this.rendered.value.state:t,n);let a=this._validateState(n);"uncaught"===a.severity&&this._context.domainServicesSelectors.getLogger().error("There was an uncaught validation error:",{updates:e,dataUpdates:s,previousState:t,newState:n,kind:i},a.error);let d={kind:i,previousState:t,state:n,updates:s,validity:a,transformationLog:void 0};return this.emissionCache.set(o,d),d};stage(e,t=!0){this.stagedUpdates=e;let i=this.prepareStateEmission(e,this.committed.value.state,"staged");return t&&this.emit(i),i}emit(e){"staged"===e.kind?e.validity.valid&&this.rendered.nextIfDifferent(e):(e.validity.valid?(this.committed.nextIfDifferent(e),this.rendered.nextIfDifferent(e)):this.rendered.nextIfDifferent(this.committed.value),this.potentiallyInvalid.nextIfDifferent(e))}commit=()=>{if(void 0===this.stagedUpdates)return;let e=this.prepareStateEmission(this.stagedUpdates,this.committed.value.state,"committed"),t=()=>{if(this._onBeforeCommitHooks.some(i=>!1===i(e,t))){this._context.domainServicesSelectors.getLogger().debug("Commit was canceled by one of the onBeforeCommit hooks! Resetting rendered state.",e),this.rollback();return}this.stagedUpdates=void 0,this._context.domainServicesSelectors.getLogger().debug("commit",e),this.emit(e)};t()};commitPrepared=e=>{if("committed"!==e.kind||!e.validity.valid)throw Error(`commitPrepared received a ${e.validity.valid?e.kind:"invalid"} emission, but only a valid committed emission can become the committed state. Prepare the emission with kind "committed" and check its validity before committing it.`);let t=()=>e.previousState===this.committed.value.state;if(!t())return"conflict";let i=()=>{t()?o():this._context.domainServicesSelectors.getLogger().warn("A held commit was dropped, because the committed state changed since it was prepared.",e)},o=()=>this._onBeforeCommitHooks.some(t=>!1===t(e,i))?(this._context.domainServicesSelectors.getLogger().debug("A prepared commit was held by one of the onBeforeCommit hooks.",e),!1):(this._context.domainServicesSelectors.getLogger().debug("commitPrepared",e),this.stagedUpdates=void 0,this.emit(e),!0);return o()?"committed":"held"};rollback=()=>{void 0!==this.stagedUpdates&&(this.stagedUpdates=void 0,this.emit(this.committed.value))};_resetInteractionState(e){return e.ephemeralRecords.some(e=>{let t;return(t=e.componentInstance.componentType)===r||t===o})?{...e,ephemeralRecords:e.ephemeralRecords.map(e=>e.componentInstance.componentType===r?{...e,state:{hoveredEntityId:null}}:e.componentInstance.componentType===o?{...e,state:{draggedEntityId:null}}:e)}:e}_preserveViewportState(e,t){let i=t.ephemeralRecords.find(m),o=e.ephemeralRecords.filter(e=>!m(e));return{...e,ephemeralRecords:i?[...o,i]:o}}reset(e,t){let i=this.committed.value.state,o=this._preserveViewportState(e,i),r=this._resetInteractionState(o),s=this._validateState(r);if(!s.valid)throw Error("Cannot reset to an invalid state");this.stagedUpdates=void 0,this.emit({kind:"reset",state:r,validity:s,tag:t,transformationLog:void 0})}stageAndCommit(e){if(0!==e.length){this.stagedUpdates=e;try{this.commit()}finally{this.stagedUpdates=void 0}}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as e,jsxs as
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import o from"@monaco-editor/react";import{Box as r,Checkbox as i,FormControlLabel as a,Stack as n,Typography as s}from"@mui/material";import{useState as l}from"react";import{EditorButton as m}from"../common/EditorButton.js";import{jsonEditorOptions as d}from"../common/monaco-config.js";import{useOptionalConfigurator as c,useOptionalDomain as p}from"../hooks/use-optional-runtime.js";import{splitOperations as u}from"./split-operations.js";let h={fontSize:"12px",fontWeight:600,color:"text.secondary"};export const GraphQLPanel=()=>{let f=c()?.graphQLSystem,g=p()?.storeSystem,[x,y]=l("query { root { id type } }"),[b,v]=l(""),[S,k]=l(!1),[j,N]=l(null),[C,w]=l(null),[z,J]=l(!1),O=async()=>{let e=u(x),t=(e=>{if(""===e.trim())return{ok:!0,variables:void 0};try{let t=JSON.parse(e);return"object"!=typeof t||null===t||Array.isArray(t)?{ok:!1,message:"Variables must be a JSON object. Wrap them in {} or clear the field."}:{ok:!0,variables:t}}catch(e){return{ok:!1,message:`Variables are not valid JSON: ${e instanceof Error?e.message:String(e)}. Fix the JSON or clear the field.`}}})(b);if(f){if(w(null),!e.ok)return void N(e.message);if(!t.ok)return void N(t.message);if(S&&!g?.isInitialized)return void N("The configuration is not loaded yet, so there is no state to run against. Run again once the configurator has finished loading.");J(!0);try{let o=e.operations.map(e=>({...e,variables:t.variables})),r=S&&g?await f.prepare(g.stateSlices.committed.value.state,o):void 0,{results:i,committed:a,message:n,sideEffects:s}=r?{results:r.map(({result:e})=>e),committed:!1,message:"Dry run: nothing was committed.",sideEffects:f.readSideEffects(r)}:await f.execute(o),l=i.map((t,o)=>({operationName:e.operations[o]?.operationName??null,...t}));N(JSON.stringify(s.length>0?{results:l,sideEffects:s}:l,null,2)),w(a?"Committed as one undo step.":n??"Nothing was committed.")}finally{J(!1)}}};return t(n,{direction:"column",spacing:1.5,sx:{px:1.5,py:1},children:[e(s,{variant:"subtitle2",sx:h,children:"Query"}),e(r,{component:"div",sx:{height:160,border:"1px solid #dee2e6"},children:e(o,{language:"graphql",value:x,onChange:e=>y(e??""),options:d})}),e(s,{variant:"subtitle2",sx:h,children:"Variables (JSON)"}),e(r,{component:"div",sx:{height:80,border:"1px solid #dee2e6"},children:e(o,{language:"json",value:b,onChange:e=>v(e??""),options:d})}),e(a,{control:e(i,{size:"small",checked:S,onChange:e=>{k(e.target.checked)},sx:{p:.5}}),label:"Dry run",sx:{ml:-.5,mr:0,"& .MuiFormControlLabel-label":{fontSize:"12px",color:"#212529"}}}),e(m,{fullWidth:!0,disabled:!f||z,onClick:()=>void O(),children:f?"Run":"Configurator is not ready"}),null!==C&&e(s,{"data-testid":"graphql-status",sx:{fontSize:"12px",color:"text.secondary"},children:C}),null!==j&&e(r,{component:"pre","data-testid":"graphql-result",sx:{m:0,p:1,fontSize:"12px",backgroundColor:"#f8f9fa",overflow:"auto",whiteSpace:"pre-wrap"},children:j})]})};
|
|
@@ -6,7 +6,8 @@ import type { AssistantSpec } from '#package/application-spec';
|
|
|
6
6
|
* about changes is left out when the schema has no `Mutation` type, the part about adding
|
|
7
7
|
* entities when it has no `addChild` mutation, the part about replacing them when it has no
|
|
8
8
|
* `replaceEntity` mutation, the part about the choices of a field when it has
|
|
9
|
-
* no options edge, and the part about custom changes when the manifest exposes no action. The last
|
|
10
|
-
* `query` and `apply` tools, which every run registers whatever the schema holds
|
|
9
|
+
* no options edge, and the part about custom changes when the manifest exposes no action. The last two sections explain the
|
|
10
|
+
* `query` and `apply` tools, which every run registers whatever the schema holds, and the change
|
|
11
|
+
* record the `AssistantSystem` attaches to every user message.
|
|
11
12
|
*/
|
|
12
13
|
export declare const generateAssistantPrompt: (assistant: NonNullable<AssistantSpec>) => string;
|