@aglyn/plugins-ai 1.0.0-beta.232 → 1.0.0-beta.234

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 (115) hide show
  1. package/package.json +17 -17
  2. package/src/lib/components/ai-job-links.d.ts +6 -0
  3. package/src/lib/components/ai-job-links.js +9 -0
  4. package/src/lib/components/ai-job-links.js.map +1 -1
  5. package/src/lib/components/ai-site-build-page.component.js +41 -3
  6. package/src/lib/components/ai-site-build-page.component.js.map +1 -1
  7. package/src/lib/components/ai-site-start-card.component.js +91 -8
  8. package/src/lib/components/ai-site-start-card.component.js.map +1 -1
  9. package/src/lib/declarations.server.js +7 -4
  10. package/src/lib/declarations.server.js.map +1 -1
  11. package/src/lib/jobs/ai-build-capabilities.js +8 -2
  12. package/src/lib/jobs/ai-build-capabilities.js.map +1 -1
  13. package/src/lib/jobs/ai-job-admission.d.ts +2 -1
  14. package/src/lib/jobs/ai-job-admission.js.map +1 -1
  15. package/src/lib/jobs/ai-job-email-step.d.ts +39 -0
  16. package/src/lib/jobs/ai-job-email-step.js +116 -5
  17. package/src/lib/jobs/ai-job-email-step.js.map +1 -1
  18. package/src/lib/jobs/ai-job-layout-language.d.ts +3 -0
  19. package/src/lib/jobs/ai-job-layout-language.js +3 -1
  20. package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
  21. package/src/lib/jobs/ai-job-layout-site-pages.d.ts +2 -0
  22. package/src/lib/jobs/ai-job-layout-site-pages.js +23 -11
  23. package/src/lib/jobs/ai-job-layout-site-pages.js.map +1 -1
  24. package/src/lib/jobs/ai-job-layout-step.js +3 -2
  25. package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
  26. package/src/lib/jobs/ai-job-page-language.d.ts +16 -0
  27. package/src/lib/jobs/ai-job-page-language.js +35 -6
  28. package/src/lib/jobs/ai-job-page-language.js.map +1 -1
  29. package/src/lib/jobs/ai-job-page-step.d.ts +3 -0
  30. package/src/lib/jobs/ai-job-page-step.js +18 -4
  31. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  32. package/src/lib/jobs/ai-job-plan-step.d.ts +40 -1
  33. package/src/lib/jobs/ai-job-plan-step.js +121 -16
  34. package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
  35. package/src/lib/jobs/ai-job-site-content.d.ts +6 -6
  36. package/src/lib/jobs/ai-job-site-content.js +6 -12
  37. package/src/lib/jobs/ai-job-site-content.js.map +1 -1
  38. package/src/lib/jobs/ai-job-site-step.d.ts +11 -0
  39. package/src/lib/jobs/ai-job-site-step.js +96 -44
  40. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  41. package/src/lib/jobs/ai-jobs-notify.d.ts +14 -4
  42. package/src/lib/jobs/ai-jobs-notify.js +70 -4
  43. package/src/lib/jobs/ai-jobs-notify.js.map +1 -1
  44. package/src/lib/jobs/ai-jobs.d.ts +22 -4
  45. package/src/lib/jobs/ai-jobs.js +47 -12
  46. package/src/lib/jobs/ai-jobs.js.map +1 -1
  47. package/src/lib/jobs/ai-layout-stock-photos.d.ts +98 -0
  48. package/src/lib/jobs/ai-layout-stock-photos.js +248 -0
  49. package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -0
  50. package/src/lib/jobs/ai-site-publish.d.ts +11 -0
  51. package/src/lib/jobs/ai-site-publish.js +31 -1
  52. package/src/lib/jobs/ai-site-publish.js.map +1 -1
  53. package/src/lib/jobs/fixtures/ai-juniper-portfolio-page-recording.d.ts +151 -0
  54. package/src/lib/jobs/fixtures/ai-juniper-portfolio-page-recording.js +183 -0
  55. package/src/lib/jobs/fixtures/ai-juniper-portfolio-page-recording.js.map +1 -0
  56. package/src/lib/jobs/fixtures/ai-slow-roads-site-plan-recording.d.ts +27 -0
  57. package/src/lib/jobs/fixtures/ai-slow-roads-site-plan-recording.js +192 -0
  58. package/src/lib/jobs/fixtures/ai-slow-roads-site-plan-recording.js.map +1 -0
  59. package/src/lib/jobs/fixtures/ai-yoga-site-plan-recording.d.ts +27 -0
  60. package/src/lib/jobs/fixtures/ai-yoga-site-plan-recording.js +222 -0
  61. package/src/lib/jobs/fixtures/ai-yoga-site-plan-recording.js.map +1 -0
  62. package/src/lib/layout-language/ai-layout-compiler.d.ts +29 -0
  63. package/src/lib/layout-language/ai-layout-compiler.js +698 -12
  64. package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
  65. package/src/lib/layout-language/ai-layout-design.d.ts +107 -0
  66. package/src/lib/layout-language/ai-layout-design.js +197 -0
  67. package/src/lib/layout-language/ai-layout-design.js.map +1 -0
  68. package/src/lib/layout-language/ai-layout-frame.d.ts +6 -0
  69. package/src/lib/layout-language/ai-layout-frame.js +22 -6
  70. package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
  71. package/src/lib/layout-language/ai-layout-language.d.ts +2 -0
  72. package/src/lib/layout-language/ai-layout-language.js +15 -1
  73. package/src/lib/layout-language/ai-layout-language.js.map +1 -1
  74. package/src/lib/layout-language/ai-layout-links.d.ts +11 -0
  75. package/src/lib/layout-language/ai-layout-links.js +4 -0
  76. package/src/lib/layout-language/ai-layout-links.js.map +1 -1
  77. package/src/lib/layout-language/ai-layout-pictures.d.ts +11 -5
  78. package/src/lib/layout-language/ai-layout-pictures.js +80 -17
  79. package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
  80. package/src/lib/model/ai-job-notice.d.ts +9 -1
  81. package/src/lib/model/ai-job-notice.js +23 -0
  82. package/src/lib/model/ai-job-notice.js.map +1 -1
  83. package/src/lib/model/ai-plan-capabilities.d.ts +23 -0
  84. package/src/lib/model/ai-plan-capabilities.js +5 -0
  85. package/src/lib/model/ai-plan-capabilities.js.map +1 -1
  86. package/src/lib/model/ai-site-build-progress.d.ts +12 -2
  87. package/src/lib/model/ai-site-build-progress.js +78 -4
  88. package/src/lib/model/ai-site-build-progress.js.map +1 -1
  89. package/src/lib/model/ai-site-job.d.ts +209 -22
  90. package/src/lib/model/ai-site-job.js +247 -20
  91. package/src/lib/model/ai-site-job.js.map +1 -1
  92. package/src/lib/model/ai-site-kinds.js +6 -1
  93. package/src/lib/model/ai-site-kinds.js.map +1 -1
  94. package/src/lib/model/ai-site-look.d.ts +21 -0
  95. package/src/lib/model/ai-site-look.js +63 -14
  96. package/src/lib/model/ai-site-look.js.map +1 -1
  97. package/src/lib/operator-alerts.d.ts +18 -0
  98. package/src/lib/operator-alerts.js +42 -0
  99. package/src/lib/operator-alerts.js.map +1 -1
  100. package/src/lib/runtime/ai-doctrine-validators.d.ts +39 -1
  101. package/src/lib/runtime/ai-doctrine-validators.js +236 -6
  102. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  103. package/src/lib/runtime/ai-doctrine.js +5 -3
  104. package/src/lib/runtime/ai-doctrine.js.map +1 -1
  105. package/src/lib/runtime/ai-palette.generated.d.ts +2 -0
  106. package/src/lib/runtime/ai-palette.generated.js +18 -2
  107. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  108. package/src/lib/server/ai-jobs-resume.js.map +1 -1
  109. package/src/lib/server/ai-jobs-route.js +15 -3
  110. package/src/lib/server/ai-jobs-route.js.map +1 -1
  111. package/src/lib/server/assist-edit.js +5 -2
  112. package/src/lib/server/assist-edit.js.map +1 -1
  113. package/src/lib/usage/free-ai-credits-left.d.ts +54 -0
  114. package/src/lib/usage/free-ai-credits-left.js +62 -0
  115. package/src/lib/usage/free-ai-credits-left.js.map +1 -0
