ki integration
This commit is contained in:
167
client/src/lib/folders.ts
Normal file
167
client/src/lib/folders.ts
Normal file
@@ -0,0 +1,167 @@
|
||||
import { ID, Query, databaseId, tables } from './appwrite';
|
||||
import { teamRechte } from './permissions';
|
||||
|
||||
/**
|
||||
* Ein Ordner ist ein **privater Wissens-Scope**, kein Sortier-Ordner
|
||||
* (konzept-bilder-feed.md §9). Beim Generieren zieht P4 nur die Attribute des
|
||||
* gewählten Ordners – er überschreibt die brand-weite Ebene vollständig,
|
||||
* gemischt wird nicht.
|
||||
*/
|
||||
export type Ordner = {
|
||||
$id: string;
|
||||
brand_id: string;
|
||||
name: string;
|
||||
theme_md?: string;
|
||||
zweck?: string;
|
||||
startwert_modus?: Startwert;
|
||||
ist_default?: boolean;
|
||||
post_count?: number;
|
||||
signal_count?: number;
|
||||
};
|
||||
|
||||
/** `sammlung` = nur einsortieren · `wissens_scope` = daraus erstellen. */
|
||||
export type Zweck = 'sammlung' | 'wissens_scope';
|
||||
/** Woher die Attribut-Scores beim Anlegen kommen. */
|
||||
export type Startwert = 'erben' | 'aus_posts' | 'neutral';
|
||||
|
||||
export const ZWECKE: { wert: Zweck; titel: string; erklaerung: string }[] = [
|
||||
{
|
||||
wert: 'wissens_scope',
|
||||
titel: 'Daraus erstellen',
|
||||
erklaerung: 'Generierungen ziehen ihr Wissen aus diesem Ordner. Das ist der Normalfall.',
|
||||
},
|
||||
{
|
||||
wert: 'sammlung',
|
||||
titel: 'Nur sammeln',
|
||||
erklaerung: 'Reine Ablage zum Sortieren. Beeinflusst keine Generierung.',
|
||||
},
|
||||
];
|
||||
|
||||
export const STARTWERTE: { wert: Startwert; titel: string; erklaerung: string }[] = [
|
||||
{
|
||||
wert: 'erben',
|
||||
titel: 'Vom Konto erben',
|
||||
erklaerung: 'Startet mit einer Kopie der bisherigen Scores. Gut, wenn der Ordner die Marke fortsetzt.',
|
||||
},
|
||||
{
|
||||
wert: 'aus_posts',
|
||||
titel: 'Nur aus den Posts',
|
||||
erklaerung:
|
||||
'Startet leer und lernt ausschließlich aus dem, was hier landet. Gut, wenn der Ordner bewusst anders aussehen soll als der Rest.',
|
||||
},
|
||||
];
|
||||
|
||||
export async function ordnerListe(brandId: string): Promise<Ordner[]> {
|
||||
const res = await tables.listRows({
|
||||
databaseId,
|
||||
tableId: 'folders',
|
||||
queries: [Query.equal('brand_id', brandId), Query.limit(100)],
|
||||
});
|
||||
return res.rows as unknown as Ordner[];
|
||||
}
|
||||
|
||||
export async function ordnerLesen(id: string): Promise<Ordner> {
|
||||
const row = await tables.getRow({ databaseId, tableId: 'folders', rowId: id });
|
||||
return row as unknown as Ordner;
|
||||
}
|
||||
|
||||
export async function ordnerAnlegen(
|
||||
brandId: string,
|
||||
teamId: string,
|
||||
daten: { name: string; zweck: Zweck; startwert_modus: Startwert; theme_md?: string },
|
||||
): Promise<Ordner> {
|
||||
const row = await tables.createRow({
|
||||
databaseId,
|
||||
tableId: 'folders',
|
||||
rowId: ID.unique(),
|
||||
data: {
|
||||
brand_id: brandId,
|
||||
name: daten.name,
|
||||
zweck: daten.zweck,
|
||||
startwert_modus: daten.startwert_modus,
|
||||
theme_md: daten.theme_md ?? '',
|
||||
ist_default: false,
|
||||
post_count: 0,
|
||||
signal_count: 0,
|
||||
},
|
||||
permissions: teamRechte(teamId),
|
||||
});
|
||||
|
||||
const ordner = row as unknown as Ordner;
|
||||
await ordnerInitialisieren(brandId, teamId, ordner.$id, daten.startwert_modus);
|
||||
return ordner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Füllt `attribute_scores` für einen frischen Ordner.
|
||||
*
|
||||
* `erben` kopiert die brand-weite Ebene (`folder_id = null`) – der Ordner setzt
|
||||
* die Marke fort. `aus_posts` und `neutral` starten leer: dort soll das Wissen
|
||||
* ausschließlich aus dem entstehen, was später hineinkommt. Genau das ist der
|
||||
* Zweck der Ordner – Wissen **segmentieren statt mitteln**
|
||||
* (konzept-bilder-feed.md §9).
|
||||
*
|
||||
* Läuft vorerst im Client statt in der Function `ordner-initialisieren`. Das
|
||||
* ist vertretbar, weil nur eigene Zeilen kopiert werden und die Zeilenrechte
|
||||
* das ohnehin begrenzen – beim Umzug in eine Function ändert sich nur der Ort.
|
||||
*/
|
||||
export async function ordnerInitialisieren(
|
||||
brandId: string,
|
||||
teamId: string,
|
||||
folderId: string,
|
||||
modus: Startwert,
|
||||
): Promise<number> {
|
||||
if (modus !== 'erben') return 0;
|
||||
|
||||
const quelle = await tables.listRows({
|
||||
databaseId,
|
||||
tableId: 'attribute_scores',
|
||||
queries: [Query.equal('brand_id', brandId), Query.isNull('folder_id'), Query.limit(200)],
|
||||
});
|
||||
|
||||
const rechte = teamRechte(teamId);
|
||||
let kopiert = 0;
|
||||
for (const z of quelle.rows as unknown as BrandScore[]) {
|
||||
await tables.createRow({
|
||||
databaseId,
|
||||
tableId: 'attribute_scores',
|
||||
rowId: ID.unique(),
|
||||
data: {
|
||||
brand_id: brandId,
|
||||
attribute_id: z.attribute_id,
|
||||
category_id: z.category_id,
|
||||
folder_id: folderId,
|
||||
score: z.score ?? 5000,
|
||||
start_value: z.score ?? 5000,
|
||||
// Der Ordner erbt den Wert, aber nicht die Sicherheit: k_factor zurück
|
||||
// auf 32, weil im neuen Scope noch nichts belegt ist.
|
||||
k_factor: 32,
|
||||
start_quelle: 'geerbt',
|
||||
used_count: 0, wins: 0, losses: 0,
|
||||
},
|
||||
permissions: rechte,
|
||||
});
|
||||
kopiert++;
|
||||
}
|
||||
return kopiert;
|
||||
}
|
||||
|
||||
type BrandScore = {
|
||||
attribute_id: string;
|
||||
category_id: string;
|
||||
score?: number;
|
||||
};
|
||||
|
||||
export async function ordnerLoeschen(id: string): Promise<void> {
|
||||
await tables.deleteRow({ databaseId, tableId: 'folders', rowId: id });
|
||||
}
|
||||
|
||||
/** „4 Posts – lernt noch“: ohne Reifegrad ist für den Nutzer nicht erklärbar,
|
||||
* warum zwei gleiche Prompts verschiedene Bilder ergeben (app-aufbau.md §5.3). */
|
||||
export function reifegrad(o: Ordner): string {
|
||||
const posts = o.post_count ?? 0;
|
||||
const signale = o.signal_count ?? 0;
|
||||
if (posts === 0) return 'leer';
|
||||
if (signale < 5) return `${posts} Posts – lernt noch`;
|
||||
return `${posts} Posts – eingespielt`;
|
||||
}
|
||||
Reference in New Issue
Block a user