@aglyn/plugins-ai 1.0.0-beta.288 → 1.0.0-beta.290

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/package.json +17 -17
  2. package/src/lib/activity/ai-activity-actions.d.ts +3 -2
  3. package/src/lib/activity/ai-activity-actions.js +3 -0
  4. package/src/lib/activity/ai-activity-actions.js.map +1 -1
  5. package/src/lib/components/ai-job-requests.d.ts +2 -0
  6. package/src/lib/components/ai-job-requests.js +2 -0
  7. package/src/lib/components/ai-job-requests.js.map +1 -1
  8. package/src/lib/components/ai-site-build-page.component.js +4 -0
  9. package/src/lib/components/ai-site-build-page.component.js.map +1 -1
  10. package/src/lib/components/ai-site-import-job.component.d.ts +6 -1
  11. package/src/lib/components/ai-site-import-job.component.js +124 -17
  12. package/src/lib/components/ai-site-import-job.component.js.map +1 -1
  13. package/src/lib/components/ai-site-import-start.component.d.ts +6 -0
  14. package/src/lib/components/ai-site-import-start.component.js +18 -4
  15. package/src/lib/components/ai-site-import-start.component.js.map +1 -1
  16. package/src/lib/components/ai-site-start-card.component.js +2 -1
  17. package/src/lib/components/ai-site-start-card.component.js.map +1 -1
  18. package/src/lib/jobs/ai-image-reads.d.ts +20 -2
  19. package/src/lib/jobs/ai-image-reads.js +47 -0
  20. package/src/lib/jobs/ai-image-reads.js.map +1 -1
  21. package/src/lib/jobs/ai-job-import-step.d.ts +53 -3
  22. package/src/lib/jobs/ai-job-import-step.js +386 -64
  23. package/src/lib/jobs/ai-job-import-step.js.map +1 -1
  24. package/src/lib/jobs/ai-job-layout-language.d.ts +33 -0
  25. package/src/lib/jobs/ai-job-layout-language.js +75 -1
  26. package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
  27. package/src/lib/jobs/ai-job-layout-step.js +8 -3
  28. package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
  29. package/src/lib/jobs/ai-job-page-language.d.ts +29 -0
  30. package/src/lib/jobs/ai-job-page-language.js +178 -2
  31. package/src/lib/jobs/ai-job-page-language.js.map +1 -1
  32. package/src/lib/jobs/ai-job-page-step.js +3 -0
  33. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  34. package/src/lib/jobs/ai-site-import-document.d.ts +117 -0
  35. package/src/lib/jobs/ai-site-import-document.js +710 -0
  36. package/src/lib/jobs/ai-site-import-document.js.map +1 -0
  37. package/src/lib/jobs/ai-site-import-look.d.ts +112 -0
  38. package/src/lib/jobs/ai-site-import-look.js +402 -0
  39. package/src/lib/jobs/ai-site-import-look.js.map +1 -0
  40. package/src/lib/jobs/ai-site-import-publish.d.ts +41 -0
  41. package/src/lib/jobs/ai-site-import-publish.js +92 -0
  42. package/src/lib/jobs/ai-site-import-publish.js.map +1 -0
  43. package/src/lib/jobs/ai-theme-brand-inputs.d.ts +27 -2
  44. package/src/lib/jobs/ai-theme-brand-inputs.js +37 -8
  45. package/src/lib/jobs/ai-theme-brand-inputs.js.map +1 -1
  46. package/src/lib/layout-language/ai-layout-frame.d.ts +17 -0
  47. package/src/lib/layout-language/ai-layout-frame.js +73 -2
  48. package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
  49. package/src/lib/layout-language/ai-layout-language.d.ts +43 -0
  50. package/src/lib/layout-language/ai-layout-language.js +199 -0
  51. package/src/lib/layout-language/ai-layout-language.js.map +1 -1
  52. package/src/lib/model/ai-credit-estimate.d.ts +15 -0
  53. package/src/lib/model/ai-credit-estimate.js +14 -1
  54. package/src/lib/model/ai-credit-estimate.js.map +1 -1
  55. package/src/lib/model/ai-jobs.types.d.ts +13 -1
  56. package/src/lib/model/ai-jobs.types.js.map +1 -1
  57. package/src/lib/model/ai-site-import-view.d.ts +47 -3
  58. package/src/lib/model/ai-site-import-view.js +122 -20
  59. package/src/lib/model/ai-site-import-view.js.map +1 -1
  60. package/src/lib/model/ai-site-import.d.ts +232 -7
  61. package/src/lib/model/ai-site-import.js +365 -35
  62. package/src/lib/model/ai-site-import.js.map +1 -1
  63. package/src/lib/runtime/ai-doctrine-validators.d.ts +18 -0
  64. package/src/lib/runtime/ai-doctrine-validators.js +16 -5
  65. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  66. package/src/lib/runtime/ai-palette.generated.js +31 -0
  67. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  68. package/src/lib/server/ai-image-reads-route.js +24 -1
  69. package/src/lib/server/ai-image-reads-route.js.map +1 -1
  70. package/src/lib/server/ai-jobs-resume.js +7 -1
  71. package/src/lib/server/ai-jobs-resume.js.map +1 -1
  72. package/src/lib/site-import/fixtures/aglyn-com-recordings.d.ts +57 -0
  73. package/src/lib/site-import/fixtures/aglyn-com-recordings.js +172 -0
  74. package/src/lib/site-import/fixtures/aglyn-com-recordings.js.map +1 -0
  75. package/src/lib/site-import/site-import-crawl.d.ts +32 -7
  76. package/src/lib/site-import/site-import-crawl.js +133 -44
  77. package/src/lib/site-import/site-import-crawl.js.map +1 -1
  78. package/src/lib/site-import/site-import-edge-server.d.ts +31 -0
  79. package/src/lib/site-import/site-import-edge-server.js +31 -0
  80. package/src/lib/site-import/site-import-edge-server.js.map +1 -0
  81. package/src/lib/site-import/site-import-edge.d.ts +44 -0
  82. package/src/lib/site-import/site-import-edge.js +108 -0
  83. package/src/lib/site-import/site-import-edge.js.map +1 -0
  84. package/src/lib/site-import/site-import-html.d.ts +73 -3
  85. package/src/lib/site-import/site-import-html.js +332 -45
  86. package/src/lib/site-import/site-import-html.js.map +1 -1
  87. package/src/lib/site-import/site-import-images.d.ts +22 -0
  88. package/src/lib/site-import/site-import-images.js +78 -2
  89. package/src/lib/site-import/site-import-images.js.map +1 -1
  90. package/src/lib/site-import/site-import-page.d.ts +44 -2
  91. package/src/lib/site-import/site-import-page.js +116 -16
  92. package/src/lib/site-import/site-import-page.js.map +1 -1
