@aglyn/plugins-ai 1.0.0-beta.227 → 1.0.0-beta.229
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/README.md +1 -1
- package/package.json +17 -17
- package/src/lib/components/ai-brief-dialog.component.js +1 -1
- package/src/lib/components/ai-brief-dialog.component.js.map +1 -1
- package/src/lib/components/ai-describe-automation.component.js +7 -2
- package/src/lib/components/ai-describe-automation.component.js.map +1 -1
- package/src/lib/components/ai-describe-button.component.js +6 -1
- package/src/lib/components/ai-describe-button.component.js.map +1 -1
- package/src/lib/components/ai-describe-page.component.d.ts +1 -1
- package/src/lib/components/ai-describe-page.component.js +1 -1
- package/src/lib/components/ai-describe-page.component.js.map +1 -1
- package/src/lib/components/ai-job-events.d.ts +7 -1
- package/src/lib/components/ai-job-events.js +4 -2
- package/src/lib/components/ai-job-events.js.map +1 -1
- package/src/lib/components/ai-job-site.d.ts +22 -0
- package/src/lib/components/ai-job-site.js +73 -0
- package/src/lib/components/ai-job-site.js.map +1 -0
- package/src/lib/components/ai-jobs-list-page.component.d.ts +23 -0
- package/src/lib/components/ai-jobs-list-page.component.js +314 -0
- package/src/lib/components/ai-jobs-list-page.component.js.map +1 -0
- package/src/lib/components/ai-jobs-page.component.d.ts +7 -0
- package/src/lib/components/ai-jobs-page.component.js +30 -0
- package/src/lib/components/ai-jobs-page.component.js.map +1 -0
- package/src/lib/components/ai-page-brief-dialog.component.d.ts +1 -1
- package/src/lib/components/ai-page-brief-dialog.component.js.map +1 -1
- package/src/lib/components/ai-site-build-page.component.d.ts +31 -3
- package/src/lib/components/ai-site-build-page.component.js +394 -243
- package/src/lib/components/ai-site-build-page.component.js.map +1 -1
- package/src/lib/components/ai-site-start-card.component.d.ts +18 -1
- package/src/lib/components/ai-site-start-card.component.js +27 -15
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/components/assist-jobs-drawer.component.d.ts +11 -0
- package/src/lib/components/assist-jobs-drawer.component.js +37 -1
- package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
- package/src/lib/components/assist-panel.component.js +9 -4
- package/src/lib/components/assist-panel.component.js.map +1 -1
- package/src/lib/jobs/ai-job-draft-ids.d.ts +6 -0
- package/src/lib/jobs/ai-job-draft-ids.js +9 -0
- package/src/lib/jobs/ai-job-draft-ids.js.map +1 -1
- package/src/lib/jobs/ai-job-drafts.d.ts +7 -0
- package/src/lib/jobs/ai-job-drafts.js +16 -7
- package/src/lib/jobs/ai-job-drafts.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-site-pages.d.ts +70 -0
- package/src/lib/jobs/ai-job-layout-site-pages.js +216 -0
- package/src/lib/jobs/ai-job-layout-site-pages.js.map +1 -0
- package/src/lib/jobs/ai-job-layout-step.d.ts +2 -2
- package/src/lib/jobs/ai-job-layout-step.js +21 -2
- package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
- package/src/lib/jobs/ai-job-page-sections.d.ts +6 -5
- package/src/lib/jobs/ai-job-page-sections.js +3 -3
- package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
- package/src/lib/jobs/ai-job-page-step.d.ts +19 -1
- package/src/lib/jobs/ai-job-page-step.js +50 -8
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.js +7 -2
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-step.d.ts +21 -0
- package/src/lib/jobs/ai-job-site-step.js +103 -17
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/ai-job-text-step.d.ts +7 -1
- package/src/lib/jobs/ai-job-text-step.js.map +1 -1
- package/src/lib/jobs/ai-jobs.d.ts +19 -1
- package/src/lib/jobs/ai-jobs.js +130 -53
- package/src/lib/jobs/ai-jobs.js.map +1 -1
- package/src/lib/jobs/ai-site-publish.d.ts +98 -0
- package/src/lib/jobs/ai-site-publish.js +372 -0
- package/src/lib/jobs/ai-site-publish.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-page-briefs.d.ts +7 -6
- package/src/lib/jobs/fixtures/ai-page-briefs.js +23 -56
- package/src/lib/jobs/fixtures/ai-page-briefs.js.map +1 -1
- package/src/lib/model/ai-job-failure-copy.d.ts +20 -1
- package/src/lib/model/ai-job-failure-copy.js +28 -1
- package/src/lib/model/ai-job-failure-copy.js.map +1 -1
- package/src/lib/model/ai-job-notice.d.ts +6 -1
- package/src/lib/model/ai-job-notice.js +29 -3
- package/src/lib/model/ai-job-notice.js.map +1 -1
- package/src/lib/model/ai-jobs.types.d.ts +34 -0
- package/src/lib/model/ai-jobs.types.js.map +1 -1
- package/src/lib/model/ai-plan-capabilities.d.ts +25 -10
- package/src/lib/model/ai-plan-capabilities.js +15 -2
- package/src/lib/model/ai-plan-capabilities.js.map +1 -1
- package/src/lib/model/ai-site-build-progress.d.ts +25 -1
- package/src/lib/model/ai-site-build-progress.js +129 -15
- package/src/lib/model/ai-site-build-progress.js.map +1 -1
- package/src/lib/model/ai-site-start-seo.d.ts +35 -0
- package/src/lib/model/ai-site-start-seo.js +145 -7
- package/src/lib/model/ai-site-start-seo.js.map +1 -1
- package/src/lib/model/ai-site-start.d.ts +14 -0
- package/src/lib/model/ai-site-start.js +43 -0
- package/src/lib/model/ai-site-start.js.map +1 -1
- package/src/lib/plugin.js +18 -10
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +16 -12
- package/src/lib/runtime/ai-doctrine-validators.js +19 -36
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.d.ts +6 -0
- package/src/lib/runtime/ai-doctrine.js +6 -2
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-eval-live.d.ts +1 -1
- package/src/lib/runtime/ai-eval-live.js +1 -1
- package/src/lib/runtime/ai-eval-live.js.map +1 -1
- package/src/lib/server/ai-jobs-live-sites.d.ts +26 -0
- package/src/lib/server/ai-jobs-live-sites.js +58 -0
- package/src/lib/server/ai-jobs-live-sites.js.map +1 -0
- package/src/lib/server/ai-jobs-route.js +22 -3
- package/src/lib/server/ai-jobs-route.js.map +1 -1
- package/src/lib/usage/assist-job-refund.d.ts +3 -2
- package/src/lib/usage/assist-job-refund.js +2 -1
- package/src/lib/usage/assist-job-refund.js.map +1 -1
package/src/lib/jobs/ai-jobs.js
CHANGED
|
@@ -43,6 +43,8 @@ import { assistExchangeExpiry, assistUsageDay, assistUsageMonth, recordAssistCos
|
|
|
43
43
|
import { aiJobRefundCredits, refundJobCredits } from "../usage/assist-job-refund.js";
|
|
44
44
|
import { freeAssistAccount } from "../usage/assist-free-taste.js";
|
|
45
45
|
import { aiJobAutoConfirms } from "./ai-job-auto-confirm.js";
|
|
46
|
+
import { AI_SITE_GUIDED_BUILD_FAILED_COPY } from "../model/ai-job-failure-copy.js";
|
|
47
|
+
import { aiSiteStartInputsOf } from "../model/ai-site-start.js";
|
|
46
48
|
import { addAdminAudit } from "@aglyn/tenant-data-admin/server/admin-audit-write";
|
|
47
49
|
/**
|
|
48
50
|
* AI generation jobs — the Firestore state machine (AGL-2904).
|
|
@@ -425,14 +427,38 @@ export async function getAiJob(firestore, orgId, jobId) {
|
|
|
425
427
|
else if ((_options_statuses = options.statuses) == null ? void 0 : _options_statuses.length) query = query.where('status', 'in', [
|
|
426
428
|
...options.statuses
|
|
427
429
|
]);
|
|
428
|
-
|
|
429
|
-
|
|
430
|
+
else if (options.hostId) query = query.where('hostId', '==', options.hostId);
|
|
431
|
+
const read = async (from, count)=>(await from.orderBy('createdAt', 'desc').limit(count).get()).docs.map((doc)=>jobFrom(doc)).filter((job)=>job !== null);
|
|
432
|
+
try {
|
|
433
|
+
return await read(query, limit);
|
|
434
|
+
} catch (error) {
|
|
435
|
+
var _options_statuses1;
|
|
436
|
+
// A site's list while its (hostId, createdAt) index is still building
|
|
437
|
+
// (AGL-3596): Firestore refuses the query with FAILED_PRECONDITION until
|
|
438
|
+
// the index is ready, which answered the site's AI jobs page with a 500.
|
|
439
|
+
// The org's own newest jobs — the index every org list already uses —
|
|
440
|
+
// filtered to the site in memory stand in, bounded to
|
|
441
|
+
// `AI_JOBS_HOST_FALLBACK_SCAN` jobs, so a site whose jobs are older than
|
|
442
|
+
// that lists fewer until the index is ready rather than none.
|
|
443
|
+
if (!options.hostId || options.status || ((_options_statuses1 = options.statuses) == null ? void 0 : _options_statuses1.length) || !isFailedPrecondition(error)) throw error;
|
|
444
|
+
console.warn('ai jobs: host index not ready; listing from the org', {
|
|
445
|
+
orgId,
|
|
446
|
+
hostId: options.hostId
|
|
447
|
+
});
|
|
448
|
+
const recent = await read(jobsCollection(firestore, orgId), AI_JOBS_HOST_FALLBACK_SCAN);
|
|
449
|
+
return recent.filter((job)=>job.hostId === options.hostId).slice(0, limit);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
/** The most of an org's newest jobs a site's list scans while its index builds (AGL-3596). */ export const AI_JOBS_HOST_FALLBACK_SCAN = 300;
|
|
453
|
+
/** Firestore's "this query needs an index that is not ready" (gRPC 9). */ function isFailedPrecondition(error) {
|
|
454
|
+
const code = error == null ? void 0 : error.code;
|
|
455
|
+
return code === 9 || code === 'failed-precondition' || code === 'FAILED_PRECONDITION';
|
|
430
456
|
}
|
|
431
457
|
/** The wire form. `running` is the lease, read against `now`. */ export function aiJobSummary(job, now = new Date()) {
|
|
432
458
|
var _job_hostId, _job_steps, _job_outputs, _job_creditsReserved, _job_creditsSpent, _job_refundedCredits, _toIso, _toIso1, _job_error, _job_plan_labels, _job_plan_confirmedBy, _job_review, _job_applied_versions, _job_applied_staged;
|
|
433
459
|
var _job_lease, _job_inputs;
|
|
434
460
|
const leaseUntil = toMillis((_job_lease = job.lease) == null ? void 0 : _job_lease.until);
|
|
435
|
-
return {
|
|
461
|
+
return _extends({
|
|
436
462
|
id: job.$id,
|
|
437
463
|
orgId: job.orgId,
|
|
438
464
|
hostId: (_job_hostId = job.hostId) != null ? _job_hostId : null,
|
|
@@ -473,7 +499,11 @@ export async function getAiJob(firestore, orgId, jobId) {
|
|
|
473
499
|
versions: (_job_applied_versions = job.applied.versions) != null ? _job_applied_versions : {},
|
|
474
500
|
staged: (_job_applied_staged = job.applied.staged) != null ? _job_applied_staged : []
|
|
475
501
|
} : null
|
|
476
|
-
}
|
|
502
|
+
}, job.sitePublish ? {
|
|
503
|
+
sitePublish: job.sitePublish
|
|
504
|
+
} : {}, job.kind === 'site' ? {
|
|
505
|
+
siteInputs: aiSiteStartInputsOf(job.inputs)
|
|
506
|
+
} : {});
|
|
477
507
|
}
|
|
478
508
|
function leaseIsLive(job, owner, nowMs) {
|
|
479
509
|
const lease = job.lease;
|
|
@@ -688,6 +718,8 @@ function nextStepIndex(job) {
|
|
|
688
718
|
lease: null
|
|
689
719
|
} : {}, input.plan ? {
|
|
690
720
|
plan: input.plan
|
|
721
|
+
} : {}, input.sitePublish ? {
|
|
722
|
+
sitePublish: input.sitePublish
|
|
691
723
|
} : {}, parksForReview && input.review ? {
|
|
692
724
|
review: input.review,
|
|
693
725
|
error: input.review.reason === 'plan' ? null : input.review.message
|
|
@@ -702,10 +734,11 @@ function nextStepIndex(job) {
|
|
|
702
734
|
parked: parksForReview && job.status !== 'needs_review'
|
|
703
735
|
};
|
|
704
736
|
});
|
|
705
|
-
if (recorded.parked) await announceAiJobTransition(recorded.job, 'needs-review');
|
|
737
|
+
if (recorded.parked && !input.quiet) await announceAiJobTransition(recorded.job, 'needs-review');
|
|
706
738
|
return {
|
|
707
739
|
job: recorded.job,
|
|
708
|
-
remaining: recorded.remaining
|
|
740
|
+
remaining: recorded.remaining,
|
|
741
|
+
parked: recorded.parked
|
|
709
742
|
};
|
|
710
743
|
}
|
|
711
744
|
async function transition(firestore, orgId, jobId, apply) {
|
|
@@ -863,6 +896,21 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
863
896
|
return job;
|
|
864
897
|
}
|
|
865
898
|
}
|
|
899
|
+
/**
|
|
900
|
+
* A failure on our side, given back BEFORE the job is failed (AGL-3596): the
|
|
901
|
+
* failed state is the last one a follower of the job reads and the one its
|
|
902
|
+
* notice is written from, so it already carries `refundedCredits`. A job that
|
|
903
|
+
* ended meanwhile — a person's cancel, which pays for what ran — is left as it
|
|
904
|
+
* ended and given nothing back.
|
|
905
|
+
*/ async function failOurFailure(firestore, orgId, jobId, message, detail, refund, now) {
|
|
906
|
+
const current = await getAiJob(firestore, orgId, jobId);
|
|
907
|
+
if (current && !isAiJobTerminal(current.status)) {
|
|
908
|
+
await refundOurFailure(firestore, orgId, current, _extends({}, refund, {
|
|
909
|
+
now
|
|
910
|
+
}));
|
|
911
|
+
}
|
|
912
|
+
return failAiJob(firestore, orgId, jobId, message, detail, now);
|
|
913
|
+
}
|
|
866
914
|
/**
|
|
867
915
|
* Resume a job that stopped for a person (AGL-2935): confirm its plan, or
|
|
868
916
|
* try again the step whose answer broke a building rule. One transaction,
|
|
@@ -1000,7 +1048,7 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
1000
1048
|
* round.
|
|
1001
1049
|
*/ export async function runAiJobStep(firestore, orgId, jobId, options) {
|
|
1002
1050
|
var _options_now, _step_attempts, _options_org, _data, _ref, _ref1, _outcome_effort, _step_passes, _options_actor;
|
|
1003
|
-
var _reservation_allotment, _reservation_allotment1;
|
|
1051
|
+
var _reservation_allotment, _reservation_allotment1, _outcome_review;
|
|
1004
1052
|
const now = (_options_now = options.now) != null ? _options_now : new Date();
|
|
1005
1053
|
// A reservation the caller took before the job existed is a message
|
|
1006
1054
|
// counted against the org; a step that fails before the provider is
|
|
@@ -1041,32 +1089,28 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
1041
1089
|
const runner = aiJobRunnerForStep(job.kind, step.name);
|
|
1042
1090
|
if (!runner) {
|
|
1043
1091
|
await releaseHeld();
|
|
1044
|
-
const failed = await failAiJob(firestore, orgId, jobId, AI_JOB_NOT_AVAILABLE_COPY, {
|
|
1045
|
-
stepIndex,
|
|
1046
|
-
error: `no runner registered for kind ${job.kind}`
|
|
1047
|
-
}, now);
|
|
1048
1092
|
return {
|
|
1049
1093
|
outcome: 'failed',
|
|
1050
|
-
job: await
|
|
1094
|
+
job: await failOurFailure(firestore, orgId, jobId, AI_JOB_NOT_AVAILABLE_COPY, {
|
|
1095
|
+
stepIndex,
|
|
1096
|
+
error: `no runner registered for kind ${job.kind}`
|
|
1097
|
+
}, {
|
|
1051
1098
|
reason: 'unavailable',
|
|
1052
|
-
stepCredits: 0
|
|
1053
|
-
|
|
1054
|
-
})
|
|
1099
|
+
stepCredits: 0
|
|
1100
|
+
}, now)
|
|
1055
1101
|
};
|
|
1056
1102
|
}
|
|
1057
1103
|
if (((_step_attempts = step.attempts) != null ? _step_attempts : 0) > AI_JOB_STEP_MAX_ATTEMPTS) {
|
|
1058
1104
|
await releaseHeld();
|
|
1059
|
-
const failed = await failAiJob(firestore, orgId, jobId, AI_UPSTREAM_FAILURE_COPY, {
|
|
1060
|
-
stepIndex,
|
|
1061
|
-
error: `step ${step.name} exhausted ${AI_JOB_STEP_MAX_ATTEMPTS} attempts`
|
|
1062
|
-
}, now);
|
|
1063
1105
|
return {
|
|
1064
1106
|
outcome: 'failed',
|
|
1065
|
-
job: await
|
|
1107
|
+
job: await failOurFailure(firestore, orgId, jobId, AI_UPSTREAM_FAILURE_COPY, {
|
|
1108
|
+
stepIndex,
|
|
1109
|
+
error: `step ${step.name} exhausted ${AI_JOB_STEP_MAX_ATTEMPTS} attempts`
|
|
1110
|
+
}, {
|
|
1066
1111
|
reason: 'timeout',
|
|
1067
|
-
stepCredits: 0
|
|
1068
|
-
|
|
1069
|
-
})
|
|
1112
|
+
stepCredits: 0
|
|
1113
|
+
}, now)
|
|
1070
1114
|
};
|
|
1071
1115
|
}
|
|
1072
1116
|
const org = (_options_org = options.org) != null ? _options_org : (_data = (await firestore.collection('orgs').doc(orgId).get()).data()) != null ? _data : {};
|
|
@@ -1192,18 +1236,16 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
1192
1236
|
job: requeued
|
|
1193
1237
|
};
|
|
1194
1238
|
}
|
|
1195
|
-
const failed = await failAiJob(firestore, orgId, jobId, AI_UPSTREAM_FAILURE_COPY, {
|
|
1196
|
-
stepIndex,
|
|
1197
|
-
error
|
|
1198
|
-
}, now);
|
|
1199
1239
|
return {
|
|
1200
1240
|
outcome: 'failed',
|
|
1201
|
-
job: await
|
|
1241
|
+
job: await failOurFailure(firestore, orgId, jobId, AI_UPSTREAM_FAILURE_COPY, {
|
|
1242
|
+
stepIndex,
|
|
1243
|
+
error
|
|
1244
|
+
}, {
|
|
1202
1245
|
reason: 'provider',
|
|
1203
1246
|
stepCredits: 0,
|
|
1204
|
-
free: (_reservation_free = reservation.free) != null ? _reservation_free : null
|
|
1205
|
-
|
|
1206
|
-
})
|
|
1247
|
+
free: (_reservation_free = reservation.free) != null ? _reservation_free : null
|
|
1248
|
+
}, now)
|
|
1207
1249
|
};
|
|
1208
1250
|
}
|
|
1209
1251
|
const latencyMs = Math.max(0, Date.now() - runStarted);
|
|
@@ -1223,18 +1265,16 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
1223
1265
|
creditsSpent: 0,
|
|
1224
1266
|
error: outcome.failure
|
|
1225
1267
|
}, now);
|
|
1226
|
-
const failed = await failAiJob(firestore, orgId, jobId, outcome.failure, {
|
|
1227
|
-
stepIndex,
|
|
1228
|
-
error: `step failure before the provider: ${outcome.failure}`
|
|
1229
|
-
}, now);
|
|
1230
1268
|
return {
|
|
1231
1269
|
outcome: 'failed',
|
|
1232
|
-
job: await
|
|
1270
|
+
job: await failOurFailure(firestore, orgId, jobId, outcome.failure, {
|
|
1271
|
+
stepIndex,
|
|
1272
|
+
error: `step failure before the provider: ${outcome.failure}`
|
|
1273
|
+
}, {
|
|
1233
1274
|
reason: 'step-failure',
|
|
1234
1275
|
stepCredits: 0,
|
|
1235
|
-
free: (_reservation_free1 = reservation.free) != null ? _reservation_free1 : null
|
|
1236
|
-
|
|
1237
|
-
})
|
|
1276
|
+
free: (_reservation_free1 = reservation.free) != null ? _reservation_free1 : null
|
|
1277
|
+
}, now)
|
|
1238
1278
|
};
|
|
1239
1279
|
}
|
|
1240
1280
|
const tokens = {
|
|
@@ -1298,19 +1338,45 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
1298
1338
|
error: message,
|
|
1299
1339
|
tokens
|
|
1300
1340
|
}, now);
|
|
1301
|
-
const
|
|
1341
|
+
const detail = {
|
|
1302
1342
|
stepIndex,
|
|
1303
1343
|
error: outcome.refused ? 'stop_reason refusal' : `step failure: ${message}`
|
|
1304
|
-
}
|
|
1344
|
+
};
|
|
1305
1345
|
// A model declining the brief is not our failure; a step's own is (AGL-3594).
|
|
1306
1346
|
return {
|
|
1307
1347
|
outcome: 'failed',
|
|
1308
|
-
job: outcome.refused ?
|
|
1348
|
+
job: outcome.refused ? await failAiJob(firestore, orgId, jobId, message, detail, now) : await failOurFailure(firestore, orgId, jobId, message, detail, {
|
|
1309
1349
|
reason: 'step-failure',
|
|
1310
1350
|
stepCredits: credits,
|
|
1311
|
-
free: (_reservation_free3 = reservation.free) != null ? _reservation_free3 : null
|
|
1312
|
-
|
|
1313
|
-
|
|
1351
|
+
free: (_reservation_free3 = reservation.free) != null ? _reservation_free3 : null
|
|
1352
|
+
}, now)
|
|
1353
|
+
};
|
|
1354
|
+
}
|
|
1355
|
+
// A guided site start whose step broke a building rule after its re-ask
|
|
1356
|
+
// fails, given back whole (AGL-3596): the person never saw the plan, so a
|
|
1357
|
+
// review asking them to look at it again is a review of nothing. The rule
|
|
1358
|
+
// and its findings go to the log for staff; the person reads one sentence,
|
|
1359
|
+
// and Try again starts a fresh job.
|
|
1360
|
+
if (((_outcome_review = outcome.review) == null ? void 0 : _outcome_review.reason) === 'doctrine' && aiJobAutoConfirms(job) && step.name !== AI_JOB_PLAN_STEP) {
|
|
1361
|
+
var _outcome_review_findings, _outcome_review_message, _reservation_free4;
|
|
1362
|
+
await recordStep(firestore, orgId, jobId, options.owner, stepIndex, _extends({
|
|
1363
|
+
status: 'failed',
|
|
1364
|
+
creditsSpent: credits,
|
|
1365
|
+
error: AI_SITE_GUIDED_BUILD_FAILED_COPY,
|
|
1366
|
+
outputs: outcome.outputs
|
|
1367
|
+
}, spentNothing ? {} : {
|
|
1368
|
+
tokens
|
|
1369
|
+
}), now);
|
|
1370
|
+
return {
|
|
1371
|
+
outcome: 'failed',
|
|
1372
|
+
job: await failOurFailure(firestore, orgId, jobId, AI_SITE_GUIDED_BUILD_FAILED_COPY, {
|
|
1373
|
+
stepIndex,
|
|
1374
|
+
error: `doctrine refusal after the re-ask: ${JSON.stringify((_outcome_review_findings = outcome.review.findings) != null ? _outcome_review_findings : [])} ${(_outcome_review_message = outcome.review.message) != null ? _outcome_review_message : ''}`
|
|
1375
|
+
}, {
|
|
1376
|
+
reason: 'doctrine-refused',
|
|
1377
|
+
stepCredits: credits,
|
|
1378
|
+
free: (_reservation_free4 = reservation.free) != null ? _reservation_free4 : null
|
|
1379
|
+
}, now)
|
|
1314
1380
|
};
|
|
1315
1381
|
}
|
|
1316
1382
|
// A step that stopped for a person parks the job in the same write that
|
|
@@ -1347,6 +1413,10 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
1347
1413
|
plan: outcome.plan
|
|
1348
1414
|
} : {}, review ? {
|
|
1349
1415
|
review
|
|
1416
|
+
} : {}, outcome.sitePublish ? {
|
|
1417
|
+
sitePublish: outcome.sitePublish
|
|
1418
|
+
} : {}, review ? {
|
|
1419
|
+
quiet: true
|
|
1350
1420
|
} : {}), now);
|
|
1351
1421
|
const actor = (_options_actor = options.actor) != null ? _options_actor : {
|
|
1352
1422
|
uid: job.createdBy
|
|
@@ -1403,7 +1473,7 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
1403
1473
|
};
|
|
1404
1474
|
}
|
|
1405
1475
|
if (review && recorded.job.status === 'needs_review') {
|
|
1406
|
-
var
|
|
1476
|
+
var _reservation_free5;
|
|
1407
1477
|
// Nobody parked the job but its own step, so the row names no actor, as
|
|
1408
1478
|
// the meter's park does.
|
|
1409
1479
|
await logAiJobNeedsInput(orgId, {
|
|
@@ -1413,15 +1483,22 @@ async function transition(firestore, orgId, jobId, apply) {
|
|
|
1413
1483
|
kind: job.kind,
|
|
1414
1484
|
reason: review.reason
|
|
1415
1485
|
});
|
|
1416
|
-
// A plan the plan rules still refused
|
|
1486
|
+
// A plan the plan rules still refused, and a step that still broke a
|
|
1487
|
+
// building rule after its re-ask, are our failures (AGL-3594, AGL-3596):
|
|
1488
|
+
// given back before the person is told, so the notice can say so. Trying
|
|
1489
|
+
// again spends anew, and a second refusal gives back again, within the
|
|
1490
|
+
// day's bound.
|
|
1491
|
+
const ours = outcome.uncredited ? 'plan-refused' : review.reason === 'doctrine' ? 'doctrine-refused' : null;
|
|
1492
|
+
const parked = ours ? await refundOurFailure(firestore, orgId, recorded.job, {
|
|
1493
|
+
reason: ours,
|
|
1494
|
+
stepCredits: credits,
|
|
1495
|
+
free: (_reservation_free5 = reservation.free) != null ? _reservation_free5 : null,
|
|
1496
|
+
now
|
|
1497
|
+
}) : recorded.job;
|
|
1498
|
+
if (recorded.parked) await announceAiJobTransition(parked, 'needs-review');
|
|
1417
1499
|
return {
|
|
1418
1500
|
outcome: 'needs_review',
|
|
1419
|
-
job:
|
|
1420
|
-
reason: 'plan-refused',
|
|
1421
|
-
stepCredits: credits,
|
|
1422
|
-
free: (_reservation_free4 = reservation.free) != null ? _reservation_free4 : null,
|
|
1423
|
-
now
|
|
1424
|
-
}) : recorded.job
|
|
1501
|
+
job: parked
|
|
1425
1502
|
};
|
|
1426
1503
|
}
|
|
1427
1504
|
if (recorded.remaining > 0 || isAiJobTerminal(recorded.job.status)) {
|