@thanh01.pmt/curriculum-kit 1.4.9 → 1.4.10

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.d.cts CHANGED
@@ -365,6 +365,8 @@ interface LayerPrefillOptions {
365
365
  timeoutMs?: number;
366
366
  /** Idle (no-data) budget override for this prefill run (ms). */
367
367
  idleTimeoutMs?: number;
368
+ /** Optional parent abort signal (e.g. from HTTP request) to stop immediately on client disconnect. */
369
+ signal?: AbortSignal;
368
370
  }
369
371
  interface PreliminaryResearchResult {
370
372
  groundTruthSummary: string;
@@ -388,7 +390,7 @@ interface StreamBudget {
388
390
  /** Abort when the whole stream exceeds this total wall time (ms). 0 disables. */
389
391
  totalMs?: number;
390
392
  }
391
- declare const DEFAULT_STREAM_IDLE_MS = 90000;
393
+ declare const DEFAULT_STREAM_IDLE_MS = 180000;
392
394
  declare const DEFAULT_STREAM_TOTAL_MS = 480000;
393
395
  declare const LAYER_IDLE_BUDGET_MS: Record<number, number>;
394
396
  /**
@@ -455,7 +457,7 @@ declare function createStreamChunkExtractor(): StreamChunkExtractor;
455
457
  * createStreamChunkExtractor, whose latch is the authoritative dedupe.
456
458
  */
457
459
  declare function extractStreamChunk(part: any): ExtractedStreamChunk;
458
- declare function createStreamAbortSignal(budget: Required<StreamBudget>): StreamAbortHandle;
460
+ declare function createStreamAbortSignal(budget: Required<StreamBudget>, parentSignal?: AbortSignal): StreamAbortHandle;
459
461
  /**
460
462
  * Close an unterminated JSON object/array: append the delimiters that are
461
463
  * still open, closing any open string first. Handles streams aborted
@@ -485,7 +487,7 @@ declare function safeParseJson<T = any>(rawText: string | null): T | null;
485
487
  /**
486
488
  * Multi-tiered resilient streaming inference helper using 100% Vercel AI SDK.
487
489
  */
488
- declare function streamLLMWithFallback(systemPrompt: string, userPrompt: string, apiKeys?: Record<string, string>, onChunk?: LayerChunkCallback, preferredModel?: string, preferredProvider?: AIProviderName, budget?: StreamBudget): Promise<string | null>;
490
+ declare function streamLLMWithFallback(systemPrompt: string, userPrompt: string, apiKeys?: Record<string, string>, onChunk?: LayerChunkCallback, preferredModel?: string, preferredProvider?: AIProviderName, budget?: StreamBudget, signal?: AbortSignal): Promise<string | null>;
489
491
  /**
490
492
  * Conducts preliminary ecosystem research for a course project.
491
493
  */
package/dist/index.d.ts CHANGED
@@ -365,6 +365,8 @@ interface LayerPrefillOptions {
365
365
  timeoutMs?: number;
366
366
  /** Idle (no-data) budget override for this prefill run (ms). */
367
367
  idleTimeoutMs?: number;
368
+ /** Optional parent abort signal (e.g. from HTTP request) to stop immediately on client disconnect. */
369
+ signal?: AbortSignal;
368
370
  }
369
371
  interface PreliminaryResearchResult {
370
372
  groundTruthSummary: string;
@@ -388,7 +390,7 @@ interface StreamBudget {
388
390
  /** Abort when the whole stream exceeds this total wall time (ms). 0 disables. */
389
391
  totalMs?: number;
390
392
  }
391
- declare const DEFAULT_STREAM_IDLE_MS = 90000;
393
+ declare const DEFAULT_STREAM_IDLE_MS = 180000;
392
394
  declare const DEFAULT_STREAM_TOTAL_MS = 480000;
393
395
  declare const LAYER_IDLE_BUDGET_MS: Record<number, number>;
394
396
  /**
@@ -455,7 +457,7 @@ declare function createStreamChunkExtractor(): StreamChunkExtractor;
455
457
  * createStreamChunkExtractor, whose latch is the authoritative dedupe.
456
458
  */
457
459
  declare function extractStreamChunk(part: any): ExtractedStreamChunk;
458
- declare function createStreamAbortSignal(budget: Required<StreamBudget>): StreamAbortHandle;
460
+ declare function createStreamAbortSignal(budget: Required<StreamBudget>, parentSignal?: AbortSignal): StreamAbortHandle;
459
461
  /**
460
462
  * Close an unterminated JSON object/array: append the delimiters that are
461
463
  * still open, closing any open string first. Handles streams aborted
@@ -485,7 +487,7 @@ declare function safeParseJson<T = any>(rawText: string | null): T | null;
485
487
  /**
486
488
  * Multi-tiered resilient streaming inference helper using 100% Vercel AI SDK.
487
489
  */
488
- declare function streamLLMWithFallback(systemPrompt: string, userPrompt: string, apiKeys?: Record<string, string>, onChunk?: LayerChunkCallback, preferredModel?: string, preferredProvider?: AIProviderName, budget?: StreamBudget): Promise<string | null>;
490
+ declare function streamLLMWithFallback(systemPrompt: string, userPrompt: string, apiKeys?: Record<string, string>, onChunk?: LayerChunkCallback, preferredModel?: string, preferredProvider?: AIProviderName, budget?: StreamBudget, signal?: AbortSignal): Promise<string | null>;
489
491
  /**
490
492
  * Conducts preliminary ecosystem research for a course project.
491
493
  */
package/dist/index.mjs CHANGED
@@ -27291,13 +27291,13 @@ var DeterministicPipelineRunner = class {
27291
27291
 
27292
27292
  // src/services/prefillService.ts
27293
27293
  init_streamRunner();
27294
- var DEFAULT_STREAM_IDLE_MS = 9e4;
27294
+ var DEFAULT_STREAM_IDLE_MS = 18e4;
27295
27295
  var DEFAULT_STREAM_TOTAL_MS = 48e4;
27296
27296
  var LAYER_IDLE_BUDGET_MS = {
27297
- 1: 9e4,
27298
- 2: 9e4,
27297
+ 1: 18e4,
27298
+ 2: 18e4,
27299
27299
  3: 18e4
27300
- // Layer 3 synthesizes all accumulated context + pathways (3 minutes idle protection)
27300
+ // 3 minutes idle protection across all layers for free-tier reasoning models
27301
27301
  };
27302
27302
  var LAYER_TOTAL_BUDGET_MS = {
27303
27303
  1: 48e4,
@@ -27358,10 +27358,20 @@ function extractStreamChunk(part) {
27358
27358
  }
27359
27359
  return {};
27360
27360
  }
27361
- function createStreamAbortSignal(budget) {
27361
+ function createStreamAbortSignal(budget, parentSignal) {
27362
27362
  const controller = new AbortController();
27363
27363
  let idleTimer = null;
27364
27364
  let totalTimer = null;
27365
+ const onParentAbort = () => {
27366
+ controller.abort(parentSignal?.reason || new Error("Aborted by parent signal"));
27367
+ };
27368
+ if (parentSignal) {
27369
+ if (parentSignal.aborted) {
27370
+ controller.abort(parentSignal.reason || new Error("Parent signal already aborted"));
27371
+ } else {
27372
+ parentSignal.addEventListener("abort", onParentAbort, { once: true });
27373
+ }
27374
+ }
27365
27375
  const armIdle = () => {
27366
27376
  if (idleTimer) clearTimeout(idleTimer);
27367
27377
  if (budget.idleMs > 0) {
@@ -27388,6 +27398,9 @@ function createStreamAbortSignal(budget) {
27388
27398
  dispose: () => {
27389
27399
  if (idleTimer) clearTimeout(idleTimer);
27390
27400
  if (totalTimer) clearTimeout(totalTimer);
27401
+ if (parentSignal) {
27402
+ parentSignal.removeEventListener("abort", onParentAbort);
27403
+ }
27391
27404
  idleTimer = null;
27392
27405
  totalTimer = null;
27393
27406
  }
@@ -27499,7 +27512,7 @@ function safeParseJson(rawText) {
27499
27512
  }
27500
27513
  return null;
27501
27514
  }
27502
- async function streamLLMWithFallback(systemPrompt, userPrompt, apiKeys = {}, onChunk, preferredModel, preferredProvider, budget) {
27515
+ async function streamLLMWithFallback(systemPrompt, userPrompt, apiKeys = {}, onChunk, preferredModel, preferredProvider, budget, signal) {
27503
27516
  const alibabaKey = apiKeys.alibaba || apiKeys.dashscope || process.env.ALIBABA_API_KEY || process.env.DASHSCOPE_API_KEY;
27504
27517
  const nvidiaKey = apiKeys.nvidia || process.env.NVIDIA_API_KEY;
27505
27518
  const deepseekKey = apiKeys.deepseek || process.env.DEEPSEEK_API_KEY;
@@ -27531,7 +27544,6 @@ async function streamLLMWithFallback(systemPrompt, userPrompt, apiKeys = {}, onC
27531
27544
  const nemotronModels = [
27532
27545
  "nvidia/nemotron-3-ultra-550b-a55b",
27533
27546
  "nvidia/nemotron-3.5-lightning-30b-a3b",
27534
- "nvidia/nemotron-3-super-120b-a12b",
27535
27547
  "nvidia/llama-3.1-nemotron-70b-instruct"
27536
27548
  ].filter((m) => isModelAllowed(m));
27537
27549
  for (const m of nemotronModels) {
@@ -27582,8 +27594,12 @@ THINKING DIRECTIVE: Do ALL your reasoning internally BEFORE emitting output. Do
27582
27594
  totalMs: budget?.totalMs ?? DEFAULT_STREAM_TOTAL_MS
27583
27595
  };
27584
27596
  for (const candidate of candidates) {
27597
+ if (signal?.aborted) {
27598
+ console.log(`[curriculum-kit:VercelAI] AbortSignal already aborted, cancelling candidate loop.`);
27599
+ break;
27600
+ }
27585
27601
  const t0 = Date.now();
27586
- const abort = createStreamAbortSignal(resolvedBudget);
27602
+ const abort = createStreamAbortSignal(resolvedBudget, signal);
27587
27603
  try {
27588
27604
  const modelInstance = getAIModel({
27589
27605
  provider: candidate.provider,
@@ -27615,6 +27631,13 @@ THINKING DIRECTIVE: Do ALL your reasoning internally BEFORE emitting output. Do
27615
27631
  }
27616
27632
  } catch (e) {
27617
27633
  console.warn(`[curriculum-kit:VercelAI] Candidate ${candidate.provider} (${candidate.model}) failed in ${Date.now() - t0}ms:`, e?.message || e);
27634
+ const isClientAborted = Boolean(
27635
+ signal?.aborted || e?.name === "AbortError" && signal?.aborted || e?.message && (e.message.includes("Controller is already closed") || e.message.includes("The operation was aborted") || e.message.includes("Aborted by parent signal"))
27636
+ );
27637
+ if (isClientAborted) {
27638
+ console.log(`[curriculum-kit:VercelAI] Client aborted or stream closed, halting candidate fallback loop.`);
27639
+ break;
27640
+ }
27618
27641
  } finally {
27619
27642
  abort.dispose();
27620
27643
  }
@@ -27666,7 +27689,8 @@ Return concise JSON matching:
27666
27689
  totalMs: options.timeoutMs,
27667
27690
  model: options.model,
27668
27691
  provider: options.provider
27669
- })
27692
+ }),
27693
+ options.signal
27670
27694
  );
27671
27695
  let parsedResearch = {
27672
27696
  groundTruthSummary: `Verified ecosystem standards for ${projectName}`,
@@ -27876,7 +27900,8 @@ REQUIREMENT: Synthesize ALL parameters above \u2014 every single line in FULL AC
27876
27900
  totalMs: options.timeoutMs,
27877
27901
  model: options.model,
27878
27902
  provider: options.provider
27879
- })
27903
+ }),
27904
+ options.signal
27880
27905
  );
27881
27906
  const parsed = safeParseJson(rawContent);
27882
27907
  return {