@salsita-ai/sdk 0.50.0-develop.ca5894b56c → 0.50.0-develop.cba048b0d7
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/errors/diagnostic-codes.d.ts +7 -1
- package/dist/application-spec/errors/diagnostic-codes.js +1 -1
- package/dist/application-spec/errors/diagnostic-messages.d.ts +14 -1
- package/dist/application-spec/errors/diagnostic-messages.js +1 -1
- package/dist/application-spec/generate-application/implementations/phx-model.d.ts +1 -1
- package/dist/application-spec/generate-application/runtime/admin-runtime/admin-model-runtime.d.ts +1 -2
- package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-model-runtime.d.ts +1 -2
- package/dist/application-spec/generate-application/runtime/factory-data/factory-data-runtime.d.ts +1 -2
- package/dist/application-spec/generate-application/runtime/factory-data/static-violations.d.ts +1 -2
- package/dist/application-spec/generate-application/runtime/sections/actions-runtime.d.ts +1 -2
- package/dist/application-spec/generate-application/runtime/sections/build-sdk-optic.d.ts +1 -1
- package/dist/application-spec/generate-application/runtime/sections/build-sdk-optic.js +1 -1
- package/dist/application-spec/generate-application/runtime/sections/build-user-bound-optic.d.ts +1 -1
- package/dist/application-spec/generate-application/runtime/sections/component-optic.d.ts +1 -2
- package/dist/application-spec/generate-application/runtime/sections/expression-runtime.d.ts +1 -2
- package/dist/application-spec/generate-application/runtime/sections/generate-memo-eval-plan-runtime.d.ts +1 -2
- package/dist/application-spec/generate-application/runtime/sections/reflection-constants-runtime.d.ts +1 -2
- package/dist/application-spec/generate-application/runtime-spec/runtime-spec.d.ts +96 -31
- package/dist/application-spec/generate-application/runtime-spec/spec-code-id.d.ts +1 -1
- package/dist/application-spec/parse-application-files/merge/merged-assistant.d.ts +13 -4
- package/dist/application-spec/parse-application-files/merge/merged-assistant.js +1 -1
- package/dist/application-spec/parse-application-files/merge/merged-infra.d.ts +4 -11
- package/dist/application-spec/parse-application-files/merge/merged-transformers.d.ts +2 -4
- package/dist/application-spec/parse-application-files/raw-spec/raw-acl.d.ts +2 -2
- package/dist/application-spec/parse-application-files/raw-spec/raw-acl.js +1 -1
- package/dist/application-spec/parse-application-files/raw-spec/raw-admin-pages.d.ts +3 -24
- package/dist/application-spec/parse-application-files/raw-spec/raw-assistant.d.ts +25 -20
- package/dist/application-spec/parse-application-files/raw-spec/raw-assistant.js +1 -1
- package/dist/application-spec/parse-application-files/raw-spec/raw-resources.d.ts +19 -64
- package/dist/application-spec/parse-application-files/spec/application/admin-spec/admin-pages.d.ts +3 -20
- package/dist/application-spec/parse-application-files/spec/application/admin-spec/states.d.ts +3 -5
- package/dist/application-spec/parse-application-files/spec/application/configurator-spec/states.d.ts +3 -8
- package/dist/application-spec/parse-application-files/spec/components/bindings/read-binding.d.ts +3 -13
- package/dist/application-spec/parse-application-files/spec/components/bindings/write-binding.d.ts +4 -32
- package/dist/application-spec/parse-application-files/spec/components/component-filter.d.ts +4 -10
- package/dist/application-spec/parse-application-files/spec/components/components.d.ts +3 -4
- package/dist/application-spec/parse-application-files/spec/components/index.d.ts +1 -2
- package/dist/application-spec/parse-application-files/spec/components/index.js +1 -1
- package/dist/application-spec/parse-application-files/spec/components/sdk-component-entry.d.ts +1 -1
- package/dist/application-spec/parse-application-files/spec/components/user-component-entry.d.ts +2 -3
- package/dist/application-spec/parse-application-files/spec/components/user-component-entry.js +1 -1
- package/dist/application-spec/parse-application-files/spec/components/user-components.d.ts +2 -3
- package/dist/application-spec/parse-application-files/spec/expressions/expression-read-types.d.ts +2 -2
- package/dist/application-spec/parse-application-files/spec/expressions/expressions.d.ts +7 -29
- package/dist/application-spec/parse-application-files/spec/expressions/index.d.ts +0 -1
- package/dist/application-spec/parse-application-files/spec/expressions/memo-eval-plan.d.ts +4 -71
- package/dist/application-spec/parse-application-files/spec/expressions/memo-eval-plan.js +1 -1
- package/dist/application-spec/parse-application-files/spec/expressions/user-expressions.d.ts +2 -2
- package/dist/application-spec/parse-application-files/spec/invariants/invariant.d.ts +5 -21
- package/dist/application-spec/parse-application-files/spec/invariants/invariants.d.ts +4 -14
- package/dist/application-spec/parse-application-files/spec/sections/actions.d.ts +6 -23
- package/dist/application-spec/parse-application-files/spec/sections/app-metadata.d.ts +3 -18
- package/dist/application-spec/parse-application-files/spec/sections/application-version.d.ts +3 -7
- package/dist/application-spec/parse-application-files/spec/sections/assistant/assistant-schema.js +1 -1
- package/dist/application-spec/parse-application-files/spec/sections/assistant/assistant.js +1 -1
- package/dist/application-spec/parse-application-files/spec/sections/data-spec/chunks.d.ts +6 -23
- package/dist/application-spec/parse-application-files/spec/sections/data-spec/custom-data-spec.d.ts +1 -16
- package/dist/application-spec/parse-application-files/spec/sections/data-spec/data-entry-key.d.ts +3 -9
- package/dist/application-spec/parse-application-files/spec/sections/data-spec/data-spec.d.ts +1 -10
- package/dist/application-spec/parse-application-files/spec/sections/data-spec/swatch-data-spec.d.ts +1 -14
- package/dist/application-spec/parse-application-files/spec/sections/state-value.d.ts +3 -7
- package/dist/application-spec/parse-application-files/spec/sections/theme.d.ts +3 -10
- package/dist/application-spec/parse-application-files/spec/sections/transformers.d.ts +4 -11
- package/dist/application-spec/parse-application-files/spec/sections/ui.d.ts +3 -12
- package/dist/configurator/ConfiguratorApp.js +1 -1
- package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.js +1 -1
- package/dist/configurator/application-runtime/extensions/systems/assistant-system/graphql-tools.d.ts +19 -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 +70 -56
- 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 +15 -0
- package/dist/configurator/application-runtime/extensions/systems/graphql-system/graphql-system.js +1 -1
- package/dist/configurator/application-runtime/extensions/systems/graphql-system/violations.d.ts +40 -0
- package/dist/configurator/application-runtime/extensions/systems/graphql-system/violations.js +1 -0
- package/dist/configurator/common/configurator-interface.d.ts +2 -2
- package/dist/configurator/common/configurator-interface.js +1 -1
- package/dist/configurator/configurator-context/configurator-hooks/layout-hooks.js +1 -1
- package/dist/configurator/configurator-context/index.d.ts +0 -1
- package/dist/configurator/configurator-context/index.js +1 -1
- package/dist/configurator/pages/NewConfiguratorPage.js +1 -1
- package/dist/configurator/ui/assistant/AssistantChips.js +1 -1
- package/dist/configurator/ui/assistant/tool-chip.d.ts +19 -9
- package/dist/configurator/ui/assistant/tool-chip.js +1 -1
- package/dist/configurator/ui/configurator-layout/universal/DesktopPreview.js +1 -1
- package/dist/configurator/ui/configurator-layout/universal/MobilePreview.js +1 -1
- package/dist/configurator/ui/legacy/layout/common/CommonTopNavigation.js +1 -1
- package/dist/configurator/ui/legacy/layout/simple/SimpleTopNavigation.js +1 -1
- package/dist/configurator/ui/legacy/layout/steps/StepsNavigation.js +1 -1
- package/dist/configurator/ui/legacy/layout/steps/StepsOwnerLayout.js +1 -1
- package/dist/configurator/ui/phoenix-layout-elements/header/common/back-button/use-go-back-action.js +1 -1
- package/dist/configurator/ui/phoenix-layout-elements/header/common/step-navigation/StepsNavigation.js +1 -1
- package/dist/configurator/ui/phoenix-layout-elements/sidebar-footer/basic/use-basic-sidebar-footer.js +1 -1
- package/dist/configurator/ui/preset-layout/CategoryPresetUi.js +1 -1
- package/dist/configurator/ui/save-message-snackbars/SaveMessageSnackbars.js +1 -1
- package/dist/docs/drag-and-drop/room-planner.mdx +1 -1
- package/dist/docs/index.json +1 -1
- package/dist/docs/phoenix/configurator-interface.mdx +1 -1
- package/dist/docs/phoenix/layout-slots.mdx +21 -0
- package/dist/docs/phoenix/phoenix-cli.mdx +1 -0
- package/dist/domain/application/application-config.d.ts +6 -24
- package/dist/domain/application/assistant/assistant-manifest.d.ts +13 -3
- package/dist/domain/application/assistant/assistant-manifest.js +1 -1
- package/dist/domain/application/assistant/assistant-resolved-manifest.d.ts +5 -9
- package/dist/domain/application/assistant/assistant-resolved-manifest.js +1 -1
- package/dist/domain/application/assistant/build-assistant-lenses.js +1 -1
- package/dist/domain/application/assistant/build-assistant-manifest.js +1 -1
- package/dist/domain/application/assistant/generate-assistant-prompt.js +1 -1
- package/dist/domain/application/assistant/index.d.ts +3 -3
- package/dist/domain/application/assistant/index.js +1 -1
- package/dist/domain/application/assistant/session-setup/apply-assistant-setup.js +1 -1
- package/dist/domain/application/assistant/session-setup/assistant-setup-manifest.d.ts +2 -4
- package/dist/domain/application/assistant/session-setup/assistant-setup-manifest.js +1 -1
- package/dist/domain/application/assistant-mutations.js +1 -1
- package/dist/domain/available-system-components/available-system-components.d.ts +11 -0
- package/dist/domain/available-system-components/available-system-components.js +1 -0
- package/dist/domain/available-system-components/index.d.ts +1 -0
- package/dist/domain/available-system-components/index.js +1 -0
- package/dist/domain/{domain-builder.d.ts → domain-builder/domain-builder.d.ts} +2 -2
- package/dist/domain/domain-builder/domain-builder.js +1 -0
- package/dist/domain/domain-builder/index.d.ts +1 -0
- package/dist/domain/domain-builder/index.js +1 -0
- package/dist/domain/index.d.ts +2 -2
- package/dist/domain/index.js +1 -1
- package/dist/domain/spec/application/admin-pages-section.d.ts +29 -0
- package/dist/domain/spec/application/admin-pages.d.ts +26 -0
- package/dist/domain/spec/application/admin-states.d.ts +5 -0
- package/dist/domain/spec/application/admin-states.js +1 -0
- package/dist/domain/spec/application/configurator-states.d.ts +8 -0
- package/dist/domain/spec/application/configurator-states.js +1 -0
- package/dist/domain/spec/application/index.d.ts +4 -0
- package/dist/domain/spec/components/bindings/index.d.ts +2 -0
- package/dist/domain/spec/components/bindings/index.js +1 -0
- package/dist/domain/spec/components/bindings/read-binding.d.ts +13 -0
- package/dist/domain/spec/components/bindings/read-binding.js +1 -0
- package/dist/domain/spec/components/bindings/write-binding.d.ts +32 -0
- package/dist/domain/spec/components/bindings/write-binding.js +1 -0
- package/dist/{application-spec/parse-application-files → domain}/spec/components/component-entry.d.ts +3 -3
- package/dist/domain/spec/components/component-entry.js +1 -0
- package/dist/domain/spec/components/component-filters.d.ts +10 -0
- package/dist/domain/spec/components/component-filters.js +1 -0
- package/dist/domain/spec/components/components.d.ts +4 -0
- package/dist/domain/spec/components/components.js +1 -0
- package/dist/domain/spec/components/index.d.ts +4 -0
- package/dist/domain/spec/{enhanced-json-value.d.ts → enhanced-json/enhanced-json-value.d.ts} +1 -1
- package/dist/domain/spec/enhanced-json/index.d.ts +1 -0
- package/dist/domain/spec/enhanced-json/index.js +1 -0
- package/dist/{application-spec/parse-application-files → domain}/spec/expressions/expression.d.ts +9 -3
- package/dist/domain/spec/expressions/expression.js +1 -0
- package/dist/domain/spec/expressions/expressions.d.ts +27 -0
- package/dist/domain/spec/expressions/expressions.js +1 -0
- package/dist/domain/spec/expressions/index.d.ts +3 -0
- package/dist/domain/spec/expressions/memo-eval-plan.d.ts +70 -0
- package/dist/domain/spec/expressions/memo-eval-plan.js +1 -0
- package/dist/domain/spec/index.d.ts +3 -1
- package/dist/domain/spec/index.js +1 -1
- package/dist/domain/spec/invariants/index.d.ts +2 -0
- package/dist/domain/spec/invariants/index.js +1 -0
- package/dist/domain/spec/invariants/invariant.d.ts +24 -0
- package/dist/domain/spec/invariants/invariant.js +1 -0
- package/dist/domain/spec/invariants/invariants.d.ts +14 -0
- package/dist/domain/spec/invariants/invariants.js +1 -0
- package/dist/domain/spec/markers/index.d.ts +1 -0
- package/dist/domain/spec/markers/index.js +1 -1
- package/dist/domain/spec/model/defaults.d.ts +1 -1
- package/dist/domain/spec/sections/actions.d.ts +23 -0
- package/dist/domain/spec/sections/actions.js +1 -0
- package/dist/domain/spec/sections/app-metadata.d.ts +18 -0
- package/dist/domain/spec/sections/app-metadata.js +1 -0
- package/dist/domain/spec/sections/application-version.d.ts +7 -0
- package/dist/domain/spec/sections/application-version.js +1 -0
- package/dist/domain/spec/sections/data-spec/chunks.d.ts +23 -0
- package/dist/domain/spec/sections/data-spec/chunks.js +1 -0
- package/dist/domain/spec/sections/data-spec/custom-data-spec-entry.d.ts +16 -0
- package/dist/domain/spec/sections/data-spec/custom-data-spec-entry.js +1 -0
- package/dist/domain/spec/sections/data-spec/data-entry-key.d.ts +9 -0
- package/dist/domain/spec/sections/data-spec/data-entry-key.js +1 -0
- package/dist/domain/spec/sections/data-spec/index.d.ts +5 -0
- package/dist/domain/spec/sections/data-spec/index.js +1 -0
- package/dist/domain/spec/sections/data-spec/parsed-data-spec-entries.d.ts +10 -0
- package/dist/domain/spec/sections/data-spec/parsed-data-spec-entries.js +1 -0
- package/dist/domain/spec/sections/data-spec/swatch-data-spec-entry.d.ts +14 -0
- package/dist/domain/spec/sections/data-spec/swatch-data-spec-entry.js +1 -0
- package/dist/domain/spec/sections/index.d.ts +9 -0
- package/dist/domain/spec/sections/index.js +1 -0
- package/dist/domain/spec/sections/infra/acl.d.ts +12 -0
- package/dist/domain/spec/sections/infra/acl.js +1 -0
- package/dist/domain/spec/sections/infra/index.d.ts +3 -0
- package/dist/domain/spec/sections/infra/index.js +1 -0
- package/dist/domain/spec/sections/infra/resource-entry.d.ts +46 -0
- package/dist/domain/spec/sections/infra/resource-entry.js +1 -0
- package/dist/domain/spec/sections/infra/resources-config.d.ts +10 -0
- package/dist/domain/spec/sections/infra/resources-config.js +1 -0
- package/dist/domain/spec/sections/state-value.d.ts +7 -0
- package/dist/domain/spec/sections/state-value.js +1 -0
- package/dist/domain/spec/sections/theme.d.ts +10 -0
- package/dist/domain/spec/sections/theme.js +1 -0
- package/dist/domain/spec/sections/transformers.d.ts +15 -0
- package/dist/domain/spec/sections/transformers.js +1 -0
- package/dist/domain/spec/sections/ui.d.ts +12 -0
- package/dist/domain/spec/sections/ui.js +1 -0
- package/dist/domain/system-definitions.js +1 -1
- package/dist/domain/utils/index.d.ts +2 -0
- package/dist/domain/utils/index.js +1 -0
- package/dist/editor/graphql/GraphQLPanel.js +1 -1
- package/dist/phoenix/services/application-spec-project-watcher.js +1 -1
- package/dist/react-sdk/domain-application-context/ConfigurationPersistSystemFailureHandler.js +1 -1
- package/dist/react-sdk/index.d.ts +2 -0
- package/dist/react-sdk/index.js +1 -1
- package/dist/react-sdk/lifecycle-providers/ConfiguratorDataProvider.d.ts +8 -0
- package/dist/react-sdk/lifecycle-providers/ConfiguratorDataProvider.js +1 -0
- package/dist/react-sdk/lifecycle-providers/index.d.ts +1 -0
- package/dist/react-sdk/lifecycle-providers/index.js +1 -1
- package/dist/react-sdk/notifications/index.d.ts +1 -0
- package/dist/react-sdk/notifications/index.js +1 -0
- package/dist/react-sdk/notifications/snackbar-action-button.d.ts +30 -0
- package/dist/react-sdk/notifications/snackbar-action-button.js +1 -0
- package/dist/react-sdk/preset-selection/PresetSelectionProvider.js +1 -0
- package/dist/react-sdk/preset-selection/index.d.ts +1 -0
- package/dist/react-sdk/preset-selection/index.js +1 -0
- package/dist/ui-sdk/components/snackbar/Snackbar.d.ts +24 -3
- package/dist/ui-sdk/components/snackbar/Snackbar.js +1 -1
- package/dist/watch/glob-matcher.d.ts +4 -4
- package/dist/watch/glob-matcher.js +1 -1
- package/dist/watch/watch.d.ts +4 -4
- package/dist/watch/watch.js +1 -1
- package/package.json +3 -3
- package/dist/configurator/configurator-context/ConfiguratorDataProvider.d.ts +0 -2
- package/dist/configurator/configurator-context/ConfiguratorDataProvider.js +0 -1
- package/dist/configurator/configurator-context/PresetSelectionProvider.js +0 -1
- package/dist/domain/available-system-components.d.ts +0 -11
- package/dist/domain/available-system-components.js +0 -1
- package/dist/domain/domain-builder.js +0 -1
- /package/dist/{application-spec/parse-application-files/spec/components/component-entry.js → domain/spec/application/admin-pages-section.js} +0 -0
- /package/dist/{application-spec/parse-application-files/spec/expressions/expression.js → domain/spec/application/admin-pages.js} +0 -0
- /package/dist/domain/spec/{enhanced-json-value.js → enhanced-json/enhanced-json-value.js} +0 -0
- /package/dist/{application-spec/parse-application-files/spec/components → domain/spec/markers}/component-prop-target.d.ts +0 -0
- /package/dist/{application-spec/parse-application-files/spec/components → domain/spec/markers}/component-prop-target.js +0 -0
- /package/dist/{configurator/configurator-context → react-sdk/preset-selection}/PresetSelectionProvider.d.ts +0 -0
package/dist/application-spec/parse-application-files/spec/sections/assistant/assistant-schema.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isArray as e}from"@salsita-ai/common/utils";import{ASSISTANT_HINTS as t,AssistantFieldClashError as r,buildAssistantManifest as i,describeAssistantValues as n,mergeAssistantFields as s,resolveAssistantField as o}from"#package/domain";import{DiagnosticCode as a,diagnosticMessages as l}from"../../../../errors/index.js";import{createSchemaRefResolver as S,isNullableSchema as p,phxDefinitionRefName as N}from"../../common/index.js";import{resolveAssistantFieldType as T}from"./assistant-field-type.js";import{resolveFormElements as c}from"./assistant-form-elements.js";let d="AnyDomainEntity",E="RecipeGroup",f="Recipe",A="DryRun",_="FieldOption",m="agentScreenshot",u=/^(?!(true|false|null)$)[_A-Za-z][_0-9A-Za-z]*$/,O={section:"childRecipes",component:"childEntityRecipes",mutation:"addChild"},I={section:"replaceRecipes",component:"replaceEntityRecipes",mutation:"replaceEntity"},y=new Set(["id","type","meta"]),h=new Set(["Query","Mutation","Navigation",E,f,A,"DryRunError",_,"Screenshot","JSON","String","Int","Float","Boolean","ID"]),v=new Set([E,f,_,A]),b=new Set(["id","type"]),g="A string, a message descriptor or a multilingual object; passed without translation.",R=(e,t)=>Object.entries(e).find(([e])=>e===t)?.[1],M=(e,{property:t,writableKey:r},i,{resolveRef:s,exposed:o,sources:S},p)=>{let N=Object.entries(R(S,e)??{}),c=o.get(e)?.find(({source:e})=>e===t)?.name??N.find(([,{source:e}])=>e===t)?.[0],d=void 0===c?N.find(([e])=>e===t)?.[1]:void 0;if(d)return void p.at(r,t).error(a.ASSISTANT_FIELD_NAME_CONFLICT,l.ASSISTANT_FIELD_NAME_CONFLICT(e,t,[d.source,t],`${r}.${t}`));let{type:E,enumValues:f,localized:A,description:_}=T(i,s),m={...E,nonNull:!1},u=c??t,O=void 0===c?n(_,f):void 0;return A?{name:u,property:t,type:{kind:"scalar",name:"JSON",nonNull:!1},description:O?`${O} ${g}`:g}:{name:u,property:t,type:m,...void 0===O?{}:{description:O}}},C=(e,t,{model:r,components:i})=>{let n=new Set([e,...[...r.aliases].filter(([,t])=>t.includes(e)).map(([e])=>e)]);return i.filter(({componentName:e,typeOrAlias:r})=>e===t&&n.has(r)).map(({instanceName:e})=>String(e))},j=(...e)=>t.filter(t=>e.some(e=>e?.includes(t))),w=(e,t,r,i)=>{let{model:n}=r,s=new Map,o=new Map;for(let[S,{groups:p,hints:N}]of Object.entries(e)){let e=n.entityTypes.find(e=>e===S),T=e?[e]:[...n.aliases].find(([e])=>e===S)?.[1];if(!T){i.at(S).error(a.ASSISTANT_UNKNOWN_TYPE,l.ASSISTANT_UNKNOWN_TYPE(t.section,S));continue}for(let[e,n]of(T.forEach(e=>o.set(e,j(o.get(e),N))),Object.entries(p))){let o=i.at(S,"groups",e),p=`${S}.groups.${e}`,N={groupId:n?.as??e,instanceName:e,...n?.description===void 0?{}:{description:n.description},dryRuns:n?.allowDryRuns??!0};for(let i of T){let n=C(i,t.component,r),T=s.get(i)??[],c=T.find(e=>e.group.groupId===N.groupId);n.includes(e)?c?o.error(a.ASSISTANT_DUPLICATE_RECIPE_GROUP,l.ASSISTANT_DUPLICATE_RECIPE_GROUP(t,i,N.groupId,[c.entry,p])):s.set(i,[...T,{group:N,entry:p,entryCtx:o}]):o.error(a.ASSISTANT_UNKNOWN_RECIPE_GROUP,l.ASSISTANT_UNKNOWN_RECIPE_GROUP(t,S,e,i,n))}}}let S=n.entityTypes.flatMap(e=>{let t=s.get(e);return t?[{entityType:e,groups:t}]:[]});return{groups:Object.fromEntries(S.map(({entityType:e,groups:t})=>[e,t.map(({group:e})=>e)])),hints:o,metaEntries:new Map(S.flatMap(({entityType:e,groups:[t]})=>t?[[e,t.entryCtx]]:[]))}},P=(e,t,{model:r,components:i})=>{let n=new Set([e,...[...r.aliases].filter(([,t])=>t.includes(e)).map(([e])=>e)]),s=i.find(e=>e.componentName===m&&String(e.instanceName)===t&&n.has(e.typeOrAlias));if(s?.implementation.kind!=="userBound"||"composite"!==s.implementation.implementation.kind)return;let o=s.implementation.implementation.resolvedProps.exportState;return"string"==typeof o?o:void 0},D=e=>`${e}Meta`,L=e=>`${e}ScreenshotView`,U=e=>`${e.charAt(0).toUpperCase()+e.slice(1)}Result`,W=e=>{let t=(({anyOf:e,oneOf:t})=>[...e??[],...t??[]].filter(e=>"null"!==e.type))(e);return e.$ref||1!==t.length?e:t[0]},$=(e,t)=>{let{type:r,enumValues:i,localized:s,description:o}=T(e,t),a={...r,nonNull:!1},l=s?`${n(o,i)??""} ${g}`.trim():n(o,i);return{type:{...s?{kind:"scalar",name:"JSON",nonNull:!1}:a,nonNull:r.nonNull},...void 0===l?{}:{description:l}}},F=(t,r)=>{let i=(t=>{let r=W(t),i=r?.type==="array"&&r.items&&!e(r.items)?W(r.items):void 0,n=i??r;if(n?.$ref!==void 0&&"$DomainEntity"===N(n.$ref))return{target:n.references??d,list:void 0!==i}})(t);if(i)return{kind:"edge",...i,nullable:p(t,r),...void 0===t.description?{}:{description:t.description}};let{type:s,enumValues:o,localized:a,description:l}=T(t,r),S=n(l,o);return a?{kind:"value",type:{kind:"scalar",name:"JSON",nonNull:s.nonNull},description:`${l??""} ${g}`.trim()}:{kind:"value",type:s,...void 0===S?{}:{description:S}}},V=(e,t)=>{let{type:r,enumValues:i,localized:n,description:s}=T(e,t);return{type:{kind:"value",type:r},localized:!0===n,description:s,enumValues:i}},K=(e,t,r,i,s)=>{let o=t.startsWith("$")?((e,t,r,i)=>{let n=((e,t,{expressions:r,entityTypes:i})=>{let n=i.find(t=>t===e);for(let i of void 0===n?[e]:r.entityExpressions.get(n)?.shapeGroups??[]){let e=[...r.expressions.get(i)?.values()??[]].find(e=>e.name===t);if(e?.declaredSchema)return{implementation:e.implementation,declaredSchema:e.declaredSchema}}})(e.name,t,r);if(!n)return void i.error(a.ASSISTANT_UNKNOWN_FIELD,l.ASSISTANT_UNKNOWN_FIELD("entities",e.name,t));let{implementation:s}=n;if("violations"===s.kind)return void i.error(a.ASSISTANT_UNSUPPORTED_EXPRESSION,l.ASSISTANT_UNSUPPORTED_EXPRESSION(e.name,t));if("relation"===s.kind){let[{target:e,cardinality:t}]=s.params;return{type:{kind:"edge",target:e,cardinality:t},localized:!1,description:void 0}}return V(n.declaredSchema,r.resolveRef)})(e,t,i,s):((e,t,{resolveRef:r},i)=>{let n=Object.entries(e.shape.properties).find(([e])=>e===t)?.[1];return n?V(n,r):void i.error(a.ASSISTANT_UNKNOWN_FIELD,l.ASSISTANT_UNKNOWN_FIELD("entities",e.name,t))})(e,t,i,s);if(!o)return;let S=r?.as??(t.startsWith("$")?`_${t.slice(1)}`:t);return y.has(S)?void s.error(a.ASSISTANT_RESERVED_FIELD_NAME,l.ASSISTANT_RESERVED_FIELD_NAME(e.name,t,S)):{name:S,source:t,type:o.type,localized:o.localized,description:n(r?.description??o.description,o.enumValues),describedByManifest:r?.description!==void 0,enumValues:o.enumValues,valueDescription:r?.description??o.description,...r?.lenses?.length?{lenses:[...new Set(r.lenses)]}:{}}},k=(e,t,r,i,n)=>s(t,r,i,(t,r,i)=>{n.error(a.ASSISTANT_FIELD_NAME_CONFLICT,l.ASSISTANT_FIELD_NAME_CONFLICT(e,t,[r,i]))});export const resolveAssistantManifest=(e,{model:t,states:r,phxDefinitions:i,expressions:n,components:s,actions:p},N)=>{let E=N.errors.length,f=N.at("entities"),A=S(t.commonTypes,i);for(let e of t.resolvedShapes.keys())h.has(e)&&N.error(a.ASSISTANT_RESERVED_TYPE_NAME,l.ASSISTANT_RESERVED_TYPE_NAME(e,[...h]));let _=((e,t,r)=>{let i=new Map;for(let n of e){let e=[];for(let[i,s]of Object.entries(n.entries)){let o=K(n,i,s,t,r.at(n.name,i));o&&e.push(o)}i.set(n.name,e)}return i})(((e,t,r)=>{let i=[];for(let[r,n]of t.resolvedShapes){let t=e[r];t&&i.push({name:r,shape:n,entries:t})}let n=new Set(t.resolvedShapes.keys());for(let t of Object.keys(e))n.has(t)||r.at(t).error(a.ASSISTANT_UNKNOWN_TYPE,l.ASSISTANT_UNKNOWN_TYPE("entities",t));return i})(e.entities??{},t,f),{resolveRef:A,expressions:n,entityTypes:t.entityTypes},f),y=k(d,[],_.get(d)??[],()=>void 0,N),W=new Map([[d,y]]);for(let e of t.aliases.keys())e!==d&&W.set(e,k(e,[y],_.get(e)??[],()=>void 0,N));for(let e of t.entityTypes){let r=[d,...[...t.aliases].filter(([t,r])=>t!==d&&r.includes(e)).map(([e])=>e)],i=[...t.resolvedShapes].find(([t])=>t===e)?.[1];W.set(e,k(e,r.map(e=>W.get(e)??[]),_.get(e)??[],e=>{let t=Object.entries(i?.properties??{}).find(([t])=>t===e)?.[1];return t&&T(t,A).enumValues},N))}let V=Object.fromEntries(t.entityTypes.map(e=>[e,Object.fromEntries((W.get(e)??[]).map(({name:e,source:t,localized:r})=>[e,r?{source:t,localized:!0}:{source:t}]))])),Y=w(e.childRecipes??{},O,{model:t,components:s},N.at("childRecipes")),x=w(e.replaceRecipes??{},I,{model:t,components:s},N.at("replaceRecipes")),H=((e,t,r)=>{let i=new Set;for(let n of Object.keys(e)){let e=t.entityTypes.find(e=>e===n),s=e?[e]:[...t.aliases].find(([e])=>e===n)?.[1];s?s.forEach(e=>i.add(e)):r.at(n).error(a.ASSISTANT_UNKNOWN_TYPE,l.ASSISTANT_UNKNOWN_TYPE("deletable",n))}return t.entityTypes.filter(e=>i.has(e))})(e.deletable??{},t,N.at("deletable")),z=((e,t,r)=>{let{model:i}=t,n=((e,t,r)=>{let i=new Map;for(let[n,s]of Object.entries(e)){let e=t.entityTypes.find(e=>e===n),o=e?[e]:[...t.aliases].find(([e])=>e===n)?.[1],S=[...t.resolvedShapes].find(([e])=>e===n)?.[1];if(!o||!S){r.at(n).error(a.ASSISTANT_UNKNOWN_TYPE,l.ASSISTANT_UNKNOWN_TYPE("writable",n));continue}for(let e of Object.keys(s)){let t=r.at(n,e);e.startsWith("$")||b.has(e)?t.error(a.ASSISTANT_NOT_WRITABLE,l.ASSISTANT_NOT_WRITABLE(n,e)):R(S.properties,e)?o.forEach(t=>{let r=i.get(t)??new Map;i.set(t,r.has(e)?r:r.set(e,n))}):t.error(a.ASSISTANT_UNKNOWN_FIELD,l.ASSISTANT_UNKNOWN_FIELD("writable",n,e))}}return i})(e,i,r);return i.entityTypes.flatMap(e=>{let s=[...i.resolvedShapes].find(([t])=>t===e)?.[1],o=[...n.get(e)??[]].flatMap(([i,n])=>{let o=s&&R(s.properties,i);return(o&&M(e,{property:i,writableKey:n},o,t,r))??[]});return o.length>0?[{entityType:e,fields:o}]:[]})})(e.writable??{},{model:t,resolveRef:A,exposed:_,sources:V},N.at("writable")),G=((e,t,r,i)=>{let{model:n}=r,s=new Map;for(let[o,S]of Object.entries(e)){let e=n.entityTypes.find(e=>e===o),p=e?[e]:[...n.aliases].find(([e])=>e===o)?.[1]??[];for(let[e,n]of Object.entries(S)){let S=n?.options;if(!S)continue;let N=i.at(o,e,"options"),T=`${o}.${e}`;for(let i of p){let n=t.find(e=>e.entityType===i)?.fields.find(t=>t.property===e);if(!n)continue;let o=S.as??`${n.name}Options`,p=C(i,S.componentType,r),c=s.get(i)??[],d=c.find(e=>e.options.edgeName===o||e.options.field===n.name);if(p.includes(S.instanceName))if(o===O.section||o===I.section||"screenshot"===o)N.error(a.ASSISTANT_RESERVED_OPTIONS_EDGE_NAME,l.ASSISTANT_RESERVED_OPTIONS_EDGE_NAME(T,o,n.name));else if(d)N.error(a.ASSISTANT_DUPLICATE_OPTIONS_EDGE,l.ASSISTANT_DUPLICATE_OPTIONS_EDGE(i,d.options.edgeName===o?{edgeName:o}:{field:n.name},[d.entry,T]));else{let e={field:n.name,edgeName:o,componentType:S.componentType,instanceName:S.instanceName,validate:S.validate??!0,dryRuns:S.allowDryRuns??!0};s.set(i,[...c,{options:e,hints:j(S.hints),entry:T,entryCtx:N}])}else N.error(a.ASSISTANT_UNKNOWN_OPTIONS_COMPONENT,l.ASSISTANT_UNKNOWN_OPTIONS_COMPONENT(T,S,i,p))}}}return s})(e.writable??{},z,{model:t,components:s},N.at("writable")),B=((e,t,r)=>{let{model:i,states:n}=t,s=new Map;for(let[o,S]of Object.entries(e)){let e=i.entityTypes.find(e=>e===o),p=e?[e]:[...i.aliases].find(([e])=>e===o)?.[1];if(!p){r.at(o).error(a.ASSISTANT_UNKNOWN_TYPE,l.ASSISTANT_UNKNOWN_TYPE("screenshots",o));continue}for(let[e,{description:i,as:N}]of Object.entries(S)){let S=r.at(o,e),T=`${o}.${e}`,c={view:N??e,instanceName:e,description:i};if(!u.test(c.view)){S.error(a.ASSISTANT_INVALID_SCREENSHOT_VIEW_NAME,l.ASSISTANT_INVALID_SCREENSHOT_VIEW_NAME(o,e,c.view));continue}for(let r of p){let i=C(r,m,t),p=P(r,e,t),N=s.get(r)??[],d=N.find(e=>e.view.view===c.view);i.includes(e)?void 0===p||n.exportStates.includes(p)?d?S.error(a.ASSISTANT_DUPLICATE_SCREENSHOT_VIEW,l.ASSISTANT_DUPLICATE_SCREENSHOT_VIEW(r,c.view,[d.entry,T])):s.set(r,[...N,{view:c,entry:T,entryCtx:S}]):S.error(a.ASSISTANT_UNKNOWN_SCREENSHOT_EXPORT_STATE,l.ASSISTANT_UNKNOWN_SCREENSHOT_EXPORT_STATE(o,e,p,n.exportStates)):S.error(a.ASSISTANT_UNKNOWN_SCREENSHOT_VIEW,l.ASSISTANT_UNKNOWN_SCREENSHOT_VIEW(o,e,r,i))}}}let o=i.entityTypes.flatMap(e=>{let t=s.get(e);return t?[{entityType:e,views:t}]:[]});return{views:new Map(o.map(({entityType:e,views:t})=>[e,t.map(({view:e})=>e)])),metaEntries:new Map(o.flatMap(({entityType:e,views:[t]})=>t?[[e,t.entryCtx]]:[]))}})(e.screenshots??{},{model:t,components:s,states:r},N.at("screenshots"));var J=[Y.metaEntries,x.metaEntries,new Map([...G].flatMap(([e,[t]])=>t?[[e,t.entryCtx]]:[])),B.metaEntries];for(let e of t.entityTypes){let r=J.flatMap(t=>t.get(e)??[])[0],i=D(e);r&&[...t.resolvedShapes.keys()].some(e=>e===i)&&r.error(a.ASSISTANT_META_TYPE_NAME_CONFLICT,l.ASSISTANT_META_TYPE_NAME_CONFLICT(e,i))}for(let[e,r]of B.metaEntries){let i=L(e);[...t.resolvedShapes.keys()].some(e=>e===i)&&r.error(a.ASSISTANT_SCREENSHOT_VIEW_TYPE_NAME_CONFLICT,l.ASSISTANT_SCREENSHOT_VIEW_TYPE_NAME_CONFLICT(e,i))}let X=t.entityTypes.filter(e=>(Y.groups[e]?.length??0)>0||(x.groups[e]?.length??0)>0||(G.get(e)?.length??0)>0||B.views.has(e)).flatMap(e=>[D(e),...B.views.has(e)?[L(e)]:[]]),Z=((e,{actions:t,resolveRef:r,builtInMutations:i,typeNames:n},s)=>{let o=[],S=[...t.values()].map(e=>String(e.name));for(let[p,N]of Object.entries(e)){let e=s.at(p),T=[...t.values()].find(e=>e.name===p);if(!T){e.error(a.ASSISTANT_UNKNOWN_ACTION,l.ASSISTANT_UNKNOWN_ACTION(p,S));continue}let c=N?.as??p,d=o.find(e=>e.fieldName===c),E=U(c);if(i.has(c)||d){e.error(a.ASSISTANT_MUTATION_NAME_CONFLICT,l.ASSISTANT_MUTATION_NAME_CONFLICT(p,c,d?`"assistant.actions.${d.actionName}" already exposes`:"the built-in mutation of that name already takes"));continue}if(n.has(E)||o.some(e=>U(e.fieldName)===E)){e.error(a.ASSISTANT_ACTION_RESULT_TYPE_CONFLICT,l.ASSISTANT_ACTION_RESULT_TYPE_CONFLICT(p,c,E));continue}let f=N?.description??T.description;o.push({fieldName:c,actionName:p,...void 0===f?{}:{description:f},args:Object.fromEntries(Object.entries(T.params).map(([e,{schema:t}])=>[e,$(t,r)])),result:Object.fromEntries(Object.entries(T.result).map(([e,t])=>[e,F(t,r)]))})}return o})(e.actions??{},{actions:p,resolveRef:A,builtInMutations:new Set(["deleteEntity",O.mutation,I.mutation,...z.map(({entityType:e})=>`modify${e}`)]),typeNames:new Set([...h,...t.resolvedShapes.keys(),...X])},N.at("actions")),Q=((e,t)=>{let r=e.lenses??{},i=new Set;for(let[n,s]of Object.entries(e.entities??{}))for(let[e,o]of Object.entries(s))for(let s of o?.lenses??[])Object.hasOwn(r,s)?i.add(s):t.at("entities",n,e,"lenses").error(a.ASSISTANT_UNKNOWN_LENS,l.ASSISTANT_UNKNOWN_LENS(`${n}.${e}`,s,Object.keys(r)));for(let e of Object.keys(r))v.has(e)?t.at("lenses",e).error(a.ASSISTANT_RESERVED_LENS_NAME,l.ASSISTANT_RESERVED_LENS_NAME(e,[...v])):i.has(e)||t.at("lenses",e).error(a.ASSISTANT_EMPTY_LENS,l.ASSISTANT_EMPTY_LENS(e));return Object.fromEntries(Object.entries(r).map(([e,{description:t,maxDepth:r}])=>[e,{description:t,maxDepth:r??1}]))})(e,N),q=c(e.formElements??{},N.at("formElements"));if(N.errors.length>E)return;let ee=e=>Object.fromEntries(Object.entries(e).map(([e,t])=>[e,{hints:j(t.hints),groups:Object.entries(t.groups).map(([e,t])=>({instanceName:e,groupId:t?.as??e,...t?.description===void 0?{}:{description:t.description},dryRuns:t?.allowDryRuns??!0}))}]));return{declarations:{entities:Object.fromEntries(Object.keys(e.entities??{}).map(e=>[e,(_.get(e)??[]).map(e=>({name:e.name,source:e.source,type:e.type,localized:e.localized,describedByManifest:e.describedByManifest,...void 0===e.description?{}:{description:e.description},...void 0===e.valueDescription?{}:{valueDescription:e.valueDescription},...void 0===e.enumValues?{}:{enumValues:e.enumValues},...void 0===e.lenses?{}:{lenses:e.lenses}}))])),enumValues:Object.fromEntries(t.entityTypes.map(e=>[e,Object.fromEntries(Object.entries(t.resolvedShapes.get(e)?.properties??{}).flatMap(([e,t])=>{let r=T(t,A).enumValues;return r?[[e,r]]:[]}))])),deletable:Object.keys(e.deletable??{}),writable:Object.fromEntries(Object.entries(e.writable??{}).map(([e,r])=>[e,Object.fromEntries(Object.entries(r).map(([r,i])=>[r,{defaultOptionsName:i?.options?.as===void 0,members:Object.fromEntries(t.entityTypes.filter(r=>r===e||[...t.aliases].find(([t])=>t===e)?.[1].includes(r)).flatMap(i=>{let n=R(t.resolvedShapes.get(i)?.properties??{},r),s=n&&M(i,{property:r,writableKey:e},n,{model:t,resolveRef:A,exposed:new Map,sources:{}},N.at("writable")),o=G.get(i)?.find(t=>t.entry===`${e}.${r}`);return s?[[i,{field:s,...T(n,A).localized?{exposedDescription:g}:{},...o?{options:{options:o.options,hints:o.hints}}:{}}]]:[]}))}]))])),childRecipes:ee(e.childRecipes??{}),replaceRecipes:ee(e.replaceRecipes??{}),screenshots:Object.fromEntries(Object.entries(e.screenshots??{}).map(([e,t])=>[e,Object.entries(t).map(([e,{description:t,as:r}])=>({view:r??e,instanceName:e,description:t}))]))},entityTypes:t.entityTypes,aliases:Object.fromEntries(t.aliases),exampleType:t.rootEntityTypes[0]??t.entityTypes[0],states:{navigationStates:r.navigationStates,viewStates:r.viewStates,toolStates:r.toolStates},deletableTypes:H,writableTypes:z,actionFields:Z,childRecipes:Object.fromEntries(Object.entries(Y.groups).map(([e,t])=>[e,{groups:t,hints:Y.hints.get(e)??[]}])),replaceRecipes:Object.fromEntries(Object.entries(x.groups).map(([e,t])=>[e,{groups:t,hints:x.hints.get(e)??[]}])),optionsEdges:Object.fromEntries([...G].map(([e,t])=>[e,t.map(({options:e,hints:t})=>({options:e,hints:t}))])),screenshots:Object.fromEntries(B.views),fields:Object.fromEntries([...W].map(([e,t])=>[e,t.map(t=>o(t,_.get(e)??[]))])),lenses:Q,formElements:q}};export const createAssistantSchema=(e,t,n)=>{let s=resolveAssistantManifest(e,t,n);if(s)try{return{...i(s),resolved:s}}catch(e){if(e instanceof r)return void n.at("entities").error(a.ASSISTANT_FIELD_SHAPE_CONFLICT,l.ASSISTANT_FIELD_SHAPE_CONFLICT(e.fieldName,e.exposures));n.error(a.ASSISTANT_INVALID_SCHEMA,l.ASSISTANT_INVALID_SCHEMA([e instanceof Error?e.message:String(e)]));return}};
|
|
1
|
+
import{isArray as e}from"@salsita-ai/common/utils";import{ASSISTANT_HINTS as t,AssistantFieldClashError as i,buildAssistantManifest as r,describeAssistantValues as n,mergeAssistantFields as s,resolveAssistantField as o}from"#package/domain";import{DiagnosticCode as a,diagnosticMessages as l}from"../../../../errors/index.js";import{ASSISTANT_OPTION_COMPONENT_TYPES as S,GRAPHQL_NAME_PATTERN as N}from"../../../raw-spec/index.js";import{createSchemaRefResolver as p,isNullableSchema as T,phxDefinitionRefName as c}from"../../common/index.js";import{resolveAssistantFieldType as _}from"./assistant-field-type.js";import{resolveFormElements as d}from"./assistant-form-elements.js";let E="AnyDomainEntity",A="RecipeGroup",m="Recipe",f="DryRun",I="FieldOption",O="agentScreenshot",u=/^(?!(true|false|null)$)[_A-Za-z][_0-9A-Za-z]*$/,y={section:"childRecipes",component:"childEntityRecipes",mutation:"addChild",typeSuffix:"ChildRecipes"},h={section:"replaceRecipes",component:"replaceEntityRecipes",mutation:"replaceEntity",typeSuffix:"ReplaceRecipes"},v=new Set(["id","type","meta"]),R=new Set(["Query","Mutation","Navigation",A,m,f,"DryRunError",I,"Screenshot","JSON","String","Int","Float","Boolean","ID"]),b=new Set([A,m,I,f]),M=new Set(["id","type"]),C="A string, a message descriptor or a multilingual object; passed without translation.",g=(e,t)=>Object.entries(e).find(([e])=>e===t)?.[1],P=(e,{property:t,writableKey:i},r,{resolveRef:s,exposed:o,sources:S},N)=>{let p=Object.entries(g(S,e)??{}),T=o.get(e)?.find(({source:e})=>e===t)?.name??p.find(([,{source:e}])=>e===t)?.[0],c=void 0===T?p.find(([e])=>e===t)?.[1]:void 0;if(c)return void N.at(i,t).error(a.ASSISTANT_FIELD_NAME_CONFLICT,l.ASSISTANT_FIELD_NAME_CONFLICT(e,t,[c.source,t],`${i}.${t}`));let{type:d,enumValues:E,localized:A,description:m}=_(r,s),f={...d,nonNull:!1},I=T??t,O=void 0===T?n(m,E):void 0;return A?{name:I,property:t,type:{kind:"scalar",name:"JSON",nonNull:!1},description:O?`${O} ${C}`:C}:{name:I,property:t,type:f,...void 0===O?{}:{description:O}}},j=(e,t)=>new Set([e,...[...t.aliases].filter(([,t])=>t.includes(e)).map(([e])=>e)]),w=(e,t,{model:i,components:r})=>{let n=j(e,i);return r.filter(({componentName:e,typeOrAlias:i})=>e===t&&n.has(i)).map(({instanceName:e})=>String(e))},D=(e,t,{model:i,components:r})=>{let n=j(e,i);return r.flatMap(({componentName:e,typeOrAlias:i,instanceName:r,implementation:s})=>S.some(t=>t===e)&&n.has(i)&&"userBound"===s.kind&&"composite"===s.implementation.kind&&s.implementation.writeBindings.some(({entityField:e})=>e===t)?[{componentType:e,instanceName:String(r)}]:[])},U=(...e)=>t.filter(t=>e.some(e=>e?.includes(t))),L=(e,t)=>({groupId:t?.as??e,instanceName:e,...t?.description===void 0?{}:{description:t.description},dryRuns:t?.allowDryRuns??!0,hints:U(t?.hints)}),W=(e,t,i,r)=>{let{model:n}=i,s=new Map;for(let[o,S]of Object.entries(e)){let e=n.entityTypes.find(e=>e===o),p=e?[e]:[...n.aliases].find(([e])=>e===o)?.[1];if(!p){r.at(o).error(a.ASSISTANT_UNKNOWN_TYPE,l.ASSISTANT_UNKNOWN_TYPE(t.section,o));continue}for(let[e,n]of Object.entries(S)){let S=r.at(o,e),T=`${o}.${e}`,c=L(e,n);if(!N.test(c.groupId)){S.error(a.ASSISTANT_INVALID_RECIPE_GROUP_ID,l.ASSISTANT_INVALID_RECIPE_GROUP_ID(t,o,e,c.groupId));continue}for(let r of p){let n=w(r,t.component,i),N=s.get(r)??[],p=N.find(e=>e.group.groupId===c.groupId);n.includes(e)?p?S.error(a.ASSISTANT_DUPLICATE_RECIPE_GROUP,l.ASSISTANT_DUPLICATE_RECIPE_GROUP(t,r,c.groupId,[p.entry,T])):s.set(r,[...N,{group:c,entry:T,entryCtx:S}]):S.error(a.ASSISTANT_UNKNOWN_RECIPE_GROUP,l.ASSISTANT_UNKNOWN_RECIPE_GROUP(t,o,e,r,n))}}}let o=n.entityTypes.flatMap(e=>{let t=s.get(e);return t?[{entityType:e,groups:t}]:[]});return{groups:Object.fromEntries(o.map(({entityType:e,groups:t})=>[e,t.map(({group:e})=>e)])),metaEntries:new Map(o.flatMap(({entityType:e,groups:[t]})=>t?[[e,t.entryCtx]]:[]))}},$=(e,t,{model:i,components:r})=>{let n=new Set([e,...[...i.aliases].filter(([,t])=>t.includes(e)).map(([e])=>e)]),s=r.find(e=>e.componentName===O&&String(e.instanceName)===t&&n.has(e.typeOrAlias));if(s?.implementation.kind!=="userBound"||"composite"!==s.implementation.implementation.kind)return;let o=s.implementation.implementation.resolvedProps.exportState;return"string"==typeof o?o:void 0},F=e=>`${e}Meta`,V=e=>`${e}ScreenshotView`,k=(e,{typeSuffix:t})=>`${e}${t}`,K=(e,t,i)=>{for(let[r,n]of e){let e=k(r,t);[...i.resolvedShapes.keys()].some(t=>t===e)&&n.error(a.ASSISTANT_RECIPE_GROUPS_TYPE_NAME_CONFLICT,l.ASSISTANT_RECIPE_GROUPS_TYPE_NAME_CONFLICT(t,r,e))}},Y=e=>`${e.charAt(0).toUpperCase()+e.slice(1)}Result`,x=e=>{let t=(({anyOf:e,oneOf:t})=>[...e??[],...t??[]].filter(e=>"null"!==e.type))(e);return e.$ref||1!==t.length?e:t[0]},G=(e,t)=>{let{type:i,enumValues:r,localized:s,description:o}=_(e,t),a={...i,nonNull:!1},l=s?`${n(o,r)??""} ${C}`.trim():n(o,r);return{type:{...s?{kind:"scalar",name:"JSON",nonNull:!1}:a,nonNull:i.nonNull},...void 0===l?{}:{description:l}}},H=(t,i)=>{let r=(t=>{let i=x(t),r=i?.type==="array"&&i.items&&!e(i.items)?x(i.items):void 0,n=r??i;if(n?.$ref!==void 0&&"$DomainEntity"===c(n.$ref))return{target:n.references??E,list:void 0!==r}})(t);if(r)return{kind:"edge",...r,nullable:T(t,i),...void 0===t.description?{}:{description:t.description}};let{type:s,enumValues:o,localized:a,description:l}=_(t,i),S=n(l,o);return a?{kind:"value",type:{kind:"scalar",name:"JSON",nonNull:s.nonNull},description:`${l??""} ${C}`.trim()}:{kind:"value",type:s,...void 0===S?{}:{description:S}}},B=(e,t)=>{let{type:i,enumValues:r,localized:n,description:s}=_(e,t);return{type:{kind:"value",type:i},localized:!0===n,description:s,enumValues:r}},z=(e,t,i,r,s)=>{let o=t.startsWith("$")?((e,t,i,r)=>{let n=((e,t,{expressions:i,entityTypes:r})=>{let n=r.find(t=>t===e);for(let r of void 0===n?[e]:i.entityExpressions.get(n)?.shapeGroups??[]){let e=[...i.expressions.get(r)?.values()??[]].find(e=>e.name===t);if(e?.declaredSchema)return{implementation:e.implementation,declaredSchema:e.declaredSchema}}})(e.name,t,i);if(!n)return void r.error(a.ASSISTANT_UNKNOWN_FIELD,l.ASSISTANT_UNKNOWN_FIELD("entities",e.name,t));let{implementation:s}=n;if("violations"===s.kind)return void r.error(a.ASSISTANT_UNSUPPORTED_EXPRESSION,l.ASSISTANT_UNSUPPORTED_EXPRESSION(e.name,t));if("relation"===s.kind){let[{target:e,cardinality:t}]=s.params;return{type:{kind:"edge",target:e,cardinality:t},localized:!1,description:void 0}}return B(n.declaredSchema,i.resolveRef)})(e,t,r,s):((e,t,{resolveRef:i},r)=>{let n=Object.entries(e.shape.properties).find(([e])=>e===t)?.[1];return n?B(n,i):void r.error(a.ASSISTANT_UNKNOWN_FIELD,l.ASSISTANT_UNKNOWN_FIELD("entities",e.name,t))})(e,t,r,s);if(!o)return;let S=i?.as??(t.startsWith("$")?`_${t.slice(1)}`:t);return v.has(S)?void s.error(a.ASSISTANT_RESERVED_FIELD_NAME,l.ASSISTANT_RESERVED_FIELD_NAME(e.name,t,S)):{name:S,source:t,type:o.type,localized:o.localized,description:n(i?.description??o.description,o.enumValues),describedByManifest:i?.description!==void 0,enumValues:o.enumValues,valueDescription:i?.description??o.description,...i?.lenses?.length?{lenses:[...new Set(i.lenses)]}:{}}},J=(e,t,i,r,n)=>s(t,i,r,(t,i,r)=>{n.error(a.ASSISTANT_FIELD_NAME_CONFLICT,l.ASSISTANT_FIELD_NAME_CONFLICT(e,t,[i,r]))});export const resolveAssistantManifest=(e,{model:t,states:i,phxDefinitions:r,expressions:n,components:s,actions:S},N)=>{let T=N.errors.length,c=N.at("entities"),A=p(t.commonTypes,r);for(let e of t.resolvedShapes.keys())R.has(e)&&N.error(a.ASSISTANT_RESERVED_TYPE_NAME,l.ASSISTANT_RESERVED_TYPE_NAME(e,[...R]));let m=((e,t,i)=>{let r=new Map;for(let n of e){let e=[];for(let[r,s]of Object.entries(n.entries)){let o=z(n,r,s,t,i.at(n.name,r));o&&e.push(o)}r.set(n.name,e)}return r})(((e,t,i)=>{let r=[];for(let[i,n]of t.resolvedShapes){let t=e[i];t&&r.push({name:i,shape:n,entries:t})}let n=new Set(t.resolvedShapes.keys());for(let t of Object.keys(e))n.has(t)||i.at(t).error(a.ASSISTANT_UNKNOWN_TYPE,l.ASSISTANT_UNKNOWN_TYPE("entities",t));return r})(e.entities??{},t,c),{resolveRef:A,expressions:n,entityTypes:t.entityTypes},c),f=J(E,[],m.get(E)??[],()=>void 0,N),I=new Map([[E,f]]);for(let e of t.aliases.keys())e!==E&&I.set(e,J(e,[f],m.get(e)??[],()=>void 0,N));for(let e of t.entityTypes){let i=[E,...[...t.aliases].filter(([t,i])=>t!==E&&i.includes(e)).map(([e])=>e)],r=[...t.resolvedShapes].find(([t])=>t===e)?.[1];I.set(e,J(e,i.map(e=>I.get(e)??[]),m.get(e)??[],e=>{let t=Object.entries(r?.properties??{}).find(([t])=>t===e)?.[1];return t&&_(t,A).enumValues},N))}let v=Object.fromEntries(t.entityTypes.map(e=>[e,Object.fromEntries((I.get(e)??[]).map(({name:e,source:t,localized:i})=>[e,i?{source:t,localized:!0}:{source:t}]))])),j=W(e.childRecipes??{},y,{model:t,components:s},N.at("childRecipes")),x=W(e.replaceRecipes??{},h,{model:t,components:s},N.at("replaceRecipes")),B=((e,t,i)=>{let r=new Set;for(let n of Object.keys(e)){let e=t.entityTypes.find(e=>e===n),s=e?[e]:[...t.aliases].find(([e])=>e===n)?.[1];s?s.forEach(e=>r.add(e)):i.at(n).error(a.ASSISTANT_UNKNOWN_TYPE,l.ASSISTANT_UNKNOWN_TYPE("deletable",n))}return t.entityTypes.filter(e=>r.has(e))})(e.deletable??{},t,N.at("deletable")),X=((e,t,i)=>{let{model:r}=t,n=((e,t,i)=>{let r=new Map;for(let[n,s]of Object.entries(e)){let e=t.entityTypes.find(e=>e===n),o=e?[e]:[...t.aliases].find(([e])=>e===n)?.[1],S=[...t.resolvedShapes].find(([e])=>e===n)?.[1];if(!o||!S){i.at(n).error(a.ASSISTANT_UNKNOWN_TYPE,l.ASSISTANT_UNKNOWN_TYPE("writable",n));continue}for(let e of Object.keys(s)){let t=i.at(n,e);e.startsWith("$")||M.has(e)?t.error(a.ASSISTANT_NOT_WRITABLE,l.ASSISTANT_NOT_WRITABLE(n,e)):g(S.properties,e)?o.forEach(t=>{let i=r.get(t)??new Map;r.set(t,i.has(e)?i:i.set(e,n))}):t.error(a.ASSISTANT_UNKNOWN_FIELD,l.ASSISTANT_UNKNOWN_FIELD("writable",n,e))}}return r})(e,r,i);return r.entityTypes.flatMap(e=>{let s=[...r.resolvedShapes].find(([t])=>t===e)?.[1],o=[...n.get(e)??[]].flatMap(([r,n])=>{let o=s&&g(s.properties,r);return(o&&P(e,{property:r,writableKey:n},o,t,i))??[]});return o.length>0?[{entityType:e,fields:o}]:[]})})(e.writable??{},{model:t,resolveRef:A,exposed:m,sources:v},N.at("writable")),Z=((e,t,i,r)=>{let{model:n}=i,s=new Map,o=e=>{let t=n.entityTypes.find(t=>t===e);return t?[t]:[...n.aliases].find(([t])=>t===e)?.[1]??[]},S=new Set(Object.entries(e).flatMap(([e,t])=>Object.entries(t).flatMap(([t,i])=>i?.options===void 0?[]:o(e).map(e=>`${e}.${t}`)))),N=new Set;for(let[n,p]of Object.entries(e)){let e=o(n);for(let[o,T]of Object.entries(p)){let p=T?.options;if(null===p)continue;let c=p?r.at(n,o,"options"):r.at(n,o),_=`${n}.${o}`;for(let r of e){let e=t.find(e=>e.entityType===r)?.fields.find(e=>e.property===o),n=`${r}.${o}`;if(!e||!p&&(S.has(n)||N.has(n)))continue;p||N.add(n);let T=s.get(r)??[],d=p?.componentType===void 0||void 0===p.instanceName?void 0:{componentType:p.componentType,instanceName:p.instanceName},E=d?[d]:D(r,o,i),[A]=E,m=p?.as??`${e.name}Options`,f=T.find(t=>t.options.edgeName===m||t.options.field===e.name);if(d&&!w(r,d.componentType,i).includes(d.instanceName))c.error(a.ASSISTANT_UNKNOWN_OPTIONS_COMPONENT,l.ASSISTANT_UNKNOWN_OPTIONS_COMPONENT(_,d,r,w(r,d.componentType,i)));else if(E.length>1)c.error(a.ASSISTANT_AMBIGUOUS_OPTIONS_COMPONENT,l.ASSISTANT_AMBIGUOUS_OPTIONS_COMPONENT(p?`${_}.options`:_,r,E));else if(A)if(m===y.section||m===h.section||"screenshot"===m)c.error(a.ASSISTANT_RESERVED_OPTIONS_EDGE_NAME,l.ASSISTANT_RESERVED_OPTIONS_EDGE_NAME(_,m,e.name));else if(f)c.error(a.ASSISTANT_DUPLICATE_OPTIONS_EDGE,l.ASSISTANT_DUPLICATE_OPTIONS_EDGE(r,f.options.edgeName===m?{edgeName:m}:{field:e.name},[f.entry,_]));else{let t={field:e.name,edgeName:m,componentType:A.componentType,instanceName:A.instanceName,validate:p?.validate??!0,dryRuns:p?.allowDryRuns??!0};s.set(r,[...T,{options:t,hints:U(p?.hints),entry:_,entryCtx:c}])}else p&&c.error(a.ASSISTANT_MISSING_OPTIONS_COMPONENT,l.ASSISTANT_MISSING_OPTIONS_COMPONENT(_,r,o))}}}return s})(e.writable??{},X,{model:t,components:s},N.at("writable")),Q=((e,t,i)=>{let{model:r,states:n}=t,s=new Map;for(let[o,S]of Object.entries(e)){let e=r.entityTypes.find(e=>e===o),N=e?[e]:[...r.aliases].find(([e])=>e===o)?.[1];if(!N){i.at(o).error(a.ASSISTANT_UNKNOWN_TYPE,l.ASSISTANT_UNKNOWN_TYPE("screenshots",o));continue}for(let[e,{description:r,as:p}]of Object.entries(S)){let S=i.at(o,e),T=`${o}.${e}`,c={view:p??e,instanceName:e,description:r};if(!u.test(c.view)){S.error(a.ASSISTANT_INVALID_SCREENSHOT_VIEW_NAME,l.ASSISTANT_INVALID_SCREENSHOT_VIEW_NAME(o,e,c.view));continue}for(let i of N){let r=w(i,O,t),N=$(i,e,t),p=s.get(i)??[],_=p.find(e=>e.view.view===c.view);r.includes(e)?void 0===N||n.exportStates.includes(N)?_?S.error(a.ASSISTANT_DUPLICATE_SCREENSHOT_VIEW,l.ASSISTANT_DUPLICATE_SCREENSHOT_VIEW(i,c.view,[_.entry,T])):s.set(i,[...p,{view:c,entry:T,entryCtx:S}]):S.error(a.ASSISTANT_UNKNOWN_SCREENSHOT_EXPORT_STATE,l.ASSISTANT_UNKNOWN_SCREENSHOT_EXPORT_STATE(o,e,N,n.exportStates)):S.error(a.ASSISTANT_UNKNOWN_SCREENSHOT_VIEW,l.ASSISTANT_UNKNOWN_SCREENSHOT_VIEW(o,e,i,r))}}}let o=r.entityTypes.flatMap(e=>{let t=s.get(e);return t?[{entityType:e,views:t}]:[]});return{views:new Map(o.map(({entityType:e,views:t})=>[e,t.map(({view:e})=>e)])),metaEntries:new Map(o.flatMap(({entityType:e,views:[t]})=>t?[[e,t.entryCtx]]:[]))}})(e.screenshots??{},{model:t,components:s,states:i},N.at("screenshots")),q=t.entityTypes.filter(e=>w(e,"violations",{model:t,components:s}).length>0);var ee=[j.metaEntries,x.metaEntries,new Map([...Z].flatMap(([e,[t]])=>t?[[e,t.entryCtx]]:[])),Q.metaEntries,new Map(q.map(e=>[e,N]))];for(let e of t.entityTypes){let i=ee.flatMap(t=>t.get(e)??[])[0],r=F(e);i&&[...t.resolvedShapes.keys()].some(e=>e===r)&&i.error(a.ASSISTANT_META_TYPE_NAME_CONFLICT,l.ASSISTANT_META_TYPE_NAME_CONFLICT(e,r))}for(let[e,i]of(K(j.metaEntries,y,t),K(x.metaEntries,h,t),Q.metaEntries)){let r=V(e);[...t.resolvedShapes.keys()].some(e=>e===r)&&i.error(a.ASSISTANT_SCREENSHOT_VIEW_TYPE_NAME_CONFLICT,l.ASSISTANT_SCREENSHOT_VIEW_TYPE_NAME_CONFLICT(e,r))}let et=t.entityTypes.filter(e=>(j.groups[e]?.length??0)>0||(x.groups[e]?.length??0)>0||(Z.get(e)?.length??0)>0||Q.views.has(e)||q.includes(e)).flatMap(e=>[F(e),...(j.groups[e]?.length??0)>0?[k(e,y)]:[],...(x.groups[e]?.length??0)>0?[k(e,h)]:[],...Q.views.has(e)?[V(e)]:[]]),ei=((e,{actions:t,resolveRef:i,builtInMutations:r,typeNames:n},s)=>{let o=[],S=[...t.values()].map(e=>String(e.name));for(let[N,p]of Object.entries(e)){let e=s.at(N),T=[...t.values()].find(e=>e.name===N);if(!T){e.error(a.ASSISTANT_UNKNOWN_ACTION,l.ASSISTANT_UNKNOWN_ACTION(N,S));continue}let c=p?.as??N,_=o.find(e=>e.fieldName===c),d=Y(c);if(r.has(c)||_){e.error(a.ASSISTANT_MUTATION_NAME_CONFLICT,l.ASSISTANT_MUTATION_NAME_CONFLICT(N,c,_?`"assistant.actions.${_.actionName}" already exposes`:"the built-in mutation of that name already takes"));continue}if(n.has(d)||o.some(e=>Y(e.fieldName)===d)){e.error(a.ASSISTANT_ACTION_RESULT_TYPE_CONFLICT,l.ASSISTANT_ACTION_RESULT_TYPE_CONFLICT(N,c,d));continue}let E=p?.description??T.description;o.push({fieldName:c,actionName:N,...void 0===E?{}:{description:E},args:Object.fromEntries(Object.entries(T.params).map(([e,{schema:t}])=>[e,G(t,i)])),result:Object.fromEntries(Object.entries(T.result).map(([e,t])=>[e,H(t,i)]))})}return o})(e.actions??{},{actions:S,resolveRef:A,builtInMutations:new Set(["deleteEntity",y.mutation,h.mutation,...X.map(({entityType:e})=>`modify${e}`)]),typeNames:new Set([...R,...t.resolvedShapes.keys(),...et])},N.at("actions")),er=((e,t)=>{let i=e.lenses??{},r=new Set;for(let[n,s]of Object.entries(e.entities??{}))for(let[e,o]of Object.entries(s))for(let s of o?.lenses??[])Object.hasOwn(i,s)?r.add(s):t.at("entities",n,e,"lenses").error(a.ASSISTANT_UNKNOWN_LENS,l.ASSISTANT_UNKNOWN_LENS(`${n}.${e}`,s,Object.keys(i)));for(let e of Object.keys(i))b.has(e)?t.at("lenses",e).error(a.ASSISTANT_RESERVED_LENS_NAME,l.ASSISTANT_RESERVED_LENS_NAME(e,[...b])):r.has(e)||t.at("lenses",e).error(a.ASSISTANT_EMPTY_LENS,l.ASSISTANT_EMPTY_LENS(e));return Object.fromEntries(Object.entries(i).map(([e,{description:t,maxDepth:i}])=>[e,{description:t,maxDepth:i??1}]))})(e,N),en=d(e.formElements??{},N.at("formElements"));if(N.errors.length>T)return;let es=e=>Object.fromEntries(Object.entries(e).map(([e,t])=>[e,Object.entries(t).map(([e,t])=>L(e,t))]));return{declarations:{entities:Object.fromEntries(Object.keys(e.entities??{}).map(e=>[e,(m.get(e)??[]).map(e=>({name:e.name,source:e.source,type:e.type,localized:e.localized,describedByManifest:e.describedByManifest,...void 0===e.description?{}:{description:e.description},...void 0===e.valueDescription?{}:{valueDescription:e.valueDescription},...void 0===e.enumValues?{}:{enumValues:e.enumValues},...void 0===e.lenses?{}:{lenses:e.lenses}}))])),enumValues:Object.fromEntries(t.entityTypes.map(e=>[e,Object.fromEntries(Object.entries(t.resolvedShapes.get(e)?.properties??{}).flatMap(([e,t])=>{let i=_(t,A).enumValues;return i?[[e,i]]:[]}))])),deletable:Object.keys(e.deletable??{}),writable:Object.fromEntries(Object.entries(e.writable??{}).map(([e,i])=>[e,Object.fromEntries(Object.entries(i).map(([i,r])=>[i,{defaultOptionsName:r?.options?.as===void 0,members:Object.fromEntries(t.entityTypes.filter(i=>i===e||[...t.aliases].find(([t])=>t===e)?.[1].includes(i)).flatMap(r=>{let n=g(t.resolvedShapes.get(r)?.properties??{},i),s=n&&P(r,{property:i,writableKey:e},n,{model:t,resolveRef:A,exposed:new Map,sources:{}},N.at("writable")),o=Z.get(r)?.find(t=>t.entry===`${e}.${i}`);return s?[[r,{field:s,..._(n,A).localized?{exposedDescription:C}:{},...o?{options:{options:o.options,hints:o.hints}}:{}}]]:[]}))}]))])),childRecipes:es(e.childRecipes??{}),replaceRecipes:es(e.replaceRecipes??{}),screenshots:Object.fromEntries(Object.entries(e.screenshots??{}).map(([e,t])=>[e,Object.entries(t).map(([e,{description:t,as:i}])=>({view:i??e,instanceName:e,description:t}))]))},entityTypes:t.entityTypes,aliases:Object.fromEntries(t.aliases),exampleType:t.rootEntityTypes[0]??t.entityTypes[0],states:{navigationStates:i.navigationStates,viewStates:i.viewStates,toolStates:i.toolStates},deletableTypes:B,writableTypes:X,actionFields:ei,invariantTypes:q,childRecipes:j.groups,replaceRecipes:x.groups,optionsEdges:Object.fromEntries([...Z].map(([e,t])=>[e,t.map(({options:e,hints:t})=>({options:e,hints:t}))])),screenshots:Object.fromEntries(Q.views),fields:Object.fromEntries([...I].map(([e,t])=>[e,t.map(t=>o(t,m.get(e)??[]))])),lenses:er,formElements:en}};export const createAssistantSchema=(e,t,n)=>{let s=resolveAssistantManifest(e,t,n);if(s)try{return{...r(s),resolved:s}}catch(e){if(e instanceof i)return void n.at("entities").error(a.ASSISTANT_FIELD_SHAPE_CONFLICT,l.ASSISTANT_FIELD_SHAPE_CONFLICT(e.fieldName,e.exposures));n.error(a.ASSISTANT_INVALID_SCHEMA,l.ASSISTANT_INVALID_SCHEMA([e instanceof Error?e.message:String(e)]));return}};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Branded as t}from"@salsita-ai/common/utils";import{createAssistantSchema as s}from"./assistant-schema.js";export const AssistantSpec=(i,
|
|
1
|
+
import{Branded as t}from"@salsita-ai/common/utils";import{createAssistantSchema as s}from"./assistant-schema.js";export const AssistantSpec=(a,i,n)=>{let{manifest:r}=a;if(!r)return null;let l=s(r,i,n.at("assistant"));return l?t(l):null};
|
|
@@ -1,27 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ChunkName as ChunkNameData, Chunks as ChunksData } from '#package/domain';
|
|
2
2
|
import type { ParseContext } from '../../../../core/index.js';
|
|
3
3
|
import type { MergedChunks } from '../../../merge/index.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* entries point to these names through their `chunk` field, and the parser adds
|
|
8
|
-
* the reserved `system` chunk when user chunks exist.
|
|
9
|
-
*/
|
|
10
|
-
export type ChunkName = Branded<'ChunkName', string>;
|
|
4
|
+
export type { ChunkDefinition } from '#package/domain';
|
|
5
|
+
/** A validated published-data chunk name; see {@link ChunkNameData | ChunkName} in `domain`. */
|
|
6
|
+
export type ChunkName = ChunkNameData;
|
|
11
7
|
export declare const ChunkName: (name: string, ctx: ParseContext) => ChunkName | undefined;
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
* `scope` is typically `'project'` (per-project data) or `'public'` (shared).
|
|
15
|
-
*/
|
|
16
|
-
export interface ChunkDefinition {
|
|
17
|
-
/** Visibility/storage scope used by runtime data publishing for this chunk. */
|
|
18
|
-
readonly scope: string;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Validated chunk definitions, keyed by chunk name.
|
|
22
|
-
* When any user-defined chunks are present, the reserved `system` chunk is
|
|
23
|
-
* auto-injected with `scope: 'public'` to carry admin presets/recipes schemas.
|
|
24
|
-
* When the input is empty, no system injection happens (mirrors domain-spec behavior).
|
|
25
|
-
*/
|
|
26
|
-
export type Chunks = Readonly<Record<ChunkName, ChunkDefinition>>;
|
|
8
|
+
/** The validated chunk definitions by chunk name; see {@link ChunksData | Chunks} in `domain`. */
|
|
9
|
+
export type Chunks = ChunksData;
|
|
27
10
|
export declare const Chunks: (merged: MergedChunks, ctx: ParseContext) => Chunks | undefined;
|
package/dist/application-spec/parse-application-files/spec/sections/data-spec/custom-data-spec.d.ts
CHANGED
|
@@ -1,24 +1,9 @@
|
|
|
1
1
|
import { Branded } from '@salsita-ai/common/utils';
|
|
2
|
-
import type {
|
|
2
|
+
import type { CustomDataSpecEntry } from '#package/domain';
|
|
3
3
|
import { type ParseContext } from '../../../../core/index.js';
|
|
4
4
|
import type { MergedDataSpec } from '../../../merge/index.js';
|
|
5
5
|
import { type ChunkDefinition, ChunkName } from './chunks.js';
|
|
6
6
|
import { DataEntryKey } from './data-entry-key.js';
|
|
7
|
-
/** Parsed `$data.custom` entry with validated definition and normalized row values. */
|
|
8
|
-
export interface CustomDataSpecEntry {
|
|
9
|
-
/** Column/property schema for a custom data row, used by admin pages and published-data schemas. */
|
|
10
|
-
readonly definition: DataSchema;
|
|
11
|
-
/** Optional published-data chunk that receives this entry as an array property. */
|
|
12
|
-
readonly chunk?: string;
|
|
13
|
-
/** Ownership mode deciding whether data is manual, externally connected, or admin-generated. */
|
|
14
|
-
readonly kind: 'manual' | 'connected' | 'generated';
|
|
15
|
-
/** Optional human-readable label used by inferred admin pages and connected-data UI. */
|
|
16
|
-
readonly title?: string;
|
|
17
|
-
/** Optional icon name used in inferred admin navigation. */
|
|
18
|
-
readonly icon?: string;
|
|
19
|
-
/** Default rows normalized to the same column order as `definition`. */
|
|
20
|
-
readonly values?: ReadonlyArray<readonly DataCellValue[]>;
|
|
21
|
-
}
|
|
22
7
|
/**
|
|
23
8
|
* Validated `$data.custom` section.
|
|
24
9
|
* Every key is a validated data entry key, every definition field has a valid
|
package/dist/application-spec/parse-application-files/spec/sections/data-spec/data-entry-key.d.ts
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { DataEntryKey as DataEntryKeyData } from '#package/domain';
|
|
2
2
|
import type { ParseContext } from '../../../../core/index.js';
|
|
3
3
|
/** `$data` subsection that owns a data entry key and determines its raw entry shape. */
|
|
4
4
|
export type DataEntrySection = 'custom' | 'swatchOptions';
|
|
5
|
-
/**
|
|
6
|
-
|
|
7
|
-
* This is the stable identifier for a data collection declared under `$data.custom`
|
|
8
|
-
* or `$data.swatchOptions`. The same key is used when extending published data,
|
|
9
|
-
* wiring connected/generated admin pages, and linking explicit admin pages through
|
|
10
|
-
* `connectedDataEntry`.
|
|
11
|
-
*/
|
|
12
|
-
export type DataEntryKey = Branded<'DataEntryKey', string>;
|
|
5
|
+
/** A validated `$data` entry key; see {@link DataEntryKeyData | DataEntryKey} in `domain`. */
|
|
6
|
+
export type DataEntryKey = DataEntryKeyData;
|
|
13
7
|
export declare const DataEntryKey: (section: DataEntrySection, key: string, ctx: ParseContext) => DataEntryKey | undefined;
|
package/dist/application-spec/parse-application-files/spec/sections/data-spec/data-spec.d.ts
CHANGED
|
@@ -1,18 +1,9 @@
|
|
|
1
1
|
import { Branded } from '@salsita-ai/common/utils';
|
|
2
|
-
import type
|
|
2
|
+
import { type DataCellValue, type DataSchema, type ParsedDataSpecEntries } from '#package/domain';
|
|
3
3
|
import { type ParseContext } from '../../../../core/index.js';
|
|
4
4
|
import type { MergedChunks, MergedDataSpec } from '../../../merge/index.js';
|
|
5
5
|
import { Chunks } from './chunks.js';
|
|
6
|
-
import { type CustomDataSpecEntry } from './custom-data-spec.js';
|
|
7
6
|
import type { DataEntryKey } from './data-entry-key.js';
|
|
8
|
-
import { type SwatchDataSpecEntry } from './swatch-data-spec.js';
|
|
9
|
-
/** Validated `$data` entries grouped by their source section. */
|
|
10
|
-
export interface ParsedDataSpecEntries {
|
|
11
|
-
/** Custom data entries with user-declared schemas. */
|
|
12
|
-
readonly custom: Readonly<Record<DataEntryKey, CustomDataSpecEntry>>;
|
|
13
|
-
/** Swatch data entries with the built-in swatch schema. */
|
|
14
|
-
readonly swatchOptions: Readonly<Record<DataEntryKey, SwatchDataSpecEntry>>;
|
|
15
|
-
}
|
|
16
7
|
export interface DataSpecDataEntry {
|
|
17
8
|
/** Data entry identifier used as published-data property and admin page navigation state. */
|
|
18
9
|
readonly key: DataEntryKey;
|
package/dist/application-spec/parse-application-files/spec/sections/data-spec/swatch-data-spec.d.ts
CHANGED
|
@@ -1,22 +1,9 @@
|
|
|
1
1
|
import { Branded } from '@salsita-ai/common/utils';
|
|
2
|
-
import type {
|
|
2
|
+
import type { SwatchDataSpecEntry } from '#package/domain';
|
|
3
3
|
import { type ParseContext } from '../../../../core/index.js';
|
|
4
4
|
import type { MergedDataSpec } from '../../../merge/index.js';
|
|
5
5
|
import { type ChunkDefinition, ChunkName } from './chunks.js';
|
|
6
6
|
import { DataEntryKey } from './data-entry-key.js';
|
|
7
|
-
/** Parsed `$data.swatchOptions` entry using the fixed swatch data shape. */
|
|
8
|
-
export interface SwatchDataSpecEntry {
|
|
9
|
-
/** Optional published-data chunk that receives this swatch entry as an array property. */
|
|
10
|
-
readonly chunk?: string;
|
|
11
|
-
/** Ownership mode deciding whether swatches are manual, externally connected, or admin-generated. */
|
|
12
|
-
readonly kind: 'manual' | 'connected' | 'generated';
|
|
13
|
-
/** Optional human-readable label used by inferred admin pages and connected-data UI. */
|
|
14
|
-
readonly title?: string;
|
|
15
|
-
/** Optional icon name used in inferred admin navigation. */
|
|
16
|
-
readonly icon?: string;
|
|
17
|
-
/** Default swatch rows normalized to `SWATCH_DEFINITION` column order. */
|
|
18
|
-
readonly values?: ReadonlyArray<readonly CellValue[]>;
|
|
19
|
-
}
|
|
20
7
|
/**
|
|
21
8
|
* Validated `$data.swatchOptions` section.
|
|
22
9
|
* Every key is a validated data entry key and default swatch values are
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { StateValue as StateValueData } from '#package/domain';
|
|
2
2
|
import type { ParseContext } from '../../../core/index.js';
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
* (e.g. "Default", "overview", "detailView").
|
|
6
|
-
* Used across navigation, view, tool, and export state dimensions.
|
|
7
|
-
*/
|
|
8
|
-
export type StateValue = Branded<'StateValue', string>;
|
|
3
|
+
/** A branded state value; see {@link StateValueData | StateValue} in `domain`. */
|
|
4
|
+
export type StateValue = StateValueData;
|
|
9
5
|
export declare const StateValue: (value: string, field: string, ctx: ParseContext) => StateValue | undefined;
|
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Theme as ThemeData } from '#package/domain';
|
|
2
2
|
import type { MergedTheme } from '../../merge/index.js';
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
* Preset identifies a built-in theme from getPhoenixThemes(),
|
|
6
|
-
* options provides partial overrides passed to the theme factory.
|
|
7
|
-
*/
|
|
8
|
-
export type Theme = Branded<'Theme', {
|
|
9
|
-
readonly preset: string;
|
|
10
|
-
readonly options: Readonly<Record<string, unknown>>;
|
|
11
|
-
}>;
|
|
3
|
+
/** The validated theme configuration; see {@link ThemeData | Theme} in `domain`. */
|
|
4
|
+
export type Theme = ThemeData;
|
|
12
5
|
export declare const Theme: (merged: MergedTheme) => Theme;
|
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { SpecTransformers } from '#package/domain';
|
|
2
2
|
import type { ParseContext } from '../../../core/index.js';
|
|
3
|
-
import type { MergedTransformers
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
* domain state transitions to enforce business rules (e.g. "fixLegsForCircleTop").
|
|
7
|
-
* Every entry's name must match a file basename in `src/transformers/`
|
|
8
|
-
* (modulo case + dashes — kebab-case files and camelCase YAML names are
|
|
9
|
-
* treated as equivalent since runtime matching happens on the `.build('name')`
|
|
10
|
-
* label, not the filename).
|
|
11
|
-
*/
|
|
12
|
-
export type Transformers = Branded<'Transformers', readonly TransformerEntry[]>;
|
|
3
|
+
import type { MergedTransformers } from '../../merge/index.js';
|
|
4
|
+
/** The validated transformer declarations; see {@link SpecTransformers} in `domain`. */
|
|
5
|
+
export type Transformers = SpecTransformers;
|
|
13
6
|
export declare const Transformers: (merged: MergedTransformers, transformerFiles: readonly string[], ctx: ParseContext) => Transformers;
|
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Ui as UiData } from '#package/domain';
|
|
2
2
|
import type { MergedUi } from '../../merge/index.js';
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
* Controls preview behavior, expansion mode, and locale settings.
|
|
6
|
-
*/
|
|
7
|
-
export type Ui = Branded<'Ui', {
|
|
8
|
-
readonly preview?: 'always' | 'never' | 'auto' | 'hide';
|
|
9
|
-
readonly alwaysExpand?: boolean;
|
|
10
|
-
readonly appLoader?: 'legacy' | 'universal';
|
|
11
|
-
readonly availableLocales: readonly string[];
|
|
12
|
-
readonly textLanguages?: readonly string[];
|
|
13
|
-
}>;
|
|
3
|
+
/** The validated user interface configuration; see {@link UiData | Ui} in `domain`. */
|
|
4
|
+
export type Ui = UiData;
|
|
14
5
|
export declare const Ui: (merged: MergedUi) => Ui;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as r,jsxs as e}from"react/jsx-runtime";import{I18nProvider as o}from"@lingui/react";import{QueryClientProvider as i}from"@tanstack/react-query";import n from"mui-modal-provider";import{useEffect as t}from"react";import{standardWebComponentProperties as c}from"#package/domain";import{getAvailableLocales as a,resolveLocale as m}from"#package/i18n";import{ApplicationType as l,ApplicationTypeProvider as d,
|
|
1
|
+
import{jsx as r,jsxs as e}from"react/jsx-runtime";import{I18nProvider as o}from"@lingui/react";import{QueryClientProvider as i}from"@tanstack/react-query";import n from"mui-modal-provider";import{useEffect as t}from"react";import{standardWebComponentProperties as c}from"#package/domain";import{getAvailableLocales as a,resolveLocale as m}from"#package/i18n";import{ApplicationType as l,ApplicationTypeProvider as d,ConfiguratorDataProvider as p,ConfiguratorRoutingProvider as s,InvalidDeploymentReload as f,LoaderHost as h,OnApplicationStartProvider as u,OnRoutingReadyProvider as x,OnSessionReadyProvider as g,PresetSelectionProvider as j,SessionServiceProvider as k,useApplicationQueryClient as b,useI18n as v,usePowerRoutingLifecycle as y,useSpecAlwaysExpand as C,useSpecAppLoader as w,useSpecPrefetchTextureUrls as E,useSpecPreview as I,useWebComponentProperty$ as L,useWebComponentPropertySetter as Z,useWebComponentPropertyValue as q}from"#package/react-sdk";import{SnackbarProvider as A}from"#package/ui-sdk";import{ConfiguratorResponsiveProvider as B}from"./configurator-context/ConfiguratorResponsiveProvider.js";import{PreviewApplicationProvider as F}from"./configurator-context/index.js";import{LoadingErrorBoundary as P}from"./pages/error-boundaries/LoadingErrorBoundary.js";import{GeneralErrorFallback as R,RootPage as S}from"./pages/index.js";import{SceneResourcesProvider as T}from"./scene/index.js";import{EncapsulatedConfiguratorTheme as U}from"./ui/index.js";import{AppLoader as z}from"./ui/phoenix-layout-elements/index.js";export const ConfiguratorApp=()=>{let D=b(),G=v(),H=w(),J=I(),K=C(),M=E(),N=Z(c.locale),O=L(c.locale);t(()=>{let r=O.subscribe(r=>{let e=m(r,a(G));G.activate(e)}),e=()=>{N(G.locale)};return G.on("change",e),()=>{r.unsubscribe(),G.removeListener("change",e)}},[O,G,N]);let Q=q(c.containerZIndex),V=q(c.power);return(y(),"off"===V)?null:r(d,{type:l.Configurator,children:r(i,{client:D,children:r(U,{children:r(h,{children:r(B,{containerZIndex:Q,children:r(z,{mode:H,children:r(F,{alwaysExpand:K,preview:J,children:r(o,{i18n:G,children:r(A,{maxSnack:5,children:r(P,{FallbackComponent:R,children:r(T,{prefetchTextureUrls:M,children:r(u,{children:r(k,{children:r(g,{children:"on"===V&&r(s,{children:r(p,{children:r(j,{children:r(x,{children:e(n,{children:[r(f,{}),r(S,{})]})})})})})})})})})})})})})})})})})})})};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ChatClient as e,fetchServerSentEvents as t}from"@tanstack/ai-client";import{BehaviorSubject as s}from"rxjs";import{skip as i}from"rxjs/operators";import{isShallowEqual as a}from"@salsita-ai/common/utils";import{AssistantRequestError as r}from"#package/client";import{createBrowserDetailsClientTool as n}from"./browser-details.js";import{ChangeRecorder as o}from"./change-recorder.js";import{createApplyClientTool as l,createQueryClientTool as h,toToolResult as d}from"./graphql-tools.js";let c=Object.freeze({messages:Object.freeze([]),isLoading:!1,error:void 0,failedStatus:void 0,isContinuable:!0,isLoaded:!1,isResuming:!1,earlierThreads:Object.freeze([]),hasEarlierThread:!1,isLoadingEarlierThread:!1}),u=Object.freeze({open:!1,hasUnreadReply:!1,isInputFocused:!1}),_=Object.freeze({}),g=d({results:[],committed:!1,sideEffects:[],screenshots:new Map,message:"Nothing was run, because the user closed the configurator while this reply was being written. Do not call any more tools in this reply and end it now. The tools work again as soon as the user writes the next message."}),f=e=>{if(e.getError())return!0;let t=e.getMessages().at(-1)?.parts.at(-1);return t?.type!=="tool-call"&&t?.type!=="tool-result"};export class AssistantSystem{_context;_tools;_chat=new s(c);_panel=new s(u);_activation=null;_current=null;_finishing=new Set;_olderThreadId=null;_resuming=null;_refused=null;_firstAttempt=null;_chain={};_loadingThreadId=null;_recorder;_recording=null;_applyToolCallIds=new WeakMap;_undoTipToolCallId=new s(void 0);_screenshotUrls=new Map;constructor(e){this._context=e;let{configuratorExtensionSelectors:t,domainContextSelectors:s,domainServicesSelectors:i,getAssistantSetup:a}=e;this._recorder=new o({maxEntities:30},{readers:{selectedEntityId:e=>s.getNavigationSystem().getActiveSelectionState(e),navigationState:e=>s.getNavigationSystem().getActiveNavigationState(e),viewState:e=>s.getNavigationSystem().getActiveViewState(e),toolState:e=>s.getNavigationSystem().getActiveToolState(e)},getExposedFields:()=>a().manifest?.fields??_,resolveLocalizable:e=>i.getResolveLocalizable()(e)});let r={getGraphQLSystem:()=>t.getGraphQLSystem(),getStoreSystem:()=>s.getStoreSystem(),getActiveMode:()=>s.getActiveMode(),getIsViewMode:()=>s.getIsViewMode(),clearChanges:()=>this._recorder.clear(this._committedState()),rememberCommit:(e,t)=>{this._applyToolCallIds.set(t,e),this._refreshUndoTip()}};this._tools=[n(),h(r),l(r)],s.getUndoSystem().tip$.subscribe(this._refreshUndoTip)}chat$=this._chat;panel$=this._panel;undoTipToolCallId$=this._undoTipToolCallId;getSessionManifest=()=>this._context.getAssistantSetup().manifest;initialize=()=>{let{committed:e}=this._context.domainContextSelectors.getStoreSystem().stateSlices;this._recording??=e.pipe(i(1)).subscribe(this._recorder.record),this._recorder.reset(e.value.state),this._endChat(),this._patchPanel(u),this._releaseScreenshotUrls(),this._activation&&this._startClient()};activate=()=>{this._endChat();let e={};return this._activation=e,this._startClient(),()=>{this._activation===e&&(this._activation=null,this._endChat())}};send=async e=>{if(!this._chat.value.isContinuable&&!await this.resume())return;let t=this._current;if(!t)return;let s={changes:this._recorder.take(this._committedState())};this._firstAttempt=t;try{await this._sendOn(t,e,s);let i=this._findRefusedMessageIndex(t);if(-1===i)return;this._refused={chat:t,index:i}}finally{this._firstAttempt===t&&(this._firstAttempt=null)}if(!await this.resume())return;let i=this._current;i&&await this._sendOn(i,e,s)};resume=async()=>{let e=this._current;if(!e)return!1;if(this._chat.value.isContinuable)return!0;if(this._resuming)return this._resuming;let t=this._resume(e).finally(()=>{this._resuming===t&&(this._resuming=null)});return this._resuming=t,t};loadScreenshotUrl=e=>{let t=this._screenshotUrls.get(e);if(t)return t;let s=this._current;if(!s)return Promise.reject(Error(`The screenshot ${e} cannot be read, because the assistant chat is not active. Open the assistant panel of the configuration first.`));let i=this._screenshotUrls,a=s.authorizedClient.getAssistantImage(s.configurationId,e).then(e=>URL.createObjectURL(e));return i.set(e,a),a.catch(()=>{i.get(e)===a&&i.delete(e)}),a};loadEarlierThread=async()=>{let e=this._current,t=this._olderThreadId;if(!e||null===t||this._loadingThreadId===t)return;let s=this._chain;this._loadingThreadId=t,this._chat.next({...this._chat.value,isLoadingEarlierThread:!0});try{let i=await e.authorizedClient.getAssistantEarlierThread(e.configurationId,t,50);if(this._chain!==s||this._olderThreadId!==t)return;this._olderThreadId=i.previousThreadId,this._chat.next({...this._chat.value,earlierThreads:[{threadId:t,messages:i.messages},...this._chat.value.earlierThreads],hasEarlierThread:null!==i.previousThreadId})}catch(e){this._context.domainServicesSelectors.getLogger().warn("Could not load the earlier assistant conversation",{error:e})}finally{this._chain===s&&this._loadingThreadId===t&&(this._loadingThreadId=null,this._chat.next({...this._chat.value,isLoadingEarlierThread:!1}))}};stop=async()=>{let e=this._current;if(!e)return;let t=e.client.getCurrentRunId();if(e.client.stop(),null!=t)try{let s=e.getConnection();await fetch(`${s.url}/runs/${encodeURIComponent(t)}/cancel`,{method:"POST",headers:await s.headers()})}catch(e){this._context.domainServicesSelectors.getLogger().warn("Could not cancel the assistant run on the server",{error:e})}};reloadThread=()=>{if(!this._activation)return;let e=this._retireChat();e?.client.stop(),e?.dispose(),this._recorder.reset(this._committedState()),this._startClient()};undoToolCalls=e=>{let t=this._context.domainContextSelectors.getUndoSystem(),s=()=>{let t=this._findTipToolCallId();return void 0!==t&&e.has(t)};for(;s();)t.undo()};setOpen=e=>{this._patchPanel(e?{open:e,hasUnreadReply:!1}:{open:e,isInputFocused:!1})};setInputFocused=e=>{this._patchPanel({isInputFocused:e})};_findRefusedMessageIndex=e=>{var t;let s,{failedStatus:i,isContinuable:a}=this._chat.value;return this._firstAttempt===e&&e.generation.active&&409===i&&!a?(s=(t=e.client.getMessages()).map(e=>e.role).lastIndexOf("user"),t.slice(s+1).every(e=>0===e.parts.length)?s:-1):-1};_sendOn=async(e,t,s)=>{let{client:i}=e;i.getIsLoading()||null===i.getResumeState()||i.stop();try{await i.sendMessage({content:t,metadata:s})}catch(s){let t=s instanceof Error?s:Error(String(s));e.generation.active&&this._chat.next({...this._chat.value,error:t}),this._context.domainServicesSelectors.getLogger().error("The assistant message could not be sent",{},t)}};_resume=async e=>{this._chat.next({...this._chat.value,isResuming:!0,error:void 0,failedStatus:void 0});try{let{previousThreadId:t}=await e.authorizedClient.compactAssistantThread(e.configurationId);if(!e.generation.active)return!1;let{messages:s,earlierThreads:i,hasEarlierThread:a}=this._chat.value,r=this._refused?.chat===e?s.slice(0,this._refused.index):s;return e.generation.active=!1,this._current=null,e.client.stop(),e.dispose(),this._chat.next({...c,earlierThreads:[...i,{threadId:t,messages:r}],hasEarlierThread:a,isLoadingEarlierThread:null!==this._loadingThreadId}),this._startClient(),!0}catch(s){let t=s instanceof Error?s:Error(String(s));if(t instanceof r&&409===t.status)return e.generation.active&&this.reloadThread(),!1;return e.generation.active&&this._chat.next({...this._chat.value,isResuming:!1,error:t,failedStatus:t instanceof r?t.status:void 0}),this._context.domainServicesSelectors.getLogger().error("The assistant thread could not be resumed",{},t),!1}};_findTipToolCallId=()=>{let e=this._context.domainContextSelectors.getUndoSystem(),t=e.tip$.value?.committedState;return void 0!==t&&e.canUndo()?this._applyToolCallIds.get(t):void 0};_refreshUndoTip=()=>{let e=this._findTipToolCallId();e!==this._undoTipToolCallId.value&&this._undoTipToolCallId.next(e)};_committedState=()=>this._context.domainContextSelectors.getStoreSystem().stateSlices.committed.value.state;_patchPanel=e=>{let t={...this._panel.value,...e};a(t,this._panel.value)||this._panel.next(t)};_takeOverThread=e=>{for(let t of this._finishing)t.configurationId===e&&(t.client.stop(),t.dispose())};_startClient=()=>{let s={active:!0},i=this._context.getConfigurationId();this._takeOverThread(i);let r=this._context.getAuthorizedClient(),n=()=>{if(s.active){let{manifest:e,error:t}=this._context.getAssistantSetup();if(t)throw t;if(!e)throw Error("The assistant is disabled for this session.")}return r.getAssistantChatConnection(i)},o=e=>{if(!s.active)return;let t={...this._chat.value,...e};a(t,this._chat.value)||this._chat.next(t)},l=async(e,t)=>{let i=await fetch(e,t).finally(()=>o({isLoaded:!0})),a=i.headers.get("x-assistant-thread-continuable");return null!=a&&i.ok&&s.active&&0===this._chat.value.earlierThreads.length&&(this._olderThreadId=i.headers.get("x-assistant-previous-thread")),o({failedStatus:i.ok?void 0:i.status,...null!=a&&{isContinuable:"false"!==a,hasEarlierThread:null!==this._olderThreadId}}),i},h=async()=>({headers:await n().headers(),fetchClient:l}),d=t(()=>n().url,h),c=t(()=>`${n().url}/runs`,h),u=this._tools.map(e=>({...e,execute:(t,i)=>{if(!s.active)return g;let{manifest:a,error:r}=this._context.getAssistantSetup();return r||!a?{error:r?.message??"The assistant is disabled for this session."}:e.execute?.(t,i)}})),_=new e({threadId:`assistant:${i}`,connection:{...d,joinRun:c.joinRun},persistence:!0,history:{pageSize:50},tools:u,onMessagesChange:e=>o({messages:e}),onLoadingChange:e=>{let t=s.active&&this._chat.value.isLoading;o({isLoading:e}),!e&&f(_)&&(s.active?t&&!this._panel.value.open&&this._patchPanel({hasUnreadReply:!0}):p())},onErrorChange:e=>{s.active&&e!==this._chat.value.error&&(!e||-1===this._findRefusedMessageIndex(v))&&(o({error:e}),e&&this._context.domainServicesSelectors.getLogger().error("The assistant request failed",{status:this._chat.value.failedStatus},e))}}),m=!1,p=()=>{m||(m=!0,this._finishing.delete(v),_.dispose())},v={client:_,configurationId:i,generation:s,authorizedClient:r,getConnection:n,dispose:p};this._current=v,_.attach()};_retireChat=()=>{let e=this._current;return this._current=null,e&&(e.generation.active=!1),this._chain={},this._olderThreadId=null,this._resuming=null,this._refused=null,this._loadingThreadId=null,this._chat.value!==c&&this._chat.next(c),e};_releaseScreenshotUrls=()=>{for(let e of this._screenshotUrls.values())e.then(URL.revokeObjectURL,()=>void 0);this._screenshotUrls=new Map};_endChat=()=>{let e=this._retireChat();if(e){if(!e.client.getIsLoading()&&f(e.client))return void e.dispose();this._finishing.add(e)}}}
|
|
1
|
+
import{ChatClient as e,fetchServerSentEvents as t}from"@tanstack/ai-client";import{BehaviorSubject as s}from"rxjs";import{skip as i}from"rxjs/operators";import{isShallowEqual as a}from"@salsita-ai/common/utils";import{AssistantRequestError as r}from"#package/client";import{createBrowserDetailsClientTool as n}from"./browser-details.js";import{ChangeRecorder as o}from"./change-recorder.js";import{createApplyClientTool as l,createQueryClientTool as h,toToolResult as d}from"./graphql-tools.js";let c=Object.freeze({messages:Object.freeze([]),isLoading:!1,error:void 0,failedStatus:void 0,isContinuable:!0,isLoaded:!1,isResuming:!1,earlierThreads:Object.freeze([]),hasEarlierThread:!1,isLoadingEarlierThread:!1}),u=Object.freeze({open:!1,hasUnreadReply:!1,isInputFocused:!1}),_=Object.freeze({}),g=d({results:[],committed:!1,sideEffects:[],warnings:[],screenshots:new Map,message:"Nothing was run, because the user closed the configurator while this reply was being written. Do not call any more tools in this reply and end it now. The tools work again as soon as the user writes the next message."}),f=e=>{if(e.getError())return!0;let t=e.getMessages().at(-1)?.parts.at(-1);return t?.type!=="tool-call"&&t?.type!=="tool-result"};export class AssistantSystem{_context;_tools;_chat=new s(c);_panel=new s(u);_activation=null;_current=null;_finishing=new Set;_olderThreadId=null;_resuming=null;_refused=null;_firstAttempt=null;_chain={};_loadingThreadId=null;_recorder;_recording=null;_applyToolCallIds=new WeakMap;_undoTipToolCallId=new s(void 0);_screenshotUrls=new Map;constructor(e){this._context=e;let{configuratorExtensionSelectors:t,domainContextSelectors:s,domainServicesSelectors:i,getAssistantSetup:a}=e;this._recorder=new o({maxEntities:30},{readers:{selectedEntityId:e=>s.getNavigationSystem().getActiveSelectionState(e),navigationState:e=>s.getNavigationSystem().getActiveNavigationState(e),viewState:e=>s.getNavigationSystem().getActiveViewState(e),toolState:e=>s.getNavigationSystem().getActiveToolState(e)},getExposedFields:()=>a().manifest?.fields??_,resolveLocalizable:e=>i.getResolveLocalizable()(e)});let r={getGraphQLSystem:()=>t.getGraphQLSystem(),getStoreSystem:()=>s.getStoreSystem(),getActiveMode:()=>s.getActiveMode(),getIsViewMode:()=>s.getIsViewMode(),clearChanges:()=>this._recorder.clear(this._committedState()),rememberCommit:(e,t)=>{this._applyToolCallIds.set(t,e),this._refreshUndoTip()}};this._tools=[n(),h(r),l(r)],s.getUndoSystem().tip$.subscribe(this._refreshUndoTip)}chat$=this._chat;panel$=this._panel;undoTipToolCallId$=this._undoTipToolCallId;getSessionManifest=()=>this._context.getAssistantSetup().manifest;initialize=()=>{let{committed:e}=this._context.domainContextSelectors.getStoreSystem().stateSlices;this._recording??=e.pipe(i(1)).subscribe(this._recorder.record),this._recorder.reset(e.value.state),this._endChat(),this._patchPanel(u),this._releaseScreenshotUrls(),this._activation&&this._startClient()};activate=()=>{this._endChat();let e={};return this._activation=e,this._startClient(),()=>{this._activation===e&&(this._activation=null,this._endChat())}};send=async e=>{if(!this._chat.value.isContinuable&&!await this.resume())return;let t=this._current;if(!t)return;let s={changes:this._recorder.take(this._committedState())};this._firstAttempt=t;try{await this._sendOn(t,e,s);let i=this._findRefusedMessageIndex(t);if(-1===i)return;this._refused={chat:t,index:i}}finally{this._firstAttempt===t&&(this._firstAttempt=null)}if(!await this.resume())return;let i=this._current;i&&await this._sendOn(i,e,s)};resume=async()=>{let e=this._current;if(!e)return!1;if(this._chat.value.isContinuable)return!0;if(this._resuming)return this._resuming;let t=this._resume(e).finally(()=>{this._resuming===t&&(this._resuming=null)});return this._resuming=t,t};loadScreenshotUrl=e=>{let t=this._screenshotUrls.get(e);if(t)return t;let s=this._current;if(!s)return Promise.reject(Error(`The screenshot ${e} cannot be read, because the assistant chat is not active. Open the assistant panel of the configuration first.`));let i=this._screenshotUrls,a=s.authorizedClient.getAssistantImage(s.configurationId,e).then(e=>URL.createObjectURL(e));return i.set(e,a),a.catch(()=>{i.get(e)===a&&i.delete(e)}),a};loadEarlierThread=async()=>{let e=this._current,t=this._olderThreadId;if(!e||null===t||this._loadingThreadId===t)return;let s=this._chain;this._loadingThreadId=t,this._chat.next({...this._chat.value,isLoadingEarlierThread:!0});try{let i=await e.authorizedClient.getAssistantEarlierThread(e.configurationId,t,50);if(this._chain!==s||this._olderThreadId!==t)return;this._olderThreadId=i.previousThreadId,this._chat.next({...this._chat.value,earlierThreads:[{threadId:t,messages:i.messages},...this._chat.value.earlierThreads],hasEarlierThread:null!==i.previousThreadId})}catch(e){this._context.domainServicesSelectors.getLogger().warn("Could not load the earlier assistant conversation",{error:e})}finally{this._chain===s&&this._loadingThreadId===t&&(this._loadingThreadId=null,this._chat.next({...this._chat.value,isLoadingEarlierThread:!1}))}};stop=async()=>{let e=this._current;if(!e)return;let t=e.client.getCurrentRunId();if(e.client.stop(),null!=t)try{let s=e.getConnection();await fetch(`${s.url}/runs/${encodeURIComponent(t)}/cancel`,{method:"POST",headers:await s.headers()})}catch(e){this._context.domainServicesSelectors.getLogger().warn("Could not cancel the assistant run on the server",{error:e})}};reloadThread=()=>{if(!this._activation)return;let e=this._retireChat();e?.client.stop(),e?.dispose(),this._recorder.reset(this._committedState()),this._startClient()};undoToolCalls=e=>{let t=this._context.domainContextSelectors.getUndoSystem(),s=()=>{let t=this._findTipToolCallId();return void 0!==t&&e.has(t)};for(;s();)t.undo()};setOpen=e=>{this._patchPanel(e?{open:e,hasUnreadReply:!1}:{open:e,isInputFocused:!1})};setInputFocused=e=>{this._patchPanel({isInputFocused:e})};_findRefusedMessageIndex=e=>{var t;let s,{failedStatus:i,isContinuable:a}=this._chat.value;return this._firstAttempt===e&&e.generation.active&&409===i&&!a?(s=(t=e.client.getMessages()).map(e=>e.role).lastIndexOf("user"),t.slice(s+1).every(e=>0===e.parts.length)?s:-1):-1};_sendOn=async(e,t,s)=>{let{client:i}=e;i.getIsLoading()||null===i.getResumeState()||i.stop();try{await i.sendMessage({content:t,metadata:s})}catch(s){let t=s instanceof Error?s:Error(String(s));e.generation.active&&this._chat.next({...this._chat.value,error:t}),this._context.domainServicesSelectors.getLogger().error("The assistant message could not be sent",{},t)}};_resume=async e=>{this._chat.next({...this._chat.value,isResuming:!0,error:void 0,failedStatus:void 0});try{let{previousThreadId:t}=await e.authorizedClient.compactAssistantThread(e.configurationId);if(!e.generation.active)return!1;let{messages:s,earlierThreads:i,hasEarlierThread:a}=this._chat.value,r=this._refused?.chat===e?s.slice(0,this._refused.index):s;return e.generation.active=!1,this._current=null,e.client.stop(),e.dispose(),this._chat.next({...c,earlierThreads:[...i,{threadId:t,messages:r}],hasEarlierThread:a,isLoadingEarlierThread:null!==this._loadingThreadId}),this._startClient(),!0}catch(s){let t=s instanceof Error?s:Error(String(s));if(t instanceof r&&409===t.status)return e.generation.active&&this.reloadThread(),!1;return e.generation.active&&this._chat.next({...this._chat.value,isResuming:!1,error:t,failedStatus:t instanceof r?t.status:void 0}),this._context.domainServicesSelectors.getLogger().error("The assistant thread could not be resumed",{},t),!1}};_findTipToolCallId=()=>{let e=this._context.domainContextSelectors.getUndoSystem(),t=e.tip$.value?.committedState;return void 0!==t&&e.canUndo()?this._applyToolCallIds.get(t):void 0};_refreshUndoTip=()=>{let e=this._findTipToolCallId();e!==this._undoTipToolCallId.value&&this._undoTipToolCallId.next(e)};_committedState=()=>this._context.domainContextSelectors.getStoreSystem().stateSlices.committed.value.state;_patchPanel=e=>{let t={...this._panel.value,...e};a(t,this._panel.value)||this._panel.next(t)};_takeOverThread=e=>{for(let t of this._finishing)t.configurationId===e&&(t.client.stop(),t.dispose())};_startClient=()=>{let s={active:!0},i=this._context.getConfigurationId();this._takeOverThread(i);let r=this._context.getAuthorizedClient(),n=()=>{if(s.active){let{manifest:e,error:t}=this._context.getAssistantSetup();if(t)throw t;if(!e)throw Error("The assistant is disabled for this session.")}return r.getAssistantChatConnection(i)},o=e=>{if(!s.active)return;let t={...this._chat.value,...e};a(t,this._chat.value)||this._chat.next(t)},l=async(e,t)=>{let i=await fetch(e,t).finally(()=>o({isLoaded:!0})),a=i.headers.get("x-assistant-thread-continuable");return null!=a&&i.ok&&s.active&&0===this._chat.value.earlierThreads.length&&(this._olderThreadId=i.headers.get("x-assistant-previous-thread")),o({failedStatus:i.ok?void 0:i.status,...null!=a&&{isContinuable:"false"!==a,hasEarlierThread:null!==this._olderThreadId}}),i},h=async()=>({headers:await n().headers(),fetchClient:l}),d=t(()=>n().url,h),c=t(()=>`${n().url}/runs`,h),u=this._tools.map(e=>({...e,execute:(t,i)=>{if(!s.active)return g;let{manifest:a,error:r}=this._context.getAssistantSetup();return r||!a?{error:r?.message??"The assistant is disabled for this session."}:e.execute?.(t,i)}})),_=new e({threadId:`assistant:${i}`,connection:{...d,joinRun:c.joinRun},persistence:!0,history:{pageSize:50},tools:u,onMessagesChange:e=>o({messages:e}),onLoadingChange:e=>{let t=s.active&&this._chat.value.isLoading;o({isLoading:e}),!e&&f(_)&&(s.active?t&&!this._panel.value.open&&this._patchPanel({hasUnreadReply:!0}):p())},onErrorChange:e=>{s.active&&e!==this._chat.value.error&&(!e||-1===this._findRefusedMessageIndex(v))&&(o({error:e}),e&&this._context.domainServicesSelectors.getLogger().error("The assistant request failed",{status:this._chat.value.failedStatus},e))}}),m=!1,p=()=>{m||(m=!0,this._finishing.delete(v),_.dispose())},v={client:_,configurationId:i,generation:s,authorizedClient:r,getConnection:n,dispose:p};this._current=v,_.attach()};_retireChat=()=>{let e=this._current;return this._current=null,e&&(e.generation.active=!1),this._chain={},this._olderThreadId=null,this._resuming=null,this._refused=null,this._loadingThreadId=null,this._chat.value!==c&&this._chat.next(c),e};_releaseScreenshotUrls=()=>{for(let e of this._screenshotUrls.values())e.then(URL.revokeObjectURL,()=>void 0);this._screenshotUrls=new Map};_endChat=()=>{let e=this._retireChat();if(e){if(!e.client.getIsLoading()&&f(e.client))return void e.dispose();this._finishing.add(e)}}}
|
package/dist/configurator/application-runtime/extensions/systems/assistant-system/graphql-tools.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type { GraphQLExecution, GraphQLSystem } from '../graphql-system/graphql-
|
|
|
7
7
|
* mode current at that moment, never against ones captured when its reply began streaming.
|
|
8
8
|
*/
|
|
9
9
|
export interface AssistantToolDependencies {
|
|
10
|
-
readonly getGraphQLSystem: () => Pick<GraphQLSystem, 'prepare' | 'execute' | 'readSideEffects' | 'readScreenshots'>;
|
|
10
|
+
readonly getGraphQLSystem: () => Pick<GraphQLSystem, 'prepare' | 'execute' | 'readSideEffects' | 'readWarnings' | 'readScreenshots'>;
|
|
11
11
|
readonly getStoreSystem: () => {
|
|
12
12
|
readonly isInitialized: boolean;
|
|
13
13
|
readonly stateSlices: {
|
|
@@ -45,12 +45,16 @@ export declare const toToolResult: ({ preparedState, screenshots, ...execution }
|
|
|
45
45
|
/**
|
|
46
46
|
* Browser implementation of the assistant's `query` tool: prepares the operations from the
|
|
47
47
|
* committed state and drops their emissions, so mutations in the list show a hypothetical state and
|
|
48
|
-
* the configuration, the undo stack and the saved revision stay as they were. The side effects
|
|
49
|
-
* the dropped emissions are still reported, as what the changes would do.
|
|
48
|
+
* the configuration, the undo stack and the saved revision stay as they were. The side effects and
|
|
49
|
+
* the new warnings of the dropped emissions are still reported, as what the changes would do.
|
|
50
50
|
*/
|
|
51
51
|
export declare const createQueryClientTool: (dependencies: AssistantToolDependencies) => import("@tanstack/ai").ClientTool<{
|
|
52
52
|
type: string;
|
|
53
53
|
properties: {
|
|
54
|
+
title: {
|
|
55
|
+
type: string;
|
|
56
|
+
description: string;
|
|
57
|
+
};
|
|
54
58
|
operations: {
|
|
55
59
|
type: string;
|
|
56
60
|
minItems: number;
|
|
@@ -80,6 +84,10 @@ export declare const createQueryClientTool: (dependencies: AssistantToolDependen
|
|
|
80
84
|
inputSchema: {
|
|
81
85
|
type: string;
|
|
82
86
|
properties: {
|
|
87
|
+
title: {
|
|
88
|
+
type: string;
|
|
89
|
+
description: string;
|
|
90
|
+
};
|
|
83
91
|
operations: {
|
|
84
92
|
type: string;
|
|
85
93
|
minItems: number;
|
|
@@ -133,6 +141,10 @@ export declare const createQueryClientTool: (dependencies: AssistantToolDependen
|
|
|
133
141
|
export declare const createApplyClientTool: (dependencies: AssistantToolDependencies) => import("@tanstack/ai").ClientTool<{
|
|
134
142
|
type: string;
|
|
135
143
|
properties: {
|
|
144
|
+
title: {
|
|
145
|
+
type: string;
|
|
146
|
+
description: string;
|
|
147
|
+
};
|
|
136
148
|
operations: {
|
|
137
149
|
type: string;
|
|
138
150
|
minItems: number;
|
|
@@ -162,6 +174,10 @@ export declare const createApplyClientTool: (dependencies: AssistantToolDependen
|
|
|
162
174
|
inputSchema: {
|
|
163
175
|
type: string;
|
|
164
176
|
properties: {
|
|
177
|
+
title: {
|
|
178
|
+
type: string;
|
|
179
|
+
description: string;
|
|
180
|
+
};
|
|
165
181
|
operations: {
|
|
166
182
|
type: string;
|
|
167
183
|
minItems: number;
|
package/dist/configurator/application-runtime/extensions/systems/assistant-system/graphql-tools.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AssistantGraphQLToolInput as e,applyTool as t,assistantImageReference as o,queryTool as
|
|
1
|
+
import{AssistantGraphQLToolInput as e,applyTool as t,assistantImageReference as o,queryTool as a}from"@salsita-ai/contracts/assistant";let i=e=>({results:[],committed:!1,message:e,sideEffects:[],screenshots:new Map,warnings:[]});export const toToolResult=({preparedState:e,screenshots:t,...a})=>[{type:"text",content:JSON.stringify(a)},...[...t].flatMap(([e,{imageId:t}])=>[{type:"text",content:e},{type:"image",source:{type:"url",value:o(t)}}])];let s=t=>{let o=e.safeParse(t);if(!o.success){let e=o.error.issues.map(e=>`${e.path.join(".")}: ${e.message}`).join("; ");return{ok:!1,refusal:i(`Nothing was run, because the tool input is not a list of operations (${e}). Send { "operations": [{ "query": "<one GraphQL operation>" }] } with at least one item.`)}}return{ok:!0,operations:o.data.operations.map(({query:e,variables:t,operationName:o})=>({document:e,variables:t??void 0,operationName:o??void 0}))}};export const createQueryClientTool=e=>a.client(async t=>{let o=s(t);if(!o.ok)return toToolResult(o.refusal);let a=e.getStoreSystem();if(!a.isInitialized)return toToolResult(i("Nothing was run, because the configuration is not loaded yet, so there is no state to query. Call the tool again once the configurator has finished loading."));let n=e.getGraphQLSystem(),r=a.stateSlices.committed.value.state,l=await n.prepare(r,o.operations);return toToolResult({results:l.map(({result:e})=>e),committed:!1,sideEffects:n.readSideEffects(l),screenshots:n.readScreenshots(l),warnings:n.readWarnings(r,l)})});export const createApplyClientTool=e=>t.client(async(t,o)=>{if("finalize"===e.getActiveMode())return toToolResult(i("Nothing was run, because changes cannot be applied in this session: the user may view this configuration but not change it. The query tool still works here, including mutations, to show what a change would do without keeping it."));if(e.getIsViewMode())return toToolResult(i("Nothing was run, because the configuration is read-only right now: the user may view it but not change it. The query tool still works here, including mutations, to show what a change would do without keeping it. Call apply again only once the configuration is editable."));let a=s(t);if(!a.ok)return toToolResult(a.refusal);let n=await e.getGraphQLSystem().execute(a.operations),r=o?.toolCallId;return void 0!==r&&void 0!==n.preparedState&&e.rememberCommit(r,n.preparedState),n.committed&&e.clearChanges(),toToolResult(n)});
|
package/dist/configurator/application-runtime/extensions/systems/graphql-system/entity-meta.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type $DomainEntity, type AssistantManifest, type AssistantRecipeContext, type DomainEntity, type DomainEntityId, type DomainState, type
|
|
1
|
+
import { type $DomainEntity, type AssistantManifest, type AssistantRecipeContext, type DomainEntity, type DomainEntityId, type DomainState, type StateUpdate, type StateUpdateEmission, type StateValidationResult } from '#package/domain';
|
|
2
|
+
import { type ViolationEntry } from './violations.js';
|
|
2
3
|
type AnyDomainState = DomainState<DomainEntity<string>>;
|
|
3
4
|
type AnyStateUpdate = StateUpdate<DomainEntity<string>, DomainEntity<string>>;
|
|
4
5
|
/** An entity and the state it was read on, which everything under its `meta` field resolves against. */
|
|
@@ -27,76 +28,89 @@ export interface EntityMetaContext {
|
|
|
27
28
|
readonly takeScreenshot: (source: EntityMetaSource, view: string) => Promise<{
|
|
28
29
|
readonly image: string;
|
|
29
30
|
} | null>;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
readonly
|
|
35
|
-
readonly message: string | null;
|
|
31
|
+
/**
|
|
32
|
+
* Validates a state: the one an entity was read on, for its warnings, or the one a dry-run ran on,
|
|
33
|
+
* whose warnings the dry-run's own are compared with.
|
|
34
|
+
*/
|
|
35
|
+
readonly validateState: (state: AnyDomainState) => StateValidationResult<DomainEntity<string>, string>;
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
38
|
* The value of an entity's `meta` field: its built-ins, resolved lazily against the state the entity
|
|
39
|
-
* was read on. `childRecipes` and `replaceRecipes`
|
|
40
|
-
*
|
|
41
|
-
* `
|
|
39
|
+
* was read on. `childRecipes` and `replaceRecipes` hold one field per manifest recipe group of their
|
|
40
|
+
* kind, read only when selected, `null` when the group is not active on the entity there; each
|
|
41
|
+
* options edge lists the choices of its field there, or `null` when its component is not active;
|
|
42
|
+
* `screenshot` renders the entity there, and `warnings` lists the warnings and notices the entity holds there.
|
|
42
43
|
*/
|
|
43
44
|
export declare const createEntityMeta: (source: EntityMetaSource, context: EntityMetaContext) => {
|
|
44
45
|
childRecipes: () => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
description: string | null;
|
|
48
|
-
recipes: {
|
|
49
|
-
key: string;
|
|
46
|
+
[k: string]: () => {
|
|
47
|
+
groupId: string;
|
|
50
48
|
name: string;
|
|
51
49
|
description: string | null;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
50
|
+
recipes: ({ keys }: {
|
|
51
|
+
readonly keys?: readonly string[] | null;
|
|
52
|
+
}) => {
|
|
53
|
+
key: string;
|
|
54
|
+
name: string;
|
|
55
|
+
description: string | null;
|
|
56
|
+
imageUrl: string | null;
|
|
57
|
+
dryRun: () => {
|
|
58
|
+
ok: boolean;
|
|
59
|
+
root: null;
|
|
60
|
+
changedEntities: never[];
|
|
61
|
+
deletedEntityIds: never[];
|
|
62
|
+
sideEffects: never[];
|
|
63
|
+
warnings: never[];
|
|
64
|
+
errors: readonly ViolationEntry[];
|
|
65
|
+
} | {
|
|
66
|
+
ok: boolean;
|
|
67
|
+
root: unknown;
|
|
68
|
+
changedEntities: {}[];
|
|
69
|
+
deletedEntityIds: DomainEntityId<string>[];
|
|
70
|
+
sideEffects: readonly string[];
|
|
71
|
+
warnings: () => readonly import("./violations.js").AssistantWarning[];
|
|
72
|
+
errors: never[];
|
|
73
|
+
} | null;
|
|
74
|
+
}[];
|
|
75
|
+
} | null;
|
|
76
|
+
};
|
|
70
77
|
replaceRecipes: () => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
description: string | null;
|
|
74
|
-
recipes: {
|
|
75
|
-
key: string;
|
|
78
|
+
[k: string]: () => {
|
|
79
|
+
groupId: string;
|
|
76
80
|
name: string;
|
|
77
81
|
description: string | null;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
82
|
+
recipes: ({ keys }: {
|
|
83
|
+
readonly keys?: readonly string[] | null;
|
|
84
|
+
}) => {
|
|
85
|
+
key: string;
|
|
86
|
+
name: string;
|
|
87
|
+
description: string | null;
|
|
88
|
+
imageUrl: string | null;
|
|
89
|
+
dryRun: () => {
|
|
90
|
+
ok: boolean;
|
|
91
|
+
root: null;
|
|
92
|
+
changedEntities: never[];
|
|
93
|
+
deletedEntityIds: never[];
|
|
94
|
+
sideEffects: never[];
|
|
95
|
+
warnings: never[];
|
|
96
|
+
errors: readonly ViolationEntry[];
|
|
97
|
+
} | {
|
|
98
|
+
ok: boolean;
|
|
99
|
+
root: unknown;
|
|
100
|
+
changedEntities: {}[];
|
|
101
|
+
deletedEntityIds: DomainEntityId<string>[];
|
|
102
|
+
sideEffects: readonly string[];
|
|
103
|
+
warnings: () => readonly import("./violations.js").AssistantWarning[];
|
|
104
|
+
errors: never[];
|
|
105
|
+
} | null;
|
|
106
|
+
}[];
|
|
107
|
+
} | null;
|
|
108
|
+
};
|
|
96
109
|
screenshot: ({ view }: {
|
|
97
110
|
readonly view: string;
|
|
98
111
|
}) => Promise<{
|
|
99
112
|
readonly image: string;
|
|
100
113
|
} | null>;
|
|
114
|
+
warnings: () => readonly import("./violations.js").AssistantWarning[];
|
|
101
115
|
};
|
|
102
116
|
export {};
|