@adia-ai/gen-ui 0.8.37
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/CHANGELOG.md +26 -0
- package/README.md +77 -0
- package/compose/CHANGELOG.md +1707 -0
- package/compose/README.md +215 -0
- package/compose/core/artifacts.js +262 -0
- package/compose/core/context-store.js +218 -0
- package/compose/core/generator.d.ts +4 -0
- package/compose/core/generator.js +602 -0
- package/compose/core/pipeline/engine.js +289 -0
- package/compose/core/pipeline/types.js +91 -0
- package/compose/core/plan-primitives.js +120 -0
- package/compose/core/plan-turn.js +145 -0
- package/compose/core/reference.js +150 -0
- package/compose/core/state.js +15 -0
- package/compose/evals/harness.d.ts +4 -0
- package/compose/evals/harness.mjs +193 -0
- package/compose/index.d.ts +4 -0
- package/compose/index.js +16 -0
- package/compose/shared/validate-and-repair.js +122 -0
- package/compose/strategies/_shared/chunk-loader.js +282 -0
- package/compose/strategies/cascade.d.ts +67 -0
- package/compose/strategies/cascade.js +165 -0
- package/compose/strategies/escalation.d.ts +13 -0
- package/compose/strategies/escalation.js +132 -0
- package/compose/strategies/free-form-composer/index.js +254 -0
- package/compose/strategies/free-form-composer/system-prompt.js +205 -0
- package/compose/strategies/free-form-composer/transpile.js +279 -0
- package/compose/strategies/monolithic/_shared.js +1619 -0
- package/compose/strategies/monolithic/generate-instant.js +228 -0
- package/compose/strategies/monolithic/generate-pro.js +490 -0
- package/compose/strategies/monolithic/generate-thinking.js +206 -0
- package/compose/strategies/registry.d.ts +20 -0
- package/compose/strategies/registry.js +495 -0
- package/compose/strategies/zettel/_smoke.js +27 -0
- package/compose/strategies/zettel/chunk-composer.js +214 -0
- package/compose/strategies/zettel/chunk-refiner.js +582 -0
- package/compose/strategies/zettel/chunk-synthesizer.js +458 -0
- package/compose/strategies/zettel/composer.js +78 -0
- package/compose/strategies/zettel/composition-library.js +418 -0
- package/compose/strategies/zettel/generate.js +15 -0
- package/compose/strategies/zettel/generator-adapter.d.ts +4 -0
- package/compose/strategies/zettel/generator-adapter.js +242 -0
- package/compose/strategies/zettel/issue-reporter.js +607 -0
- package/compose/strategies/zettel/session-store.js +121 -0
- package/compose/strategies/zettel/state-cache.js +158 -0
- package/compose/transpiler/transpiler-maps.js +675 -0
- package/compose/transpiler/transpiler.d.ts +4 -0
- package/compose/transpiler/transpiler.js +962 -0
- package/corpus/CHANGELOG.md +1957 -0
- package/corpus/README.md +279 -0
- package/corpus/catalog-a2ui_0_9.d.ts +4 -0
- package/corpus/catalog-a2ui_0_9.json +29571 -0
- package/corpus/catalog-a2ui_0_9_rules.txt +1215 -0
- package/corpus/chunk-embeddings.d.ts +4 -0
- package/corpus/chunk-embeddings.json +1 -0
- package/corpus/chunks/_index.json +16658 -0
- package/corpus/chunks/_source-hashes.json +571 -0
- package/corpus/chunks/access-denied-with-request.json +124 -0
- package/corpus/chunks/access-request-form.json +166 -0
- package/corpus/chunks/access-request-pending.json +133 -0
- package/corpus/chunks/accordion-settings.json +176 -0
- package/corpus/chunks/achievement-badges.json +413 -0
- package/corpus/chunks/achievement-unlock.json +104 -0
- package/corpus/chunks/action-list-record-actions.json +84 -0
- package/corpus/chunks/activity-feed.json +390 -0
- package/corpus/chunks/admin-page-header-flush.json +83 -0
- package/corpus/chunks/admin-page-header-title-description.json +80 -0
- package/corpus/chunks/admin-page-header-with-actions.json +107 -0
- package/corpus/chunks/admin-page-header-with-tabs.json +144 -0
- package/corpus/chunks/admin-shell-rounded-borderless.json +287 -0
- package/corpus/chunks/admin-shell-standard.json +310 -0
- package/corpus/chunks/admin-sidebar-brand-signin.json +158 -0
- package/corpus/chunks/admin-sidebar-brand-version.json +130 -0
- package/corpus/chunks/admin-sidebar-flat-nav.json +131 -0
- package/corpus/chunks/admin-sidebar-nav-dividers.json +150 -0
- package/corpus/chunks/admin-sidebar-nav-groups.json +171 -0
- package/corpus/chunks/admin-sidebar-workspace-switcher.json +139 -0
- package/corpus/chunks/admin-topbar-breadcrumb-actions.json +130 -0
- package/corpus/chunks/admin-topbar-breadcrumb-minimal.json +79 -0
- package/corpus/chunks/admin-topbar-deep-breadcrumb.json +129 -0
- package/corpus/chunks/admin-topbar-search.json +104 -0
- package/corpus/chunks/admin-topbar-status-indicator.json +122 -0
- package/corpus/chunks/admin-topbar-trailing-toggle.json +114 -0
- package/corpus/chunks/agent-activity-feed.json +163 -0
- package/corpus/chunks/agent-artifact-stub-card.json +115 -0
- package/corpus/chunks/agent-canvas-shell.json +305 -0
- package/corpus/chunks/agent-citations-source-chips.json +82 -0
- package/corpus/chunks/agent-command-palette-search.json +120 -0
- package/corpus/chunks/agent-cost-detailed.json +260 -0
- package/corpus/chunks/agent-cost-inline.json +78 -0
- package/corpus/chunks/agent-memory-detail.json +181 -0
- package/corpus/chunks/agent-memory-editor.json +173 -0
- package/corpus/chunks/agent-memory-list.json +207 -0
- package/corpus/chunks/agent-pipeline-status-stages.json +61 -0
- package/corpus/chunks/agent-prompt-card.json +179 -0
- package/corpus/chunks/agent-prompt-library-grid.json +341 -0
- package/corpus/chunks/agent-prompt-picker.json +282 -0
- package/corpus/chunks/agent-rate-limit.json +100 -0
- package/corpus/chunks/agent-reasoning-collapsed.json +128 -0
- package/corpus/chunks/agent-tool-call-accordion.json +109 -0
- package/corpus/chunks/agent-tool-call-collapsed.json +98 -0
- package/corpus/chunks/agent-tool-call-error.json +112 -0
- package/corpus/chunks/agent-tool-call-result.json +145 -0
- package/corpus/chunks/agent-tool-call-running.json +85 -0
- package/corpus/chunks/agent-tool-call-success.json +137 -0
- package/corpus/chunks/agent-trace-timeline.json +244 -0
- package/corpus/chunks/ai-streaming-response.json +147 -0
- package/corpus/chunks/alert-banner-stack.json +78 -0
- package/corpus/chunks/alert-banner.json +55 -0
- package/corpus/chunks/alert-dialog-simple.json +72 -0
- package/corpus/chunks/alert-dialog-typed.json +107 -0
- package/corpus/chunks/alert-dialog-unsaved.json +81 -0
- package/corpus/chunks/analytics-chart.json +213 -0
- package/corpus/chunks/analytics-sparklines-dashboard.json +259 -0
- package/corpus/chunks/anchor-bar-selection-bar.json +226 -0
- package/corpus/chunks/api-key-table.json +148 -0
- package/corpus/chunks/api-keys-create.json +140 -0
- package/corpus/chunks/api-keys-list.json +271 -0
- package/corpus/chunks/app-nav-badges-counts.json +77 -0
- package/corpus/chunks/app-nav-badges-group-rollup-badges.json +100 -0
- package/corpus/chunks/app-nav-badges-plan-tiers.json +76 -0
- package/corpus/chunks/app-nav-badges-status-callouts.json +75 -0
- package/corpus/chunks/app-nav-full-example.json +195 -0
- package/corpus/chunks/app-nav-groups.json +103 -0
- package/corpus/chunks/app-nav-items.json +74 -0
- package/corpus/chunks/app-nav-labels-and-dividers.json +92 -0
- package/corpus/chunks/app-nav-spacer.json +77 -0
- package/corpus/chunks/app-product-listing-card.json +214 -0
- package/corpus/chunks/approvals-detail.json +240 -0
- package/corpus/chunks/approvals-queue.json +321 -0
- package/corpus/chunks/audit-log-basic.json +184 -0
- package/corpus/chunks/audit-log.json +174 -0
- package/corpus/chunks/auth-account-deleted-actions.json +51 -0
- package/corpus/chunks/auth-account-deleted.json +202 -0
- package/corpus/chunks/auth-card-content.json +260 -0
- package/corpus/chunks/auth-card-header.json +205 -0
- package/corpus/chunks/auth-email-entry.json +65 -0
- package/corpus/chunks/auth-email-verify-confirm.json +52 -0
- package/corpus/chunks/auth-email-verify.json +196 -0
- package/corpus/chunks/auth-forbidden-actions.json +59 -0
- package/corpus/chunks/auth-forbidden.json +203 -0
- package/corpus/chunks/auth-invite-actions.json +49 -0
- package/corpus/chunks/auth-invite-team-card.json +86 -0
- package/corpus/chunks/auth-link-expired-form.json +65 -0
- package/corpus/chunks/auth-link-expired.json +196 -0
- package/corpus/chunks/auth-locked-account.json +211 -0
- package/corpus/chunks/auth-locked-recovery-options.json +60 -0
- package/corpus/chunks/auth-mfa-enrollment-submit.json +54 -0
- package/corpus/chunks/auth-mfa-enrollment.json +284 -0
- package/corpus/chunks/auth-mfa-fallback-actions.json +52 -0
- package/corpus/chunks/auth-mfa-recovery.json +61 -0
- package/corpus/chunks/auth-new-password-form.json +75 -0
- package/corpus/chunks/auth-new-password.json +217 -0
- package/corpus/chunks/auth-oauth-fallback-actions.json +52 -0
- package/corpus/chunks/auth-oauth-interstitial.json +160 -0
- package/corpus/chunks/auth-password-challenge.json +94 -0
- package/corpus/chunks/auth-password-reset-form.json +64 -0
- package/corpus/chunks/auth-password-reset.json +195 -0
- package/corpus/chunks/auth-profile-form.json +72 -0
- package/corpus/chunks/auth-profile-setup.json +194 -0
- package/corpus/chunks/auth-reset-sent.json +188 -0
- package/corpus/chunks/auth-session-expired-actions.json +52 -0
- package/corpus/chunks/auth-session-expired.json +201 -0
- package/corpus/chunks/auth-signin-card-email.json +245 -0
- package/corpus/chunks/auth-signin-card-magic-link.json +147 -0
- package/corpus/chunks/auth-signin-card-mfa.json +231 -0
- package/corpus/chunks/auth-signin-card-otp.json +205 -0
- package/corpus/chunks/auth-signin-card-password.json +264 -0
- package/corpus/chunks/auth-signin-card-recovery.json +218 -0
- package/corpus/chunks/auth-signout-actions.json +51 -0
- package/corpus/chunks/auth-signout.json +184 -0
- package/corpus/chunks/auth-signup-email-entry.json +66 -0
- package/corpus/chunks/auth-signup-entry.json +281 -0
- package/corpus/chunks/auth-signup-social-auths.json +54 -0
- package/corpus/chunks/auth-signup-verify.json +227 -0
- package/corpus/chunks/auth-social-auths.json +62 -0
- package/corpus/chunks/auth-sso-providers.json +55 -0
- package/corpus/chunks/auth-sso-required.json +213 -0
- package/corpus/chunks/auth-team-invite.json +288 -0
- package/corpus/chunks/avatar-group-overflow.json +137 -0
- package/corpus/chunks/avatar-stack-overflow.json +124 -0
- package/corpus/chunks/banner-announcement-beta.json +99 -0
- package/corpus/chunks/banner-announcement-promo.json +102 -0
- package/corpus/chunks/banner-live-update.json +102 -0
- package/corpus/chunks/banner-system-maintenance.json +101 -0
- package/corpus/chunks/banner-system-offline.json +85 -0
- package/corpus/chunks/banner-system-update.json +102 -0
- package/corpus/chunks/bell-menu-empty.json +107 -0
- package/corpus/chunks/bell-menu-unread.json +395 -0
- package/corpus/chunks/billing-cancel-subscription-danger.json +61 -0
- package/corpus/chunks/billing-invoice-history-table.json +75 -0
- package/corpus/chunks/billing-overview.json +202 -0
- package/corpus/chunks/billing-payment-method-card-on-file.json +157 -0
- package/corpus/chunks/billing-progress-label.json +101 -0
- package/corpus/chunks/blog-post-card.json +212 -0
- package/corpus/chunks/breadcrumb-navigation.json +72 -0
- package/corpus/chunks/bulk-action-toolbar-floating.json +199 -0
- package/corpus/chunks/bulk-action-toolbar-swap.json +158 -0
- package/corpus/chunks/bulk-selection-actions-bar.json +162 -0
- package/corpus/chunks/business-address-form.json +953 -0
- package/corpus/chunks/calendar-month-view.json +74 -0
- package/corpus/chunks/card-grid-images.json +459 -0
- package/corpus/chunks/card-header-with-description.json +47 -0
- package/corpus/chunks/card-with-empty-state.json +96 -0
- package/corpus/chunks/card-with-form.json +143 -0
- package/corpus/chunks/card-with-sparkline.json +90 -0
- package/corpus/chunks/card-with-stat-kpi.json +86 -0
- package/corpus/chunks/changelog-feed-basic.json +470 -0
- package/corpus/chunks/chart-in-card-chart-plus-breakdown.json +188 -0
- package/corpus/chunks/chart-in-card-chart-plus-stat.json +89 -0
- package/corpus/chunks/chart-in-card-chart-with-filter-pills.json +124 -0
- package/corpus/chunks/chart-in-card-full-bleed-legend.json +116 -0
- package/corpus/chunks/chart-in-card-full-chart.json +107 -0
- package/corpus/chunks/chart-in-card-sparkline-tile.json +93 -0
- package/corpus/chunks/chart-in-card-stat-with-sparkline.json +73 -0
- package/corpus/chunks/chart-in-card-trend-footer.json +115 -0
- package/corpus/chunks/chart-with-filter-pills.json +169 -0
- package/corpus/chunks/chat-empty-state-hero.json +102 -0
- package/corpus/chunks/chat-message-assistant-byline.json +85 -0
- package/corpus/chunks/chat-message-user-byline.json +84 -0
- package/corpus/chunks/chat-page-shell.json +379 -0
- package/corpus/chunks/chat-streaming-surface.json +169 -0
- package/corpus/chunks/checkout-order-summary-card.json +140 -0
- package/corpus/chunks/code-snippet.json +107 -0
- package/corpus/chunks/col-form-stack.json +93 -0
- package/corpus/chunks/col-heading-body-action.json +79 -0
- package/corpus/chunks/col-stat-label.json +63 -0
- package/corpus/chunks/color-picker-swatches.json +153 -0
- package/corpus/chunks/command-palette.json +327 -0
- package/corpus/chunks/comments-composer.json +158 -0
- package/corpus/chunks/comments-mention-menu.json +237 -0
- package/corpus/chunks/comments-thread.json +344 -0
- package/corpus/chunks/commerce-pricing-tiers.json +401 -0
- package/corpus/chunks/comparison-table.json +246 -0
- package/corpus/chunks/contact-form-card.json +197 -0
- package/corpus/chunks/contact-form.json +157 -0
- package/corpus/chunks/contact-support-form.json +702 -0
- package/corpus/chunks/conversion-funnel-4-step-funnel.json +139 -0
- package/corpus/chunks/conversion-funnel-6step.json +151 -0
- package/corpus/chunks/conversion-funnel-wide-summary.json +192 -0
- package/corpus/chunks/conversion-funnel-with-segment-compare.json +202 -0
- package/corpus/chunks/cta-banner-centered.json +102 -0
- package/corpus/chunks/dashboard-acquisition-panel.json +212 -0
- package/corpus/chunks/dashboard-admin-page.json +104 -0
- package/corpus/chunks/dashboard-audience-kpis.json +165 -0
- package/corpus/chunks/dashboard-audience-panel.json +756 -0
- package/corpus/chunks/dashboard-behavior-panel.json +114 -0
- package/corpus/chunks/dashboard-chart-recent.json +566 -0
- package/corpus/chunks/dashboard-cohort-retention.json +83 -0
- package/corpus/chunks/dashboard-conversion-panel.json +234 -0
- package/corpus/chunks/dashboard-country-list.json +304 -0
- package/corpus/chunks/dashboard-filter-bar.json +118 -0
- package/corpus/chunks/dashboard-funnel.json +142 -0
- package/corpus/chunks/dashboard-notifications-panel.json +423 -0
- package/corpus/chunks/dashboard-overview-panel.json +1644 -0
- package/corpus/chunks/dashboard-page-header.json +166 -0
- package/corpus/chunks/dashboard-pages-table.json +86 -0
- package/corpus/chunks/dashboard-quick-actions.json +116 -0
- package/corpus/chunks/dashboard-reports-panel.json +166 -0
- package/corpus/chunks/dashboard-reports-table.json +138 -0
- package/corpus/chunks/dashboard-storage-card.json +117 -0
- package/corpus/chunks/dashboard-tabs.json +86 -0
- package/corpus/chunks/dashboard-team-actions-storage.json +605 -0
- package/corpus/chunks/dashboard-team-list.json +334 -0
- package/corpus/chunks/dashboard-traffic-channels.json +184 -0
- package/corpus/chunks/dashboard-transactions-table.json +145 -0
- package/corpus/chunks/data-export-history.json +192 -0
- package/corpus/chunks/data-export-request.json +197 -0
- package/corpus/chunks/data-import-wizard.json +391 -0
- package/corpus/chunks/date-range-picker.json +156 -0
- package/corpus/chunks/date-time-picker-form.json +222 -0
- package/corpus/chunks/departments-checkbox-form.json +390 -0
- package/corpus/chunks/destructive-confirm-modal.json +149 -0
- package/corpus/chunks/diff-inline.json +84 -0
- package/corpus/chunks/diff-side-by-side.json +131 -0
- package/corpus/chunks/diff-structured.json +216 -0
- package/corpus/chunks/digest-email-preview.json +374 -0
- package/corpus/chunks/divider-text-label.json +87 -0
- package/corpus/chunks/doc-editor-shell.json +356 -0
- package/corpus/chunks/drawer-2fa-key.json +273 -0
- package/corpus/chunks/drawer-2fa-sms.json +261 -0
- package/corpus/chunks/drawer-2fa-totp.json +385 -0
- package/corpus/chunks/drawer-cancel-sub.json +636 -0
- package/corpus/chunks/drawer-change-plan.json +561 -0
- package/corpus/chunks/drawer-custom-roles.json +696 -0
- package/corpus/chunks/drawer-data-start.json +171 -0
- package/corpus/chunks/drawer-delete-account.json +341 -0
- package/corpus/chunks/drawer-delete-workspace.json +362 -0
- package/corpus/chunks/drawer-discord.json +434 -0
- package/corpus/chunks/drawer-figma.json +401 -0
- package/corpus/chunks/drawer-first-dashboard.json +220 -0
- package/corpus/chunks/drawer-gcal.json +475 -0
- package/corpus/chunks/drawer-github.json +589 -0
- package/corpus/chunks/drawer-invite.json +397 -0
- package/corpus/chunks/drawer-record-detail.json +44 -0
- package/corpus/chunks/drawer-report.json +528 -0
- package/corpus/chunks/drawer-revoke-session.json +331 -0
- package/corpus/chunks/drawer-role.json +190 -0
- package/corpus/chunks/drawer-slack.json +429 -0
- package/corpus/chunks/drawer-smtp.json +476 -0
- package/corpus/chunks/drawer-source.json +294 -0
- package/corpus/chunks/drawer-transaction.json +493 -0
- package/corpus/chunks/drawer-with-create-form.json +43 -0
- package/corpus/chunks/editor-code-pane.json +204 -0
- package/corpus/chunks/editor-page-shell.json +149 -0
- package/corpus/chunks/editor-preview-pane.json +136 -0
- package/corpus/chunks/editor-statusbar-ready.json +99 -0
- package/corpus/chunks/editor-toolbar-import-export.json +195 -0
- package/corpus/chunks/email-inbox-list.json +678 -0
- package/corpus/chunks/empty-state-danger.json +58 -0
- package/corpus/chunks/empty-state-minimal.json +44 -0
- package/corpus/chunks/empty-state-warning.json +53 -0
- package/corpus/chunks/empty-state.json +65 -0
- package/corpus/chunks/error-404-actions.json +54 -0
- package/corpus/chunks/error-404.json +204 -0
- package/corpus/chunks/error-500-actions.json +61 -0
- package/corpus/chunks/error-500.json +220 -0
- package/corpus/chunks/error-maintenance-actions.json +53 -0
- package/corpus/chunks/error-maintenance.json +203 -0
- package/corpus/chunks/error-page-shell.json +132 -0
- package/corpus/chunks/export-flow-async.json +210 -0
- package/corpus/chunks/export-flow-delivery.json +163 -0
- package/corpus/chunks/export-flow-sync.json +162 -0
- package/corpus/chunks/extended-profile-form.json +512 -0
- package/corpus/chunks/faq-accordion.json +123 -0
- package/corpus/chunks/feature-grid-icons.json +314 -0
- package/corpus/chunks/feature-grid-three-cards.json +187 -0
- package/corpus/chunks/feature-toggle-switch-grid.json +213 -0
- package/corpus/chunks/file-upload-dnd.json +166 -0
- package/corpus/chunks/file-upload-field.json +97 -0
- package/corpus/chunks/file-upload-form.json +251 -0
- package/corpus/chunks/filter-bar-active-filters.json +176 -0
- package/corpus/chunks/filter-bar-filter-bar-with-table.json +113 -0
- package/corpus/chunks/filter-bar-saved-views.json +117 -0
- package/corpus/chunks/filter-popover-form.json +137 -0
- package/corpus/chunks/footer-multi-column.json +270 -0
- package/corpus/chunks/footer-primary-only.json +41 -0
- package/corpus/chunks/form-checkbox-group.json +65 -0
- package/corpus/chunks/form-drawer-edit-form.json +178 -0
- package/corpus/chunks/form-drawer-simple-form.json +151 -0
- package/corpus/chunks/form-drawer-tall-form.json +325 -0
- package/corpus/chunks/form-field-email-hint.json +53 -0
- package/corpus/chunks/form-field-range.json +54 -0
- package/corpus/chunks/form-field-required.json +52 -0
- package/corpus/chunks/form-field-select.json +66 -0
- package/corpus/chunks/form-field-textarea.json +51 -0
- package/corpus/chunks/form-field-with-error.json +151 -0
- package/corpus/chunks/form-fields-two-column.json +69 -0
- package/corpus/chunks/form-page-shell.json +146 -0
- package/corpus/chunks/form-switch-toggle.json +41 -0
- package/corpus/chunks/form-system-live-demo.json +123 -0
- package/corpus/chunks/forms-address-autocomplete.json +277 -0
- package/corpus/chunks/forms-address-fields.json +221 -0
- package/corpus/chunks/forms-conditional-reveal.json +195 -0
- package/corpus/chunks/gallery-page-shell.json +444 -0
- package/corpus/chunks/grid-2col-entry-cards.json +140 -0
- package/corpus/chunks/grid-kpi-4col.json +164 -0
- package/corpus/chunks/grid-responsive-kpi.json +165 -0
- package/corpus/chunks/hero-cta-simple.json +107 -0
- package/corpus/chunks/hero-cta-split.json +183 -0
- package/corpus/chunks/hero-section-split.json +111 -0
- package/corpus/chunks/icon-text-row.json +60 -0
- package/corpus/chunks/image-caption-tile.json +99 -0
- package/corpus/chunks/image-carousel.json +156 -0
- package/corpus/chunks/image-thumbnail-grid.json +77 -0
- package/corpus/chunks/image-upload-preview.json +118 -0
- package/corpus/chunks/import-mapping-flow.json +972 -0
- package/corpus/chunks/inline-dialog-rename.json +128 -0
- package/corpus/chunks/inline-dialog-schedule.json +154 -0
- package/corpus/chunks/inline-dialog-status.json +179 -0
- package/corpus/chunks/integrations-api-keys-card-list.json +475 -0
- package/corpus/chunks/integrations-connect-form.json +550 -0
- package/corpus/chunks/integrations-grid.json +141 -0
- package/corpus/chunks/integrations-webhooks-empty-state.json +66 -0
- package/corpus/chunks/inventory-list-stock.json +137 -0
- package/corpus/chunks/invite-members.json +153 -0
- package/corpus/chunks/invoice-line-items.json +493 -0
- package/corpus/chunks/kanban-board-3col.json +713 -0
- package/corpus/chunks/kanban-page-shell.json +671 -0
- package/corpus/chunks/key-value-detail-list.json +242 -0
- package/corpus/chunks/keyboard-shortcut-display.json +250 -0
- package/corpus/chunks/labeled-textarea.json +45 -0
- package/corpus/chunks/leaderboard-table.json +140 -0
- package/corpus/chunks/library-browser-search-filter.json +109 -0
- package/corpus/chunks/linked-record-row.json +61 -0
- package/corpus/chunks/loading-skeleton-placeholder.json +387 -0
- package/corpus/chunks/login-form-card.json +207 -0
- package/corpus/chunks/logo-cloud-trusted-by.json +235 -0
- package/corpus/chunks/map-with-location-list.json +293 -0
- package/corpus/chunks/marketing-hero-cta.json +102 -0
- package/corpus/chunks/marketing-page-shell.json +352 -0
- package/corpus/chunks/masonry-gallery.json +154 -0
- package/corpus/chunks/member-edit-drawer.json +236 -0
- package/corpus/chunks/members-active-table-search-filter.json +184 -0
- package/corpus/chunks/members-pending-invites-cards.json +251 -0
- package/corpus/chunks/members-roles-permissions-list.json +146 -0
- package/corpus/chunks/menu-context-actions.json +113 -0
- package/corpus/chunks/metadata-description-list.json +178 -0
- package/corpus/chunks/modal-create-project-form.json +133 -0
- package/corpus/chunks/modal-preferences-tabs.json +147 -0
- package/corpus/chunks/multi-field-form-validation.json +394 -0
- package/corpus/chunks/nav-menu-icons.json +74 -0
- package/corpus/chunks/newsletter-subscription.json +190 -0
- package/corpus/chunks/notification-badges-feed.json +411 -0
- package/corpus/chunks/notification-preferences-panel.json +238 -0
- package/corpus/chunks/onb-completion.json +139 -0
- package/corpus/chunks/onb-extension-install.json +172 -0
- package/corpus/chunks/onb-hero-welcome.json +156 -0
- package/corpus/chunks/onb-import-picker.json +86 -0
- package/corpus/chunks/onb-mobile-handoff.json +121 -0
- package/corpus/chunks/onb-notification-prefs.json +83 -0
- package/corpus/chunks/onb-persona-picker.json +82 -0
- package/corpus/chunks/onb-provider-tiles.json +137 -0
- package/corpus/chunks/onb-settings-review.json +257 -0
- package/corpus/chunks/onb-step-footer.json +121 -0
- package/corpus/chunks/onb-step-header.json +121 -0
- package/corpus/chunks/onb-step-progress.json +140 -0
- package/corpus/chunks/onb-step-shell.json +380 -0
- package/corpus/chunks/onb-story-pane.json +121 -0
- package/corpus/chunks/onb-tutorial-steps.json +193 -0
- package/corpus/chunks/order-confirmation-success-card.json +177 -0
- package/corpus/chunks/order-tracking-timeline.json +131 -0
- package/corpus/chunks/pagination-controls.json +82 -0
- package/corpus/chunks/pane-settings-sidebar.json +204 -0
- package/corpus/chunks/patient-visit-shell.json +191 -0
- package/corpus/chunks/payment-checkout-form.json +341 -0
- package/corpus/chunks/payment-method-form.json +328 -0
- package/corpus/chunks/period-comparison.json +236 -0
- package/corpus/chunks/permission-matrix-table.json +438 -0
- package/corpus/chunks/permissions-matrix-grid.json +111 -0
- package/corpus/chunks/permissions-matrix-summary.json +157 -0
- package/corpus/chunks/permissions-role-picker-radio.json +107 -0
- package/corpus/chunks/permissions-role-picker-select.json +101 -0
- package/corpus/chunks/permissions-share-link.json +256 -0
- package/corpus/chunks/permissions-share-people.json +297 -0
- package/corpus/chunks/permissions-sharing-scopes.json +109 -0
- package/corpus/chunks/plan-selection-form.json +529 -0
- package/corpus/chunks/playground-a2ui.json +181 -0
- package/corpus/chunks/playground-agent-admin.json +117 -0
- package/corpus/chunks/playground-agent-chat.json +126 -0
- package/corpus/chunks/playground-app-shell.json +488 -0
- package/corpus/chunks/playground-chat.json +265 -0
- package/corpus/chunks/playground-construct-canvas.json +118 -0
- package/corpus/chunks/playground-css-channel.json +487 -0
- package/corpus/chunks/playground-gen-ui.json +224 -0
- package/corpus/chunks/playground-render-preview.json +369 -0
- package/corpus/chunks/playground-streams-bridge.json +437 -0
- package/corpus/chunks/playground-table-toolbar.json +38 -0
- package/corpus/chunks/popover-with-content.json +118 -0
- package/corpus/chunks/pricing-tiers.json +561 -0
- package/corpus/chunks/product-tour.json +158 -0
- package/corpus/chunks/profile-public.json +297 -0
- package/corpus/chunks/progress-tracker-milestones.json +294 -0
- package/corpus/chunks/radio-button-group.json +83 -0
- package/corpus/chunks/rating-stars-review-summary.json +259 -0
- package/corpus/chunks/reactions-bar.json +75 -0
- package/corpus/chunks/reactions-picker.json +245 -0
- package/corpus/chunks/real-time-metrics-dashboard.json +344 -0
- package/corpus/chunks/record-detail-drawer-simple-detail.json +296 -0
- package/corpus/chunks/record-detail-drawer-tabbed-detail.json +443 -0
- package/corpus/chunks/referral-share-link.json +128 -0
- package/corpus/chunks/referral-status.json +243 -0
- package/corpus/chunks/reg-address-form.json +825 -0
- package/corpus/chunks/reg-billing-card.json +210 -0
- package/corpus/chunks/reg-brand-scrape.json +599 -0
- package/corpus/chunks/reg-departments-toggle.json +259 -0
- package/corpus/chunks/reg-extended-profile.json +356 -0
- package/corpus/chunks/reg-final-done.json +457 -0
- package/corpus/chunks/reg-helpdesk-grid.json +571 -0
- package/corpus/chunks/reg-import-picker.json +112 -0
- package/corpus/chunks/reg-integrations-grid.json +418 -0
- package/corpus/chunks/reg-invite-form.json +245 -0
- package/corpus/chunks/reg-legal-entity.json +260 -0
- package/corpus/chunks/reg-org-chart-review.json +891 -0
- package/corpus/chunks/reg-profile-identity.json +188 -0
- package/corpus/chunks/reg-step-footer.json +201 -0
- package/corpus/chunks/reg-step-header.json +201 -0
- package/corpus/chunks/reg-step-progress.json +236 -0
- package/corpus/chunks/reg-step-shell.json +605 -0
- package/corpus/chunks/reg-story-pane.json +201 -0
- package/corpus/chunks/reg-success-summary.json +257 -0
- package/corpus/chunks/reg-team-size.json +128 -0
- package/corpus/chunks/reg-usecase-picker.json +104 -0
- package/corpus/chunks/reg-workspace-name.json +159 -0
- package/corpus/chunks/responsive-grid-pattern.json +71 -0
- package/corpus/chunks/responsive-kpi-grid.json +166 -0
- package/corpus/chunks/responsive-row-pattern.json +71 -0
- package/corpus/chunks/responsive-shell-sidebar.json +308 -0
- package/corpus/chunks/responsive-wrap-at-pattern.json +124 -0
- package/corpus/chunks/retention-cohort-default-retention.json +80 -0
- package/corpus/chunks/retention-cohort-stat-pair.json +163 -0
- package/corpus/chunks/retention-cohort-with-legend.json +135 -0
- package/corpus/chunks/revenue-heatmap.json +82 -0
- package/corpus/chunks/role-management.json +272 -0
- package/corpus/chunks/row-action-cluster.json +54 -0
- package/corpus/chunks/row-avatar-name-role.json +71 -0
- package/corpus/chunks/row-icon-label.json +52 -0
- package/corpus/chunks/row-spread-label-value.json +54 -0
- package/corpus/chunks/row-wrap-tags.json +72 -0
- package/corpus/chunks/schedule-meeting-form-card.json +229 -0
- package/corpus/chunks/search-recents-menu.json +195 -0
- package/corpus/chunks/search-results-grouped.json +357 -0
- package/corpus/chunks/search-results-list.json +202 -0
- package/corpus/chunks/search-saved-views.json +356 -0
- package/corpus/chunks/search-with-filters.json +311 -0
- package/corpus/chunks/searchable-picker-modal.json +164 -0
- package/corpus/chunks/section-with-stack.json +48 -0
- package/corpus/chunks/security-active-sessions-devices.json +287 -0
- package/corpus/chunks/security-change-password-form.json +102 -0
- package/corpus/chunks/security-delete-account-danger.json +79 -0
- package/corpus/chunks/segmented-control-billing-tabs.json +164 -0
- package/corpus/chunks/select-multiple-preselected.json +70 -0
- package/corpus/chunks/settings-2fa-setup.json +307 -0
- package/corpus/chunks/settings-admin-page.json +1205 -0
- package/corpus/chunks/settings-appearance-primitives.json +145 -0
- package/corpus/chunks/settings-appearance-theme-panel.json +55 -0
- package/corpus/chunks/settings-appearance.json +81 -0
- package/corpus/chunks/settings-danger-zone-delete-workspace.json +93 -0
- package/corpus/chunks/settings-general-form.json +69 -0
- package/corpus/chunks/settings-integrations.json +298 -0
- package/corpus/chunks/settings-members-invite.json +112 -0
- package/corpus/chunks/settings-notification-activity-checkboxes.json +108 -0
- package/corpus/chunks/settings-notification-channels-switches.json +101 -0
- package/corpus/chunks/settings-page-shell.json +190 -0
- package/corpus/chunks/settings-privacy.json +83 -0
- package/corpus/chunks/settings-profile-security.json +122 -0
- package/corpus/chunks/settings-toggle-switches.json +66 -0
- package/corpus/chunks/sidebar-nav.json +120 -0
- package/corpus/chunks/sidebar-navigation-panel.json +165 -0
- package/corpus/chunks/signup-form-card.json +218 -0
- package/corpus/chunks/signup-team-size-form.json +259 -0
- package/corpus/chunks/single-select-card-form.json +231 -0
- package/corpus/chunks/slider-range-controls.json +119 -0
- package/corpus/chunks/social-media-post-card.json +159 -0
- package/corpus/chunks/sortable-list.json +307 -0
- package/corpus/chunks/sortable-search-paginate-table.json +162 -0
- package/corpus/chunks/split-pane-editor.json +146 -0
- package/corpus/chunks/stack-avatar-badge-overlay.json +53 -0
- package/corpus/chunks/stack-image-shimmer.json +51 -0
- package/corpus/chunks/stat-cards-kpi-dashboard.json +178 -0
- package/corpus/chunks/stats-band-big-numbers.json +175 -0
- package/corpus/chunks/status-dashboard.json +282 -0
- package/corpus/chunks/stepper-form-wizard.json +165 -0
- package/corpus/chunks/subscription-status-renewal-card.json +285 -0
- package/corpus/chunks/survey-rating-form.json +165 -0
- package/corpus/chunks/swiper-product-carousel.json +349 -0
- package/corpus/chunks/swiper-testimonial-carousel.json +279 -0
- package/corpus/chunks/table-empty-state.json +116 -0
- package/corpus/chunks/table-inline-edit-row.json +269 -0
- package/corpus/chunks/table-spreadsheet-cells.json +334 -0
- package/corpus/chunks/table-toolbar-no-search.json +42 -0
- package/corpus/chunks/table-toolbar-with-table.json +208 -0
- package/corpus/chunks/table-with-toolbar-card.json +80 -0
- package/corpus/chunks/tabs-with-panels.json +187 -0
- package/corpus/chunks/tag-chips-filter.json +100 -0
- package/corpus/chunks/team-invite-form.json +380 -0
- package/corpus/chunks/team-members-list.json +341 -0
- package/corpus/chunks/testimonial-grid.json +269 -0
- package/corpus/chunks/testimonial-pull-quote.json +137 -0
- package/corpus/chunks/testimonials-avatar-cards.json +286 -0
- package/corpus/chunks/timeline-events.json +89 -0
- package/corpus/chunks/timezone-selector-basic.json +99 -0
- package/corpus/chunks/timezone-selector-preview.json +104 -0
- package/corpus/chunks/toolbar-icons.json +216 -0
- package/corpus/chunks/toolbar-rich-text-editor.json +230 -0
- package/corpus/chunks/toolbar-tooltips.json +191 -0
- package/corpus/chunks/tooltip-hover-button.json +106 -0
- package/corpus/chunks/tree-file-explorer.json +136 -0
- package/corpus/chunks/tree-table-basic.json +171 -0
- package/corpus/chunks/trial-banner.json +158 -0
- package/corpus/chunks/url-import-form.json +728 -0
- package/corpus/chunks/usage-quota-meter-card.json +217 -0
- package/corpus/chunks/user-identity-row.json +81 -0
- package/corpus/chunks/user-onboarding-checklist.json +301 -0
- package/corpus/chunks/user-profile-card.json +192 -0
- package/corpus/chunks/users-table-badge.json +135 -0
- package/corpus/chunks/verification-document-upload.json +179 -0
- package/corpus/chunks/verification-status.json +97 -0
- package/corpus/chunks/verification-stepper.json +111 -0
- package/corpus/chunks/video-player-controls.json +120 -0
- package/corpus/chunks/webhook-config.json +209 -0
- package/corpus/chunks/webhooks-list.json +204 -0
- package/corpus/chunks/wizard-drawer-three-step-wizard.json +443 -0
- package/corpus/manifest.d.ts +4 -0
- package/corpus/manifest.json +6 -0
- package/corpus/scripts/chunk-library.d.ts +4 -0
- package/corpus/scripts/chunk-library.js +335 -0
- package/node-shims.d.ts +48 -0
- package/package.json +215 -0
- package/retrieval/CHANGELOG.md +1073 -0
- package/retrieval/README.md +71 -0
- package/retrieval/anti-patterns.js +189 -0
- package/retrieval/authoring/index.d.ts +4 -0
- package/retrieval/authoring/index.js +9 -0
- package/retrieval/authoring/web-research.js +220 -0
- package/retrieval/catalog.js +250 -0
- package/retrieval/component-catalog.js +168 -0
- package/retrieval/component-entry.js +80 -0
- package/retrieval/context-assembler.js +174 -0
- package/retrieval/domain-router.js +417 -0
- package/retrieval/embedding/chunk-embedding-retriever.js +117 -0
- package/retrieval/embedding/embedding-provider.js +72 -0
- package/retrieval/embedding/index.d.ts +4 -0
- package/retrieval/embedding/index.js +2 -0
- package/retrieval/feedback/dialog-recorder.js +107 -0
- package/retrieval/feedback/feedback-analyzer.js +180 -0
- package/retrieval/feedback/feedback-store.js +194 -0
- package/retrieval/feedback/feedback.js +117 -0
- package/retrieval/feedback/gap-registry.js +80 -0
- package/retrieval/feedback/human-signal.js +113 -0
- package/retrieval/feedback/index.d.ts +4 -0
- package/retrieval/feedback/index.js +24 -0
- package/retrieval/feedback/submit-feedback.js +45 -0
- package/retrieval/index.d.ts +4 -0
- package/retrieval/index.js +53 -0
- package/retrieval/intent/clarity.js +139 -0
- package/retrieval/intent/decomposer.js +124 -0
- package/retrieval/intent/index.d.ts +4 -0
- package/retrieval/intent/index.js +18 -0
- package/retrieval/intent/intent-alignment.js +172 -0
- package/retrieval/intent/intent-categorizer.js +69 -0
- package/retrieval/intent/intent-gate.js +96 -0
- package/retrieval/intent/prompt-analyzer.js +162 -0
- package/retrieval/wiring-catalog.js +168 -0
- package/validate/catalog-validator.d.ts +4 -0
- package/validate/catalog-validator.js +327 -0
- package/validate/semantic/cache.js +54 -0
- package/validate/semantic/classify-intent.js +128 -0
- package/validate/semantic/index.js +163 -0
- package/validate/semantic/intent-specs.js +162 -0
- package/validate/semantic/judge.js +180 -0
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* chunk-refiner — multi-turn refinement engine for chunk-composed UIs.
|
|
3
|
+
*
|
|
4
|
+
* Sibling to chunk-synthesizer.js. Where the synthesizer produces fresh
|
|
5
|
+
* compositions from intent, the refiner takes a prior composition + intent
|
|
6
|
+
* and emits ops that mutate it.
|
|
7
|
+
*
|
|
8
|
+
* Phase A scope (per .claude/docs/specs/genui-multiturn-architecture.md §4):
|
|
9
|
+
* - Two-pass synthesis (locator → modifier).
|
|
10
|
+
* - Validator-driven retry loop, default maxAttempts=2.
|
|
11
|
+
* - Op format: chunk-plan-level ops internally; A2UI-message-shaped on output.
|
|
12
|
+
* - Auto-fires on engine failure paths through the IssueAccumulator passed
|
|
13
|
+
* in via opts (issueAccumulator).
|
|
14
|
+
*
|
|
15
|
+
* Phase A simplification: refinements operate on the chunk binding plan
|
|
16
|
+
* (rebindSlot / appendToSlot / removeFromSlot / replacePage). The
|
|
17
|
+
* `opsToA2UI()` translator wraps each plan-mutation in a standard
|
|
18
|
+
* `updateComponents` A2UI message so the wire-format contract holds.
|
|
19
|
+
* Phase B may introduce richer component-tree refinements; this Phase A
|
|
20
|
+
* approach honors the wire format while keeping engine code focused on the
|
|
21
|
+
* chunk corpus.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import {
|
|
25
|
+
getChunk,
|
|
26
|
+
listChunksByKind,
|
|
27
|
+
searchChunksAsync,
|
|
28
|
+
} from '../../../corpus/scripts/chunk-library.js';
|
|
29
|
+
import { composeFromPlan } from './chunk-composer.js';
|
|
30
|
+
|
|
31
|
+
const DEFAULT_MAX_ATTEMPTS = 2;
|
|
32
|
+
const PRE_SEARCH_LIMIT = 30;
|
|
33
|
+
const SURFACE_ID = 'main';
|
|
34
|
+
|
|
35
|
+
const VALID_OP_TYPES = new Set(['rebindSlot', 'appendToSlot', 'removeFromSlot', 'replacePage']);
|
|
36
|
+
|
|
37
|
+
const LOCATOR_SYSTEM_PROMPT = `You identify which slots in an existing UI need modification.
|
|
38
|
+
|
|
39
|
+
You are given:
|
|
40
|
+
- An "intent" describing what the user wants changed.
|
|
41
|
+
- A "component map" listing the slots in the prior UI, each with its name
|
|
42
|
+
and the chunks currently bound to it.
|
|
43
|
+
|
|
44
|
+
If the component map is EMPTY, the prior UI is a single chunk with no bindable
|
|
45
|
+
slots. There is nothing to target: return { "targeted": false, "target_slots": [] }.
|
|
46
|
+
|
|
47
|
+
Decide if the intent is:
|
|
48
|
+
- "targeted" — the user named a specific slot/element to change, OR the
|
|
49
|
+
intent's verb implies a localized change (e.g. "change the title",
|
|
50
|
+
"remove the funnel", "add a country list to page-content").
|
|
51
|
+
- "untargeted" — broad changes touching many slots (e.g. "make everything
|
|
52
|
+
more compact", "use teal not blue").
|
|
53
|
+
|
|
54
|
+
If targeted, return target_slots: list of slot names to modify.
|
|
55
|
+
If untargeted, return targeted: false and target_slots: [].
|
|
56
|
+
|
|
57
|
+
Return ONLY a JSON object: { "targeted": bool, "target_slots": string[] }.
|
|
58
|
+
No prose. Begin with {.`;
|
|
59
|
+
|
|
60
|
+
const MODIFIER_SYSTEM_PROMPT = `You emit refinement ops on an existing chunk-composed UI.
|
|
61
|
+
|
|
62
|
+
Op types:
|
|
63
|
+
- rebindSlot: replace a slot's binding entirely.
|
|
64
|
+
{ "type": "rebindSlot", "slot": "<name>", "chunks": ["<chunk-name>"...] }
|
|
65
|
+
- appendToSlot: append chunk(s) to the END of a slot's bound list.
|
|
66
|
+
{ "type": "appendToSlot", "slot": "<name>", "chunks": ["<chunk-name>"...] }
|
|
67
|
+
- removeFromSlot: remove chunks from a slot's bound list by index.
|
|
68
|
+
{ "type": "removeFromSlot", "slot": "<name>", "indices": [0, 2] }
|
|
69
|
+
- replacePage: swap the page chunk entirely.
|
|
70
|
+
{ "type": "replacePage", "page": "<page-chunk-name>", "slot_bindings": { ... } }
|
|
71
|
+
|
|
72
|
+
Rules:
|
|
73
|
+
- Mutate only the slots you've been told to target (when target_slots provided).
|
|
74
|
+
- Every chunk name must exist in the catalog.
|
|
75
|
+
- Multi-clause intents → emit multiple ops.
|
|
76
|
+
|
|
77
|
+
SINGLE-CHUNK PRIOR (the prior plan lists NO slot bindings):
|
|
78
|
+
The prior UI is one chunk with no slots, so slot ops have nothing to
|
|
79
|
+
address — they will fail validation. Emit exactly ONE "replacePage" op that
|
|
80
|
+
re-roots the UI in a shell:
|
|
81
|
+
- "page" MUST be a catalog chunk with kind=page or kind=panel.
|
|
82
|
+
- "slot_bindings" MUST bind the PRIOR chunk (named in the prompt) into one
|
|
83
|
+
of that shell's slots, so the existing UI is preserved, PLUS the chunk(s)
|
|
84
|
+
the intent asks to add. Never drop the prior chunk unless the intent
|
|
85
|
+
explicitly asks to remove it.
|
|
86
|
+
|
|
87
|
+
Return ONLY a JSON object: { "ops": [...], "delta_summary": "<one-line>" }.
|
|
88
|
+
No prose. Begin with {.`;
|
|
89
|
+
|
|
90
|
+
function buildComponentMap(priorState) {
|
|
91
|
+
const plan = priorState?.plan;
|
|
92
|
+
if (!plan?.slot_bindings) return [];
|
|
93
|
+
return Object.entries(plan.slot_bindings).map(([slot, bound]) => ({
|
|
94
|
+
slot,
|
|
95
|
+
chunks: Array.isArray(bound) ? bound : [bound],
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* A plan with no slot bindings is a single-chunk composition — what the
|
|
101
|
+
* retrieval tier produces (gh#832). It has no addressable slots, so the only
|
|
102
|
+
* refinement the op vocabulary can express is `replacePage`.
|
|
103
|
+
*/
|
|
104
|
+
function isSingleChunkPlan(plan) {
|
|
105
|
+
return !!plan && Object.keys(plan.slot_bindings || {}).length === 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Every chunk name a plan references — its root plus everything bound. */
|
|
109
|
+
function priorPlanChunkNames(plan) {
|
|
110
|
+
const names = new Set();
|
|
111
|
+
if (!plan) return names;
|
|
112
|
+
if (plan.page) names.add(plan.page);
|
|
113
|
+
for (const bound of Object.values(plan.slot_bindings || {})) {
|
|
114
|
+
for (const n of (Array.isArray(bound) ? bound : [bound])) if (n) names.add(n);
|
|
115
|
+
}
|
|
116
|
+
return names;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function buildLocatorPrompt(intent, componentMap, plan) {
|
|
120
|
+
const lines = [];
|
|
121
|
+
lines.push(`Intent: ${intent}`);
|
|
122
|
+
lines.push('');
|
|
123
|
+
lines.push('## Component map');
|
|
124
|
+
if (componentMap.length === 0) {
|
|
125
|
+
lines.push(`(empty — the prior UI is the single chunk "${plan?.page}", no bindable slots)`);
|
|
126
|
+
}
|
|
127
|
+
for (const { slot, chunks } of componentMap) {
|
|
128
|
+
lines.push(`- ${slot}: [${chunks.join(', ')}]`);
|
|
129
|
+
}
|
|
130
|
+
lines.push('');
|
|
131
|
+
lines.push('Return JSON: { "targeted": bool, "target_slots": string[] }.');
|
|
132
|
+
return lines.join('\n');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function buildModifierPrompt(intent, priorPlan, targetedSlots, catalog) {
|
|
136
|
+
const lines = [];
|
|
137
|
+
lines.push(`Intent: ${intent}`);
|
|
138
|
+
lines.push('');
|
|
139
|
+
lines.push('## Prior plan');
|
|
140
|
+
lines.push(`Page: ${priorPlan?.page || '(unknown)'}`);
|
|
141
|
+
if (isSingleChunkPlan(priorPlan)) {
|
|
142
|
+
lines.push('Slot bindings: (none — SINGLE-CHUNK PRIOR)');
|
|
143
|
+
lines.push('');
|
|
144
|
+
lines.push(
|
|
145
|
+
`The prior UI is the single chunk "${priorPlan?.page}". Emit ONE replacePage ` +
|
|
146
|
+
`op: pick a kind=page or kind=panel shell from the catalog below and bind ` +
|
|
147
|
+
`"${priorPlan?.page}" into one of its slots ALONGSIDE the chunk(s) the intent asks for, ` +
|
|
148
|
+
`so the existing UI survives the refinement.`,
|
|
149
|
+
);
|
|
150
|
+
} else {
|
|
151
|
+
lines.push('Slot bindings:');
|
|
152
|
+
for (const [slot, bound] of Object.entries(priorPlan?.slot_bindings || {})) {
|
|
153
|
+
const arr = Array.isArray(bound) ? bound : [bound];
|
|
154
|
+
const focus = targetedSlots.includes(slot) ? ' ← TARGETED' : '';
|
|
155
|
+
lines.push(` ${slot}: [${arr.join(', ')}]${focus}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
lines.push('');
|
|
159
|
+
lines.push('## Available chunks (filtered)');
|
|
160
|
+
for (const c of catalog) {
|
|
161
|
+
const slots = c.slots?.length ? ` slots=[${c.slots.join(', ')}]` : '';
|
|
162
|
+
lines.push(`- ${c.name} (kind=${c.kind}, primary=${c.primary})${slots}`);
|
|
163
|
+
}
|
|
164
|
+
lines.push('');
|
|
165
|
+
lines.push('Return JSON: { "ops": [...], "delta_summary": "..." }');
|
|
166
|
+
return lines.join('\n');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function extractJSON(raw) {
|
|
170
|
+
if (!raw || typeof raw !== 'string') return null;
|
|
171
|
+
const trimmed = raw.trim();
|
|
172
|
+
const fenced = trimmed.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
173
|
+
const candidate = fenced ? fenced[1].trim() : trimmed;
|
|
174
|
+
try { return JSON.parse(candidate); } catch {}
|
|
175
|
+
const m = candidate.match(/\{[\s\S]*\}/);
|
|
176
|
+
if (!m) return null;
|
|
177
|
+
try { return JSON.parse(m[0]); } catch { return null; }
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Validate ops against the prior state.
|
|
182
|
+
*
|
|
183
|
+
* Checks:
|
|
184
|
+
* - Op shape (type field is one of four known types; required fields present).
|
|
185
|
+
* - Slot references exist in the prior plan.
|
|
186
|
+
* - Chunk references exist in the corpus.
|
|
187
|
+
* - Page references (replacePage) are kind=page or kind=panel.
|
|
188
|
+
*
|
|
189
|
+
* @param {object[]} ops
|
|
190
|
+
* @param {object} priorState — must have .plan.{page, slot_bindings}
|
|
191
|
+
* @returns {{ ok: boolean, errors: string[] }}
|
|
192
|
+
*/
|
|
193
|
+
export function validateOps(ops, priorState) {
|
|
194
|
+
const errors = [];
|
|
195
|
+
if (!Array.isArray(ops)) {
|
|
196
|
+
return { ok: false, errors: ['ops must be an array'] };
|
|
197
|
+
}
|
|
198
|
+
if (!priorState?.plan) {
|
|
199
|
+
return { ok: false, errors: ['priorState must have a plan with page+slot_bindings'] };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const declaredSlots = new Set(Object.keys(priorState.plan.slot_bindings || {}));
|
|
203
|
+
|
|
204
|
+
ops.forEach((op, i) => {
|
|
205
|
+
if (!op || typeof op !== 'object') {
|
|
206
|
+
errors.push(`ops[${i}]: not an object`);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const T = op.type;
|
|
210
|
+
if (!VALID_OP_TYPES.has(T)) {
|
|
211
|
+
errors.push(`ops[${i}]: unknown op type "${T}"`);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (T === 'replacePage') {
|
|
216
|
+
if (!op.page || typeof op.page !== 'string') {
|
|
217
|
+
errors.push(`ops[${i}]: replacePage requires a "page" string`);
|
|
218
|
+
} else {
|
|
219
|
+
const rec = getChunk(op.page);
|
|
220
|
+
if (!rec) {
|
|
221
|
+
errors.push(`ops[${i}]: page chunk "${op.page}" not found`);
|
|
222
|
+
} else if (rec.kind !== 'page' && rec.kind !== 'panel') {
|
|
223
|
+
errors.push(`ops[${i}]: replacePage chunk "${op.page}" must be kind page|panel; got ${rec.kind}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const bindings = op.slot_bindings || {};
|
|
227
|
+
for (const [slot, bound] of Object.entries(bindings)) {
|
|
228
|
+
const names = Array.isArray(bound) ? bound : [bound];
|
|
229
|
+
for (const name of names) {
|
|
230
|
+
if (!getChunk(name)) {
|
|
231
|
+
errors.push(`ops[${i}]: bound chunk "${name}" (slot "${slot}") not found`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (!op.slot || typeof op.slot !== 'string') {
|
|
239
|
+
errors.push(`ops[${i}]: ${T} requires a "slot" string`);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
if (!declaredSlots.has(op.slot)) {
|
|
243
|
+
errors.push(`ops[${i}]: slot "${op.slot}" not in prior plan (declared: ${[...declaredSlots].join(',')})`);
|
|
244
|
+
}
|
|
245
|
+
if (T === 'rebindSlot' || T === 'appendToSlot') {
|
|
246
|
+
if (!Array.isArray(op.chunks) || op.chunks.length === 0) {
|
|
247
|
+
errors.push(`ops[${i}]: ${T} requires a non-empty "chunks" array`);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
for (const c of op.chunks) {
|
|
251
|
+
if (!getChunk(c)) errors.push(`ops[${i}]: chunk "${c}" not found`);
|
|
252
|
+
}
|
|
253
|
+
} else if (T === 'removeFromSlot') {
|
|
254
|
+
if (!Array.isArray(op.indices) || op.indices.length === 0) {
|
|
255
|
+
errors.push(`ops[${i}]: removeFromSlot requires a non-empty "indices" array`);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
const slotBound = priorState.plan.slot_bindings[op.slot];
|
|
259
|
+
const slotArr = Array.isArray(slotBound) ? slotBound : (slotBound ? [slotBound] : []);
|
|
260
|
+
for (const idx of op.indices) {
|
|
261
|
+
if (!Number.isInteger(idx) || idx < 0 || idx >= slotArr.length) {
|
|
262
|
+
errors.push(`ops[${i}]: index ${idx} out of range for slot "${op.slot}" (length ${slotArr.length})`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
return { ok: errors.length === 0, errors };
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Apply ops to the prior state.
|
|
273
|
+
*
|
|
274
|
+
* Op-level failures are non-fatal — the apply phase continues with subsequent
|
|
275
|
+
* ops. Returns { newState, ops_applied, ops_failed }. The `newState` includes
|
|
276
|
+
* the mutated plan + freshly materialized HTML.
|
|
277
|
+
*
|
|
278
|
+
* @param {object} input
|
|
279
|
+
* @param {object} input.priorState — { plan, html, ... }
|
|
280
|
+
* @param {object[]} input.ops
|
|
281
|
+
* @returns {Promise<{
|
|
282
|
+
* newState: { plan, html, warnings },
|
|
283
|
+
* ops_applied: object[],
|
|
284
|
+
* ops_failed: { op, reason }[],
|
|
285
|
+
* }>}
|
|
286
|
+
*/
|
|
287
|
+
export async function applyOps({ priorState, ops }) {
|
|
288
|
+
if (!priorState?.plan) {
|
|
289
|
+
return {
|
|
290
|
+
newState: priorState,
|
|
291
|
+
ops_applied: [],
|
|
292
|
+
ops_failed: (ops || []).map((op) => ({ op, reason: 'priorState has no plan' })),
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Deep-clone the plan so we mutate a copy
|
|
297
|
+
const plan = {
|
|
298
|
+
page: priorState.plan.page,
|
|
299
|
+
slot_bindings: {},
|
|
300
|
+
};
|
|
301
|
+
for (const [slot, bound] of Object.entries(priorState.plan.slot_bindings || {})) {
|
|
302
|
+
plan.slot_bindings[slot] = Array.isArray(bound) ? [...bound] : (bound ? [bound] : []);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const ops_applied = [];
|
|
306
|
+
const ops_failed = [];
|
|
307
|
+
|
|
308
|
+
for (const op of (ops || [])) {
|
|
309
|
+
try {
|
|
310
|
+
if (!op || typeof op !== 'object') {
|
|
311
|
+
ops_failed.push({ op, reason: 'op is not an object' });
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
if (op.type === 'rebindSlot') {
|
|
315
|
+
if (!Array.isArray(op.chunks)) {
|
|
316
|
+
ops_failed.push({ op, reason: 'rebindSlot.chunks must be an array' });
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
plan.slot_bindings[op.slot] = [...op.chunks];
|
|
320
|
+
ops_applied.push(op);
|
|
321
|
+
} else if (op.type === 'appendToSlot') {
|
|
322
|
+
if (!Array.isArray(op.chunks)) {
|
|
323
|
+
ops_failed.push({ op, reason: 'appendToSlot.chunks must be an array' });
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
const cur = plan.slot_bindings[op.slot];
|
|
327
|
+
const arr = Array.isArray(cur) ? [...cur] : (cur ? [cur] : []);
|
|
328
|
+
arr.push(...op.chunks);
|
|
329
|
+
plan.slot_bindings[op.slot] = arr;
|
|
330
|
+
ops_applied.push(op);
|
|
331
|
+
} else if (op.type === 'removeFromSlot') {
|
|
332
|
+
if (!Array.isArray(op.indices)) {
|
|
333
|
+
ops_failed.push({ op, reason: 'removeFromSlot.indices must be an array' });
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
const cur = plan.slot_bindings[op.slot];
|
|
337
|
+
const arr = Array.isArray(cur) ? [...cur] : (cur ? [cur] : []);
|
|
338
|
+
const dropSet = new Set(op.indices);
|
|
339
|
+
plan.slot_bindings[op.slot] = arr.filter((_, i) => !dropSet.has(i));
|
|
340
|
+
ops_applied.push(op);
|
|
341
|
+
} else if (op.type === 'replacePage') {
|
|
342
|
+
plan.page = op.page;
|
|
343
|
+
plan.slot_bindings = {};
|
|
344
|
+
for (const [slot, bound] of Object.entries(op.slot_bindings || {})) {
|
|
345
|
+
plan.slot_bindings[slot] = Array.isArray(bound) ? [...bound] : (bound ? [bound] : []);
|
|
346
|
+
}
|
|
347
|
+
ops_applied.push(op);
|
|
348
|
+
} else {
|
|
349
|
+
ops_failed.push({ op, reason: `unknown op type "${op.type}"` });
|
|
350
|
+
}
|
|
351
|
+
} catch (e) {
|
|
352
|
+
ops_failed.push({ op, reason: e.message });
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Re-materialize the HTML
|
|
357
|
+
const composed = composeFromPlan(plan);
|
|
358
|
+
|
|
359
|
+
return {
|
|
360
|
+
newState: {
|
|
361
|
+
plan,
|
|
362
|
+
html: composed.html,
|
|
363
|
+
warnings: composed.warnings || [],
|
|
364
|
+
},
|
|
365
|
+
ops_applied,
|
|
366
|
+
ops_failed,
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Translate chunk-plan-level ops to A2UI message arrays for wire-format
|
|
372
|
+
* compatibility (spec §2.3 + §3.4).
|
|
373
|
+
*
|
|
374
|
+
* Phase A approach: each chunk-plan op produces one `updateComponents`
|
|
375
|
+
* message targeting the affected slot. Components carry a `chunk_op` echo
|
|
376
|
+
* + a materialized `html` string. Phase B may upgrade `html` to a proper
|
|
377
|
+
* component-tree shape.
|
|
378
|
+
*
|
|
379
|
+
* @param {object[]} ops — chunk-plan ops (post-validation)
|
|
380
|
+
* @param {object} newState — { html, plan, warnings } from applyOps
|
|
381
|
+
* @returns {object[]} A2UI messages
|
|
382
|
+
*/
|
|
383
|
+
export function opsToA2UI(ops, newState) {
|
|
384
|
+
const messages = [];
|
|
385
|
+
for (const op of (ops || [])) {
|
|
386
|
+
if (op.type === 'replacePage') {
|
|
387
|
+
messages.push({
|
|
388
|
+
type: 'updateComponents',
|
|
389
|
+
surfaceId: SURFACE_ID,
|
|
390
|
+
components: [
|
|
391
|
+
{
|
|
392
|
+
id: SURFACE_ID,
|
|
393
|
+
chunk_op: op,
|
|
394
|
+
html: newState?.html ?? null,
|
|
395
|
+
},
|
|
396
|
+
],
|
|
397
|
+
});
|
|
398
|
+
} else {
|
|
399
|
+
messages.push({
|
|
400
|
+
type: 'updateComponents',
|
|
401
|
+
surfaceId: SURFACE_ID,
|
|
402
|
+
components: [
|
|
403
|
+
{
|
|
404
|
+
id: `slot-${op.slot}`,
|
|
405
|
+
chunk_op: op,
|
|
406
|
+
html: newState?.html ?? null,
|
|
407
|
+
},
|
|
408
|
+
],
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
return messages;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Refine a prior composition based on a natural-language intent.
|
|
417
|
+
*
|
|
418
|
+
* Two-pass synthesis:
|
|
419
|
+
* Pass 1 (locator) — LLM identifies which slots to modify.
|
|
420
|
+
* Pass 2 (modifier) — LLM emits chunk-plan ops on the targeted slots.
|
|
421
|
+
*
|
|
422
|
+
* Validator-driven retry: if modifier ops fail validation, the engine
|
|
423
|
+
* re-prompts with errors, up to maxAttempts.
|
|
424
|
+
*
|
|
425
|
+
* Auto-fires on these failure paths (when issueAccumulator is provided):
|
|
426
|
+
* - locator-empty-targets: targeted=true but target_slots is empty.
|
|
427
|
+
* - validator-exhausted: maxAttempts reached without valid ops.
|
|
428
|
+
*
|
|
429
|
+
* @param {object} opts
|
|
430
|
+
* @param {object} opts.priorState — { state_id, plan, html, ... }
|
|
431
|
+
* @param {string} opts.intent
|
|
432
|
+
* @param {object} opts.llmAdapter — { complete: async ({messages, systemPrompt}) }
|
|
433
|
+
* @param {number} [opts.maxAttempts=2]
|
|
434
|
+
* @param {object} [opts.issueAccumulator] — IssueAccumulator from issue-reporter.js
|
|
435
|
+
* @returns {Promise<{
|
|
436
|
+
* ops: object[],
|
|
437
|
+
* delta_summary?: string,
|
|
438
|
+
* warnings: string[],
|
|
439
|
+
* synthesis: { attempts, attemptsLog?, locatedTargets, targeted },
|
|
440
|
+
* }>}
|
|
441
|
+
*/
|
|
442
|
+
export async function refineFromIntent({
|
|
443
|
+
priorState,
|
|
444
|
+
intent,
|
|
445
|
+
llmAdapter,
|
|
446
|
+
maxAttempts = DEFAULT_MAX_ATTEMPTS,
|
|
447
|
+
issueAccumulator = null,
|
|
448
|
+
catalog = null,
|
|
449
|
+
}) {
|
|
450
|
+
if (!priorState?.plan) {
|
|
451
|
+
return {
|
|
452
|
+
ops: [],
|
|
453
|
+
warnings: ['priorState has no plan; cannot refine'],
|
|
454
|
+
synthesis: { attempts: 0, locatedTargets: null, targeted: false },
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
if (!llmAdapter?.complete) {
|
|
458
|
+
return {
|
|
459
|
+
ops: [],
|
|
460
|
+
warnings: ['no llmAdapter provided'],
|
|
461
|
+
synthesis: { attempts: 0, locatedTargets: null, targeted: false },
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Pass 1 — locate
|
|
466
|
+
const componentMap = buildComponentMap(priorState);
|
|
467
|
+
const locatorPrompt = buildLocatorPrompt(intent, componentMap, priorState.plan);
|
|
468
|
+
const locatorResp = await llmAdapter.complete({
|
|
469
|
+
messages: [{ role: 'user', content: locatorPrompt }],
|
|
470
|
+
systemPrompt: LOCATOR_SYSTEM_PROMPT,
|
|
471
|
+
});
|
|
472
|
+
const locatorRaw = locatorResp?.content || locatorResp?.text || '';
|
|
473
|
+
const locatorParsed = extractJSON(locatorRaw);
|
|
474
|
+
|
|
475
|
+
let targeted = false;
|
|
476
|
+
let target_slots = [];
|
|
477
|
+
if (locatorParsed && typeof locatorParsed === 'object') {
|
|
478
|
+
targeted = !!locatorParsed.targeted;
|
|
479
|
+
target_slots = Array.isArray(locatorParsed.target_slots) ? locatorParsed.target_slots : [];
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
if (targeted && target_slots.length === 0) {
|
|
483
|
+
issueAccumulator?.add('locator-empty-targets', {
|
|
484
|
+
intent,
|
|
485
|
+
state_id: priorState.state_id,
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// Pass 2 — modify. Pre-search the catalog if not provided.
|
|
490
|
+
let resolvedCatalog = catalog;
|
|
491
|
+
if (!resolvedCatalog) {
|
|
492
|
+
const blockHits = await searchChunksAsync(intent, { kind: 'block', limit: PRE_SEARCH_LIMIT });
|
|
493
|
+
const blockChunks = blockHits.map((h) => getChunk(h.name)).filter(Boolean);
|
|
494
|
+
const pageChunks = listChunksByKind('page');
|
|
495
|
+
const panelChunks = listChunksByKind('panel');
|
|
496
|
+
const filtered = [...pageChunks, ...panelChunks, ...blockChunks];
|
|
497
|
+
resolvedCatalog = filtered.map((c) => ({
|
|
498
|
+
name: c.name,
|
|
499
|
+
kind: c.kind,
|
|
500
|
+
primary: c.primary || c.instances?.[0]?.primary,
|
|
501
|
+
slots: (c.slots || c.instances?.[0]?.slots || []).map((s) => s.name),
|
|
502
|
+
}));
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// The prior plan's own chunks must be in the catalog the modifier sees:
|
|
506
|
+
// a single-chunk refinement has to re-bind the prior root by name, and the
|
|
507
|
+
// intent-driven pre-search (which searches for the CHANGE, not the existing
|
|
508
|
+
// UI) has no reason to surface it (gh#832).
|
|
509
|
+
const catalogNames = new Set(resolvedCatalog.map((c) => c.name));
|
|
510
|
+
for (const name of priorPlanChunkNames(priorState.plan)) {
|
|
511
|
+
if (catalogNames.has(name)) continue;
|
|
512
|
+
const rec = getChunk(name);
|
|
513
|
+
if (!rec) continue;
|
|
514
|
+
catalogNames.add(name);
|
|
515
|
+
resolvedCatalog = [
|
|
516
|
+
...resolvedCatalog,
|
|
517
|
+
{
|
|
518
|
+
name: rec.name,
|
|
519
|
+
kind: rec.kind,
|
|
520
|
+
primary: rec.primary || rec.instances?.[0]?.primary,
|
|
521
|
+
slots: (rec.slots || rec.instances?.[0]?.slots || []).map((s) => s.name),
|
|
522
|
+
},
|
|
523
|
+
];
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const modifierUserPrompt = buildModifierPrompt(intent, priorState.plan, target_slots, resolvedCatalog);
|
|
527
|
+
const attemptsLog = [];
|
|
528
|
+
let lastError = null;
|
|
529
|
+
|
|
530
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
531
|
+
const retryNudge = lastError
|
|
532
|
+
? `\n\nPREVIOUS ATTEMPT FAILED VALIDATION: ${lastError}. Re-emit ops without invalid references.`
|
|
533
|
+
: '';
|
|
534
|
+
const modifierResp = await llmAdapter.complete({
|
|
535
|
+
messages: [{ role: 'user', content: modifierUserPrompt + retryNudge }],
|
|
536
|
+
systemPrompt: MODIFIER_SYSTEM_PROMPT,
|
|
537
|
+
});
|
|
538
|
+
const modifierRaw = modifierResp?.content || modifierResp?.text || '';
|
|
539
|
+
attemptsLog.push({ attempt: i + 1, raw: modifierRaw });
|
|
540
|
+
|
|
541
|
+
const parsed = extractJSON(modifierRaw);
|
|
542
|
+
if (!parsed || !Array.isArray(parsed.ops)) {
|
|
543
|
+
lastError = 'response was not valid JSON with { ops: [...] } shape';
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
const validation = validateOps(parsed.ops, priorState);
|
|
548
|
+
if (!validation.ok) {
|
|
549
|
+
lastError = validation.errors.slice(0, 3).join('; ');
|
|
550
|
+
continue;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
return {
|
|
554
|
+
ops: parsed.ops,
|
|
555
|
+
delta_summary: parsed.delta_summary || '',
|
|
556
|
+
warnings: [],
|
|
557
|
+
synthesis: {
|
|
558
|
+
attempts: i + 1,
|
|
559
|
+
attemptsLog,
|
|
560
|
+
locatedTargets: target_slots,
|
|
561
|
+
targeted,
|
|
562
|
+
},
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
issueAccumulator?.add('validator-exhausted', {
|
|
567
|
+
state_id: priorState.state_id,
|
|
568
|
+
tool: 'refine_composition',
|
|
569
|
+
intent,
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
return {
|
|
573
|
+
ops: [],
|
|
574
|
+
warnings: [`refinement failed after ${maxAttempts} attempts: ${lastError}`],
|
|
575
|
+
synthesis: {
|
|
576
|
+
attempts: maxAttempts,
|
|
577
|
+
attemptsLog,
|
|
578
|
+
locatedTargets: target_slots,
|
|
579
|
+
targeted,
|
|
580
|
+
},
|
|
581
|
+
};
|
|
582
|
+
}
|