@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.
Files changed (574) hide show
  1. package/agents/assistant.md +29 -2
  2. package/agents/shell.md +13 -0
  3. package/app/404.html +27 -30
  4. package/app/_app/immutable/assets/0.BaRFeYGU.css +1 -0
  5. package/app/_app/immutable/assets/AppShell.BkKNrxND.css +1 -0
  6. package/app/_app/immutable/assets/{ModelPage.FEM0ZnPM.css → ModelPage.SIoeO-AU.css} +1 -1
  7. package/app/_app/immutable/assets/app.BHwMQ9Zv.css +1 -0
  8. package/app/_app/immutable/assets/{forms.DXOeP4wZ.css → forms.BRdbPdvs.css} +1 -1
  9. package/app/_app/immutable/assets/icons.BDx21rPt.css +1 -0
  10. package/app/_app/immutable/assets/labels.Dxa6EyRI.css +1 -0
  11. package/app/_app/immutable/assets/planner.DOQVfcOi.css +1 -0
  12. package/app/_app/immutable/assets/state.C0UZEhxS.css +1 -0
  13. package/app/_app/immutable/chunks/{C1VofLtR.js → B2uXaQfZ.js} +1 -1
  14. package/app/_app/immutable/chunks/{DuZeZzOA.js → BQLQsso4.js} +1 -1
  15. package/app/_app/immutable/chunks/BdOPgmQ_.js +11 -0
  16. package/app/_app/immutable/chunks/BeL8dJx9.js +4 -0
  17. package/app/_app/immutable/chunks/{Bal1oPZu.js → Bhd-3niN.js} +1 -1
  18. package/app/_app/immutable/chunks/{CTlMHIE6.js → BqEBz5Vq.js} +1 -1
  19. package/app/_app/immutable/chunks/{GdHEbDDH.js → BxyJ_Q7v.js} +1 -1
  20. package/app/_app/immutable/chunks/{C3sRGrYK.js → C2OYATC6.js} +1 -1
  21. package/app/_app/immutable/chunks/C6AANt9H.js +26 -0
  22. package/app/_app/immutable/chunks/{BybfWt-B.js → C8FX0hli.js} +6 -6
  23. package/app/_app/immutable/chunks/{BDbFl7UA.js → CYhwv6d2.js} +1 -1
  24. package/app/_app/immutable/chunks/CdKHckEF.js +1 -0
  25. package/app/_app/immutable/chunks/CsaWd8kG.js +2 -0
  26. package/app/_app/immutable/chunks/Cwz7QFS4.js +2 -0
  27. package/app/_app/immutable/chunks/{BG9Gz_25.js → D3lXu_rt.js} +25 -25
  28. package/app/_app/immutable/chunks/{YGONf0jr.js → D8MqcCKq.js} +1 -1
  29. package/app/_app/immutable/chunks/DF-0MxNw.js +1 -0
  30. package/app/_app/immutable/chunks/DGaFQflg.js +1 -0
  31. package/app/_app/immutable/chunks/DIE02RSm.js +1 -0
  32. package/app/_app/immutable/chunks/DIgo5ngo.js +1 -0
  33. package/app/_app/immutable/chunks/{5ukUzDcw.js → Db12RzZi.js} +1 -1
  34. package/app/_app/immutable/chunks/{Cga8zF3r.js → DfN2k_EX.js} +1 -1
  35. package/app/_app/immutable/chunks/DmHVTNcC.js +4 -0
  36. package/app/_app/immutable/chunks/{gCpxN2IC.js → DmdvNG82.js} +2 -2
  37. package/app/_app/immutable/chunks/{DjJovMrk.js → DwIRC3h5.js} +1 -1
  38. package/app/_app/immutable/chunks/{nphy1MQF.js → FeyhlLIZ.js} +1 -1
  39. package/app/_app/immutable/chunks/ICDFUCZL.js +2 -0
  40. package/app/_app/immutable/chunks/IDZmjRDr.js +1 -0
  41. package/app/_app/immutable/chunks/JqlEoPqZ.js +1 -0
  42. package/app/_app/immutable/chunks/{BiEOJeYb.js → TcjpRcdI.js} +1 -1
  43. package/app/_app/immutable/chunks/Vt9hDpHd.js +1 -0
  44. package/app/_app/immutable/chunks/ezs6CGyc.js +1 -0
  45. package/app/_app/immutable/chunks/lUJaueNM.js +16 -0
  46. package/app/_app/immutable/entry/app.C5bxPKCP.js +2 -0
  47. package/app/_app/immutable/entry/start.CZvO61qD.js +1 -0
  48. package/app/_app/immutable/nodes/0.DFJFBCCB.js +7 -0
  49. package/app/_app/immutable/nodes/{1.DKP901Gn.js → 1.D_79m87b.js} +1 -1
  50. package/app/_app/immutable/nodes/{10.DNN0cVai.js → 10.20u2-jxn.js} +1 -1
  51. package/app/_app/immutable/nodes/{11.DgbmegX3.js → 11.CvMq32jC.js} +1 -1
  52. package/app/_app/immutable/nodes/{12.D5MtnJoE.js → 12.Cd0cy1AC.js} +1 -1
  53. package/app/_app/immutable/nodes/{13._rY66Xa_.js → 13.DYYS3YVQ.js} +1 -1
  54. package/app/_app/immutable/nodes/14.BEf5BJDn.js +1 -0
  55. package/app/_app/immutable/nodes/2.C_kLkHNl.js +24 -0
  56. package/app/_app/immutable/nodes/{3.V5uGCpGb.js → 3.CZw3hv8O.js} +1 -1
  57. package/app/_app/immutable/nodes/{4.CCwzLrgu.js → 4.WMU9NDex.js} +1 -1
  58. package/app/_app/immutable/nodes/{5.CgHzwpns.js → 5.CuqxSfl4.js} +1 -1
  59. package/app/_app/immutable/nodes/{6.CvQHLh_u.js → 6.BXLQB7tR.js} +1 -1
  60. package/app/_app/immutable/nodes/{7.7EIrly34.js → 7.BZvxNeL2.js} +1 -1
  61. package/app/_app/immutable/nodes/{8.DyyRBuTw.js → 8.Bj2O4pyx.js} +1 -1
  62. package/app/_app/immutable/nodes/{9.DcURs0gN.js → 9.yeFzeUHj.js} +1 -1
  63. package/app/_app/version.json +1 -1
  64. package/app/advanced-styles/index.html +34 -35
  65. package/app/ai/index.html +39 -40
  66. package/app/blueprint/index.html +29 -32
  67. package/app/cookbook/index.html +29 -32
  68. package/app/index.html +39 -42
  69. package/app/m/ads/AdDeliveryTier/index.html +36 -37
  70. package/app/m/ads/AdEvent/index.html +36 -37
  71. package/app/m/ads/AdFormat/index.html +36 -37
  72. package/app/m/ads/AdGroup/index.html +36 -37
  73. package/app/m/ads/AdVariation/index.html +36 -37
  74. package/app/m/analytics/AnalyticsDataStream/index.html +36 -37
  75. package/app/m/analytics/AnalyticsEvent/index.html +36 -37
  76. package/app/m/analytics/AnalyticsProperty/index.html +36 -37
  77. package/app/m/analytics/AnalyticsReport/index.html +36 -37
  78. package/app/m/approvals/ApprovalEvent/index.html +36 -37
  79. package/app/m/approvals/ApprovalPolicy/index.html +36 -37
  80. package/app/m/approvals/ApprovalRequest/index.html +36 -37
  81. package/app/m/assets/Asset/attachments/index.html +38 -39
  82. package/app/m/assets/Asset/index.html +36 -37
  83. package/app/m/assets/AssetAssociation/index.html +36 -37
  84. package/app/m/assets/AssetMetafield/index.html +36 -37
  85. package/app/m/assets/AssetStatus/index.html +36 -37
  86. package/app/m/assets/AssetType/index.html +36 -37
  87. package/app/m/assets/Folder/index.html +36 -37
  88. package/app/m/chat/AgentSession/index.html +36 -37
  89. package/app/m/chat/ChatMessage/index.html +36 -37
  90. package/app/m/chat/ChatParticipant/index.html +36 -37
  91. package/app/m/chat/ChatReaction/index.html +36 -37
  92. package/app/m/chat/ChatRoom/index.html +36 -37
  93. package/app/m/chat/ChatThread/index.html +36 -37
  94. package/app/m/chat/VoiceGatewayTurn/index.html +36 -37
  95. package/app/m/chat/VoiceSession/index.html +36 -37
  96. package/app/m/commerce/Agreement/index.html +36 -37
  97. package/app/m/commerce/Cart/index.html +36 -37
  98. package/app/m/commerce/Contract/index.html +36 -37
  99. package/app/m/commerce/ContractLineItem/index.html +36 -37
  100. package/app/m/commerce/Customer/index.html +36 -37
  101. package/app/m/commerce/DocumentTax/index.html +36 -37
  102. package/app/m/commerce/Estimate/index.html +36 -37
  103. package/app/m/commerce/Fulfillment/index.html +36 -37
  104. package/app/m/commerce/FulfillmentLineItem/index.html +36 -37
  105. package/app/m/commerce/HistoricalCustomerFunds/index.html +36 -37
  106. package/app/m/commerce/HistoricalCustomerFundsAllocation/index.html +36 -37
  107. package/app/m/commerce/HistoricalSalesLine/index.html +36 -37
  108. package/app/m/commerce/Invoice/index.html +36 -37
  109. package/app/m/commerce/InvoiceLineItem/index.html +36 -37
  110. package/app/m/commerce/Lease/index.html +36 -37
  111. package/app/m/commerce/LicenseSale/index.html +36 -37
  112. package/app/m/commerce/Order/index.html +36 -37
  113. package/app/m/commerce/Payment/index.html +36 -37
  114. package/app/m/commerce/PaymentAllocation/index.html +36 -37
  115. package/app/m/commerce/PaymentInstrument/index.html +36 -37
  116. package/app/m/commerce/PaymentIntent/index.html +36 -37
  117. package/app/m/commerce/Payout/index.html +36 -37
  118. package/app/m/commerce/ProductionOrder/index.html +36 -37
  119. package/app/m/commerce/PurchaseContract/index.html +36 -37
  120. package/app/m/commerce/PurchaseOrder/index.html +36 -37
  121. package/app/m/commerce/SalesContract/index.html +36 -37
  122. package/app/m/commerce/SupplierQuote/index.html +36 -37
  123. package/app/m/commerce/TaxCode/index.html +36 -37
  124. package/app/m/commerce/TaxComponent/index.html +36 -37
  125. package/app/m/commerce/TaxSettings/index.html +36 -37
  126. package/app/m/commerce/TaxSummaryReport/index.html +36 -37
  127. package/app/m/commerce/Vendor/index.html +36 -37
  128. package/app/m/commerce/WholesaleOrder/index.html +36 -37
  129. package/app/m/content/Content/index.html +36 -37
  130. package/app/m/content/ContentContribution/index.html +36 -37
  131. package/app/m/content/ContentContributionAttachment/index.html +36 -37
  132. package/app/m/content/ContentContributionRevision/index.html +36 -37
  133. package/app/m/content/ContentContributionType/index.html +36 -37
  134. package/app/m/content/ContentContributor/index.html +36 -37
  135. package/app/m/content/ContentCorrection/index.html +36 -37
  136. package/app/m/content/ContentFeedSource/index.html +36 -37
  137. package/app/m/content/ContentGovernanceAssignment/index.html +36 -37
  138. package/app/m/content/ContentGovernancePolicy/index.html +36 -37
  139. package/app/m/content/ContentGovernanceProfile/index.html +36 -37
  140. package/app/m/content/ContentReference/index.html +36 -37
  141. package/app/m/content/ContentReview/index.html +36 -37
  142. package/app/m/content/ContentVersion/index.html +36 -37
  143. package/app/m/events/Event/index.html +36 -37
  144. package/app/m/events/EventParticipant/index.html +36 -37
  145. package/app/m/events/EventSeries/index.html +36 -37
  146. package/app/m/events/EventType/index.html +36 -37
  147. package/app/m/expenses/Expense/index.html +36 -37
  148. package/app/m/facts/Fact/index.html +36 -37
  149. package/app/m/facts/FactContent/index.html +36 -37
  150. package/app/m/facts/FactEvidence/index.html +36 -37
  151. package/app/m/facts/FactSource/index.html +36 -37
  152. package/app/m/facts/FactSubject/index.html +36 -37
  153. package/app/m/facts/FactTag/index.html +36 -37
  154. package/app/m/fields/FieldPolicy/index.html +36 -37
  155. package/app/m/fields/FieldPolicySuggestion/index.html +36 -37
  156. package/app/m/fields/FieldUsageCounter/index.html +36 -37
  157. package/app/m/images/Image/index.html +36 -37
  158. package/app/m/inventory/InventoryLocation/index.html +36 -37
  159. package/app/m/inventory/StockLevel/index.html +36 -37
  160. package/app/m/inventory/StockMovement/index.html +36 -37
  161. package/app/m/ledgers/Account/index.html +36 -37
  162. package/app/m/ledgers/Journal/index.html +36 -37
  163. package/app/m/ledgers/JournalEntry/index.html +36 -37
  164. package/app/m/ledgers/Ledger/index.html +36 -37
  165. package/app/m/manufacturing/Assembly/index.html +36 -37
  166. package/app/m/manufacturing/BillOfMaterials/index.html +36 -37
  167. package/app/m/manufacturing/BomLine/index.html +36 -37
  168. package/app/m/manufacturing/Operation/index.html +36 -37
  169. package/app/m/manufacturing/ProductionRun/index.html +36 -37
  170. package/app/m/manufacturing/ProductionRunCompletion/index.html +36 -37
  171. package/app/m/manufacturing/RoutingStep/index.html +36 -37
  172. package/app/m/marketing/Campaign/index.html +36 -37
  173. package/app/m/marketing/CampaignChannel/index.html +36 -37
  174. package/app/m/marketing/CampaignMetricSnapshot/index.html +36 -37
  175. package/app/m/messages/Account/index.html +36 -37
  176. package/app/m/messages/Attachment/index.html +36 -37
  177. package/app/m/messages/Blacklist/index.html +36 -37
  178. package/app/m/messages/Email/failed-sends/index.html +38 -39
  179. package/app/m/messages/Email/index.html +36 -37
  180. package/app/m/messages/Email/mailbox/index.html +38 -39
  181. package/app/m/messages/EmailAccount/index.html +36 -37
  182. package/app/m/messages/EmailAttachment/index.html +36 -37
  183. package/app/m/messages/EmailFolder/index.html +36 -37
  184. package/app/m/messages/Message/index.html +36 -37
  185. package/app/m/messages/MessagingEndpoint/index.html +36 -37
  186. package/app/m/messages/PersonaMessageRoute/index.html +36 -37
  187. package/app/m/messages/SlackAccount/index.html +36 -37
  188. package/app/m/messages/SlackMessage/index.html +36 -37
  189. package/app/m/messages/TelegramAccount/index.html +36 -37
  190. package/app/m/messages/Tweet/index.html +36 -37
  191. package/app/m/messages/TwitterAccount/index.html +36 -37
  192. package/app/m/messages/Whitelist/index.html +36 -37
  193. package/app/m/messages/ZulipAccount/index.html +36 -37
  194. package/app/m/places/Place/index.html +36 -37
  195. package/app/m/places/PlaceType/index.html +36 -37
  196. package/app/m/products/Category/index.html +36 -37
  197. package/app/m/products/Material/index.html +36 -37
  198. package/app/m/products/Product/index.html +36 -37
  199. package/app/m/products/Product/ingredients/index.html +38 -39
  200. package/app/m/products/ProductVariant/index.html +36 -37
  201. package/app/m/products/Sku/index.html +36 -37
  202. package/app/m/profiles/ApiKey/index.html +36 -37
  203. package/app/m/profiles/Bot/index.html +36 -37
  204. package/app/m/profiles/MagicLinkToken/index.html +36 -37
  205. package/app/m/profiles/NostrIdentity/index.html +36 -37
  206. package/app/m/profiles/OidcIdentity/index.html +36 -37
  207. package/app/m/profiles/Organization/index.html +36 -37
  208. package/app/m/profiles/Person/index.html +36 -37
  209. package/app/m/profiles/Profile/index.html +36 -37
  210. package/app/m/profiles/ProfileMetadata/index.html +36 -37
  211. package/app/m/profiles/ProfileMetafield/index.html +36 -37
  212. package/app/m/profiles/ProfileRelationship/index.html +36 -37
  213. package/app/m/profiles/ProfileRelationshipTerm/index.html +36 -37
  214. package/app/m/profiles/ProfileRelationshipType/index.html +36 -37
  215. package/app/m/profiles/ProfileType/index.html +36 -37
  216. package/app/m/projects/Comment/index.html +36 -37
  217. package/app/m/projects/Issue/index.html +36 -37
  218. package/app/m/projects/Label/index.html +36 -37
  219. package/app/m/projects/Project/index.html +36 -37
  220. package/app/m/projects/ProjectIntegration/index.html +36 -37
  221. package/app/m/projects/PullRequest/index.html +36 -37
  222. package/app/m/projects/Repository/index.html +36 -37
  223. package/app/m/properties/Property/index.html +36 -37
  224. package/app/m/properties/Zone/index.html +36 -37
  225. package/app/m/reports/RuntimeReport/index.html +39 -37
  226. package/app/m/reports/SmrtPrincipalReportRefreshTask/index.html +36 -37
  227. package/app/m/reports/SmrtReportLock/index.html +36 -37
  228. package/app/m/reports/SmrtReportRefreshTask/index.html +36 -37
  229. package/app/m/reports/SmrtReportRun/index.html +36 -37
  230. package/app/m/reports/SmrtReportSchedule/index.html +36 -37
  231. package/app/m/reports/SmrtReportWatermark/index.html +36 -37
  232. package/app/m/sales/Agreement/index.html +36 -37
  233. package/app/m/sales/AttributionException/index.html +36 -37
  234. package/app/m/sales/AttributionPolicy/index.html +36 -37
  235. package/app/m/sales/Commission/index.html +36 -37
  236. package/app/m/sales/CommissionAdjustment/index.html +36 -37
  237. package/app/m/sales/CommissionPayout/index.html +36 -37
  238. package/app/m/sales/CommissionPlan/index.html +36 -37
  239. package/app/m/sales/Earner/index.html +36 -37
  240. package/app/m/sales/EarnerSourceAttribution/index.html +36 -37
  241. package/app/m/sales/EarningEvent/index.html +36 -37
  242. package/app/m/sales/ExecutedAgreement/index.html +36 -37
  243. package/app/m/sales/Lead/index.html +36 -37
  244. package/app/m/sales/Opportunity/index.html +36 -37
  245. package/app/m/sales/OpportunityConversion/index.html +36 -37
  246. package/app/m/sales/PipelineDefinition/index.html +36 -37
  247. package/app/m/sales/PipelineStage/index.html +36 -37
  248. package/app/m/sales/Referral/index.html +36 -37
  249. package/app/m/sales/ReferralAgreement/index.html +36 -37
  250. package/app/m/sales/ReferralLink/index.html +36 -37
  251. package/app/m/sales/ReferralProgram/index.html +36 -37
  252. package/app/m/sales/ReferralTermSnapshot/index.html +36 -37
  253. package/app/m/sales/ReferralTouch/index.html +36 -37
  254. package/app/m/sales/Referrer/index.html +36 -37
  255. package/app/m/sales/SalesActivity/index.html +36 -37
  256. package/app/m/sales/SalesRepresentative/index.html +36 -37
  257. package/app/m/sites/Site/index.html +36 -37
  258. package/app/m/sites/SiteAgentBinding/index.html +36 -37
  259. package/app/m/social/OAuthState/index.html +36 -37
  260. package/app/m/social/SocialAccount/index.html +36 -37
  261. package/app/m/social/SocialPost/index.html +36 -37
  262. package/app/m/social/SocialPostAnalyticsSnapshot/index.html +36 -37
  263. package/app/m/subscriptions/BillingAdjustment/index.html +36 -37
  264. package/app/m/subscriptions/ClientCharge/index.html +36 -37
  265. package/app/m/subscriptions/CreditGrant/index.html +36 -37
  266. package/app/m/subscriptions/PricingRule/index.html +36 -37
  267. package/app/m/subscriptions/RetailCharge/index.html +36 -37
  268. package/app/m/subscriptions/SpendingPolicy/index.html +36 -37
  269. package/app/m/subscriptions/SubscriptionPlan/index.html +36 -37
  270. package/app/m/subscriptions/TenantSubscription/index.html +36 -37
  271. package/app/m/subscriptions/TenantUsageMetric/index.html +36 -37
  272. package/app/m/support/ServiceTimeEntry/index.html +36 -37
  273. package/app/m/support/SupportAiRun/index.html +36 -37
  274. package/app/m/support/SupportAvailability/index.html +36 -37
  275. package/app/m/support/SupportCase/index.html +36 -37
  276. package/app/m/support/SupportCaseEvent/index.html +36 -37
  277. package/app/m/support/SupportChannelBinding/index.html +36 -37
  278. package/app/m/support/SupportCharge/index.html +36 -37
  279. package/app/m/support/SupportCompensation/index.html +36 -37
  280. package/app/m/support/SupportCompensationPlan/index.html +36 -37
  281. package/app/m/support/SupportEscalation/index.html +36 -37
  282. package/app/m/support/SupportInteraction/index.html +36 -37
  283. package/app/m/support/SupportPlan/index.html +36 -37
  284. package/app/m/support/SupportPolicy/index.html +36 -37
  285. package/app/m/support/SupportQualification/index.html +36 -37
  286. package/app/m/support/SupportServiceTarget/index.html +36 -37
  287. package/app/m/support/SupportSpecialist/index.html +36 -37
  288. package/app/m/support/SupportWorkLink/index.html +36 -37
  289. package/app/m/tags/Tag/index.html +36 -37
  290. package/app/m/tags/TagAlias/index.html +36 -37
  291. package/app/m/timesheets/AttendanceBreak/index.html +36 -37
  292. package/app/m/timesheets/AttendancePunch/index.html +36 -37
  293. package/app/m/timesheets/AttendanceSegment/index.html +36 -37
  294. package/app/m/timesheets/ServiceChargeSnapshot/index.html +36 -37
  295. package/app/m/timesheets/ServiceCompensationSnapshot/index.html +36 -37
  296. package/app/m/timesheets/ServiceTimeEntry/index.html +36 -37
  297. package/app/m/users/Group/index.html +36 -37
  298. package/app/m/users/GroupMember/index.html +36 -37
  299. package/app/m/users/GroupRole/index.html +36 -37
  300. package/app/m/users/Membership/index.html +36 -37
  301. package/app/m/users/MembershipOverride/index.html +36 -37
  302. package/app/m/users/Permission/index.html +36 -37
  303. package/app/m/users/Role/index.html +36 -37
  304. package/app/m/users/RolePermission/index.html +36 -37
  305. package/app/m/users/Session/index.html +36 -37
  306. package/app/m/users/Tenant/index.html +36 -37
  307. package/app/m/users/TenantIntegration/index.html +36 -37
  308. package/app/m/users/TenantPermissionOverride/index.html +36 -37
  309. package/app/m/users/User/index.html +36 -37
  310. package/app/m/video/Character/index.html +36 -37
  311. package/app/m/video/CharacterAsset/index.html +36 -37
  312. package/app/m/video/CompositeJob/index.html +36 -37
  313. package/app/m/video/Performer/index.html +36 -37
  314. package/app/m/video/PerformerAsset/index.html +36 -37
  315. package/app/m/video/Scene/index.html +36 -37
  316. package/app/m/video/SceneAsset/index.html +36 -37
  317. package/app/m/video/VideoComposition/index.html +36 -37
  318. package/app/m/video/VideoCompositionAsset/index.html +36 -37
  319. package/app/m/video/VideoSequence/index.html +36 -37
  320. package/app/m/video/VideoSequenceAsset/index.html +36 -37
  321. package/app/m/video/VideoShot/index.html +36 -37
  322. package/app/m/video/VideoShotAsset/index.html +36 -37
  323. package/app/m/video/VideoShotCharacter/index.html +36 -37
  324. package/app/m/video/VideoWorkflow/index.html +36 -37
  325. package/app/m/voice/VoiceOutput/index.html +36 -37
  326. package/app/m/voice/VoiceProfile/index.html +36 -37
  327. package/app/m/voice/VoiceSample/index.html +36 -37
  328. package/app/mcp.html +2 -2
  329. package/app/packages/ads/index.html +30 -33
  330. package/app/packages/analytics/index.html +30 -33
  331. package/app/packages/approvals/index.html +30 -33
  332. package/app/packages/assets/index.html +30 -33
  333. package/app/packages/chat/index.html +30 -33
  334. package/app/packages/comments/index.html +30 -33
  335. package/app/packages/commerce/index.html +30 -33
  336. package/app/packages/content/index.html +30 -33
  337. package/app/packages/events/index.html +30 -33
  338. package/app/packages/expenses/index.html +30 -33
  339. package/app/packages/facts/index.html +30 -33
  340. package/app/packages/fields/index.html +30 -33
  341. package/app/packages/human-resources/index.html +30 -33
  342. package/app/packages/images/index.html +30 -33
  343. package/app/packages/index.html +30 -33
  344. package/app/packages/ingestion/index.html +30 -33
  345. package/app/packages/inventory/index.html +30 -33
  346. package/app/packages/ledgers/index.html +30 -33
  347. package/app/packages/manufacturing/index.html +30 -33
  348. package/app/packages/marketing/index.html +30 -33
  349. package/app/packages/messages/index.html +30 -33
  350. package/app/packages/places/index.html +30 -33
  351. package/app/packages/preferences/index.html +30 -33
  352. package/app/packages/products/index.html +30 -33
  353. package/app/packages/profiles/index.html +30 -33
  354. package/app/packages/projects/index.html +30 -33
  355. package/app/packages/properties/index.html +30 -33
  356. package/app/packages/reports/index.html +30 -33
  357. package/app/packages/sales/index.html +30 -33
  358. package/app/packages/sites/index.html +30 -33
  359. package/app/packages/social/index.html +30 -33
  360. package/app/packages/subscriptions/index.html +30 -33
  361. package/app/packages/support/index.html +30 -33
  362. package/app/packages/tags/index.html +30 -33
  363. package/app/packages/timesheets/index.html +30 -33
  364. package/app/packages/users/index.html +30 -33
  365. package/app/packages/video/index.html +30 -33
  366. package/app/packages/voice/index.html +30 -33
  367. package/app/packages/webhooks/index.html +30 -33
  368. package/app/recipes/account-access/help/index.html +32 -35
  369. package/app/recipes/account-access/index.html +36 -38
  370. package/app/recipes/activity/help/index.html +32 -35
  371. package/app/recipes/activity/index.html +36 -38
  372. package/app/recipes/agreements/help/index.html +32 -35
  373. package/app/recipes/agreements/index.html +36 -38
  374. package/app/recipes/analytics.reports/help/index.html +32 -35
  375. package/app/recipes/analytics.reports/index.html +36 -38
  376. package/app/recipes/assets/help/index.html +32 -35
  377. package/app/recipes/assets/index.html +36 -38
  378. package/app/recipes/billing/help/index.html +32 -35
  379. package/app/recipes/billing/index.html +36 -38
  380. package/app/recipes/chat.assistant/help/index.html +32 -35
  381. package/app/recipes/chat.assistant/index.html +36 -38
  382. package/app/recipes/comments/help/index.html +32 -35
  383. package/app/recipes/comments/index.html +36 -38
  384. package/app/recipes/commerce.customers/help/index.html +32 -35
  385. package/app/recipes/commerce.customers/index.html +36 -38
  386. package/app/recipes/commerce.estimates/help/index.html +32 -35
  387. package/app/recipes/commerce.estimates/index.html +36 -38
  388. package/app/recipes/commerce.purchases/help/index.html +32 -35
  389. package/app/recipes/commerce.purchases/index.html +36 -38
  390. package/app/recipes/commerce.sales/help/index.html +32 -35
  391. package/app/recipes/commerce.sales/index.html +36 -38
  392. package/app/recipes/commerce.vendors/help/index.html +32 -35
  393. package/app/recipes/commerce.vendors/index.html +36 -38
  394. package/app/recipes/commerce.wholesale/help/index.html +32 -35
  395. package/app/recipes/commerce.wholesale/index.html +36 -38
  396. package/app/recipes/events.calendar/help/index.html +32 -35
  397. package/app/recipes/events.calendar/index.html +36 -38
  398. package/app/recipes/expenses.tracking/help/index.html +32 -35
  399. package/app/recipes/expenses.tracking/index.html +36 -38
  400. package/app/recipes/fields.form-customization/help/index.html +32 -35
  401. package/app/recipes/fields.form-customization/index.html +36 -38
  402. package/app/recipes/ingestion/help/index.html +32 -35
  403. package/app/recipes/ingestion/index.html +36 -38
  404. package/app/recipes/integrations/help/index.html +32 -35
  405. package/app/recipes/integrations/index.html +36 -38
  406. package/app/recipes/inventory.stock/help/index.html +32 -35
  407. package/app/recipes/inventory.stock/index.html +36 -38
  408. package/app/recipes/ledgers.bookkeeping/help/index.html +32 -35
  409. package/app/recipes/ledgers.bookkeeping/index.html +36 -38
  410. package/app/recipes/messages/help/index.html +32 -35
  411. package/app/recipes/messages/index.html +36 -38
  412. package/app/recipes/products/help/index.html +32 -35
  413. package/app/recipes/products/index.html +36 -38
  414. package/app/recipes/projects.tracker/help/index.html +32 -35
  415. package/app/recipes/projects.tracker/index.html +36 -38
  416. package/app/recipes/reports.materialized/help/index.html +32 -35
  417. package/app/recipes/reports.materialized/index.html +36 -38
  418. package/app/recipes/reports.runtime/help/index.html +32 -35
  419. package/app/recipes/reports.runtime/index.html +37 -39
  420. package/app/recipes/sales.pipeline/help/index.html +32 -35
  421. package/app/recipes/sales.pipeline/index.html +36 -38
  422. package/app/recipes/tags.taxonomy/help/index.html +32 -35
  423. package/app/recipes/tags.taxonomy/index.html +36 -38
  424. package/app/recipes/team-collaboration/help/index.html +32 -35
  425. package/app/recipes/team-collaboration/index.html +36 -38
  426. package/app/recipes/timesheets.time-entries/help/index.html +32 -35
  427. package/app/recipes/timesheets.time-entries/index.html +36 -38
  428. package/app/s/custom-accounts/index.html +29 -32
  429. package/app/s/custom-appointments/index.html +29 -32
  430. package/app/s/custom-billing/index.html +29 -32
  431. package/app/s/custom-bookings/index.html +79 -0
  432. package/app/s/custom-buying/index.html +29 -32
  433. package/app/s/custom-checkout/index.html +29 -32
  434. package/app/s/custom-classes/index.html +29 -32
  435. package/app/s/custom-clients/index.html +29 -32
  436. package/app/s/custom-events/index.html +29 -32
  437. package/app/s/custom-fleet/index.html +29 -32
  438. package/app/s/custom-gigs/index.html +79 -0
  439. package/app/s/custom-giving/index.html +29 -32
  440. package/app/s/custom-instruments/index.html +79 -0
  441. package/app/s/custom-jobs/index.html +29 -32
  442. package/app/s/custom-kitchen/index.html +29 -32
  443. package/app/s/custom-lessons/index.html +79 -0
  444. package/app/s/custom-material/index.html +29 -32
  445. package/app/s/custom-meetings/index.html +29 -32
  446. package/app/s/custom-members/index.html +29 -32
  447. package/app/s/custom-merch/index.html +79 -0
  448. package/app/s/custom-money/index.html +79 -0
  449. package/app/s/custom-paint/index.html +29 -32
  450. package/app/s/custom-parts/index.html +29 -32
  451. package/app/s/custom-rentals/index.html +29 -32
  452. package/app/s/custom-roastery/index.html +29 -32
  453. package/app/s/custom-schedule/index.html +29 -32
  454. package/app/s/custom-shelf/index.html +29 -32
  455. package/app/s/custom-shop/index.html +29 -32
  456. package/app/s/custom-students/index.html +79 -0
  457. package/app/s/custom-wholesale/index.html +29 -32
  458. package/app/s/custom-work/index.html +29 -32
  459. package/app/s/custom-yard/index.html +29 -32
  460. package/app/s/section-access-control/index.html +29 -32
  461. package/app/s/section-account-security/index.html +29 -32
  462. package/app/s/section-accounting/index.html +29 -32
  463. package/app/s/section-activity/index.html +29 -32
  464. package/app/s/section-agreements/index.html +29 -32
  465. package/app/s/section-analytics/index.html +29 -32
  466. package/app/s/section-assets/index.html +29 -32
  467. package/app/s/section-billing/index.html +29 -32
  468. package/app/s/section-calendar/index.html +29 -32
  469. package/app/s/section-catalog/index.html +29 -32
  470. package/app/s/section-chat.assistant/index.html +29 -32
  471. package/app/s/section-comments/index.html +29 -32
  472. package/app/s/section-fields.form-customization/index.html +29 -32
  473. package/app/s/section-ingestion/index.html +29 -32
  474. package/app/s/section-integrations/index.html +29 -32
  475. package/app/s/section-messages/index.html +29 -32
  476. package/app/s/section-more/index.html +29 -32
  477. package/app/s/section-operations/index.html +29 -32
  478. package/app/s/section-projects/index.html +29 -32
  479. package/app/s/section-purchasing/index.html +29 -32
  480. package/app/s/section-reports.materialized/index.html +29 -32
  481. package/app/s/section-reports.runtime/index.html +29 -32
  482. package/app/s/section-sales/index.html +29 -32
  483. package/app/s/section-taxonomy/index.html +29 -32
  484. package/app/s/section-team/index.html +29 -32
  485. package/app/s/section-work/index.html +29 -32
  486. package/dist/assistant/change.d.ts +10 -1
  487. package/dist/assistant/change.d.ts.map +1 -1
  488. package/dist/assistant/change.js +6 -1
  489. package/dist/assistant/prompt.d.ts +10 -1
  490. package/dist/assistant/prompt.d.ts.map +1 -1
  491. package/dist/assistant/prompt.js +42 -7
  492. package/dist/assistant/session.svelte.d.ts +6 -0
  493. package/dist/assistant/session.svelte.d.ts.map +1 -1
  494. package/dist/assistant/session.svelte.js +6 -0
  495. package/dist/assistant/transport.d.ts +23 -3
  496. package/dist/assistant/transport.d.ts.map +1 -1
  497. package/dist/assistant/transport.js +356 -13
  498. package/dist/catalog/catalog.json +107 -41
  499. package/dist/components/BrowserAssistant.svelte +26 -0
  500. package/dist/components/BrowserAssistant.svelte.d.ts.map +1 -1
  501. package/dist/components/ModelPage.svelte +36 -4
  502. package/dist/components/ModelPage.svelte.d.ts.map +1 -1
  503. package/dist/components/PlannerReports.svelte +61 -0
  504. package/dist/components/PlannerReports.svelte.d.ts +10 -0
  505. package/dist/components/PlannerReports.svelte.d.ts.map +1 -0
  506. package/dist/components/PlannerSavedReportsWidget.svelte +38 -0
  507. package/dist/components/PlannerSavedReportsWidget.svelte.d.ts +9 -0
  508. package/dist/components/PlannerSavedReportsWidget.svelte.d.ts.map +1 -0
  509. package/dist/components/ReportProposalCard.svelte +63 -0
  510. package/dist/components/ReportProposalCard.svelte.d.ts +17 -0
  511. package/dist/components/ReportProposalCard.svelte.d.ts.map +1 -0
  512. package/dist/components/SectionOverview.svelte +22 -1
  513. package/dist/components/SectionOverview.svelte.d.ts.map +1 -1
  514. package/dist/components/ThemeBridge.svelte +2 -2
  515. package/dist/core/prompt.d.ts.map +1 -1
  516. package/dist/core/prompt.js +7 -1
  517. package/dist/core/reply.d.ts +6 -0
  518. package/dist/core/reply.d.ts.map +1 -1
  519. package/dist/core/reply.js +11 -0
  520. package/dist/data/packs.d.ts.map +1 -1
  521. package/dist/data/packs.js +415 -0
  522. package/dist/data/planner-source.d.ts.map +1 -1
  523. package/dist/data/planner-source.js +4 -1
  524. package/dist/library/icons.d.ts.map +1 -1
  525. package/dist/library/icons.js +10 -0
  526. package/dist/library/library.json +506 -0
  527. package/dist/overviews/definitions.d.ts.map +1 -1
  528. package/dist/overviews/definitions.js +6 -1
  529. package/dist/overviews/registry.d.ts.map +1 -1
  530. package/dist/overviews/registry.js +9 -5
  531. package/dist/planner/Planner.svelte +17 -0
  532. package/dist/planner/Planner.svelte.d.ts.map +1 -1
  533. package/dist/planner/instance.d.ts +6 -0
  534. package/dist/planner/instance.d.ts.map +1 -1
  535. package/dist/planner/shell.d.ts.map +1 -1
  536. package/dist/planner/shell.js +3 -1
  537. package/dist/reports/intent.d.ts +106 -0
  538. package/dist/reports/intent.d.ts.map +1 -0
  539. package/dist/reports/intent.js +667 -0
  540. package/dist/reports/planner.d.ts +33 -0
  541. package/dist/reports/planner.d.ts.map +1 -0
  542. package/dist/reports/planner.js +60 -0
  543. package/dist/reports/sources.d.ts +36 -0
  544. package/dist/reports/sources.d.ts.map +1 -0
  545. package/dist/reports/sources.js +125 -0
  546. package/dist/reports/store.d.ts +64 -0
  547. package/dist/reports/store.d.ts.map +1 -0
  548. package/dist/reports/store.js +214 -0
  549. package/dist/smrt-version.d.ts +1 -1
  550. package/dist/smrt-version.js +1 -1
  551. package/package.json +54 -54
  552. package/app/_app/immutable/assets/0.C8CwV4Fz.css +0 -1
  553. package/app/_app/immutable/assets/AppShell.Dnc9PAvY.css +0 -1
  554. package/app/_app/immutable/assets/app.4ScdTV_S.css +0 -1
  555. package/app/_app/immutable/assets/labels.DrQMsG17.css +0 -1
  556. package/app/_app/immutable/assets/state.CkVocVUJ.css +0 -1
  557. package/app/_app/immutable/chunks/9pRTae44.js +0 -1
  558. package/app/_app/immutable/chunks/BhU_yBI_.js +0 -1
  559. package/app/_app/immutable/chunks/Bsn3IIve.js +0 -4
  560. package/app/_app/immutable/chunks/C_3CJO_1.js +0 -1
  561. package/app/_app/immutable/chunks/Cr4byQts.js +0 -24
  562. package/app/_app/immutable/chunks/CtjBwCj8.js +0 -1
  563. package/app/_app/immutable/chunks/CyUSxz1P.js +0 -4
  564. package/app/_app/immutable/chunks/J9kOiFLO.js +0 -11
  565. package/app/_app/immutable/chunks/M-CuJzQN.js +0 -1
  566. package/app/_app/immutable/chunks/NppCG--v.js +0 -1
  567. package/app/_app/immutable/chunks/O8DAZ_le.js +0 -1
  568. package/app/_app/immutable/chunks/d_dqmeIr.js +0 -1
  569. package/app/_app/immutable/chunks/gMSmS-_y.js +0 -2
  570. package/app/_app/immutable/entry/app.B4gMiHwR.js +0 -2
  571. package/app/_app/immutable/entry/start.BXkBl20Z.js +0 -1
  572. package/app/_app/immutable/nodes/0.2MYMg80l.js +0 -9
  573. package/app/_app/immutable/nodes/14.B6TD25VU.js +0 -1
  574. package/app/_app/immutable/nodes/2.x9WyxQ1S.js +0 -24
@@ -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)).map((e) => `"${e.says}" -> ${JSON.stringify(e.answer)}`);
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
- out.push('"reply" never claims anything beyond add, remove, cookbook, settings, theme and open: the app reports what changed.');
118
- if (recipes.some((r) => r.id === REPORTS_RECIPE)) {
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
- const shown = examples(new Set(recipes.map((r) => r.id)), new Set(cookbooks.map((c) => c.id)), Boolean(settings), Boolean(themeInfo));
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;IAiCnC;;;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"}
1
+ {"version":3,"file":"session.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/assistant/session.svelte.ts"],"names":[],"mappings":"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"}
@@ -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 { AssistantTransport } from '@happyvertical/smrt-chat/svelte';
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: the planner cannot build one yet (smrt#4100). */
79
- export declare const REPORTS_PENDING = "Building the report itself is not available in the planner yet; it will live under Reports.";
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":"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"}
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: the planner cannot build one yet (smrt#4100). */
41
- export const REPORTS_PENDING = 'Building the report itself is not available in the planner yet; it will live under Reports.';
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
- const summary = [
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 and a theme Undo in one turn ride together.
236
- const refs = offer && undo ? [offer, undo] : (offer ?? undo);
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
  },