@thanh01.pmt/curriculum-kit 1.0.0
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 +22 -0
- package/dist/ai/index.cjs +4980 -0
- package/dist/ai/index.cjs.map +1 -0
- package/dist/ai/index.d.cts +1287 -0
- package/dist/ai/index.d.ts +1287 -0
- package/dist/ai/index.mjs +4924 -0
- package/dist/ai/index.mjs.map +1 -0
- package/dist/index.cjs +15308 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +747 -0
- package/dist/index.d.ts +747 -0
- package/dist/index.mjs +14965 -0
- package/dist/index.mjs.map +1 -0
- package/dist/media/index.cjs +1238 -0
- package/dist/media/index.cjs.map +1 -0
- package/dist/media/index.d.cts +254 -0
- package/dist/media/index.d.ts +254 -0
- package/dist/media/index.mjs +1221 -0
- package/dist/media/index.mjs.map +1 -0
- package/dist/milestoneBundleGenerator-CbXhs1CP.d.ts +62 -0
- package/dist/milestoneBundleGenerator-DrBtHzBO.d.cts +62 -0
- package/dist/pipeline/index.cjs +4894 -0
- package/dist/pipeline/index.cjs.map +1 -0
- package/dist/pipeline/index.d.cts +161 -0
- package/dist/pipeline/index.d.ts +161 -0
- package/dist/pipeline/index.mjs +4869 -0
- package/dist/pipeline/index.mjs.map +1 -0
- package/dist/provider-factory-DH3udYlN.d.cts +25 -0
- package/dist/provider-factory-DH3udYlN.d.ts +25 -0
- package/dist/publishers/index.cjs +575 -0
- package/dist/publishers/index.cjs.map +1 -0
- package/dist/publishers/index.d.cts +85 -0
- package/dist/publishers/index.d.ts +85 -0
- package/dist/publishers/index.mjs +561 -0
- package/dist/publishers/index.mjs.map +1 -0
- package/dist/schemas/index.cjs +1640 -0
- package/dist/schemas/index.cjs.map +1 -0
- package/dist/schemas/index.d.cts +14194 -0
- package/dist/schemas/index.d.ts +14194 -0
- package/dist/schemas/index.mjs +1517 -0
- package/dist/schemas/index.mjs.map +1 -0
- package/dist/standards/index.cjs +910 -0
- package/dist/standards/index.cjs.map +1 -0
- package/dist/standards/index.d.cts +130 -0
- package/dist/standards/index.d.ts +130 -0
- package/dist/standards/index.mjs +890 -0
- package/dist/standards/index.mjs.map +1 -0
- package/dist/standardsCoverageGate-BWAkXY76.d.cts +767 -0
- package/dist/standardsCoverageGate-BWAkXY76.d.ts +767 -0
- package/dist/storage/index.cjs +595 -0
- package/dist/storage/index.cjs.map +1 -0
- package/dist/storage/index.d.cts +77 -0
- package/dist/storage/index.d.ts +77 -0
- package/dist/storage/index.mjs +583 -0
- package/dist/storage/index.mjs.map +1 -0
- package/dist/streamRunner-C7j5LKon.d.cts +60 -0
- package/dist/streamRunner-C7j5LKon.d.ts +60 -0
- package/dist/supabasePublisher-C627qXFT.d.cts +63 -0
- package/dist/supabasePublisher-C627qXFT.d.ts +63 -0
- package/dist/types-BUJGYiep.d.cts +89 -0
- package/dist/types-BUJGYiep.d.ts +89 -0
- package/dist/workflow/index.cjs +5266 -0
- package/dist/workflow/index.cjs.map +1 -0
- package/dist/workflow/index.d.cts +295 -0
- package/dist/workflow/index.d.ts +295 -0
- package/dist/workflow/index.mjs +5216 -0
- package/dist/workflow/index.mjs.map +1 -0
- package/package.json +105 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { S as StreamRunnerOptions } from '../streamRunner-C7j5LKon.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Media Types — image generation, image search, video search cho học liệu.
|
|
5
|
+
* Mục tiêu: mọi artifact instruction step-by-step / slide đều có minh họa phù hợp,
|
|
6
|
+
* sinh bằng AI (Gemini/GPT image) HOẶC tìm kiếm ảnh/video thật có license phù hợp.
|
|
7
|
+
*/
|
|
8
|
+
type MediaProvider = 'openai' | 'gemini';
|
|
9
|
+
/** Default = 'openai' (gpt-image-1): infographic quality preferred. */
|
|
10
|
+
interface GeneratedImage {
|
|
11
|
+
/** Base64-encoded image data (không kèm prefix data:) */
|
|
12
|
+
base64: string;
|
|
13
|
+
mimeType: string;
|
|
14
|
+
/** Provider dùng để sinh (audit/debug) */
|
|
15
|
+
provider: string;
|
|
16
|
+
/** Prompt đã được dùng (sau khi enrich theo ngữ cảnh) */
|
|
17
|
+
prompt: string;
|
|
18
|
+
revisedPrompt?: string;
|
|
19
|
+
}
|
|
20
|
+
interface StockImage {
|
|
21
|
+
url: string;
|
|
22
|
+
thumbnailUrl?: string;
|
|
23
|
+
width?: number;
|
|
24
|
+
height?: number;
|
|
25
|
+
photographer?: string;
|
|
26
|
+
source: string;
|
|
27
|
+
license: string;
|
|
28
|
+
pageUrl?: string;
|
|
29
|
+
altText?: string;
|
|
30
|
+
}
|
|
31
|
+
interface StockVideo {
|
|
32
|
+
url: string;
|
|
33
|
+
thumbnailUrl?: string;
|
|
34
|
+
durationSeconds?: number;
|
|
35
|
+
width?: number;
|
|
36
|
+
height?: number;
|
|
37
|
+
source: string;
|
|
38
|
+
license: string;
|
|
39
|
+
pageUrl?: string;
|
|
40
|
+
}
|
|
41
|
+
interface GenerateImageOptions {
|
|
42
|
+
/** Mô tả minh họa cần sinh */
|
|
43
|
+
prompt: string;
|
|
44
|
+
/** Ngữ cảnh bài học để enrich prompt (concept, grade band, style guide excerpt) */
|
|
45
|
+
context?: {
|
|
46
|
+
lessonTitle?: string;
|
|
47
|
+
concept?: string;
|
|
48
|
+
gradeBand?: [number, number] | number;
|
|
49
|
+
pedagogy?: string;
|
|
50
|
+
styleGuideExcerpt?: string;
|
|
51
|
+
language?: string;
|
|
52
|
+
};
|
|
53
|
+
/** Tỷ lệ khung: 16:9 cho slide, 4:3/1:1 cho worksheet */
|
|
54
|
+
aspectRatio?: '1:1' | '16:9' | '4:3' | '3:4';
|
|
55
|
+
/** Phong cách hình: phù hợp giáo dục, rõ ràng, an toàn cho học sinh */
|
|
56
|
+
style?: 'educational-diagram' | 'realistic-photo' | 'flat-illustration' | 'technical-schematic';
|
|
57
|
+
provider?: MediaProvider;
|
|
58
|
+
/** API key override (nếu không dùng env) */
|
|
59
|
+
apiKey?: string;
|
|
60
|
+
}
|
|
61
|
+
interface SearchImageOptions {
|
|
62
|
+
query: string;
|
|
63
|
+
perPage?: number;
|
|
64
|
+
orientation?: 'landscape' | 'portrait' | 'square';
|
|
65
|
+
apiKey?: string;
|
|
66
|
+
}
|
|
67
|
+
interface SearchVideoOptions {
|
|
68
|
+
query: string;
|
|
69
|
+
perPage?: number;
|
|
70
|
+
apiKey?: string;
|
|
71
|
+
}
|
|
72
|
+
declare class MediaError extends Error {
|
|
73
|
+
readonly provider?: string | undefined;
|
|
74
|
+
readonly status?: number | undefined;
|
|
75
|
+
constructor(message: string, provider?: string | undefined, status?: number | undefined);
|
|
76
|
+
}
|
|
77
|
+
/** Enrich prompt gốc với ngữ cảnh sư phạm → prompt sinh ảnh chất lượng, nhất quán phong cách */
|
|
78
|
+
declare function buildImagePrompt(options: GenerateImageOptions): string;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Sinh ảnh minh họa cho học liệu. Provider mặc định: gemini.
|
|
82
|
+
* Prompt tự động enrich với ngữ cảnh sư phạm (grade band, style guide, khái niệm bài học).
|
|
83
|
+
*/
|
|
84
|
+
declare function generateEducationalImage(options: GenerateImageOptions): Promise<GeneratedImage>;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Stock Media Search — tìm ảnh/video minh họa THẬT có license mở (Pexels).
|
|
88
|
+
* Dùng khi: không cần sinh AI, muốn ảnh thật của phần cứng (ESP32, breadboard…),
|
|
89
|
+
* hoặc muốn video demo quá trình thực tế cho step-by-step instructions.
|
|
90
|
+
* API key: PEXELS_API_KEY (miễn phí tại pexels.com/api).
|
|
91
|
+
*/
|
|
92
|
+
declare function searchEducationalImages(options: SearchImageOptions): Promise<StockImage[]>;
|
|
93
|
+
declare function searchEducationalVideos(options: SearchVideoOptions): Promise<StockVideo[]>;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Media Ledger — sổ cái ảnh per-lesson (JSONL), nguồn chân lý cho quy hoạch ảnh.
|
|
97
|
+
* Vòng đời entry: pending → approved (Curator chốt) → done | failed (kèm lastError)
|
|
98
|
+
* Agent tạo artifact chỉ APPEND (pending). Curator quyết định. Orchestrator thực thi.
|
|
99
|
+
* Idempotent: 1 slug chỉ có 1 entry active; append cùng slug → cập nhật, không trùng.
|
|
100
|
+
*/
|
|
101
|
+
type MediaLedgerMode = 'generate' | 'search';
|
|
102
|
+
type MediaLedgerStatus = 'pending' | 'approved' | 'rejected' | 'done' | 'failed';
|
|
103
|
+
interface MediaLedgerEntry {
|
|
104
|
+
/** Định danh ảnh trong bài, vd 'img-loop-diagram' — unique per lesson */
|
|
105
|
+
slug: string;
|
|
106
|
+
/** Artifact chứa slot, vd 'LESSON_U01_M01_L01' */
|
|
107
|
+
artifactId: string;
|
|
108
|
+
/** Tên ảnh (human-readable) */
|
|
109
|
+
name: string;
|
|
110
|
+
/** Mô tả chi tiết nội dung ảnh — input chính cho Curator enrich + agent con */
|
|
111
|
+
description: string;
|
|
112
|
+
/** 'generate' (AI) hoặc 'search' (ảnh/video thật) */
|
|
113
|
+
mode: MediaLedgerMode;
|
|
114
|
+
/** Vị trí chèn: markdown heading/anchor gần nhất trong artifact */
|
|
115
|
+
anchor?: string;
|
|
116
|
+
status: MediaLedgerStatus;
|
|
117
|
+
/** Provider đã dùng (set khi done) */
|
|
118
|
+
provider?: string;
|
|
119
|
+
/** Path tương đối trong project sau khi done: _media/xxx.png */
|
|
120
|
+
relPath?: string;
|
|
121
|
+
/** Prompt cuối (đã enrich) — audit/debug */
|
|
122
|
+
finalPrompt?: string;
|
|
123
|
+
lastError?: string;
|
|
124
|
+
retryCount?: number;
|
|
125
|
+
/** Quyết định của Curator: mã lý do (duplicate/content_mismatch/...) — audit + user override */
|
|
126
|
+
decisionReasonCode?: string;
|
|
127
|
+
decisionReason?: string;
|
|
128
|
+
updatedAt: string;
|
|
129
|
+
}
|
|
130
|
+
declare class MediaLedger {
|
|
131
|
+
readonly filePath: string;
|
|
132
|
+
private entries;
|
|
133
|
+
constructor(projectDir: string, lessonId: string);
|
|
134
|
+
private load;
|
|
135
|
+
private persist;
|
|
136
|
+
/** Agent tạo artifact ghi entry mới (hoặc cập nhật nếu slug đã có và chưa done) */
|
|
137
|
+
upsert(input: Omit<MediaLedgerEntry, 'status' | 'updatedAt'> & {
|
|
138
|
+
status?: MediaLedgerStatus;
|
|
139
|
+
}): MediaLedgerEntry;
|
|
140
|
+
get(slug: string): MediaLedgerEntry | undefined;
|
|
141
|
+
list(): MediaLedgerEntry[];
|
|
142
|
+
listByStatus(status: MediaLedgerStatus): MediaLedgerEntry[];
|
|
143
|
+
pending(): MediaLedgerEntry[];
|
|
144
|
+
setStatus(slug: string, status: MediaLedgerStatus, patch?: Partial<MediaLedgerEntry>): MediaLedgerEntry | undefined;
|
|
145
|
+
/** Đếm ảnh đã done trong lesson — để Curator tôn trọng maxImages */
|
|
146
|
+
doneCount(): number;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
type MediaPolicyMode = 'search_only' | 'gen_only' | 'auto';
|
|
150
|
+
interface MediaPolicy {
|
|
151
|
+
/** Giới hạn số ảnh ĐƯỢC GEN (AI) tối đa per artifact — search kho ảnh KHÔNG tốn quota */
|
|
152
|
+
maxGenImagesPerArtifact: number;
|
|
153
|
+
/** Ưu tiên provider khi mode=generate */
|
|
154
|
+
preferredProvider?: 'openai' | 'gemini';
|
|
155
|
+
/**
|
|
156
|
+
* Chiến lược nguồn ảnh:
|
|
157
|
+
* — search_only: chỉ tìm kho ảnh (Pexels), không sinh AI
|
|
158
|
+
* — gen_only: chỉ sinh AI, bỏ qua kho ảnh
|
|
159
|
+
* — auto: LUÔN search trước, không có kết quả mới generate (mặc định)
|
|
160
|
+
*/
|
|
161
|
+
mode?: MediaPolicyMode;
|
|
162
|
+
}
|
|
163
|
+
interface CurationDecision {
|
|
164
|
+
slug: string;
|
|
165
|
+
action: 'approve' | 'drop' | 're-describe';
|
|
166
|
+
/** Mã lý do máy-đọc-được — bắt buộc khi drop, để audit + user có thể override */
|
|
167
|
+
reasonCode?: 'duplicate' | 'content_mismatch' | 'low_quality_description' | 'over_quota' | 'none_needed';
|
|
168
|
+
/** Mô tả đã enrich (grade band, style, pedagogy) — chỉ khi approve/re-describe */
|
|
169
|
+
enrichedPrompt?: string;
|
|
170
|
+
reason: string;
|
|
171
|
+
}
|
|
172
|
+
interface CurateOptions {
|
|
173
|
+
ledger: MediaLedger;
|
|
174
|
+
/** Nội dung artifact ĐÃ PASS judge (markdown, strip YAML) */
|
|
175
|
+
artifactContent: string;
|
|
176
|
+
policy: MediaPolicy;
|
|
177
|
+
/** Ngữ cảnh dự án: grade band, style guide, tiêu đề bài */
|
|
178
|
+
context: {
|
|
179
|
+
lessonTitle?: string;
|
|
180
|
+
gradeBand?: [number, number];
|
|
181
|
+
styleGuideExcerpt?: string;
|
|
182
|
+
language?: string;
|
|
183
|
+
};
|
|
184
|
+
llm?: StreamRunnerOptions;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Curator: phân tích toàn bộ sổ cái + nội dung đã chốt → quyết định ảnh nào tạo.
|
|
188
|
+
* Tôn trọng maxImagesPerArtifact (count cả ảnh done + pending được approve).
|
|
189
|
+
* LLM trả JSON: [{slug, action, enrichedPrompt, reason}]. Parse lỗi → MediaError rõ ràng.
|
|
190
|
+
*/
|
|
191
|
+
declare function curateMediaLedger(options: CurateOptions): Promise<CurationDecision[]>;
|
|
192
|
+
/** Input ranking cho 1 gen candidate */
|
|
193
|
+
interface GenCandidate {
|
|
194
|
+
slug: string;
|
|
195
|
+
name: string;
|
|
196
|
+
description: string;
|
|
197
|
+
}
|
|
198
|
+
interface GenRanking {
|
|
199
|
+
/** Slugs được quyền gen (≤ quota) theo thứ tự ưu tiên */
|
|
200
|
+
selected: string[];
|
|
201
|
+
/** Slots không được gen kèm lý do */
|
|
202
|
+
dropped: Array<{
|
|
203
|
+
slug: string;
|
|
204
|
+
rank: number;
|
|
205
|
+
}>;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Xếp hạng gen candidates khi số slot search-miss (hoặc gen_only tổng slot) VƯỢT quota gen.
|
|
209
|
+
* Chỉ xếp hạng theo mức cần thiết của minh họa cho hiểu bài — KHÔNG đụng ledger (orchestrate lo persist).
|
|
210
|
+
* LLM fail → fallback first-come theo thứ tự sổ cái + log warning rõ (degradation có chủ đích, không im lặng).
|
|
211
|
+
*/
|
|
212
|
+
declare function rankGenCandidates(candidates: GenCandidate[], quota: number, context: {
|
|
213
|
+
lessonTitle?: string;
|
|
214
|
+
gradeBand?: [number, number];
|
|
215
|
+
}, llm?: StreamRunnerOptions): Promise<GenRanking>;
|
|
216
|
+
|
|
217
|
+
interface FulfillOptions {
|
|
218
|
+
ledger: MediaLedger;
|
|
219
|
+
projectDir: string;
|
|
220
|
+
policy: MediaPolicy;
|
|
221
|
+
/** Tỷ lệ khung mặc định cho artifact type (SLIDE → 16:9) */
|
|
222
|
+
defaultAspect?: '1:1' | '16:9' | '4:3' | '3:4';
|
|
223
|
+
apiKeyOverrides?: {
|
|
224
|
+
openai?: string;
|
|
225
|
+
gemini?: string;
|
|
226
|
+
pexels?: string;
|
|
227
|
+
};
|
|
228
|
+
/** Số lần retry tối đa trước khi đánh dấu failed vĩnh viễn */
|
|
229
|
+
maxRetries?: number;
|
|
230
|
+
/** Ngữ cảnh cho gen-ranking (khi search-miss vượt quota gen) */
|
|
231
|
+
rankingContext?: {
|
|
232
|
+
lessonTitle?: string;
|
|
233
|
+
gradeBand?: [number, number];
|
|
234
|
+
};
|
|
235
|
+
llm?: StreamRunnerOptions;
|
|
236
|
+
onProgress?: (slug: string, status: string, detail?: string) => void;
|
|
237
|
+
}
|
|
238
|
+
interface FulfillResult {
|
|
239
|
+
done: string[];
|
|
240
|
+
failed: string[];
|
|
241
|
+
skipped: string[];
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Thực thi các entry approved trong sổ cái (từng ảnh độc lập — lỗi 1 ảnh không chặn ảnh khác).
|
|
245
|
+
* generate → base64 → save file _media/; search → lưu URL đầu tiên (metadata vào ledger).
|
|
246
|
+
* Quá maxRetries → status 'failed', slot giữ placeholder trong markdown (client render).
|
|
247
|
+
*/
|
|
248
|
+
declare function fulfillMediaLedger(options: FulfillOptions): Promise<FulfillResult>;
|
|
249
|
+
/** Sau khi done: thay placeholder [IMAGE: slug] trong markdown bằng  */
|
|
250
|
+
declare function injectMediaIntoMarkdown(markdown: string, ledger: MediaLedger | MediaLedgerEntry[]): string;
|
|
251
|
+
/** Tạo placeholder hiển thị khi failed/pending — client render rõ trạng thái, không im lặng */
|
|
252
|
+
declare function renderMediaPlaceholder(entry: MediaLedgerEntry): string;
|
|
253
|
+
|
|
254
|
+
export { type CurateOptions, type CurationDecision, type FulfillOptions, type FulfillResult, type GenCandidate, type GenRanking, type GenerateImageOptions, type GeneratedImage, MediaError, MediaLedger, type MediaLedgerEntry, type MediaLedgerMode, type MediaLedgerStatus, type MediaPolicy, type MediaPolicyMode, type MediaProvider, type SearchImageOptions, type SearchVideoOptions, type StockImage, type StockVideo, buildImagePrompt, curateMediaLedger, fulfillMediaLedger, generateEducationalImage, injectMediaIntoMarkdown, rankGenCandidates, renderMediaPlaceholder, searchEducationalImages, searchEducationalVideos };
|