Versie 0.2.0
This commit is contained in:
commit
e77d8fd373
495 files changed
+81026
No files matched your search
@@ -0,0 +1,179 @@
|
||||
// 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]);
|
||||
Reference in new issue
Block a user