@thanh01.pmt/curriculum-kit 1.0.15 → 1.0.17

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/dist/index.cjs CHANGED
@@ -140,6 +140,10 @@ var init_errors = __esm({
140
140
  // src/ai/streamRunner.ts
141
141
  var streamRunner_exports = {};
142
142
  __export(streamRunner_exports, {
143
+ DEFAULT_ARTIFACT_STREAM_IDLE_MS: () => exports.DEFAULT_ARTIFACT_STREAM_IDLE_MS,
144
+ DEFAULT_ARTIFACT_STREAM_TOTAL_MS: () => exports.DEFAULT_ARTIFACT_STREAM_TOTAL_MS,
145
+ createIdleAbortController: () => createIdleAbortController,
146
+ createStreamAbortController: () => createStreamAbortController,
143
147
  extractThoughtAndContent: () => extractThoughtAndContent,
144
148
  getDesignatedFallbackChain: () => getDesignatedFallbackChain,
145
149
  getDesignatedFallbackConfig: () => getDesignatedFallbackConfig,
@@ -291,29 +295,44 @@ function extractThoughtAndContent(rawText) {
291
295
  content: content.trim()
292
296
  };
293
297
  }
294
- function createIdleAbortController(idleMs) {
298
+ function createStreamAbortController(options) {
299
+ const envIdle = Number(process.env.ARTIFACT_STREAM_IDLE_TIMEOUT_MS || process.env.STREAM_IDLE_TIMEOUT_MS);
300
+ const envTotal = Number(process.env.ARTIFACT_STREAM_TOTAL_TIMEOUT_MS || process.env.STREAM_TOTAL_TIMEOUT_MS);
301
+ const idleMs = Number.isFinite(options?.idleMs) && options.idleMs > 0 ? options.idleMs : Number.isFinite(envIdle) && envIdle > 0 ? envIdle : exports.DEFAULT_ARTIFACT_STREAM_IDLE_MS;
302
+ const totalMs = Number.isFinite(options?.totalMs) && options.totalMs > 0 ? options.totalMs : Number.isFinite(envTotal) && envTotal > 0 ? envTotal : exports.DEFAULT_ARTIFACT_STREAM_TOTAL_MS;
295
303
  const controller = new AbortController();
296
- let timer = null;
297
- const arm = () => {
298
- if (timer) clearTimeout(timer);
299
- timer = setTimeout(
304
+ let idleTimer = null;
305
+ let totalTimer = null;
306
+ const armIdle = () => {
307
+ if (idleTimer) clearTimeout(idleTimer);
308
+ idleTimer = setTimeout(
300
309
  () => controller.abort(new Error(`Idle timeout: no data for ${Math.round(idleMs / 1e3)}s`)),
301
310
  idleMs
302
311
  );
303
- timer?.unref?.();
312
+ idleTimer?.unref?.();
304
313
  };
305
- arm();
314
+ armIdle();
315
+ if (totalMs > 0) {
316
+ totalTimer = setTimeout(
317
+ () => controller.abort(new Error(`Total stream timeout after ${Math.round(totalMs / 1e3)}s`)),
318
+ totalMs
319
+ );
320
+ totalTimer?.unref?.();
321
+ }
306
322
  return {
307
323
  signal: controller.signal,
308
- /** Reset the idle window (call on every received chunk). */
309
- kick: arm,
310
- /** Clear the pending timer once the request lifecycle is over. */
324
+ kick: armIdle,
311
325
  dispose: () => {
312
- if (timer) clearTimeout(timer);
313
- timer = null;
326
+ if (idleTimer) clearTimeout(idleTimer);
327
+ if (totalTimer) clearTimeout(totalTimer);
328
+ idleTimer = null;
329
+ totalTimer = null;
314
330
  }
315
331
  };
316
332
  }
333
+ function createIdleAbortController(idleMs, totalMs) {
334
+ return createStreamAbortController({ idleMs, totalMs });
335
+ }
317
336
  async function processOpenAISSEStream(response, onChunk, idle, toolCallCollector) {
318
337
  if (!response.body) return "";
319
338
  const reader = response.body.getReader();
@@ -497,7 +516,7 @@ Guidelines:
497
516
  if (isNvidiaPreferred || uniqueNvidiaModels.length > 0) {
498
517
  for (const model of uniqueNvidiaModels) {
499
518
  try {
500
- const idle = createIdleAbortController(18e4);
519
+ const idle = createStreamAbortController({ idleMs: options.idleTimeoutMs, totalMs: options.timeoutMs });
501
520
  const res = await fetch("https://integrate.api.nvidia.com/v1/chat/completions", {
502
521
  method: "POST",
503
522
  headers: {
@@ -541,7 +560,7 @@ Guidelines:
541
560
  const uniqueOrModels = Array.from(new Set(openrouterModels));
542
561
  for (const model of uniqueOrModels) {
543
562
  try {
544
- const idle = createIdleAbortController(18e4);
563
+ const idle = createStreamAbortController({ idleMs: options.idleTimeoutMs, totalMs: options.timeoutMs });
545
564
  const res = await fetch("https://openrouter.ai/api/v1/chat/completions", {
546
565
  method: "POST",
547
566
  headers: {
@@ -580,7 +599,7 @@ Guidelines:
580
599
  const dsModel = options.model?.includes("deepseek-reasoner") ? "deepseek-reasoner" : "deepseek-chat";
581
600
  if (isModelAllowed(dsModel)) {
582
601
  try {
583
- const idle = createIdleAbortController(18e4);
602
+ const idle = createStreamAbortController({ idleMs: options.idleTimeoutMs, totalMs: options.timeoutMs });
584
603
  const res = await fetch("https://api.deepseek.com/chat/completions", {
585
604
  method: "POST",
586
605
  headers: {
@@ -615,7 +634,7 @@ Guidelines:
615
634
  const baseUrl = alibabaKey.startsWith("sk-sp-") ? "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1/chat/completions" : "https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions";
616
635
  for (const qwenModel of qwenModels) {
617
636
  try {
618
- const idle = createIdleAbortController(18e4);
637
+ const idle = createStreamAbortController({ idleMs: options.idleTimeoutMs, totalMs: options.timeoutMs });
619
638
  const payload = {
620
639
  model: qwenModel,
621
640
  messages: formattedMessages,
@@ -658,7 +677,7 @@ Guidelines:
658
677
  ];
659
678
  for (const gModel of geminiModels) {
660
679
  try {
661
- const idle = createIdleAbortController(18e4);
680
+ const idle = createStreamAbortController({ idleMs: options.idleTimeoutMs, totalMs: options.timeoutMs });
662
681
  const res = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${gModel}:streamGenerateContent?alt=sse&key=${geminiKey}`, {
663
682
  method: "POST",
664
683
  headers: { "Content-Type": "application/json" },
@@ -694,7 +713,7 @@ Guidelines:
694
713
  const { provider, model } = target;
695
714
  if (provider === "nvidia" && nvidiaKey && isProviderEnabled("nvidia")) {
696
715
  try {
697
- const idle = createIdleAbortController(18e4);
716
+ const idle = createStreamAbortController({ idleMs: options.idleTimeoutMs, totalMs: options.timeoutMs });
698
717
  const res = await fetch("https://integrate.api.nvidia.com/v1/chat/completions", {
699
718
  method: "POST",
700
719
  headers: {
@@ -726,7 +745,7 @@ Guidelines:
726
745
  }
727
746
  } else if (provider === "openrouter" && openrouterKey && isProviderEnabled("openrouter")) {
728
747
  try {
729
- const idle = createIdleAbortController(18e4);
748
+ const idle = createStreamAbortController({ idleMs: options.idleTimeoutMs, totalMs: options.timeoutMs });
730
749
  const res = await fetch("https://openrouter.ai/api/v1/chat/completions", {
731
750
  method: "POST",
732
751
  headers: {
@@ -761,7 +780,7 @@ Guidelines:
761
780
  } else if ((provider === "alibaba" || provider === "dashscope") && alibabaKey && isProviderEnabled("alibaba")) {
762
781
  const baseUrl = alibabaKey.startsWith("sk-sp-") ? "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1/chat/completions" : "https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions";
763
782
  try {
764
- const idle = createIdleAbortController(18e4);
783
+ const idle = createStreamAbortController({ idleMs: options.idleTimeoutMs, totalMs: options.timeoutMs });
765
784
  const res = await fetch(baseUrl, {
766
785
  method: "POST",
767
786
  headers: {
@@ -793,7 +812,7 @@ Guidelines:
793
812
  }
794
813
  } else if ((provider === "google" || provider === "gemini") && geminiKey && (isProviderEnabled("gemini") || isProviderEnabled("google"))) {
795
814
  try {
796
- const idle = createIdleAbortController(18e4);
815
+ const idle = createStreamAbortController({ idleMs: options.idleTimeoutMs, totalMs: options.timeoutMs });
797
816
  const res = await fetch(
798
817
  `https://generativelanguage.googleapis.com/v1beta/models/${model}:streamGenerateContent?alt=sse&key=${geminiKey}`,
799
818
  {
@@ -844,9 +863,12 @@ Guidelines:
844
863
  async function runCurriculumAIInference(messages, projectContext, options = {}, onChunk) {
845
864
  return await streamCurriculumAIInference(messages, projectContext, options, onChunk);
846
865
  }
866
+ exports.DEFAULT_ARTIFACT_STREAM_IDLE_MS = void 0; exports.DEFAULT_ARTIFACT_STREAM_TOTAL_MS = void 0;
847
867
  var init_streamRunner = __esm({
848
868
  "src/ai/streamRunner.ts"() {
849
869
  init_errors();
870
+ exports.DEFAULT_ARTIFACT_STREAM_IDLE_MS = 45e3;
871
+ exports.DEFAULT_ARTIFACT_STREAM_TOTAL_MS = 42e4;
850
872
  }
851
873
  });
852
874
 
@@ -13550,15 +13572,6 @@ function extractStreamChunk(part) {
13550
13572
  const content = part.text ?? part.delta ?? "";
13551
13573
  return content ? { content } : {};
13552
13574
  }
13553
- if (part.type === "raw") {
13554
- const raw = part.rawValue;
13555
- const delta = raw?.choices?.[0]?.delta;
13556
- const reasoning = delta?.reasoning_content ?? delta?.reasoning ?? raw?.delta?.reasoning_content ?? raw?.delta?.reasoning;
13557
- if (typeof reasoning === "string" && reasoning) return { thought: reasoning };
13558
- const text = delta?.content ?? raw?.delta?.content;
13559
- if (typeof text === "string" && text) return { content: text };
13560
- return {};
13561
- }
13562
13575
  return {};
13563
13576
  }
13564
13577
  function createStreamAbortSignal(budget) {
@@ -16213,6 +16226,10 @@ function resolveApiKey2(options) {
16213
16226
  }
16214
16227
  return { provider, key };
16215
16228
  }
16229
+ function resolveImageTimeout(options) {
16230
+ const envTimeout = Number(process.env.IMAGE_GEN_TIMEOUT_MS || process.env.ARTIFACT_STREAM_TOTAL_TIMEOUT_MS);
16231
+ return Number.isFinite(options.timeoutMs) && options.timeoutMs > 0 ? options.timeoutMs : Number.isFinite(envTimeout) && envTimeout > 0 ? envTimeout : 42e4;
16232
+ }
16216
16233
  async function generateWithGemini(options, key) {
16217
16234
  const finalPrompt = buildImagePrompt(options);
16218
16235
  const model = "gemini-2.0-flash-exp";
@@ -16223,7 +16240,7 @@ async function generateWithGemini(options, key) {
16223
16240
  contents: [{ parts: [{ text: finalPrompt }] }],
16224
16241
  generationConfig: { responseModalities: ["TEXT", "IMAGE"] }
16225
16242
  }),
16226
- signal: AbortSignal.timeout(9e4)
16243
+ signal: AbortSignal.timeout(resolveImageTimeout(options))
16227
16244
  });
16228
16245
  if (!res.ok) {
16229
16246
  const body = await res.text().catch(() => "");
@@ -16256,7 +16273,7 @@ async function generateWithOpenAI(options, key) {
16256
16273
  size: sizeMap[options.aspectRatio || "1:1"] || "1024x1024",
16257
16274
  n: 1
16258
16275
  }),
16259
- signal: AbortSignal.timeout(9e4)
16276
+ signal: AbortSignal.timeout(resolveImageTimeout(options))
16260
16277
  });
16261
16278
  if (!res.ok) {
16262
16279
  const body = await res.text().catch(() => "");
@@ -16880,6 +16897,8 @@ exports.contentTools = contentTools;
16880
16897
  exports.convertRoadmapToFoundationSot = convertRoadmapToFoundationSot;
16881
16898
  exports.createAiInferenceError = createAiInferenceError;
16882
16899
  exports.createCurriculumStorage = createCurriculumStorage;
16900
+ exports.createIdleAbortController = createIdleAbortController;
16901
+ exports.createStreamAbortController = createStreamAbortController;
16883
16902
  exports.createStreamAbortSignal = createStreamAbortSignal;
16884
16903
  exports.curateMediaLedger = curateMediaLedger;
16885
16904
  exports.designerTools = designerTools;