@elytracms/studio 0.0.92 → 0.0.94
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/convex/analytics-cost.test.ts +817 -0
- package/convex/asset-alt-migration.test.ts +127 -0
- package/convex/asset-replace.test.ts +168 -0
- package/convex/asset-revalidate.test.ts +6 -6
- package/convex/assets.ts +41 -5
- package/convex/auth.ts +5 -2
- package/convex/authority.ts +35 -11
- package/convex/cms.ts +25 -11
- package/convex/contract-parity.test.ts +25 -3
- package/convex/delivery.ts +12 -9
- package/convex/document-revalidate.test.ts +10 -12
- package/convex/guard.ts +9 -7
- package/convex/http-routes.test.ts +18 -8
- package/convex/http.ts +23 -17
- package/convex/ingest.test.ts +326 -0
- package/convex/ingest.ts +281 -0
- package/convex/invites.ts +13 -5
- package/convex/members.ts +10 -4
- package/convex/orphan-hydration.test.ts +116 -0
- package/convex/rail-write-parity.test.ts +11 -8
- package/convex/record-functions.ts +325 -0
- package/convex/records.test.ts +156 -0
- package/convex/redirect-migration.test.ts +205 -0
- package/convex/redirect-revalidate.test.ts +5 -1
- package/convex/redirects.ts +120 -79
- package/convex/role-policy.test.ts +315 -0
- package/convex/roles.ts +83 -0
- package/convex/schema.ts +36 -0
- package/convex/triggers.ts +21 -1
- package/dist/addon.d.ts +71 -0
- package/dist/addon.js +67 -0
- package/dist/addon.js.map +1 -0
- package/dist/components/account/account-settings.js +2 -2
- package/dist/components/account/account-settings.js.map +1 -1
- package/dist/components/account/credential-panel.js +2 -2
- package/dist/components/account/credential-panel.js.map +1 -1
- package/dist/components/account/self-account-schema.d.ts +6 -15
- package/dist/components/account/self-account-schema.js +52 -34
- package/dist/components/account/self-account-schema.js.map +1 -1
- package/dist/components/account/self-account-view-source.d.ts +1 -1
- package/dist/components/account/self-account-view-source.js +6 -4
- package/dist/components/account/self-account-view-source.js.map +1 -1
- package/dist/components/ai/ai-chat-panel-lazy.js +1 -1
- package/dist/components/ai/ai-chat-panel-lazy.js.map +1 -1
- package/dist/components/ai/ai-chat-panel.js +6 -6
- package/dist/components/ai/ai-chat-panel.js.map +1 -1
- package/dist/components/ai/ai-cms-panel.js +2 -2
- package/dist/components/ai/ai-cms-panel.js.map +1 -1
- package/dist/components/ai/ai-panel-toggle.js +4 -4
- package/dist/components/ai/ai-panel-toggle.js.map +1 -1
- package/dist/components/ai/chat-ui.js +2 -2
- package/dist/components/ai/chat-ui.js.map +1 -1
- package/dist/components/ai/proposal-card.d.ts +2 -2
- package/dist/components/ai/proposal-card.js +4 -3
- package/dist/components/ai/proposal-card.js.map +1 -1
- package/dist/components/ai/proposal-issues.js +2 -2
- package/dist/components/ai/proposal-issues.js.map +1 -1
- package/dist/components/ai/translate-document-action.js +2 -2
- package/dist/components/ai/translate-document-action.js.map +1 -1
- package/dist/components/ai/translate-document-dialog.js +10 -8
- package/dist/components/ai/translate-document-dialog.js.map +1 -1
- package/dist/components/ai/translate-skipped.d.ts +19 -0
- package/dist/components/ai/translate-skipped.js +46 -0
- package/dist/components/ai/translate-skipped.js.map +1 -0
- package/dist/components/app-views/default-modules.d.ts +50 -2
- package/dist/components/app-views/default-modules.js +65 -20
- package/dist/components/app-views/default-modules.js.map +1 -1
- package/dist/components/app-views/module.d.ts +53 -3
- package/dist/components/app-views/module.js +14 -7
- package/dist/components/app-views/module.js.map +1 -1
- package/dist/components/app-views/sidebar.js +1 -1
- package/dist/components/app-views/sidebar.js.map +1 -1
- package/dist/components/app-views/studio-config.d.ts +11 -2
- package/dist/components/app-views/studio-config.js.map +1 -1
- package/dist/components/assets/asset-detail.js +20 -10
- package/dist/components/assets/asset-detail.js.map +1 -1
- package/dist/components/assets/asset-grid.js +2 -2
- package/dist/components/assets/asset-grid.js.map +1 -1
- package/dist/components/assets/asset-metadata.d.ts +15 -4
- package/dist/components/assets/asset-metadata.js +15 -2
- package/dist/components/assets/asset-metadata.js.map +1 -1
- package/dist/components/assets/asset-search.js +4 -1
- package/dist/components/assets/asset-search.js.map +1 -1
- package/dist/components/assets/asset-selection.d.ts +0 -8
- package/dist/components/assets/asset-selection.js +4 -23
- package/dist/components/assets/asset-selection.js.map +1 -1
- package/dist/components/assets/asset-thumb.js +6 -5
- package/dist/components/assets/asset-thumb.js.map +1 -1
- package/dist/components/assets/assets-collection-view-source.d.ts +5 -5
- package/dist/components/assets/assets-collection-view-source.js +9 -5
- package/dist/components/assets/assets-collection-view-source.js.map +1 -1
- package/dist/components/assets/assets-module.js +1 -1
- package/dist/components/assets/assets-module.js.map +1 -1
- package/dist/components/assets/assets-store.d.ts +16 -2
- package/dist/components/assets/assets-store.js +28 -6
- package/dist/components/assets/assets-store.js.map +1 -1
- package/dist/components/assets/assets-view-preference.js +1 -1
- package/dist/components/assets/assets-view-preference.js.map +1 -1
- package/dist/components/assets/replace-file.d.ts +22 -0
- package/dist/components/assets/replace-file.js +59 -0
- package/dist/components/assets/replace-file.js.map +1 -0
- package/dist/components/auth-context.d.ts +1 -1
- package/dist/components/auth-context.js +6 -6
- package/dist/components/auth-context.js.map +1 -1
- package/dist/components/builder/blocks-model.d.ts +15 -27
- package/dist/components/builder/blocks-model.js +38 -44
- package/dist/components/builder/blocks-model.js.map +1 -1
- package/dist/components/builder/blocks-panel.d.ts +8 -4
- package/dist/components/builder/blocks-panel.js +10 -9
- package/dist/components/builder/blocks-panel.js.map +1 -1
- package/dist/components/builder/builder-store.d.ts +104 -15
- package/dist/components/builder/builder-store.js +157 -32
- package/dist/components/builder/builder-store.js.map +1 -1
- package/dist/components/builder/canvas-body.d.ts +30 -0
- package/dist/components/builder/canvas-body.js +38 -0
- package/dist/components/builder/canvas-body.js.map +1 -0
- package/dist/components/builder/canvas-breakpoints.js +1 -1
- package/dist/components/builder/canvas-breakpoints.js.map +1 -1
- package/dist/components/builder/canvas-chrome-css.js +7 -0
- package/dist/components/builder/canvas-chrome-css.js.map +1 -1
- package/dist/components/builder/canvas-dnd.d.ts +9 -9
- package/dist/components/builder/canvas-dnd.js +6 -6
- package/dist/components/builder/canvas-dnd.js.map +1 -1
- package/dist/components/builder/canvas-inline-editing.d.ts +1 -1
- package/dist/components/builder/canvas-inline-editing.js.map +1 -1
- package/dist/components/builder/canvas-overlay-geometry.d.ts +1 -1
- package/dist/components/builder/canvas-overlay-geometry.js.map +1 -1
- package/dist/components/builder/canvas-render-context.d.ts +28 -20
- package/dist/components/builder/canvas-render-context.js +46 -47
- package/dist/components/builder/canvas-render-context.js.map +1 -1
- package/dist/components/builder/canvas-runs.d.ts +45 -0
- package/dist/components/builder/canvas-runs.js +51 -0
- package/dist/components/builder/canvas-runs.js.map +1 -0
- package/dist/components/builder/canvas-theme-notice.js +2 -2
- package/dist/components/builder/canvas-theme-notice.js.map +1 -1
- package/dist/components/builder/canvas.js +35 -8
- package/dist/components/builder/canvas.js.map +1 -1
- package/dist/components/builder/clipboard-actions.d.ts +16 -1
- package/dist/components/builder/clipboard-actions.js +48 -11
- package/dist/components/builder/clipboard-actions.js.map +1 -1
- package/dist/components/builder/composition-field-editor-lazy.js +1 -1
- package/dist/components/builder/composition-field-editor-lazy.js.map +1 -1
- package/dist/components/builder/composition-field-editor.d.ts +4 -16
- package/dist/components/builder/composition-field-editor.js +32 -43
- package/dist/components/builder/composition-field-editor.js.map +1 -1
- package/dist/components/builder/delete-key.d.ts +5 -0
- package/dist/components/builder/delete-key.js +4 -0
- package/dist/components/builder/delete-key.js.map +1 -1
- package/dist/components/builder/drag-session.d.ts +1 -1
- package/dist/components/builder/drag-session.js.map +1 -1
- package/dist/components/builder/fixture-thumbnail.js +1 -1
- package/dist/components/builder/fixture-thumbnail.js.map +1 -1
- package/dist/components/builder/insert-context.d.ts +18 -26
- package/dist/components/builder/insert-context.js +47 -94
- package/dist/components/builder/insert-context.js.map +1 -1
- package/dist/components/builder/layout-inspector.js +1 -1
- package/dist/components/builder/layout-inspector.js.map +1 -1
- package/dist/components/builder/node-title.js +1 -1
- package/dist/components/builder/node-title.js.map +1 -1
- package/dist/components/builder/page-tree.d.ts +4 -4
- package/dist/components/builder/page-tree.js +8 -8
- package/dist/components/builder/page-tree.js.map +1 -1
- package/dist/components/builder/placement-refusal.d.ts +18 -0
- package/dist/components/builder/placement-refusal.js +46 -0
- package/dist/components/builder/placement-refusal.js.map +1 -0
- package/dist/components/builder/property-inspector.js +8 -4
- package/dist/components/builder/property-inspector.js.map +1 -1
- package/dist/components/builder/reuse-context.js +68 -30
- package/dist/components/builder/reuse-context.js.map +1 -1
- package/dist/components/builder/reuse.d.ts +79 -1
- package/dist/components/builder/reuse.js +70 -3
- package/dist/components/builder/reuse.js.map +1 -1
- package/dist/components/builder/rich-text-toolbar.js +1 -1
- package/dist/components/builder/rich-text-toolbar.js.map +1 -1
- package/dist/components/builder/run-inspector.d.ts +11 -0
- package/dist/components/builder/run-inspector.js +33 -0
- package/dist/components/builder/run-inspector.js.map +1 -0
- package/dist/components/builder/selection-overlay.js +3 -3
- package/dist/components/builder/selection-overlay.js.map +1 -1
- package/dist/components/builder/spacing-handles.d.ts +2 -2
- package/dist/components/builder/spacing-handles.js +3 -3
- package/dist/components/builder/spacing-handles.js.map +1 -1
- package/dist/components/cms/asset-field.d.ts +38 -1
- package/dist/components/cms/asset-field.js +184 -60
- package/dist/components/cms/asset-field.js.map +1 -1
- package/dist/components/cms/asset-picker-core.d.ts +16 -0
- package/dist/components/cms/asset-picker-core.js +20 -0
- package/dist/components/cms/asset-picker-core.js.map +1 -1
- package/dist/components/cms/asset-picker.js +14 -20
- package/dist/components/cms/asset-picker.js.map +1 -1
- package/dist/components/cms/bulk-actions.d.ts +4 -20
- package/dist/components/cms/bulk-actions.js +5 -26
- package/dist/components/cms/bulk-actions.js.map +1 -1
- package/dist/components/cms/bulk-bar.d.ts +2 -2
- package/dist/components/cms/bulk-bar.js +2 -2
- package/dist/components/cms/bulk-bar.js.map +1 -1
- package/dist/components/cms/cell-edit.d.ts +1 -1
- package/dist/components/cms/cell-edit.js +1 -1
- package/dist/components/cms/cell-edit.js.map +1 -1
- package/dist/components/cms/cell.d.ts +1 -1
- package/dist/components/cms/cell.js +3 -3
- package/dist/components/cms/cell.js.map +1 -1
- package/dist/components/cms/cms-index.js +2 -2
- package/dist/components/cms/cms-index.js.map +1 -1
- package/dist/components/cms/cms-labels.js +2 -2
- package/dist/components/cms/cms-labels.js.map +1 -1
- package/dist/components/cms/cms-store.d.ts +7 -6
- package/dist/components/cms/cms-store.js +23 -43
- package/dist/components/cms/cms-store.js.map +1 -1
- package/dist/components/cms/collection-table.js +7 -7
- package/dist/components/cms/collection-table.js.map +1 -1
- package/dist/components/cms/detail-editor.d.ts +5 -2
- package/dist/components/cms/detail-editor.js +20 -15
- package/dist/components/cms/detail-editor.js.map +1 -1
- package/dist/components/cms/details-pane.js +1 -1
- package/dist/components/cms/details-pane.js.map +1 -1
- package/dist/components/cms/doc-state.js +1 -1
- package/dist/components/cms/doc-state.js.map +1 -1
- package/dist/components/cms/document-diff-view.d.ts +3 -1
- package/dist/components/cms/document-diff-view.js +17 -12
- package/dist/components/cms/document-diff-view.js.map +1 -1
- package/dist/components/cms/document-editor-context.js +1 -1
- package/dist/components/cms/document-editor-context.js.map +1 -1
- package/dist/components/cms/document-staging.js +1 -1
- package/dist/components/cms/document-staging.js.map +1 -1
- package/dist/components/cms/document-url-path.js +2 -2
- package/dist/components/cms/document-url-path.js.map +1 -1
- package/dist/components/cms/duplicate-document.d.ts +1 -1
- package/dist/components/cms/duplicate-document.js.map +1 -1
- package/dist/components/cms/editable-cell.js +3 -3
- package/dist/components/cms/editable-cell.js.map +1 -1
- package/dist/components/cms/field-anchors.d.ts +7 -4
- package/dist/components/cms/field-anchors.js +9 -7
- package/dist/components/cms/field-anchors.js.map +1 -1
- package/dist/components/cms/field-collaboration.d.ts +1 -1
- package/dist/components/cms/field-collaboration.js +1 -1
- package/dist/components/cms/field-collaboration.js.map +1 -1
- package/dist/components/cms/field-connection.d.ts +1 -1
- package/dist/components/cms/field-connection.js +2 -2
- package/dist/components/cms/field-connection.js.map +1 -1
- package/dist/components/cms/field-control-lib.d.ts +15 -1
- package/dist/components/cms/field-control-lib.js +23 -4
- package/dist/components/cms/field-control-lib.js.map +1 -1
- package/dist/components/cms/field-control.js +4 -4
- package/dist/components/cms/field-control.js.map +1 -1
- package/dist/components/cms/field-renderer.d.ts +1 -1
- package/dist/components/cms/field-renderer.js +2 -2
- package/dist/components/cms/field-renderer.js.map +1 -1
- package/dist/components/cms/filter-builder.d.ts +1 -1
- package/dist/components/cms/filter-builder.js +3 -3
- package/dist/components/cms/filter-builder.js.map +1 -1
- package/dist/components/cms/gate-validation.d.ts +21 -30
- package/dist/components/cms/gate-validation.js +11 -32
- package/dist/components/cms/gate-validation.js.map +1 -1
- package/dist/components/cms/import-export.js +2 -2
- package/dist/components/cms/import-export.js.map +1 -1
- package/dist/components/cms/issue-copy.js +1 -1
- package/dist/components/cms/issue-copy.js.map +1 -1
- package/dist/components/cms/issues-pane.js +3 -3
- package/dist/components/cms/issues-pane.js.map +1 -1
- package/dist/components/cms/object-array-field.js +6 -6
- package/dist/components/cms/object-array-field.js.map +1 -1
- package/dist/components/cms/prop-fields.d.ts +7 -2
- package/dist/components/cms/prop-fields.js +14 -7
- package/dist/components/cms/prop-fields.js.map +1 -1
- package/dist/components/cms/reference-confirm.d.ts +1 -1
- package/dist/components/cms/reference-confirm.js +2 -2
- package/dist/components/cms/reference-confirm.js.map +1 -1
- package/dist/components/cms/relation-picker.js +2 -2
- package/dist/components/cms/relation-picker.js.map +1 -1
- package/dist/components/cms/rich-text/block-style.js +1 -1
- package/dist/components/cms/rich-text/block-style.js.map +1 -1
- package/dist/components/cms/rich-text/component-embed.js +4 -4
- package/dist/components/cms/rich-text/component-embed.js.map +1 -1
- package/dist/components/cms/rich-text/editor.js +3 -3
- package/dist/components/cms/rich-text/editor.js.map +1 -1
- package/dist/components/cms/rich-text/embed-picker.d.ts +1 -1
- package/dist/components/cms/rich-text/embed-picker.js +3 -3
- package/dist/components/cms/rich-text/embed-picker.js.map +1 -1
- package/dist/components/cms/rich-text/embed-props.js +3 -3
- package/dist/components/cms/rich-text/embed-props.js.map +1 -1
- package/dist/components/cms/rich-text/extensions.js +1 -1
- package/dist/components/cms/rich-text/extensions.js.map +1 -1
- package/dist/components/cms/rich-text/font-size-control.d.ts +1 -1
- package/dist/components/cms/rich-text/font-size-control.js +2 -2
- package/dist/components/cms/rich-text/font-size-control.js.map +1 -1
- package/dist/components/cms/rich-text/insert.d.ts +20 -9
- package/dist/components/cms/rich-text/insert.js +25 -17
- package/dist/components/cms/rich-text/insert.js.map +1 -1
- package/dist/components/cms/rich-text/lazy.js +1 -1
- package/dist/components/cms/rich-text/lazy.js.map +1 -1
- package/dist/components/cms/rich-text/link-control.js +2 -2
- package/dist/components/cms/rich-text/link-control.js.map +1 -1
- package/dist/components/cms/rich-text/slash-command.js +3 -3
- package/dist/components/cms/rich-text/slash-command.js.map +1 -1
- package/dist/components/cms/rich-text/toolbar.js +1 -1
- package/dist/components/cms/rich-text/toolbar.js.map +1 -1
- package/dist/components/cms/rich-text/unknown-node.js +2 -2
- package/dist/components/cms/rich-text/unknown-node.js.map +1 -1
- package/dist/components/cms/rich-text-preview.js +2 -2
- package/dist/components/cms/rich-text-preview.js.map +1 -1
- package/dist/components/cms/row-actions.d.ts +1 -1
- package/dist/components/cms/row-actions.js.map +1 -1
- package/dist/components/cms/scalar-value-editor.d.ts +1 -1
- package/dist/components/cms/scalar-value-editor.js +2 -2
- package/dist/components/cms/scalar-value-editor.js.map +1 -1
- package/dist/components/cms/use-discard-controller.d.ts +1 -1
- package/dist/components/cms/use-discard-controller.js +1 -1
- package/dist/components/cms/use-discard-controller.js.map +1 -1
- package/dist/components/cms/use-document-draft.d.ts +7 -1
- package/dist/components/cms/use-document-draft.js +16 -2
- package/dist/components/cms/use-document-draft.js.map +1 -1
- package/dist/components/cms/use-document-versions.js +1 -1
- package/dist/components/cms/use-document-versions.js.map +1 -1
- package/dist/components/cms/use-field-focus.d.ts +1 -1
- package/dist/components/cms/use-field-focus.js +2 -2
- package/dist/components/cms/use-field-focus.js.map +1 -1
- package/dist/components/cms/use-live-url.d.ts +1 -1
- package/dist/components/cms/use-live-url.js +3 -3
- package/dist/components/cms/use-live-url.js.map +1 -1
- package/dist/components/cms/use-publish-controller.d.ts +2 -3
- package/dist/components/cms/use-publish-controller.js +8 -20
- package/dist/components/cms/use-publish-controller.js.map +1 -1
- package/dist/components/cms/use-published-perspective.d.ts +1 -1
- package/dist/components/cms/use-published-perspective.js.map +1 -1
- package/dist/components/cms/use-restore-version.d.ts +1 -1
- package/dist/components/cms/use-restore-version.js +1 -1
- package/dist/components/cms/use-restore-version.js.map +1 -1
- package/dist/components/cms/version-compare-lazy.js +1 -1
- package/dist/components/cms/version-compare-lazy.js.map +1 -1
- package/dist/components/cms/version-compare.js +1 -1
- package/dist/components/cms/version-compare.js.map +1 -1
- package/dist/components/cms/versions-pane.js +11 -4
- package/dist/components/cms/versions-pane.js.map +1 -1
- package/dist/components/cms/view-bar.js +3 -3
- package/dist/components/cms/view-bar.js.map +1 -1
- package/dist/components/collection-view/cms-collection-view-source.d.ts +1 -1
- package/dist/components/collection-view/cms-collection-view-source.js +5 -3
- package/dist/components/collection-view/cms-collection-view-source.js.map +1 -1
- package/dist/components/collection-view/collection-view-context.d.ts +1 -1
- package/dist/components/collection-view/collection-view-context.js +1 -1
- package/dist/components/collection-view/collection-view-context.js.map +1 -1
- package/dist/components/collection-view/collection-view-surface.d.ts +13 -0
- package/dist/components/collection-view/collection-view-surface.js +18 -0
- package/dist/components/collection-view/collection-view-surface.js.map +1 -0
- package/dist/components/components/component-detail.js +10 -10
- package/dist/components/components/component-detail.js.map +1 -1
- package/dist/components/components/component-preview.d.ts +2 -2
- package/dist/components/components/component-preview.js +5 -5
- package/dist/components/components/component-preview.js.map +1 -1
- package/dist/components/components/component-status.d.ts +1 -1
- package/dist/components/components/component-status.js +1 -1
- package/dist/components/components/component-status.js.map +1 -1
- package/dist/components/components/components-index.js +2 -2
- package/dist/components/components/components-index.js.map +1 -1
- package/dist/components/components/field-inspector.js +1 -1
- package/dist/components/components/field-inspector.js.map +1 -1
- package/dist/components/components/registry-browser.js +3 -3
- package/dist/components/components/registry-browser.js.map +1 -1
- package/dist/components/components/taxonomy.d.ts +1 -1
- package/dist/components/components/taxonomy.js.map +1 -1
- package/dist/components/components/transfer-dialog.js +4 -3
- package/dist/components/components/transfer-dialog.js.map +1 -1
- package/dist/components/components/transfer.d.ts +10 -10
- package/dist/components/components/transfer.js +13 -12
- package/dist/components/components/transfer.js.map +1 -1
- package/dist/components/current-user-menu.js +1 -1
- package/dist/components/current-user-menu.js.map +1 -1
- package/dist/components/delivery-health-banner.js +2 -2
- package/dist/components/delivery-health-banner.js.map +1 -1
- package/dist/components/deployment-setup-gate.js +3 -3
- package/dist/components/deployment-setup-gate.js.map +1 -1
- package/dist/components/dev-login-badge.js +2 -2
- package/dist/components/dev-login-badge.js.map +1 -1
- package/dist/components/guards.js +1 -1
- package/dist/components/guards.js.map +1 -1
- package/dist/components/inspector/document-panes.d.ts +54 -0
- package/dist/components/inspector/document-panes.js +41 -0
- package/dist/components/inspector/document-panes.js.map +1 -0
- package/dist/components/inspector/inspector-sidebar.js +1 -1
- package/dist/components/inspector/inspector-sidebar.js.map +1 -1
- package/dist/components/nav-issues-registry.d.ts +53 -0
- package/dist/components/nav-issues-registry.js +69 -0
- package/dist/components/nav-issues-registry.js.map +1 -0
- package/dist/components/nav-issues.js +4 -4
- package/dist/components/nav-issues.js.map +1 -1
- package/dist/components/operation-error.d.ts +1 -1
- package/dist/components/operation-error.js +4 -4
- package/dist/components/operation-error.js.map +1 -1
- package/dist/components/playground-badge.js +2 -2
- package/dist/components/playground-badge.js.map +1 -1
- package/dist/components/project-list.js +3 -3
- package/dist/components/project-list.js.map +1 -1
- package/dist/components/project-session.d.ts +2 -2
- package/dist/components/project-session.js +5 -5
- package/dist/components/project-session.js.map +1 -1
- package/dist/components/project-switcher.js +2 -2
- package/dist/components/project-switcher.js.map +1 -1
- package/dist/components/rail-store-status.js +1 -1
- package/dist/components/rail-store-status.js.map +1 -1
- package/dist/components/rail-view-source.d.ts +6 -5
- package/dist/components/rail-view-source.js +4 -3
- package/dist/components/rail-view-source.js.map +1 -1
- package/dist/components/records/record-lens.d.ts +51 -0
- package/dist/components/records/record-lens.js +156 -0
- package/dist/components/records/record-lens.js.map +1 -0
- package/dist/components/records/record-rail.d.ts +86 -0
- package/dist/components/records/record-rail.js +241 -0
- package/dist/components/records/record-rail.js.map +1 -0
- package/dist/components/redirects/redirects-schema.js +1 -1
- package/dist/components/redirects/redirects-schema.js.map +1 -1
- package/dist/components/references/references-panel.js +2 -2
- package/dist/components/references/references-panel.js.map +1 -1
- package/dist/components/section-nav.js +27 -11
- package/dist/components/section-nav.js.map +1 -1
- package/dist/components/section-state.js +2 -2
- package/dist/components/section-state.js.map +1 -1
- package/dist/components/section-surface.js +2 -2
- package/dist/components/section-surface.js.map +1 -1
- package/dist/components/session-expired-overlay.js +3 -3
- package/dist/components/session-expired-overlay.js.map +1 -1
- package/dist/components/settings-form.js +1 -1
- package/dist/components/settings-form.js.map +1 -1
- package/dist/components/sign-in-needed-badge.js +1 -1
- package/dist/components/sign-in-needed-badge.js.map +1 -1
- package/dist/components/sign-in-view.d.ts +2 -2
- package/dist/components/sign-in-view.js +5 -5
- package/dist/components/sign-in-view.js.map +1 -1
- package/dist/components/studio-context.js +3 -3
- package/dist/components/studio-context.js.map +1 -1
- package/dist/components/studio-project-screen.js +30 -3
- package/dist/components/studio-project-screen.js.map +1 -1
- package/dist/components/studio-shell.js +6 -5
- package/dist/components/studio-shell.js.map +1 -1
- package/dist/components/theme-context.d.ts +1 -1
- package/dist/components/theme-context.js +2 -2
- package/dist/components/theme-context.js.map +1 -1
- package/dist/components/use-hydration-phase.d.ts +1 -1
- package/dist/components/use-hydration-phase.js +1 -1
- package/dist/components/use-hydration-phase.js.map +1 -1
- package/dist/components/users/invite-user-bar.d.ts +27 -0
- package/dist/components/users/invite-user-bar.js +25 -9
- package/dist/components/users/invite-user-bar.js.map +1 -1
- package/dist/components/users/role-policy-drift-issues.d.ts +38 -0
- package/dist/components/users/role-policy-drift-issues.js +71 -0
- package/dist/components/users/role-policy-drift-issues.js.map +1 -0
- package/dist/components/users/users-collection-view-source.d.ts +1 -1
- package/dist/components/users/users-collection-view-source.js +4 -2
- package/dist/components/users/users-collection-view-source.js.map +1 -1
- package/dist/components/users/users-module.js +1 -1
- package/dist/components/users/users-module.js.map +1 -1
- package/dist/components/users/users-schema.d.ts +10 -1
- package/dist/components/users/users-schema.js +45 -25
- package/dist/components/users/users-schema.js.map +1 -1
- package/dist/components/users/users-store.js +3 -3
- package/dist/components/users/users-store.js.map +1 -1
- package/dist/components/workspace-projects.d.ts +1 -1
- package/dist/components/workspace-projects.js +1 -1
- package/dist/components/workspace-projects.js.map +1 -1
- package/dist/lib/ai/apply-content.js +56 -116
- package/dist/lib/ai/apply-content.js.map +1 -1
- package/dist/lib/ai/chat-context.d.ts +8 -0
- package/dist/lib/ai/chat-context.js +37 -6
- package/dist/lib/ai/chat-context.js.map +1 -1
- package/dist/lib/ai/chat-state.d.ts +6 -0
- package/dist/lib/ai/chat-state.js.map +1 -1
- package/dist/lib/ai/constraints.d.ts +20 -5
- package/dist/lib/ai/constraints.js +125 -33
- package/dist/lib/ai/constraints.js.map +1 -1
- package/dist/lib/ai/fake-provider.d.ts +16 -3
- package/dist/lib/ai/fake-provider.js +22 -6
- package/dist/lib/ai/fake-provider.js.map +1 -1
- package/dist/lib/ai/index.d.ts +3 -1
- package/dist/lib/ai/index.js +3 -1
- package/dist/lib/ai/index.js.map +1 -1
- package/dist/lib/ai/leash.d.ts +34 -0
- package/dist/lib/ai/leash.js +28 -0
- package/dist/lib/ai/leash.js.map +1 -0
- package/dist/lib/ai/node-handler.d.ts +1 -1
- package/dist/lib/ai/node-handler.js.map +1 -1
- package/dist/lib/ai/rich-text-input.d.ts +8 -8
- package/dist/lib/ai/rich-text-input.js +2 -1
- package/dist/lib/ai/rich-text-input.js.map +1 -1
- package/dist/lib/ai/rich-text-translate.d.ts +27 -4
- package/dist/lib/ai/rich-text-translate.js +28 -10
- package/dist/lib/ai/rich-text-translate.js.map +1 -1
- package/dist/lib/ai/shape.d.ts +13 -13
- package/dist/lib/ai/shape.js +69 -93
- package/dist/lib/ai/shape.js.map +1 -1
- package/dist/lib/ai/tools.d.ts +36 -41
- package/dist/lib/ai/tools.js +83 -87
- package/dist/lib/ai/tools.js.map +1 -1
- package/dist/lib/ai/translate-document.d.ts +32 -4
- package/dist/lib/ai/translate-document.js +145 -47
- package/dist/lib/ai/translate-document.js.map +1 -1
- package/dist/lib/ai/types.d.ts +34 -23
- package/dist/lib/ai/types.js.map +1 -1
- package/dist/lib/ai/update-fields.d.ts +15 -12
- package/dist/lib/ai/update-fields.js +112 -188
- package/dist/lib/ai/update-fields.js.map +1 -1
- package/dist/lib/ai/writer-form.d.ts +116 -0
- package/dist/lib/ai/writer-form.js +429 -0
- package/dist/lib/ai/writer-form.js.map +1 -0
- package/dist/lib/assets/upload.d.ts +31 -2
- package/dist/lib/assets/upload.js +61 -6
- package/dist/lib/assets/upload.js.map +1 -1
- package/dist/lib/clipboard/os-clipboard.d.ts +10 -2
- package/dist/lib/clipboard/os-clipboard.js +8 -4
- package/dist/lib/clipboard/os-clipboard.js.map +1 -1
- package/dist/lib/clipboard/paste-issues.js +1 -1
- package/dist/lib/clipboard/paste-issues.js.map +1 -1
- package/dist/lib/clipboard/paste-target.d.ts +18 -9
- package/dist/lib/clipboard/paste-target.js +10 -9
- package/dist/lib/clipboard/paste-target.js.map +1 -1
- package/dist/lib/cms/field-patch.d.ts +0 -10
- package/dist/lib/cms/field-patch.js +4 -30
- package/dist/lib/cms/field-patch.js.map +1 -1
- package/dist/lib/cms/published-documents.js +1 -1
- package/dist/lib/cms/published-documents.js.map +1 -1
- package/dist/lib/cms-views/view-model.d.ts +9 -9
- package/dist/lib/cms-views/view-model.js +2 -2
- package/dist/lib/cms-views/view-model.js.map +1 -1
- package/dist/lib/collection-view/collection-view-source.d.ts +14 -5
- package/dist/lib/collection-view/collection-view-source.js.map +1 -1
- package/dist/lib/data/collection-content.js +3 -2
- package/dist/lib/data/collection-content.js.map +1 -1
- package/dist/lib/data/content-session-refresh.d.ts +1 -1
- package/dist/lib/data/content-session-refresh.js.map +1 -1
- package/dist/lib/data/playground-unload-guard.d.ts +1 -1
- package/dist/lib/data/playground-unload-guard.js +1 -1
- package/dist/lib/data/playground-unload-guard.js.map +1 -1
- package/dist/lib/dnd/drop-rules.d.ts +25 -31
- package/dist/lib/dnd/drop-rules.js +53 -59
- package/dist/lib/dnd/drop-rules.js.map +1 -1
- package/dist/lib/engine-version.d.ts +1 -1
- package/dist/lib/engine-version.js +1 -1
- package/dist/lib/engine-version.js.map +1 -1
- package/dist/lib/i18n/i18n.js +1 -1
- package/dist/lib/i18n/i18n.js.map +1 -1
- package/dist/lib/i18n/messages.de.js +44 -3
- package/dist/lib/i18n/messages.de.js.map +1 -1
- package/dist/lib/i18n/messages.en.d.ts +38 -2
- package/dist/lib/i18n/messages.en.js +51 -3
- package/dist/lib/i18n/messages.en.js.map +1 -1
- package/dist/lib/operations/project-runtime-config.d.ts +34 -6
- package/dist/lib/operations/project-runtime-config.js +50 -10
- package/dist/lib/operations/project-runtime-config.js.map +1 -1
- package/dist/lib/operations/publish-with-revision.d.ts +33 -1
- package/dist/lib/operations/publish-with-revision.js +32 -0
- package/dist/lib/operations/publish-with-revision.js.map +1 -1
- package/dist/lib/operations/runtime-validator.d.ts +19 -68
- package/dist/lib/operations/runtime-validator.js +12 -138
- package/dist/lib/operations/runtime-validator.js.map +1 -1
- package/dist/lib/operations/studio-operations.d.ts +17 -2
- package/dist/lib/operations/studio-operations.js +18 -11
- package/dist/lib/operations/studio-operations.js.map +1 -1
- package/dist/lib/persistence/convex-adapter.d.ts +16 -3
- package/dist/lib/persistence/convex-adapter.js +83 -47
- package/dist/lib/persistence/convex-adapter.js.map +1 -1
- package/dist/lib/persistence/index.js +14 -1
- package/dist/lib/persistence/index.js.map +1 -1
- package/dist/lib/persona/labels.js +4 -2
- package/dist/lib/persona/labels.js.map +1 -1
- package/dist/lib/query/operations-query.d.ts +1 -1
- package/dist/lib/query/operations-query.js +1 -1
- package/dist/lib/query/operations-query.js.map +1 -1
- package/dist/lib/references/reference-model.js +1 -1
- package/dist/lib/references/reference-model.js.map +1 -1
- package/dist/lib/references/references-store.js +1 -1
- package/dist/lib/references/references-store.js.map +1 -1
- package/dist/lib/workspace/index.d.ts +14 -11
- package/dist/lib/workspace/index.js +20 -24
- package/dist/lib/workspace/index.js.map +1 -1
- package/dist/mount.d.ts +28 -0
- package/dist/mount.js +27 -0
- package/dist/mount.js.map +1 -0
- package/dist/router/root.js +10 -10
- package/dist/router/root.js.map +1 -1
- package/dist/ui/badge.d.ts +1 -1
- package/dist/ui/button.d.ts +2 -2
- package/package.json +15 -11
- package/dist/components/cms/cms-composition-validators.d.ts +0 -16
- package/dist/components/cms/cms-composition-validators.js +0 -133
- package/dist/components/cms/cms-composition-validators.js.map +0 -1
- package/dist/components/cms/publish-clean.d.ts +0 -28
- package/dist/components/cms/publish-clean.js +0 -38
- package/dist/components/cms/publish-clean.js.map +0 -1
- package/dist/components/redirects/redirects-collection-view-source.d.ts +0 -53
- package/dist/components/redirects/redirects-collection-view-source.js +0 -146
- package/dist/components/redirects/redirects-collection-view-source.js.map +0 -1
- package/dist/components/redirects/redirects-module.d.ts +0 -21
- package/dist/components/redirects/redirects-module.js +0 -40
- package/dist/components/redirects/redirects-module.js.map +0 -1
- package/dist/components/redirects/redirects-store.d.ts +0 -68
- package/dist/components/redirects/redirects-store.js +0 -132
- package/dist/components/redirects/redirects-store.js.map +0 -1
- package/dist/lib/assets/asset-placements.d.ts +0 -28
- package/dist/lib/assets/asset-placements.js +0 -83
- package/dist/lib/assets/asset-placements.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fake-provider.js","sourceRoot":"","sources":["../../../src/lib/ai/fake-provider.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * FakeProvider (EC-331): a deterministic, fixture-driven {@link AiProvider} that\n * implements the same interface as the Anthropic provider, so playground / demo /\n * tests run the WHOLE loop (config gate → shape → generate → validate → repair →\n * patch) without a key. Determinism is a project principle: the same fixtures always\n * yield the same result. Imports no AI SDK at runtime — the `LanguageModelV4` spec\n * below is implemented STRUCTURALLY from type-only imports (erased at compile;\n * pinned in `bundle.test.ts`).\n *\n * For the repair loop, pass `objects: [invalidDoc, validDoc]` — the provider returns\n * them in call order (the last is reused once the script is exhausted). Or pass\n * `respond` to compute the object from the request.\n *\n * EC-334 adds {@link createFakeChatModel}: a scripted fake `LanguageModel` served by\n * the ROUTE's native chat branch, so the keyless playground / CI drive the FULL\n * `streamText` → SSE wire → client-tool loop. It is a STATELESS prompt-inspecting\n * responder (state read from the prompt, the FakeProvider trick): a prompt without a\n * tool result emits a tool call; a prompt carrying one streams a text answer.\n */\n// Type-only (erased): the fake implements the SDK's v4 model spec structurally.\nimport type { LanguageModel } from 'ai'\nimport type { AiProvider, AiProviderCapabilities, GenerateStructuredRequest } from './types'\n\n// --- Fake chat model (EC-334) -------------------------------------------------------\n\n/** The SDK's v4 language-model spec, extracted structurally from the type-only union. */\nexport type FakeLanguageModelV4 = Extract<LanguageModel, { specificationVersion: 'v4' }>\n\n/** The call options a fake chat model receives (`LanguageModelV4CallOptions`). */\nexport type FakeChatModelCallOptions = Parameters<FakeLanguageModelV4['doGenerate']>[0]\n\n/** One provider-spec stream part the fake emits (`LanguageModelV4StreamPart`). */\nexport type FakeChatModelStreamPart =\n Awaited<ReturnType<FakeLanguageModelV4['doStream']>>['stream'] extends ReadableStream<infer PART>\n ? PART\n : never\n\ntype FakeFinishPart = Extract<FakeChatModelStreamPart, { type: 'finish' }>\ntype FakeGenerateResult = Awaited<ReturnType<FakeLanguageModelV4['doGenerate']>>\n\n/** Zero-usage report (the fake spends nothing). Shape = `LanguageModelV4Usage`. */\nconst FAKE_USAGE: FakeFinishPart['usage'] = {\n inputTokens: { total: 0, noCache: 0, cacheRead: 0, cacheWrite: 0 },\n outputTokens: { total: 0, text: 0, reasoning: 0 },\n}\n\n/** Default preamble streamed before the scripted tool call. */\nexport const FAKE_CHAT_PREAMBLE = 'Let me look that up. '\n/** Default final answer streamed once the prompt carries a tool result. */\nexport const FAKE_CHAT_ANSWER = 'Found it — the tool result is in, and this is the answer.'\n\nexport interface FakeChatModelOptions {\n /** Model id reported to the SDK (default `fake-chat-model`). */\n modelId?: string\n /** Text streamed before the tool call on the first (tool-result-free) turn. */\n preambleText?: string\n /** The tool the first turn requests (default `searchDocuments`). */\n toolName?: string\n /** The tool-call input (default `{ collection: 'post' }`). */\n toolInput?: Record<string, unknown>\n /** The answer streamed word-by-word once the prompt carries a tool result. */\n answerText?: string\n /**\n * Full override: script the exact provider-spec stream parts for a call\n * (zero-based call index). The default prompt-inspecting behavior is skipped.\n */\n script?: (options: FakeChatModelCallOptions, callIndex: number) => FakeChatModelStreamPart[]\n}\n\n/** A fake chat model that also records the calls it received, for assertions. */\nexport type FakeChatModel = FakeLanguageModelV4 & {\n /** Every `doStream` / `doGenerate` call options received, in order. */\n readonly calls: FakeChatModelCallOptions[]\n}\n\n/** Does any prompt message carry a tool RESULT part? (The fake's only \"state\".) */\nfunction promptHasToolResult(prompt: FakeChatModelCallOptions['prompt']): boolean {\n return prompt.some(\n (message) =>\n Array.isArray(message.content) &&\n message.content.some(\n (part) => (part as { type?: unknown }).type === 'tool-result',\n ),\n )\n}\n\n/** Index of the LAST user message in the prompt (`-1` when none). */\nfunction lastUserIndex(prompt: FakeChatModelCallOptions['prompt']): number {\n for (let i = prompt.length - 1; i >= 0; i -= 1) {\n if (prompt[i]?.role === 'user') return i\n }\n return -1\n}\n\n/** The last user message's text (the fake's \"instruction\" source). */\nfunction lastUserText(prompt: FakeChatModelCallOptions['prompt']): string {\n const index = lastUserIndex(prompt)\n const message = prompt[index]\n if (!message || !Array.isArray(message.content)) return ''\n return message.content\n .filter((part): part is { type: 'text'; text: string } => (part as { type?: unknown }).type === 'text')\n .map((part) => part.text)\n .join(' ')\n .trim()\n}\n\n/**\n * Tool names with a RESULT in the CURRENT user turn (prompt suffix after the\n * last user message) — the stateless stage detector for scripted flows.\n */\nfunction toolResultNamesInCurrentTurn(prompt: FakeChatModelCallOptions['prompt']): Set<string> {\n const names = new Set<string>()\n for (const message of prompt.slice(lastUserIndex(prompt) + 1)) {\n if (!Array.isArray(message.content)) continue\n for (const part of message.content) {\n const candidate = part as { type?: unknown; toolName?: unknown }\n if (candidate.type === 'tool-result' && typeof candidate.toolName === 'string') {\n names.add(candidate.toolName)\n }\n }\n }\n return names\n}\n\n/** Provider-spec parts for one text-preamble + tool-call turn (finish `tool-calls`). */\nfunction toolTurnParts(\n preamble: string,\n toolName: string,\n input: Record<string, unknown>,\n callId: string,\n): FakeChatModelStreamPart[] {\n const encoded = JSON.stringify(input)\n return [\n { type: 'stream-start', warnings: [] },\n { type: 'text-start', id: 'text-1' },\n { type: 'text-delta', id: 'text-1', delta: preamble },\n { type: 'text-end', id: 'text-1' },\n { type: 'tool-input-start', id: callId, toolName },\n { type: 'tool-input-delta', id: callId, delta: encoded },\n { type: 'tool-input-end', id: callId },\n { type: 'tool-call', toolCallId: callId, toolName, input: encoded },\n {\n type: 'finish',\n usage: FAKE_USAGE,\n finishReason: { unified: 'tool-calls', raw: 'fake-tool-calls' },\n },\n ]\n}\n\n/** Provider-spec parts for a word-by-word streamed text answer (finish `stop`). */\nfunction answerTurnParts(answer: string): FakeChatModelStreamPart[] {\n return [\n { type: 'stream-start', warnings: [] },\n { type: 'text-start', id: 'text-1' },\n ...wordDeltas(answer).map(\n (delta): FakeChatModelStreamPart => ({ type: 'text-delta', id: 'text-1', delta }),\n ),\n { type: 'text-end', id: 'text-1' },\n { type: 'finish', usage: FAKE_USAGE, finishReason: { unified: 'stop', raw: 'fake-stop' } },\n ]\n}\n\n/** Split text into word deltas (trailing spaces preserved) for visible streaming. */\nfunction wordDeltas(text: string): string[] {\n const words = text.split(' ')\n return words.map((word, index) => (index < words.length - 1 ? `${word} ` : word))\n}\n\n/**\n * Build a scripted, stateless fake `LanguageModel` (the `LanguageModelV4` spec,\n * implemented structurally — zero SDK runtime import). Default behavior:\n * - prompt WITHOUT a tool result → preamble text, then a `tool-call` for\n * {@link FakeChatModelOptions.toolName} (finish reason `tool-calls`);\n * - prompt WITH a tool result → the answer text streamed word-by-word (`stop`).\n * Chunk shapes follow the v4 spec: `finishReason` is `{ unified, raw }`, tool chunks\n * are `tool-input-start/delta/end` + `tool-call`.\n */\nexport function createFakeChatModel(options: FakeChatModelOptions = {}): FakeChatModel {\n const preamble = options.preambleText ?? FAKE_CHAT_PREAMBLE\n const toolName = options.toolName ?? 'searchDocuments'\n const toolInput = options.toolInput ?? { collection: 'post' }\n const answer = options.answerText ?? FAKE_CHAT_ANSWER\n const calls: FakeChatModelCallOptions[] = []\n let callIndex = 0\n\n function partsFor(callOptions: FakeChatModelCallOptions): FakeChatModelStreamPart[] {\n if (options.script) return options.script(callOptions, callIndex)\n if (!promptHasToolResult(callOptions.prompt)) {\n return toolTurnParts(preamble, toolName, toolInput, 'call-1')\n }\n return answerTurnParts(answer)\n }\n\n /** Fold the scripted stream parts into a non-streaming `doGenerate` result. */\n function materialize(parts: FakeChatModelStreamPart[]): FakeGenerateResult {\n const content: FakeGenerateResult['content'] = []\n const textById = new Map<string, string>()\n let finishReason: FakeFinishPart['finishReason'] = { unified: 'stop', raw: 'fake-stop' }\n for (const part of parts) {\n if (part.type === 'text-delta') {\n textById.set(part.id, (textById.get(part.id) ?? '') + part.delta)\n } else if (part.type === 'tool-call') {\n content.push(part)\n } else if (part.type === 'finish') {\n finishReason = part.finishReason\n }\n }\n for (const text of textById.values()) content.unshift({ type: 'text', text })\n return { content, finishReason, usage: FAKE_USAGE, warnings: [] }\n }\n\n return {\n specificationVersion: 'v4',\n provider: 'fake',\n modelId: options.modelId ?? 'fake-chat-model',\n supportedUrls: {},\n calls,\n doGenerate(callOptions) {\n calls.push(callOptions)\n const parts = partsFor(callOptions)\n callIndex += 1\n return Promise.resolve(materialize(parts))\n },\n doStream(callOptions) {\n calls.push(callOptions)\n const parts = partsFor(callOptions)\n callIndex += 1\n return Promise.resolve({\n stream: new ReadableStream<FakeChatModelStreamPart>({\n start(controller) {\n for (const part of parts) controller.enqueue(part)\n controller.close()\n },\n }),\n })\n },\n }\n}\n\n// --- Fake create-flow chat model (EC-334 slice 2) -------------------------------------\n\nexport interface FakeCreateFlowChatModelOptions {\n /** Model id reported to the SDK (default `fake-create-flow-model`). */\n modelId?: string\n /** The collection the first stage searches (a relation target; default `author`). */\n searchCollection?: string\n /**\n * EC-381: when set, the create flow inserts a `listAssets` stage after the\n * relation search and before `createDocument`, so a collection with an image\n * field gets it filled from a REAL library asset (the enum leash). Optional\n * search text passed to `listAssets` (omit to list all).\n */\n searchAssets?: boolean\n /** Optional query passed to the scripted `listAssets` stage (EC-381). */\n assetQuery?: string\n /** The collection the terminal stage creates in (default `post`). */\n createCollection?: string\n /** The final answer streamed word-by-word after the proposal lands. */\n answerText?: string\n /**\n * EC-378: the field the scripted UPDATE flow changes (default `title`). A user\n * turn matching {@link FakeCreateFlowChatModelOptions.updatePattern} routes to\n * the update flow instead of the create flow.\n */\n updateField?: string\n /** Routes a user turn to the update flow (default {@link FAKE_UPDATE_PATTERN}). */\n updatePattern?: RegExp\n /** The final answer of the scripted update flow. */\n updateAnswerText?: string\n}\n\n/** Default final answer of the scripted create flow. */\nexport const FAKE_CREATE_FLOW_ANSWER =\n 'Done — review the proposal below and apply it as a draft.'\n\n/** Default final answer of the scripted update flow (EC-378). */\nexport const FAKE_UPDATE_FLOW_ANSWER =\n 'Done — review the proposed change below and apply it as a draft.'\n\n/** Default edit-request detector of the scripted assistant (EC-378). */\nexport const FAKE_UPDATE_PATTERN = /\\b(change|update|edit|remove|replace|rewrite|fix|set)\\b/i\n\n/**\n * The scripted update flow's new value for the target field: the text after the\n * FIRST colon when present (`Set the title to: New Title` → `New Title`), else\n * the whole user text — deterministic either way. First (not last) colon so a\n * markdown body value may itself contain colons (EC-379).\n */\nexport function fakeUpdateValueFrom(userText: string): string {\n const colon = userText.indexOf(':')\n const value = colon >= 0 ? userText.slice(colon + 1) : userText\n return value.trim() || 'Updated by the assistant'\n}\n\n/**\n * The scripted update flow's TARGET FIELD (EC-379): `set/change/update the\n * <field> to: …` names it (so the playground can drive a markdown-authored\n * rich-text update deterministically, e.g. `Set the body to: ## Neu`); anything\n * else falls back to the configured default field.\n */\nexport function fakeUpdateFieldFrom(userText: string, fallback: string): string {\n const match = /\\b(?:set|change|update)\\s+the\\s+([A-Za-z]\\w*)\\s+to\\s*:/i.exec(userText)\n return match?.[1] ?? fallback\n}\n\n/**\n * A scripted, STATELESS fake chat model that drives the FULL create flow — and,\n * for a user turn matching the update pattern, the EC-378 UPDATE flow — over the\n * native loop (EC-334): keyless playground / CI exercise the whole client-tool\n * round-trip deterministically. Stage is read from the CURRENT user turn's tool\n * results (prompt suffix after the last user message), so every follow-up turn\n * starts a fresh flow — multi-turn works without model state.\n *\n * Create flow (default):\n * 1. no tool result yet → `searchDocuments({ collection: searchCollection })`\n * 2. search result, no create → `createDocument({ collection, instruction: <last user text> })`\n * 3. create result present → the answer text, word by word.\n *\n * With `searchAssets` (EC-381), a `listAssets` stage is inserted between 1 and 2:\n * 1. no tool result yet → `searchDocuments({ collection: searchCollection })`\n * 2. search done, no listAssets → `listAssets({ query?: assetQuery })`\n * 3. listAssets done, no create → `createDocument({ collection, instruction })`\n * 4. create result present → the answer text, word by word.\n *\n * Update flow (user text matches `updatePattern`, e.g. \"Change the title to: X\"):\n * 1. no tool result yet → `getDocument({})` — target omitted on purpose:\n * the executor resolves the document OPEN in the\n * editor (the EC-378 current-document seam)\n * 2. document read, no update → `updateFields({ changes: [{ field:\n * fakeUpdateFieldFrom(<text>, updateField),\n * value: fakeUpdateValueFrom(<last user text>) }] })`\n * — \"Set the body to: ## Neu\" drives a markdown\n * rich-text update deterministically (EC-379)\n * 3. update result present → the update answer, word by word.\n */\nexport function createFakeCreateFlowChatModel(\n options: FakeCreateFlowChatModelOptions = {},\n): FakeChatModel {\n const searchCollection = options.searchCollection ?? 'author'\n const createCollection = options.createCollection ?? 'post'\n const searchAssets = options.searchAssets ?? false\n const answer = options.answerText ?? FAKE_CREATE_FLOW_ANSWER\n const updateField = options.updateField ?? 'title'\n const updatePattern = options.updatePattern ?? FAKE_UPDATE_PATTERN\n const updateAnswer = options.updateAnswerText ?? FAKE_UPDATE_FLOW_ANSWER\n return createFakeChatModel({\n modelId: options.modelId ?? 'fake-create-flow-model',\n script: (callOptions) => {\n const done = toolResultNamesInCurrentTurn(callOptions.prompt)\n const userText = lastUserText(callOptions.prompt)\n if (updatePattern.test(userText)) {\n if (done.has('updateFields')) return answerTurnParts(updateAnswer)\n if (done.has('getDocument')) {\n return toolTurnParts(\n 'Proposing the change. ',\n 'updateFields',\n {\n changes: [\n {\n field: fakeUpdateFieldFrom(userText, updateField),\n value: fakeUpdateValueFrom(userText),\n },\n ],\n },\n 'call-update-1',\n )\n }\n return toolTurnParts('Reading the document. ', 'getDocument', {}, 'call-get-1')\n }\n if (done.has('createDocument')) return answerTurnParts(answer)\n if (done.has('searchDocuments')) {\n // EC-381 — search the media library before creating (a topically fitting,\n // REAL asset fills the image field via the enum leash).\n if (searchAssets && !done.has('listAssets')) {\n return toolTurnParts(\n 'Looking for a fitting image. ',\n 'listAssets',\n { ...(options.assetQuery ? { query: options.assetQuery } : {}) },\n 'call-assets-1',\n )\n }\n const instruction = userText || 'Write a short document.'\n return toolTurnParts(\n 'Drafting a proposal. ',\n 'createDocument',\n { collection: createCollection, instruction },\n 'call-create-1',\n )\n }\n return toolTurnParts(\n FAKE_CHAT_PREAMBLE,\n 'searchDocuments',\n { collection: searchCollection },\n 'call-search-1',\n )\n },\n })\n}\n\n// --- Fake provider ------------------------------------------------------------------\n\nexport interface FakeProviderOptions {\n /** Provider id (default `fake`). */\n id?: string\n /** Model id recorded in provenance (default `fake-model`). */\n model?: string\n /** Reported capabilities (default: both true). Set to test the capability gate. */\n capabilities?: AiProviderCapabilities\n /** Scripted objects returned in call order; the last entry is reused when exhausted. */\n objects?: unknown[]\n /** Compute the object from the request + zero-based call index (overrides `objects`). */\n respond?: (request: GenerateStructuredRequest, callIndex: number) => unknown\n /** The scripted chat model `languageModel()` serves (default {@link createFakeChatModel}). */\n chatModel?: FakeChatModel\n}\n\n/** A FakeProvider that also records the requests it received, for assertions. */\nexport interface FakeProvider extends AiProvider {\n /** Every `generateStructured` request received, in order. */\n readonly calls: GenerateStructuredRequest[]\n /** The scripted fake chat model behind `languageModel()` (records its calls). */\n readonly chatModel: FakeChatModel\n}\n\nexport function createFakeProvider(options: FakeProviderOptions = {}): FakeProvider {\n const calls: GenerateStructuredRequest[] = []\n const objects = options.objects ?? []\n const chatModel = options.chatModel ?? createFakeChatModel()\n let index = 0\n\n return {\n id: options.id ?? 'fake',\n model: options.model ?? 'fake-model',\n calls,\n chatModel,\n capabilities: (): AiProviderCapabilities =>\n options.capabilities ?? { toolCalling: true, structuredOutput: true },\n\n languageModel: () => Promise.resolve(chatModel),\n\n generateStructured(request) {\n calls.push(request)\n const callIndex = index\n index += 1\n const object = options.respond\n ? options.respond(request, callIndex)\n : objects.length > 0\n ? objects[Math.min(callIndex, objects.length - 1)]\n : {}\n return Promise.resolve({ object, usage: { inputTokens: 0, outputTokens: 0 } })\n },\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"fake-provider.js","sourceRoot":"","sources":["../../../src/lib/ai/fake-provider.ts"],"names":[],"mappings":"AAwCA,mFAAmF;AACnF,MAAM,UAAU,GAA4B;IAC1C,WAAW,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE;IAClE,YAAY,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE;CAClD,CAAA;AAED,+DAA+D;AAC/D,MAAM,CAAC,MAAM,kBAAkB,GAAG,uBAAuB,CAAA;AACzD,2EAA2E;AAC3E,MAAM,CAAC,MAAM,gBAAgB,GAAG,2DAA2D,CAAA;AA0B3F,mFAAmF;AACnF,SAAS,mBAAmB,CAAC,MAA0C;IACrE,OAAO,MAAM,CAAC,IAAI,CAChB,CAAC,OAAO,EAAE,EAAE,CACV,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QAC9B,OAAO,CAAC,OAAO,CAAC,IAAI,CAClB,CAAC,IAAI,EAAE,EAAE,CAAE,IAA2B,CAAC,IAAI,KAAK,aAAa,CAC9D,CACJ,CAAA;AACH,CAAC;AAED,qEAAqE;AACrE,SAAS,aAAa,CAAC,MAA0C;IAC/D,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/C,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,MAAM;YAAE,OAAO,CAAC,CAAA;IAC1C,CAAC;IACD,OAAO,CAAC,CAAC,CAAA;AACX,CAAC;AAED,sEAAsE;AACtE,SAAS,YAAY,CAAC,MAA0C;IAC9D,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;IACnC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAC7B,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAA;IAC1D,OAAO,OAAO,CAAC,OAAO;SACnB,MAAM,CAAC,CAAC,IAAI,EAA0C,EAAE,CAAE,IAA2B,CAAC,IAAI,KAAK,MAAM,CAAC;SACtG,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;SACxB,IAAI,CAAC,GAAG,CAAC;SACT,IAAI,EAAE,CAAA;AACX,CAAC;AAED;;;GAGG;AACH,SAAS,4BAA4B,CAAC,MAA0C;IAC9E,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAA;IAC/B,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAC9D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,SAAQ;QAC7C,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACnC,MAAM,SAAS,GAAG,IAA8C,CAAA;YAChE,IAAI,SAAS,CAAC,IAAI,KAAK,aAAa,IAAI,OAAO,SAAS,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAC/E,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,wFAAwF;AACxF,SAAS,aAAa,CACpB,QAAgB,EAChB,QAAgB,EAChB,KAA8B,EAC9B,MAAc;IAEd,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IACrC,OAAO;QACL,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,EAAE,EAAE;QACtC,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,QAAQ,EAAE;QACpC,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;QACrD,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,QAAQ,EAAE;QAClC,EAAE,IAAI,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;QAClD,EAAE,IAAI,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE;QACxD,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,MAAM,EAAE;QACtC,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE;QACnE;YACE,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,UAAU;YACjB,YAAY,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,iBAAiB,EAAE;SAChE;KACF,CAAA;AACH,CAAC;AAED,mFAAmF;AACnF,SAAS,eAAe,CAAC,MAAc;IACrC,OAAO;QACL,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,EAAE,EAAE;QACtC,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,QAAQ,EAAE;QACpC,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,CACvB,CAAC,KAAK,EAA2B,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAClF;QACD,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,QAAQ,EAAE;QAClC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE;KAC3F,CAAA;AACH,CAAC;AAED,qFAAqF;AACrF,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC7B,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;AACnF,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAgC,EAAE;IACpE,MAAM,QAAQ,GAAG,OAAO,CAAC,YAAY,IAAI,kBAAkB,CAAA;IAC3D,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,iBAAiB,CAAA;IACtD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,CAAA;IAC7D,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,IAAI,gBAAgB,CAAA;IACrD,MAAM,KAAK,GAA+B,EAAE,CAAA;IAC5C,IAAI,SAAS,GAAG,CAAC,CAAA;IAEjB,SAAS,QAAQ,CAAC,WAAqC;QACrD,IAAI,OAAO,CAAC,MAAM;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;QACjE,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7C,OAAO,aAAa,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAA;QAC/D,CAAC;QACD,OAAO,eAAe,CAAC,MAAM,CAAC,CAAA;IAChC,CAAC;IAED,+EAA+E;IAC/E,SAAS,WAAW,CAAC,KAAgC;QACnD,MAAM,OAAO,GAAkC,EAAE,CAAA;QACjD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAA;QAC1C,IAAI,YAAY,GAAmC,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,CAAA;QACxF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC/B,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;YACnE,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBACrC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACpB,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAClC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAA;YAClC,CAAC;QACH,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,MAAM,EAAE;YAAE,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;QAC7E,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IACnE,CAAC;IAED,OAAO;QACL,oBAAoB,EAAE,IAAI;QAC1B,QAAQ,EAAE,MAAM;QAChB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,iBAAiB;QAC7C,aAAa,EAAE,EAAE;QACjB,KAAK;QACL,UAAU,CAAC,WAAW;YACpB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;YACvB,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAA;YACnC,SAAS,IAAI,CAAC,CAAA;YACd,OAAO,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAA;QAC5C,CAAC;QACD,QAAQ,CAAC,WAAW;YAClB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;YACvB,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAA;YACnC,SAAS,IAAI,CAAC,CAAA;YACd,OAAO,OAAO,CAAC,OAAO,CAAC;gBACrB,MAAM,EAAE,IAAI,cAAc,CAA0B;oBAClD,KAAK,CAAC,UAAU;wBACd,KAAK,MAAM,IAAI,IAAI,KAAK;4BAAE,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;wBAClD,UAAU,CAAC,KAAK,EAAE,CAAA;oBACpB,CAAC;iBACF,CAAC;aACH,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC;AAkCD,wDAAwD;AACxD,MAAM,CAAC,MAAM,uBAAuB,GAClC,2DAA2D,CAAA;AAE7D,iEAAiE;AACjE,MAAM,CAAC,MAAM,uBAAuB,GAClC,kEAAkE,CAAA;AAEpE,wEAAwE;AACxE,MAAM,CAAC,MAAM,mBAAmB,GAAG,0DAA0D,CAAA;AAE7F;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACnC,MAAM,KAAK,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAA;IAC/D,OAAO,KAAK,CAAC,IAAI,EAAE,IAAI,0BAA0B,CAAA;AACnD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,QAAgB;IACpE,OAAO,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAA;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAAgB,EAChB,QAAgB;IAEhB,MAAM,KAAK,GACT,qGAAqG,CAAC,IAAI,CACxG,QAAQ,CACT,CAAA;IACH,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAA;IACtC,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,CAAC,CAAE;QAChB,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACnG,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,6BAA6B,CAC3C,UAA0C,EAAE;IAE5C,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,QAAQ,CAAA;IAC7D,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,MAAM,CAAA;IAC3D,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,KAAK,CAAA;IAClD,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,IAAI,uBAAuB,CAAA;IAC5D,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAA;IAClD,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,mBAAmB,CAAA;IAClE,MAAM,YAAY,GAAG,OAAO,CAAC,gBAAgB,IAAI,uBAAuB,CAAA;IACxE,OAAO,mBAAmB,CAAC;QACzB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,wBAAwB;QACpD,MAAM,EAAE,CAAC,WAAW,EAAE,EAAE;YACtB,MAAM,IAAI,GAAG,4BAA4B,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;YAC7D,MAAM,QAAQ,GAAG,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;YACjD,IAAI,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACjC,IAAI,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC;oBAAE,OAAO,eAAe,CAAC,YAAY,CAAC,CAAA;gBAClE,IAAI,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;oBAC5B,OAAO,aAAa,CAClB,wBAAwB,EACxB,cAAc,EACd;wBACE,OAAO,EAAE;4BACP;gCACE,GAAG,oBAAoB,CAAC,QAAQ,EAAE,WAAW,CAAC;gCAC9C,KAAK,EAAE,mBAAmB,CAAC,QAAQ,CAAC;6BACrC;yBACF;qBACF,EACD,eAAe,CAChB,CAAA;gBACH,CAAC;gBACD,OAAO,aAAa,CAAC,wBAAwB,EAAE,aAAa,EAAE,EAAE,EAAE,YAAY,CAAC,CAAA;YACjF,CAAC;YACD,IAAI,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC;gBAAE,OAAO,eAAe,CAAC,MAAM,CAAC,CAAA;YAC9D,IAAI,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBAChC,0EAA0E;gBAC1E,wDAAwD;gBACxD,IAAI,YAAY,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;oBAC5C,OAAO,aAAa,CAClB,+BAA+B,EAC/B,YAAY,EACZ,EAAE,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAChE,eAAe,CAChB,CAAA;gBACH,CAAC;gBACD,MAAM,WAAW,GAAG,QAAQ,IAAI,yBAAyB,CAAA;gBACzD,OAAO,aAAa,CAClB,uBAAuB,EACvB,gBAAgB,EAChB,EAAE,UAAU,EAAE,gBAAgB,EAAE,WAAW,EAAE,EAC7C,eAAe,CAChB,CAAA;YACH,CAAC;YACD,OAAO,aAAa,CAClB,kBAAkB,EAClB,iBAAiB,EACjB,EAAE,UAAU,EAAE,gBAAgB,EAAE,EAChC,eAAe,CAChB,CAAA;QACH,CAAC;KACF,CAAC,CAAA;AACJ,CAAC;AA2BD,MAAM,UAAU,kBAAkB,CAAC,UAA+B,EAAE;IAClE,MAAM,KAAK,GAAgC,EAAE,CAAA;IAC7C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAA;IACrC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,mBAAmB,EAAE,CAAA;IAC5D,IAAI,KAAK,GAAG,CAAC,CAAA;IAEb,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,MAAM;QACxB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,YAAY;QACpC,KAAK;QACL,SAAS;QACT,YAAY,EAAE,GAA2B,EAAE,CACzC,OAAO,CAAC,YAAY,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE;QAEvE,aAAa,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;QAE/C,kBAAkB,CAAC,OAAO;YACxB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACnB,MAAM,SAAS,GAAG,KAAK,CAAA;YACvB,KAAK,IAAI,CAAC,CAAA;YACV,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO;gBAC5B,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC;gBACrC,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;oBAClB,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;oBAClD,CAAC,CAAC,EAAE,CAAA;YACR,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;QAChF,CAAC;KACF,CAAA;AACH,CAAC","sourcesContent":["/**\n * FakeProvider (EC-331): a deterministic, fixture-driven {@link AiProvider} that\n * implements the same interface as the Anthropic provider, so playground / demo /\n * tests run the WHOLE loop (config gate → shape → generate → validate → repair →\n * patch) without a key. Determinism is a project principle: the same fixtures always\n * yield the same result. Imports no AI SDK at runtime — the `LanguageModelV4` spec\n * below is implemented STRUCTURALLY from type-only imports (erased at compile;\n * pinned in `bundle.test.ts`).\n *\n * For the repair loop, pass `objects: [invalidDoc, validDoc]` — the provider returns\n * them in call order (the last is reused once the script is exhausted). Or pass\n * `respond` to compute the object from the request.\n *\n * EC-334 adds {@link createFakeChatModel}: a scripted fake `LanguageModel` served by\n * the ROUTE's native chat branch, so the keyless playground / CI drive the FULL\n * `streamText` → SSE wire → client-tool loop. It is a STATELESS prompt-inspecting\n * responder (state read from the prompt, the FakeProvider trick): a prompt without a\n * tool result emits a tool call; a prompt carrying one streams a text answer.\n */\n// Type-only (erased): the fake implements the SDK's v4 model spec structurally.\nimport type { LanguageModel } from 'ai'\nimport type { AiProvider, AiProviderCapabilities, GenerateStructuredRequest } from './types'\n\n// --- Fake chat model (EC-334) -------------------------------------------------------\n\n/** The SDK's v4 language-model spec, extracted structurally from the type-only union. */\nexport type FakeLanguageModelV4 = Extract<LanguageModel, { specificationVersion: 'v4' }>\n\n/** The call options a fake chat model receives (`LanguageModelV4CallOptions`). */\nexport type FakeChatModelCallOptions = Parameters<FakeLanguageModelV4['doGenerate']>[0]\n\n/** One provider-spec stream part the fake emits (`LanguageModelV4StreamPart`). */\nexport type FakeChatModelStreamPart =\n Awaited<ReturnType<FakeLanguageModelV4['doStream']>>['stream'] extends ReadableStream<infer PART>\n ? PART\n : never\n\ntype FakeFinishPart = Extract<FakeChatModelStreamPart, { type: 'finish' }>\ntype FakeGenerateResult = Awaited<ReturnType<FakeLanguageModelV4['doGenerate']>>\n\n/** Zero-usage report (the fake spends nothing). Shape = `LanguageModelV4Usage`. */\nconst FAKE_USAGE: FakeFinishPart['usage'] = {\n inputTokens: { total: 0, noCache: 0, cacheRead: 0, cacheWrite: 0 },\n outputTokens: { total: 0, text: 0, reasoning: 0 },\n}\n\n/** Default preamble streamed before the scripted tool call. */\nexport const FAKE_CHAT_PREAMBLE = 'Let me look that up. '\n/** Default final answer streamed once the prompt carries a tool result. */\nexport const FAKE_CHAT_ANSWER = 'Found it — the tool result is in, and this is the answer.'\n\nexport interface FakeChatModelOptions {\n /** Model id reported to the SDK (default `fake-chat-model`). */\n modelId?: string\n /** Text streamed before the tool call on the first (tool-result-free) turn. */\n preambleText?: string\n /** The tool the first turn requests (default `searchDocuments`). */\n toolName?: string\n /** The tool-call input (default `{ collection: 'post' }`). */\n toolInput?: Record<string, unknown>\n /** The answer streamed word-by-word once the prompt carries a tool result. */\n answerText?: string\n /**\n * Full override: script the exact provider-spec stream parts for a call\n * (zero-based call index). The default prompt-inspecting behavior is skipped.\n */\n script?: (options: FakeChatModelCallOptions, callIndex: number) => FakeChatModelStreamPart[]\n}\n\n/** A fake chat model that also records the calls it received, for assertions. */\nexport type FakeChatModel = FakeLanguageModelV4 & {\n /** Every `doStream` / `doGenerate` call options received, in order. */\n readonly calls: FakeChatModelCallOptions[]\n}\n\n/** Does any prompt message carry a tool RESULT part? (The fake's only \"state\".) */\nfunction promptHasToolResult(prompt: FakeChatModelCallOptions['prompt']): boolean {\n return prompt.some(\n (message) =>\n Array.isArray(message.content) &&\n message.content.some(\n (part) => (part as { type?: unknown }).type === 'tool-result',\n ),\n )\n}\n\n/** Index of the LAST user message in the prompt (`-1` when none). */\nfunction lastUserIndex(prompt: FakeChatModelCallOptions['prompt']): number {\n for (let i = prompt.length - 1; i >= 0; i -= 1) {\n if (prompt[i]?.role === 'user') return i\n }\n return -1\n}\n\n/** The last user message's text (the fake's \"instruction\" source). */\nfunction lastUserText(prompt: FakeChatModelCallOptions['prompt']): string {\n const index = lastUserIndex(prompt)\n const message = prompt[index]\n if (!message || !Array.isArray(message.content)) return ''\n return message.content\n .filter((part): part is { type: 'text'; text: string } => (part as { type?: unknown }).type === 'text')\n .map((part) => part.text)\n .join(' ')\n .trim()\n}\n\n/**\n * Tool names with a RESULT in the CURRENT user turn (prompt suffix after the\n * last user message) — the stateless stage detector for scripted flows.\n */\nfunction toolResultNamesInCurrentTurn(prompt: FakeChatModelCallOptions['prompt']): Set<string> {\n const names = new Set<string>()\n for (const message of prompt.slice(lastUserIndex(prompt) + 1)) {\n if (!Array.isArray(message.content)) continue\n for (const part of message.content) {\n const candidate = part as { type?: unknown; toolName?: unknown }\n if (candidate.type === 'tool-result' && typeof candidate.toolName === 'string') {\n names.add(candidate.toolName)\n }\n }\n }\n return names\n}\n\n/** Provider-spec parts for one text-preamble + tool-call turn (finish `tool-calls`). */\nfunction toolTurnParts(\n preamble: string,\n toolName: string,\n input: Record<string, unknown>,\n callId: string,\n): FakeChatModelStreamPart[] {\n const encoded = JSON.stringify(input)\n return [\n { type: 'stream-start', warnings: [] },\n { type: 'text-start', id: 'text-1' },\n { type: 'text-delta', id: 'text-1', delta: preamble },\n { type: 'text-end', id: 'text-1' },\n { type: 'tool-input-start', id: callId, toolName },\n { type: 'tool-input-delta', id: callId, delta: encoded },\n { type: 'tool-input-end', id: callId },\n { type: 'tool-call', toolCallId: callId, toolName, input: encoded },\n {\n type: 'finish',\n usage: FAKE_USAGE,\n finishReason: { unified: 'tool-calls', raw: 'fake-tool-calls' },\n },\n ]\n}\n\n/** Provider-spec parts for a word-by-word streamed text answer (finish `stop`). */\nfunction answerTurnParts(answer: string): FakeChatModelStreamPart[] {\n return [\n { type: 'stream-start', warnings: [] },\n { type: 'text-start', id: 'text-1' },\n ...wordDeltas(answer).map(\n (delta): FakeChatModelStreamPart => ({ type: 'text-delta', id: 'text-1', delta }),\n ),\n { type: 'text-end', id: 'text-1' },\n { type: 'finish', usage: FAKE_USAGE, finishReason: { unified: 'stop', raw: 'fake-stop' } },\n ]\n}\n\n/** Split text into word deltas (trailing spaces preserved) for visible streaming. */\nfunction wordDeltas(text: string): string[] {\n const words = text.split(' ')\n return words.map((word, index) => (index < words.length - 1 ? `${word} ` : word))\n}\n\n/**\n * Build a scripted, stateless fake `LanguageModel` (the `LanguageModelV4` spec,\n * implemented structurally — zero SDK runtime import). Default behavior:\n * - prompt WITHOUT a tool result → preamble text, then a `tool-call` for\n * {@link FakeChatModelOptions.toolName} (finish reason `tool-calls`);\n * - prompt WITH a tool result → the answer text streamed word-by-word (`stop`).\n * Chunk shapes follow the v4 spec: `finishReason` is `{ unified, raw }`, tool chunks\n * are `tool-input-start/delta/end` + `tool-call`.\n */\nexport function createFakeChatModel(options: FakeChatModelOptions = {}): FakeChatModel {\n const preamble = options.preambleText ?? FAKE_CHAT_PREAMBLE\n const toolName = options.toolName ?? 'searchDocuments'\n const toolInput = options.toolInput ?? { collection: 'post' }\n const answer = options.answerText ?? FAKE_CHAT_ANSWER\n const calls: FakeChatModelCallOptions[] = []\n let callIndex = 0\n\n function partsFor(callOptions: FakeChatModelCallOptions): FakeChatModelStreamPart[] {\n if (options.script) return options.script(callOptions, callIndex)\n if (!promptHasToolResult(callOptions.prompt)) {\n return toolTurnParts(preamble, toolName, toolInput, 'call-1')\n }\n return answerTurnParts(answer)\n }\n\n /** Fold the scripted stream parts into a non-streaming `doGenerate` result. */\n function materialize(parts: FakeChatModelStreamPart[]): FakeGenerateResult {\n const content: FakeGenerateResult['content'] = []\n const textById = new Map<string, string>()\n let finishReason: FakeFinishPart['finishReason'] = { unified: 'stop', raw: 'fake-stop' }\n for (const part of parts) {\n if (part.type === 'text-delta') {\n textById.set(part.id, (textById.get(part.id) ?? '') + part.delta)\n } else if (part.type === 'tool-call') {\n content.push(part)\n } else if (part.type === 'finish') {\n finishReason = part.finishReason\n }\n }\n for (const text of textById.values()) content.unshift({ type: 'text', text })\n return { content, finishReason, usage: FAKE_USAGE, warnings: [] }\n }\n\n return {\n specificationVersion: 'v4',\n provider: 'fake',\n modelId: options.modelId ?? 'fake-chat-model',\n supportedUrls: {},\n calls,\n doGenerate(callOptions) {\n calls.push(callOptions)\n const parts = partsFor(callOptions)\n callIndex += 1\n return Promise.resolve(materialize(parts))\n },\n doStream(callOptions) {\n calls.push(callOptions)\n const parts = partsFor(callOptions)\n callIndex += 1\n return Promise.resolve({\n stream: new ReadableStream<FakeChatModelStreamPart>({\n start(controller) {\n for (const part of parts) controller.enqueue(part)\n controller.close()\n },\n }),\n })\n },\n }\n}\n\n// --- Fake create-flow chat model (EC-334 slice 2) -------------------------------------\n\nexport interface FakeCreateFlowChatModelOptions {\n /** Model id reported to the SDK (default `fake-create-flow-model`). */\n modelId?: string\n /** The collection the first stage searches (a relation target; default `author`). */\n searchCollection?: string\n /**\n * EC-381: when set, the create flow inserts a `listAssets` stage after the\n * relation search and before `createDocument`, so a collection with an image\n * field gets it filled from a REAL library asset (the enum leash). Optional\n * search text passed to `listAssets` (omit to list all).\n */\n searchAssets?: boolean\n /** Optional query passed to the scripted `listAssets` stage (EC-381). */\n assetQuery?: string\n /** The collection the terminal stage creates in (default `post`). */\n createCollection?: string\n /** The final answer streamed word-by-word after the proposal lands. */\n answerText?: string\n /**\n * EC-378: the field the scripted UPDATE flow changes (default `title`). A user\n * turn matching {@link FakeCreateFlowChatModelOptions.updatePattern} routes to\n * the update flow instead of the create flow.\n */\n updateField?: string\n /** Routes a user turn to the update flow (default {@link FAKE_UPDATE_PATTERN}). */\n updatePattern?: RegExp\n /** The final answer of the scripted update flow. */\n updateAnswerText?: string\n}\n\n/** Default final answer of the scripted create flow. */\nexport const FAKE_CREATE_FLOW_ANSWER =\n 'Done — review the proposal below and apply it as a draft.'\n\n/** Default final answer of the scripted update flow (EC-378). */\nexport const FAKE_UPDATE_FLOW_ANSWER =\n 'Done — review the proposed change below and apply it as a draft.'\n\n/** Default edit-request detector of the scripted assistant (EC-378). */\nexport const FAKE_UPDATE_PATTERN = /\\b(change|update|edit|remove|replace|rewrite|fix|set)\\b/i\n\n/**\n * The scripted update flow's new value for the target field: the text after the\n * FIRST colon when present (`Set the title to: New Title` → `New Title`), else\n * the whole user text — deterministic either way. First (not last) colon so a\n * markdown body value may itself contain colons (EC-379).\n */\nexport function fakeUpdateValueFrom(userText: string): string {\n const colon = userText.indexOf(':')\n const value = colon >= 0 ? userText.slice(colon + 1) : userText\n return value.trim() || 'Updated by the assistant'\n}\n\n/**\n * The scripted update flow's TARGET FIELD (EC-379): `set/change/update the\n * <field> to: …` names it (so the playground can drive a markdown-authored\n * rich-text update deterministically, e.g. `Set the body to: ## Neu`); anything\n * else falls back to the configured default field.\n */\nexport function fakeUpdateFieldFrom(userText: string, fallback: string): string {\n return fakeUpdateTargetFrom(userText, fallback).field\n}\n\n/**\n * The scripted update flow's full TARGET (EC-593): a field, or one component prop\n * inside it — `set the <field> component <id> <prop> to: …` names a component by its\n * node id at any depth (`Set the body component p-home-quote-note value to: Hi`), so the\n * keyless playground can drive a component-prop edit through the one converter.\n */\nexport function fakeUpdateTargetFrom(\n userText: string,\n fallback: string,\n): { field: string; blockId?: string; prop?: string } {\n const match =\n /\\b(?:set|change|update)\\s+the\\s+([A-Za-z]\\w*)(?:\\s+component\\s+([\\w-]+)\\s+([A-Za-z]\\w*))?\\s+to\\s*:/i.exec(\n userText,\n )\n if (!match) return { field: fallback }\n return {\n field: match[1]!,\n ...(match[2] !== undefined && match[3] !== undefined ? { blockId: match[2], prop: match[3] } : {}),\n }\n}\n\n/**\n * A scripted, STATELESS fake chat model that drives the FULL create flow — and,\n * for a user turn matching the update pattern, the EC-378 UPDATE flow — over the\n * native loop (EC-334): keyless playground / CI exercise the whole client-tool\n * round-trip deterministically. Stage is read from the CURRENT user turn's tool\n * results (prompt suffix after the last user message), so every follow-up turn\n * starts a fresh flow — multi-turn works without model state.\n *\n * Create flow (default):\n * 1. no tool result yet → `searchDocuments({ collection: searchCollection })`\n * 2. search result, no create → `createDocument({ collection, instruction: <last user text> })`\n * 3. create result present → the answer text, word by word.\n *\n * With `searchAssets` (EC-381), a `listAssets` stage is inserted between 1 and 2:\n * 1. no tool result yet → `searchDocuments({ collection: searchCollection })`\n * 2. search done, no listAssets → `listAssets({ query?: assetQuery })`\n * 3. listAssets done, no create → `createDocument({ collection, instruction })`\n * 4. create result present → the answer text, word by word.\n *\n * Update flow (user text matches `updatePattern`, e.g. \"Change the title to: X\"):\n * 1. no tool result yet → `getDocument({})` — target omitted on purpose:\n * the executor resolves the document OPEN in the\n * editor (the EC-378 current-document seam)\n * 2. document read, no update → `updateFields({ changes: [{\n * ...fakeUpdateTargetFrom(<text>, updateField),\n * value: fakeUpdateValueFrom(<last user text>) }] })`\n * — \"Set the body to: ## Neu\" drives a markdown\n * rich-text update deterministically (EC-379);\n * \"Set the body component <id> <prop> to: X\" one\n * component prop at any depth (EC-593)\n * 3. update result present → the update answer, word by word.\n */\nexport function createFakeCreateFlowChatModel(\n options: FakeCreateFlowChatModelOptions = {},\n): FakeChatModel {\n const searchCollection = options.searchCollection ?? 'author'\n const createCollection = options.createCollection ?? 'post'\n const searchAssets = options.searchAssets ?? false\n const answer = options.answerText ?? FAKE_CREATE_FLOW_ANSWER\n const updateField = options.updateField ?? 'title'\n const updatePattern = options.updatePattern ?? FAKE_UPDATE_PATTERN\n const updateAnswer = options.updateAnswerText ?? FAKE_UPDATE_FLOW_ANSWER\n return createFakeChatModel({\n modelId: options.modelId ?? 'fake-create-flow-model',\n script: (callOptions) => {\n const done = toolResultNamesInCurrentTurn(callOptions.prompt)\n const userText = lastUserText(callOptions.prompt)\n if (updatePattern.test(userText)) {\n if (done.has('updateFields')) return answerTurnParts(updateAnswer)\n if (done.has('getDocument')) {\n return toolTurnParts(\n 'Proposing the change. ',\n 'updateFields',\n {\n changes: [\n {\n ...fakeUpdateTargetFrom(userText, updateField),\n value: fakeUpdateValueFrom(userText),\n },\n ],\n },\n 'call-update-1',\n )\n }\n return toolTurnParts('Reading the document. ', 'getDocument', {}, 'call-get-1')\n }\n if (done.has('createDocument')) return answerTurnParts(answer)\n if (done.has('searchDocuments')) {\n // EC-381 — search the media library before creating (a topically fitting,\n // REAL asset fills the image field via the enum leash).\n if (searchAssets && !done.has('listAssets')) {\n return toolTurnParts(\n 'Looking for a fitting image. ',\n 'listAssets',\n { ...(options.assetQuery ? { query: options.assetQuery } : {}) },\n 'call-assets-1',\n )\n }\n const instruction = userText || 'Write a short document.'\n return toolTurnParts(\n 'Drafting a proposal. ',\n 'createDocument',\n { collection: createCollection, instruction },\n 'call-create-1',\n )\n }\n return toolTurnParts(\n FAKE_CHAT_PREAMBLE,\n 'searchDocuments',\n { collection: searchCollection },\n 'call-search-1',\n )\n },\n })\n}\n\n// --- Fake provider ------------------------------------------------------------------\n\nexport interface FakeProviderOptions {\n /** Provider id (default `fake`). */\n id?: string\n /** Model id recorded in provenance (default `fake-model`). */\n model?: string\n /** Reported capabilities (default: both true). Set to test the capability gate. */\n capabilities?: AiProviderCapabilities\n /** Scripted objects returned in call order; the last entry is reused when exhausted. */\n objects?: unknown[]\n /** Compute the object from the request + zero-based call index (overrides `objects`). */\n respond?: (request: GenerateStructuredRequest, callIndex: number) => unknown\n /** The scripted chat model `languageModel()` serves (default {@link createFakeChatModel}). */\n chatModel?: FakeChatModel\n}\n\n/** A FakeProvider that also records the requests it received, for assertions. */\nexport interface FakeProvider extends AiProvider {\n /** Every `generateStructured` request received, in order. */\n readonly calls: GenerateStructuredRequest[]\n /** The scripted fake chat model behind `languageModel()` (records its calls). */\n readonly chatModel: FakeChatModel\n}\n\nexport function createFakeProvider(options: FakeProviderOptions = {}): FakeProvider {\n const calls: GenerateStructuredRequest[] = []\n const objects = options.objects ?? []\n const chatModel = options.chatModel ?? createFakeChatModel()\n let index = 0\n\n return {\n id: options.id ?? 'fake',\n model: options.model ?? 'fake-model',\n calls,\n chatModel,\n capabilities: (): AiProviderCapabilities =>\n options.capabilities ?? { toolCalling: true, structuredOutput: true },\n\n languageModel: () => Promise.resolve(chatModel),\n\n generateStructured(request) {\n calls.push(request)\n const callIndex = index\n index += 1\n const object = options.respond\n ? options.respond(request, callIndex)\n : objects.length > 0\n ? objects[Math.min(callIndex, objects.length - 1)]\n : {}\n return Promise.resolve({ object, usage: { inputTokens: 0, outputTokens: 0 } })\n },\n }\n}\n"]}
|
package/dist/lib/ai/index.d.ts
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* `@elytracms/studio/lib/ai/vite` (`createAiDevPlugin`) — because it imports `vite`,
|
|
19
19
|
* a dev-only tool that must stay out of this barrel's dependency edge.
|
|
20
20
|
*/
|
|
21
|
-
export declare const PACKAGE = "
|
|
21
|
+
export declare const PACKAGE = "./index";
|
|
22
22
|
export * from './types.js';
|
|
23
23
|
export * from './config.js';
|
|
24
24
|
export * from './provenance.js';
|
|
@@ -26,6 +26,8 @@ export * from './knowledge.js';
|
|
|
26
26
|
export * from './rich-text-input.js';
|
|
27
27
|
export * from './constraints.js';
|
|
28
28
|
export * from './proposal-validation.js';
|
|
29
|
+
export * from './leash.js';
|
|
30
|
+
export * from './writer-form.js';
|
|
29
31
|
export * from './shape.js';
|
|
30
32
|
export * from './apply-content.js';
|
|
31
33
|
export * from './update-fields.js';
|
package/dist/lib/ai/index.js
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* `@elytracms/studio/lib/ai/vite` (`createAiDevPlugin`) — because it imports `vite`,
|
|
19
19
|
* a dev-only tool that must stay out of this barrel's dependency edge.
|
|
20
20
|
*/
|
|
21
|
-
export const PACKAGE = '
|
|
21
|
+
export const PACKAGE = './index';
|
|
22
22
|
export * from './types.js';
|
|
23
23
|
export * from './config.js';
|
|
24
24
|
export * from './provenance.js';
|
|
@@ -26,6 +26,8 @@ export * from './knowledge.js';
|
|
|
26
26
|
export * from './rich-text-input.js';
|
|
27
27
|
export * from './constraints.js';
|
|
28
28
|
export * from './proposal-validation.js';
|
|
29
|
+
export * from './leash.js';
|
|
30
|
+
export * from './writer-form.js';
|
|
29
31
|
export * from './shape.js';
|
|
30
32
|
export * from './apply-content.js';
|
|
31
33
|
export * from './update-fields.js';
|
package/dist/lib/ai/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/ai/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/ai/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,SAAS,CAAA;AAEhC,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,eAAe,CAAA;AAC7B,cAAc,uBAAuB,CAAA;AACrC,cAAc,SAAS,CAAA;AACvB,cAAc,eAAe,CAAA;AAC7B,cAAc,SAAS,CAAA;AACvB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,SAAS,CAAA;AACvB,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,0BAA0B,CAAA;AACxC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,SAAS,CAAA;AACvB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,uBAAuB,CAAA;AACrC,cAAc,sBAAsB,CAAA","sourcesContent":["/**\n * `@elytracms/studio/lib/ai` — the headless AI platform seam (EC-331, phase 1).\n *\n * Public surface: the config gate, the provider adapters (Anthropic + Fake), the\n * knowledge mechanism, the target-shape derivation, the `applyContentWithShape`\n * engine, the server-route factory, and the provenance seam. No chat UI here.\n *\n * Bundle discipline: nothing exported here statically imports `ai` / `@ai-sdk/*` —\n * only `anthropic-provider` touches them, via dynamic `import()`. So importing this\n * barrel never eagerly loads the AI SDK, and a studio without an `ai` config block\n * (which only references `StudioAiConfig` as a type) reaches none of it. The same\n * discipline keeps `jose` (the session resolver's JWT library) behind a dynamic\n * `import()` in `convex-session`.\n *\n * EC-371 adds the engine-default session gate + mounting kit: the Convex JWT\n * session resolver (server), the matching client header provider, and the Node\n * `(req, res)` bridge. The Vite DEV mount lives in its own entry —\n * `@elytracms/studio/lib/ai/vite` (`createAiDevPlugin`) — because it imports `vite`,\n * a dev-only tool that must stay out of this barrel's dependency edge.\n */\nexport const PACKAGE = './index'\n\nexport * from './types'\nexport * from './config'\nexport * from './provenance'\nexport * from './knowledge'\nexport * from './rich-text-input'\nexport * from './constraints'\nexport * from './proposal-validation'\nexport * from './leash'\nexport * from './writer-form'\nexport * from './shape'\nexport * from './apply-content'\nexport * from './update-fields'\nexport * from './anthropic-provider'\nexport * from './gateway-provider'\nexport * from './fake-provider'\nexport * from './route'\nexport * from './route-fetch'\nexport * from './route-provider'\nexport * from './convex-session'\nexport * from './convex-session-headers'\nexport * from './node-handler'\nexport * from './tools'\nexport * from './chat-context'\nexport * from './chat-loop'\nexport * from './chat-state'\nexport * from './rich-text-translate'\nexport * from './translate-document'\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { AssetFieldDef } from '@elytracms/core/cms-core';
|
|
2
|
+
import type { AssetCandidate, RelationCandidate, WriterLeash } from './types.js';
|
|
3
|
+
/** One searched document (a `searchDocuments` result). */
|
|
4
|
+
export interface SearchedDocument {
|
|
5
|
+
id: string;
|
|
6
|
+
title?: string;
|
|
7
|
+
}
|
|
8
|
+
/** One searched library asset (a `listAssets` result) — with the two facts `accept` is judged on. */
|
|
9
|
+
export interface SearchedAsset {
|
|
10
|
+
id: string;
|
|
11
|
+
title?: string;
|
|
12
|
+
contentType: string;
|
|
13
|
+
filename: string;
|
|
14
|
+
}
|
|
15
|
+
/** What a conversation searched: documents by collection, and one flat library pool. */
|
|
16
|
+
export interface SearchResults {
|
|
17
|
+
readonly documents?: Readonly<Record<string, readonly SearchedDocument[]>>;
|
|
18
|
+
readonly assets?: readonly SearchedAsset[];
|
|
19
|
+
}
|
|
20
|
+
/** The relation candidates a set of searched documents offers. */
|
|
21
|
+
export declare function relationCandidatesOf(documents: Iterable<SearchedDocument>): RelationCandidate[];
|
|
22
|
+
/**
|
|
23
|
+
* The asset candidates an asset POSITION may hold (EC-588 A4, at every position since
|
|
24
|
+
* EC-593): the searched pool filtered by that position's own `accept` — an image field
|
|
25
|
+
* is never offered a PDF, and neither is an image prop of a component.
|
|
26
|
+
*/
|
|
27
|
+
export declare function assetCandidatesOf(field: AssetFieldDef, pool: Iterable<SearchedAsset>): AssetCandidate[];
|
|
28
|
+
/**
|
|
29
|
+
* A {@link WriterLeash} over plain search results — what the chat's per-conversation
|
|
30
|
+
* store is, built once (tests and any non-chat caller construct one the same way).
|
|
31
|
+
*/
|
|
32
|
+
export declare function writerLeash(results: SearchResults): WriterLeash;
|
|
33
|
+
/** Nothing searched: every relation / asset position is empty (empty beats wrong). */
|
|
34
|
+
export declare const NO_SEARCHED_IDS: WriterLeash;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { assetMatchesAccept } from '@elytracms/core/cms-core';
|
|
2
|
+
/** The relation candidates a set of searched documents offers. */
|
|
3
|
+
export function relationCandidatesOf(documents) {
|
|
4
|
+
return [...documents].map((r) => ({ id: r.id, ...(r.title ? { label: r.title } : {}) }));
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* The asset candidates an asset POSITION may hold (EC-588 A4, at every position since
|
|
8
|
+
* EC-593): the searched pool filtered by that position's own `accept` — an image field
|
|
9
|
+
* is never offered a PDF, and neither is an image prop of a component.
|
|
10
|
+
*/
|
|
11
|
+
export function assetCandidatesOf(field, pool) {
|
|
12
|
+
return [...pool]
|
|
13
|
+
.filter((asset) => assetMatchesAccept(asset, field.accept))
|
|
14
|
+
.map((a) => ({ id: a.id, ...(a.title ? { label: a.title } : {}) }));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A {@link WriterLeash} over plain search results — what the chat's per-conversation
|
|
18
|
+
* store is, built once (tests and any non-chat caller construct one the same way).
|
|
19
|
+
*/
|
|
20
|
+
export function writerLeash(results) {
|
|
21
|
+
return {
|
|
22
|
+
relationCandidates: (target) => relationCandidatesOf(results.documents?.[target] ?? []),
|
|
23
|
+
assetCandidates: (field) => assetCandidatesOf(field, results.assets ?? []),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/** Nothing searched: every relation / asset position is empty (empty beats wrong). */
|
|
27
|
+
export const NO_SEARCHED_IDS = writerLeash({});
|
|
28
|
+
//# sourceMappingURL=leash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leash.js","sourceRoot":"","sources":["../../../src/lib/ai/leash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAwB7D,kEAAkE;AAClE,MAAM,UAAU,oBAAoB,CAAC,SAAqC;IACxE,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;AAC1F,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAoB,EAAE,IAA6B;IACnF,OAAO,CAAC,GAAG,IAAI,CAAC;SACb,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;SAC1D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;AACvE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,OAAsB;IAChD,OAAO;QACL,kBAAkB,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,oBAAoB,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACvF,eAAe,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;KAC3E,CAAA;AACH,CAAC;AAED,sFAAsF;AACtF,MAAM,CAAC,MAAM,eAAe,GAAgB,WAAW,CAAC,EAAE,CAAC,CAAA","sourcesContent":["import { assetMatchesAccept } from '@elytracms/core/cms-core'\nimport type { AssetFieldDef } from '@elytracms/core/cms-core'\nimport type { AssetCandidate, RelationCandidate, WriterLeash } from './types'\n\n/** One searched document (a `searchDocuments` result). */\nexport interface SearchedDocument {\n id: string\n title?: string\n}\n\n/** One searched library asset (a `listAssets` result) — with the two facts `accept` is judged on. */\nexport interface SearchedAsset {\n id: string\n title?: string\n contentType: string\n filename: string\n}\n\n/** What a conversation searched: documents by collection, and one flat library pool. */\nexport interface SearchResults {\n readonly documents?: Readonly<Record<string, readonly SearchedDocument[]>>\n readonly assets?: readonly SearchedAsset[]\n}\n\n/** The relation candidates a set of searched documents offers. */\nexport function relationCandidatesOf(documents: Iterable<SearchedDocument>): RelationCandidate[] {\n return [...documents].map((r) => ({ id: r.id, ...(r.title ? { label: r.title } : {}) }))\n}\n\n/**\n * The asset candidates an asset POSITION may hold (EC-588 A4, at every position since\n * EC-593): the searched pool filtered by that position's own `accept` — an image field\n * is never offered a PDF, and neither is an image prop of a component.\n */\nexport function assetCandidatesOf(field: AssetFieldDef, pool: Iterable<SearchedAsset>): AssetCandidate[] {\n return [...pool]\n .filter((asset) => assetMatchesAccept(asset, field.accept))\n .map((a) => ({ id: a.id, ...(a.title ? { label: a.title } : {}) }))\n}\n\n/**\n * A {@link WriterLeash} over plain search results — what the chat's per-conversation\n * store is, built once (tests and any non-chat caller construct one the same way).\n */\nexport function writerLeash(results: SearchResults): WriterLeash {\n return {\n relationCandidates: (target) => relationCandidatesOf(results.documents?.[target] ?? []),\n assetCandidates: (field) => assetCandidatesOf(field, results.assets ?? []),\n }\n}\n\n/** Nothing searched: every relation / asset position is empty (empty beats wrong). */\nexport const NO_SEARCHED_IDS: WriterLeash = writerLeash({})\n"]}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* ```ts
|
|
9
9
|
* // api/ai.ts (Vercel filesystem routing beats the SPA catch-all rewrite)
|
|
10
|
-
* import { toNodeHandler } from '
|
|
10
|
+
* import { toNodeHandler } from './index'
|
|
11
11
|
* import { aiRouteHandler } from '../src/server/ai-handler.js'
|
|
12
12
|
* export default toNodeHandler(aiRouteHandler)
|
|
13
13
|
* ```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-handler.js","sourceRoot":"","sources":["../../../src/lib/ai/node-handler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `toNodeHandler` — bridge the framework-agnostic Web `Request → Response`\n * {@link AiRouteHandler} to Node's `(req, res)` signature (EC-371; closes EC-369\n * finding #2, where the identical ~25-line bridge was hand-copied four times across\n * consumers). This is the PROD half of the mounting kit: a Vercel Node function (or\n * any Node server) mounts the route as\n *\n * ```ts\n * // api/ai.ts (Vercel filesystem routing beats the SPA catch-all rewrite)\n * import { toNodeHandler } from '
|
|
1
|
+
{"version":3,"file":"node-handler.js","sourceRoot":"","sources":["../../../src/lib/ai/node-handler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `toNodeHandler` — bridge the framework-agnostic Web `Request → Response`\n * {@link AiRouteHandler} to Node's `(req, res)` signature (EC-371; closes EC-369\n * finding #2, where the identical ~25-line bridge was hand-copied four times across\n * consumers). This is the PROD half of the mounting kit: a Vercel Node function (or\n * any Node server) mounts the route as\n *\n * ```ts\n * // api/ai.ts (Vercel filesystem routing beats the SPA catch-all rewrite)\n * import { toNodeHandler } from './index'\n * import { aiRouteHandler } from '../src/server/ai-handler.js'\n * export default toNodeHandler(aiRouteHandler)\n * ```\n *\n * The DEV half (`createAiDevPlugin`, Vite middleware + `ssrLoadModule`) reuses this\n * same bridge — one implementation, both mounts. No platform dependency: the classic\n * `(IncomingMessage, ServerResponse)` signature works on every @vercel/node version\n * and on plain `node:http`.\n *\n * EC-334: the RESPONSE side STREAMS — `response.body` reader chunks are piped to\n * `res.write` as they arrive, so the route's native SSE chat protocol delivers\n * token-by-token through every mount (the previous `arrayBuffer()` buffering would\n * have erased token streaming). The REQUEST side stays buffered (the route only\n * ever reads JSON bodies). Ships to every consumer mount — streaming through\n * Vercel Node functions goes on the post-release live-verify checklist.\n */\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { AiRouteHandler } from './types'\n\n/** A Node-mountable request handler (Vercel Node function / `node:http` compatible). */\nexport type NodeAiRouteHandler = (req: IncomingMessage, res: ServerResponse) => Promise<void>\n\nconst encoder = new TextEncoder()\n\nfunction concatBytes(chunks: Uint8Array[]): Uint8Array<ArrayBuffer> {\n let total = 0\n for (const chunk of chunks) total += chunk.byteLength\n const out = new Uint8Array(total)\n let offset = 0\n for (const chunk of chunks) {\n out.set(chunk, offset)\n offset += chunk.byteLength\n }\n return out\n}\n\n/** Reconstruct a Web `Request` from a Node request (headers, method, buffered body). */\nasync function toWebRequest(req: IncomingMessage): Promise<Request> {\n const chunks: Uint8Array[] = []\n for await (const chunk of req) {\n chunks.push(typeof chunk === 'string' ? encoder.encode(chunk) : (chunk as Uint8Array))\n }\n const headers = new Headers()\n for (const [key, value] of Object.entries(req.headers)) {\n if (typeof value === 'string') headers.set(key, value)\n else if (Array.isArray(value)) headers.set(key, value.join(', '))\n }\n const forwardedProto = req.headers['x-forwarded-proto']\n const proto =\n (typeof forwardedProto === 'string' && forwardedProto.split(',')[0]?.trim()) || 'http'\n return new Request(`${proto}://${req.headers.host ?? 'localhost'}${req.url ?? '/'}`, {\n method: req.method,\n headers,\n body: req.method === 'GET' || req.method === 'HEAD' ? undefined : concatBytes(chunks),\n })\n}\n\n/**\n * Wrap an {@link AiRouteHandler} as a Node `(req, res)` handler: buffer the request\n * body, bridge headers both directions, copy the status back, and STREAM the\n * response body — each chunk is written as it arrives (EC-334), so SSE token\n * streaming survives the bridge. A client disconnect cancels the reader so the\n * handler's stream stops being pulled.\n */\nexport function toNodeHandler(handler: AiRouteHandler): NodeAiRouteHandler {\n return async (req: IncomingMessage, res: ServerResponse): Promise<void> => {\n const request = await toWebRequest(req)\n const response = await handler(request)\n res.statusCode = response.status\n response.headers.forEach((value, key) => res.setHeader(key, value))\n\n const body = response.body\n if (!body) {\n res.end()\n return\n }\n\n const reader = body.getReader()\n let finished = false\n res.on('close', () => {\n // Client gone before the stream ended — stop pulling from the handler.\n if (!finished) void reader.cancel().catch(() => undefined)\n })\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n if (value !== undefined) res.write(value)\n }\n } catch {\n // Stream error mid-flight (or cancelled by disconnect): terminate below.\n } finally {\n finished = true\n res.end()\n }\n }\n}\n"]}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import type { RichTextValue } from '@elytracms/core/rich-text';
|
|
2
2
|
/**
|
|
3
|
-
* The model-input policy for rich-text
|
|
4
|
-
*
|
|
5
|
-
* (`buildUpdateProposal`):
|
|
3
|
+
* The model-input policy for rich-text values (EC-379), at every position the AI
|
|
4
|
+
* writes one — read by THE writer-form converter (`writer-form.ts`, EC-593), which
|
|
5
|
+
* create (`applyContentWithShape`) and edit (`buildUpdateProposal`) both call:
|
|
6
6
|
*
|
|
7
7
|
* - a **string is ALWAYS markdown** (never JSON-sniffed — deterministic): it is
|
|
8
8
|
* converted through the engine's strict subset converter, and out-of-subset
|
|
9
9
|
* constructs come back as explicit problems the caller feeds to the model for
|
|
10
10
|
* repair;
|
|
11
|
-
* - a `{ version,
|
|
12
|
-
* (the model sees
|
|
13
|
-
*
|
|
14
|
-
* schema-validated here and leash-validated downstream by
|
|
15
|
-
* + the injected `validateRichTextEmbeds`;
|
|
11
|
+
* - a stored `{ version: 2, content }` **value is still accepted** for robustness
|
|
12
|
+
* (the model sees one in `getDocument` output whenever a value is not losslessly
|
|
13
|
+
* expressible as markdown — embedded components, internal links — and may echo it
|
|
14
|
+
* back) — it is schema-validated here and leash-validated downstream by
|
|
15
|
+
* `validateDocument` + the injected `validateRichTextEmbeds`;
|
|
16
16
|
* - anything else is a problem. The target SHAPE only ever advertises the
|
|
17
17
|
* markdown string form (`shape.ts`), so markdown is what the model is
|
|
18
18
|
* steered to author.
|
|
@@ -13,7 +13,8 @@ export function richTextValueFromModelInput(raw) {
|
|
|
13
13
|
return {
|
|
14
14
|
ok: false,
|
|
15
15
|
problems: [
|
|
16
|
-
|
|
16
|
+
// SHAPES #16 (EC-593): the storage value this names is the one the engine reads.
|
|
17
|
+
`Rich text must be authored as a markdown string (${MARKDOWN_PROSE_DESCRIPTION}); the provided object is not a valid stored { version: 2, content } value either.`,
|
|
17
18
|
],
|
|
18
19
|
};
|
|
19
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rich-text-input.js","sourceRoot":"","sources":["../../../src/lib/ai/rich-text-input.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,2BAA2B,CAAA;AAyBlC,MAAM,UAAU,2BAA2B,CAAC,GAAY;IACtD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,4BAA4B,CAAC,GAAG,CAAC,CAAA;QACnD,IAAI,SAAS,CAAC,EAAE;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,CAAA;QAC7D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAA;IAChF,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5C,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAA;QACtC,IAAI,MAAM,CAAC,EAAE;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAA;QACvD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,QAAQ,EAAE;gBACR,oDAAoD,0BAA0B,
|
|
1
|
+
{"version":3,"file":"rich-text-input.js","sourceRoot":"","sources":["../../../src/lib/ai/rich-text-input.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,2BAA2B,CAAA;AAyBlC,MAAM,UAAU,2BAA2B,CAAC,GAAY;IACtD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,4BAA4B,CAAC,GAAG,CAAC,CAAA;QACnD,IAAI,SAAS,CAAC,EAAE;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,CAAA;QAC7D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAA;IAChF,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5C,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAA;QACtC,IAAI,MAAM,CAAC,EAAE;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAA;QACvD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,QAAQ,EAAE;gBACR,iFAAiF;gBACjF,oDAAoD,0BAA0B,oFAAoF;aACnK;SACF,CAAA;IACH,CAAC;IACD,OAAO;QACL,EAAE,EAAE,KAAK;QACT,QAAQ,EAAE,CAAC,oDAAoD,0BAA0B,IAAI,CAAC;KAC/F,CAAA;AACH,CAAC","sourcesContent":["import {\n MARKDOWN_PROSE_DESCRIPTION,\n markdownProseToRichTextValue,\n parseRichTextValue,\n} from '@elytracms/core/rich-text'\nimport type { RichTextValue } from '@elytracms/core/rich-text'\n\n/**\n * The model-input policy for rich-text values (EC-379), at every position the AI\n * writes one — read by THE writer-form converter (`writer-form.ts`, EC-593), which\n * create (`applyContentWithShape`) and edit (`buildUpdateProposal`) both call:\n *\n * - a **string is ALWAYS markdown** (never JSON-sniffed — deterministic): it is\n * converted through the engine's strict subset converter, and out-of-subset\n * constructs come back as explicit problems the caller feeds to the model for\n * repair;\n * - a stored `{ version: 2, content }` **value is still accepted** for robustness\n * (the model sees one in `getDocument` output whenever a value is not losslessly\n * expressible as markdown — embedded components, internal links — and may echo it\n * back) — it is schema-validated here and leash-validated downstream by\n * `validateDocument` + the injected `validateRichTextEmbeds`;\n * - anything else is a problem. The target SHAPE only ever advertises the\n * markdown string form (`shape.ts`), so markdown is what the model is\n * steered to author.\n */\nexport type RichTextInputResult =\n | { ok: true; value: RichTextValue }\n | { ok: false; problems: string[] }\n\nexport function richTextValueFromModelInput(raw: unknown): RichTextInputResult {\n if (typeof raw === 'string') {\n const converted = markdownProseToRichTextValue(raw)\n if (converted.ok) return { ok: true, value: converted.value }\n return { ok: false, problems: converted.issues.map((issue) => issue.message) }\n }\n if (typeof raw === 'object' && raw !== null) {\n const parsed = parseRichTextValue(raw)\n if (parsed.ok) return { ok: true, value: parsed.value }\n return {\n ok: false,\n problems: [\n // SHAPES #16 (EC-593): the storage value this names is the one the engine reads.\n `Rich text must be authored as a markdown string (${MARKDOWN_PROSE_DESCRIPTION}); the provided object is not a valid stored { version: 2, content } value either.`,\n ],\n }\n }\n return {\n ok: false,\n problems: [`Rich text must be authored as a markdown string (${MARKDOWN_PROSE_DESCRIPTION}).`],\n }\n}\n"]}
|
|
@@ -21,19 +21,42 @@ export interface RichTextPlan {
|
|
|
21
21
|
blocks: Map<string, BlockTables>;
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
|
-
* Walk a rich-text value
|
|
25
|
-
*
|
|
26
|
-
*
|
|
24
|
+
* Walk a rich-text value — or any `{ version: 2, content }` sequence, a `blocks` value's
|
|
25
|
+
* typography included — and extract its translatable blocks. Deterministic; never
|
|
26
|
+
* throws. A value that is not a readable sequence yields no units, a plan whose rebuild
|
|
27
|
+
* is a no-op, and `readable: false` — the caller REPORTS it (EC-593: translate never
|
|
28
|
+
* skips silently). Code blocks are skipped (code is not prose). Component nodes are not
|
|
29
|
+
* text here: their props are positions of the value traversal, translated by the caller.
|
|
30
|
+
*
|
|
31
|
+
* The walk reads the STORED value once the parse proved it readable, so every node the
|
|
32
|
+
* rebuild does not touch — a component node, an atom — comes back byte-for-byte as
|
|
33
|
+
* stored (a parse is a validation, not a copy to write from).
|
|
27
34
|
*/
|
|
28
35
|
export declare function extractRichTextUnits(raw: unknown): {
|
|
29
36
|
units: RichTextBlockUnit[];
|
|
30
37
|
plan: RichTextPlan;
|
|
38
|
+
readable: boolean;
|
|
31
39
|
};
|
|
40
|
+
/** {@link rebuildRichTextReport}'s outcome: the value, and which blocks did and did not apply. */
|
|
41
|
+
export interface RichTextRebuild {
|
|
42
|
+
value: RichTextValue;
|
|
43
|
+
/** Block ids whose translation was applied. */
|
|
44
|
+
applied: string[];
|
|
45
|
+
/**
|
|
46
|
+
* Block ids whose translation came back but did not decode token-faithfully — the
|
|
47
|
+
* ORIGINAL block was kept (never a broken tree), so it is untranslated: EC-593 makes
|
|
48
|
+
* the caller report it rather than count it as done.
|
|
49
|
+
*/
|
|
50
|
+
rejected: string[];
|
|
51
|
+
}
|
|
32
52
|
/**
|
|
33
53
|
* Rebuild a rich-text value from a plan + a per-block translation map. A block absent
|
|
34
54
|
* from `translations` (skipped/aborted) or whose translated tokens don't parse keeps its
|
|
35
|
-
* ORIGINAL content — never a broken structure. Returns a fresh `{ version,
|
|
55
|
+
* ORIGINAL content — never a broken structure. Returns a fresh `{ version: 2, content }`
|
|
56
|
+
* value, and the blocks it applied and rejected.
|
|
36
57
|
*/
|
|
58
|
+
export declare function rebuildRichTextReport(plan: RichTextPlan, translations: ReadonlyMap<string, string>): RichTextRebuild;
|
|
59
|
+
/** {@link rebuildRichTextReport}'s value alone. */
|
|
37
60
|
export declare function rebuildRichText(plan: RichTextPlan, translations: ReadonlyMap<string, string>): RichTextValue;
|
|
38
61
|
/**
|
|
39
62
|
* Apply `fn` to only the human-readable text segments of an encoded block (the runs
|
|
@@ -86,18 +86,26 @@ function hasTranslatableText(encoded) {
|
|
|
86
86
|
return encoded.replace(TOKEN_RE, '').trim().length > 0;
|
|
87
87
|
}
|
|
88
88
|
/**
|
|
89
|
-
* Walk a rich-text value
|
|
90
|
-
*
|
|
91
|
-
*
|
|
89
|
+
* Walk a rich-text value — or any `{ version: 2, content }` sequence, a `blocks` value's
|
|
90
|
+
* typography included — and extract its translatable blocks. Deterministic; never
|
|
91
|
+
* throws. A value that is not a readable sequence yields no units, a plan whose rebuild
|
|
92
|
+
* is a no-op, and `readable: false` — the caller REPORTS it (EC-593: translate never
|
|
93
|
+
* skips silently). Code blocks are skipped (code is not prose). Component nodes are not
|
|
94
|
+
* text here: their props are positions of the value traversal, translated by the caller.
|
|
95
|
+
*
|
|
96
|
+
* The walk reads the STORED value once the parse proved it readable, so every node the
|
|
97
|
+
* rebuild does not touch — a component node, an atom — comes back byte-for-byte as
|
|
98
|
+
* stored (a parse is a validation, not a copy to write from).
|
|
92
99
|
*/
|
|
93
100
|
export function extractRichTextUnits(raw) {
|
|
94
101
|
const parsed = parseRichTextValue(raw);
|
|
95
102
|
const blocks = new Map();
|
|
96
103
|
const units = [];
|
|
97
104
|
if (!parsed.ok) {
|
|
98
|
-
return { units, plan: { value: { version: 2, content: [] }, blocks } };
|
|
105
|
+
return { units, plan: { value: { version: 2, content: [] }, blocks }, readable: false };
|
|
99
106
|
}
|
|
100
|
-
|
|
107
|
+
// A readable value whose `content` the parse defaulted (absent) has nothing stored to keep.
|
|
108
|
+
const value = Array.isArray(raw.content) ? raw : parsed.value;
|
|
101
109
|
const walk = (node, path) => {
|
|
102
110
|
if (node.type === 'codeBlock')
|
|
103
111
|
return;
|
|
@@ -113,7 +121,7 @@ export function extractRichTextUnits(raw) {
|
|
|
113
121
|
node.content?.forEach((child, i) => walk(child, [...path, i]));
|
|
114
122
|
};
|
|
115
123
|
value.content.forEach((node, i) => walk(node, [i]));
|
|
116
|
-
return { units, plan: { value, blocks } };
|
|
124
|
+
return { units, plan: { value, blocks }, readable: true };
|
|
117
125
|
}
|
|
118
126
|
// --- Reconstruction ---------------------------------------------------------------
|
|
119
127
|
/**
|
|
@@ -191,21 +199,31 @@ function replaceAtPath(nodes, path, content) {
|
|
|
191
199
|
/**
|
|
192
200
|
* Rebuild a rich-text value from a plan + a per-block translation map. A block absent
|
|
193
201
|
* from `translations` (skipped/aborted) or whose translated tokens don't parse keeps its
|
|
194
|
-
* ORIGINAL content — never a broken structure. Returns a fresh `{ version,
|
|
202
|
+
* ORIGINAL content — never a broken structure. Returns a fresh `{ version: 2, content }`
|
|
203
|
+
* value, and the blocks it applied and rejected.
|
|
195
204
|
*/
|
|
196
|
-
export function
|
|
205
|
+
export function rebuildRichTextReport(plan, translations) {
|
|
197
206
|
let content = plan.value.content.map((n) => n);
|
|
207
|
+
const applied = [];
|
|
208
|
+
const rejected = [];
|
|
198
209
|
for (const [id, tables] of plan.blocks) {
|
|
199
210
|
const translated = translations.get(id);
|
|
200
211
|
if (translated === undefined)
|
|
201
212
|
continue;
|
|
202
213
|
const decoded = decodeBlock(translated, tables);
|
|
203
|
-
if (!decoded)
|
|
214
|
+
if (!decoded) {
|
|
215
|
+
rejected.push(id);
|
|
204
216
|
continue;
|
|
217
|
+
}
|
|
218
|
+
applied.push(id);
|
|
205
219
|
content = replaceAtPath(content, tables.path, decoded);
|
|
206
220
|
}
|
|
207
221
|
const doc = { type: 'doc', content };
|
|
208
|
-
return createRichTextValue(doc);
|
|
222
|
+
return { value: createRichTextValue(doc), applied, rejected };
|
|
223
|
+
}
|
|
224
|
+
/** {@link rebuildRichTextReport}'s value alone. */
|
|
225
|
+
export function rebuildRichText(plan, translations) {
|
|
226
|
+
return rebuildRichTextReport(plan, translations).value;
|
|
209
227
|
}
|
|
210
228
|
// --- Deterministic segment transform (FakeProvider + tests) -----------------------
|
|
211
229
|
/**
|