@x12i/catalox 3.7.1 → 3.8.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.
- package/README.md +39 -0
- package/dist/src/catalox/catalog-discovery.d.ts +1 -24
- package/dist/src/catalox/catalog-discovery.d.ts.map +1 -1
- package/dist/src/catalox/catalog-discovery.js +0 -82
- package/dist/src/catalox/catalog-discovery.js.map +1 -1
- package/dist/src/catalox/catalox-bound.d.ts +1 -5
- package/dist/src/catalox/catalox-bound.d.ts.map +1 -1
- package/dist/src/catalox/catalox-bound.js +0 -12
- package/dist/src/catalox/catalox-bound.js.map +1 -1
- package/dist/src/catalox/catalox.d.ts +1 -5
- package/dist/src/catalox/catalox.d.ts.map +1 -1
- package/dist/src/catalox/catalox.js +1 -170
- package/dist/src/catalox/catalox.js.map +1 -1
- package/dist/src/contracts/descriptor-rules.d.ts +5 -5
- package/dist/src/contracts/descriptor-rules.d.ts.map +1 -1
- package/dist/src/contracts/discovery.d.ts +0 -30
- package/dist/src/contracts/discovery.d.ts.map +1 -1
- package/dist/src/contracts/index.d.ts +2 -2
- package/dist/src/contracts/index.d.ts.map +1 -1
- package/dist/src/contracts/index.js.map +1 -1
- package/dist/src/contracts/search.d.ts +1 -108
- package/dist/src/contracts/search.d.ts.map +1 -1
- package/dist/src/firebase/bootstrap.d.ts +62 -0
- package/dist/src/firebase/bootstrap.d.ts.map +1 -1
- package/dist/src/firebase/bootstrap.js +91 -1
- package/dist/src/firebase/bootstrap.js.map +1 -1
- package/package.json +1 -2
- package/dist/src/catalox/ai-functions-loader.d.ts +0 -6
- package/dist/src/catalox/ai-functions-loader.d.ts.map +0 -1
- package/dist/src/catalox/ai-functions-loader.js +0 -19
- package/dist/src/catalox/ai-functions-loader.js.map +0 -1
|
@@ -34,8 +34,7 @@ import { SnapshotStore } from "../firebase/snapshot-store.js";
|
|
|
34
34
|
import { StoreAppBindingStore } from "../firebase/store-app-binding-store.js";
|
|
35
35
|
import { IdentityBindingStore } from "../firebase/identity-binding-store.js";
|
|
36
36
|
import { nativeItemsCollectionId } from "../firebase/catalog-data-paths.js";
|
|
37
|
-
import { applyCatalogVisibilityFilter, filterCatalogsByText,
|
|
38
|
-
import { loadAiFunctions } from "./ai-functions-loader.js";
|
|
37
|
+
import { applyCatalogVisibilityFilter, filterCatalogsByText, summarizeCatalog, } from "./catalog-discovery.js";
|
|
39
38
|
import { runBackupData, pruneGcsBackupRuns } from "./backup-data.js";
|
|
40
39
|
import { runUndoFirestoreRestore } from "./restore-firestore-backup.js";
|
|
41
40
|
import { runRestoreFirestoreBackupFromGcs, runDeleteCataloxGcsBackupRun } from "./restore-firestore-backup-from-gcs.js";
|
|
@@ -840,13 +839,6 @@ export class Catalox {
|
|
|
840
839
|
});
|
|
841
840
|
return filterCatalogsByText(all, input);
|
|
842
841
|
}
|
|
843
|
-
async findCatalogsByAi(context, input) {
|
|
844
|
-
const all = await this.listAllCatalogs(context, {
|
|
845
|
-
...(input.includeDisabled != null ? { includeDisabled: input.includeDisabled } : {}),
|
|
846
|
-
...(input.includeHidden != null ? { includeHidden: input.includeHidden } : {}),
|
|
847
|
-
});
|
|
848
|
-
return findCatalogsByAiHelper({ query: input.query, catalogs: all, input });
|
|
849
|
-
}
|
|
850
842
|
async getCatalogDescriptor(context, catalogId) {
|
|
851
843
|
const appId = await this.resolveAppIdForCatalogAccess({ context, catalogId, required: "read" });
|
|
852
844
|
await this.deps.authz.requireBindingAccess(context, appId, catalogId, "read");
|
|
@@ -1370,167 +1362,6 @@ export class Catalox {
|
|
|
1370
1362
|
});
|
|
1371
1363
|
return { ...base, items: filtered.slice(0, limit) };
|
|
1372
1364
|
}
|
|
1373
|
-
async findCatalogItemsByAi(context, catalogId, input) {
|
|
1374
|
-
const poolLimit = input.poolLimit ?? 300;
|
|
1375
|
-
const base = await this.listCatalogItems(context, catalogId, {
|
|
1376
|
-
limit: poolLimit,
|
|
1377
|
-
...(input.scope ? { scope: input.scope } : {}),
|
|
1378
|
-
...(input.filter ? { filter: input.filter } : {}),
|
|
1379
|
-
...(input.sort ? { sort: input.sort } : {}),
|
|
1380
|
-
});
|
|
1381
|
-
if (base.listOutcome !== "ok")
|
|
1382
|
-
return { query: input.query, hits: [], noMatch: true };
|
|
1383
|
-
const items = base.items;
|
|
1384
|
-
const candidates = items.map((it) => {
|
|
1385
|
-
const title = it.title ? String(it.title) : "";
|
|
1386
|
-
const subtitle = it.subtitle ? String(it.subtitle) : "";
|
|
1387
|
-
const label = [title, subtitle].filter(Boolean).join(" — ") || String(it.itemId);
|
|
1388
|
-
return {
|
|
1389
|
-
id: String(it.itemId),
|
|
1390
|
-
label,
|
|
1391
|
-
metadata: { catalogId: String(catalogId) },
|
|
1392
|
-
};
|
|
1393
|
-
});
|
|
1394
|
-
const { match } = await loadAiFunctions();
|
|
1395
|
-
const res = await match({
|
|
1396
|
-
query: input.query,
|
|
1397
|
-
candidates,
|
|
1398
|
-
...(input.guidance ? { guidance: input.guidance } : {}),
|
|
1399
|
-
...(input.maxResults != null ? { maxResults: input.maxResults } : {}),
|
|
1400
|
-
...(input.minScore != null ? { minScore: input.minScore } : {}),
|
|
1401
|
-
...(input.allowNoMatch != null ? { allowNoMatch: input.allowNoMatch } : {}),
|
|
1402
|
-
...(input.returnReasons != null ? { returnReasons: input.returnReasons } : {}),
|
|
1403
|
-
...(input.additionalInstructions ? { additionalInstructions: input.additionalInstructions } : {}),
|
|
1404
|
-
...(input.maxCandidates != null ? { maxCandidates: input.maxCandidates } : {}),
|
|
1405
|
-
...(input.mode ? { mode: input.mode } : {}),
|
|
1406
|
-
...(input.client ? { client: input.client } : {}),
|
|
1407
|
-
...(input.model ? { model: input.model } : {}),
|
|
1408
|
-
...(input.temperature != null ? { temperature: input.temperature } : {}),
|
|
1409
|
-
...(input.maxTokens != null ? { maxTokens: input.maxTokens } : {}),
|
|
1410
|
-
...(input.timeoutMs != null ? { timeoutMs: input.timeoutMs } : {}),
|
|
1411
|
-
...(input.vendor != null ? { vendor: input.vendor } : {}),
|
|
1412
|
-
});
|
|
1413
|
-
const byId = new Map(items.map((it) => [String(it.itemId), it]));
|
|
1414
|
-
const hits = res.matches
|
|
1415
|
-
.map((m) => {
|
|
1416
|
-
const it = byId.get(String(m.id));
|
|
1417
|
-
if (!it)
|
|
1418
|
-
return null;
|
|
1419
|
-
return { itemId: it.itemId, score: m.score, ...(m.reason ? { reason: m.reason } : {}), item: it };
|
|
1420
|
-
})
|
|
1421
|
-
.filter(Boolean);
|
|
1422
|
-
return { query: input.query, hits, noMatch: Boolean(res.noMatch) };
|
|
1423
|
-
}
|
|
1424
|
-
async createCatalogItemByAi(context, catalogId, input) {
|
|
1425
|
-
const appId = await this.resolveAppIdForCatalogAccess({ context, catalogId, required: "write" });
|
|
1426
|
-
await this.deps.authz.requireBindingAccess(context, appId, catalogId, "write");
|
|
1427
|
-
const descRec = await this.deps.descriptors.get(catalogId);
|
|
1428
|
-
if (!descRec)
|
|
1429
|
-
throw new CatalogAdapterError({ catalogId, reason: "missing_descriptor" });
|
|
1430
|
-
const rules = descRec.descriptor.creationRules;
|
|
1431
|
-
if (!rules)
|
|
1432
|
-
throw new CatalogAdapterError({ catalogId, reason: "creation_rules_missing" });
|
|
1433
|
-
if (rules.enabled === false)
|
|
1434
|
-
throw new CatalogAdapterError({ catalogId, reason: "creation_rules_disabled" });
|
|
1435
|
-
const catalog = await this.deps.catalogs.get(catalogId);
|
|
1436
|
-
if (!catalog)
|
|
1437
|
-
throw new CatalogNotFoundError({ catalogId });
|
|
1438
|
-
const existingLimit = input.existingItemsSampleLimit ?? 0;
|
|
1439
|
-
const existingItemsSample = existingLimit > 0
|
|
1440
|
-
? (await this.listCatalogItems(context, catalogId, { limit: existingLimit })).items.map((i) => i.data)
|
|
1441
|
-
: undefined;
|
|
1442
|
-
const { createItem } = await loadAiFunctions();
|
|
1443
|
-
const result = await createItem({
|
|
1444
|
-
...(descRec.descriptor.itemLabel ? { itemLabel: descRec.descriptor.itemLabel } : {}),
|
|
1445
|
-
creationRules: rules,
|
|
1446
|
-
provided: input.provided,
|
|
1447
|
-
fieldSchema: (descRec.descriptor.queryableFields ?? []),
|
|
1448
|
-
...(existingItemsSample ? { existingItemsSample } : {}),
|
|
1449
|
-
...(input.additionalInstructions ? { additionalInstructions: input.additionalInstructions } : {}),
|
|
1450
|
-
...(input.mode ? { mode: input.mode } : {}),
|
|
1451
|
-
...(input.model ? { model: input.model } : {}),
|
|
1452
|
-
...(input.client ? { client: input.client } : {}),
|
|
1453
|
-
...(input.temperature != null ? { temperature: input.temperature } : {}),
|
|
1454
|
-
...(input.maxTokens != null ? { maxTokens: input.maxTokens } : {}),
|
|
1455
|
-
...(input.timeoutMs != null ? { timeoutMs: input.timeoutMs } : {}),
|
|
1456
|
-
...(input.vendor != null ? { vendor: input.vendor } : {}),
|
|
1457
|
-
}, undefined);
|
|
1458
|
-
const out = {
|
|
1459
|
-
catalogId,
|
|
1460
|
-
proposed: result.item ?? {},
|
|
1461
|
-
issues: (result.issues ?? []),
|
|
1462
|
-
...(result.missingInputs ? { missingInputs: result.missingInputs } : {}),
|
|
1463
|
-
noCreate: Boolean(result.noCreate),
|
|
1464
|
-
...(result.reason ? { reason: result.reason } : {}),
|
|
1465
|
-
};
|
|
1466
|
-
const autoPersist = input.autoPersist === true;
|
|
1467
|
-
const hasErrors = (result.issues ?? []).some((i) => i?.severity === "error");
|
|
1468
|
-
if (autoPersist && !out.noCreate && !hasErrors) {
|
|
1469
|
-
if (catalog.sourceMode !== "native") {
|
|
1470
|
-
throw new CatalogAdapterError({ catalogId, reason: "autopersist_mapped_unsupported" });
|
|
1471
|
-
}
|
|
1472
|
-
const writePayload = input.scope != null ? { ...out.proposed, scope: input.scope } : out.proposed;
|
|
1473
|
-
out.item = await this.upsertNativeCatalogItem(context, catalogId, writePayload);
|
|
1474
|
-
}
|
|
1475
|
-
return out;
|
|
1476
|
-
}
|
|
1477
|
-
async modifyCatalogItemByAi(context, catalogId, itemId, input) {
|
|
1478
|
-
const appId = await this.resolveAppIdForCatalogAccess({ context, catalogId, required: "write" });
|
|
1479
|
-
await this.deps.authz.requireBindingAccess(context, appId, catalogId, "write");
|
|
1480
|
-
const descRec = await this.deps.descriptors.get(catalogId);
|
|
1481
|
-
if (!descRec)
|
|
1482
|
-
throw new CatalogAdapterError({ catalogId, reason: "missing_descriptor" });
|
|
1483
|
-
const rules = descRec.descriptor.modificationRules;
|
|
1484
|
-
if (!rules)
|
|
1485
|
-
throw new CatalogAdapterError({ catalogId, reason: "modification_rules_missing" });
|
|
1486
|
-
if (rules.enabled === false)
|
|
1487
|
-
throw new CatalogAdapterError({ catalogId, reason: "modification_rules_disabled" });
|
|
1488
|
-
const catalog = await this.deps.catalogs.get(catalogId);
|
|
1489
|
-
if (!catalog)
|
|
1490
|
-
throw new CatalogNotFoundError({ catalogId });
|
|
1491
|
-
const got = await this.getCatalogItem(context, catalogId, itemId, input.nativeItemOptions);
|
|
1492
|
-
if (got.outcome === "mapping_blocked") {
|
|
1493
|
-
throw new CatalogAdapterError({ catalogId, reason: "mapping_validation_failed", issues: got.issues });
|
|
1494
|
-
}
|
|
1495
|
-
if (got.outcome === "not_found")
|
|
1496
|
-
throw new CatalogNotFoundError({ catalogId, itemId });
|
|
1497
|
-
const currentItem = (got.item.data ?? {});
|
|
1498
|
-
const { modifyItem } = await loadAiFunctions();
|
|
1499
|
-
const result = await modifyItem({
|
|
1500
|
-
...(descRec.descriptor.itemLabel ? { itemLabel: descRec.descriptor.itemLabel } : {}),
|
|
1501
|
-
currentItem: currentItem,
|
|
1502
|
-
modificationRules: rules,
|
|
1503
|
-
patch: input.patch,
|
|
1504
|
-
fieldSchema: (descRec.descriptor.queryableFields ?? []),
|
|
1505
|
-
...(input.additionalInstructions ? { additionalInstructions: input.additionalInstructions } : {}),
|
|
1506
|
-
...(input.mode ? { mode: input.mode } : {}),
|
|
1507
|
-
...(input.model ? { model: input.model } : {}),
|
|
1508
|
-
...(input.client ? { client: input.client } : {}),
|
|
1509
|
-
...(input.temperature != null ? { temperature: input.temperature } : {}),
|
|
1510
|
-
...(input.maxTokens != null ? { maxTokens: input.maxTokens } : {}),
|
|
1511
|
-
...(input.timeoutMs != null ? { timeoutMs: input.timeoutMs } : {}),
|
|
1512
|
-
...(input.vendor != null ? { vendor: input.vendor } : {}),
|
|
1513
|
-
}, undefined);
|
|
1514
|
-
const out = {
|
|
1515
|
-
catalogId,
|
|
1516
|
-
itemId,
|
|
1517
|
-
proposed: result.item ?? {},
|
|
1518
|
-
diff: (result.diff ?? []),
|
|
1519
|
-
issues: (result.issues ?? []),
|
|
1520
|
-
...(result.violatedRules ? { violatedRules: result.violatedRules } : {}),
|
|
1521
|
-
noChange: Boolean(result.noChange),
|
|
1522
|
-
...(result.reason ? { reason: result.reason } : {}),
|
|
1523
|
-
};
|
|
1524
|
-
const autoPersist = input.autoPersist === true;
|
|
1525
|
-
const hasErrors = (result.issues ?? []).some((i) => i?.severity === "error");
|
|
1526
|
-
if (autoPersist && !out.noChange && !hasErrors) {
|
|
1527
|
-
if (catalog.sourceMode !== "native") {
|
|
1528
|
-
throw new CatalogAdapterError({ catalogId, reason: "autopersist_mapped_unsupported" });
|
|
1529
|
-
}
|
|
1530
|
-
out.item = await this.updateNativeCatalogItem(context, catalogId, itemId, out.proposed, input.nativeItemOptions);
|
|
1531
|
-
}
|
|
1532
|
-
return out;
|
|
1533
|
-
}
|
|
1534
1365
|
async bindCatalogToApp(_context, _input) {
|
|
1535
1366
|
const existing = await this.deps.bindings.findByAppCatalog(_input.appId, _input.catalogId);
|
|
1536
1367
|
if (existing)
|