@@ -21,14 +21,14 @@ import { aiHomeScreenIds } from "../model/ai-site-inventory.js";
21
21
  import { AI_LAYOUT_POST_ADDRESS_TOKENS, aiCompileLayoutPage } from "../layout-language/ai-layout-compiler.js";
22
22
  import { aiSiteMotionStyle, aiWithSiteMotion } from "../layout-language/ai-layout-motion.js";
23
23
  import { aiLayoutListingAt, aiLayoutListingsOf, aiLayoutRecordHref } from "../layout-language/ai-layout-listings.js";
24
- import { AI_LAYOUT_LANGUAGE_TEXT, AI_LAYOUT_PAGE_TOOL, aiReadLayoutPage } from "../layout-language/ai-layout-language.js";
24
+ import { AI_LAYOUT_ARRANGE_TOOL, AI_LAYOUT_LANGUAGE_TEXT, AI_LAYOUT_PAGE_TOOL, aiReadLayoutArrangement, aiReadLayoutPage } from "../layout-language/ai-layout-language.js";
25
25
  import { aiLayoutCopyCheck, aiLayoutWithoutSections } from "../layout-language/ai-layout-gaps.js";
26
26
  import { aiLayoutPromisedCopyViolations, aiLayoutPromisedSections } from "../layout-language/ai-layout-promised-copy.js";