@@ -200,15 +200,31 @@ export type AiJobPauseReader = (input: {
200
200
  export declare function registerAiJobPauseReader(reader: AiJobPauseReader | null): void;
201
201
  /**
202
202
  * A change a person is told about: the job's plan waits for them (or a step
203
- * stopped for their decision), the job finished, or it stopped.
203
+ * stopped for their decision), the job finished, it stopped, or it PAUSED
204
+ * because the meter refused its next step (AGL-3660) — out of credits, at a
205
+ * cap — which a person resolves by getting more and resuming the same job.
204
206
  */
205
- export type AiJobTransition = 'needs-review' | 'done' | 'failed';
207
+ export type AiJobTransition = 'needs-review' | 'done' | 'failed' | 'paused';
208
+ /**
209
+ * Why a job failed, for staff only (never shown to the customer): whether
210
+ * the failure was ours — a provider error, a step that produced nothing, a
211
+ * build that delivered nothing — rather than the model declining the brief
212
+ * or the site having AI switched off, and what the runner actually said.
213
+ */
214
+ export interface AiJobFailureCause {
215
+ ours: boolean;
216
+ stepIndex: number | null;
217
+ error: string | null;
218
+ }
206
219
  export type AiJobTransitionListener = (input: {
207
220
  job: AiJob;
208
221
  to: AiJobTransition;
222
+ /** Present on `failed` only. */
223
+ failure?: AiJobFailureCause;
209
224
  }) => Promise<void> | void;
210
225
  /**
211
- * The listener told each time a job ENTERS `needs_review`, `done` or `failed`
226
+ * The listener told each time a job ENTERS `needs_review`, `done` or `failed`,
227
+ * or is paused by the meter (`needs_input`, once per reason)
212
228
  * — once per entry, from the write that made it, so a stream that re-reads
213
229
  * the job or a beat that sees it again tells nobody twice. Registered by its
214
230
  * own module (`ai-jobs-notify.ts`) from the console's server surface, as the
@@ -418,6 +434,7 @@ export declare function completeAiJob(firestore: Firestore, orgId: string, jobId
418
434
  export declare function failAiJob(firestore: Firestore, orgId: string, jobId: string, message: string, detail?: {
419
435
  stepIndex?: number;
420
436
  error?: unknown;
437
+ ours?: boolean;
421
438
  }, now?: Date): Promise<AiJob>;
422
439
  /**
423
440
  * Park the job for something only the workspace can change. The running
@@ -487,7 +504,8 @@ export declare function retryAiBuildJob(firestore: Firestore, orgId: string, job
487
504
  }>;
488
505
  /**
489
506
  * Resume a job that stopped for a person (AGL-2935): confirm its plan, or
490
- * try again the step whose answer broke a building rule. One transaction,
507
+ * try again the step whose answer broke a building rule — or carry on a job
508
+ * the meter paused, from its paused step (AGL-3660). One transaction,
491
509
  * so two confirmations land once; anything but a `needs_review` job comes
492
510
  * back unchanged. The pending step's attempts start over — a person asking
493
511
  * again is not a provider failing again — and a confirmed plan with no step
@@ -242,7 +242,8 @@ let pauseReader = null;
242
242
  }
243
243
  let transitionListener = null;
244
244
  /**
245
- * The listener told each time a job ENTERS `needs_review`, `done` or `failed`
245
+ * The listener told each time a job ENTERS `needs_review`, `done` or `failed`,
246
+ * or is paused by the meter (`needs_input`, once per reason)
246
247
  * — once per entry, from the write that made it, so a stream that re-reads
247
248
  * the job or a beat that sees it again tells nobody twice. Registered by its
248
249
  * own module (`ai-jobs-notify.ts`) from the console's server surface, as the
@@ -254,10 +255,14 @@ let transitionListener = null;
254
255
  /** Whether a transition listener is registered: what a surface that runs jobs must have. */ export function aiJobTransitionListenerRegistered() {
255
256
  return transitionListener !== null;
256
257
  }
257
- /** Tells the listener; a listener that throws never fails the write it follows. */ async function announceAiJobTransition(job, to) {
258
+ /** Tells the listener; a listener that throws never fails the write it follows. */ async function announceAiJobTransition(job, to, failure) {
258
259
  if (!transitionListener) return;
259
260
  try {
260
- await transitionListener({
261
+ await transitionListener(failure ? {
262
+ job,
263
+ to,
264
+ failure
265
+ } : {
261
266
  job,
262
267
  to
263
268
  });
@@ -850,7 +855,14 @@ async function transition(firestore, orgId, jobId, apply) {
850
855
  }) : step),
851
856
  updatedAt: now
852
857
  });
853
- if (changed) await announceAiJobTransition(job, 'failed');
858
+ if (changed) {
859
+ var _ref2, _ref3;
860
+ await announceAiJobTransition(job, 'failed', {
861
+ ours: (_ref2 = detail == null ? void 0 : detail.ours) != null ? _ref2 : false,
862
+ stepIndex: (_ref3 = detail == null ? void 0 : detail.stepIndex) != null ? _ref3 : null,
863
+ error: (detail == null ? void 0 : detail.error) instanceof Error ? detail.error.message : (detail == null ? void 0 : detail.error) == null ? null : String(detail.error)
864
+ });
865
+ }
854
866
  return job;
855
867
  }
856
868
  /**
@@ -984,7 +996,9 @@ async function transition(firestore, orgId, jobId, apply) {
984
996
  now
985
997
  }));
986
998
  }
987
- return failAiJob(firestore, orgId, jobId, message, detail, now);
999
+ return failAiJob(firestore, orgId, jobId, message, _extends({}, detail, {
1000
+ ours: true
1001
+ }), now);
988
1002
  }
989
1003
  // ── A build's settlement (AGL-3616) ──────────────────────────────────────
990
1004
  /**
@@ -1066,16 +1080,16 @@ async function transition(firestore, orgId, jobId, apply) {
1066
1080
  * planning is charged and the job is `done`, failed items and all; nothing
1067
1081
  * delivered, and its planning is given back too and the job is `failed`.
1068
1082
  */ export async function settleAiBuildJob(firestore, orgId, jobId, input) {
1069
- var _job_items, _job_items1, _job_items2, _ref, _ref1;
1083
+ var _job_items, _job_items1, _job_items2, _ref, _ref1, _job_items3;
1070
1084
  var _job_orchestration;
1071
1085
  const { now } = input;
1072
1086
  let job = await getAiJob(firestore, orgId, jobId);
1073
1087
  if (!job || isAiJobTerminal(job.status)) return job;
1074
1088
  const stopped = input.stopped;
1075
1089
  if (stopped && ((_job_items = job.items) != null ? _job_items : []).some((row)=>row.status === 'pending' || row.status === 'running')) {
1076
- var _job_items3;
1090
+ var _job_items4;
1077
1091
  const refunds = new Map();
1078
- for (const row of (_job_items3 = job.items) != null ? _job_items3 : []){
1092
+ for (const row of (_job_items4 = job.items) != null ? _job_items4 : []){
1079
1093
  var _row_attemptCredits;
1080
1094
  if (row.status !== 'running') continue;
1081
1095
  const refund = await refundBuildCredits(firestore, orgId, job, {
@@ -1141,8 +1155,8 @@ async function transition(firestore, orgId, jobId, apply) {
1141
1155
  // was not built, and its Try again starts over from its answers.
1142
1156
  const parts = new Map();
1143
1157
  if (job.kind === 'site') {
1144
- var _job_items4;
1145
- for (const row of (_job_items4 = job.items) != null ? _job_items4 : []){
1158
+ var _job_items5;
1159
+ for (const row of (_job_items5 = job.items) != null ? _job_items5 : []){
1146
1160
  var _row_creditsSpent, _row_creditsRefunded, _ref2;
1147
1161
  const owed = Math.max(0, ((_row_creditsSpent = row.creditsSpent) != null ? _row_creditsSpent : 0) - ((_row_creditsRefunded = row.creditsRefunded) != null ? _row_creditsRefunded : 0));
1148
1162
  if (owed <= 0 || row.status === 'failed') continue;
@@ -1193,7 +1207,12 @@ async function transition(firestore, orgId, jobId, apply) {
1193
1207
  });
1194
1208
  const nothing = job.kind === 'site' ? AI_SITE_GUIDED_BUILD_FAILED_COPY : AI_BUILD_NOTHING_BUILT_COPY;
1195
1209
  return failAiJob(firestore, orgId, jobId, (_ref1 = stopped == null ? void 0 : stopped.message) != null ? _ref1 : nothing, {
1196
- error: 'build delivered nothing'
1210
+ error: 'build delivered nothing',
1211
+ // Ours unless every item that failed was the model declining (AGL-3616).
1212
+ ours: Boolean(stopped) || ((_job_items3 = job.items) != null ? _job_items3 : []).some((row)=>{
1213
+ var _row_failure;
1214
+ return row.status === 'failed' && ((_row_failure = row.failure) == null ? void 0 : _row_failure.ours);
1215
+ })
1197
1216
  }, now);
1198
1217
  }
1199
1218
  /**
@@ -1238,7 +1257,8 @@ async function transition(firestore, orgId, jobId, apply) {
1238
1257
  }
1239
1258
  /**
1240
1259
  * Resume a job that stopped for a person (AGL-2935): confirm its plan, or
1241
- * try again the step whose answer broke a building rule. One transaction,
1260
+ * try again the step whose answer broke a building rule — or carry on a job
1261
+ * the meter paused, from its paused step (AGL-3660). One transaction,
1242
1262
  * so two confirmations land once; anything but a `needs_review` job comes
1243
1263
  * back unchanged. The pending step's attempts start over — a person asking
1244
1264
  * again is not a provider failing again — and a confirmed plan with no step
@@ -1249,6 +1269,18 @@ async function transition(firestore, orgId, jobId, apply) {
1249
1269
  */ export async function resumeAiJob(firestore, orgId, jobId, actor, now = new Date(), options = {}) {
1250
1270
  return transition(firestore, orgId, jobId, (current)=>{
1251
1271
  var _current_review, _current_inputs;
1272
+ // A job the meter paused (AGL-3660) carries on from the step it paused
1273
+ // on: that step is already pending, so it is queued again with nothing
1274
+ // else changed. Whether the credits are there now is the reservation's
1275
+ // to say, at the door and again at the step.
1276
+ if (current.status === 'needs_input') {
1277
+ return {
1278
+ status: 'queued',
1279
+ error: null,
1280
+ lease: null,
1281
+ updatedAt: now
1282
+ };
1283
+ }
1252
1284
  if (current.status !== 'needs_review') return null;
1253
1285
  const steps = current.steps.map((step)=>step.status === 'pending' ? _extends({}, step, {
1254
1286
  attempts: 0
@@ -1510,6 +1542,9 @@ async function transition(firestore, orgId, jobId, apply) {
1510
1542
  kind: job.kind,
1511
1543
  reason: reservation.refusedBy
1512
1544
  });
1545
+ // The person is told once per pause (AGL-3660), not once an hour: a
1546
+ // job the beat re-queues and the meter refuses again keeps its reason.
1547
+ await announceAiJobTransition(parked, 'paused');
1513
1548
  }
1514
1549
  return {
1515
1550
  outcome: 'needs_input',