paisa-mcp 0.2.0 → 0.3.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.
- package/dist/index.js +575 -910
- package/dist/index.js.map +28 -27
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -53145,6 +53145,90 @@ class PaisaApiClient {
|
|
|
53145
53145
|
}
|
|
53146
53146
|
}
|
|
53147
53147
|
|
|
53148
|
+
// ../../node_modules/.bun/@nimit9+signet-lib@0.1.15+d40099021b198cb0/node_modules/@nimit9/signet-lib/dist/crypto/index.js
|
|
53149
|
+
var isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
53150
|
+
async function decryptFields(input2, paths, { decrypt, isCiphertext }) {
|
|
53151
|
+
const undecrypted = [];
|
|
53152
|
+
const pending = [];
|
|
53153
|
+
const looksEncrypted = (value, path) => {
|
|
53154
|
+
if (!isCiphertext)
|
|
53155
|
+
return true;
|
|
53156
|
+
try {
|
|
53157
|
+
return isCiphertext(value, path) !== false;
|
|
53158
|
+
} catch {
|
|
53159
|
+
return true;
|
|
53160
|
+
}
|
|
53161
|
+
};
|
|
53162
|
+
const decryptInto = (target, key, value, path) => {
|
|
53163
|
+
pending.push((async () => {
|
|
53164
|
+
try {
|
|
53165
|
+
const plain = await decrypt(value, path);
|
|
53166
|
+
if (typeof plain !== "string")
|
|
53167
|
+
throw new TypeError("decrypt returned a non-string");
|
|
53168
|
+
target[key] = plain;
|
|
53169
|
+
} catch {
|
|
53170
|
+
target[key] = null;
|
|
53171
|
+
undecrypted.push(path);
|
|
53172
|
+
}
|
|
53173
|
+
})());
|
|
53174
|
+
};
|
|
53175
|
+
const copies = new Map;
|
|
53176
|
+
const mine = new WeakSet;
|
|
53177
|
+
const copyOf = (v) => {
|
|
53178
|
+
if (mine.has(v))
|
|
53179
|
+
return v;
|
|
53180
|
+
let c = copies.get(v);
|
|
53181
|
+
if (!c) {
|
|
53182
|
+
c = Array.isArray(v) ? [...v] : { ...v };
|
|
53183
|
+
copies.set(v, c);
|
|
53184
|
+
mine.add(c);
|
|
53185
|
+
}
|
|
53186
|
+
return c;
|
|
53187
|
+
};
|
|
53188
|
+
const walk = (node2, keys, at, set2) => {
|
|
53189
|
+
if (Array.isArray(node2)) {
|
|
53190
|
+
const arr = copyOf(node2);
|
|
53191
|
+
set2(arr);
|
|
53192
|
+
arr.forEach((item, i) => {
|
|
53193
|
+
walk(item, keys, at ? `${at}.${i}` : String(i), (v) => {
|
|
53194
|
+
arr[i] = v;
|
|
53195
|
+
});
|
|
53196
|
+
});
|
|
53197
|
+
return;
|
|
53198
|
+
}
|
|
53199
|
+
if (!isObj(node2) || keys.length === 0)
|
|
53200
|
+
return;
|
|
53201
|
+
const [key, ...rest] = keys;
|
|
53202
|
+
if (!Object.hasOwn(node2, key))
|
|
53203
|
+
return;
|
|
53204
|
+
const obj = copyOf(node2);
|
|
53205
|
+
set2(obj);
|
|
53206
|
+
const path = at ? `${at}.${key}` : key;
|
|
53207
|
+
const value = obj[key];
|
|
53208
|
+
if (rest.length > 0) {
|
|
53209
|
+
walk(value, rest, path, (v) => {
|
|
53210
|
+
obj[key] = v;
|
|
53211
|
+
});
|
|
53212
|
+
return;
|
|
53213
|
+
}
|
|
53214
|
+
if (typeof value === "string" && value !== "" && looksEncrypted(value, path)) {
|
|
53215
|
+
decryptInto(obj, key, value, path);
|
|
53216
|
+
}
|
|
53217
|
+
};
|
|
53218
|
+
let data = input2;
|
|
53219
|
+
for (const p of paths) {
|
|
53220
|
+
const keys = p.split(".").filter(Boolean);
|
|
53221
|
+
if (keys.length === 0)
|
|
53222
|
+
continue;
|
|
53223
|
+
walk(data, keys, "", (v) => {
|
|
53224
|
+
data = v;
|
|
53225
|
+
});
|
|
53226
|
+
}
|
|
53227
|
+
await Promise.all(pending);
|
|
53228
|
+
undecrypted.sort();
|
|
53229
|
+
return { data, undecrypted };
|
|
53230
|
+
}
|
|
53231
|
+
|
|
53148
53232
|
// src/crypto.ts
|
|
53149
53233
|
var import_hash_wasm = __toESM(require_index_umd(), 1);
|
|
53150
53234
|
var ENCRYPTED_TXN_FIELDS = ["description", "referenceNumber", "notes"];
|
|
@@ -53207,16 +53291,6 @@ async function decryptField(encrypted, key) {
|
|
|
53207
53291
|
const plaintext = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, key, ciphertext);
|
|
53208
53292
|
return new TextDecoder().decode(plaintext);
|
|
53209
53293
|
}
|
|
53210
|
-
async function decryptObjectFields(obj, fields, key) {
|
|
53211
|
-
for (const field of fields) {
|
|
53212
|
-
const val = obj[field];
|
|
53213
|
-
if (typeof val !== "string" || !val)
|
|
53214
|
-
continue;
|
|
53215
|
-
try {
|
|
53216
|
-
obj[field] = await decryptField(val, key);
|
|
53217
|
-
} catch {}
|
|
53218
|
-
}
|
|
53219
|
-
}
|
|
53220
53294
|
async function encryptObjectFields(obj, fields, key) {
|
|
53221
53295
|
for (const field of fields) {
|
|
53222
53296
|
const val = obj[field];
|
|
@@ -53225,25 +53299,55 @@ async function encryptObjectFields(obj, fields, key) {
|
|
|
53225
53299
|
obj[field] = await encryptField(val, key);
|
|
53226
53300
|
}
|
|
53227
53301
|
}
|
|
53302
|
+
var CIPHERTEXT_CHARSET_RE = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
53303
|
+
var MIN_CIPHERTEXT_B64_LEN = 40;
|
|
53304
|
+
function looksLikeCiphertext(value) {
|
|
53305
|
+
return value.length >= MIN_CIPHERTEXT_B64_LEN && CIPHERTEXT_CHARSET_RE.test(value);
|
|
53306
|
+
}
|
|
53307
|
+
async function decryptFieldsFailClosed(input2, paths, key) {
|
|
53308
|
+
return decryptFields(input2, paths, {
|
|
53309
|
+
decrypt: (ciphertext) => decryptField(ciphertext, key),
|
|
53310
|
+
isCiphertext: (value) => looksLikeCiphertext(value)
|
|
53311
|
+
});
|
|
53312
|
+
}
|
|
53313
|
+
var TXN_DECRYPT_PATHS = [
|
|
53314
|
+
...ENCRYPTED_TXN_FIELDS,
|
|
53315
|
+
...ENCRYPTED_MERCHANT_FIELDS.map((f) => `merchant.${f}`)
|
|
53316
|
+
];
|
|
53228
53317
|
async function decryptTransactionFields(items, key) {
|
|
53229
|
-
|
|
53230
|
-
await decryptObjectFields(item, ENCRYPTED_TXN_FIELDS, key);
|
|
53231
|
-
const merchant = item.merchant;
|
|
53232
|
-
if (merchant && typeof merchant === "object") {
|
|
53233
|
-
await decryptObjectFields(merchant, ENCRYPTED_MERCHANT_FIELDS, key);
|
|
53234
|
-
}
|
|
53235
|
-
}
|
|
53318
|
+
return decryptFieldsFailClosed(items, TXN_DECRYPT_PATHS, key);
|
|
53236
53319
|
}
|
|
53237
53320
|
async function decryptMerchantFields(items, key) {
|
|
53238
|
-
|
|
53239
|
-
await decryptObjectFields(item, ENCRYPTED_MERCHANT_FIELDS, key);
|
|
53240
|
-
}
|
|
53321
|
+
return decryptFieldsFailClosed(items, ENCRYPTED_MERCHANT_FIELDS, key);
|
|
53241
53322
|
}
|
|
53242
53323
|
async function encryptTransactionFields(items, key) {
|
|
53243
53324
|
for (const item of items) {
|
|
53244
53325
|
await encryptObjectFields(item, ENCRYPTED_TXN_FIELDS, key);
|
|
53245
53326
|
}
|
|
53246
53327
|
}
|
|
53328
|
+
async function decryptPersonCiphers(input2, key) {
|
|
53329
|
+
const { data, undecrypted } = await decryptFields(input2, ["cipher"], {
|
|
53330
|
+
decrypt: async (ciphertext) => {
|
|
53331
|
+
const json2 = await decryptField(ciphertext, key);
|
|
53332
|
+
JSON.parse(json2);
|
|
53333
|
+
return json2;
|
|
53334
|
+
}
|
|
53335
|
+
});
|
|
53336
|
+
const merge3 = (row) => {
|
|
53337
|
+
if (!row || typeof row !== "object")
|
|
53338
|
+
return;
|
|
53339
|
+
const r = row;
|
|
53340
|
+
if (typeof r.cipher !== "string")
|
|
53341
|
+
return;
|
|
53342
|
+
const fields = JSON.parse(r.cipher);
|
|
53343
|
+
Object.assign(r, fields, { cipher: null });
|
|
53344
|
+
};
|
|
53345
|
+
if (Array.isArray(data))
|
|
53346
|
+
data.forEach(merge3);
|
|
53347
|
+
else
|
|
53348
|
+
merge3(data);
|
|
53349
|
+
return { data, undecrypted };
|
|
53350
|
+
}
|
|
53247
53351
|
var VERIFIER_PLAINTEXT = "paisa-verify-v1";
|
|
53248
53352
|
async function checkVerifier(key, encryptedVerifier) {
|
|
53249
53353
|
try {
|
|
@@ -53300,7 +53404,7 @@ async function initCrypto(client, pin, userId) {
|
|
|
53300
53404
|
// ../../node_modules/.bun/@modelcontextprotocol+server@2.1.0/node_modules/@modelcontextprotocol/server/dist/index.mjs
|
|
53301
53405
|
var DEFAULT_MAX_REQUEST_BODY_SIZE = 4 * 1024 * 1024;
|
|
53302
53406
|
|
|
53303
|
-
// ../../node_modules/.bun/@nimit9+signet-server@0.2.
|
|
53407
|
+
// ../../node_modules/.bun/@nimit9+signet-server@0.2.3+e803b2305afdb064/node_modules/@nimit9/signet-server/dist/http/status-codes.js
|
|
53304
53408
|
var STATUS_CODES = {
|
|
53305
53409
|
400: "BAD_REQUEST",
|
|
53306
53410
|
401: "UNAUTHORIZED",
|
|
@@ -53314,7 +53418,7 @@ var STATUS_CODES = {
|
|
|
53314
53418
|
429: "RATE_LIMITED"
|
|
53315
53419
|
};
|
|
53316
53420
|
|
|
53317
|
-
// ../../node_modules/.bun/@nimit9+signet-server@0.2.
|
|
53421
|
+
// ../../node_modules/.bun/@nimit9+signet-server@0.2.3+e803b2305afdb064/node_modules/@nimit9/signet-server/dist/mcp/server.js
|
|
53318
53422
|
var RAW = Symbol.for("signet.mcp.rawResult");
|
|
53319
53423
|
function toolResult(result) {
|
|
53320
53424
|
return Object.defineProperty({ ...result }, RAW, { value: true, enumerable: false });
|
|
@@ -53398,10 +53502,17 @@ function toResult(value, structured) {
|
|
|
53398
53502
|
return { content: [{ type: "text", text }] };
|
|
53399
53503
|
}
|
|
53400
53504
|
function createMcpServer(options) {
|
|
53505
|
+
const unlisted = new Set(options.tools.filter((t) => t.listed === false).map((t) => t.name));
|
|
53506
|
+
const toolsCapability = { tools: { listChanged: false } };
|
|
53401
53507
|
const server = new McpServer({ name: options.name, version: options.version }, {
|
|
53402
|
-
|
|
53508
|
+
...unlisted.size ? {} : { capabilities: toolsCapability },
|
|
53403
53509
|
...options.instructions ? { instructions: options.instructions } : {}
|
|
53404
53510
|
});
|
|
53511
|
+
let restore;
|
|
53512
|
+
if (unlisted.size) {
|
|
53513
|
+
server.server.registerCapabilities(toolsCapability);
|
|
53514
|
+
restore = hideUnlisted(server, unlisted);
|
|
53515
|
+
}
|
|
53405
53516
|
const register2 = server.registerTool.bind(server);
|
|
53406
53517
|
const { c, token } = options.context ?? {};
|
|
53407
53518
|
for (const tool of options.tools) {
|
|
@@ -53445,29 +53556,110 @@ function createMcpServer(options) {
|
|
|
53445
53556
|
...tool.input ? { inputSchema: tool.input } : {},
|
|
53446
53557
|
...tool.output ? { outputSchema: tool.output } : {}
|
|
53447
53558
|
}, tool.input ? (input2, mcp) => run(input2, mcp) : (mcp) => run({}, mcp));
|
|
53559
|
+
restore?.();
|
|
53560
|
+
restore = undefined;
|
|
53448
53561
|
}
|
|
53449
53562
|
return server;
|
|
53450
53563
|
}
|
|
53564
|
+
function hideUnlisted(server, unlisted) {
|
|
53565
|
+
const inner = server.server;
|
|
53566
|
+
const original = inner.setRequestHandler.bind(inner);
|
|
53567
|
+
let caught = false;
|
|
53568
|
+
inner.setRequestHandler = (method, handler) => {
|
|
53569
|
+
if (method !== "tools/list" || typeof handler !== "function")
|
|
53570
|
+
return original(method, handler);
|
|
53571
|
+
caught = true;
|
|
53572
|
+
original(method, async (request, ctx) => {
|
|
53573
|
+
const result = await handler(request, ctx);
|
|
53574
|
+
return { ...result, tools: result.tools.filter((t) => !unlisted.has(t.name)) };
|
|
53575
|
+
});
|
|
53576
|
+
};
|
|
53577
|
+
return () => {
|
|
53578
|
+
delete inner.setRequestHandler;
|
|
53579
|
+
if (!caught)
|
|
53580
|
+
throw new Error("signet mcp: could not hide unlisted tools; @modelcontextprotocol/server no longer installs tools/list through setRequestHandler");
|
|
53581
|
+
};
|
|
53582
|
+
}
|
|
53583
|
+
|
|
53584
|
+
// src/annotations.ts
|
|
53585
|
+
var RO = { readOnlyHint: true, openWorldHint: false };
|
|
53586
|
+
var WI = {
|
|
53587
|
+
readOnlyHint: false,
|
|
53588
|
+
destructiveHint: false,
|
|
53589
|
+
idempotentHint: true,
|
|
53590
|
+
openWorldHint: false
|
|
53591
|
+
};
|
|
53592
|
+
var W = {
|
|
53593
|
+
readOnlyHint: false,
|
|
53594
|
+
destructiveHint: false,
|
|
53595
|
+
idempotentHint: false,
|
|
53596
|
+
openWorldHint: false
|
|
53597
|
+
};
|
|
53598
|
+
var D = {
|
|
53599
|
+
readOnlyHint: false,
|
|
53600
|
+
destructiveHint: true,
|
|
53601
|
+
idempotentHint: false,
|
|
53602
|
+
openWorldHint: false
|
|
53603
|
+
};
|
|
53604
|
+
var WI_OPEN = {
|
|
53605
|
+
readOnlyHint: false,
|
|
53606
|
+
destructiveHint: false,
|
|
53607
|
+
idempotentHint: true,
|
|
53608
|
+
openWorldHint: true
|
|
53609
|
+
};
|
|
53610
|
+
var TOOL_META = {
|
|
53611
|
+
get_transactions: { title: "Search Transactions", annotations: RO },
|
|
53612
|
+
get_uncategorized_groups: { title: "Group Uncategorized Transactions", annotations: RO },
|
|
53613
|
+
categorize_groups: { title: "Categorize Transaction Groups", annotations: W },
|
|
53614
|
+
backfill_persons: { title: "Backfill Persons from Transactions", annotations: WI },
|
|
53615
|
+
update_transaction: { title: "Update Transaction", annotations: WI },
|
|
53616
|
+
bulk_link_entity: { title: "Bulk Link Transactions", annotations: WI },
|
|
53617
|
+
manage_duplicates: { title: "Manage Duplicate Transactions", annotations: W },
|
|
53618
|
+
get_reconciliation_context: { title: "Get Reconciliation Context", annotations: RO },
|
|
53619
|
+
bulk_categorize_transactions: { title: "Bulk Categorize Transactions", annotations: WI },
|
|
53620
|
+
delete_transactions: { title: "Delete Transactions", annotations: D },
|
|
53621
|
+
rescan_transactions: { title: "Rescan Transactions", annotations: WI },
|
|
53622
|
+
get_settlement_candidates: { title: "Find Settlement Candidates", annotations: RO },
|
|
53623
|
+
get_transaction: { title: "Get Transaction", annotations: RO },
|
|
53624
|
+
preview_import: { title: "Preview Statement Import", annotations: RO },
|
|
53625
|
+
import_statement: { title: "Import Statement", annotations: W },
|
|
53626
|
+
auto_categorize_jev: { title: "Auto-Categorize with Jev", annotations: W },
|
|
53627
|
+
list_entities: { title: "List Entities", annotations: RO },
|
|
53628
|
+
upsert_entity: { title: "Create or Update Entity", annotations: W },
|
|
53629
|
+
delete_entity: { title: "Delete Entity", annotations: D },
|
|
53630
|
+
merge_merchants: { title: "Merge Merchants", annotations: D },
|
|
53631
|
+
get_analytics: { title: "Get Analytics", annotations: RO },
|
|
53632
|
+
upsert_savings: { title: "Create or Update Savings Vehicle", annotations: W },
|
|
53633
|
+
contribute_to_goal: { title: "Contribute to Goal", annotations: W },
|
|
53634
|
+
set_budget: { title: "Set Budget", annotations: WI },
|
|
53635
|
+
get_dashboard: { title: "Get Dashboard", annotations: RO },
|
|
53636
|
+
sync_recurring: { title: "Sync Recurring Merchants", annotations: WI },
|
|
53637
|
+
check_alerts: { title: "Check Alerts", annotations: W },
|
|
53638
|
+
manage_alerts: { title: "Manage Alerts and Rules", annotations: WI },
|
|
53639
|
+
manage_debt: { title: "Add or Settle Debt", annotations: W },
|
|
53640
|
+
generate_monthly_report: { title: "Generate Monthly Report", annotations: WI },
|
|
53641
|
+
get_report: { title: "Get Report", annotations: RO },
|
|
53642
|
+
export_transactions: { title: "Export Transactions", annotations: RO },
|
|
53643
|
+
set_learning_rule: { title: "Set Learning Rule", annotations: WI },
|
|
53644
|
+
update_net_worth: { title: "Update Net Worth", annotations: WI },
|
|
53645
|
+
upsert_investment: { title: "Create or Update Investment", annotations: W },
|
|
53646
|
+
sync_zerodha: { title: "Sync Zerodha", annotations: WI_OPEN },
|
|
53647
|
+
get_settings: { title: "Get Settings", annotations: RO },
|
|
53648
|
+
update_settings: { title: "Update Settings", annotations: WI },
|
|
53649
|
+
set_encryption_mode: { title: "Set Encryption Mode", annotations: D }
|
|
53650
|
+
};
|
|
53651
|
+
function applyAnnotations(tools) {
|
|
53652
|
+
return tools.map((tool) => {
|
|
53653
|
+
const meta3 = TOOL_META[tool.name];
|
|
53654
|
+
if (!meta3)
|
|
53655
|
+
throw new Error(`No TOOL_META entry for tool "${tool.name}" — add one to annotations.ts`);
|
|
53656
|
+
return { ...tool, title: meta3.title, annotations: meta3.annotations };
|
|
53657
|
+
});
|
|
53658
|
+
}
|
|
53451
53659
|
// src/lib/union-tool.ts
|
|
53452
53660
|
function variant(input2, run) {
|
|
53453
53661
|
return { input: input2, run };
|
|
53454
53662
|
}
|
|
53455
|
-
function isAlias(tool) {
|
|
53456
|
-
return typeof tool.aliasFor === "string";
|
|
53457
|
-
}
|
|
53458
|
-
function aliasTool(name, input2, aliasFor, note, route) {
|
|
53459
|
-
const tool = defineTool({
|
|
53460
|
-
name,
|
|
53461
|
-
description: `Deprecated alias of ${aliasFor}.`,
|
|
53462
|
-
input: input2,
|
|
53463
|
-
handler: async (args, ctx) => {
|
|
53464
|
-
const [to, next] = route(args);
|
|
53465
|
-
const parsed = to.input ? await to.input.parseAsync(next) : next;
|
|
53466
|
-
return to.handler(parsed, ctx);
|
|
53467
|
-
}
|
|
53468
|
-
});
|
|
53469
|
-
return { ...tool, aliasFor, aliasNote: note };
|
|
53470
|
-
}
|
|
53471
53663
|
function compactJsonSchema(schema) {
|
|
53472
53664
|
const walk = (node2, root) => {
|
|
53473
53665
|
if (Array.isArray(node2))
|
|
@@ -53564,91 +53756,7 @@ function unionTool(opts) {
|
|
|
53564
53756
|
return v.run(rest, ctx);
|
|
53565
53757
|
}
|
|
53566
53758
|
});
|
|
53567
|
-
return {
|
|
53568
|
-
tool,
|
|
53569
|
-
alias: (aliasName, value) => aliasTool(aliasName, variants[value].input, name, `${key}: "${value}"`, (a) => [
|
|
53570
|
-
tool,
|
|
53571
|
-
{ ...a, [key]: value }
|
|
53572
|
-
])
|
|
53573
|
-
};
|
|
53574
|
-
}
|
|
53575
|
-
|
|
53576
|
-
// src/annotations.ts
|
|
53577
|
-
var RO = { readOnlyHint: true, openWorldHint: false };
|
|
53578
|
-
var WI = {
|
|
53579
|
-
readOnlyHint: false,
|
|
53580
|
-
destructiveHint: false,
|
|
53581
|
-
idempotentHint: true,
|
|
53582
|
-
openWorldHint: false
|
|
53583
|
-
};
|
|
53584
|
-
var W = {
|
|
53585
|
-
readOnlyHint: false,
|
|
53586
|
-
destructiveHint: false,
|
|
53587
|
-
idempotentHint: false,
|
|
53588
|
-
openWorldHint: false
|
|
53589
|
-
};
|
|
53590
|
-
var D = {
|
|
53591
|
-
readOnlyHint: false,
|
|
53592
|
-
destructiveHint: true,
|
|
53593
|
-
idempotentHint: false,
|
|
53594
|
-
openWorldHint: false
|
|
53595
|
-
};
|
|
53596
|
-
var WI_OPEN = {
|
|
53597
|
-
readOnlyHint: false,
|
|
53598
|
-
destructiveHint: false,
|
|
53599
|
-
idempotentHint: true,
|
|
53600
|
-
openWorldHint: true
|
|
53601
|
-
};
|
|
53602
|
-
var TOOL_META = {
|
|
53603
|
-
get_transactions: { title: "Search Transactions", annotations: RO },
|
|
53604
|
-
get_uncategorized_groups: { title: "Group Uncategorized Transactions", annotations: RO },
|
|
53605
|
-
categorize_groups: { title: "Categorize Transaction Groups", annotations: W },
|
|
53606
|
-
backfill_persons: { title: "Backfill Persons from Transactions", annotations: WI },
|
|
53607
|
-
update_transaction: { title: "Update Transaction", annotations: WI },
|
|
53608
|
-
bulk_link_entity: { title: "Bulk Link Transactions", annotations: WI },
|
|
53609
|
-
manage_duplicates: { title: "Manage Duplicate Transactions", annotations: W },
|
|
53610
|
-
get_reconciliation_context: { title: "Get Reconciliation Context", annotations: RO },
|
|
53611
|
-
bulk_categorize_transactions: { title: "Bulk Categorize Transactions", annotations: WI },
|
|
53612
|
-
delete_transactions: { title: "Delete Transactions", annotations: D },
|
|
53613
|
-
rescan_transactions: { title: "Rescan Transactions", annotations: WI },
|
|
53614
|
-
get_settlement_candidates: { title: "Find Settlement Candidates", annotations: RO },
|
|
53615
|
-
get_transaction: { title: "Get Transaction", annotations: RO },
|
|
53616
|
-
preview_import: { title: "Preview Statement Import", annotations: RO },
|
|
53617
|
-
import_statement: { title: "Import Statement", annotations: W },
|
|
53618
|
-
auto_categorize_jev: { title: "Auto-Categorize with Jev", annotations: W },
|
|
53619
|
-
list_entities: { title: "List Entities", annotations: RO },
|
|
53620
|
-
upsert_entity: { title: "Create or Update Entity", annotations: W },
|
|
53621
|
-
delete_entity: { title: "Delete Entity", annotations: D },
|
|
53622
|
-
merge_merchants: { title: "Merge Merchants", annotations: D },
|
|
53623
|
-
get_analytics: { title: "Get Analytics", annotations: RO },
|
|
53624
|
-
upsert_savings: { title: "Create or Update Savings Vehicle", annotations: W },
|
|
53625
|
-
contribute_to_goal: { title: "Contribute to Goal", annotations: W },
|
|
53626
|
-
set_budget: { title: "Set Budget", annotations: WI },
|
|
53627
|
-
get_dashboard: { title: "Get Dashboard", annotations: RO },
|
|
53628
|
-
sync_recurring: { title: "Sync Recurring Merchants", annotations: WI },
|
|
53629
|
-
check_alerts: { title: "Check Alerts", annotations: W },
|
|
53630
|
-
manage_alerts: { title: "Manage Alerts and Rules", annotations: WI },
|
|
53631
|
-
manage_debt: { title: "Add or Settle Debt", annotations: W },
|
|
53632
|
-
generate_monthly_report: { title: "Generate Monthly Report", annotations: WI },
|
|
53633
|
-
get_report: { title: "Get Report", annotations: RO },
|
|
53634
|
-
export_transactions: { title: "Export Transactions", annotations: RO },
|
|
53635
|
-
set_learning_rule: { title: "Set Learning Rule", annotations: WI },
|
|
53636
|
-
update_net_worth: { title: "Update Net Worth", annotations: WI },
|
|
53637
|
-
upsert_investment: { title: "Create or Update Investment", annotations: W },
|
|
53638
|
-
sync_zerodha: { title: "Sync Zerodha", annotations: WI_OPEN },
|
|
53639
|
-
get_settings: { title: "Get Settings", annotations: RO },
|
|
53640
|
-
update_settings: { title: "Update Settings", annotations: WI },
|
|
53641
|
-
set_encryption_mode: { title: "Set Encryption Mode", annotations: D }
|
|
53642
|
-
};
|
|
53643
|
-
function applyAnnotations(tools) {
|
|
53644
|
-
return tools.map((tool) => {
|
|
53645
|
-
if (isAlias(tool))
|
|
53646
|
-
return tool;
|
|
53647
|
-
const meta3 = TOOL_META[tool.name];
|
|
53648
|
-
if (!meta3)
|
|
53649
|
-
throw new Error(`No TOOL_META entry for tool "${tool.name}" — add one to annotations.ts`);
|
|
53650
|
-
return { ...tool, title: meta3.title, annotations: meta3.annotations };
|
|
53651
|
-
});
|
|
53759
|
+
return { tool };
|
|
53652
53760
|
}
|
|
53653
53761
|
|
|
53654
53762
|
// src/prompts.ts
|
|
@@ -53809,11 +53917,7 @@ function alertTools(client) {
|
|
|
53809
53917
|
return { success: true, generated, unread };
|
|
53810
53918
|
}
|
|
53811
53919
|
}),
|
|
53812
|
-
manage.tool
|
|
53813
|
-
manage.alias("dismiss_alert", "dismiss"),
|
|
53814
|
-
manage.alias("mark_alert_read", "read"),
|
|
53815
|
-
manage.alias("list_alert_rules", "list_rules"),
|
|
53816
|
-
manage.alias("set_alert_rule", "set_rule")
|
|
53920
|
+
manage.tool
|
|
53817
53921
|
];
|
|
53818
53922
|
}
|
|
53819
53923
|
|
|
@@ -53862,7 +53966,8 @@ var dashboardOutputSchema = exports_external.object({
|
|
|
53862
53966
|
recentTransactions: exports_external.array(exports_external.record(exports_external.string(), exports_external.unknown())),
|
|
53863
53967
|
netWorth: exports_external.record(exports_external.string(), exports_external.unknown()).nullable(),
|
|
53864
53968
|
debtSummary: exports_external.object({ totalOutstanding: exports_external.number(), totalEmi: exports_external.number(), count: exports_external.number() }).nullable(),
|
|
53865
|
-
budgetVsActual: exports_external.array(budgetVsActualEntrySchema)
|
|
53969
|
+
budgetVsActual: exports_external.array(budgetVsActualEntrySchema),
|
|
53970
|
+
undecrypted: exports_external.array(exports_external.string()).optional()
|
|
53866
53971
|
});
|
|
53867
53972
|
var spendingTrendsSchema = exports_external.object({
|
|
53868
53973
|
success: exports_external.literal(true),
|
|
@@ -53897,7 +54002,8 @@ var spendingTrendsSchema = exports_external.object({
|
|
|
53897
54002
|
total: exports_external.number(),
|
|
53898
54003
|
count: exports_external.number()
|
|
53899
54004
|
})),
|
|
53900
|
-
budgetVsActual: exports_external.array(budgetVsActualEntrySchema)
|
|
54005
|
+
budgetVsActual: exports_external.array(budgetVsActualEntrySchema),
|
|
54006
|
+
undecrypted: exports_external.array(exports_external.string()).optional()
|
|
53901
54007
|
});
|
|
53902
54008
|
var categoryAnalyticsSchema = exports_external.object({
|
|
53903
54009
|
success: exports_external.literal(true),
|
|
@@ -53912,7 +54018,7 @@ var categoryAnalyticsSchema = exports_external.object({
|
|
|
53912
54018
|
recentTransactions: exports_external.array(exports_external.object({
|
|
53913
54019
|
id: exports_external.string(),
|
|
53914
54020
|
date: exports_external.string(),
|
|
53915
|
-
description: exports_external.string(),
|
|
54021
|
+
description: exports_external.string().nullable(),
|
|
53916
54022
|
amount: exports_external.number(),
|
|
53917
54023
|
type: exports_external.string(),
|
|
53918
54024
|
owner: exports_external.string(),
|
|
@@ -53926,7 +54032,8 @@ var categoryAnalyticsSchema = exports_external.object({
|
|
|
53926
54032
|
total: exports_external.number(),
|
|
53927
54033
|
count: exports_external.number()
|
|
53928
54034
|
})),
|
|
53929
|
-
stats: exports_external.object({ total: exports_external.number(), avgMonthly: exports_external.number(), count: exports_external.number() })
|
|
54035
|
+
stats: exports_external.object({ total: exports_external.number(), avgMonthly: exports_external.number(), count: exports_external.number() }),
|
|
54036
|
+
undecrypted: exports_external.array(exports_external.string()).optional()
|
|
53930
54037
|
});
|
|
53931
54038
|
var merchantAnalyticsSchema = exports_external.object({
|
|
53932
54039
|
success: exports_external.literal(true),
|
|
@@ -53941,7 +54048,7 @@ var merchantAnalyticsSchema = exports_external.object({
|
|
|
53941
54048
|
recentTransactions: exports_external.array(exports_external.object({
|
|
53942
54049
|
id: exports_external.string(),
|
|
53943
54050
|
date: exports_external.string(),
|
|
53944
|
-
description: exports_external.string(),
|
|
54051
|
+
description: exports_external.string().nullable(),
|
|
53945
54052
|
amount: exports_external.number(),
|
|
53946
54053
|
type: exports_external.string(),
|
|
53947
54054
|
owner: exports_external.string(),
|
|
@@ -53956,7 +54063,8 @@ var merchantAnalyticsSchema = exports_external.object({
|
|
|
53956
54063
|
total: exports_external.number(),
|
|
53957
54064
|
count: exports_external.number()
|
|
53958
54065
|
})),
|
|
53959
|
-
stats: exports_external.object({ total: exports_external.number(), avgMonthly: exports_external.number(), count: exports_external.number() })
|
|
54066
|
+
stats: exports_external.object({ total: exports_external.number(), avgMonthly: exports_external.number(), count: exports_external.number() }),
|
|
54067
|
+
undecrypted: exports_external.array(exports_external.string()).optional()
|
|
53960
54068
|
});
|
|
53961
54069
|
var analyticsOutputSchema = exports_external.union([
|
|
53962
54070
|
spendingTrendsSchema,
|
|
@@ -53965,37 +54073,17 @@ var analyticsOutputSchema = exports_external.union([
|
|
|
53965
54073
|
]);
|
|
53966
54074
|
|
|
53967
54075
|
// src/tools/analytics.ts
|
|
53968
|
-
async function dec(value, key) {
|
|
53969
|
-
if (typeof value !== "string" || !value)
|
|
53970
|
-
return value;
|
|
53971
|
-
try {
|
|
53972
|
-
return await decryptField(value, key);
|
|
53973
|
-
} catch {
|
|
53974
|
-
return value;
|
|
53975
|
-
}
|
|
53976
|
-
}
|
|
53977
54076
|
async function decryptAnalytics(data, key) {
|
|
53978
54077
|
if (!data || typeof data !== "object")
|
|
53979
|
-
return;
|
|
53980
|
-
const
|
|
53981
|
-
|
|
53982
|
-
|
|
53983
|
-
|
|
53984
|
-
|
|
53985
|
-
|
|
53986
|
-
|
|
53987
|
-
|
|
53988
|
-
for (const t of recent) {
|
|
53989
|
-
t.description = await dec(t.description, key);
|
|
53990
|
-
if ("merchantName" in t)
|
|
53991
|
-
t.merchantName = await dec(t.merchantName, key);
|
|
53992
|
-
}
|
|
53993
|
-
}
|
|
53994
|
-
const merchant = d.merchant;
|
|
53995
|
-
if (merchant && typeof merchant === "object") {
|
|
53996
|
-
merchant.cleanName = await dec(merchant.cleanName, key);
|
|
53997
|
-
merchant.rawId = await dec(merchant.rawId, key);
|
|
53998
|
-
}
|
|
54078
|
+
return data;
|
|
54079
|
+
const { data: decrypted, undecrypted } = await decryptFieldsFailClosed(data, [
|
|
54080
|
+
"topMerchants.name",
|
|
54081
|
+
"recentTransactions.description",
|
|
54082
|
+
"recentTransactions.merchantName",
|
|
54083
|
+
"merchant.cleanName",
|
|
54084
|
+
"merchant.rawId"
|
|
54085
|
+
], key);
|
|
54086
|
+
return undecrypted.length ? { ...decrypted, undecrypted } : decrypted;
|
|
53999
54087
|
}
|
|
54000
54088
|
function analyticsTools(client, crypto3) {
|
|
54001
54089
|
return [
|
|
@@ -54023,7 +54111,7 @@ function analyticsTools(client, crypto3) {
|
|
|
54023
54111
|
break;
|
|
54024
54112
|
}
|
|
54025
54113
|
if (crypto3)
|
|
54026
|
-
await decryptAnalytics(data, crypto3.key);
|
|
54114
|
+
data = await decryptAnalytics(data, crypto3.key);
|
|
54027
54115
|
return data;
|
|
54028
54116
|
}
|
|
54029
54117
|
})
|
|
@@ -54091,7 +54179,10 @@ function dashboardTools(client, crypto3) {
|
|
|
54091
54179
|
handler: async (params) => {
|
|
54092
54180
|
const data = await client.get("/api/dashboard", params.months ? { months: params.months } : undefined);
|
|
54093
54181
|
if (crypto3 && Array.isArray(data?.recentTransactions)) {
|
|
54094
|
-
await decryptTransactionFields(data.recentTransactions, crypto3.key);
|
|
54182
|
+
const { data: decrypted, undecrypted } = await decryptTransactionFields(data.recentTransactions, crypto3.key);
|
|
54183
|
+
data.recentTransactions = decrypted;
|
|
54184
|
+
if (undecrypted.length)
|
|
54185
|
+
return { ...data, undecrypted };
|
|
54095
54186
|
}
|
|
54096
54187
|
return data;
|
|
54097
54188
|
}
|
|
@@ -54142,7 +54233,7 @@ function debtTools(client) {
|
|
|
54142
54233
|
})
|
|
54143
54234
|
}
|
|
54144
54235
|
});
|
|
54145
|
-
return [manage.tool
|
|
54236
|
+
return [manage.tool];
|
|
54146
54237
|
}
|
|
54147
54238
|
|
|
54148
54239
|
// src/tools/accounts.ts
|
|
@@ -54643,13 +54734,17 @@ function merchantVariants(client, crypto3) {
|
|
|
54643
54734
|
return {
|
|
54644
54735
|
list: variant(exports_external.object({ rawId: exports_external.string().optional().describe("merchants: find one by UPI ID or name") }), async ({ rawId }) => {
|
|
54645
54736
|
const data = await client.get("/api/merchants");
|
|
54646
|
-
|
|
54647
|
-
|
|
54737
|
+
let undecrypted = [];
|
|
54738
|
+
if (crypto3 && data.data) {
|
|
54739
|
+
const dec = await decryptMerchantFields(data.data, crypto3.key);
|
|
54740
|
+
data.data = dec.data;
|
|
54741
|
+
undecrypted = dec.undecrypted;
|
|
54742
|
+
}
|
|
54648
54743
|
if (!rawId)
|
|
54649
|
-
return data;
|
|
54744
|
+
return undecrypted.length ? { ...data, undecrypted } : data;
|
|
54650
54745
|
const needle = rawId.toLowerCase();
|
|
54651
54746
|
const merchants = (data.data ?? []).filter((m) => String(m.rawId ?? "").toLowerCase() === needle || String(m.cleanName ?? "").toLowerCase().includes(needle));
|
|
54652
|
-
return { ...data, data: merchants };
|
|
54747
|
+
return { ...data, data: merchants, ...undecrypted.length ? { undecrypted } : {} };
|
|
54653
54748
|
}),
|
|
54654
54749
|
upsert: variant(exports_external.object({
|
|
54655
54750
|
id: exports_external.string().optional().describe("Merchant UUID — pass to update, omit to create"),
|
|
@@ -54758,22 +54853,19 @@ function personVariants(client, crypto3) {
|
|
|
54758
54853
|
if (id) {
|
|
54759
54854
|
const data2 = await client.get(`/api/persons/${id}`);
|
|
54760
54855
|
if (crypto3 && data2.data.cipher) {
|
|
54761
|
-
const
|
|
54762
|
-
|
|
54856
|
+
const { data: decrypted, undecrypted } = await decryptPersonCiphers(data2.data, crypto3.key);
|
|
54857
|
+
data2.data = decrypted;
|
|
54858
|
+
if (undecrypted.length)
|
|
54859
|
+
return { ...data2, undecrypted };
|
|
54763
54860
|
}
|
|
54764
54861
|
return data2;
|
|
54765
54862
|
}
|
|
54766
54863
|
const data = await client.get("/api/persons");
|
|
54767
54864
|
if (crypto3 && data.data) {
|
|
54768
|
-
|
|
54769
|
-
|
|
54770
|
-
|
|
54771
|
-
|
|
54772
|
-
const fields = await decryptPersonCipher(cipher, crypto3.key);
|
|
54773
|
-
Object.assign(person, fields, { cipher: null });
|
|
54774
|
-
} catch {}
|
|
54775
|
-
}
|
|
54776
|
-
}
|
|
54865
|
+
const { data: decrypted, undecrypted } = await decryptPersonCiphers(data.data, crypto3.key);
|
|
54866
|
+
data.data = decrypted;
|
|
54867
|
+
if (undecrypted.length)
|
|
54868
|
+
return { ...data, undecrypted };
|
|
54777
54869
|
}
|
|
54778
54870
|
return data;
|
|
54779
54871
|
}),
|
|
@@ -54903,11 +54995,7 @@ function reportTools(client) {
|
|
|
54903
54995
|
}),
|
|
54904
54996
|
handler: (body) => client.post("/api/reports/generate", body)
|
|
54905
54997
|
}),
|
|
54906
|
-
report2.tool
|
|
54907
|
-
report2.alias("get_reports", "monthly"),
|
|
54908
|
-
report2.alias("get_net_worth", "net_worth"),
|
|
54909
|
-
report2.alias("get_upcoming", "upcoming"),
|
|
54910
|
-
report2.alias("get_spending_heatmap", "heatmap")
|
|
54998
|
+
report2.tool
|
|
54911
54999
|
];
|
|
54912
55000
|
}
|
|
54913
55001
|
|
|
@@ -54986,56 +55074,7 @@ function entityTools(client, crypto3) {
|
|
|
54986
55074
|
fixed_deposit: investment.deleteFd
|
|
54987
55075
|
}
|
|
54988
55076
|
});
|
|
54989
|
-
return [
|
|
54990
|
-
list.tool,
|
|
54991
|
-
upsert.tool,
|
|
54992
|
-
del.tool,
|
|
54993
|
-
list.alias("list_categories", "categories"),
|
|
54994
|
-
list.alias("list_merchants", "merchants"),
|
|
54995
|
-
list.alias("list_bank_accounts", "bank_accounts"),
|
|
54996
|
-
list.alias("list_persons", "persons"),
|
|
54997
|
-
list.alias("list_budgets", "budgets"),
|
|
54998
|
-
list.alias("list_debts", "debts"),
|
|
54999
|
-
list.alias("list_invites", "invites"),
|
|
55000
|
-
list.alias("list_alerts", "alerts"),
|
|
55001
|
-
list.alias("list_recurring", "recurring"),
|
|
55002
|
-
list.alias("list_push_subscriptions", "push_subscriptions"),
|
|
55003
|
-
list.alias("list_saved_reports", "saved_reports"),
|
|
55004
|
-
aliasTool("list_learning", exports_external.object({ type: exports_external.enum(LEARNING_SLICES) }), "list_entities", 'entity: "learning", slice: <type>', ({ type }) => [list.tool, { entity: "learning", slice: type }]),
|
|
55005
|
-
aliasTool("list_savings", exports_external.object({
|
|
55006
|
-
type: exports_external.enum(["goals", "emis", "sinking_funds", "insurance", "contributions"]),
|
|
55007
|
-
id: exports_external.string().optional()
|
|
55008
|
-
}), "list_entities", "entity: <type> (contributions → goal_contributions)", ({ type, id }) => {
|
|
55009
|
-
if (type !== "contributions")
|
|
55010
|
-
return [list.tool, { entity: type }];
|
|
55011
|
-
if (!id)
|
|
55012
|
-
throw new Error("list_savings type='contributions' requires id (goal UUID)");
|
|
55013
|
-
return [list.tool, { entity: "goal_contributions", id }];
|
|
55014
|
-
}),
|
|
55015
|
-
aliasTool("list_investments", exports_external.object({
|
|
55016
|
-
type: exports_external.enum(["holdings", "sips", "fixed_deposits", "transactions"]),
|
|
55017
|
-
id: exports_external.string().optional()
|
|
55018
|
-
}), "list_entities", "entity: <type> (transactions → investment_transactions)", ({ type, id }) => {
|
|
55019
|
-
if (type !== "transactions")
|
|
55020
|
-
return [list.tool, { entity: type }];
|
|
55021
|
-
if (!id)
|
|
55022
|
-
throw new Error("list_investments type='transactions' requires id");
|
|
55023
|
-
return [list.tool, { entity: "investment_transactions", id }];
|
|
55024
|
-
}),
|
|
55025
|
-
upsert.alias("upsert_merchant", "merchant"),
|
|
55026
|
-
upsert.alias("upsert_person", "person"),
|
|
55027
|
-
upsert.alias("upsert_category", "category"),
|
|
55028
|
-
upsert.alias("upsert_bank_account", "bank_account"),
|
|
55029
|
-
upsert.alias("upsert_insurance", "insurance"),
|
|
55030
|
-
upsert.alias("create_invite", "invite"),
|
|
55031
|
-
del.alias("delete_category", "category"),
|
|
55032
|
-
del.alias("delete_merchant", "merchant"),
|
|
55033
|
-
del.alias("delete_person", "person"),
|
|
55034
|
-
del.alias("delete_debt", "debt"),
|
|
55035
|
-
del.alias("revoke_invite", "invite"),
|
|
55036
|
-
aliasTool("delete_savings", exports_external.object({ type: exports_external.enum(["goal", "emi", "insurance", "sinking_fund"]), id: exports_external.string() }), "delete_entity", "entity: <type>", ({ type, id }) => [del.tool, { entity: type, id }]),
|
|
55037
|
-
aliasTool("delete_investment", exports_external.object({ type: exports_external.enum(["sip", "fixed_deposit"]), id: exports_external.string() }), "delete_entity", "entity: <type>", ({ type, id }) => [del.tool, { entity: type, id }])
|
|
55038
|
-
];
|
|
55077
|
+
return [list.tool, upsert.tool, del.tool];
|
|
55039
55078
|
}
|
|
55040
55079
|
|
|
55041
55080
|
// ../reconciliation/src/aliases.ts
|
|
@@ -58620,9 +58659,8 @@ async function fetchAllRowsPaged(client, crypto3, params = {}, maxPages = 100) {
|
|
|
58620
58659
|
if (cursor)
|
|
58621
58660
|
q2.cursor = cursor;
|
|
58622
58661
|
const res = await client.get("/api/transactions", q2);
|
|
58623
|
-
const
|
|
58624
|
-
|
|
58625
|
-
await decryptTransactionFields(batch, crypto3.key);
|
|
58662
|
+
const batch0 = res.data ?? [];
|
|
58663
|
+
const batch = crypto3 ? (await decryptTransactionFields(batch0, crypto3.key)).data : batch0;
|
|
58626
58664
|
out.push(...batch.map(toTxnRow));
|
|
58627
58665
|
if (!res.hasMore || !res.nextCursor || batch.length === 0 || res.nextCursor === cursor)
|
|
58628
58666
|
break;
|
|
@@ -59087,9 +59125,8 @@ async function runRescan(client, crypto3) {
|
|
|
59087
59125
|
bag = (await loadBag(client)).bag;
|
|
59088
59126
|
} catch {}
|
|
59089
59127
|
const merchantsRes = await client.get("/api/merchants");
|
|
59090
|
-
const
|
|
59091
|
-
|
|
59092
|
-
await decryptMerchantFields(allMerchants, crypto3.key);
|
|
59128
|
+
const allMerchants0 = merchantsRes.data ?? [];
|
|
59129
|
+
const allMerchants = crypto3 ? (await decryptMerchantFields(allMerchants0, crypto3.key)).data : allMerchants0;
|
|
59093
59130
|
const globalMerchants = allMerchants.filter((m2) => !m2.householdId && m2.cleanName).map((m2) => ({ id: m2.id, name: m2.cleanName }));
|
|
59094
59131
|
const localMerchants = allMerchants.filter((m2) => m2.householdId && m2.cleanName).map((m2) => ({ id: m2.id, name: m2.cleanName }));
|
|
59095
59132
|
const merchantCategoryById = new Map(allMerchants.filter((m2) => m2.categoryId).map((m2) => [m2.id, m2.categoryId]));
|
|
@@ -59186,9 +59223,13 @@ function transactionTools(client, crypto3) {
|
|
|
59186
59223
|
if (!full)
|
|
59187
59224
|
apiParams.view = "lean";
|
|
59188
59225
|
const data = await client.get("/api/transactions", Object.fromEntries(Object.entries(apiParams).filter(([, v2]) => v2 !== undefined).map(([k2, v2]) => [k2, String(v2)])));
|
|
59189
|
-
|
|
59190
|
-
|
|
59191
|
-
|
|
59226
|
+
let rows = data.data ?? [];
|
|
59227
|
+
let undecrypted = [];
|
|
59228
|
+
if (crypto3) {
|
|
59229
|
+
const dec = await decryptTransactionFields(rows, crypto3.key);
|
|
59230
|
+
rows = dec.data;
|
|
59231
|
+
undecrypted = dec.undecrypted;
|
|
59232
|
+
}
|
|
59192
59233
|
const personNames = new Map;
|
|
59193
59234
|
if (rows.some((r2) => r2.personId)) {
|
|
59194
59235
|
for (const p2 of await loadDecryptedPersons(client, crypto3))
|
|
@@ -59200,12 +59241,14 @@ function transactionTools(client, crypto3) {
|
|
|
59200
59241
|
if (person && personNames.has(person.id))
|
|
59201
59242
|
person.name = personNames.get(person.id) ?? "";
|
|
59202
59243
|
}
|
|
59203
|
-
|
|
59244
|
+
data.data = rows;
|
|
59245
|
+
return undecrypted.length ? { ...data, undecrypted } : data;
|
|
59204
59246
|
}
|
|
59205
59247
|
const out = {
|
|
59206
59248
|
rows: rows.map((r2) => toLeanRow(r2, personNames)),
|
|
59207
59249
|
...data.hasMore ? { more: true, cursor: data.nextCursor } : {},
|
|
59208
|
-
...data.summary ? { spent: data.summary.spent, income: data.summary.income } : {}
|
|
59250
|
+
...data.summary ? { spent: data.summary.spent, income: data.summary.income } : {},
|
|
59251
|
+
...undecrypted.length ? { undecrypted } : {}
|
|
59209
59252
|
};
|
|
59210
59253
|
return out;
|
|
59211
59254
|
}
|
|
@@ -59331,8 +59374,11 @@ function transactionTools(client, crypto3) {
|
|
|
59331
59374
|
}
|
|
59332
59375
|
if (action === "list") {
|
|
59333
59376
|
const data2 = await client.get("/api/transactions/duplicates");
|
|
59334
|
-
if (crypto3 && data2.data)
|
|
59335
|
-
await decryptTransactionFields(data2.data, crypto3.key);
|
|
59377
|
+
if (crypto3 && data2.data) {
|
|
59378
|
+
const { data: decrypted, undecrypted } = await decryptTransactionFields(data2.data, crypto3.key);
|
|
59379
|
+
data2.data = decrypted;
|
|
59380
|
+
return withTruncationWarning(undecrypted.length ? { ...data2, undecrypted } : data2);
|
|
59381
|
+
}
|
|
59336
59382
|
return withTruncationWarning(data2);
|
|
59337
59383
|
}
|
|
59338
59384
|
const data = await client.post("/api/transactions/duplicates/resolve", {
|
|
@@ -59352,8 +59398,11 @@ function transactionTools(client, crypto3) {
|
|
|
59352
59398
|
}),
|
|
59353
59399
|
handler: async ({ accountId, startDate, endDate }) => {
|
|
59354
59400
|
const data = await client.get("/api/transactions/reconciliation-context", { accountId, startDate, endDate });
|
|
59355
|
-
if (crypto3 && data.data)
|
|
59356
|
-
await decryptTransactionFields(data.data, crypto3.key);
|
|
59401
|
+
if (crypto3 && data.data) {
|
|
59402
|
+
const { data: decrypted, undecrypted } = await decryptTransactionFields(data.data, crypto3.key);
|
|
59403
|
+
data.data = decrypted;
|
|
59404
|
+
return withTruncationWarning(undecrypted.length ? { ...data, undecrypted } : data);
|
|
59405
|
+
}
|
|
59357
59406
|
return withTruncationWarning(data);
|
|
59358
59407
|
}
|
|
59359
59408
|
}),
|
|
@@ -59445,8 +59494,11 @@ function transactionTools(client, crypto3) {
|
|
|
59445
59494
|
input: exports_external.object({ ccAccountId: exports_external.string().uuid() }),
|
|
59446
59495
|
handler: async ({ ccAccountId }) => {
|
|
59447
59496
|
const data = await client.get("/api/transactions/settlement-candidates", { ccAccountId });
|
|
59448
|
-
if (crypto3 && data.data)
|
|
59449
|
-
await decryptTransactionFields(data.data, crypto3.key);
|
|
59497
|
+
if (crypto3 && data.data) {
|
|
59498
|
+
const { data: decrypted, undecrypted } = await decryptTransactionFields(data.data, crypto3.key);
|
|
59499
|
+
data.data = decrypted;
|
|
59500
|
+
return withTruncationWarning(undecrypted.length ? { ...data, undecrypted } : data);
|
|
59501
|
+
}
|
|
59450
59502
|
return withTruncationWarning(data);
|
|
59451
59503
|
}
|
|
59452
59504
|
}),
|
|
@@ -59456,11 +59508,15 @@ function transactionTools(client, crypto3) {
|
|
|
59456
59508
|
input: exports_external.object({ id: exports_external.string().uuid() }),
|
|
59457
59509
|
handler: async ({ id }) => {
|
|
59458
59510
|
const res = await client.get(`/api/transactions/${id}`);
|
|
59459
|
-
|
|
59511
|
+
let row = res.data;
|
|
59460
59512
|
if (!row)
|
|
59461
59513
|
return res;
|
|
59462
|
-
|
|
59463
|
-
|
|
59514
|
+
let undecrypted = [];
|
|
59515
|
+
if (crypto3) {
|
|
59516
|
+
const dec = await decryptTransactionFields([row], crypto3.key);
|
|
59517
|
+
row = dec.data[0];
|
|
59518
|
+
undecrypted = dec.undecrypted;
|
|
59519
|
+
}
|
|
59464
59520
|
const lean = Object.fromEntries([
|
|
59465
59521
|
"id",
|
|
59466
59522
|
"date",
|
|
@@ -59476,7 +59532,7 @@ function transactionTools(client, crypto3) {
|
|
|
59476
59532
|
"isDuplicate",
|
|
59477
59533
|
"source"
|
|
59478
59534
|
].filter((k2) => row[k2] !== undefined).map((k2) => [k2, row[k2]]));
|
|
59479
|
-
return lean;
|
|
59535
|
+
return undecrypted.length ? { ...lean, undecrypted } : lean;
|
|
59480
59536
|
}
|
|
59481
59537
|
})
|
|
59482
59538
|
];
|
|
@@ -59501,7 +59557,9 @@ function exportTools(client, crypto3) {
|
|
|
59501
59557
|
format: "json"
|
|
59502
59558
|
});
|
|
59503
59559
|
if (crypto3 && Array.isArray(data?.transactions)) {
|
|
59504
|
-
await decryptTransactionFields(data.transactions, crypto3.key);
|
|
59560
|
+
const { data: decrypted, undecrypted } = await decryptTransactionFields(data.transactions, crypto3.key);
|
|
59561
|
+
data.transactions = decrypted;
|
|
59562
|
+
return withTruncationWarning(undecrypted.length ? { ...data, undecrypted } : data);
|
|
59505
59563
|
}
|
|
59506
59564
|
return withTruncationWarning(data);
|
|
59507
59565
|
}
|
|
@@ -59509,603 +59567,231 @@ function exportTools(client, crypto3) {
|
|
|
59509
59567
|
];
|
|
59510
59568
|
}
|
|
59511
59569
|
|
|
59512
|
-
// ../../node_modules/.bun/@
|
|
59513
|
-
var
|
|
59514
|
-
var
|
|
59515
|
-
|
|
59516
|
-
|
|
59517
|
-
|
|
59518
|
-
|
|
59519
|
-
|
|
59520
|
-
|
|
59521
|
-
|
|
59522
|
-
|
|
59523
|
-
|
|
59524
|
-
|
|
59525
|
-
|
|
59526
|
-
|
|
59527
|
-
|
|
59528
|
-
|
|
59529
|
-
|
|
59530
|
-
|
|
59531
|
-
|
|
59532
|
-
|
|
59533
|
-
|
|
59534
|
-
|
|
59535
|
-
return
|
|
59536
|
-
|
|
59537
|
-
|
|
59538
|
-
|
|
59539
|
-
|
|
59540
|
-
|
|
59541
|
-
|
|
59542
|
-
|
|
59543
|
-
|
|
59544
|
-
|
|
59545
|
-
|
|
59546
|
-
|
|
59547
|
-
|
|
59548
|
-
return
|
|
59549
|
-
}
|
|
59550
|
-
|
|
59551
|
-
|
|
59552
|
-
|
|
59553
|
-
|
|
59554
|
-
|
|
59555
|
-
|
|
59556
|
-
|
|
59557
|
-
|
|
59558
|
-
if (
|
|
59559
|
-
|
|
59560
|
-
|
|
59561
|
-
|
|
59562
|
-
|
|
59563
|
-
|
|
59564
|
-
|
|
59565
|
-
|
|
59566
|
-
|
|
59567
|
-
|
|
59568
|
-
|
|
59569
|
-
|
|
59570
|
-
|
|
59571
|
-
|
|
59572
|
-
|
|
59573
|
-
|
|
59574
|
-
|
|
59575
|
-
|
|
59576
|
-
|
|
59577
|
-
|
|
59578
|
-
}
|
|
59579
|
-
|
|
59580
|
-
|
|
59581
|
-
|
|
59582
|
-
|
|
59583
|
-
|
|
59584
|
-
return ms;
|
|
59585
|
-
const raw = headers.get("retry-after");
|
|
59586
|
-
if (raw === null)
|
|
59587
|
-
return;
|
|
59588
|
-
const seconds = Number(raw);
|
|
59589
|
-
if (Number.isFinite(seconds))
|
|
59590
|
-
return seconds >= 0 ? seconds * 1000 : undefined;
|
|
59591
|
-
const date5 = Date.parse(raw);
|
|
59592
|
-
if (!Number.isNaN(date5))
|
|
59593
|
-
return Math.max(0, date5 - now);
|
|
59594
|
-
};
|
|
59595
|
-
var retryDelayMs = (attempt, headers, policy = DEFAULT_RETRY_POLICY, random = Math.random) => {
|
|
59596
|
-
if (policy.respectRetryAfter && headers !== undefined) {
|
|
59597
|
-
const retryAfter = parseRetryAfter(headers);
|
|
59598
|
-
if (retryAfter !== undefined && retryAfter <= policy.maxRetryAfterMs)
|
|
59599
|
-
return retryAfter;
|
|
59600
|
-
}
|
|
59601
|
-
const exponential = Math.min(policy.backoffInitialMs * 2 ** attempt, policy.backoffMaxMs);
|
|
59602
|
-
return Math.round(exponential * (1 - random() * policy.backoffJitter));
|
|
59603
|
-
};
|
|
59604
|
-
var sleep3 = (ms, signal) => new Promise((resolve, reject) => {
|
|
59605
|
-
if (signal?.aborted)
|
|
59606
|
-
return reject(signal.reason);
|
|
59607
|
-
const onAbort = () => {
|
|
59608
|
-
clearTimeout(timer);
|
|
59609
|
-
reject(signal?.reason);
|
|
59610
|
-
};
|
|
59611
|
-
const timer = setTimeout(() => {
|
|
59612
|
-
signal?.removeEventListener("abort", onAbort);
|
|
59613
|
-
resolve();
|
|
59614
|
-
}, ms);
|
|
59615
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
59616
|
-
});
|
|
59617
|
-
var TypeSafeError = class extends Error {
|
|
59618
|
-
constructor(message, options) {
|
|
59619
|
-
super(message, options);
|
|
59620
|
-
this.name = new.target.name;
|
|
59621
|
-
}
|
|
59622
|
-
};
|
|
59623
|
-
var isRecord = (value) => typeof value === "object" && value !== null;
|
|
59624
|
-
var extractMessage = (body) => {
|
|
59625
|
-
if (typeof body === "string")
|
|
59626
|
-
return body || undefined;
|
|
59627
|
-
if (!isRecord(body))
|
|
59628
|
-
return;
|
|
59629
|
-
const { error: error62, message, detail } = body;
|
|
59630
|
-
if (typeof error62 === "string")
|
|
59631
|
-
return error62;
|
|
59632
|
-
if (isRecord(error62) && typeof error62.message === "string")
|
|
59633
|
-
return error62.message;
|
|
59634
|
-
if (typeof message === "string")
|
|
59635
|
-
return message;
|
|
59636
|
-
if (typeof detail === "string")
|
|
59637
|
-
return detail;
|
|
59638
|
-
if (isRecord(detail) && typeof detail.message === "string")
|
|
59639
|
-
return detail.message;
|
|
59640
|
-
if (Array.isArray(detail))
|
|
59641
|
-
return describeValidationErrors(detail);
|
|
59642
|
-
};
|
|
59643
|
-
var describeValidationErrors = (errors3) => {
|
|
59644
|
-
const parts = errors3.flatMap((e2) => {
|
|
59645
|
-
if (!isRecord(e2) || typeof e2.msg !== "string")
|
|
59646
|
-
return [];
|
|
59647
|
-
const loc = Array.isArray(e2.loc) ? e2.loc.filter((x2) => x2 !== "body").join(".") : "";
|
|
59648
|
-
return [loc ? `${loc}: ${e2.msg}` : e2.msg];
|
|
59649
|
-
});
|
|
59650
|
-
return parts.length > 0 ? parts.join("; ") : undefined;
|
|
59651
|
-
};
|
|
59652
|
-
var MAX_RAW_BODY_IN_MESSAGE = 200;
|
|
59653
|
-
var APIError = class APIError2 extends TypeSafeError {
|
|
59654
|
-
status;
|
|
59655
|
-
headers;
|
|
59656
|
-
body;
|
|
59657
|
-
requestId;
|
|
59658
|
-
constructor(status, body, headers, message) {
|
|
59659
|
-
super(message ?? APIError2.describe(status, body));
|
|
59660
|
-
this.status = status;
|
|
59661
|
-
this.body = body;
|
|
59662
|
-
this.headers = headers;
|
|
59663
|
-
this.requestId = requestIdFrom(headers);
|
|
59664
|
-
}
|
|
59665
|
-
static describe(status, body) {
|
|
59666
|
-
const detail = extractMessage(body);
|
|
59667
|
-
if (detail)
|
|
59668
|
-
return `${status} ${detail}`;
|
|
59669
|
-
if (body === undefined)
|
|
59670
|
-
return `${status} status code (no body)`;
|
|
59671
|
-
const raw = typeof body === "string" ? body : JSON.stringify(body);
|
|
59672
|
-
return `${status} ${raw.length > MAX_RAW_BODY_IN_MESSAGE ? `${raw.slice(0, MAX_RAW_BODY_IN_MESSAGE)}…` : raw}`;
|
|
59673
|
-
}
|
|
59674
|
-
static fromResponse(status, body, headers) {
|
|
59675
|
-
if (status === 400)
|
|
59676
|
-
return new BadRequestError(status, body, headers);
|
|
59677
|
-
if (status === 401)
|
|
59678
|
-
return new AuthenticationError(status, body, headers);
|
|
59679
|
-
if (status === 403)
|
|
59680
|
-
return new PermissionDeniedError(status, body, headers);
|
|
59681
|
-
if (status === 404)
|
|
59682
|
-
return new NotFoundError(status, body, headers);
|
|
59683
|
-
if (status === 422)
|
|
59684
|
-
return new UnprocessableEntityError(status, body, headers);
|
|
59685
|
-
if (status === 429)
|
|
59686
|
-
return new RateLimitError(status, body, headers);
|
|
59687
|
-
if (status >= 500)
|
|
59688
|
-
return new InternalServerError(status, body, headers);
|
|
59689
|
-
return new APIError2(status, body, headers);
|
|
59690
|
-
}
|
|
59691
|
-
};
|
|
59692
|
-
var BadRequestError = class extends APIError {
|
|
59693
|
-
};
|
|
59694
|
-
var AuthenticationError = class extends APIError {
|
|
59695
|
-
};
|
|
59696
|
-
var PermissionDeniedError = class extends APIError {
|
|
59697
|
-
};
|
|
59698
|
-
var NotFoundError = class extends APIError {
|
|
59699
|
-
};
|
|
59700
|
-
var UnprocessableEntityError = class extends APIError {
|
|
59701
|
-
};
|
|
59702
|
-
var RateLimitError = class extends APIError {
|
|
59703
|
-
retryAfterMs = parseRetryAfter(this.headers);
|
|
59704
|
-
};
|
|
59705
|
-
var InternalServerError = class extends APIError {
|
|
59706
|
-
};
|
|
59707
|
-
var APIConnectionError = class extends TypeSafeError {
|
|
59708
|
-
constructor(message = "Connection error.", options) {
|
|
59709
|
-
super(message, options);
|
|
59710
|
-
}
|
|
59711
|
-
};
|
|
59712
|
-
var APITimeoutError = class extends APIConnectionError {
|
|
59713
|
-
timeoutMs;
|
|
59714
|
-
constructor(timeoutMs, options) {
|
|
59715
|
-
super(`Request timed out after ${timeoutMs}ms.`, options);
|
|
59716
|
-
this.timeoutMs = timeoutMs;
|
|
59717
|
-
}
|
|
59718
|
-
};
|
|
59719
|
-
var APIUserAbortError = class extends TypeSafeError {
|
|
59720
|
-
constructor(message = "Request was aborted.", options) {
|
|
59721
|
-
super(message, options);
|
|
59722
|
-
}
|
|
59723
|
-
};
|
|
59724
|
-
var LOG_LEVELS = [
|
|
59725
|
-
"debug",
|
|
59726
|
-
"info",
|
|
59727
|
-
"warn",
|
|
59728
|
-
"error",
|
|
59729
|
-
"off"
|
|
59730
|
-
];
|
|
59731
|
-
var DEFAULT_LOG_LEVEL = "warn";
|
|
59732
|
-
var isLogLevel = (value) => LOG_LEVELS.includes(value);
|
|
59733
|
-
var parseLogLevel = (value, source) => {
|
|
59734
|
-
if (isLogLevel(value))
|
|
59735
|
-
return value;
|
|
59736
|
-
throw new TypeSafeError(`Invalid log level "${value}" from ${source}. Expected one of: ${LOG_LEVELS.join(", ")}.`);
|
|
59737
|
-
};
|
|
59738
|
-
var PREFIX = "[typesafe-sdk]";
|
|
59739
|
-
var consoleLogger = {
|
|
59740
|
-
debug: (message, ...args) => console.debug(`${PREFIX} ${message}`, ...args),
|
|
59741
|
-
info: (message, ...args) => console.info(`${PREFIX} ${message}`, ...args),
|
|
59742
|
-
warn: (message, ...args) => console.warn(`${PREFIX} ${message}`, ...args),
|
|
59743
|
-
error: (message, ...args) => console.error(`${PREFIX} ${message}`, ...args)
|
|
59744
|
-
};
|
|
59745
|
-
var RANK = {
|
|
59746
|
-
debug: 0,
|
|
59747
|
-
info: 1,
|
|
59748
|
-
warn: 2,
|
|
59749
|
-
error: 3,
|
|
59750
|
-
off: 4
|
|
59751
|
-
};
|
|
59752
|
-
var drop = () => {};
|
|
59753
|
-
var withLevel = (sink, level) => {
|
|
59754
|
-
const enabled = (at2) => RANK[at2] >= RANK[level];
|
|
59755
|
-
return {
|
|
59756
|
-
debug: enabled("debug") ? (message, ...args) => sink.debug(message, ...args) : drop,
|
|
59757
|
-
info: enabled("info") ? (message, ...args) => sink.info(message, ...args) : drop,
|
|
59758
|
-
warn: enabled("warn") ? (message, ...args) => sink.warn(message, ...args) : drop,
|
|
59759
|
-
error: enabled("error") ? (message, ...args) => sink.error(message, ...args) : drop
|
|
59760
|
-
};
|
|
59761
|
-
};
|
|
59762
|
-
var KEY_HEADERS = /* @__PURE__ */ new Set([
|
|
59763
|
-
"authorization",
|
|
59764
|
-
"proxy-authorization",
|
|
59765
|
-
"x-api-key"
|
|
59766
|
-
]);
|
|
59767
|
-
var OPAQUE_HEADERS = /* @__PURE__ */ new Set(["cookie", "set-cookie"]);
|
|
59768
|
-
var redactKey = (value) => {
|
|
59769
|
-
const [scheme, secret] = value.includes(" ") ? value.split(/\s+/, 2) : [undefined, value];
|
|
59770
|
-
const tail = secret && secret.length > 8 ? secret.slice(-4) : "";
|
|
59771
|
-
return `${scheme ? `${scheme} ` : ""}***${tail}`;
|
|
59772
|
-
};
|
|
59773
|
-
var redact = (name, value) => {
|
|
59774
|
-
const lower = name.toLowerCase();
|
|
59775
|
-
if (KEY_HEADERS.has(lower))
|
|
59776
|
-
return redactKey(value);
|
|
59777
|
-
if (OPAQUE_HEADERS.has(lower))
|
|
59778
|
-
return "***";
|
|
59779
|
-
return value;
|
|
59780
|
-
};
|
|
59781
|
-
var redactHeaders = (headers) => Object.fromEntries(Object.entries(headers).map(([name, value]) => [name, redact(name, value)]));
|
|
59782
|
-
var choice = (instructions, criteria) => {
|
|
59783
|
-
if (Array.isArray(criteria))
|
|
59784
|
-
throw new TypeSafeError("Choice criteria must be a map of labels to descriptions, not a list.");
|
|
59785
|
-
return {
|
|
59786
|
-
type: "choice",
|
|
59787
|
-
instructions,
|
|
59788
|
-
criteria
|
|
59789
|
-
};
|
|
59790
|
-
};
|
|
59791
|
-
var validateQuestions = (questions) => {
|
|
59792
|
-
if (Object.keys(questions).length === 0)
|
|
59793
|
-
throw new TypeSafeError("At least one question is required.");
|
|
59794
|
-
for (const [name, question] of Object.entries(questions)) {
|
|
59795
|
-
if (question.type !== "score")
|
|
59796
|
-
continue;
|
|
59797
|
-
if (!Array.isArray(question.criteria))
|
|
59798
|
-
throw new TypeSafeError(`Score question "${name}" has criteria that are not a list; score criteria must be a list of descriptions indexed by score from zero.`);
|
|
59799
|
-
if (question.criteria.length < 2)
|
|
59800
|
-
throw new TypeSafeError(`Score question "${name}" has ${question.criteria.length} criteria; at least two scores are required.`);
|
|
59801
|
-
}
|
|
59802
|
-
};
|
|
59803
|
-
var Models = class {
|
|
59804
|
-
#transport;
|
|
59805
|
-
constructor(transport) {
|
|
59806
|
-
this.#transport = transport;
|
|
59807
|
-
}
|
|
59808
|
-
list(options = {}) {
|
|
59809
|
-
return this.#transport.request("GET", "/v1/models", options).map(unwrapModels);
|
|
59810
|
-
}
|
|
59811
|
-
};
|
|
59812
|
-
var unwrapModels = (wire) => {
|
|
59813
|
-
if (Array.isArray(wire?.models))
|
|
59814
|
-
return wire.models;
|
|
59815
|
-
throw new TypeSafeError("Unexpected response shape from GET /v1/models; expected { models: [...] }.");
|
|
59816
|
-
};
|
|
59817
|
-
var g2 = globalThis;
|
|
59818
|
-
var isBrowser = () => typeof g2.window !== "undefined" && typeof g2.window.document !== "undefined" && typeof g2.navigator !== "undefined";
|
|
59819
|
-
var describeRuntime = () => {
|
|
59820
|
-
const platform = g2.process?.platform && g2.process?.arch ? ` (${g2.process.platform}; ${g2.process.arch})` : "";
|
|
59821
|
-
if (g2.Bun?.version)
|
|
59822
|
-
return `bun/${g2.Bun.version}${platform}`;
|
|
59823
|
-
if (g2.Deno?.version?.deno)
|
|
59824
|
-
return `deno/${g2.Deno.version.deno}${platform}`;
|
|
59825
|
-
if (g2.EdgeRuntime !== undefined)
|
|
59826
|
-
return "vercel-edge";
|
|
59827
|
-
if (g2.navigator?.userAgent === "Cloudflare-Workers")
|
|
59828
|
-
return "cloudflare-workers";
|
|
59829
|
-
if (g2.process?.versions?.node)
|
|
59830
|
-
return `node/${g2.process.versions.node}${platform}`;
|
|
59831
|
-
if (isBrowser())
|
|
59832
|
-
return "browser";
|
|
59833
|
-
return "unknown";
|
|
59834
|
-
};
|
|
59835
|
-
var VERSION2 = "0.6.0";
|
|
59836
|
-
var missingApiKey = () => {
|
|
59837
|
-
throw new TypeSafeError(`No API key was provided. Pass \`apiKey\` to the TypeSafeClient constructor or set the ${ENV.apiKey} environment variable.`);
|
|
59838
|
-
};
|
|
59839
|
-
var missingFetch = () => {
|
|
59840
|
-
throw new TypeSafeError("No global `fetch` is available in this runtime. Pass a `fetch` implementation to the TypeSafeClient constructor.");
|
|
59841
|
-
};
|
|
59842
|
-
var refuseBrowser = () => {
|
|
59843
|
-
throw new TypeSafeError("TypeSafeClient is running in a browser, which would expose your API key to anyone using the page. Call the API from a server instead, or pass `dangerouslyAllowBrowser: true` if you understand the risk.");
|
|
59844
|
-
};
|
|
59845
|
-
var defaultFetch = (input2, init) => globalThis.fetch(input2, init);
|
|
59846
|
-
var assertNonNegativeInteger = (name, value) => {
|
|
59847
|
-
if (!Number.isInteger(value) || value < 0)
|
|
59848
|
-
throw new TypeSafeError(`\`${name}\` must be a non-negative integer, got ${String(value)}.`);
|
|
59849
|
-
return value;
|
|
59850
|
-
};
|
|
59851
|
-
var assertPositiveMs = (name, value) => {
|
|
59852
|
-
if (!Number.isFinite(value) || value <= 0)
|
|
59853
|
-
throw new TypeSafeError(`\`${name}\` must be a positive number of milliseconds, got ${String(value)}.`);
|
|
59854
|
-
return value;
|
|
59855
|
-
};
|
|
59856
|
-
var assertNonNegativeMs = (name, value) => {
|
|
59857
|
-
if (!Number.isFinite(value) || value < 0)
|
|
59858
|
-
throw new TypeSafeError(`\`${name}\` must be a non-negative number of milliseconds, got ${String(value)}.`);
|
|
59859
|
-
return value;
|
|
59860
|
-
};
|
|
59861
|
-
var assertFraction = (name, value) => {
|
|
59862
|
-
if (!Number.isFinite(value) || value < 0 || value > 1)
|
|
59863
|
-
throw new TypeSafeError(`\`${name}\` must be between 0 and 1, got ${String(value)}.`);
|
|
59864
|
-
return value;
|
|
59865
|
-
};
|
|
59866
|
-
var assertStatusSet = (name, statuses) => {
|
|
59867
|
-
for (const status of statuses)
|
|
59868
|
-
if (!Number.isInteger(status) || status < 100 || status > 999)
|
|
59869
|
-
throw new TypeSafeError(`\`${name}\` must contain HTTP status codes, got ${String(status)}.`);
|
|
59870
|
-
return statuses;
|
|
59871
|
-
};
|
|
59872
|
-
var resolveRetryPolicy = (base, overrides) => {
|
|
59873
|
-
const o2 = overrides ?? {};
|
|
59874
|
-
return {
|
|
59875
|
-
maxRetries: o2.maxRetries === undefined ? base.maxRetries : assertNonNegativeInteger("retry.maxRetries", o2.maxRetries),
|
|
59876
|
-
backoffInitialMs: o2.backoffInitialMs === undefined ? base.backoffInitialMs : assertNonNegativeMs("retry.backoffInitialMs", o2.backoffInitialMs),
|
|
59877
|
-
backoffMaxMs: o2.backoffMaxMs === undefined ? base.backoffMaxMs : assertNonNegativeMs("retry.backoffMaxMs", o2.backoffMaxMs),
|
|
59878
|
-
backoffJitter: o2.backoffJitter === undefined ? base.backoffJitter : assertFraction("retry.backoffJitter", o2.backoffJitter),
|
|
59879
|
-
httpStatuses: new Set(o2.httpStatuses === undefined ? base.httpStatuses : assertStatusSet("retry.httpStatuses", o2.httpStatuses)),
|
|
59880
|
-
respectRetryAfter: o2.respectRetryAfter ?? base.respectRetryAfter,
|
|
59881
|
-
maxRetryAfterMs: o2.maxRetryAfterMs === undefined ? base.maxRetryAfterMs : assertNonNegativeMs("retry.maxRetryAfterMs", o2.maxRetryAfterMs),
|
|
59882
|
-
apiConnectionError: o2.apiConnectionError ?? base.apiConnectionError,
|
|
59883
|
-
apiTimeoutError: o2.apiTimeoutError ?? base.apiTimeoutError
|
|
59884
|
-
};
|
|
59885
|
-
};
|
|
59886
|
-
var isRetryableError = (err, policy) => {
|
|
59887
|
-
if (err instanceof APITimeoutError)
|
|
59888
|
-
return policy.apiTimeoutError;
|
|
59889
|
-
if (err instanceof APIConnectionError)
|
|
59890
|
-
return policy.apiConnectionError;
|
|
59891
|
-
return false;
|
|
59892
|
-
};
|
|
59893
|
-
var resolveLogLevel = (fromCode) => {
|
|
59894
|
-
if (fromCode !== undefined)
|
|
59895
|
-
return parseLogLevel(fromCode, "the `logLevel` option");
|
|
59896
|
-
const fromEnv = readEnv(ENV.logLevel);
|
|
59897
|
-
if (fromEnv !== undefined)
|
|
59898
|
-
return parseLogLevel(fromEnv, ENV.logLevel);
|
|
59899
|
-
return DEFAULT_LOG_LEVEL;
|
|
59900
|
-
};
|
|
59901
|
-
var stripTrailingSlashes = (url3) => url3.replace(/\/+$/, "");
|
|
59902
|
-
var mergeHeaders = (...sources) => {
|
|
59903
|
-
const entries = /* @__PURE__ */ new Map;
|
|
59904
|
-
for (const source of sources)
|
|
59905
|
-
for (const [name, value] of Object.entries(source))
|
|
59906
|
-
if (value === undefined)
|
|
59907
|
-
entries.delete(name.toLowerCase());
|
|
59908
|
-
else
|
|
59909
|
-
entries.set(name.toLowerCase(), [name, value]);
|
|
59910
|
-
return Object.fromEntries(entries.values());
|
|
59911
|
-
};
|
|
59912
|
-
var bufferResponse = async (response, signal) => {
|
|
59913
|
-
const reader = response.clone().body?.getReader();
|
|
59914
|
-
if (!reader)
|
|
59915
|
-
return;
|
|
59916
|
-
const cancel = () => {
|
|
59917
|
-
reader.cancel(signal.reason).catch(() => {});
|
|
59918
|
-
response.body?.cancel(signal.reason).catch(() => {});
|
|
59919
|
-
};
|
|
59920
|
-
signal.addEventListener("abort", cancel, { once: true });
|
|
59921
|
-
try {
|
|
59922
|
-
if (signal.aborted)
|
|
59923
|
-
cancel();
|
|
59924
|
-
signal.throwIfAborted();
|
|
59925
|
-
while (!(await reader.read()).done)
|
|
59926
|
-
signal.throwIfAborted();
|
|
59927
|
-
signal.throwIfAborted();
|
|
59928
|
-
} finally {
|
|
59929
|
-
signal.removeEventListener("abort", cancel);
|
|
59930
|
-
reader.releaseLock();
|
|
59931
|
-
}
|
|
59932
|
-
};
|
|
59933
|
-
var RUNTIME = describeRuntime();
|
|
59934
|
-
var TypeSafeClient = class {
|
|
59935
|
-
#apiKey;
|
|
59936
|
-
baseURL;
|
|
59937
|
-
defaultModel;
|
|
59938
|
-
logLevel;
|
|
59939
|
-
logger;
|
|
59940
|
-
retry;
|
|
59941
|
-
timeout;
|
|
59942
|
-
defaultHeaders;
|
|
59943
|
-
fetch;
|
|
59944
|
-
models;
|
|
59945
|
-
#requestCount = 0;
|
|
59946
|
-
constructor(config2 = {}) {
|
|
59947
|
-
if (isBrowser() && !config2.dangerouslyAllowBrowser)
|
|
59948
|
-
refuseBrowser();
|
|
59949
|
-
this.#apiKey = fromCodeOrEnv(config2.apiKey, ENV.apiKey) ?? missingApiKey();
|
|
59950
|
-
this.baseURL = stripTrailingSlashes(fromCodeOrEnv(config2.baseURL, ENV.baseURL) ?? "https://api.typesafe.ai");
|
|
59951
|
-
this.defaultModel = fromCodeOrEnv(config2.defaultModel, ENV.defaultModel) ?? "jev-latest";
|
|
59952
|
-
this.logLevel = resolveLogLevel(config2.logLevel);
|
|
59953
|
-
this.logger = withLevel(config2.logger ?? consoleLogger, this.logLevel);
|
|
59954
|
-
this.retry = resolveRetryPolicy(DEFAULT_RETRY_POLICY, config2.retry);
|
|
59955
|
-
this.timeout = assertPositiveMs("timeout", config2.timeout ?? 1e4);
|
|
59956
|
-
this.defaultHeaders = { ...config2.defaultHeaders };
|
|
59957
|
-
if (config2.fetch === undefined && typeof globalThis.fetch !== "function")
|
|
59958
|
-
missingFetch();
|
|
59959
|
-
this.fetch = config2.fetch ?? defaultFetch;
|
|
59960
|
-
const transport = {
|
|
59961
|
-
request: (method, path, options) => this.#request(method, path, options),
|
|
59962
|
-
defaultModel: this.defaultModel
|
|
59963
|
-
};
|
|
59964
|
-
this.models = new Models(transport);
|
|
59965
|
-
}
|
|
59966
|
-
systemOne(request, options = {}) {
|
|
59967
|
-
validateQuestions(request.questions);
|
|
59968
|
-
const body = {
|
|
59969
|
-
...request,
|
|
59970
|
-
model: request.model ?? this.defaultModel
|
|
59971
|
-
};
|
|
59972
|
-
return this.#request("POST", "/v1/systemone", {
|
|
59973
|
-
...options,
|
|
59974
|
-
body
|
|
59975
|
-
});
|
|
59570
|
+
// ../../node_modules/.bun/@nimit9+signet-ai@0.1.11+53d0ad1559459462/node_modules/@nimit9/signet-ai/dist/jev.js
|
|
59571
|
+
var JEV_DEFAULT_MODEL = "jev-1.13.0";
|
|
59572
|
+
var JEV_DEFAULT_MIN_CONFIDENCE = 0.95;
|
|
59573
|
+
var JEV_DEFAULT_TIMEOUT_MS = 8000;
|
|
59574
|
+
var JEV_DEFAULT_BASE_URL = "https://api.typesafe.ai";
|
|
59575
|
+
function fallbackOf(q2, reason, extra = {}) {
|
|
59576
|
+
const d2 = { value: q2.fallback, confident: false, source: "fallback", reason };
|
|
59577
|
+
if (extra.confidence !== undefined)
|
|
59578
|
+
d2.confidence = extra.confidence;
|
|
59579
|
+
if (extra.answer !== undefined)
|
|
59580
|
+
d2.answer = extra.answer;
|
|
59581
|
+
if (extra.probability !== undefined)
|
|
59582
|
+
d2.probability = extra.probability;
|
|
59583
|
+
return d2;
|
|
59584
|
+
}
|
|
59585
|
+
function labelsOf(options) {
|
|
59586
|
+
return Array.isArray(options) ? [...options] : Object.keys(options);
|
|
59587
|
+
}
|
|
59588
|
+
function isUnit(n2) {
|
|
59589
|
+
return typeof n2 === "number" && Number.isFinite(n2) && n2 >= 0 && n2 <= 1;
|
|
59590
|
+
}
|
|
59591
|
+
function validQuestion(q2) {
|
|
59592
|
+
if (!q2 || typeof q2.question !== "string")
|
|
59593
|
+
return false;
|
|
59594
|
+
if (q2.type === "choice") {
|
|
59595
|
+
const labels = labelsOf(q2.options);
|
|
59596
|
+
return labels.length >= 1 && labels.length <= 255 && labels.includes(q2.fallback);
|
|
59597
|
+
}
|
|
59598
|
+
if (q2.type === "score") {
|
|
59599
|
+
return Array.isArray(q2.levels) && q2.levels.length >= 2 && q2.levels.length <= 10;
|
|
59600
|
+
}
|
|
59601
|
+
return q2.type === "noul";
|
|
59602
|
+
}
|
|
59603
|
+
function toWire(q2) {
|
|
59604
|
+
if (q2.type === "choice") {
|
|
59605
|
+
const criteria = Array.isArray(q2.options) ? Object.fromEntries(q2.options.map((l2) => [l2, null])) : q2.options;
|
|
59606
|
+
return { type: "choice", instructions: q2.question, criteria };
|
|
59607
|
+
}
|
|
59608
|
+
if (q2.type === "score")
|
|
59609
|
+
return { type: "score", instructions: q2.question, criteria: q2.levels };
|
|
59610
|
+
return { type: "noul", instructions: q2.question };
|
|
59611
|
+
}
|
|
59612
|
+
function judge(q2, raw, min) {
|
|
59613
|
+
const a2 = raw;
|
|
59614
|
+
if (!a2 || typeof a2 !== "object")
|
|
59615
|
+
return fallbackOf(q2, "invalid_response");
|
|
59616
|
+
if (q2.type === "noul") {
|
|
59617
|
+
const p2 = a2.noul;
|
|
59618
|
+
if (!isUnit(p2))
|
|
59619
|
+
return fallbackOf(q2, "invalid_response");
|
|
59620
|
+
const confidence2 = Math.max(p2, 1 - p2);
|
|
59621
|
+
const answer2 = p2 >= 0.5;
|
|
59622
|
+
if (confidence2 < min) {
|
|
59623
|
+
return fallbackOf(q2, "low_confidence", { confidence: confidence2, answer: answer2, probability: p2 });
|
|
59624
|
+
}
|
|
59625
|
+
return { value: answer2, confident: true, source: "jev", confidence: confidence2, probability: p2 };
|
|
59626
|
+
}
|
|
59627
|
+
const confidence = a2.confidence;
|
|
59628
|
+
if (!isUnit(confidence))
|
|
59629
|
+
return fallbackOf(q2, "invalid_response");
|
|
59630
|
+
let answer;
|
|
59631
|
+
if (q2.type === "choice") {
|
|
59632
|
+
if (typeof a2.choice !== "string" || !labelsOf(q2.options).includes(a2.choice)) {
|
|
59633
|
+
return fallbackOf(q2, "invalid_response", { confidence });
|
|
59634
|
+
}
|
|
59635
|
+
answer = a2.choice;
|
|
59636
|
+
} else {
|
|
59637
|
+
const s2 = a2.score;
|
|
59638
|
+
if (typeof s2 !== "number" || !Number.isFinite(s2) || s2 < 0 || s2 > q2.levels.length - 1) {
|
|
59639
|
+
return fallbackOf(q2, "invalid_response", { confidence });
|
|
59640
|
+
}
|
|
59641
|
+
answer = s2;
|
|
59976
59642
|
}
|
|
59977
|
-
|
|
59978
|
-
|
|
59979
|
-
|
|
59980
|
-
|
|
59981
|
-
|
|
59982
|
-
|
|
59983
|
-
|
|
59984
|
-
|
|
59985
|
-
|
|
59986
|
-
|
|
59987
|
-
|
|
59988
|
-
|
|
59989
|
-
|
|
59990
|
-
|
|
59991
|
-
|
|
59992
|
-
|
|
59643
|
+
if (confidence < min)
|
|
59644
|
+
return fallbackOf(q2, "low_confidence", { confidence, answer });
|
|
59645
|
+
return { value: answer, confident: true, source: "jev", confidence };
|
|
59646
|
+
}
|
|
59647
|
+
|
|
59648
|
+
class Timeout {
|
|
59649
|
+
}
|
|
59650
|
+
function createJev(config2) {
|
|
59651
|
+
const apiKey = typeof config2.apiKey === "string" ? config2.apiKey.trim() : "";
|
|
59652
|
+
const model = config2.model ?? JEV_DEFAULT_MODEL;
|
|
59653
|
+
const floor = config2.minConfidence ?? JEV_DEFAULT_MIN_CONFIDENCE;
|
|
59654
|
+
const timeoutMs = config2.timeoutMs ?? JEV_DEFAULT_TIMEOUT_MS;
|
|
59655
|
+
const allowSensitive = config2.allowSensitive === true;
|
|
59656
|
+
const url3 = `${(config2.baseUrl ?? JEV_DEFAULT_BASE_URL).replace(/\/+$/, "")}/v1/systemone`;
|
|
59657
|
+
function emit(event) {
|
|
59658
|
+
if (!config2.onEvent)
|
|
59659
|
+
return;
|
|
59660
|
+
try {
|
|
59661
|
+
config2.onEvent(event);
|
|
59662
|
+
} catch {}
|
|
59993
59663
|
}
|
|
59994
|
-
|
|
59995
|
-
const
|
|
59996
|
-
const
|
|
59997
|
-
|
|
59998
|
-
|
|
59999
|
-
|
|
60000
|
-
|
|
60001
|
-
|
|
60002
|
-
|
|
60003
|
-
|
|
60004
|
-
});
|
|
60005
|
-
const body = req.body === undefined ? undefined : JSON.stringify(req.body);
|
|
60006
|
-
for (let attempt = 0;; attempt++) {
|
|
60007
|
-
const retriesLeft = req.retry.maxRetries - attempt;
|
|
60008
|
-
const attemptHeaders = attempt === 0 ? headers : {
|
|
60009
|
-
...headers,
|
|
60010
|
-
"X-TypeSafe-Retry-Count": String(attempt)
|
|
59664
|
+
function finish(questions, decisions, meta3) {
|
|
59665
|
+
const durationMs = Date.now() - meta3.started;
|
|
59666
|
+
for (const [name, d2] of Object.entries(decisions)) {
|
|
59667
|
+
const event = {
|
|
59668
|
+
kind: questions[name].type,
|
|
59669
|
+
name,
|
|
59670
|
+
source: d2.source,
|
|
59671
|
+
sensitive: meta3.sensitive,
|
|
59672
|
+
model,
|
|
59673
|
+
durationMs
|
|
60011
59674
|
};
|
|
60012
|
-
|
|
60013
|
-
|
|
60014
|
-
|
|
60015
|
-
|
|
60016
|
-
|
|
60017
|
-
|
|
60018
|
-
|
|
60019
|
-
res = await this.attempt(tag, url3, {
|
|
60020
|
-
method: req.method,
|
|
60021
|
-
headers: attemptHeaders,
|
|
60022
|
-
body
|
|
60023
|
-
}, req);
|
|
60024
|
-
} catch (err) {
|
|
60025
|
-
if (err instanceof APIUserAbortError || retriesLeft <= 0)
|
|
60026
|
-
throw err;
|
|
60027
|
-
if (!isRetryableError(err, req.retry))
|
|
60028
|
-
throw err;
|
|
60029
|
-
await this.backOff(tag, attempt, retriesLeft, err.message, undefined, req);
|
|
60030
|
-
continue;
|
|
60031
|
-
}
|
|
60032
|
-
const requestId = requestIdFrom(res.headers);
|
|
60033
|
-
this.logger.info(`${tag} <- ${res.status} in ${Date.now() - started}ms${requestId ? ` (request ${requestId})` : ""}`);
|
|
60034
|
-
if (res.ok)
|
|
60035
|
-
return res;
|
|
60036
|
-
const errorBody = await parseBody(res);
|
|
60037
|
-
this.logger.debug(`${tag} <- error body`, errorBody);
|
|
60038
|
-
const error62 = APIError.fromResponse(res.status, errorBody, res.headers);
|
|
60039
|
-
if (retriesLeft <= 0 || !isRetryableStatus(res.status, req.retry))
|
|
60040
|
-
throw error62;
|
|
60041
|
-
await this.backOff(tag, attempt, retriesLeft, `${res.status}`, res.headers, req);
|
|
59675
|
+
if (d2.reason)
|
|
59676
|
+
event.reason = d2.reason;
|
|
59677
|
+
if (d2.confidence !== undefined)
|
|
59678
|
+
event.confidence = d2.confidence;
|
|
59679
|
+
if (meta3.status !== undefined && d2.reason === "http_error")
|
|
59680
|
+
event.status = meta3.status;
|
|
59681
|
+
emit(event);
|
|
60042
59682
|
}
|
|
59683
|
+
return decisions;
|
|
60043
59684
|
}
|
|
60044
|
-
async
|
|
60045
|
-
const controller = new AbortController;
|
|
60046
|
-
const abortFromCaller = () => controller.abort(signal?.reason);
|
|
60047
|
-
if (signal?.aborted)
|
|
60048
|
-
abortFromCaller();
|
|
60049
|
-
signal?.addEventListener("abort", abortFromCaller, { once: true });
|
|
60050
|
-
let timedOut = false;
|
|
60051
|
-
const timer = setTimeout(() => {
|
|
60052
|
-
timedOut = true;
|
|
60053
|
-
controller.abort();
|
|
60054
|
-
}, timeout);
|
|
59685
|
+
async function run(questions, base) {
|
|
60055
59686
|
const started = Date.now();
|
|
60056
|
-
const
|
|
59687
|
+
const sensitive = base.sensitive === true;
|
|
59688
|
+
const all2 = (reason, status2) => finish(questions, Object.fromEntries(Object.entries(questions).map(([n2, q2]) => [n2, fallbackOf(q2, reason)])), { sensitive, started, status: status2 });
|
|
59689
|
+
if (base.sensitive !== false && !allowSensitive)
|
|
59690
|
+
return all2("sensitive_not_allowed");
|
|
59691
|
+
if (!apiKey)
|
|
59692
|
+
return all2("no_key");
|
|
59693
|
+
const min = base.minConfidence ?? floor;
|
|
59694
|
+
const names = Object.keys(questions);
|
|
59695
|
+
if (!isUnit(min) || names.length === 0 || !names.every((n2) => validQuestion(questions[n2]))) {
|
|
59696
|
+
return all2("invalid_request");
|
|
59697
|
+
}
|
|
59698
|
+
if (base.signal?.aborted)
|
|
59699
|
+
return all2("aborted");
|
|
59700
|
+
const controller = new AbortController;
|
|
59701
|
+
const onAbort = () => controller.abort();
|
|
59702
|
+
base.signal?.addEventListener("abort", onAbort, { once: true });
|
|
59703
|
+
let timer;
|
|
59704
|
+
const timeout = new Promise((resolve) => {
|
|
59705
|
+
timer = setTimeout(() => {
|
|
59706
|
+
controller.abort();
|
|
59707
|
+
resolve(new Timeout);
|
|
59708
|
+
}, timeoutMs);
|
|
59709
|
+
});
|
|
59710
|
+
const doFetch = config2.fetch ?? ((u2, i2) => globalThis.fetch(u2, i2));
|
|
59711
|
+
let status;
|
|
60057
59712
|
try {
|
|
60058
|
-
const
|
|
60059
|
-
|
|
60060
|
-
|
|
60061
|
-
|
|
60062
|
-
|
|
60063
|
-
|
|
59713
|
+
const request = (async () => {
|
|
59714
|
+
const res = await doFetch(url3, {
|
|
59715
|
+
method: "POST",
|
|
59716
|
+
headers: {
|
|
59717
|
+
Authorization: `Bearer ${apiKey}`,
|
|
59718
|
+
Accept: "application/json",
|
|
59719
|
+
"Content-Type": "application/json"
|
|
59720
|
+
},
|
|
59721
|
+
body: JSON.stringify({
|
|
59722
|
+
model,
|
|
59723
|
+
state: base.state,
|
|
59724
|
+
questions: Object.fromEntries(names.map((n2) => [n2, toWire(questions[n2])]))
|
|
59725
|
+
}),
|
|
59726
|
+
signal: controller.signal
|
|
59727
|
+
});
|
|
59728
|
+
status = res.status;
|
|
59729
|
+
if (!res.ok)
|
|
59730
|
+
return { ok: false };
|
|
59731
|
+
return { ok: true, body: await res.json() };
|
|
59732
|
+
})();
|
|
59733
|
+
const out = await Promise.race([request, timeout]);
|
|
59734
|
+
if (out instanceof Timeout) {
|
|
59735
|
+
request.catch(() => {});
|
|
59736
|
+
return all2("timeout");
|
|
59737
|
+
}
|
|
59738
|
+
if (!out.ok)
|
|
59739
|
+
return all2("http_error", status);
|
|
59740
|
+
const answers = out.body?.answers;
|
|
59741
|
+
if (!answers || typeof answers !== "object")
|
|
59742
|
+
return all2("invalid_response");
|
|
59743
|
+
return finish(questions, Object.fromEntries(names.map((n2) => [n2, judge(questions[n2], answers[n2], min)])), { sensitive, started });
|
|
60064
59744
|
} catch (err) {
|
|
60065
|
-
if (signal?.aborted)
|
|
60066
|
-
|
|
60067
|
-
|
|
60068
|
-
|
|
60069
|
-
|
|
60070
|
-
this.logger.info(`${tag} timed out after ${elapsed()}`);
|
|
60071
|
-
throw new APITimeoutError(timeout, { cause: err });
|
|
60072
|
-
}
|
|
60073
|
-
this.logger.info(`${tag} connection error after ${elapsed()}`, err);
|
|
60074
|
-
throw new APIConnectionError(err instanceof Error ? `Connection error: ${err.message}` : undefined, { cause: err });
|
|
59745
|
+
if (base.signal?.aborted)
|
|
59746
|
+
return all2("aborted");
|
|
59747
|
+
if (status !== undefined)
|
|
59748
|
+
return all2("invalid_response");
|
|
59749
|
+
return all2(err?.name === "TimeoutError" ? "timeout" : "network_error");
|
|
60075
59750
|
} finally {
|
|
60076
59751
|
clearTimeout(timer);
|
|
60077
|
-
signal?.removeEventListener("abort",
|
|
59752
|
+
base.signal?.removeEventListener("abort", onAbort);
|
|
60078
59753
|
}
|
|
60079
59754
|
}
|
|
60080
|
-
|
|
60081
|
-
|
|
60082
|
-
|
|
60083
|
-
|
|
60084
|
-
|
|
60085
|
-
|
|
60086
|
-
|
|
60087
|
-
} catch (err) {
|
|
60088
|
-
this.logger.info(`${tag} aborted by caller while waiting to retry`);
|
|
60089
|
-
throw new APIUserAbortError(undefined, { cause: err });
|
|
60090
|
-
}
|
|
59755
|
+
function baseOf(args) {
|
|
59756
|
+
return {
|
|
59757
|
+
state: args.state,
|
|
59758
|
+
sensitive: args.sensitive,
|
|
59759
|
+
minConfidence: args.minConfidence,
|
|
59760
|
+
signal: args.signal
|
|
59761
|
+
};
|
|
60091
59762
|
}
|
|
60092
|
-
|
|
60093
|
-
|
|
60094
|
-
|
|
60095
|
-
|
|
60096
|
-
|
|
60097
|
-
|
|
60098
|
-
|
|
60099
|
-
|
|
60100
|
-
|
|
60101
|
-
|
|
59763
|
+
return {
|
|
59764
|
+
enabled: apiKey.length > 0,
|
|
59765
|
+
async choice(args) {
|
|
59766
|
+
const q2 = {
|
|
59767
|
+
type: "choice",
|
|
59768
|
+
question: args.question,
|
|
59769
|
+
options: args.options,
|
|
59770
|
+
fallback: args.fallback
|
|
59771
|
+
};
|
|
59772
|
+
const { result } = await run({ result: q2 }, baseOf(args));
|
|
59773
|
+
return result;
|
|
59774
|
+
},
|
|
59775
|
+
async score(args) {
|
|
59776
|
+
const q2 = {
|
|
59777
|
+
type: "score",
|
|
59778
|
+
question: args.question,
|
|
59779
|
+
levels: args.levels,
|
|
59780
|
+
fallback: args.fallback
|
|
59781
|
+
};
|
|
59782
|
+
const { result } = await run({ result: q2 }, baseOf(args));
|
|
59783
|
+
return result;
|
|
59784
|
+
},
|
|
59785
|
+
async noul(args) {
|
|
59786
|
+
const q2 = { type: "noul", question: args.question, fallback: args.fallback };
|
|
59787
|
+
const { result } = await run({ result: q2 }, baseOf(args));
|
|
59788
|
+
return result;
|
|
59789
|
+
},
|
|
59790
|
+
async batch(args) {
|
|
59791
|
+
return await run(args.questions, baseOf(args));
|
|
60102
59792
|
}
|
|
60103
|
-
|
|
60104
|
-
|
|
60105
|
-
} catch {
|
|
60106
|
-
return text;
|
|
60107
|
-
}
|
|
60108
|
-
};
|
|
59793
|
+
};
|
|
59794
|
+
}
|
|
60109
59795
|
|
|
60110
59796
|
// src/lib/jev-categorize.ts
|
|
60111
59797
|
var JEV_MODEL = "jev-1.13.0";
|
|
@@ -60125,18 +59811,18 @@ function assertJevAllowed(crypto3, env2 = process.env) {
|
|
|
60125
59811
|
throw new Error("JEV_API_KEY is not set — Jev categorization is off.");
|
|
60126
59812
|
return key;
|
|
60127
59813
|
}
|
|
60128
|
-
function
|
|
60129
|
-
|
|
60130
|
-
|
|
60131
|
-
|
|
60132
|
-
|
|
60133
|
-
|
|
60134
|
-
|
|
60135
|
-
|
|
60136
|
-
|
|
60137
|
-
|
|
60138
|
-
|
|
60139
|
-
};
|
|
59814
|
+
function jevAllowSensitive(crypto3, env2) {
|
|
59815
|
+
return crypto3 === undefined || env2.JEV_ALLOW_PRIVATE_MODE === "1";
|
|
59816
|
+
}
|
|
59817
|
+
function makeJev(apiKey, crypto3, env2 = process.env, fetchImpl) {
|
|
59818
|
+
return createJev({
|
|
59819
|
+
apiKey,
|
|
59820
|
+
model: JEV_MODEL,
|
|
59821
|
+
minConfidence: DEFAULT_MIN_CONFIDENCE,
|
|
59822
|
+
timeoutMs: TIMEOUT_MS,
|
|
59823
|
+
allowSensitive: jevAllowSensitive(crypto3, env2),
|
|
59824
|
+
...fetchImpl ? { fetch: fetchImpl } : {}
|
|
59825
|
+
});
|
|
60140
59826
|
}
|
|
60141
59827
|
var UNSURE = "unsure";
|
|
60142
59828
|
function optionsFor(type, index) {
|
|
@@ -60154,26 +59840,33 @@ function groupState(type, sample) {
|
|
|
60154
59840
|
const dir = type === "credit" ? "Money received" : "Money paid out";
|
|
60155
59841
|
return `${dir}. Bank narration: "${sample.slice(0, 80)}"`;
|
|
60156
59842
|
}
|
|
60157
|
-
async function jevCategorize(client, crypto3,
|
|
59843
|
+
async function jevCategorize(client, crypto3, jev, opts = {}) {
|
|
60158
59844
|
assertPrivateModeAllowed(crypto3, opts.env);
|
|
60159
|
-
const min = opts.minConfidence ?? DEFAULT_MIN_CONFIDENCE;
|
|
60160
59845
|
const index = await loadCategoryIndex(client);
|
|
60161
59846
|
const rows = await fetchUncategorized(client, crypto3, opts);
|
|
60162
59847
|
const groups = groupRows(rows);
|
|
60163
|
-
const unparsed = groups.filter((
|
|
60164
|
-
const candidates = groups.filter((
|
|
59848
|
+
const unparsed = groups.filter((g2) => g2.pattern === UNPARSED).length;
|
|
59849
|
+
const candidates = groups.filter((g2) => g2.pattern !== UNPARSED);
|
|
60165
59850
|
let errors3 = 0;
|
|
60166
|
-
const suggestions = await mapLimit(candidates, CONCURRENCY, async (
|
|
60167
|
-
|
|
60168
|
-
|
|
60169
|
-
|
|
60170
|
-
|
|
60171
|
-
|
|
60172
|
-
|
|
60173
|
-
|
|
60174
|
-
|
|
60175
|
-
|
|
59851
|
+
const suggestions = await mapLimit(candidates, CONCURRENCY, async (g2) => {
|
|
59852
|
+
const options = optionsFor(g2.type, index);
|
|
59853
|
+
const sample = g2.rows[0].description;
|
|
59854
|
+
const text = crypto3 ? g2.pattern : sample;
|
|
59855
|
+
const d2 = await jev.choice({
|
|
59856
|
+
question: "Which spending category best fits this bank transaction?",
|
|
59857
|
+
options,
|
|
59858
|
+
fallback: UNSURE,
|
|
59859
|
+
state: groupState(g2.type, text),
|
|
59860
|
+
sensitive: true,
|
|
59861
|
+
minConfidence: opts.minConfidence
|
|
59862
|
+
});
|
|
59863
|
+
if (d2.confident)
|
|
59864
|
+
return { g: g2, choice: d2.value, confidence: d2.confidence, confident: true };
|
|
59865
|
+
if (d2.reason === "low_confidence" && d2.answer !== undefined) {
|
|
59866
|
+
return { g: g2, choice: d2.answer, confidence: d2.confidence ?? 0, confident: false };
|
|
60176
59867
|
}
|
|
59868
|
+
errors3 += 1;
|
|
59869
|
+
return null;
|
|
60177
59870
|
});
|
|
60178
59871
|
const accepted = [];
|
|
60179
59872
|
const review = [];
|
|
@@ -60181,7 +59874,7 @@ async function jevCategorize(client, crypto3, classify, opts = {}) {
|
|
|
60181
59874
|
if (!s2)
|
|
60182
59875
|
continue;
|
|
60183
59876
|
const isTransfer = index.bySlug.get(s2.choice)?.type === "transfer";
|
|
60184
|
-
if (s2.choice !== UNSURE && !isTransfer
|
|
59877
|
+
if (s2.confident && s2.choice !== UNSURE && !isTransfer) {
|
|
60185
59878
|
accepted.push({
|
|
60186
59879
|
pattern: s2.g.pattern,
|
|
60187
59880
|
type: s2.g.type,
|
|
@@ -60230,7 +59923,8 @@ function jevTools(client, crypto3) {
|
|
|
60230
59923
|
}),
|
|
60231
59924
|
handler: async ({ startDate, endDate, minConfidence, dryRun }) => {
|
|
60232
59925
|
const key = assertJevAllowed(crypto3);
|
|
60233
|
-
const
|
|
59926
|
+
const jev = makeJev(key, crypto3);
|
|
59927
|
+
const result = await jevCategorize(client, crypto3, jev, {
|
|
60234
59928
|
startDate,
|
|
60235
59929
|
endDate,
|
|
60236
59930
|
minConfidence,
|
|
@@ -60268,15 +59962,7 @@ function settingsTools(client) {
|
|
|
60268
59962
|
describe: { name: "", ownerLabels: "Owner slug → display name" },
|
|
60269
59963
|
variants: { profile: profile.update, household: household.update }
|
|
60270
59964
|
});
|
|
60271
|
-
return [
|
|
60272
|
-
get.tool,
|
|
60273
|
-
update.tool,
|
|
60274
|
-
get.alias("get_profile", "profile"),
|
|
60275
|
-
get.alias("get_household", "household"),
|
|
60276
|
-
get.alias("get_encryption_status", "encryption"),
|
|
60277
|
-
update.alias("update_profile", "profile"),
|
|
60278
|
-
update.alias("update_household", "household")
|
|
60279
|
-
];
|
|
59965
|
+
return [get.tool, update.tool];
|
|
60280
59966
|
}
|
|
60281
59967
|
|
|
60282
59968
|
// src/tools/statement-import.ts
|
|
@@ -60367,9 +60053,8 @@ async function runStatementImport(deps, args) {
|
|
|
60367
60053
|
throw new Error(`${basename(args.filePath)} parsed to 0 transactions (format ${format}). If it is a statement with real activity, the layout may not be supported.`);
|
|
60368
60054
|
}
|
|
60369
60055
|
const dates = txns.map((t2) => t2.date).sort();
|
|
60370
|
-
const
|
|
60371
|
-
|
|
60372
|
-
await decryptTransactionFields(existing, crypto3.key);
|
|
60056
|
+
const existing0 = await fetchReconciliationContext(client, account.id, dates[0], dates[dates.length - 1]);
|
|
60057
|
+
const existing = crypto3 ? (await decryptTransactionFields(existing0, crypto3.key)).data : existing0;
|
|
60373
60058
|
const present = existing.map((r2) => ({ ...r2, isDuplicate: false, isIgnored: false }));
|
|
60374
60059
|
const result = reconcile(present, { ...statement, transactions: txns });
|
|
60375
60060
|
const fresh = result.unmatched;
|
|
@@ -60562,15 +60247,7 @@ function statementImportTools(client, crypto3) {
|
|
|
60562
60247
|
})
|
|
60563
60248
|
}
|
|
60564
60249
|
});
|
|
60565
|
-
return [
|
|
60566
|
-
preview.tool,
|
|
60567
|
-
commit.tool,
|
|
60568
|
-
aliasTool("import_statement_pdf", pdfInput.extend({ confirm: exports_external.boolean().optional() }), "preview_import / import_statement", 'from: "pdf" (confirm:true → import_statement, else preview_import)', ({ confirm, ...args }) => confirm ? [commit.tool, { ...args, from: "pdf" }] : [preview.tool, { ...args, from: "pdf" }]),
|
|
60569
|
-
preview.alias("import_csv_parse", "csv"),
|
|
60570
|
-
commit.alias("import_csv_confirm", "csv"),
|
|
60571
|
-
commit.alias("import_statement_batch", "rows"),
|
|
60572
|
-
commit.alias("import_statement_file", "json_file")
|
|
60573
|
-
];
|
|
60250
|
+
return [preview.tool, commit.tool];
|
|
60574
60251
|
}
|
|
60575
60252
|
|
|
60576
60253
|
// src/registrations.ts
|
|
@@ -60715,7 +60392,7 @@ function registerResources(server, tools) {
|
|
|
60715
60392
|
// package.json
|
|
60716
60393
|
var package_default = {
|
|
60717
60394
|
name: "paisa-mcp",
|
|
60718
|
-
version: "0.
|
|
60395
|
+
version: "0.3.1",
|
|
60719
60396
|
repository: {
|
|
60720
60397
|
type: "git",
|
|
60721
60398
|
url: "git+https://github.com/nimit9/paisa.git",
|
|
@@ -60742,13 +60419,14 @@ var package_default = {
|
|
|
60742
60419
|
devDependencies: {
|
|
60743
60420
|
"@modelcontextprotocol/client": "^2.1.0",
|
|
60744
60421
|
"@modelcontextprotocol/server": "^2.1.0",
|
|
60422
|
+
"@nimit9/signet-ai": "^0.1.11",
|
|
60423
|
+
"@nimit9/signet-lib": "^0.1.15",
|
|
60745
60424
|
"@nimit9/signet-server": "^0.2.2",
|
|
60746
60425
|
"@paisa/parsers": "workspace:*",
|
|
60747
60426
|
"@paisa/reconciliation": "workspace:*",
|
|
60748
60427
|
"@paisa/types": "workspace:*",
|
|
60749
60428
|
"@scure/bip39": "^2.2.0",
|
|
60750
60429
|
"@types/bun": "^1.3.14",
|
|
60751
|
-
"@typesafe-ai/sdk": "^0.6.0",
|
|
60752
60430
|
axios: "^1.16.1",
|
|
60753
60431
|
"hash-wasm": "^4.12.0",
|
|
60754
60432
|
typescript: "^7.0.2",
|
|
@@ -60760,7 +60438,7 @@ var package_default = {
|
|
|
60760
60438
|
};
|
|
60761
60439
|
|
|
60762
60440
|
// src/version.ts
|
|
60763
|
-
var
|
|
60441
|
+
var VERSION2 = package_default.version;
|
|
60764
60442
|
|
|
60765
60443
|
// src/server.ts
|
|
60766
60444
|
function paisaErrorResult(err) {
|
|
@@ -60772,31 +60450,18 @@ function paisaErrorResult(err) {
|
|
|
60772
60450
|
function buildServer(client, crypto3) {
|
|
60773
60451
|
const tools = applyAnnotations(REGISTRATIONS.flatMap((group) => group.tools(client, crypto3)));
|
|
60774
60452
|
for (const t2 of tools)
|
|
60775
|
-
if (t2.input
|
|
60453
|
+
if (t2.input)
|
|
60776
60454
|
withCompactJsonSchema(t2.input);
|
|
60777
60455
|
const server = createMcpServer({
|
|
60778
60456
|
name: "paisa",
|
|
60779
|
-
version:
|
|
60457
|
+
version: VERSION2,
|
|
60780
60458
|
tools,
|
|
60781
60459
|
errorResult: paisaErrorResult
|
|
60782
60460
|
});
|
|
60783
|
-
hideFromToolsList(server, new Set(tools.filter(isAlias).map((t2) => t2.name)));
|
|
60784
60461
|
registerResources(server, tools);
|
|
60785
60462
|
registerPrompts(server);
|
|
60786
60463
|
return server;
|
|
60787
60464
|
}
|
|
60788
|
-
function hideFromToolsList(server, hidden) {
|
|
60789
|
-
if (hidden.size === 0)
|
|
60790
|
-
return;
|
|
60791
|
-
const inner = server.server;
|
|
60792
|
-
const list = inner._getRequestHandler("tools/list");
|
|
60793
|
-
if (!list)
|
|
60794
|
-
throw new Error("MCP SDK: no tools/list handler to wrap (aliases would be listed)");
|
|
60795
|
-
server.server.setRequestHandler("tools/list", async (request, ctx) => {
|
|
60796
|
-
const result = await list(request, ctx);
|
|
60797
|
-
return { ...result, tools: result.tools.filter((t2) => !hidden.has(t2.name)) };
|
|
60798
|
-
});
|
|
60799
|
-
}
|
|
60800
60465
|
|
|
60801
60466
|
// src/index.ts
|
|
60802
60467
|
async function main() {
|
|
@@ -60819,5 +60484,5 @@ main().catch((err) => {
|
|
|
60819
60484
|
process.exit(1);
|
|
60820
60485
|
});
|
|
60821
60486
|
|
|
60822
|
-
//# debugId=
|
|
60487
|
+
//# debugId=E169545C1C52BE7864756E2164756E21
|
|
60823
60488
|
//# sourceMappingURL=index.js.map
|