Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | 4x 4x 4x 4x 49x 29x 29x 29x 29x 29x 29x 35x 35x | import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { z } from 'zod';
import { UsageStatsSchema } from '../types/index.js';
import { BUILD_STATE_FILE } from './definition.js';
import {
SkillBuildOutlineSchema,
} from './outline-contract.js';
export const SKILL_BUILD_STATE_SCHEMA_VERSION = 1;
export const SKILL_BUILD_STATE_KIND = 'skill-build-state';
export const GeneratedSkillArtifactStateSchema = z.object({
version: z.literal(5),
sourceHash: z.string().min(1),
outlineHash: z.string().min(1),
buildVersion: z.string().min(1),
authoringProvider: z.object({
name: z.string().min(1),
rootDir: z.string().min(1),
contentHash: z.string().min(1),
}).strict(),
name: z.string().min(1),
fileManifest: z.array(z.object({
path: z.string().min(1),
bytes: z.number().int().nonnegative(),
}).strict()).min(1),
deterministicWarnings: z.array(z.string().min(1)).default([]),
bytes: z.number().int().nonnegative(),
durationMs: z.number().nonnegative(),
usage: UsageStatsSchema,
externalSources: z.array(z.object({
title: z.string().min(1),
url: z.string().min(1),
reason: z.string().min(1),
}).strict()),
missingInputs: z.array(z.string().min(1)),
authoringWarnings: z.array(z.string().min(1)).default([]),
responseModel: z.string().optional(),
numTurns: z.number().int().nonnegative().optional(),
generatedAt: z.string().min(1),
}).strict();
export type GeneratedSkillArtifactState = z.infer<typeof GeneratedSkillArtifactStateSchema>;
export const SkillBuildStateSchema = z.object({
version: z.literal(SKILL_BUILD_STATE_SCHEMA_VERSION),
kind: z.literal(SKILL_BUILD_STATE_KIND),
identity: z.object({
requestedModel: z.string().min(1).optional(),
}).strict().optional(),
outline: SkillBuildOutlineSchema,
outlineRun: z.object({
durationMs: z.number().nonnegative().optional(),
usage: UsageStatsSchema.optional(),
responseModel: z.string().optional(),
numTurns: z.number().int().nonnegative().optional(),
}).strict().optional(),
artifact: GeneratedSkillArtifactStateSchema.optional(),
updatedAt: z.string().optional(),
}).strict();
export type SkillBuildState = z.infer<typeof SkillBuildStateSchema>;
export function getBuildStatePath(rootDir: string): string {
return join(rootDir, BUILD_STATE_FILE);
}
export function readSkillBuildState(path: string): SkillBuildState | undefined {
Iif (!existsSync(path)) {
return undefined;
}
let parsed: unknown;
try {
parsed = JSON.parse(readFileSync(path, 'utf-8'));
} catch {
return undefined;
}
const validation = SkillBuildStateSchema.safeParse(parsed);
Iif (!validation.success) {
if (parsed && typeof parsed === 'object' && 'artifact' in parsed) {
const withoutArtifact = { ...parsed };
delete (withoutArtifact as { artifact?: unknown }).artifact;
const outlineOnlyValidation = SkillBuildStateSchema.safeParse(withoutArtifact);
if (outlineOnlyValidation.success) {
return outlineOnlyValidation.data;
}
}
return undefined;
}
return validation.data;
}
export function writeSkillBuildState(path: string, state: SkillBuildState): void {
mkdirSync(dirname(path), { recursive: true });
writeFileSync(path, `${JSON.stringify(state, null, 2)}\n`, 'utf-8');
}
|