@cat-factory/app 0.214.0 → 0.215.1

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.
@@ -227,6 +227,20 @@ function setMediaTypes(text: string) {
227
227
  patch({ mediaTypes: lastWritten })
228
228
  }
229
229
 
230
+ /**
231
+ * The overlap, as `content type: id, id` per shared content type.
232
+ *
233
+ * Assembled here rather than in the read model because it needs `modalityLabel`, and it renders a
234
+ * RETIRED content type through the same guard every other line does: a step saved under an older
235
+ * vocabulary can hold one, and two integrations serving it would otherwise put a `TypeError` on
236
+ * the surface where the re-pick has to be made.
237
+ */
238
+ const overlapSummary = computed(() =>
239
+ pick.value.generatorOverlaps
240
+ .map((overlap) => `${modalityLabel(overlap.modality)}: ${overlap.generatorIds.join(', ')}`)
241
+ .join('; '),
242
+ )
243
+
230
244
  /** What the SELECTED integrations say they emit — the discoverable half of the free-text field. */
231
245
  const declaredFormats = computed(() => {
232
246
  const byId = new Map(agents.binaryGenerators.map((generator) => [generator.id, generator]))
@@ -423,6 +437,17 @@ const declaredFormats = computed(() => {
423
437
  })
424
438
  }}
425
439
  </p>
440
+ <!-- ADVISORY, and grouped with the line above it rather than the refusals: selecting two
441
+ producers of one content type is the reason the selection is a list, and nothing about
442
+ the step is wrong. What it costs is a decision nobody wrote down, so the remedy this
443
+ line carries is the step's own prompt, which is the field right beside it. -->
444
+ <p
445
+ v-if="has('generator_overlap')"
446
+ class="text-[10px] text-slate-500"
447
+ data-testid="binary-output-generator-overlap"
448
+ >
449
+ {{ t('pipeline.builder.binaryOutputGeneratorOverlap', { overlaps: overlapSummary }) }}
450
+ </p>
426
451
  <p
427
452
  v-if="unusableMediaTypes.length"
428
453
  class="text-[10px] text-amber-400"
@@ -428,8 +428,9 @@ describe('binaryOutputPickIssues, generative half', () => {
428
428
  expect(pick.issues).toEqual([])
429
429
  })
430
430
 