27
27
  import { aiLayoutStoredTree } from "../layout-language/ai-layout-store.js";
28
28
  import { AI_GENERATION_MAX_ATTEMPTS } from "../runtime/ai-generation-bounds.js";
29
29
  import { AI_STEP_TIERS } from "../providers/catalog.js";
30
30
  import { aiCacheWriteHourSum } from "../providers/cache-write-hour.js";
31
- import { runValidatedGeneration } from "../runtime/ai-doctrine.js";
31
+ import { aiDoctrineNeedsInputMessage, runValidatedGeneration } from "../runtime/ai-doctrine.js";
32
32
  import { aiSettleMechanicalRules, aiSettleUnrelatedScreenLinks, validateAiDoctrineTree } from "../runtime/ai-doctrine-validators.js";
33
33
  import { aiSiteKindDesignLines, aiSiteKindOfInputs } from "../model/ai-site-kinds.js";
34
34
  import { aiSiteSeed } from "../model/ai-site-look.js";
@@ -38,6 +38,7 @@ import { aiJobBriefLine, aiPlanReferenceLines } from "./ai-job-generation.js";
38
38
  import { aiLayoutIsHomeSlug, aiLayoutSiteAliases, aiLayoutSitePages } from "./ai-job-layout-site-pages.js";
39
39
  import { aiLayoutInventedContactViolations } from "./ai-layout-site-facts.js";
40
40
  import { aiSiteContactOf } from "../model/ai-site-details.js";
