179 lines
7.4 KiB
JavaScript
179 lines
7.4 KiB
JavaScript
// Generated, do not edit. sha256:c8d6a3abd48730edcf0689606e46d90e911be6fb20a947fc1829093ad98e9800
|
|||
|
|
import { listAccounts } from '../data/accounts.js';
|
||
|
|
import { listAssets } from '../data/assets.js';
|
||
|
|
import { listLabels } from '../data/labels.js';
|
||
|
|
import { accountStructure, assetStructure, labelStructure, eventRefs } from '../data/structure.js';
|
||
|
|
import { rowOrigin } from '../data/ai-proposals.js';
|
||
|
|
import { assertScope } from '../ai/gate.js';
|
||
|
|
import { limitedList } from '../ai/limits.js';
|
||
|
|
import { vertalerVoor } from './session.mjs';
|
||
|
|
import { HANDLE_VORM, idVoorHandle } from './handles.mjs';
|
||
|
|
|
||
|
|
function assetVoorSymbool(gevraagd) {
|
||
|
|
const gezocht = String(gevraagd ?? '').trim().toUpperCase();
|
||
|
|
if (!gezocht || gezocht.includes(':')) return null;
|
||
|
|
return listAssets().find(a => String(a.symbol).toUpperCase() === gezocht) || null;
|
||
|
|
}
|
||
|
|
|
||
|
|
const SOORTEN = Object.freeze({
|
||
|
|
account: Object.freeze({ ids: () => listAccounts().map(r => r.id), structuur: accountStructure }),
|
||
|
|
asset: Object.freeze({ ids: () => listAssets().map(r => r.id), structuur: assetStructure }),
|
||
|
|
label: Object.freeze({ ids: () => listLabels().map(r => r.id), structuur: labelStructure }),
|
||
|
|
});
|
||
|
|
|
||
|
|
const SOORT_NAMEN = Object.keys(SOORTEN);
|
||
|
|
|
||
|
|
const telRegel = (aantal, enkelvoud, meervoud) =>
|
||
|
|
`${aantal} ${aantal === 1 ? enkelvoud : meervoud}`;
|
||
|
|
|
||
|
|
const TELLING_TEKST = Object.freeze({
|
||
|
|
events: n => telRegel(n, 'gebeurtenis', 'gebeurtenissen'),
|
||
|
|
assets: n => telRegel(n, 'asset waarin geboekt is', 'assets waarin geboekt is'),
|
||
|
|
accounts: n => telRegel(n, 'account waarop hij voorkomt', 'accounts waarop hij voorkomt'),
|
||
|
|
walletSources: n => telRegel(n, 'wallet-bron', 'wallet-bronnen'),
|
||
|
|
addresses: n => telRegel(n, 'adres', 'adressen'),
|
||
|
|
walletTransactions: n => telRegel(n, 'on-chain beweging', 'on-chain bewegingen'),
|
||
|
|
valuations: n => telRegel(n, 'balans', 'balansen'),
|
||
|
|
pricePoints: n => telRegel(n, 'koerspunt', 'koerspunten'),
|
||
|
|
products: n => telRegel(n, 'metaalproduct', 'metaalproducten'),
|
||
|
|
coverage: n => telRegel(n, 'koersbron die dit symbool zegt te dekken', 'koersbronnen die dit symbool zeggen te dekken'),
|
||
|
|
});
|
||
|
|
|
||
|
|
function rijRegels(veilig) {
|
||
|
|
return Object.entries(veilig)
|
||
|
|
.filter(([naam]) => naam !== 'id')
|
||
|
|
.map(([naam, waarde]) => ` ${naam} = ${waarde === null ? '(leeg)' : waarde}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
const recordDetail = Object.freeze({
|
||
|
|
name: 'record_detail',
|
||
|
|
title: 'Eén rij uitdiepen',
|
||
|
|
description:
|
||
|
|
'Geeft van één rij uit de administratie van AssetApp terug waar hij aan vasthangt: zijn eigen '
|
||
|
|
+ 'kenmerken en hoeveel gebeurtenissen, adressen, balansen en koerspunten eraan hangen. Bedoeld als '
|
||
|
|
+ 'vervolgvraag op een verwijzing die admin_overview of data_health heeft gegeven. Werkt op een '
|
||
|
|
+ 'account (account:...) of een label (label:...), ook als die verwijzing uit een eerder gesprek '
|
||
|
|
+ 'komt, en op een asset bij zijn SYMBOOL (BTC). Bij die twee ook de gebeurtenissen met hun '
|
||
|
|
+ 'verwijzing, soort en maand. Alleen kenmerken, aantallen en verwijzingen; geen bedragen, geen '
|
||
|
|
+ 'exacte datums en geen adressen, en wijzigt niets.',
|
||
|
|
inputSchema: Object.freeze({
|
||
|
|
type: 'object',
|
||
|
|
properties: {
|
||
|
|
handle: {
|
||
|
|
type: 'string',
|
||
|
|
maxLength: 64,
|
||
|
|
description:
|
||
|
|
'De verwijzing zoals een andere tool hem gaf (account:7f3a9c, label:9e8f7a), of het symbool '
|
||
|
|
+ 'van een asset (BTC).',
|
||
|
|
},
|
||
|
|
},
|
||
|
|
required: ['handle'],
|
||
|
|
additionalProperties: false,
|
||
|
|
}),
|
||
|
|
scope: 'read',
|
||
|
|
|
||
|
|
async run(args, context) {
|
||
|
|
assertScope(recordDetail.scope);
|
||
|
|
const t = await vertalerVoor(context);
|
||
|
|
t.beginCall();
|
||
|
|
|
||
|
|
const gevraagd = typeof args?.handle === 'string' ? args.handle.trim() : '';
|
||
|
|
|
||
|
|
const symbool = assetVoorSymbool(gevraagd);
|
||
|
|
if (symbool) return detailVan('asset', symbool.id, gevraagd, t);
|
||
|
|
|
||
|
|
const vorm = HANDLE_VORM.exec(gevraagd);
|
||
|
|
if (!vorm) {
|
||
|
|
return {
|
||
|
|
text: `'${gevraagd}' is geen verwijzing zoals deze app ze uitdeelt en geen asset-symbool. `
|
||
|
|
+ `Verwijzingen zien eruit als account:7f3a9c: een soort, een dubbele punt en zes tekens. `
|
||
|
|
+ `Staat onbewerkt delen aan, dan is het de soort met het rij-id erachter, zoals account:3. `
|
||
|
|
+ `Een asset wijs je aan met zijn symbool, zoals BTC.`,
|
||
|
|
fieldsShared: [],
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
const soort = vorm[1];
|
||
|
|
if (!Object.hasOwn(SOORTEN, soort)) {
|
||
|
|
return {
|
||
|
|
text: `Een verwijzing van de soort '${soort}' kan deze tool niet uitdiepen. Dat kan voor: `
|
||
|
|
+ `${SOORT_NAMEN.join(', ')}.`,
|
||
|
|
fieldsShared: [],
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
const kandidaten = SOORTEN[soort].ids();
|
||
|
|
const id = idVoorHandle(t, soort, gevraagd, kandidaten) ?? idVoorHandle(t, soort, vorm[2], kandidaten);
|
||
|
|
if (id === null) {
|
||
|
|
return {
|
||
|
|
text: `De verwijzing ${gevraagd} hoort bij geen enkele ${soort} in deze administratie. `
|
||
|
|
+ `Mogelijk is de rij verwijderd.`,
|
||
|
|
fieldsShared: [],
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
return detailVan(soort, id, gevraagd, t);
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
function detailVan(soort, id, gevraagd, t) {
|
||
|
|
{
|
||
|
|
const structuur = SOORTEN[soort].structuur(id);
|
||
|
|
if (!structuur) {
|
||
|
|
return { text: `De ${soort} achter ${gevraagd} bestaat niet meer.`, fieldsShared: [] };
|
||
|
|
}
|
||
|
|
|
||
|
|
const veilig = t.toAi(structuur.row, { entity: soort });
|
||
|
|
const tellingen = limitedList(
|
||
|
|
Object.entries(structuur.counts),
|
||
|
|
([naam, n]) => ` ${TELLING_TEKST[naam] ? TELLING_TEKST[naam](n) : `${naam} = ${n}`}`,
|
||
|
|
).lines;
|
||
|
|
|
||
|
|
const verwijzingen = Object.entries(structuur.refs)
|
||
|
|
.filter(([, ids]) => Array.isArray(ids) && ids.length)
|
||
|
|
.map(([naam, ids]) => {
|
||
|
|
const soortVanRef = naam === 'assetIds' ? 'asset' : 'account';
|
||
|
|
const { lines } = limitedList(ids, refId => ` ${t.toAi({ id: refId }, { entity: soortVanRef }).id}`);
|
||
|
|
return [`${naam === 'assetIds' ? 'Assets' : 'Accounts'}:`, ...lines].join('\n');
|
||
|
|
});
|
||
|
|
|
||
|
|
const gebeurtenissen = (soort === 'account' || soort === 'asset')
|
||
|
|
? limitedList(
|
||
|
|
eventRefs(soort === 'account' ? { accountId: id } : { assetId: id }),
|
||
|
|
(e) => {
|
||
|
|
const uit = rowOrigin('event', e.id);
|
||
|
|
const bron = uit ? ` · uit ${t.toAi({ id: uit.proposalId }, { entity: 'proposal' }).id}` : '';
|
||
|
|
return ` ${t.toAi({ id: e.id }, { entity: 'event' }).id} · ${e.type} · ${e.month}${bron}`;
|
||
|
|
},
|
||
|
|
).lines
|
||
|
|
: [];
|
||
|
|
|
||
|
|
const herkomst = soort === 'account' ? rowOrigin('account', id) : null;
|
||
|
|
const herkomstRegels = herkomst
|
||
|
|
? ['', `Ontstaan uit ${t.toAi({ id: herkomst.proposalId }, { entity: 'proposal' }).id}, `
|
||
|
|
+ `goedgekeurd op ${String(herkomst.resolvedAt || '').slice(0, 10)}.`]
|
||
|
|
: [];
|
||
|
|
|
||
|
|
return {
|
||
|
|
text: [
|
||
|
|
`${soort} ${gevraagd}:`,
|
||
|
|
...rijRegels(veilig),
|
||
|
|
'',
|
||
|
|
'Hangt eraan:',
|
||
|
|
...tellingen,
|
||
|
|
...herkomstRegels,
|
||
|
|
...(gebeurtenissen.length ? ['', 'Gebeurtenissen (nieuwste eerst, maand):', ...gebeurtenissen] : []),
|
||
|
|
...(verwijzingen.length ? ['', ...verwijzingen] : []),
|
||
|
|
].join('\n'),
|
||
|
|
fieldsShared: [...new Set([
|
||
|
|
...t.fieldsShared(),
|
||
|
|
'assetId', 'fromAccountId', 'toAccountId', 'accountId', 'labelId', 'providerId',
|
||
|
|
...(gebeurtenissen.length ? ['type', 'occurredAt'] : []),
|
||
|
|
...(gebeurtenissen.some(r => r.includes(' · uit ')) ? ['createdEventId'] : []),
|
||
|
|
...(herkomst ? ['createdAccountId'] : []),
|
||
|
|
])].sort(),
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export const DETAIL_TOOLS = Object.freeze([recordDetail]);
|