431
- // The FORMAT half, mirroring kernel's `binaryFormatCoverage` and its three outcomes, which
432
- // are what a second copy of the rule most easily loses.
431
+ // The FORMAT half. The rule itself is contracts' `binaryFormatCoverage`, tested there; what
432
+ // these pin is the picker's own job, which is mapping its three outcomes onto two issues that
433
+ // read differently: a refusal and an advisory.
433
434
  const meshy = {
434
435
  id: 'meshy',
435
436
  modalities: ['3d-model' as const],
@@ -490,6 +491,59 @@ describe('binaryOutputPickIssues, generative half', () => {
490
491
  expect(pick.uncoveredModalities).toEqual([])
491
492
  })
492
493
 
494
+ it('flags an OVERLAP as ADVISORY, where the content type stops deciding', () => {
495
+ // The step saves and starts: two producers of one content type is the reason the selection is
496
+ // a list. What it costs is a decision nobody wrote down, and this is the surface where the
497
+ // person who knows the answer has the step's prompt already open.
498
+ const pick = binaryOutputPickIssues(
499
+ { storageServiceId: 'files', generatorIds: ['retro', 'flux'] },
500
+ catalog,
501
+ true,
502
+ [...generators, { id: 'flux', modalities: ['image' as const] }],
503
+ )
504
+ expect(pick.issues).toEqual(['generator_overlap'])
505
+ expect(pick.generatorOverlaps).toEqual([{ modality: 'image', generatorIds: ['retro', 'flux'] }])
506
+ })
507
+
508
+ it('reads a repeated id as ONE integration, exactly as the backend resolves it', () => {
509
+ // A step naming one integration twice holds one producer, so there is no choice to advise
510
+ // about, and the unknown-id list must not name the same missing id twice either.
511
+ const pick = binaryOutputPickIssues(
512
+ { storageServiceId: 'files', generatorIds: ['retro', 'retro', 'ghost', 'ghost'] },
513
+ catalog,
514
+ true,
515
+ generators,
516
+ )
517
+ expect(pick.issues).toEqual(['unknown_generator'])
518
+ expect(pick.unknownGeneratorIds).toEqual(['ghost'])
519
+ expect(pick.generatorOverlaps).toEqual([])
520
+ })
521
+
522
+ it('says nothing about an overlap while one integration produces each content type', () => {
523
+ const pick = binaryOutputPickIssues(
524
+ { storageServiceId: 'files', generatorIds: ['retro', 'studio'] },
525
+ catalog,
526
+ true,
527
+ generators,
528
+ )
529
+ expect(pick.issues).not.toContain('generator_overlap')
530
+ expect(pick.generatorOverlaps).toEqual([])
531
+ })
532
+
533
+ it('claims no overlap about a set nobody could read', () => {
534
+ // Same rule every other generative judgement here follows: an unreachable mothership answers
535
+ // the same empty list a deployment registering nothing does, and only one of them is a fact.
536
+ const pick = binaryOutputPickIssues(
537
+ { storageServiceId: 'files', generatorIds: ['retro', 'flux'] },
538
+ catalog,
539
+ true,
540
+ [],
541
+ true,
542
+ )
543
+ expect(pick.issues).toEqual(['generators_unavailable'])
544
+ expect(pick.generatorOverlaps).toEqual([])
545
+ })
546
+
493
547
  it('still judges an EMPTY set, which is a real answer about the deployment', () => {
494
548
  // The distinction the flag exists for: same empty list, opposite fact, opposite message.
495
549
  const pick = binaryOutputPickIssues(
@@ -1,5 +1,14 @@
1
- import { ASSET_STORAGE_CAPABILITY, normalizeMediaType } from '@cat-factory/contracts'
2
- import type { BinaryModality, RegisteredBinaryGenerator } from '@cat-factory/contracts'
1
+ import {
2
+ ASSET_STORAGE_CAPABILITY,
3
+ binaryFormatCoverage,
4
+ binaryModalityOverlaps,
5
+ normalizeMediaType,
6
+ } from '@cat-factory/contracts'
7
+ import type {
8
+ BinaryModality,
9
+ BinaryModalityOverlap,
10
+ RegisteredBinaryGenerator,
11
+ } from '@cat-factory/contracts'
3
12
  import type {
4
13
  BinaryOutputArtifact,
5
14
  BinaryOutputConfig,
@@ -412,6 +421,22 @@ export type BinaryOutputPickIssue =
412
421
  * comes to look exactly like "this is fine".
413
422
  */
414
423
  | 'media_type_unverifiable'
424
+ /**
425
+ * Two or more selected integrations produce the SAME content type, so the content type no
426
+ * longer decides which one the agent calls.
427
+ *
428
+ * ADVISORY, like `media_type_unverifiable` and unlike everything above it: the step saves, it
429
+ * starts, and selecting two producers of one kind is the whole reason the selection is a list.
430
+ * What it costs is a decision nobody has written down, and the agent resolves an unstated
431
+ * choice by picking one and picking it consistently, which is invisible in the artifacts,
432
+ * since every one of them has the right modality, the right format and a clean storage verdict.
433
+ *
434
+ * It is raised HERE as well as in the agent's brief because this is the surface where it can be
435
+ * acted on: the person selecting two integrations is the one who knows why, and the step's
436
+ * prompt is a field they already have open. The brief catches the step whose author did not
437
+ * think to write it; this catches the author.
438
+ */
439
+ | 'generator_overlap'
415
440
 
416
441
  /** What the builder found wrong with one step's selection, and which ids to name. */
417
442
  export interface BinaryOutputPickState {
@@ -426,6 +451,12 @@ export interface BinaryOutputPickState {
426
451
  uncoveredMediaTypes: readonly string[]
427
452
  /** The declared formats that could not be judged, kept apart from the refusal above. */
428
453
  unverifiableMediaTypes: readonly string[]
454
+ /**
455
+ * The content types more than one selected integration produces, with the ids that share each.
456
+ * Computed through the SAME `binaryModalityOverlaps` the agent's brief renders from, so the
457
+ * picker and the brief cannot describe one selection two ways.
458
+ */
459
+ generatorOverlaps: readonly BinaryModalityOverlap[]
429
460
  }
430
461
 
431
462
  /**
@@ -433,6 +464,12 @@ export interface BinaryOutputPickState {
433
464
  * `binaryGeneratorSelectionIssues` so the builder surfaces the `binary_output_generator_invalid`
434
465
  * refusal before the round trip rather than inventing a second opinion.
435
466
  *
467
+ * What is mirrored is the DISPOSITION: which conditions refuse, which advise, and what each is
468
+ * called on this surface. The two rules underneath are IMPORTED (`binaryFormatCoverage`,
469
+ * `binaryModalityOverlaps`), because a rule restated on both sides of a wire is one that can come
470
+ * to two answers about the same selection, and the reader here is the person who would then be
471
+ * told the builder's version and the agent the other.
472
+ *
436
473
  * `unavailable` is the one state that is NOT derivable from the list, which is why the snapshot
437
474
  * carries it as its own flag. An empty list normally IS a real empty — this deployment registers
438
475
  * none — and that is exactly why a selected id in that state is `unknown_generator` rather than
@@ -453,16 +490,21 @@ function generatorPickIssues(
453
490
  uncovered: BinaryModality[]
454
491
  uncoveredMediaTypes: string[]
455
492
  unverifiableMediaTypes: string[]
493
+ overlaps: BinaryModalityOverlap[]
456
494
  } {
457
495
  const none = {
458
496
  unknownGeneratorIds: [],
459
497
  uncovered: [],
460
498
  uncoveredMediaTypes: [],
461
499
  unverifiableMediaTypes: [],
500
+ overlaps: [],
462
501
  }
463
502
  if (unavailable) return { issues: ['generators_unavailable'], ...none }
464
503
  const byId = new Map(generators.map((g) => [g.id, g]))
465
- const selectedIds = config?.generatorIds ?? []
504
+ // Deduplicated on the way in, exactly as `resolveBinaryGeneratorSelection` does it on the
505
+ // backend: a step that names one integration twice holds ONE, and every line below states a
506
+ // count or a list a repeat would double.
507
+ const selectedIds = [...new Set(config?.generatorIds ?? [])]
466
508
  const unknownGeneratorIds = selectedIds.filter((id) => !byId.has(id))
467
509
  // Coverage is judged against what RESOLVED, exactly as admission judges it: an unknown id
468
510
  // contributes no content types, so a step whose only audio generator is unregistered is told
@@ -470,49 +512,28 @@ function generatorPickIssues(
470
512
  const selected = selectedIds.flatMap((id) => byId.get(id) ?? [])
471
513
  const covered = new Set(selected.flatMap((g) => g.modalities))
472
514
  const uncovered = (config?.modalities ?? []).filter((m) => !covered.has(m))
473
- const format = formatCoverage(config?.mediaTypes ?? [], selected)
515
+ const format = binaryFormatCoverage(config?.mediaTypes ?? [], selected)
516
+ // Judged against what RESOLVED, like every rule above it, and against the SELECTION rather than
517
+ // the step's declared content types: the case that most often puts two producers of one kind on
518
+ // one step is the one where neither is the deliverable (an image generated to feed a mesh API),
519
+ // and gating on `modalities` would go silent on exactly that step.
520
+ const overlaps = binaryModalityOverlaps(selected)
474
521
  const issues: BinaryOutputPickIssue[] = []
475
522
  if (unknownGeneratorIds.length) issues.push('unknown_generator')
476
523
  if (uncovered.length) issues.push('modality_uncovered')
477
524
  if (format.uncovered.length) issues.push('media_type_uncovered')
478
525
  if (format.unverifiable.length) issues.push('media_type_unverifiable')
526
+ if (overlaps.length) issues.push('generator_overlap')
479
527
  return {
480
528
  issues,
481
529
  unknownGeneratorIds,
482
530
  uncovered,
483
531
  uncoveredMediaTypes: format.uncovered,
484
532
  unverifiableMediaTypes: format.unverifiable,
533
+ overlaps,
485
534
  }
486
535
  }
487
536
 
488
- /**
489
- * The SPA's copy of kernel's `binaryFormatCoverage`, restated for the reason the two `*_service`
490
- * members above are: the builder cannot see kernel, and the wire vocabulary that does cross
491
- * (`@cat-factory/contracts`) carries the schema, not the rule.
492
- *
493
- * The THIRD outcome is what must not be lost in the copying. A generator that declares no formats
494
- * has said "only my modality is known" — a documented state, not an empty answer — so a
495
- * requirement it cannot be judged against is unverifiable and the step still starts. Collapsing
496
- * that into `uncovered` would flag steps the backend admits (and send someone editing a selection
497
- * that is fine); collapsing it into silence would present an unchecked requirement as a checked
498
- * one.
499
- */
500
- function formatCoverage(
501
- required: readonly string[],
502
- selected: readonly Pick<RegisteredBinaryGenerator, 'mediaTypes'>[],
503
- ): { uncovered: string[]; unverifiable: string[] } {
504
- const emitted = new Set(selected.flatMap((g) => g.mediaTypes ?? []))
505
- const undeclared = selected.some((g) => (g.mediaTypes ?? []).length === 0)
506
- const uncovered: string[] = []
507
- const unverifiable: string[] = []
508
- for (const mediaType of required) {
509
- if (emitted.has(mediaType)) continue
510
- if (undeclared) unverifiable.push(mediaType)
511
- else uncovered.push(mediaType)
512
- }
513
- return { uncovered, unverifiable }
514
- }
515
-
516
537
  /**
517
538
  * Validate a step's selection against the workspace's RESOLVED catalog — the same catalog run
518
539
  * admission re-validates against, which is the whole reason the picker offers only resolved
@@ -572,6 +593,7 @@ export function binaryOutputPickIssues(
572
593
  uncoveredModalities: generative.uncovered,
573
594
  uncoveredMediaTypes: generative.uncoveredMediaTypes,
574
595
  unverifiableMediaTypes: generative.unverifiableMediaTypes,
596
+ generatorOverlaps: generative.overlaps,
575
597
  }
576
598
  }
577
599
 
@@ -595,5 +617,6 @@ export function binaryOutputPickIssues(
595
617
  uncoveredModalities: generative.uncovered,
596
618
  uncoveredMediaTypes: generative.uncoveredMediaTypes,
597
619
  unverifiableMediaTypes: generative.unverifiableMediaTypes,
620
+ generatorOverlaps: generative.overlaps,
598
621
  }
599
622
  }
@@ -3931,6 +3931,7 @@
3931
3931
  "binaryOutputMediaTypeUnverifiable": "Keine ausgewählte Integration gibt {formats} an, aber eine von ihnen gibt überhaupt keine Formate an, daher konnte das nicht geprüft werden. Der Schritt startet trotzdem; prüfe in der API der Integration, ob sie das erzeugen kann.",
3932
3932
  "binaryOutputMediaTypeUnusable": "Nicht gespeichert, denn dies sind keine Medientypen: {entries}. Schreibe jeden als type/subtype.",
3933
3933
  "binaryOutputGeneratorMissing": "Diese Installation registriert diese generativen Integrationen nicht: {ids}. Sie werden im Code der Installation registriert, nicht in diesem Workspace.",
3934
+ "binaryOutputGeneratorOverlap": "Mehrere ausgewählte Integrationen erzeugen denselben Inhaltstyp ({overlaps}). Daran ist nichts falsch, aber der Inhaltstyp entscheidet nicht mehr, welche der Agent aufruft: Lege im Prompt dieses Schritts fest, welche wofür verwendet wird, sonst wählt er eine aus und bleibt dabei.",
3934
3935
  "binaryOutputModalityUncovered": "Keine ausgewählte Integration erzeugt {modalities}, was dieser Schritt liefern soll.",
3935
3936
  "binaryOutputModalityRetired": "{modality} (nicht mehr verfügbar — wähle die Inhaltstypen dieses Schritts neu)",
3936
3937
  "binaryOutputModality": {
@@ -4424,6 +4424,8 @@
4424
4424
  "binaryOutputMediaTypeUnverifiable": "No selected integration declares {formats}, but one of them declares no formats at all, so this could not be checked. The step still starts; confirm from the integration's API that it can emit this.",
4425
4425
  "binaryOutputMediaTypeUnusable": "Not saved, because these are not media types: {entries}. Write each one as type/subtype.",
4426
4426
  "binaryOutputGeneratorMissing": "This deployment does not register these generative integrations: {ids}. They are registered in the deployment's code, not in this workspace.",
4427
+ "binaryOutputGeneratorOverlap": "More than one selected integration produces the same content type ({overlaps}). Nothing is wrong with that, but the content type no longer decides which one the agent calls: say in this step's prompt which to use for what, or it will pick one and keep picking it.",
4428
+ "@binaryOutputGeneratorOverlap": "{overlaps} is assembled by the app, not prose: a semicolon-separated list of 'content type: id, id' (e.g. 'Images: flux, retro-diffusion'). The ids are raw machine values and must not be translated; only the content-type label before each colon is translated, and it comes from its own key. This is advice, not an error: the step saves and runs either way, so keep the tone neutral.",
4427
4429
  "binaryOutputModalityUncovered": "No selected integration produces {modalities}, which this step is set to deliver.",
4428
4430
  "binaryOutputModalityRetired": "{modality} (no longer offered — re-pick this step's content types)",
4429
4431
  "@binaryOutputModalityRetired": "A content type saved on a step that this build no longer defines. {modality} is a raw machine value (e.g. 3d) and must not be translated. Appears inside the binaryOutputModalityUncovered sentence, so keep it a short noun phrase, not a sentence.",
@@ -4293,6 +4293,7 @@
4293
4293
  "binaryOutputMediaTypeUnverifiable": "Ninguna integración seleccionada declara {formats}, pero una de ellas no declara ningún formato, así que no se pudo comprobar. El paso se inicia igualmente; confirma en la API de la integración que puede emitirlo.",
4294
4294
  "binaryOutputMediaTypeUnusable": "No se guardó, porque esto no son tipos de medio: {entries}. Escribe cada uno como type/subtype.",
4295
4295
  "binaryOutputGeneratorMissing": "Esta instalación no registra estas integraciones generativas: {ids}. Se registran en el código de la instalación, no en este espacio de trabajo.",
4296
+ "binaryOutputGeneratorOverlap": "Más de una integración seleccionada produce el mismo tipo de contenido ({overlaps}). No hay nada malo en ello, pero el tipo de contenido ya no decide a cuál llama el agente: indica en el prompt de este paso cuál usar para qué, o elegirá una y seguirá usando esa.",
4296
4297
  "binaryOutputModalityUncovered": "Ninguna integración seleccionada produce {modalities}, que este paso debe entregar.",
4297
4298
  "binaryOutputModalityRetired": "{modality} (ya no disponible: vuelve a elegir los tipos de contenido de este paso)",
4298
4299
  "binaryOutputModality": {
@@ -4293,6 +4293,7 @@
4293
4293
  "binaryOutputMediaTypeUnverifiable": "Aucune intégration sélectionnée ne déclare {formats}, mais l’une d’elles ne déclare aucun format, cela n’a donc pas pu être vérifié. L’étape démarre quand même ; confirmez dans l’API de l’intégration qu’elle peut l’émettre.",
4294
4294
  "binaryOutputMediaTypeUnusable": "Non enregistré, car ce ne sont pas des types de média : {entries}. Écrivez chacun sous la forme type/subtype.",
4295
4295
  "binaryOutputGeneratorMissing": "Ce déploiement n'enregistre pas ces intégrations génératives : {ids}. Elles s'enregistrent dans le code du déploiement, pas dans cet espace de travail.",
4296
+ "binaryOutputGeneratorOverlap": "Plusieurs intégrations sélectionnées produisent le même type de contenu ({overlaps}). Ce n’est pas un problème en soi, mais le type de contenu ne décide plus laquelle l’agent appelle : indiquez dans le prompt de cette étape laquelle utiliser et pour quoi, sinon il en choisira une et s’y tiendra.",
4296
4297
  "binaryOutputModalityUncovered": "Aucune intégration sélectionnée ne produit {modalities}, que cette étape doit livrer.",
4297
4298
  "binaryOutputModalityRetired": "{modality} (n'est plus proposé — resélectionnez les types de contenu de cette étape)",
4298
4299
  "binaryOutputModality": {
@@ -4304,6 +4304,7 @@
4304
4304
  "binaryOutputMediaTypeUnverifiable": "אף אינטגרציה שנבחרה אינה מצהירה על {formats}, אבל אחת מהן אינה מצהירה על פורמטים כלל, ולכן לא ניתן היה לבדוק זאת. השלב יתחיל בכל מקרה; ודאו ב-API של האינטגרציה שהיא יכולה להפיק את זה.",
4305
4305
  "binaryOutputMediaTypeUnusable": "לא נשמר, כי אלה אינם סוגי מדיה: {entries}. כתבו כל אחד בצורה type/subtype.",
4306
4306
  "binaryOutputGeneratorMissing": "ההתקנה הזו אינה רושמת את האינטגרציות הגנרטיביות האלה: {ids}. הן נרשמות בקוד ההתקנה, לא במרחב העבודה הזה.",
4307
+ "binaryOutputGeneratorOverlap": "יותר מאינטגרציה אחת שנבחרה מפיקה את אותו סוג תוכן ({overlaps}). אין בכך שום פסול, אבל סוג התוכן כבר לא קובע באיזו מהן הסוכן ישתמש: ציינו בהנחיות של השלב הזה באיזו להשתמש ולשם מה, אחרת הוא יבחר אחת וימשיך איתה.",
4307
4308
  "binaryOutputModalityUncovered": "אף אינטגרציה שנבחרה אינה מייצרת {modalities}, שהשלב הזה אמור לספק.",
4308
4309
  "binaryOutputModalityRetired": "{modality} (כבר לא נתמך — בחרו מחדש את סוגי התוכן של השלב)",
4309
4310
  "binaryOutputModality": {
@@ -3931,6 +3931,7 @@
3931
3931
  "binaryOutputMediaTypeUnverifiable": "Nessuna integrazione selezionata dichiara {formats}, ma una di esse non dichiara alcun formato, quindi non è stato possibile verificarlo. Il passaggio parte comunque; verifica nell’API dell’integrazione che possa emetterlo.",
3932
3932
  "binaryOutputMediaTypeUnusable": "Non salvato, perché questi non sono tipi di media: {entries}. Scrivi ciascuno come type/subtype.",
3933
3933
  "binaryOutputGeneratorMissing": "Questa installazione non registra queste integrazioni generative: {ids}. Si registrano nel codice dell'installazione, non in questo spazio di lavoro.",
3934
+ "binaryOutputGeneratorOverlap": "Più di un’integrazione selezionata produce lo stesso tipo di contenuto ({overlaps}). Non c’è nulla di sbagliato, ma il tipo di contenuto non decide più quale l’agente chiama: indica nel prompt di questo passaggio quale usare e per cosa, altrimenti ne sceglierà una e continuerà a usare quella.",
3934
3935
  "binaryOutputModalityUncovered": "Nessuna integrazione selezionata produce {modalities}, che questo passaggio deve fornire.",
3935
3936
  "binaryOutputModalityRetired": "{modality} (non più disponibile: riseleziona i tipi di contenuto di questo passaggio)",
3936
3937
  "binaryOutputModality": {
@@ -4305,6 +4305,7 @@
4305
4305
  "binaryOutputMediaTypeUnverifiable": "選択されたどの統合も {formats} を宣言していませんが、うち一つは形式をまったく宣言していないため、確認できませんでした。ステップはそのまま開始されます。その統合の API で出力できるか確認してください。",
4306
4306
  "binaryOutputMediaTypeUnusable": "メディアタイプではないため保存されませんでした: {entries}。それぞれ type/subtype の形で入力してください。",
4307
4307
  "binaryOutputGeneratorMissing": "このデプロイメントは次の生成統合を登録していません: {ids}。これらはこのワークスペースではなくデプロイメントのコードで登録します。",
4308
+ "binaryOutputGeneratorOverlap": "選択された統合のうち複数が同じコンテンツタイプを生成します({overlaps})。それ自体は問題ありませんが、どれを呼び出すかをコンテンツタイプが決められなくなります。このステップのプロンプトで、どれを何に使うかを指定してください。指定がなければエージェントは一つを選び、そのまま使い続けます。",
4308
4309
  "binaryOutputModalityUncovered": "このステップが提供することになっている {modalities} を、選択されたどの統合も生成できません。",
4309
4310
  "binaryOutputModalityRetired": "{modality}(現在は提供されていません。このステップのコンテンツ種別を選び直してください)",
4310
4311
  "binaryOutputModality": {
@@ -4293,6 +4293,7 @@
4293
4293
  "binaryOutputMediaTypeUnverifiable": "Żadna wybrana integracja nie deklaruje {formats}, ale jedna z nich nie deklaruje żadnych formatów, więc nie dało się tego sprawdzić. Krok i tak wystartuje; potwierdź w API integracji, że potrafi to wytworzyć.",
4294
4294
  "binaryOutputMediaTypeUnusable": "Nie zapisano, bo to nie są typy mediów: {entries}. Zapisz każdy jako type/subtype.",
4295
4295
  "binaryOutputGeneratorMissing": "Ta instalacja nie rejestruje tych integracji generatywnych: {ids}. Rejestruje się je w kodzie instalacji, a nie w tym obszarze roboczym.",
4296
+ "binaryOutputGeneratorOverlap": "Więcej niż jedna wybrana integracja tworzy ten sam typ treści ({overlaps}). Nie ma w tym nic złego, ale typ treści nie decyduje już, którą wywoła agent: napisz w promptcie tego kroku, której użyć i do czego, bo inaczej wybierze jedną i będzie jej używał dalej.",
4296
4297
  "binaryOutputModalityUncovered": "Żadna wybrana integracja nie tworzy {modalities}, które ten krok ma dostarczyć.",
4297
4298
  "binaryOutputModalityRetired": "{modality} (już niedostępne — wybierz ponownie typy treści tego kroku)",
4298
4299
  "binaryOutputModality": {
@@ -4305,6 +4305,7 @@
4305
4305
  "binaryOutputMediaTypeUnverifiable": "Seçili entegrasyonların hiçbiri {formats} bildirmiyor, ancak içlerinden biri hiç biçim bildirmiyor; bu yüzden denetlenemedi. Adım yine de başlar; entegrasyonun API’sinden bunu üretebildiğini doğrulayın.",
4306
4306
  "binaryOutputMediaTypeUnusable": "Kaydedilmedi, çünkü bunlar ortam türü değil: {entries}. Her birini type/subtype olarak yazın.",
4307
4307
  "binaryOutputGeneratorMissing": "Bu kurulum şu üretken entegrasyonları kaydetmiyor: {ids}. Bunlar bu çalışma alanında değil, kurulumun kodunda kaydedilir.",
4308
+ "binaryOutputGeneratorOverlap": "Seçili entegrasyonlardan birden fazlası aynı içerik türünü üretiyor ({overlaps}). Bunda bir sakınca yok, ancak artık hangisinin çağrılacağına içerik türü karar vermiyor: bu adımın isteminde hangisinin ne için kullanılacağını belirtin, yoksa ajan birini seçip onu kullanmayı sürdürür.",
4308
4309
  "binaryOutputModalityUncovered": "Seçili entegrasyonların hiçbiri, bu adımın teslim etmesi gereken {modalities} içeriğini üretmiyor.",
4309
4310
  "binaryOutputModalityRetired": "{modality} (artık sunulmuyor — bu adımın içerik türlerini yeniden seçin)",
4310
4311
  "binaryOutputModality": {
@@ -4293,6 +4293,7 @@
4293
4293
  "binaryOutputMediaTypeUnverifiable": "Жодна вибрана інтеграція не заявляє {formats}, але одна з них взагалі не заявляє форматів, тому перевірити це не вдалося. Крок все одно запуститься; перевірте в API інтеграції, чи може вона це створити.",
4294
4294
  "binaryOutputMediaTypeUnusable": "Не збережено, бо це не типи медіа: {entries}. Запишіть кожен як type/subtype.",
4295
4295
  "binaryOutputGeneratorMissing": "Ця інсталяція не реєструє ці генеративні інтеграції: {ids}. Їх реєструють у коді інсталяції, а не в цьому робочому просторі.",
4296
+ "binaryOutputGeneratorOverlap": "Кілька вибраних інтеграцій створюють той самий тип вмісту ({overlaps}). Нічого поганого в цьому немає, але тип вмісту більше не визначає, яку з них викличе агент: зазначте в промті цього кроку, яку і для чого використовувати, інакше він обере одну й користуватиметься лише нею.",
4296
4297
  "binaryOutputModalityUncovered": "Жодна вибрана інтеграція не створює {modalities}, які має надати цей крок.",
4297
4298
  "binaryOutputModalityRetired": "{modality} (більше не пропонується — виберіть типи вмісту цього кроку заново)",
4298
4299
  "binaryOutputModality": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/app",
3
- "version": "0.214.0",
3
+ "version": "0.215.1",
4
4
  "description": "Reusable Nuxt layer for the Agent Architecture Board SPA (components, stores, composables, pages). Consume it from a thin deployment app via `extends: ['@cat-factory/app']` and point it at your backend with NUXT_PUBLIC_API_BASE. See deploy/frontend for an example.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -40,7 +40,7 @@
40
40
  "valibot": "^1.4.2",
41
41
  "vue": "3.5.40",
42
42
  "wretch": "^3.0.9",
43
- "@cat-factory/contracts": "0.224.0"
43
+ "@cat-factory/contracts": "0.226.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@toad-contracts/testing": "0.3.2",