zam-core 0.15.6 → 0.16.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.
@@ -12262,7 +12262,7 @@ async function readWebLink(url) {
12262
12262
  redirect: "manual",
12263
12263
  signal: controller.signal,
12264
12264
  headers: {
12265
- "User-Agent": "ZAM-Content-Studio/0.15.6"
12265
+ "User-Agent": "ZAM-Content-Studio/0.16.0"
12266
12266
  }
12267
12267
  });
12268
12268
  if (res.status >= 300 && res.status < 400) {
@@ -12446,6 +12446,32 @@ function installCliShim(options = {}) {
12446
12446
  }
12447
12447
  }
12448
12448
 
12449
+ // src/cli/curriculum/concurrency.ts
12450
+ async function mapWithConcurrency(items, concurrency, mapper) {
12451
+ if (items.length === 0) return [];
12452
+ const workerCount = Math.max(
12453
+ 1,
12454
+ Math.min(items.length, Math.floor(concurrency) || 1)
12455
+ );
12456
+ const results = new Array(items.length);
12457
+ let nextIndex = 0;
12458
+ let failure;
12459
+ async function worker() {
12460
+ while (!failure) {
12461
+ const index = nextIndex++;
12462
+ if (index >= items.length) return;
12463
+ try {
12464
+ results[index] = await mapper(items[index], index);
12465
+ } catch (error) {
12466
+ failure ??= { error };
12467
+ }
12468
+ }
12469
+ }
12470
+ await Promise.all(Array.from({ length: workerCount }, () => worker()));
12471
+ if (failure) throw failure.error;
12472
+ return results;
12473
+ }
12474
+
12449
12475
  // src/cli/curriculum/breadcrumb.ts
12450
12476
  init_kernel();
12451
12477
  var LAST_SELECTION_KEY = "curriculum.lastSelection";
@@ -83619,20 +83645,29 @@ bridgeCommand.command("curriculum-preview-topic").description(
83619
83645
  parentTopicId: resolved.topicId
83620
83646
  });
83621
83647
  }
83648
+ const generationChunks = chunks.filter((chunk) => chunk.text.trim());
83649
+ const textProvider = await getProviderForRole(db, "text");
83650
+ const generatedChunks = await mapWithConcurrency(
83651
+ generationChunks,
83652
+ textProvider.local ? 1 : 3,
83653
+ async (chunk) => ({
83654
+ chunk,
83655
+ cards: await importCurriculumViaLLM(
83656
+ db,
83657
+ chunk.text,
83658
+ opts.domain,
83659
+ item.uri,
83660
+ { knowledgeContext: firstContext }
83661
+ )
83662
+ })
83663
+ );
83622
83664
  let proposalIndex = 0;
83623
- for (const chunk of chunks) {
83624
- if (!chunk.text.trim()) continue;
83625
- const cards = await importCurriculumViaLLM(
83626
- db,
83627
- chunk.text,
83628
- opts.domain,
83629
- item.uri,
83630
- { knowledgeContext: firstContext }
83631
- );
83665
+ for (const { chunk, cards } of generatedChunks) {
83632
83666
  const scopedTopicId = chunk.subTopicId ? `${resolved.topicId}@${chunk.subTopicId}` : resolved.topicId;
83633
83667
  for (const card of cards) {
83668
+ const targetDomain = (typeof opts.domain === "string" ? opts.domain.trim() : "") || card.domain;
83634
83669
  const slug = proposalBaseSlug(
83635
- card.domain,
83670
+ targetDomain.split("/")[0] || targetDomain,
83636
83671
  card.question,
83637
83672
  card.concept
83638
83673
  );
@@ -83642,7 +83677,7 @@ bridgeCommand.command("curriculum-preview-topic").description(
83642
83677
  const proposal = {
83643
83678
  question: card.question,
83644
83679
  concept: card.concept,
83645
- domain: card.domain,
83680
+ domain: targetDomain,
83646
83681
  bloom_level: card.bloom_level,
83647
83682
  symbiosis_mode: card.symbiosis_mode || "none",
83648
83683
  excerpt: card.context || "",
@@ -83660,7 +83695,7 @@ bridgeCommand.command("curriculum-preview-topic").description(
83660
83695
  symbiosis_mode: proposal.symbiosis_mode,
83661
83696
  excerpt: proposal.excerpt,
83662
83697
  isExisting: false,
83663
- selected: false,
83698
+ selected: true,
83664
83699
  subTopicId: chunk.subTopicId,
83665
83700
  parentTopicId: resolved.topicId,
83666
83701
  proposal