@12ui/design 0.2.12 → 0.2.13
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 +9 -0
- package/dist/cli-arguments.d.ts.map +1 -1
- package/dist/cli-arguments.js +1 -0
- package/dist/cli-arguments.js.map +1 -1
- package/dist/cli-image-batch-command.d.ts.map +1 -1
- package/dist/cli-image-batch-command.js +104 -53
- package/dist/cli-image-batch-command.js.map +1 -1
- package/dist/cli-image-batch-materialize.d.ts +27 -0
- package/dist/cli-image-batch-materialize.d.ts.map +1 -0
- package/dist/cli-image-batch-materialize.js +41 -0
- package/dist/cli-image-batch-materialize.js.map +1 -0
- package/dist/cli-image-batch-resume.d.ts +27 -0
- package/dist/cli-image-batch-resume.d.ts.map +1 -0
- package/dist/cli-image-batch-resume.js +158 -0
- package/dist/cli-image-batch-resume.js.map +1 -0
- package/dist/cli-image-command.d.ts.map +1 -1
- package/dist/cli-image-command.js +14 -2
- package/dist/cli-image-command.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/image-generation-batch-attempt.d.ts +28 -0
- package/dist/image-generation-batch-attempt.d.ts.map +1 -0
- package/dist/image-generation-batch-attempt.js +48 -0
- package/dist/image-generation-batch-attempt.js.map +1 -0
- package/dist/image-generation-completion.d.ts +43 -0
- package/dist/image-generation-completion.d.ts.map +1 -0
- package/dist/image-generation-completion.js +54 -0
- package/dist/image-generation-completion.js.map +1 -0
- package/dist/image-generation-fs.d.ts +3 -0
- package/dist/image-generation-fs.d.ts.map +1 -0
- package/dist/image-generation-fs.js +23 -0
- package/dist/image-generation-fs.js.map +1 -0
- package/dist/image-generation-request.d.ts +13 -3
- package/dist/image-generation-request.d.ts.map +1 -1
- package/dist/image-generation-request.js +21 -19
- package/dist/image-generation-request.js.map +1 -1
- package/dist/image-generation-resume.d.ts +36 -0
- package/dist/image-generation-resume.d.ts.map +1 -0
- package/dist/image-generation-resume.js +83 -0
- package/dist/image-generation-resume.js.map +1 -0
- package/dist/image-generation-run.d.ts +11 -0
- package/dist/image-generation-run.d.ts.map +1 -1
- package/dist/image-generation-run.js +23 -9
- package/dist/image-generation-run.js.map +1 -1
- package/dist/image-generation-staging.d.ts +25 -0
- package/dist/image-generation-staging.d.ts.map +1 -0
- package/dist/image-generation-staging.js +80 -0
- package/dist/image-generation-staging.js.map +1 -0
- package/dist/legacy-skill-catalog.d.ts.map +1 -1
- package/dist/legacy-skill-catalog.js +18 -0
- package/dist/legacy-skill-catalog.js.map +1 -1
- package/package.json +1 -1
- package/skills/design/SKILL.md +49 -8
- package/skills/design/references/selection-contract.md +16 -0
- package/skills/design-convert/SKILL.md +17 -1
package/README.md
CHANGED
|
@@ -99,6 +99,15 @@ PNG output, and one stable idempotency key. Per-candidate and batch evidence
|
|
|
99
99
|
records provider-start and completion times. It never retries a candidate or
|
|
100
100
|
switches providers after dispatch.
|
|
101
101
|
|
|
102
|
+
Candidates are written into a hidden staging directory and moved into place only
|
|
103
|
+
once the batch is terminal, so a caller listing the output directory can never
|
|
104
|
+
observe a half-written batch. Completion is published as a
|
|
105
|
+
`generation.complete.json` sentinel beside the candidates, carrying each
|
|
106
|
+
candidate's status, sha256, and byte count. `--resume` recovers an interrupted
|
|
107
|
+
batch: it delivers candidates that were already generated and re-requests only
|
|
108
|
+
those the provider provably never billed, so it can never buy a candidate twice,
|
|
109
|
+
and it refuses a batch that already completed.
|
|
110
|
+
|
|
102
111
|
The single-candidate `image generate` command remains available. Both commands
|
|
103
112
|
resolve authenticated Codex first, then `OPENAI_API_KEY` from the process or
|
|
104
113
|
exactly `<project-root>/.env`. They refuse a Git-tracked `.env`, never store or
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-arguments.d.ts","sourceRoot":"","sources":["../src/cli-arguments.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"cli-arguments.d.ts","sourceRoot":"","sources":["../src/cli-arguments.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;AAarD,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,EAAE,KACb;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAA;CAqBtC,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,OAAO,QAAQ,EAAE,MAAM,MAAM,KAAG,MAAM,GAAG,SAGnE,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,OAAO,QAAQ,EAAE,MAAM,MAAM,KAAG,OAA+B,CAAC"}
|
package/dist/cli-arguments.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-arguments.js","sourceRoot":"","sources":["../src/cli-arguments.ts"],"names":[],"mappings":"AAEA,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;IAC3B,QAAQ;IACR,OAAO;IACP,MAAM;IACN,MAAM;IACN,OAAO;IACP,WAAW;IACX,SAAS;CACV,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,IAAc,EAC0B,EAAE;IAC1C,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,IAAI,KAAK;gBAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC/B,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACjD,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;YACnB,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QAC7B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,KAAK,IAAI,mBAAmB,CAAC,CAAC;QAClF,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACnB,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC5B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAe,EAAE,IAAY,EAAsB,EAAE;IAC9E,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAe,EAAE,IAAY,EAAW,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC"}
|
|
1
|
+
{"version":3,"file":"cli-arguments.js","sourceRoot":"","sources":["../src/cli-arguments.ts"],"names":[],"mappings":"AAEA,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;IAC3B,QAAQ;IACR,OAAO;IACP,MAAM;IACN,MAAM;IACN,OAAO;IACP,QAAQ;IACR,WAAW;IACX,SAAS;CACV,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,IAAc,EAC0B,EAAE;IAC1C,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,IAAI,KAAK;gBAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC/B,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACjD,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;YACnB,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QAC7B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,KAAK,IAAI,mBAAmB,CAAC,CAAC;QAClF,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACnB,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC5B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAe,EAAE,IAAY,EAAsB,EAAE;IAC9E,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAe,EAAE,IAAY,EAAW,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-image-batch-command.d.ts","sourceRoot":"","sources":["../src/cli-image-batch-command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli-image-batch-command.d.ts","sourceRoot":"","sources":["../src/cli-image-batch-command.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAA2B,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAoC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AA+CvE,eAAO,MAAM,oBAAoB,GAC/B,OAAO,QAAQ,EACf,eAAc;IACZ,QAAQ,CAAC,EAAE,OAAO,aAAa,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,sBAAsB,CAAC;CACtC,KACL,OAAO,CAAC,IAAI,CA8Kd,CAAC"}
|
|
@@ -1,57 +1,86 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { mkdir, rename, rm, writeFile } from 'node:fs/promises';
|
|
3
1
|
import path from 'node:path';
|
|
4
|
-
import { stringFlag } from './cli-arguments.js';
|
|
2
|
+
import { booleanFlag, stringFlag } from './cli-arguments.js';
|
|
3
|
+
import { materializeImageBatch, publishImageBatchCompletion, } from './cli-image-batch-materialize.js';
|
|
4
|
+
import { describeBatchRecovery, resumeImageBatchCommand } from './cli-image-batch-resume.js';
|
|
5
|
+
import { imageBatchAttemptPath, readBatchAttempt, writeBatchAttempt, } from './image-generation-batch-attempt.js';
|
|
5
6
|
import { readImageGenerationBatchManifest, resolveImageGenerationBatchRequests, } from './image-generation-batch-manifest.js';
|
|
7
|
+
import { imageGenerationPathExists } from './image-generation-fs.js';
|
|
8
|
+
import { classifyImageGenerationResume, resumeStateSummary, } from './image-generation-resume.js';
|
|
6
9
|
import { dispatchImageGeneration, failImageGenerationBeforeDispatch, markImageGenerationDispatched, reserveImageGeneration, } from './image-generation-run.js';
|
|
7
|
-
import {
|
|
8
|
-
import { summarizeImageGenerationUsage
|
|
9
|
-
import { preflightImageProvider
|
|
10
|
-
const writeBatchAttempt = async (file, attempt, exclusive = false) => {
|
|
11
|
-
await mkdir(path.dirname(file), { recursive: true });
|
|
12
|
-
if (exclusive) {
|
|
13
|
-
await writeFile(file, `${JSON.stringify(attempt, null, 2)}\n`, {
|
|
14
|
-
encoding: 'utf8',
|
|
15
|
-
flag: 'wx',
|
|
16
|
-
mode: 0o600,
|
|
17
|
-
});
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
const temporary = `${file}.${randomUUID()}.tmp`;
|
|
21
|
-
try {
|
|
22
|
-
await writeFile(temporary, `${JSON.stringify(attempt, null, 2)}\n`, {
|
|
23
|
-
encoding: 'utf8',
|
|
24
|
-
flag: 'wx',
|
|
25
|
-
mode: 0o600,
|
|
26
|
-
});
|
|
27
|
-
await rename(temporary, file);
|
|
28
|
-
}
|
|
29
|
-
finally {
|
|
30
|
-
await rm(temporary, { force: true });
|
|
31
|
-
}
|
|
32
|
-
};
|
|
10
|
+
import { imageGenerationSha256, prepareImageGenerationRequest, } from './image-generation-request.js';
|
|
11
|
+
import { summarizeImageGenerationUsage } from './image-generation-usage.js';
|
|
12
|
+
import { preflightImageProvider } from './image-provider-preflight.js';
|
|
33
13
|
const errorMessage = (error) => (error instanceof Error ? error.message : String(error));
|
|
34
14
|
const failReserved = async (reserved, message) => {
|
|
35
15
|
await Promise.allSettled(reserved.map((item) => failImageGenerationBeforeDispatch(item, message)));
|
|
36
16
|
};
|
|
17
|
+
const identities = (requests) => requests.map((request) => ({
|
|
18
|
+
...(request.candidateId ? { candidateId: request.candidateId } : {}),
|
|
19
|
+
outputPath: request.outputPath,
|
|
20
|
+
idempotencyKey: request.idempotencyKey,
|
|
21
|
+
}));
|
|
22
|
+
/**
|
|
23
|
+
* Explain what the existing evidence permits instead of stopping at "evidence
|
|
24
|
+
* exists". A refusal that names no recovery is what turned a finished batch
|
|
25
|
+
* into a dead end for eleven benchmark runs.
|
|
26
|
+
*/
|
|
27
|
+
const existingEvidenceRefusal = async (args) => {
|
|
28
|
+
const states = await Promise.all(args.requests.map((request) => classifyImageGenerationResume({
|
|
29
|
+
outputPath: request.outputPath,
|
|
30
|
+
...(request.candidateId ? { candidateId: request.candidateId } : {}),
|
|
31
|
+
})));
|
|
32
|
+
const summary = resumeStateSummary(states);
|
|
33
|
+
const recoverable = summary.stageable + summary.redispatchable;
|
|
34
|
+
const guidance = recoverable > 0
|
|
35
|
+
? `Re-run the same command with --resume to recover ${recoverable} candidate(s) with no new`
|
|
36
|
+
+ ' spend; it never re-buys a candidate.'
|
|
37
|
+
: summary.unrecoverable > 0
|
|
38
|
+
? 'Nothing can be recovered without new spend; give the affected candidates a new output'
|
|
39
|
+
+ ' path and idempotency key if you accept buying them again.'
|
|
40
|
+
: 'Every candidate is already on disk — read them rather than generating again.';
|
|
41
|
+
return `Image batch attempt evidence already exists at ${args.batchAttemptFile}.`
|
|
42
|
+
+ ` ${describeBatchRecovery(states)}. ${guidance}`;
|
|
43
|
+
};
|
|
37
44
|
export const runImageBatchCommand = async (flags, dependencies = {}) => {
|
|
38
45
|
const manifestFlag = stringFlag(flags, 'manifest')?.trim();
|
|
39
46
|
if (!manifestFlag) {
|
|
40
|
-
throw new Error('Usage: 12ui image generate-batch --manifest <batch.json>');
|
|
47
|
+
throw new Error('Usage: 12ui image generate-batch --manifest <batch.json> [--resume]');
|
|
41
48
|
}
|
|
42
49
|
const manifestPath = path.resolve(manifestFlag);
|
|
43
|
-
const batchAttemptFile =
|
|
44
|
-
|
|
45
|
-
throw new Error(`Image batch attempt evidence already exists at ${batchAttemptFile}`);
|
|
46
|
-
}
|
|
50
|
+
const batchAttemptFile = imageBatchAttemptPath(manifestPath);
|
|
51
|
+
const resumeRequested = booleanFlag(flags, 'resume');
|
|
47
52
|
const { manifest, source } = await readImageGenerationBatchManifest(manifestPath);
|
|
48
53
|
const requests = resolveImageGenerationBatchRequests({ manifest, manifestPath });
|
|
49
|
-
const
|
|
54
|
+
const manifestSha256 = imageGenerationSha256(source);
|
|
55
|
+
const existingBatchAttempt = await readBatchAttempt(batchAttemptFile);
|
|
56
|
+
if (await imageGenerationPathExists(batchAttemptFile)) {
|
|
57
|
+
if (!resumeRequested) {
|
|
58
|
+
throw new Error(await existingEvidenceRefusal({ batchAttemptFile, requests }));
|
|
59
|
+
}
|
|
60
|
+
if (!existingBatchAttempt) {
|
|
61
|
+
throw new Error(`Image batch attempt evidence at ${batchAttemptFile} is unreadable, so no candidate can be`
|
|
62
|
+
+ ' proved unbilled. Inspect it before resuming.');
|
|
63
|
+
}
|
|
64
|
+
if (existingBatchAttempt.manifestSha256 !== manifestSha256) {
|
|
65
|
+
throw new Error(`Refusing to resume: ${manifestPath} has changed since the batch was dispatched`
|
|
66
|
+
+ ` (${existingBatchAttempt.manifestSha256} then, ${manifestSha256} now). A resume must`
|
|
67
|
+
+ ' replay the same candidate identities.');
|
|
68
|
+
}
|
|
69
|
+
await resumeImageBatchCommand({
|
|
70
|
+
manifestPath,
|
|
71
|
+
manifestSha256,
|
|
72
|
+
batchAttemptFile,
|
|
73
|
+
batchAttempt: existingBatchAttempt,
|
|
74
|
+
requests,
|
|
75
|
+
dependencies,
|
|
76
|
+
});
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const prepared = await Promise.all(requests.map((request) => (prepareImageGenerationRequest(request))));
|
|
50
80
|
const preflight = await (dependencies.preflight ?? preflightImageProvider)({
|
|
51
81
|
provider: manifest.provider,
|
|
52
82
|
projectRoot: prepared[0].projectRoot,
|
|
53
83
|
});
|
|
54
|
-
const manifestSha256 = imageGenerationSha256(source);
|
|
55
84
|
const attempt = {
|
|
56
85
|
version: 2,
|
|
57
86
|
status: 'prepared',
|
|
@@ -67,6 +96,28 @@ export const runImageBatchCommand = async (flags, dependencies = {}) => {
|
|
|
67
96
|
preparedAt: new Date().toISOString(),
|
|
68
97
|
};
|
|
69
98
|
await writeBatchAttempt(batchAttemptFile, attempt, true);
|
|
99
|
+
const candidates = identities(prepared);
|
|
100
|
+
const terminate = async (args) => {
|
|
101
|
+
if (args.materialize)
|
|
102
|
+
await materializeImageBatch(candidates);
|
|
103
|
+
const { completionPath } = await publishImageBatchCompletion({
|
|
104
|
+
manifestPath,
|
|
105
|
+
manifestSha256,
|
|
106
|
+
batchAttemptFile,
|
|
107
|
+
provider: attempt.provider,
|
|
108
|
+
model: attempt.model,
|
|
109
|
+
resumed: false,
|
|
110
|
+
status: args.status,
|
|
111
|
+
candidates,
|
|
112
|
+
});
|
|
113
|
+
attempt.status = args.status;
|
|
114
|
+
attempt.completedAt = new Date().toISOString();
|
|
115
|
+
attempt.completionPath = completionPath;
|
|
116
|
+
if (args.errors)
|
|
117
|
+
attempt.errors = args.errors;
|
|
118
|
+
await writeBatchAttempt(batchAttemptFile, attempt);
|
|
119
|
+
return completionPath;
|
|
120
|
+
};
|
|
70
121
|
const reservations = await Promise.allSettled(prepared.map((request) => (reserveImageGeneration({
|
|
71
122
|
request,
|
|
72
123
|
preflight,
|
|
@@ -81,11 +132,12 @@ export const runImageBatchCommand = async (flags, dependencies = {}) => {
|
|
|
81
132
|
if (reservationErrors.length > 0) {
|
|
82
133
|
const message = 'Batch reservation failed before any provider request was started';
|
|
83
134
|
await failReserved(reserved, message);
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
135
|
+
const completionPath = await terminate({
|
|
136
|
+
status: 'failed',
|
|
137
|
+
errors: reservationErrors,
|
|
138
|
+
materialize: false,
|
|
139
|
+
});
|
|
140
|
+
throw new AggregateError(reservationErrors, `${message}. Evidence: ${batchAttemptFile}. Completion sentinel: ${completionPath}`);
|
|
89
141
|
}
|
|
90
142
|
attempt.status = 'dispatched';
|
|
91
143
|
attempt.dispatchedAt = new Date().toISOString();
|
|
@@ -95,32 +147,31 @@ export const runImageBatchCommand = async (flags, dependencies = {}) => {
|
|
|
95
147
|
if (markErrors.length > 0) {
|
|
96
148
|
const message = 'Batch evidence preparation failed before any provider request was started';
|
|
97
149
|
await failReserved(reserved, message);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
150
|
+
const completionPath = await terminate({
|
|
151
|
+
status: 'failed',
|
|
152
|
+
errors: markErrors,
|
|
153
|
+
materialize: false,
|
|
154
|
+
});
|
|
155
|
+
throw new AggregateError(markErrors, `${message}. Evidence: ${batchAttemptFile}. Completion sentinel: ${completionPath}`);
|
|
103
156
|
}
|
|
104
157
|
const settled = await Promise.allSettled(reserved.map((item) => (dispatchImageGeneration(item, { generate: dependencies.generate }))));
|
|
105
158
|
const results = settled.flatMap((result) => (result.status === 'fulfilled' ? [result.value] : []));
|
|
106
159
|
const errors = settled.flatMap((result) => (result.status === 'rejected' ? [errorMessage(result.reason)] : []));
|
|
107
|
-
attempt.completedAt = new Date().toISOString();
|
|
108
160
|
attempt.results = results;
|
|
109
161
|
attempt.accounting = summarizeImageGenerationUsage(reserved.map((item) => item.attempt.usage), preflight.provider);
|
|
110
162
|
if (errors.length > 0) {
|
|
111
|
-
|
|
112
|
-
attempt.errors = errors;
|
|
113
|
-
await writeBatchAttempt(batchAttemptFile, attempt);
|
|
163
|
+
const completionPath = await terminate({ status: 'failed', errors, materialize: true });
|
|
114
164
|
throw new AggregateError(errors, `Image batch finished with ${errors.length} failed candidate(s); no retries or provider`
|
|
115
|
-
+ ` fallback were attempted. Evidence: ${batchAttemptFile}
|
|
165
|
+
+ ` fallback were attempted. Evidence: ${batchAttemptFile}.`
|
|
166
|
+
+ ` Completion sentinel: ${completionPath}`);
|
|
116
167
|
}
|
|
117
|
-
|
|
118
|
-
await writeBatchAttempt(batchAttemptFile, attempt);
|
|
168
|
+
const completionPath = await terminate({ status: 'succeeded', materialize: true });
|
|
119
169
|
console.log(JSON.stringify({
|
|
120
170
|
provider: attempt.provider,
|
|
121
171
|
model: attempt.model,
|
|
122
172
|
manifestPath,
|
|
123
173
|
batchAttemptFile,
|
|
174
|
+
completionPath,
|
|
124
175
|
accounting: attempt.accounting,
|
|
125
176
|
candidates: results,
|
|
126
177
|
}, null, 2));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-image-batch-command.js","sourceRoot":"","sources":["../src/cli-image-batch-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"cli-image-batch-command.js","sourceRoot":"","sources":["../src/cli-image-batch-command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type ImageBatchCompletion } from './image-generation-completion.js';
|
|
2
|
+
export type ImageBatchCandidateIdentity = {
|
|
3
|
+
candidateId?: string;
|
|
4
|
+
outputPath: string;
|
|
5
|
+
idempotencyKey: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Move every candidate the provider settled — succeeded or failed — out of the
|
|
9
|
+
* hidden staging directory in one pass. Nothing is delivered mid-flight, so the
|
|
10
|
+
* candidates directory goes from empty to complete rather than through a
|
|
11
|
+
* half-written state that reads as failure.
|
|
12
|
+
*/
|
|
13
|
+
export declare const materializeImageBatch: (candidates: readonly ImageBatchCandidateIdentity[]) => Promise<void>;
|
|
14
|
+
export declare const publishImageBatchCompletion: (args: {
|
|
15
|
+
manifestPath: string;
|
|
16
|
+
manifestSha256: string;
|
|
17
|
+
batchAttemptFile: string;
|
|
18
|
+
provider: string;
|
|
19
|
+
model: string;
|
|
20
|
+
resumed: boolean;
|
|
21
|
+
status: "succeeded" | "failed";
|
|
22
|
+
candidates: readonly ImageBatchCandidateIdentity[];
|
|
23
|
+
}) => Promise<{
|
|
24
|
+
completionPath: string;
|
|
25
|
+
completion: ImageBatchCompletion;
|
|
26
|
+
}>;
|
|
27
|
+
//# sourceMappingURL=cli-image-batch-materialize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-image-batch-materialize.d.ts","sourceRoot":"","sources":["../src/cli-image-batch-materialize.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,kCAAkC,CAAC;AAG1C,MAAM,MAAM,2BAA2B,GAAG;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAMF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAChC,YAAY,SAAS,2BAA2B,EAAE,KACjD,OAAO,CAAC,IAAI,CAId,CAAC;AAEF,eAAO,MAAM,2BAA2B,GAAU,MAAM;IACtD,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAC;IAC/B,UAAU,EAAE,SAAS,2BAA2B,EAAE,CAAC;CACpD,KAAG,OAAO,CAAC;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,oBAAoB,CAAA;CAAE,CA2BvE,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { imageBatchCompletionPath, summarizeImageBatchCandidates, writeImageBatchCompletion, } from './image-generation-completion.js';
|
|
2
|
+
import { materializeImageGeneration } from './image-generation-staging.js';
|
|
3
|
+
const identityId = (candidate, index) => (candidate.candidateId ?? String(index + 1));
|
|
4
|
+
/**
|
|
5
|
+
* Move every candidate the provider settled — succeeded or failed — out of the
|
|
6
|
+
* hidden staging directory in one pass. Nothing is delivered mid-flight, so the
|
|
7
|
+
* candidates directory goes from empty to complete rather than through a
|
|
8
|
+
* half-written state that reads as failure.
|
|
9
|
+
*/
|
|
10
|
+
export const materializeImageBatch = async (candidates) => {
|
|
11
|
+
await Promise.all(candidates.map((candidate) => (materializeImageGeneration(candidate.outputPath))));
|
|
12
|
+
};
|
|
13
|
+
export const publishImageBatchCompletion = async (args) => {
|
|
14
|
+
const completionPath = imageBatchCompletionPath({
|
|
15
|
+
manifestPath: args.manifestPath,
|
|
16
|
+
outputPaths: args.candidates.map((candidate) => candidate.outputPath),
|
|
17
|
+
});
|
|
18
|
+
const candidates = await summarizeImageBatchCandidates(args.candidates.map((candidate, index) => ({
|
|
19
|
+
id: identityId(candidate, index),
|
|
20
|
+
outputPath: candidate.outputPath,
|
|
21
|
+
idempotencyKey: candidate.idempotencyKey,
|
|
22
|
+
})));
|
|
23
|
+
const completion = {
|
|
24
|
+
version: 1,
|
|
25
|
+
status: args.status,
|
|
26
|
+
manifestPath: args.manifestPath,
|
|
27
|
+
manifestSha256: args.manifestSha256,
|
|
28
|
+
batchAttemptFile: args.batchAttemptFile,
|
|
29
|
+
provider: args.provider,
|
|
30
|
+
model: args.model,
|
|
31
|
+
resumed: args.resumed,
|
|
32
|
+
completedAt: new Date().toISOString(),
|
|
33
|
+
candidateCount: candidates.length,
|
|
34
|
+
succeededCount: candidates.filter((candidate) => candidate.status === 'succeeded').length,
|
|
35
|
+
failedCount: candidates.filter((candidate) => candidate.status !== 'succeeded').length,
|
|
36
|
+
candidates,
|
|
37
|
+
};
|
|
38
|
+
await writeImageBatchCompletion(completionPath, completion);
|
|
39
|
+
return { completionPath, completion };
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=cli-image-batch-materialize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-image-batch-materialize.js","sourceRoot":"","sources":["../src/cli-image-batch-materialize.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,6BAA6B,EAC7B,yBAAyB,GAE1B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAQ3E,MAAM,UAAU,GAAG,CAAC,SAAsC,EAAE,KAAa,EAAU,EAAE,CAAC,CACpF,SAAS,CAAC,WAAW,IAAI,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAC3C,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EACxC,UAAkD,EACnC,EAAE;IACjB,MAAM,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAC9C,0BAA0B,CAAC,SAAS,CAAC,UAAU,CAAC,CACjD,CAAC,CAAC,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG,KAAK,EAAE,IASjD,EAAyE,EAAE;IAC1E,MAAM,cAAc,GAAG,wBAAwB,CAAC;QAC9C,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC;KACtE,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,MAAM,6BAA6B,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QAChG,EAAE,EAAE,UAAU,CAAC,SAAS,EAAE,KAAK,CAAC;QAChC,UAAU,EAAE,SAAS,CAAC,UAAU;QAChC,cAAc,EAAE,SAAS,CAAC,cAAc;KACzC,CAAC,CAAC,CAAC,CAAC;IACL,MAAM,UAAU,GAAyB;QACvC,OAAO,EAAE,CAAC;QACV,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,cAAc,EAAE,IAAI,CAAC,cAAc;QACnC,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;QACvC,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACrC,cAAc,EAAE,UAAU,CAAC,MAAM;QACjC,cAAc,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,MAAM;QACzF,WAAW,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,MAAM;QACtF,UAAU;KACX,CAAC;IACF,MAAM,yBAAyB,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;IAC5D,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,CAAC;AACxC,CAAC,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ensembleImage } from '@just-every/ensemble';
|
|
2
|
+
import { type ImageBatchAttempt } from './image-generation-batch-attempt.js';
|
|
3
|
+
import type { ImageGenerationRequest } from './image-generation-request.js';
|
|
4
|
+
import { type ImageGenerationResumeState } from './image-generation-resume.js';
|
|
5
|
+
import { preflightImageProvider } from './image-provider-preflight.js';
|
|
6
|
+
export declare const describeBatchRecovery: (states: readonly ImageGenerationResumeState[]) => string;
|
|
7
|
+
/**
|
|
8
|
+
* Recover a batch whose candidates were dispatched but never delivered.
|
|
9
|
+
*
|
|
10
|
+
* Every candidate is classified from its own durable ledger entry first. Work
|
|
11
|
+
* that was already bought is delivered from staging; work that provably was not
|
|
12
|
+
* bought, or that the provider will return again for free under the recorded
|
|
13
|
+
* idempotency key, is re-requested under that same identity. Anything else is
|
|
14
|
+
* refused rather than bought a second time.
|
|
15
|
+
*/
|
|
16
|
+
export declare const resumeImageBatchCommand: (args: {
|
|
17
|
+
manifestPath: string;
|
|
18
|
+
manifestSha256: string;
|
|
19
|
+
batchAttemptFile: string;
|
|
20
|
+
batchAttempt: ImageBatchAttempt;
|
|
21
|
+
requests: ImageGenerationRequest[];
|
|
22
|
+
dependencies: {
|
|
23
|
+
generate?: typeof ensembleImage;
|
|
24
|
+
preflight?: typeof preflightImageProvider;
|
|
25
|
+
};
|
|
26
|
+
}) => Promise<void>;
|
|
27
|
+
//# sourceMappingURL=cli-image-batch-resume.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-image-batch-resume.d.ts","sourceRoot":"","sources":["../src/cli-image-batch-resume.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAOrD,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAE5E,OAAO,EAIL,KAAK,0BAA0B,EAChC,MAAM,8BAA8B,CAAC;AAStC,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAcvE,eAAO,MAAM,qBAAqB,GAChC,QAAQ,SAAS,0BAA0B,EAAE,KAC5C,MASF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,GAAU,MAAM;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,iBAAiB,CAAC;IAChC,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IACnC,YAAY,EAAE;QACZ,QAAQ,CAAC,EAAE,OAAO,aAAa,CAAC;QAChC,SAAS,CAAC,EAAE,OAAO,sBAAsB,CAAC;KAC3C,CAAC;CACH,KAAG,OAAO,CAAC,IAAI,CA8If,CAAC"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { materializeImageBatch, publishImageBatchCompletion, } from './cli-image-batch-materialize.js';
|
|
2
|
+
import { writeBatchAttempt, } from './image-generation-batch-attempt.js';
|
|
3
|
+
import { prepareImageGenerationRequest } from './image-generation-request.js';
|
|
4
|
+
import { classifyImageGenerationResume, describeResumeState, resumeStateSummary, } from './image-generation-resume.js';
|
|
5
|
+
import { dispatchImageGeneration, markImageGenerationDispatched, resumeReservedImageGeneration, } from './image-generation-run.js';
|
|
6
|
+
import { materializeImageGeneration } from './image-generation-staging.js';
|
|
7
|
+
import { summarizeImageGenerationUsage } from './image-generation-usage.js';
|
|
8
|
+
import { preflightImageProvider } from './image-provider-preflight.js';
|
|
9
|
+
const errorMessage = (error) => (error instanceof Error ? error.message : String(error));
|
|
10
|
+
const identities = (requests) => requests.map((request) => ({
|
|
11
|
+
...(request.candidateId ? { candidateId: request.candidateId } : {}),
|
|
12
|
+
outputPath: request.outputPath,
|
|
13
|
+
idempotencyKey: request.idempotencyKey,
|
|
14
|
+
}));
|
|
15
|
+
export const describeBatchRecovery = (states) => {
|
|
16
|
+
const summary = resumeStateSummary(states);
|
|
17
|
+
const parts = [
|
|
18
|
+
`${summary.materialized} already on disk`,
|
|
19
|
+
`${summary.stageable} generated and awaiting delivery`,
|
|
20
|
+
`${summary.redispatchable} recoverable without new spend`,
|
|
21
|
+
`${summary.unrecoverable} unrecoverable`,
|
|
22
|
+
];
|
|
23
|
+
return `${states.length} candidate(s): ${parts.join(', ')}`;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Recover a batch whose candidates were dispatched but never delivered.
|
|
27
|
+
*
|
|
28
|
+
* Every candidate is classified from its own durable ledger entry first. Work
|
|
29
|
+
* that was already bought is delivered from staging; work that provably was not
|
|
30
|
+
* bought, or that the provider will return again for free under the recorded
|
|
31
|
+
* idempotency key, is re-requested under that same identity. Anything else is
|
|
32
|
+
* refused rather than bought a second time.
|
|
33
|
+
*/
|
|
34
|
+
export const resumeImageBatchCommand = async (args) => {
|
|
35
|
+
const { batchAttempt, batchAttemptFile, manifestPath, manifestSha256, requests } = args;
|
|
36
|
+
const states = await Promise.all(requests.map((request) => classifyImageGenerationResume({
|
|
37
|
+
outputPath: request.outputPath,
|
|
38
|
+
...(request.candidateId ? { candidateId: request.candidateId } : {}),
|
|
39
|
+
})));
|
|
40
|
+
const summary = resumeStateSummary(states);
|
|
41
|
+
const candidates = identities(requests);
|
|
42
|
+
if (summary.stageable === 0 && summary.redispatchable === 0 && summary.unrecoverable === 0) {
|
|
43
|
+
// Nothing is outstanding. This is the state the eleven benchmark runs were
|
|
44
|
+
// actually in when they gave up: the batch had finished. Republish the
|
|
45
|
+
// sentinel so the caller can read what it already owns, then refuse — a
|
|
46
|
+
// completed batch is never re-run, because that would be a second purchase.
|
|
47
|
+
const { completionPath, completion } = await publishImageBatchCompletion({
|
|
48
|
+
manifestPath,
|
|
49
|
+
manifestSha256,
|
|
50
|
+
batchAttemptFile,
|
|
51
|
+
provider: batchAttempt.provider,
|
|
52
|
+
model: batchAttempt.model,
|
|
53
|
+
resumed: true,
|
|
54
|
+
status: 'succeeded',
|
|
55
|
+
candidates,
|
|
56
|
+
});
|
|
57
|
+
throw new Error(`Image batch already completed; every candidate is on disk and nothing can be resumed.`
|
|
58
|
+
+ ` Re-running it would be a second paid call. Candidates: ${completion.candidates
|
|
59
|
+
.map((candidate) => `${candidate.id} ${candidate.outputPath}`
|
|
60
|
+
+ ` sha256=${candidate.sha256 ?? 'unknown'} bytes=${candidate.bytes ?? 0}`)
|
|
61
|
+
.join('; ')}. Completion sentinel: ${completionPath}`);
|
|
62
|
+
}
|
|
63
|
+
const delivered = states.filter((state) => state.disposition === 'stageable');
|
|
64
|
+
await Promise.all(delivered.map((state) => materializeImageGeneration(state.outputPath)));
|
|
65
|
+
const redispatch = states.filter((state) => state.disposition === 'redispatchable');
|
|
66
|
+
const results = [];
|
|
67
|
+
const errors = [];
|
|
68
|
+
if (redispatch.length > 0) {
|
|
69
|
+
const outstanding = new Map(redispatch.map((state) => [state.outputPath, state]));
|
|
70
|
+
const pending = requests.filter((request) => outstanding.has(request.outputPath));
|
|
71
|
+
const preflight = await (args.dependencies.preflight ?? preflightImageProvider)({
|
|
72
|
+
provider: batchAttempt.requestedProvider,
|
|
73
|
+
projectRoot: batchAttempt.projectRoot,
|
|
74
|
+
});
|
|
75
|
+
if (preflight.provider !== batchAttempt.provider) {
|
|
76
|
+
throw new Error(`Refusing to resume with ${preflight.provider} because the batch was dispatched to`
|
|
77
|
+
+ ` ${batchAttempt.provider}; switching providers after dispatch is never a resume.`);
|
|
78
|
+
}
|
|
79
|
+
const prepared = await Promise.all(pending.map((request) => (prepareImageGenerationRequest(request, { mode: 'resume' }))));
|
|
80
|
+
const reserved = prepared.map((request) => resumeReservedImageGeneration({
|
|
81
|
+
request,
|
|
82
|
+
preflight,
|
|
83
|
+
attempt: outstanding.get(request.outputPath)?.attempt ?? {
|
|
84
|
+
schemaVersion: 4,
|
|
85
|
+
status: 'prepared',
|
|
86
|
+
idempotencyKey: request.idempotencyKey,
|
|
87
|
+
provider: preflight.provider,
|
|
88
|
+
model: preflight.model,
|
|
89
|
+
providerIdempotencyEnforced: preflight.provider === 'openai',
|
|
90
|
+
providerEvidence: preflight.provider === 'codex'
|
|
91
|
+
? { codexVersion: preflight.codexVersion }
|
|
92
|
+
: { keySource: preflight.keySource },
|
|
93
|
+
prompt: request.prompt,
|
|
94
|
+
promptSource: request.promptSource,
|
|
95
|
+
promptSha256: request.promptSha256,
|
|
96
|
+
reference: { path: request.reference.path, sha256: request.reference.sha256 },
|
|
97
|
+
referenceMode: request.referenceMode,
|
|
98
|
+
outputPath: request.outputPath,
|
|
99
|
+
preparedAt: new Date().toISOString(),
|
|
100
|
+
},
|
|
101
|
+
}));
|
|
102
|
+
await Promise.all(reserved.map((item) => markImageGenerationDispatched(item)));
|
|
103
|
+
const settled = await Promise.allSettled(reserved.map((item) => (dispatchImageGeneration(item, { generate: args.dependencies.generate }))));
|
|
104
|
+
for (const outcome of settled) {
|
|
105
|
+
if (outcome.status === 'fulfilled')
|
|
106
|
+
results.push(outcome.value);
|
|
107
|
+
else
|
|
108
|
+
errors.push(errorMessage(outcome.reason));
|
|
109
|
+
}
|
|
110
|
+
batchAttempt.accounting = summarizeImageGenerationUsage(reserved.map((item) => item.attempt.usage), preflight.provider);
|
|
111
|
+
}
|
|
112
|
+
await materializeImageBatch(candidates);
|
|
113
|
+
const unrecoverable = states.filter((state) => state.disposition === 'unrecoverable');
|
|
114
|
+
const failed = errors.length > 0 || unrecoverable.length > 0;
|
|
115
|
+
const { completionPath, completion } = await publishImageBatchCompletion({
|
|
116
|
+
manifestPath,
|
|
117
|
+
manifestSha256,
|
|
118
|
+
batchAttemptFile,
|
|
119
|
+
provider: batchAttempt.provider,
|
|
120
|
+
model: batchAttempt.model,
|
|
121
|
+
resumed: true,
|
|
122
|
+
status: failed ? 'failed' : 'succeeded',
|
|
123
|
+
candidates,
|
|
124
|
+
});
|
|
125
|
+
batchAttempt.status = failed ? 'failed' : 'succeeded';
|
|
126
|
+
batchAttempt.completedAt = new Date().toISOString();
|
|
127
|
+
batchAttempt.completionPath = completionPath;
|
|
128
|
+
batchAttempt.resumedAt = [...batchAttempt.resumedAt ?? [], new Date().toISOString()];
|
|
129
|
+
if (results.length > 0)
|
|
130
|
+
batchAttempt.results = [...batchAttempt.results ?? [], ...results];
|
|
131
|
+
if (failed) {
|
|
132
|
+
batchAttempt.errors = [
|
|
133
|
+
...errors,
|
|
134
|
+
...unrecoverable.map((state) => describeResumeState(state)),
|
|
135
|
+
];
|
|
136
|
+
}
|
|
137
|
+
await writeBatchAttempt(batchAttemptFile, batchAttempt);
|
|
138
|
+
if (failed) {
|
|
139
|
+
throw new AggregateError(batchAttempt.errors ?? [], `Image batch resume recovered ${completion.succeededCount} of ${completion.candidateCount}`
|
|
140
|
+
+ ` candidate(s) without new spend, and cannot recover the rest.`
|
|
141
|
+
+ ` ${describeBatchRecovery(states)}. Give any unrecoverable candidate a new output path and`
|
|
142
|
+
+ ` idempotency key to buy it again. Evidence: ${batchAttemptFile}.`
|
|
143
|
+
+ ` Completion sentinel: ${completionPath}`);
|
|
144
|
+
}
|
|
145
|
+
console.log(JSON.stringify({
|
|
146
|
+
provider: batchAttempt.provider,
|
|
147
|
+
model: batchAttempt.model,
|
|
148
|
+
manifestPath,
|
|
149
|
+
batchAttemptFile,
|
|
150
|
+
completionPath,
|
|
151
|
+
resumed: true,
|
|
152
|
+
deliveredFromStaging: delivered.length,
|
|
153
|
+
redispatchedWithoutNewSpend: results.length,
|
|
154
|
+
accounting: batchAttempt.accounting,
|
|
155
|
+
candidates: completion.candidates,
|
|
156
|
+
}, null, 2));
|
|
157
|
+
};
|
|
158
|
+
//# sourceMappingURL=cli-image-batch-resume.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-image-batch-resume.js","sourceRoot":"","sources":["../src/cli-image-batch-resume.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-image-command.d.ts","sourceRoot":"","sources":["../src/cli-image-command.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"cli-image-command.d.ts","sourceRoot":"","sources":["../src/cli-image-command.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAiB/D,OAAO,EAGL,sBAAsB,EACvB,MAAM,+BAA+B,CAAC;AAoCvC,eAAO,MAAM,eAAe,GAC1B,QAAQ,MAAM,GAAG,SAAS,EAC1B,OAAO,QAAQ,EACf,eAAc;IACZ,QAAQ,CAAC,EAAE,OAAO,aAAa,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,sBAAsB,CAAC;CACtC,KACL,OAAO,CAAC,IAAI,CAoEd,CAAC"}
|
|
@@ -3,6 +3,7 @@ import path from 'node:path';
|
|
|
3
3
|
import { stringFlag } from './cli-arguments.js';
|
|
4
4
|
import { dispatchImageGeneration, markImageGenerationDispatched, reserveImageGeneration, } from './image-generation-run.js';
|
|
5
5
|
import { IMAGE_GENERATION_ASPECTS, IMAGE_GENERATION_REFERENCE_MODES, isImageGenerationAspect, isImageGenerationReferenceMode, prepareImageGenerationRequest, } from './image-generation-request.js';
|
|
6
|
+
import { materializeImageGeneration } from './image-generation-staging.js';
|
|
6
7
|
import { IMAGE_GENERATION_PROVIDERS, isImageGenerationProvider, preflightImageProvider, } from './image-provider-preflight.js';
|
|
7
8
|
import { normalizeOptionalIdempotencyKey } from './idempotency-key.js';
|
|
8
9
|
const referenceFlag = (flags) => {
|
|
@@ -86,7 +87,18 @@ export const runImageCommand = async (action, flags, dependencies = {}) => {
|
|
|
86
87
|
});
|
|
87
88
|
const reserved = await reserveImageGeneration({ request, preflight });
|
|
88
89
|
await markImageGenerationDispatched(reserved);
|
|
89
|
-
|
|
90
|
-
|
|
90
|
+
try {
|
|
91
|
+
const result = await dispatchImageGeneration(reserved, { generate: dependencies.generate });
|
|
92
|
+
// The PNG and its completed ledger entry appear together. Until this
|
|
93
|
+
// returns, the destination directory holds neither.
|
|
94
|
+
await materializeImageGeneration(outputPath);
|
|
95
|
+
console.log(JSON.stringify(result, null, 2));
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
// Terminal failures still owe the caller their evidence at the documented
|
|
99
|
+
// path, even though there is no image to deliver.
|
|
100
|
+
await materializeImageGeneration(outputPath).catch(() => undefined);
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
91
103
|
};
|
|
92
104
|
//# sourceMappingURL=cli-image-command.js.map
|