@happyvertical/smrt-planner 0.57.5 → 0.57.7
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/agents/assistant.md +29 -2
- package/agents/shell.md +13 -0
- package/app/404.html +27 -30
- package/app/_app/immutable/assets/0.BaRFeYGU.css +1 -0
- package/app/_app/immutable/assets/AppShell.BkKNrxND.css +1 -0
- package/app/_app/immutable/assets/{ModelPage.FEM0ZnPM.css → ModelPage.SIoeO-AU.css} +1 -1
- package/app/_app/immutable/assets/app.BHwMQ9Zv.css +1 -0
- package/app/_app/immutable/assets/{forms.DXOeP4wZ.css → forms.BRdbPdvs.css} +1 -1
- package/app/_app/immutable/assets/icons.BDx21rPt.css +1 -0
- package/app/_app/immutable/assets/labels.Dxa6EyRI.css +1 -0
- package/app/_app/immutable/assets/planner.DOQVfcOi.css +1 -0
- package/app/_app/immutable/assets/state.C0UZEhxS.css +1 -0
- package/app/_app/immutable/chunks/{C1VofLtR.js → B2uXaQfZ.js} +1 -1
- package/app/_app/immutable/chunks/{DuZeZzOA.js → BQLQsso4.js} +1 -1
- package/app/_app/immutable/chunks/BdOPgmQ_.js +11 -0
- package/app/_app/immutable/chunks/BeL8dJx9.js +4 -0
- package/app/_app/immutable/chunks/{Bal1oPZu.js → Bhd-3niN.js} +1 -1
- package/app/_app/immutable/chunks/{CTlMHIE6.js → BqEBz5Vq.js} +1 -1
- package/app/_app/immutable/chunks/{GdHEbDDH.js → BxyJ_Q7v.js} +1 -1
- package/app/_app/immutable/chunks/{C3sRGrYK.js → C2OYATC6.js} +1 -1
- package/app/_app/immutable/chunks/C6AANt9H.js +26 -0
- package/app/_app/immutable/chunks/{BybfWt-B.js → C8FX0hli.js} +6 -6
- package/app/_app/immutable/chunks/{BDbFl7UA.js → CYhwv6d2.js} +1 -1
- package/app/_app/immutable/chunks/CdKHckEF.js +1 -0
- package/app/_app/immutable/chunks/CsaWd8kG.js +2 -0
- package/app/_app/immutable/chunks/Cwz7QFS4.js +2 -0
- package/app/_app/immutable/chunks/{BG9Gz_25.js → D3lXu_rt.js} +25 -25
- package/app/_app/immutable/chunks/{YGONf0jr.js → D8MqcCKq.js} +1 -1
- package/app/_app/immutable/chunks/DF-0MxNw.js +1 -0
- package/app/_app/immutable/chunks/DGaFQflg.js +1 -0
- package/app/_app/immutable/chunks/DIE02RSm.js +1 -0
- package/app/_app/immutable/chunks/DIgo5ngo.js +1 -0
- package/app/_app/immutable/chunks/{5ukUzDcw.js → Db12RzZi.js} +1 -1
- package/app/_app/immutable/chunks/{Cga8zF3r.js → DfN2k_EX.js} +1 -1
- package/app/_app/immutable/chunks/DmHVTNcC.js +4 -0
- package/app/_app/immutable/chunks/{gCpxN2IC.js → DmdvNG82.js} +2 -2
- package/app/_app/immutable/chunks/{DjJovMrk.js → DwIRC3h5.js} +1 -1
- package/app/_app/immutable/chunks/{nphy1MQF.js → FeyhlLIZ.js} +1 -1
- package/app/_app/immutable/chunks/ICDFUCZL.js +2 -0
- package/app/_app/immutable/chunks/IDZmjRDr.js +1 -0
- package/app/_app/immutable/chunks/JqlEoPqZ.js +1 -0
- package/app/_app/immutable/chunks/{BiEOJeYb.js → TcjpRcdI.js} +1 -1
- package/app/_app/immutable/chunks/Vt9hDpHd.js +1 -0
- package/app/_app/immutable/chunks/ezs6CGyc.js +1 -0
- package/app/_app/immutable/chunks/lUJaueNM.js +16 -0
- package/app/_app/immutable/entry/app.C5bxPKCP.js +2 -0
- package/app/_app/immutable/entry/start.CZvO61qD.js +1 -0
- package/app/_app/immutable/nodes/0.DFJFBCCB.js +7 -0
- package/app/_app/immutable/nodes/{1.DKP901Gn.js → 1.D_79m87b.js} +1 -1
- package/app/_app/immutable/nodes/{10.DNN0cVai.js → 10.20u2-jxn.js} +1 -1
- package/app/_app/immutable/nodes/{11.DgbmegX3.js → 11.CvMq32jC.js} +1 -1
- package/app/_app/immutable/nodes/{12.D5MtnJoE.js → 12.Cd0cy1AC.js} +1 -1
- package/app/_app/immutable/nodes/{13._rY66Xa_.js → 13.DYYS3YVQ.js} +1 -1
- package/app/_app/immutable/nodes/14.BEf5BJDn.js +1 -0
- package/app/_app/immutable/nodes/2.C_kLkHNl.js +24 -0
- package/app/_app/immutable/nodes/{3.V5uGCpGb.js → 3.CZw3hv8O.js} +1 -1
- package/app/_app/immutable/nodes/{4.CCwzLrgu.js → 4.WMU9NDex.js} +1 -1
- package/app/_app/immutable/nodes/{5.CgHzwpns.js → 5.CuqxSfl4.js} +1 -1
- package/app/_app/immutable/nodes/{6.CvQHLh_u.js → 6.BXLQB7tR.js} +1 -1
- package/app/_app/immutable/nodes/{7.7EIrly34.js → 7.BZvxNeL2.js} +1 -1
- package/app/_app/immutable/nodes/{8.DyyRBuTw.js → 8.Bj2O4pyx.js} +1 -1
- package/app/_app/immutable/nodes/{9.DcURs0gN.js → 9.yeFzeUHj.js} +1 -1
- package/app/_app/version.json +1 -1
- package/app/advanced-styles/index.html +34 -35
- package/app/ai/index.html +39 -40
- package/app/blueprint/index.html +29 -32
- package/app/cookbook/index.html +29 -32
- package/app/index.html +39 -42
- package/app/m/ads/AdDeliveryTier/index.html +36 -37
- package/app/m/ads/AdEvent/index.html +36 -37
- package/app/m/ads/AdFormat/index.html +36 -37
- package/app/m/ads/AdGroup/index.html +36 -37
- package/app/m/ads/AdVariation/index.html +36 -37
- package/app/m/analytics/AnalyticsDataStream/index.html +36 -37
- package/app/m/analytics/AnalyticsEvent/index.html +36 -37
- package/app/m/analytics/AnalyticsProperty/index.html +36 -37
- package/app/m/analytics/AnalyticsReport/index.html +36 -37
- package/app/m/approvals/ApprovalEvent/index.html +36 -37
- package/app/m/approvals/ApprovalPolicy/index.html +36 -37
- package/app/m/approvals/ApprovalRequest/index.html +36 -37
- package/app/m/assets/Asset/attachments/index.html +38 -39
- package/app/m/assets/Asset/index.html +36 -37
- package/app/m/assets/AssetAssociation/index.html +36 -37
- package/app/m/assets/AssetMetafield/index.html +36 -37
- package/app/m/assets/AssetStatus/index.html +36 -37
- package/app/m/assets/AssetType/index.html +36 -37
- package/app/m/assets/Folder/index.html +36 -37
- package/app/m/chat/AgentSession/index.html +36 -37
- package/app/m/chat/ChatMessage/index.html +36 -37
- package/app/m/chat/ChatParticipant/index.html +36 -37
- package/app/m/chat/ChatReaction/index.html +36 -37
- package/app/m/chat/ChatRoom/index.html +36 -37
- package/app/m/chat/ChatThread/index.html +36 -37
- package/app/m/chat/VoiceGatewayTurn/index.html +36 -37
- package/app/m/chat/VoiceSession/index.html +36 -37
- package/app/m/commerce/Agreement/index.html +36 -37
- package/app/m/commerce/Cart/index.html +36 -37
- package/app/m/commerce/Contract/index.html +36 -37
- package/app/m/commerce/ContractLineItem/index.html +36 -37
- package/app/m/commerce/Customer/index.html +36 -37
- package/app/m/commerce/DocumentTax/index.html +36 -37
- package/app/m/commerce/Estimate/index.html +36 -37
- package/app/m/commerce/Fulfillment/index.html +36 -37
- package/app/m/commerce/FulfillmentLineItem/index.html +36 -37
- package/app/m/commerce/HistoricalCustomerFunds/index.html +36 -37
- package/app/m/commerce/HistoricalCustomerFundsAllocation/index.html +36 -37
- package/app/m/commerce/HistoricalSalesLine/index.html +36 -37
- package/app/m/commerce/Invoice/index.html +36 -37
- package/app/m/commerce/InvoiceLineItem/index.html +36 -37
- package/app/m/commerce/Lease/index.html +36 -37
- package/app/m/commerce/LicenseSale/index.html +36 -37
- package/app/m/commerce/Order/index.html +36 -37
- package/app/m/commerce/Payment/index.html +36 -37
- package/app/m/commerce/PaymentAllocation/index.html +36 -37
- package/app/m/commerce/PaymentInstrument/index.html +36 -37
- package/app/m/commerce/PaymentIntent/index.html +36 -37
- package/app/m/commerce/Payout/index.html +36 -37
- package/app/m/commerce/ProductionOrder/index.html +36 -37
- package/app/m/commerce/PurchaseContract/index.html +36 -37
- package/app/m/commerce/PurchaseOrder/index.html +36 -37
- package/app/m/commerce/SalesContract/index.html +36 -37
- package/app/m/commerce/SupplierQuote/index.html +36 -37
- package/app/m/commerce/TaxCode/index.html +36 -37
- package/app/m/commerce/TaxComponent/index.html +36 -37
- package/app/m/commerce/TaxSettings/index.html +36 -37
- package/app/m/commerce/TaxSummaryReport/index.html +36 -37
- package/app/m/commerce/Vendor/index.html +36 -37
- package/app/m/commerce/WholesaleOrder/index.html +36 -37
- package/app/m/content/Content/index.html +36 -37
- package/app/m/content/ContentContribution/index.html +36 -37
- package/app/m/content/ContentContributionAttachment/index.html +36 -37
- package/app/m/content/ContentContributionRevision/index.html +36 -37
- package/app/m/content/ContentContributionType/index.html +36 -37
- package/app/m/content/ContentContributor/index.html +36 -37
- package/app/m/content/ContentCorrection/index.html +36 -37
- package/app/m/content/ContentFeedSource/index.html +36 -37
- package/app/m/content/ContentGovernanceAssignment/index.html +36 -37
- package/app/m/content/ContentGovernancePolicy/index.html +36 -37
- package/app/m/content/ContentGovernanceProfile/index.html +36 -37
- package/app/m/content/ContentReference/index.html +36 -37
- package/app/m/content/ContentReview/index.html +36 -37
- package/app/m/content/ContentVersion/index.html +36 -37
- package/app/m/events/Event/index.html +36 -37
- package/app/m/events/EventParticipant/index.html +36 -37
- package/app/m/events/EventSeries/index.html +36 -37
- package/app/m/events/EventType/index.html +36 -37
- package/app/m/expenses/Expense/index.html +36 -37
- package/app/m/facts/Fact/index.html +36 -37
- package/app/m/facts/FactContent/index.html +36 -37
- package/app/m/facts/FactEvidence/index.html +36 -37
- package/app/m/facts/FactSource/index.html +36 -37
- package/app/m/facts/FactSubject/index.html +36 -37
- package/app/m/facts/FactTag/index.html +36 -37
- package/app/m/fields/FieldPolicy/index.html +36 -37
- package/app/m/fields/FieldPolicySuggestion/index.html +36 -37
- package/app/m/fields/FieldUsageCounter/index.html +36 -37
- package/app/m/images/Image/index.html +36 -37
- package/app/m/inventory/InventoryLocation/index.html +36 -37
- package/app/m/inventory/StockLevel/index.html +36 -37
- package/app/m/inventory/StockMovement/index.html +36 -37
- package/app/m/ledgers/Account/index.html +36 -37
- package/app/m/ledgers/Journal/index.html +36 -37
- package/app/m/ledgers/JournalEntry/index.html +36 -37
- package/app/m/ledgers/Ledger/index.html +36 -37
- package/app/m/manufacturing/Assembly/index.html +36 -37
- package/app/m/manufacturing/BillOfMaterials/index.html +36 -37
- package/app/m/manufacturing/BomLine/index.html +36 -37
- package/app/m/manufacturing/Operation/index.html +36 -37
- package/app/m/manufacturing/ProductionRun/index.html +36 -37
- package/app/m/manufacturing/ProductionRunCompletion/index.html +36 -37
- package/app/m/manufacturing/RoutingStep/index.html +36 -37
- package/app/m/marketing/Campaign/index.html +36 -37
- package/app/m/marketing/CampaignChannel/index.html +36 -37
- package/app/m/marketing/CampaignMetricSnapshot/index.html +36 -37
- package/app/m/messages/Account/index.html +36 -37
- package/app/m/messages/Attachment/index.html +36 -37
- package/app/m/messages/Blacklist/index.html +36 -37
- package/app/m/messages/Email/failed-sends/index.html +38 -39
- package/app/m/messages/Email/index.html +36 -37
- package/app/m/messages/Email/mailbox/index.html +38 -39
- package/app/m/messages/EmailAccount/index.html +36 -37
- package/app/m/messages/EmailAttachment/index.html +36 -37
- package/app/m/messages/EmailFolder/index.html +36 -37
- package/app/m/messages/Message/index.html +36 -37
- package/app/m/messages/MessagingEndpoint/index.html +36 -37
- package/app/m/messages/PersonaMessageRoute/index.html +36 -37
- package/app/m/messages/SlackAccount/index.html +36 -37
- package/app/m/messages/SlackMessage/index.html +36 -37
- package/app/m/messages/TelegramAccount/index.html +36 -37
- package/app/m/messages/Tweet/index.html +36 -37
- package/app/m/messages/TwitterAccount/index.html +36 -37
- package/app/m/messages/Whitelist/index.html +36 -37
- package/app/m/messages/ZulipAccount/index.html +36 -37
- package/app/m/places/Place/index.html +36 -37
- package/app/m/places/PlaceType/index.html +36 -37
- package/app/m/products/Category/index.html +36 -37
- package/app/m/products/Material/index.html +36 -37
- package/app/m/products/Product/index.html +36 -37
- package/app/m/products/Product/ingredients/index.html +38 -39
- package/app/m/products/ProductVariant/index.html +36 -37
- package/app/m/products/Sku/index.html +36 -37
- package/app/m/profiles/ApiKey/index.html +36 -37
- package/app/m/profiles/Bot/index.html +36 -37
- package/app/m/profiles/MagicLinkToken/index.html +36 -37
- package/app/m/profiles/NostrIdentity/index.html +36 -37
- package/app/m/profiles/OidcIdentity/index.html +36 -37
- package/app/m/profiles/Organization/index.html +36 -37
- package/app/m/profiles/Person/index.html +36 -37
- package/app/m/profiles/Profile/index.html +36 -37
- package/app/m/profiles/ProfileMetadata/index.html +36 -37
- package/app/m/profiles/ProfileMetafield/index.html +36 -37
- package/app/m/profiles/ProfileRelationship/index.html +36 -37
- package/app/m/profiles/ProfileRelationshipTerm/index.html +36 -37
- package/app/m/profiles/ProfileRelationshipType/index.html +36 -37
- package/app/m/profiles/ProfileType/index.html +36 -37
- package/app/m/projects/Comment/index.html +36 -37
- package/app/m/projects/Issue/index.html +36 -37
- package/app/m/projects/Label/index.html +36 -37
- package/app/m/projects/Project/index.html +36 -37
- package/app/m/projects/ProjectIntegration/index.html +36 -37
- package/app/m/projects/PullRequest/index.html +36 -37
- package/app/m/projects/Repository/index.html +36 -37
- package/app/m/properties/Property/index.html +36 -37
- package/app/m/properties/Zone/index.html +36 -37
- package/app/m/reports/RuntimeReport/index.html +39 -37
- package/app/m/reports/SmrtPrincipalReportRefreshTask/index.html +36 -37
- package/app/m/reports/SmrtReportLock/index.html +36 -37
- package/app/m/reports/SmrtReportRefreshTask/index.html +36 -37
- package/app/m/reports/SmrtReportRun/index.html +36 -37
- package/app/m/reports/SmrtReportSchedule/index.html +36 -37
- package/app/m/reports/SmrtReportWatermark/index.html +36 -37
- package/app/m/sales/Agreement/index.html +36 -37
- package/app/m/sales/AttributionException/index.html +36 -37
- package/app/m/sales/AttributionPolicy/index.html +36 -37
- package/app/m/sales/Commission/index.html +36 -37
- package/app/m/sales/CommissionAdjustment/index.html +36 -37
- package/app/m/sales/CommissionPayout/index.html +36 -37
- package/app/m/sales/CommissionPlan/index.html +36 -37
- package/app/m/sales/Earner/index.html +36 -37
- package/app/m/sales/EarnerSourceAttribution/index.html +36 -37
- package/app/m/sales/EarningEvent/index.html +36 -37
- package/app/m/sales/ExecutedAgreement/index.html +36 -37
- package/app/m/sales/Lead/index.html +36 -37
- package/app/m/sales/Opportunity/index.html +36 -37
- package/app/m/sales/OpportunityConversion/index.html +36 -37
- package/app/m/sales/PipelineDefinition/index.html +36 -37
- package/app/m/sales/PipelineStage/index.html +36 -37
- package/app/m/sales/Referral/index.html +36 -37
- package/app/m/sales/ReferralAgreement/index.html +36 -37
- package/app/m/sales/ReferralLink/index.html +36 -37
- package/app/m/sales/ReferralProgram/index.html +36 -37
- package/app/m/sales/ReferralTermSnapshot/index.html +36 -37
- package/app/m/sales/ReferralTouch/index.html +36 -37
- package/app/m/sales/Referrer/index.html +36 -37
- package/app/m/sales/SalesActivity/index.html +36 -37
- package/app/m/sales/SalesRepresentative/index.html +36 -37
- package/app/m/sites/Site/index.html +36 -37
- package/app/m/sites/SiteAgentBinding/index.html +36 -37
- package/app/m/social/OAuthState/index.html +36 -37
- package/app/m/social/SocialAccount/index.html +36 -37
- package/app/m/social/SocialPost/index.html +36 -37
- package/app/m/social/SocialPostAnalyticsSnapshot/index.html +36 -37
- package/app/m/subscriptions/BillingAdjustment/index.html +36 -37
- package/app/m/subscriptions/ClientCharge/index.html +36 -37
- package/app/m/subscriptions/CreditGrant/index.html +36 -37
- package/app/m/subscriptions/PricingRule/index.html +36 -37
- package/app/m/subscriptions/RetailCharge/index.html +36 -37
- package/app/m/subscriptions/SpendingPolicy/index.html +36 -37
- package/app/m/subscriptions/SubscriptionPlan/index.html +36 -37
- package/app/m/subscriptions/TenantSubscription/index.html +36 -37
- package/app/m/subscriptions/TenantUsageMetric/index.html +36 -37
- package/app/m/support/ServiceTimeEntry/index.html +36 -37
- package/app/m/support/SupportAiRun/index.html +36 -37
- package/app/m/support/SupportAvailability/index.html +36 -37
- package/app/m/support/SupportCase/index.html +36 -37
- package/app/m/support/SupportCaseEvent/index.html +36 -37
- package/app/m/support/SupportChannelBinding/index.html +36 -37
- package/app/m/support/SupportCharge/index.html +36 -37
- package/app/m/support/SupportCompensation/index.html +36 -37
- package/app/m/support/SupportCompensationPlan/index.html +36 -37
- package/app/m/support/SupportEscalation/index.html +36 -37
- package/app/m/support/SupportInteraction/index.html +36 -37
- package/app/m/support/SupportPlan/index.html +36 -37
- package/app/m/support/SupportPolicy/index.html +36 -37
- package/app/m/support/SupportQualification/index.html +36 -37
- package/app/m/support/SupportServiceTarget/index.html +36 -37
- package/app/m/support/SupportSpecialist/index.html +36 -37
- package/app/m/support/SupportWorkLink/index.html +36 -37
- package/app/m/tags/Tag/index.html +36 -37
- package/app/m/tags/TagAlias/index.html +36 -37
- package/app/m/timesheets/AttendanceBreak/index.html +36 -37
- package/app/m/timesheets/AttendancePunch/index.html +36 -37
- package/app/m/timesheets/AttendanceSegment/index.html +36 -37
- package/app/m/timesheets/ServiceChargeSnapshot/index.html +36 -37
- package/app/m/timesheets/ServiceCompensationSnapshot/index.html +36 -37
- package/app/m/timesheets/ServiceTimeEntry/index.html +36 -37
- package/app/m/users/Group/index.html +36 -37
- package/app/m/users/GroupMember/index.html +36 -37
- package/app/m/users/GroupRole/index.html +36 -37
- package/app/m/users/Membership/index.html +36 -37
- package/app/m/users/MembershipOverride/index.html +36 -37
- package/app/m/users/Permission/index.html +36 -37
- package/app/m/users/Role/index.html +36 -37
- package/app/m/users/RolePermission/index.html +36 -37
- package/app/m/users/Session/index.html +36 -37
- package/app/m/users/Tenant/index.html +36 -37
- package/app/m/users/TenantIntegration/index.html +36 -37
- package/app/m/users/TenantPermissionOverride/index.html +36 -37
- package/app/m/users/User/index.html +36 -37
- package/app/m/video/Character/index.html +36 -37
- package/app/m/video/CharacterAsset/index.html +36 -37
- package/app/m/video/CompositeJob/index.html +36 -37
- package/app/m/video/Performer/index.html +36 -37
- package/app/m/video/PerformerAsset/index.html +36 -37
- package/app/m/video/Scene/index.html +36 -37
- package/app/m/video/SceneAsset/index.html +36 -37
- package/app/m/video/VideoComposition/index.html +36 -37
- package/app/m/video/VideoCompositionAsset/index.html +36 -37
- package/app/m/video/VideoSequence/index.html +36 -37
- package/app/m/video/VideoSequenceAsset/index.html +36 -37
- package/app/m/video/VideoShot/index.html +36 -37
- package/app/m/video/VideoShotAsset/index.html +36 -37
- package/app/m/video/VideoShotCharacter/index.html +36 -37
- package/app/m/video/VideoWorkflow/index.html +36 -37
- package/app/m/voice/VoiceOutput/index.html +36 -37
- package/app/m/voice/VoiceProfile/index.html +36 -37
- package/app/m/voice/VoiceSample/index.html +36 -37
- package/app/mcp.html +2 -2
- package/app/packages/ads/index.html +30 -33
- package/app/packages/analytics/index.html +30 -33
- package/app/packages/approvals/index.html +30 -33
- package/app/packages/assets/index.html +30 -33
- package/app/packages/chat/index.html +30 -33
- package/app/packages/comments/index.html +30 -33
- package/app/packages/commerce/index.html +30 -33
- package/app/packages/content/index.html +30 -33
- package/app/packages/events/index.html +30 -33
- package/app/packages/expenses/index.html +30 -33
- package/app/packages/facts/index.html +30 -33
- package/app/packages/fields/index.html +30 -33
- package/app/packages/human-resources/index.html +30 -33
- package/app/packages/images/index.html +30 -33
- package/app/packages/index.html +30 -33
- package/app/packages/ingestion/index.html +30 -33
- package/app/packages/inventory/index.html +30 -33
- package/app/packages/ledgers/index.html +30 -33
- package/app/packages/manufacturing/index.html +30 -33
- package/app/packages/marketing/index.html +30 -33
- package/app/packages/messages/index.html +30 -33
- package/app/packages/places/index.html +30 -33
- package/app/packages/preferences/index.html +30 -33
- package/app/packages/products/index.html +30 -33
- package/app/packages/profiles/index.html +30 -33
- package/app/packages/projects/index.html +30 -33
- package/app/packages/properties/index.html +30 -33
- package/app/packages/reports/index.html +30 -33
- package/app/packages/sales/index.html +30 -33
- package/app/packages/sites/index.html +30 -33
- package/app/packages/social/index.html +30 -33
- package/app/packages/subscriptions/index.html +30 -33
- package/app/packages/support/index.html +30 -33
- package/app/packages/tags/index.html +30 -33
- package/app/packages/timesheets/index.html +30 -33
- package/app/packages/users/index.html +30 -33
- package/app/packages/video/index.html +30 -33
- package/app/packages/voice/index.html +30 -33
- package/app/packages/webhooks/index.html +30 -33
- package/app/recipes/account-access/help/index.html +32 -35
- package/app/recipes/account-access/index.html +36 -38
- package/app/recipes/activity/help/index.html +32 -35
- package/app/recipes/activity/index.html +36 -38
- package/app/recipes/agreements/help/index.html +32 -35
- package/app/recipes/agreements/index.html +36 -38
- package/app/recipes/analytics.reports/help/index.html +32 -35
- package/app/recipes/analytics.reports/index.html +36 -38
- package/app/recipes/assets/help/index.html +32 -35
- package/app/recipes/assets/index.html +36 -38
- package/app/recipes/billing/help/index.html +32 -35
- package/app/recipes/billing/index.html +36 -38
- package/app/recipes/chat.assistant/help/index.html +32 -35
- package/app/recipes/chat.assistant/index.html +36 -38
- package/app/recipes/comments/help/index.html +32 -35
- package/app/recipes/comments/index.html +36 -38
- package/app/recipes/commerce.customers/help/index.html +32 -35
- package/app/recipes/commerce.customers/index.html +36 -38
- package/app/recipes/commerce.estimates/help/index.html +32 -35
- package/app/recipes/commerce.estimates/index.html +36 -38
- package/app/recipes/commerce.purchases/help/index.html +32 -35
- package/app/recipes/commerce.purchases/index.html +36 -38
- package/app/recipes/commerce.sales/help/index.html +32 -35
- package/app/recipes/commerce.sales/index.html +36 -38
- package/app/recipes/commerce.vendors/help/index.html +32 -35
- package/app/recipes/commerce.vendors/index.html +36 -38
- package/app/recipes/commerce.wholesale/help/index.html +32 -35
- package/app/recipes/commerce.wholesale/index.html +36 -38
- package/app/recipes/events.calendar/help/index.html +32 -35
- package/app/recipes/events.calendar/index.html +36 -38
- package/app/recipes/expenses.tracking/help/index.html +32 -35
- package/app/recipes/expenses.tracking/index.html +36 -38
- package/app/recipes/fields.form-customization/help/index.html +32 -35
- package/app/recipes/fields.form-customization/index.html +36 -38
- package/app/recipes/ingestion/help/index.html +32 -35
- package/app/recipes/ingestion/index.html +36 -38
- package/app/recipes/integrations/help/index.html +32 -35
- package/app/recipes/integrations/index.html +36 -38
- package/app/recipes/inventory.stock/help/index.html +32 -35
- package/app/recipes/inventory.stock/index.html +36 -38
- package/app/recipes/ledgers.bookkeeping/help/index.html +32 -35
- package/app/recipes/ledgers.bookkeeping/index.html +36 -38
- package/app/recipes/messages/help/index.html +32 -35
- package/app/recipes/messages/index.html +36 -38
- package/app/recipes/products/help/index.html +32 -35
- package/app/recipes/products/index.html +36 -38
- package/app/recipes/projects.tracker/help/index.html +32 -35
- package/app/recipes/projects.tracker/index.html +36 -38
- package/app/recipes/reports.materialized/help/index.html +32 -35
- package/app/recipes/reports.materialized/index.html +36 -38
- package/app/recipes/reports.runtime/help/index.html +32 -35
- package/app/recipes/reports.runtime/index.html +37 -39
- package/app/recipes/sales.pipeline/help/index.html +32 -35
- package/app/recipes/sales.pipeline/index.html +36 -38
- package/app/recipes/tags.taxonomy/help/index.html +32 -35
- package/app/recipes/tags.taxonomy/index.html +36 -38
- package/app/recipes/team-collaboration/help/index.html +32 -35
- package/app/recipes/team-collaboration/index.html +36 -38
- package/app/recipes/timesheets.time-entries/help/index.html +32 -35
- package/app/recipes/timesheets.time-entries/index.html +36 -38
- package/app/s/custom-accounts/index.html +29 -32
- package/app/s/custom-appointments/index.html +29 -32
- package/app/s/custom-billing/index.html +29 -32
- package/app/s/custom-bookings/index.html +79 -0
- package/app/s/custom-buying/index.html +29 -32
- package/app/s/custom-checkout/index.html +29 -32
- package/app/s/custom-classes/index.html +29 -32
- package/app/s/custom-clients/index.html +29 -32
- package/app/s/custom-events/index.html +29 -32
- package/app/s/custom-fleet/index.html +29 -32
- package/app/s/custom-gigs/index.html +79 -0
- package/app/s/custom-giving/index.html +29 -32
- package/app/s/custom-instruments/index.html +79 -0
- package/app/s/custom-jobs/index.html +29 -32
- package/app/s/custom-kitchen/index.html +29 -32
- package/app/s/custom-lessons/index.html +79 -0
- package/app/s/custom-material/index.html +29 -32
- package/app/s/custom-meetings/index.html +29 -32
- package/app/s/custom-members/index.html +29 -32
- package/app/s/custom-merch/index.html +79 -0
- package/app/s/custom-money/index.html +79 -0
- package/app/s/custom-paint/index.html +29 -32
- package/app/s/custom-parts/index.html +29 -32
- package/app/s/custom-rentals/index.html +29 -32
- package/app/s/custom-roastery/index.html +29 -32
- package/app/s/custom-schedule/index.html +29 -32
- package/app/s/custom-shelf/index.html +29 -32
- package/app/s/custom-shop/index.html +29 -32
- package/app/s/custom-students/index.html +79 -0
- package/app/s/custom-wholesale/index.html +29 -32
- package/app/s/custom-work/index.html +29 -32
- package/app/s/custom-yard/index.html +29 -32
- package/app/s/section-access-control/index.html +29 -32
- package/app/s/section-account-security/index.html +29 -32
- package/app/s/section-accounting/index.html +29 -32
- package/app/s/section-activity/index.html +29 -32
- package/app/s/section-agreements/index.html +29 -32
- package/app/s/section-analytics/index.html +29 -32
- package/app/s/section-assets/index.html +29 -32
- package/app/s/section-billing/index.html +29 -32
- package/app/s/section-calendar/index.html +29 -32
- package/app/s/section-catalog/index.html +29 -32
- package/app/s/section-chat.assistant/index.html +29 -32
- package/app/s/section-comments/index.html +29 -32
- package/app/s/section-fields.form-customization/index.html +29 -32
- package/app/s/section-ingestion/index.html +29 -32
- package/app/s/section-integrations/index.html +29 -32
- package/app/s/section-messages/index.html +29 -32
- package/app/s/section-more/index.html +29 -32
- package/app/s/section-operations/index.html +29 -32
- package/app/s/section-projects/index.html +29 -32
- package/app/s/section-purchasing/index.html +29 -32
- package/app/s/section-reports.materialized/index.html +29 -32
- package/app/s/section-reports.runtime/index.html +29 -32
- package/app/s/section-sales/index.html +29 -32
- package/app/s/section-taxonomy/index.html +29 -32
- package/app/s/section-team/index.html +29 -32
- package/app/s/section-work/index.html +29 -32
- package/dist/assistant/change.d.ts +10 -1
- package/dist/assistant/change.d.ts.map +1 -1
- package/dist/assistant/change.js +6 -1
- package/dist/assistant/prompt.d.ts +10 -1
- package/dist/assistant/prompt.d.ts.map +1 -1
- package/dist/assistant/prompt.js +42 -7
- package/dist/assistant/session.svelte.d.ts +6 -0
- package/dist/assistant/session.svelte.d.ts.map +1 -1
- package/dist/assistant/session.svelte.js +6 -0
- package/dist/assistant/transport.d.ts +23 -3
- package/dist/assistant/transport.d.ts.map +1 -1
- package/dist/assistant/transport.js +356 -13
- package/dist/catalog/catalog.json +107 -41
- package/dist/components/BrowserAssistant.svelte +26 -0
- package/dist/components/BrowserAssistant.svelte.d.ts.map +1 -1
- package/dist/components/ModelPage.svelte +36 -4
- package/dist/components/ModelPage.svelte.d.ts.map +1 -1
- package/dist/components/PlannerReports.svelte +61 -0
- package/dist/components/PlannerReports.svelte.d.ts +10 -0
- package/dist/components/PlannerReports.svelte.d.ts.map +1 -0
- package/dist/components/PlannerSavedReportsWidget.svelte +38 -0
- package/dist/components/PlannerSavedReportsWidget.svelte.d.ts +9 -0
- package/dist/components/PlannerSavedReportsWidget.svelte.d.ts.map +1 -0
- package/dist/components/ReportProposalCard.svelte +63 -0
- package/dist/components/ReportProposalCard.svelte.d.ts +17 -0
- package/dist/components/ReportProposalCard.svelte.d.ts.map +1 -0
- package/dist/components/SectionOverview.svelte +22 -1
- package/dist/components/SectionOverview.svelte.d.ts.map +1 -1
- package/dist/components/ThemeBridge.svelte +2 -2
- package/dist/core/prompt.d.ts.map +1 -1
- package/dist/core/prompt.js +7 -1
- package/dist/core/reply.d.ts +6 -0
- package/dist/core/reply.d.ts.map +1 -1
- package/dist/core/reply.js +11 -0
- package/dist/data/packs.d.ts.map +1 -1
- package/dist/data/packs.js +415 -0
- package/dist/data/planner-source.d.ts.map +1 -1
- package/dist/data/planner-source.js +4 -1
- package/dist/library/icons.d.ts.map +1 -1
- package/dist/library/icons.js +10 -0
- package/dist/library/library.json +506 -0
- package/dist/overviews/definitions.d.ts.map +1 -1
- package/dist/overviews/definitions.js +6 -1
- package/dist/overviews/registry.d.ts.map +1 -1
- package/dist/overviews/registry.js +9 -5
- package/dist/planner/Planner.svelte +17 -0
- package/dist/planner/Planner.svelte.d.ts.map +1 -1
- package/dist/planner/instance.d.ts +6 -0
- package/dist/planner/instance.d.ts.map +1 -1
- package/dist/planner/shell.d.ts.map +1 -1
- package/dist/planner/shell.js +3 -1
- package/dist/reports/intent.d.ts +106 -0
- package/dist/reports/intent.d.ts.map +1 -0
- package/dist/reports/intent.js +667 -0
- package/dist/reports/planner.d.ts +33 -0
- package/dist/reports/planner.d.ts.map +1 -0
- package/dist/reports/planner.js +60 -0
- package/dist/reports/sources.d.ts +36 -0
- package/dist/reports/sources.d.ts.map +1 -0
- package/dist/reports/sources.js +125 -0
- package/dist/reports/store.d.ts +64 -0
- package/dist/reports/store.d.ts.map +1 -0
- package/dist/reports/store.js +214 -0
- package/dist/smrt-version.d.ts +1 -1
- package/dist/smrt-version.js +1 -1
- package/package.json +54 -54
- package/app/_app/immutable/assets/0.C8CwV4Fz.css +0 -1
- package/app/_app/immutable/assets/AppShell.Dnc9PAvY.css +0 -1
- package/app/_app/immutable/assets/app.4ScdTV_S.css +0 -1
- package/app/_app/immutable/assets/labels.DrQMsG17.css +0 -1
- package/app/_app/immutable/assets/state.CkVocVUJ.css +0 -1
- package/app/_app/immutable/chunks/9pRTae44.js +0 -1
- package/app/_app/immutable/chunks/BhU_yBI_.js +0 -1
- package/app/_app/immutable/chunks/Bsn3IIve.js +0 -4
- package/app/_app/immutable/chunks/C_3CJO_1.js +0 -1
- package/app/_app/immutable/chunks/Cr4byQts.js +0 -24
- package/app/_app/immutable/chunks/CtjBwCj8.js +0 -1
- package/app/_app/immutable/chunks/CyUSxz1P.js +0 -4
- package/app/_app/immutable/chunks/J9kOiFLO.js +0 -11
- package/app/_app/immutable/chunks/M-CuJzQN.js +0 -1
- package/app/_app/immutable/chunks/NppCG--v.js +0 -1
- package/app/_app/immutable/chunks/O8DAZ_le.js +0 -1
- package/app/_app/immutable/chunks/d_dqmeIr.js +0 -1
- package/app/_app/immutable/chunks/gMSmS-_y.js +0 -2
- package/app/_app/immutable/entry/app.B4gMiHwR.js +0 -2
- package/app/_app/immutable/entry/start.BXkBl20Z.js +0 -1
- package/app/_app/immutable/nodes/0.2MYMg80l.js +0 -9
- package/app/_app/immutable/nodes/14.B6TD25VU.js +0 -1
- package/app/_app/immutable/nodes/2.x9WyxQ1S.js +0 -24
package/dist/assistant/prompt.js
CHANGED
|
@@ -51,16 +51,37 @@ const EXAMPLES = [
|
|
|
51
51
|
theme: { primary: '#d97706' },
|
|
52
52
|
},
|
|
53
53
|
},
|
|
54
|
+
{
|
|
55
|
+
says: 'give me a summary of all sales last month',
|
|
56
|
+
report: 'invoices',
|
|
57
|
+
answer: {
|
|
58
|
+
reply: 'Here is a summary of last month.',
|
|
59
|
+
add: [],
|
|
60
|
+
remove: [],
|
|
61
|
+
report: { source: 'invoices', range: 'last month' },
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
says: 'show me a report of sales by month',
|
|
66
|
+
report: 'invoices',
|
|
67
|
+
answer: {
|
|
68
|
+
reply: 'Here are sales by month.',
|
|
69
|
+
add: [],
|
|
70
|
+
remove: [],
|
|
71
|
+
report: { source: 'invoices', bucket: 'month' },
|
|
72
|
+
},
|
|
73
|
+
},
|
|
54
74
|
{
|
|
55
75
|
says: 'hello',
|
|
56
76
|
answer: { reply: 'Hi. What kind of business is it?', add: [], remove: [] },
|
|
57
77
|
},
|
|
58
78
|
];
|
|
59
|
-
function examples(recipeIds, cookbookIds, withSettings, withTheme) {
|
|
79
|
+
function examples(recipeIds, cookbookIds, withSettings, withTheme, reportIds = new Set()) {
|
|
60
80
|
return EXAMPLES.filter((e) => (e.recipes ?? []).every((id) => recipeIds.has(id)) &&
|
|
61
81
|
(!e.cookbook || cookbookIds.has(e.cookbook)) &&
|
|
62
82
|
(!e.settings || withSettings) &&
|
|
63
|
-
(!e.theme || withTheme)
|
|
83
|
+
(!e.theme || withTheme) &&
|
|
84
|
+
(!e.report || reportIds.has(e.report))).map((e) => `"${e.says}" -> ${JSON.stringify(e.answer)}`);
|
|
64
85
|
}
|
|
65
86
|
/** The recipe a request for a report or a summary of the app's data needs. */
|
|
66
87
|
export const REPORTS_RECIPE = 'reports.runtime';
|
|
@@ -79,7 +100,7 @@ export function formatTaxPercent(fraction) {
|
|
|
79
100
|
* and a hint line naming what looks relevant. Without it every item gets a
|
|
80
101
|
* full line. The response schema lists every id either way.
|
|
81
102
|
*/
|
|
82
|
-
export function buildSystemPrompt(recipes, current, cookbooks = [], settings, matches, themeInfo, menu = []) {
|
|
103
|
+
export function buildSystemPrompt(recipes, current, cookbooks = [], settings, matches, themeInfo, menu = [], reports = [], pendingReport) {
|
|
83
104
|
const focused = matches !== undefined;
|
|
84
105
|
const matchedRecipes = (matches ?? [])
|
|
85
106
|
.filter((m) => m.kind === 'recipe')
|
|
@@ -114,11 +135,17 @@ export function buildSystemPrompt(recipes, current, cookbooks = [], settings, ma
|
|
|
114
135
|
if (menu.length) {
|
|
115
136
|
out.push('"open": a menu section id only when they ask to see or go to one, else null.');
|
|
116
137
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
out.push(`A report or summary of their data needs ${REPORTS_RECIPE} (Reports): add it, and open only its section, never another. You cannot build the report itself yet.`);
|
|
138
|
+
if (reports.length) {
|
|
139
|
+
out.push('"report": only when they ask for a report, summary or totals of their records: {"source": a report source id, optional "measures": [{"fn": count|sum|avg|min|max, "field"}], "groupBy": a field (not a time word), "bucket": minute|hour|day|week|month|quarter|year for "by month"/"weekly"/"over time", "range": their period in words ("last month", "last 90 days", "Q3"), "filters": [{"field", "op": eq|ne|gt|gte|lt|lte|contains, "value"}]}; a summary needs only source and range; money values are in currency units (500 for $500). Else omit.');
|
|
120
140
|
}
|
|
121
|
-
|
|
141
|
+
out.push(`"reply" never claims anything beyond add, remove, cookbook, settings, theme, open${reports.length ? ' and report' : ''}: the app reports what changed.`);
|
|
142
|
+
if (reports.length) {
|
|
143
|
+
out.push(`A report or summary of their data is "report", never a recipe to add or a section to open: the app turns on ${REPORTS_RECIPE} (Reports), builds the report, shows a preview and saves it only when they approve.`);
|
|
144
|
+
}
|
|
145
|
+
else if (recipes.some((r) => r.id === REPORTS_RECIPE)) {
|
|
146
|
+
out.push(`A report or summary of their data needs ${REPORTS_RECIPE} (Reports): add it, and open only its section, never another. You cannot build the report itself here.`);
|
|
147
|
+
}
|
|
148
|
+
const shown = examples(new Set(recipes.map((r) => r.id)), new Set(cookbooks.map((c) => c.id)), Boolean(settings), Boolean(themeInfo), new Set(reports.map((r) => r.id)));
|
|
122
149
|
if (shown.length)
|
|
123
150
|
out.push('', 'Examples:', ...shown);
|
|
124
151
|
const themeHint = !!themeInfo && (matches ?? []).some((m) => m.kind === 'theme');
|
|
@@ -175,5 +202,13 @@ export function buildSystemPrompt(recipes, current, cookbooks = [], settings, ma
|
|
|
175
202
|
if (menu.length) {
|
|
176
203
|
out.push(`Menu: ${menu.map((s) => `${s.id} (${s.label})`).join(', ')}.`);
|
|
177
204
|
}
|
|
205
|
+
if (reports.length) {
|
|
206
|
+
out.push(`Report sources: ${reports.map((r) => `${r.id} (${r.label})`).join(', ')}.`);
|
|
207
|
+
}
|
|
208
|
+
if (pendingReport) {
|
|
209
|
+
// The follow-up the app just asked: an answer comes back as "report"
|
|
210
|
+
// with the same source plus what they chose; the app merges it.
|
|
211
|
+
out.push('', `Pending report question: "${pendingReport.prompt}" Options: ${pendingReport.options.join(', ')}. If they answer it, set "report" with source "${pendingReport.source}" and what they chose (a grouping as "groupBy", a time grouping as "bucket").`);
|
|
212
|
+
}
|
|
178
213
|
return out.join('\n');
|
|
179
214
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { InferenceMode } from '../inference/config.ts';
|
|
2
2
|
import type { PlannerController } from '../planner/commands/index.ts';
|
|
3
3
|
import type { Recipe } from '../recipes/types.ts';
|
|
4
|
+
import type { PlannerReports } from '../reports/store.ts';
|
|
4
5
|
import type { RecipeStore, SettingsStore, ThemeStore } from './change.ts';
|
|
5
6
|
import { type EngineHost, type LoadProgress } from './engine.ts';
|
|
6
7
|
import { CookbookOffers } from './offers.svelte.ts';
|
|
@@ -54,6 +55,11 @@ export declare class AssistantSession {
|
|
|
54
55
|
readonly offers: CookbookOffers;
|
|
55
56
|
/** Theme changes the assistant made, each undoable from the chat. */
|
|
56
57
|
readonly themeUndos: ThemeUndos | null;
|
|
58
|
+
/**
|
|
59
|
+
* Runtime reports over the app's sample data, set by the component that
|
|
60
|
+
* has the data source (`BrowserAssistant`); null, the assistant builds none.
|
|
61
|
+
*/
|
|
62
|
+
reports: PlannerReports | null;
|
|
57
63
|
private loaded;
|
|
58
64
|
private chat;
|
|
59
65
|
private abort;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/assistant/session.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAEL,KAAK,UAAU,EAEf,KAAK,YAAY,EAElB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,KAAK,cAAc,EAAwB,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EACL,KAAK,yBAAyB,EAC9B,KAAK,SAAS,EAEf,MAAM,gBAAgB,CAAC;AAExB;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAK3E;AAED,MAAM,MAAM,aAAa,GACrB,aAAa,GACb,MAAM,GACN,SAAS,GACT,OAAO,GACP,OAAO,CAAC;AAEZ,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,gFAAgF;IAChF,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,0FAA0F;IAC1F,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,wEAAwE;IACxE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACvD;AAED;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,MAAM,gBAAiC;IACvC,KAAK,iBAA0D;IAC/D,QAAQ,eAAmD;IAC3D,KAAK,SAAc;IACnB,gFAAgF;IAChF,IAAI,gBAAoC;IACxC,4EAA4E;IAC5E,WAAW,SAAc;IAEzB,QAAQ,CAAC,SAAS,EAAE,yBAAyB,CAAC;IAC9C,4EAA4E;IAC5E,QAAQ,CAAC,MAAM,iBAA0C;IACzD,qEAAqE;IACrE,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IACvC,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,IAAI,CAA0B;IACtC,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;gBAE7B,OAAO,EAAE,cAAc;
|
|
1
|
+
{"version":3,"file":"session.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/assistant/session.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAEL,KAAK,UAAU,EAEf,KAAK,YAAY,EAElB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,KAAK,cAAc,EAAwB,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EACL,KAAK,yBAAyB,EAC9B,KAAK,SAAS,EAEf,MAAM,gBAAgB,CAAC;AAExB;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAK3E;AAED,MAAM,MAAM,aAAa,GACrB,aAAa,GACb,MAAM,GACN,SAAS,GACT,OAAO,GACP,OAAO,CAAC;AAEZ,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,gFAAgF;IAChF,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,0FAA0F;IAC1F,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,wEAAwE;IACxE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACvD;AAED;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,MAAM,gBAAiC;IACvC,KAAK,iBAA0D;IAC/D,QAAQ,eAAmD;IAC3D,KAAK,SAAc;IACnB,gFAAgF;IAChF,IAAI,gBAAoC;IACxC,4EAA4E;IAC5E,WAAW,SAAc;IAEzB,QAAQ,CAAC,SAAS,EAAE,yBAAyB,CAAC;IAC9C,4EAA4E;IAC5E,QAAQ,CAAC,MAAM,iBAA0C;IACzD,qEAAqE;IACrE,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IACvC;;;OAGG;IACH,OAAO,EAAE,cAAc,GAAG,IAAI,CAAQ;IACtC,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,IAAI,CAA0B;IACtC,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;gBAE7B,OAAO,EAAE,cAAc;IAkCnC;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAYlC,iFAAiF;IACjF,SAAS,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAOtD,0EAA0E;IAC1E,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAM7B,8EAA8E;IACxE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAqD5B,mCAAmC;IACnC,MAAM,IAAI,IAAI;IAId,qDAAqD;IACrD,MAAM,IAAI,IAAI;CAYf"}
|
|
@@ -37,6 +37,11 @@ export class AssistantSession {
|
|
|
37
37
|
offers = new CookbookOffers(getLibraryCookbook);
|
|
38
38
|
/** Theme changes the assistant made, each undoable from the chat. */
|
|
39
39
|
themeUndos;
|
|
40
|
+
/**
|
|
41
|
+
* Runtime reports over the app's sample data, set by the component that
|
|
42
|
+
* has the data source (`BrowserAssistant`); null, the assistant builds none.
|
|
43
|
+
*/
|
|
44
|
+
reports = null;
|
|
40
45
|
loaded = null;
|
|
41
46
|
chat = null;
|
|
42
47
|
abort = null;
|
|
@@ -71,6 +76,7 @@ export class AssistantSession {
|
|
|
71
76
|
: 'Download a model first, then I can help. The cards on the Planner page work without one.',
|
|
72
77
|
onReply: (text) => options.onReply?.(text),
|
|
73
78
|
menu: options.menu,
|
|
79
|
+
reports: () => this.reports,
|
|
74
80
|
});
|
|
75
81
|
}
|
|
76
82
|
/**
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AssistantQuestion, type AssistantTransport } from '@happyvertical/smrt-chat/svelte';
|
|
2
2
|
import { type PlannerController } from '../planner/commands/index.ts';
|
|
3
3
|
import type { Recipe } from '../recipes/types.ts';
|
|
4
|
+
import { type ReportFollowUp } from '../reports/intent.ts';
|
|
5
|
+
import type { PlannerReports } from '../reports/store.ts';
|
|
4
6
|
import type { ThemeSetting } from '../theme/theme.ts';
|
|
5
7
|
import { type RecipeStore, type SettingsStore, type ThemeStore } from './change.ts';
|
|
6
8
|
import type { OfferRef } from './offers.svelte.ts';
|
|
@@ -66,17 +68,35 @@ export interface BrowserTransportOptions {
|
|
|
66
68
|
id: string;
|
|
67
69
|
label: string;
|
|
68
70
|
}[];
|
|
71
|
+
/**
|
|
72
|
+
* Runtime reports over the app's sample data (#4100). With it the model may
|
|
73
|
+
* answer a report request with a `report` intent, which the transport turns
|
|
74
|
+
* into smrt-reports' `reports.runtime.*` steps: sources, define (preview),
|
|
75
|
+
* run; the person's approval saves. Null or omitted: no report building.
|
|
76
|
+
*/
|
|
77
|
+
reports?: () => PlannerReports | null;
|
|
69
78
|
}
|
|
70
79
|
export interface BrowserAssistantTransport extends AssistantTransport {
|
|
71
80
|
/** Stop the turn in flight, if any. */
|
|
72
81
|
abort(): void;
|
|
82
|
+
/**
|
|
83
|
+
* Record how a report preview was answered on the transcript's own tool
|
|
84
|
+
* data, so a reloaded transcript shows the outcome, not live buttons.
|
|
85
|
+
*/
|
|
86
|
+
recordReportOutcome(specHash: string, outcome: unknown): void;
|
|
73
87
|
}
|
|
74
88
|
/** The one line the chat opens with. */
|
|
75
89
|
export declare const GREETING = "What would you like to build?";
|
|
76
90
|
/** Said when a turn changed nothing and the model's sentence was not a question. */
|
|
77
91
|
export declare const NOTHING_CHANGED = "Nothing in the app changed.";
|
|
78
|
-
/** Said after a report request
|
|
79
|
-
export declare const
|
|
92
|
+
/** Said after a report request where this planner has no sample data to report on. */
|
|
93
|
+
export declare const REPORTS_UNAVAILABLE = "Building a report needs the planner app and its sample records; it will live under Reports.";
|
|
94
|
+
/** The tool call a report preview rides on, as smrt-chat names it. */
|
|
95
|
+
export declare const REPORT_DEFINE_TOOL = "reports.runtime.define";
|
|
96
|
+
/** A report follow-up as smrt-chat's structured question (a form in the dock). */
|
|
97
|
+
export declare function reportQuestion(followUp: ReportFollowUp, id: string): AssistantQuestion;
|
|
98
|
+
/** What the chat says under a report preview. */
|
|
99
|
+
export declare function reportPreviewText(title: string, rows: number): string;
|
|
80
100
|
/**
|
|
81
101
|
* What the chat says for a turn. When something ran, the commands' own
|
|
82
102
|
* summaries ("Added Invoicing.", "Opened Billing."), never the model's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/lib/assistant/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/lib/assistant/transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { ASSISTANT_QUESTION_KIND, matchAssistantQuestionText, validateAssistantQuestionAnswer, } from '@happyvertical/smrt-chat/svelte';
|
|
2
|
+
import { resolveRuntimeReportTimeRange } from '@happyvertical/smrt-reports/spec';
|
|
1
3
|
import { createSliceController, } from "../planner/commands/index.js";
|
|
4
|
+
import { sourceFollowUp, whichSourceQuestion, } from "../reports/intent.js";
|
|
2
5
|
import { buildResponseSchema, describeChange, parseChange, } from "./change.js";
|
|
3
6
|
import { buildMatchIndex, matchText } from "./match.js";
|
|
4
7
|
import { buildSystemPrompt, REPORTS_RECIPE, } from "./prompt.js";
|
|
@@ -37,8 +40,128 @@ function runCommands(controller, calls) {
|
|
|
37
40
|
}
|
|
38
41
|
/** Said when a turn changed nothing and the model's sentence was not a question. */
|
|
39
42
|
export const NOTHING_CHANGED = 'Nothing in the app changed.';
|
|
40
|
-
/** Said after a report request
|
|
41
|
-
export const
|
|
43
|
+
/** Said after a report request where this planner has no sample data to report on. */
|
|
44
|
+
export const REPORTS_UNAVAILABLE = 'Building a report needs the planner app and its sample records; it will live under Reports.';
|
|
45
|
+
/** The tool call a report preview rides on, as smrt-chat names it. */
|
|
46
|
+
export const REPORT_DEFINE_TOOL = 'reports.runtime.define';
|
|
47
|
+
/** A report follow-up as smrt-chat's structured question (a form in the dock). */
|
|
48
|
+
export function reportQuestion(followUp, id) {
|
|
49
|
+
return {
|
|
50
|
+
kind: ASSISTANT_QUESTION_KIND,
|
|
51
|
+
id,
|
|
52
|
+
prompt: followUp.prompt,
|
|
53
|
+
fields: [
|
|
54
|
+
{
|
|
55
|
+
name: followUp.field,
|
|
56
|
+
label: followUp.label,
|
|
57
|
+
type: 'choice',
|
|
58
|
+
options: followUp.options.map(({ value, label, keywords }) => ({
|
|
59
|
+
value,
|
|
60
|
+
label,
|
|
61
|
+
...(keywords ? { keywords } : {}),
|
|
62
|
+
})),
|
|
63
|
+
default: followUp.default,
|
|
64
|
+
required: true,
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/** Merge a follow-up pick or a model's partial answer into a pending intent. */
|
|
70
|
+
function mergeIntent(base, patch) {
|
|
71
|
+
const out = { ...base };
|
|
72
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
73
|
+
if (value === undefined)
|
|
74
|
+
delete out[key];
|
|
75
|
+
else
|
|
76
|
+
out[key] = value;
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
/** Words that are filler, or time words the report reads itself. */
|
|
81
|
+
const ANSWER_FILLER = new Set([
|
|
82
|
+
'a',
|
|
83
|
+
'an',
|
|
84
|
+
'and',
|
|
85
|
+
'the',
|
|
86
|
+
'by',
|
|
87
|
+
'per',
|
|
88
|
+
'of',
|
|
89
|
+
'in',
|
|
90
|
+
'on',
|
|
91
|
+
'for',
|
|
92
|
+
'to',
|
|
93
|
+
'with',
|
|
94
|
+
'please',
|
|
95
|
+
'use',
|
|
96
|
+
'i',
|
|
97
|
+
'want',
|
|
98
|
+
'it',
|
|
99
|
+
'its',
|
|
100
|
+
'group',
|
|
101
|
+
'grouped',
|
|
102
|
+
'show',
|
|
103
|
+
'me',
|
|
104
|
+
'just',
|
|
105
|
+
'ok',
|
|
106
|
+
'okay',
|
|
107
|
+
'yes',
|
|
108
|
+
'that',
|
|
109
|
+
'one',
|
|
110
|
+
'option',
|
|
111
|
+
'last',
|
|
112
|
+
'this',
|
|
113
|
+
'past',
|
|
114
|
+
'previous',
|
|
115
|
+
'current',
|
|
116
|
+
'day',
|
|
117
|
+
'week',
|
|
118
|
+
'month',
|
|
119
|
+
'quarter',
|
|
120
|
+
'year',
|
|
121
|
+
'today',
|
|
122
|
+
'yesterday',
|
|
123
|
+
'ytd',
|
|
124
|
+
'date',
|
|
125
|
+
'time',
|
|
126
|
+
]);
|
|
127
|
+
const answerWords = (text) => text
|
|
128
|
+
.toLowerCase()
|
|
129
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
130
|
+
.split(/[^a-z0-9]+/)
|
|
131
|
+
.filter(Boolean)
|
|
132
|
+
.map((w) => (w.length > 3 && w.endsWith('s') ? w.slice(0, -1) : w));
|
|
133
|
+
/**
|
|
134
|
+
* A typed reply that answers the pending question and says nothing else
|
|
135
|
+
* ("the date month", "status", "status last month"): every word is an
|
|
136
|
+
* option's word, filler, or a time word the report reads itself. Anything
|
|
137
|
+
* more ("invoices over $500", "add invoicing") goes to the model with the
|
|
138
|
+
* pending question in its prompt, so nothing the person said is dropped.
|
|
139
|
+
*/
|
|
140
|
+
function directAnswer(followUp, question, text) {
|
|
141
|
+
const values = matchAssistantQuestionText(question, text);
|
|
142
|
+
if (!values)
|
|
143
|
+
return undefined;
|
|
144
|
+
const known = new Set(followUp.options.flatMap((o) => answerWords([o.label, o.value, ...(o.keywords ?? [])].join(' '))));
|
|
145
|
+
// A number counts only when it is part of a period the time parser read
|
|
146
|
+
// ("last 90 days", "Q3", "2025"); "over 500" is a threshold for the model.
|
|
147
|
+
const period = resolveRuntimeReportTimeRange(text, new Date()) !== null;
|
|
148
|
+
const extra = answerWords(text).filter((w) => !known.has(w) &&
|
|
149
|
+
!ANSWER_FILLER.has(w) &&
|
|
150
|
+
!(period && (/^\d+$/.test(w) || /^q[1-4]$/.test(w))));
|
|
151
|
+
if (extra.length)
|
|
152
|
+
return undefined;
|
|
153
|
+
const chosen = values[followUp.field];
|
|
154
|
+
const value = Array.isArray(chosen) ? chosen[0] : chosen;
|
|
155
|
+
return followUp.options.find((o) => o.value === value);
|
|
156
|
+
}
|
|
157
|
+
const sameFollowUp = (a, b) => a.field === b.field &&
|
|
158
|
+
a.prompt === b.prompt &&
|
|
159
|
+
a.options.map((o) => o.value).join('|') ===
|
|
160
|
+
b.options.map((o) => o.value).join('|');
|
|
161
|
+
/** What the chat says under a report preview. */
|
|
162
|
+
export function reportPreviewText(title, rows) {
|
|
163
|
+
return `Here is a preview of ${title} (${rows} ${rows === 1 ? 'row' : 'rows'}). Approve it to save it under Saved reports.`;
|
|
164
|
+
}
|
|
42
165
|
/** The Reports menu entry (reports.runtime's RuntimeReport). */
|
|
43
166
|
const REPORTS_ITEM = 'item:reports:RuntimeReport';
|
|
44
167
|
/**
|
|
@@ -106,6 +229,79 @@ export function createBrowserAssistantTransport(options) {
|
|
|
106
229
|
const messages = [];
|
|
107
230
|
const seen = new Map();
|
|
108
231
|
let controller = null;
|
|
232
|
+
/**
|
|
233
|
+
* The report follow-up waiting for an answer: the intent so far, the
|
|
234
|
+
* question asked (its options from the source descriptor), and the words
|
|
235
|
+
* of the original request (their time words still count).
|
|
236
|
+
*/
|
|
237
|
+
let pending = null;
|
|
238
|
+
let questions = 0;
|
|
239
|
+
/**
|
|
240
|
+
* `reports.runtime.define` (preview) then `run`, by code. A follow-up the
|
|
241
|
+
* intent still needs becomes a form (and the pending question); asking the
|
|
242
|
+
* identical question twice is never done: the sensible default is taken
|
|
243
|
+
* and the reply says so.
|
|
244
|
+
*/
|
|
245
|
+
async function buildReport(reports, intent, text, previous) {
|
|
246
|
+
const defined = await reports.define(intent, text);
|
|
247
|
+
if (defined.ok) {
|
|
248
|
+
pending = null;
|
|
249
|
+
// Reports must be on to keep the report; turning it on is a command
|
|
250
|
+
// like any other, so the reply says it ran.
|
|
251
|
+
const added = options.store.ids.includes(REPORTS_RECIPE)
|
|
252
|
+
? []
|
|
253
|
+
: applyRecipes(planner, { add: [REPORTS_RECIPE], remove: [] }).added;
|
|
254
|
+
return {
|
|
255
|
+
added,
|
|
256
|
+
ref: {
|
|
257
|
+
name: REPORT_DEFINE_TOOL,
|
|
258
|
+
phase: 'preview',
|
|
259
|
+
result: defined.proposal,
|
|
260
|
+
},
|
|
261
|
+
text: reportPreviewText(defined.proposal.spec.title, defined.proposal.preview.rowCount),
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
const followUp = defined.followUp;
|
|
265
|
+
if (!followUp) {
|
|
266
|
+
pending = null;
|
|
267
|
+
return { added: [], text: defined.question };
|
|
268
|
+
}
|
|
269
|
+
if (previous && sameFollowUp(previous, followUp)) {
|
|
270
|
+
const pick = followUp.options.find((o) => o.value === followUp.default);
|
|
271
|
+
if (pick) {
|
|
272
|
+
const next = await buildReport(reports, mergeIntent(intent, pick.apply), text, followUp);
|
|
273
|
+
return { ...next, text: `I went with ${pick.label}. ${next.text}` };
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
const question = reportQuestion(followUp, `report-${++questions}`);
|
|
277
|
+
pending = { intent, followUp, question, text };
|
|
278
|
+
return { added: [], ref: question, text: followUp.prompt };
|
|
279
|
+
}
|
|
280
|
+
/** The option a form submission or a typed answer picked. */
|
|
281
|
+
function pickedOption(followUp, values) {
|
|
282
|
+
const chosen = values[followUp.field];
|
|
283
|
+
const value = Array.isArray(chosen) ? chosen[0] : chosen;
|
|
284
|
+
return followUp.options.find((o) => o.value === value);
|
|
285
|
+
}
|
|
286
|
+
/** Continue a pending report with a picked option, with no model turn. */
|
|
287
|
+
async function answerPending(reports, option, reply = '') {
|
|
288
|
+
const current = pending;
|
|
289
|
+
if (!current)
|
|
290
|
+
return { content: '' };
|
|
291
|
+
const built = await buildReport(reports, mergeIntent(current.intent, option.apply), `${current.text} ${reply}`.trim(), current.followUp);
|
|
292
|
+
const content = [
|
|
293
|
+
describeChange({ added: built.added, removed: [], kept: [] }, options.recipes),
|
|
294
|
+
built.text,
|
|
295
|
+
]
|
|
296
|
+
.filter(Boolean)
|
|
297
|
+
.join(' ');
|
|
298
|
+
if (content)
|
|
299
|
+
options.onReply?.(content);
|
|
300
|
+
return { content, refs: built.ref };
|
|
301
|
+
}
|
|
302
|
+
const reportsHost = () => options.recipes.some((r) => r.id === REPORTS_RECIPE)
|
|
303
|
+
? (options.reports?.() ?? null)
|
|
304
|
+
: null;
|
|
109
305
|
const push = (role, content, clientRequestId, toolCallData) => {
|
|
110
306
|
const message = {
|
|
111
307
|
id: id('m'),
|
|
@@ -133,6 +329,16 @@ export function createBrowserAssistantTransport(options) {
|
|
|
133
329
|
});
|
|
134
330
|
const greeting = push('assistant', GREETING);
|
|
135
331
|
async function turn(text) {
|
|
332
|
+
// A typed answer to the pending report question resolves against its
|
|
333
|
+
// options in code: no model turn, and "the date month" means the date by
|
|
334
|
+
// month whatever the model would have made of it.
|
|
335
|
+
const pendingReports = pending ? reportsHost() : null;
|
|
336
|
+
if (pending && pendingReports) {
|
|
337
|
+
const option = directAnswer(pending.followUp, pending.question, text);
|
|
338
|
+
// The reply's own time words ("status last month") still count.
|
|
339
|
+
if (option)
|
|
340
|
+
return answerPending(pendingReports, option, text);
|
|
341
|
+
}
|
|
136
342
|
const model = options.model();
|
|
137
343
|
if (!model) {
|
|
138
344
|
return {
|
|
@@ -155,15 +361,25 @@ export function createBrowserAssistantTransport(options) {
|
|
|
155
361
|
}));
|
|
156
362
|
const matches = matchText(index, text);
|
|
157
363
|
const menu = options.menu?.() ?? [];
|
|
364
|
+
// `reports.runtime.sources`: what a report may cover in this app.
|
|
365
|
+
const reports = reportsHost();
|
|
366
|
+
const reportSources = reports?.sources() ?? [];
|
|
367
|
+
const asked = pending;
|
|
158
368
|
const raw = await model.message(text, {
|
|
159
369
|
history: [
|
|
160
370
|
{
|
|
161
371
|
role: 'system',
|
|
162
|
-
content: buildSystemPrompt(options.recipes, options.store.ids, cookbooks, options.settings?.read(), matches, options.theme ? { current: options.theme.read() } : undefined, menu),
|
|
372
|
+
content: buildSystemPrompt(options.recipes, options.store.ids, cookbooks, options.settings?.read(), matches, options.theme ? { current: options.theme.read() } : undefined, menu, reportSources.map(({ id, label }) => ({ id, label })), asked
|
|
373
|
+
? {
|
|
374
|
+
source: asked.intent.source,
|
|
375
|
+
prompt: asked.followUp.prompt,
|
|
376
|
+
options: asked.followUp.options.map((o) => o.label),
|
|
377
|
+
}
|
|
378
|
+
: undefined),
|
|
163
379
|
},
|
|
164
380
|
...prior,
|
|
165
381
|
],
|
|
166
|
-
responseSchema: buildResponseSchema(options.recipes, cookbooks, !!options.settings, !!options.theme, menu.map((section) => section.id)),
|
|
382
|
+
responseSchema: buildResponseSchema(options.recipes, cookbooks, !!options.settings, !!options.theme, menu.map((section) => section.id), reportSources.map((source) => source.id)),
|
|
167
383
|
temperature: 0,
|
|
168
384
|
maxTokens: MAX_REPLY_TOKENS,
|
|
169
385
|
signal: controller.signal,
|
|
@@ -173,7 +389,16 @@ export function createBrowserAssistantTransport(options) {
|
|
|
173
389
|
? options.acceptCommands()
|
|
174
390
|
: options.acceptCommands,
|
|
175
391
|
sections: menu.map((section) => section.id),
|
|
392
|
+
reports: reportSources.length > 0,
|
|
176
393
|
});
|
|
394
|
+
// A report turn is driven by code, not by the model's other choices: a
|
|
395
|
+
// report is never a recipe to add or a section to open ("sales report"
|
|
396
|
+
// must not land in the product catalogue). Settings and theme still apply.
|
|
397
|
+
if (change.report) {
|
|
398
|
+
change.add = [];
|
|
399
|
+
change.remove = [];
|
|
400
|
+
delete change.open;
|
|
401
|
+
}
|
|
177
402
|
const applied = applyRecipes(planner, change);
|
|
178
403
|
const settingsText = options.settings && hasKeys(change.settings)
|
|
179
404
|
? runSummary(planner, 'set_settings', change.settings)
|
|
@@ -199,7 +424,49 @@ export function createBrowserAssistantTransport(options) {
|
|
|
199
424
|
? change.open
|
|
200
425
|
: undefined;
|
|
201
426
|
const openText = open ? openSection(planner, open, menu) : '';
|
|
202
|
-
|
|
427
|
+
// `reports.runtime.define` (preview) then `reports.runtime.run`, by code
|
|
428
|
+
// (`buildReport`). An answer to a pending follow-up merges into its
|
|
429
|
+
// intent; a turn that answers nothing takes the sensible default rather
|
|
430
|
+
// than asking the same question again.
|
|
431
|
+
let reportText = '';
|
|
432
|
+
let reportRef;
|
|
433
|
+
let reportIntent = null;
|
|
434
|
+
let reportWords = text;
|
|
435
|
+
if (asked && change.report) {
|
|
436
|
+
reportIntent = mergeIntent(asked.intent, change.report);
|
|
437
|
+
reportWords = `${asked.text} ${text}`;
|
|
438
|
+
}
|
|
439
|
+
else if (change.report) {
|
|
440
|
+
reportIntent = change.report;
|
|
441
|
+
}
|
|
442
|
+
const didOther = applied.added.length > 0 ||
|
|
443
|
+
applied.removed.length > 0 ||
|
|
444
|
+
!!settingsText ||
|
|
445
|
+
!!themed?.summary ||
|
|
446
|
+
!!commandText ||
|
|
447
|
+
!!openText ||
|
|
448
|
+
!!change.cookbook;
|
|
449
|
+
if (reports && reportIntent) {
|
|
450
|
+
const built = await buildReport(reports, reportIntent, reportWords, asked?.followUp ?? null);
|
|
451
|
+
applied.added.push(...built.added);
|
|
452
|
+
reportText = built.text;
|
|
453
|
+
reportRef = built.ref;
|
|
454
|
+
}
|
|
455
|
+
else if (reports && asked && !didOther) {
|
|
456
|
+
// A second miss: never the identical question again.
|
|
457
|
+
const pick = asked.followUp.options.find((o) => o.value === asked.followUp.default);
|
|
458
|
+
if (pick) {
|
|
459
|
+
const built = await buildReport(reports, mergeIntent(asked.intent, pick.apply), asked.text, asked.followUp);
|
|
460
|
+
applied.added.push(...built.added);
|
|
461
|
+
reportText = `I went with ${pick.label}. ${built.text}`;
|
|
462
|
+
reportRef = built.ref;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
else if (asked) {
|
|
466
|
+
// The person moved on to something else.
|
|
467
|
+
pending = null;
|
|
468
|
+
}
|
|
469
|
+
const ran = [
|
|
203
470
|
describeChange(applied, options.recipes),
|
|
204
471
|
settingsText,
|
|
205
472
|
themed?.summary ?? '',
|
|
@@ -208,6 +475,30 @@ export function createBrowserAssistantTransport(options) {
|
|
|
208
475
|
]
|
|
209
476
|
.filter(Boolean)
|
|
210
477
|
.join(' ');
|
|
478
|
+
// The model adding Reports is a report request too, whatever the words.
|
|
479
|
+
const askedForReport = reportRequest || applied.added.includes(REPORTS_RECIPE);
|
|
480
|
+
if (askedForReport &&
|
|
481
|
+
!change.report &&
|
|
482
|
+
!asked &&
|
|
483
|
+
!openText &&
|
|
484
|
+
!applied.removed.length) {
|
|
485
|
+
// Asked for a report but named nothing to build (adding Reports alone
|
|
486
|
+
// builds nothing): ask which records, never guess, or say this planner
|
|
487
|
+
// cannot build one. Going to the Reports section needs no question.
|
|
488
|
+
const followUp = reports ? sourceFollowUp(reportSources) : null;
|
|
489
|
+
if (followUp) {
|
|
490
|
+
const question = reportQuestion(followUp, `report-${++questions}`);
|
|
491
|
+
pending = { intent: { source: '' }, followUp, question, text };
|
|
492
|
+
reportText = followUp.prompt;
|
|
493
|
+
reportRef = question;
|
|
494
|
+
}
|
|
495
|
+
else {
|
|
496
|
+
reportText = reports
|
|
497
|
+
? whichSourceQuestion(reportSources)
|
|
498
|
+
: REPORTS_UNAVAILABLE;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
const summary = [ran, reportText].filter(Boolean).join(' ');
|
|
211
502
|
// Backstop: a small model sometimes misses a plain "I run a bakery".
|
|
212
503
|
// A strong cookbook match is offered anyway (never applied without the
|
|
213
504
|
// click) when the model offered none and none is applied or pending.
|
|
@@ -224,16 +515,13 @@ export function createBrowserAssistantTransport(options) {
|
|
|
224
515
|
? cookbooks.find((c) => c.id === cookbookId)
|
|
225
516
|
: undefined;
|
|
226
517
|
const line = change.reply || (offered ? `Set up ${offered.name}?` : '');
|
|
227
|
-
const reply =
|
|
228
|
-
honestReply(line, summary, !!offer),
|
|
229
|
-
reportRequest ? REPORTS_PENDING : '',
|
|
230
|
-
]
|
|
231
|
-
.filter(Boolean)
|
|
232
|
-
.join(' ');
|
|
518
|
+
const reply = honestReply(line, summary, !!offer);
|
|
233
519
|
if (reply)
|
|
234
520
|
options.onReply?.(reply);
|
|
235
|
-
// One ref renders as is; a cookbook offer
|
|
236
|
-
|
|
521
|
+
// One ref renders as is; several in one turn (a cookbook offer, a theme
|
|
522
|
+
// Undo, a report preview) ride together.
|
|
523
|
+
const all = [offer, undo, reportRef].filter(Boolean);
|
|
524
|
+
const refs = all.length > 1 ? all : all[0];
|
|
237
525
|
return { content: reply, refs };
|
|
238
526
|
}
|
|
239
527
|
catch (error) {
|
|
@@ -270,6 +558,61 @@ export function createBrowserAssistantTransport(options) {
|
|
|
270
558
|
seen.set(input.clientRequestId, result);
|
|
271
559
|
return result;
|
|
272
560
|
},
|
|
561
|
+
/**
|
|
562
|
+
* The report follow-up's form, submitted: its pick merges into the
|
|
563
|
+
* pending intent and the flow continues (preview, then confirmation) with
|
|
564
|
+
* no model turn. The question is marked answered for the transcript.
|
|
565
|
+
*/
|
|
566
|
+
async answerQuestion(input) {
|
|
567
|
+
const cached = seen.get(input.clientRequestId);
|
|
568
|
+
if (cached)
|
|
569
|
+
return cached;
|
|
570
|
+
const reports = reportsHost();
|
|
571
|
+
if (!pending || !reports || pending.question.id !== input.questionId) {
|
|
572
|
+
throw new Error('That question is no longer open. Ask again?');
|
|
573
|
+
}
|
|
574
|
+
const values = validateAssistantQuestionAnswer(pending.question, input.values);
|
|
575
|
+
const option = values
|
|
576
|
+
? pickedOption(pending.followUp, values)
|
|
577
|
+
: undefined;
|
|
578
|
+
if (!values || !option)
|
|
579
|
+
throw new Error('Choose one of the options.');
|
|
580
|
+
const asked = messages.find((m) => m.id === input.messageId);
|
|
581
|
+
if (asked) {
|
|
582
|
+
const mark = (ref) => {
|
|
583
|
+
const item = ref;
|
|
584
|
+
return item?.kind === ASSISTANT_QUESTION_KIND &&
|
|
585
|
+
item.id === input.questionId
|
|
586
|
+
? { ...item, answer: values }
|
|
587
|
+
: ref;
|
|
588
|
+
};
|
|
589
|
+
asked.toolCallData = Array.isArray(asked.toolCallData)
|
|
590
|
+
? asked.toolCallData.map(mark)
|
|
591
|
+
: mark(asked.toolCallData);
|
|
592
|
+
}
|
|
593
|
+
const reply = await answerPending(reports, option);
|
|
594
|
+
const result = {
|
|
595
|
+
inProgress: false,
|
|
596
|
+
...(asked ? { messages: [asked] } : {}),
|
|
597
|
+
assistantMessage: push('assistant', reply.content, undefined, reply.refs),
|
|
598
|
+
};
|
|
599
|
+
seen.set(input.clientRequestId, result);
|
|
600
|
+
return result;
|
|
601
|
+
},
|
|
602
|
+
recordReportOutcome(specHash, outcome) {
|
|
603
|
+
for (const message of messages) {
|
|
604
|
+
const refs = Array.isArray(message.toolCallData)
|
|
605
|
+
? message.toolCallData
|
|
606
|
+
: [message.toolCallData];
|
|
607
|
+
for (const ref of refs) {
|
|
608
|
+
const item = ref;
|
|
609
|
+
if (item?.name === REPORT_DEFINE_TOOL &&
|
|
610
|
+
item.result?.specHash === specHash) {
|
|
611
|
+
item.outcome = outcome;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
},
|
|
273
616
|
async uploadAttachment(file) {
|
|
274
617
|
throw new Error(`The assistant cannot take attachments (${file.name}).`);
|
|
275
618
|
},
|