41
+ import { AI_SITE_IMPORT_ARRANGE_MAX_CHARS, aiCompileImportedDocument, aiSiteImportArrangeText, aiSiteImportDocLines, aiSiteImportDocumentOf } from "./ai-site-import-document.js";
41
42
  /**
42
43
  * A page built in the compact layout language (AGL-3660): the page step's
43
44
  * pass for a site's page units — a guided start's and a build's — in place of
@@ -794,6 +795,9 @@ export const AI_JOB_PAGE_LANGUAGE_BUDGET = aiJobStepBudget({
794
795
  * them, so the page is compiled whole once every section is designed.
795
796
  */ export async function aiRunLayoutPage(input) {
796
797
  var _input_observe, _input_startsFrom;
798
+ // A page brought in from the owner's own site is never written (AGL-4084).
799
+ const imported = aiSiteImportDocumentOf(input.job.inputs);
800
+ if (imported) return aiRunImportedPage(input, imported);
797
801
  const kept = input.screen.sections.map(()=>null);
798
802
  const observe = (_input_observe = input.observe) != null ? _input_observe : (check)=>check;
799
803
  const base = aiLayoutPagePrompt({
@@ -856,5 +860,177 @@ export const AI_JOB_PAGE_LANGUAGE_BUDGET = aiJobStepBudget({
856
860
  }), Math.min(AI_JOB_PAGE_LANGUAGE_FOLLOW_UP_TOKENS, AI_JOB_PAGE_LANGUAGE_BUDGET.maxTokens(input.model)), missing);
857
861
  return _extends({}, second, spentTogether(first, second));
858
862
  }
863
+ /*------------------------------------------
864
+ * A page brought in: copied, or arranged (AGL-4084)
865
+ *-----------------------------------------*/ /**
866
+ * What an arranged page's answer is told (AGL-4084), cached: the page's words
867
+ * are the source's and fixed, and the answer only lays them out. The tool has
868
+ * no field for a word of copy, so a rewording has nowhere to go.
869
+ */ export const AI_LAYOUT_ARRANGE_TEXT = [
870
+ "You arrange a page brought in from its owner's own website. Arrange; keep every line as written; add nothing; reword nothing. Its words are fixed: every line of the page is shown numbered, and the platform places each line you name exactly as its source wrote it, in the site's theme. You never write a word of copy.",
871
+ '',
872
+ 'Answer with submit_arrangement: one entry in sections for each section of the page, in order. A section has:',
873
+ '- band: plain (the page background), soft (a light band) or dark. Vary the bands down the page so neighboring sections read apart, and keep dark to one or two sections a page.',
874
+ '- cols: [] for one column, or relative column widths for a row, such as [1, 1] or [7, 5]; at most 4.',
875
+ '- align: start or center.',
876
+ '- blocks: top to bottom. A block has kind, col (-1 to span the section, or the column of the row it sits in, 0 first), from (the numbers of the lines it shows, in order), style (primary, secondary or quiet for a button, none otherwise) and items.',
877
+ '',
878
+ 'Block kinds: heading, eyebrow, lede, text and note show their lines one under another; list shows each of its lines as an item; cards, steps, stats and faq show items, each item\'s from its title line first and then its text lines (from is then []); button is a line that is a link; image is a line that is a picture.',
879
+ "Every line goes in exactly one block of its own section. Name no line twice and no line of another section. A line you leave out is still shown, at the end of its section, so leave none out on purpose. The page's first section opens with its heading line."
880
+ ].join('\n');
881
+ /** The arranged page's cached instructions, and the rule that fenced text is data. */ export const AI_JOB_PAGE_ARRANGE_INSTRUCTIONS = [
882
+ {
883
+ text: AI_LAYOUT_ARRANGE_TEXT,
884
+ cacheBreakpoint: true
885
+ },
886
+ {
887
+ text: UNTRUSTED_TEXT_RULE
888
+ }
889
+ ];
890
+ /** An arranged page's user turn: the page, the kind of site it is, and its numbered lines, fenced. */ export function aiLayoutArrangePrompt(input) {
891
+ const { sections } = aiSiteImportDocLines(input.doc.blocks, input.doc.title);
892
+ return [
893
+ `Page: "${input.screen.title}" at ${input.screen.slug}`,
894
+ ...aiSiteKindDesignLines(input.job.inputs),
895
+ `Its ${sections.length === 1 ? 'one section' : `${sections.length} sections`}, each with its numbered lines:`,
896
+ fenceUntrustedText(`The owner's page ${input.doc.url}`, aiSiteImportArrangeText(input.doc), {
897
+ maxChars: AI_SITE_IMPORT_ARRANGE_MAX_CHARS
898
+ }),
899
+ `Design seed: ${input.job.$id.slice(-6)}.`
900
+ ].join('\n');
901
+ }
902
+ /**
903
+ * The check a page brought in is held to (AGL-4084): the arrangement read
904
+ * (or none, for a page copied as it is), the source's lines substituted
905
+ * into it, the page stored and checked whole as a page of the owner's own
906
+ * words. Nothing in an answer can change a word.
907
+ */ export function aiImportedPageCheck(input) {
908
+ const context = _extends({}, aiLayoutListingContext(input.context, input.targets), {
909
+ ownWords: true
910
+ });
911
+ return (answer)=>{
912
+ var _ref, _input_motion;
913
+ const arrangement = answer && input.doc.build === 'arranged' ? aiReadLayoutArrangement(answer, input.sectionIds.length) : null;
914
+ const compiled = aiCompileImportedDocument({
915
+ doc: input.doc,
916
+ sectionIds: input.sectionIds,
917
+ pages: input.targets.pages,
918
+ arrangement
919
+ });
920
+ const stored = aiLayoutStoredTree(compiled.tree, 'screen', context, input.sectionIds);
921
+ if (stored.ok === false) {
922
+ console.error('ai imported page: a compiled page did not store', {
923
+ error: stored.error
924
+ });
925
+ return {
926
+ value: null,
927
+ violations: [
928
+ {
929
+ rule: null,
930
+ code: 'layout-compile',
931
+ message: 'This page could not be built. Try again.',
932
+ detail: stored.error
933
+ }
934
+ ]
935
+ };
936
+ }
937
+ const report = validateAiDoctrineTree({
938
+ rootId: CANVAS_ROOT_ELEMENT_ID,
939
+ nodes: stored.nodes
940
+ }, 'page', _extends({}, context, {
941
+ scrollTargetIds: input.sectionIds,
942
+ repeatsCompiled: true
943
+ }));
944
+ if (report.violations.length) return {
945
+ value: null,
946
+ violations: report.violations
947
+ };
948
+ return {
949
+ value: {
950
+ nodes: aiWithSiteMotion(stored.nodes, (_ref = (_input_motion = input.motion) != null ? _input_motion : input.design) != null ? _ref : {
951
+ seed: 0
952
+ }, {
953
+ sectionIds: input.sectionIds
954
+ }),
955
+ load: report.load,
956
+ settled: [],
957
+ dropped: [],
958
+ items: input.sectionIds.map(()=>0)
959
+ },
960
+ violations: []
961
+ };
962
+ };
963
+ }
964
+ /** The most an arrangement answer runs to: a few hundred tokens of line numbers, inside a page's ceiling. */ export const AI_LAYOUT_ARRANGE_KIND = AI_LAYOUT_PAGE_KIND;
965
+ const NO_USAGE = {
966
+ inputTokens: 0,
967
+ outputTokens: 0,
968
+ cacheReadTokens: 0,
969
+ cacheWriteTokens: 0
970
+ };
971
+ /**
972
+ * A page brought in (AGL-4084). Copied as it is: compiled by code, no model
973
+ * at all, nothing spent. Arranged: one answer on the page step's tier that
974
+ * lays the numbered lines out, every word still the source's.
975
+ */ async function aiRunImportedPage(input, doc) {
976
+ var _input_observe;
977
+ const check = aiImportedPageCheck({
978
+ screen: input.screen,
979
+ sectionIds: input.sectionIds,
980
+ targets: input.targets,
981
+ context: input.context,
982
+ design: aiLayoutDesignOf(input.job, input.screen.slug),
983
+ motion: aiLayoutMotionSiteOf(input.job, input.screen.slug),
984
+ doc
985
+ });
986
+ if (doc.build === 'copied') {
987
+ const spend = {
988
+ attempts: 0,
989
+ usage: NO_USAGE,
990
+ estCostUsd: 0,
991
+ model: input.model,
992
+ stopReason: null,
993
+ effort: null
994
+ };
995
+ const result = check(null);
996
+ return result.value ? _extends({}, spend, {
997
+ status: 'ok',
998
+ value: result.value
999
+ }) : _extends({}, spend, {
1000
+ status: 'needs_input',
1001
+ violations: result.violations,
1002
+ message: aiDoctrineNeedsInputMessage(result.violations),
1003
+ answer: null
1004
+ });
1005
+ }
1006
+ const observe = (_input_observe = input.observe) != null ? _input_observe : (inner)=>inner;
1007
+ return runValidatedGeneration(AI_LAYOUT_ARRANGE_KIND, _extends({
1008
+ step: 'job.page',
1009
+ model: input.model,
1010
+ instructions: AI_JOB_PAGE_ARRANGE_INSTRUCTIONS,
1011
+ // The lines are the whole question: no lookup of the site is offered.
1012
+ inventory: null,
1013
+ messages: [
1014
+ {
1015
+ role: 'user',
1016
+ content: aiLayoutArrangePrompt({
1017
+ job: input.job,
1018
+ screen: input.screen,
1019
+ doc
1020
+ })
1021
+ }
1022
+ ],
1023
+ tool: AI_LAYOUT_ARRANGE_TOOL,
1024
+ maxTokens: AI_JOB_PAGE_LANGUAGE_BUDGET.maxTokens(input.model),
1025
+ cutOff: {
1026
+ noun: 'page',
1027
+ smaller: 'Use fewer blocks: give each block more of its lines.'
1028
+ }
1029
+ }, AI_LAYOUT_LANGUAGE_THINKING, {
1030
+ check: observe((answer)=>check(answer))
1031
+ }, input.signal ? {
1032
+ signal: input.signal
1033
+ } : {}));
1034
+ }
859
1035
 
860
1036
  //# sourceMappingURL=ai-job-page-language.js.map