[{"data":1,"prerenderedAt":946},["ShallowReactive",2],{"navigation_docs_en":3,"-en-premium-ai-chat":191,"-en-premium-ai-chat-surround":943},[4,61,127,171],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":60},"Guide","i-lucide-book-open","\u002Fen\u002Fguide","en\u002F1.guide",[10,15,20,25,30,35,40,45,50,55],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fen\u002Fguide\u002Fintroduction","en\u002F1.guide\u002F01.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Install the App","\u002Fen\u002Fguide\u002Finstallation","en\u002F1.guide\u002F02.installation","i-lucide-smartphone",{"title":21,"path":22,"stem":23,"icon":24},"Authentication","\u002Fen\u002Fguide\u002Fauth","en\u002F1.guide\u002F03.auth","i-lucide-lock",{"title":26,"path":27,"stem":28,"icon":29},"Wallets","\u002Fen\u002Fguide\u002Fwallets","en\u002F1.guide\u002F04.wallets","i-lucide-wallet",{"title":31,"path":32,"stem":33,"icon":34},"Categories","\u002Fen\u002Fguide\u002Fcategories","en\u002F1.guide\u002F05.categories","i-lucide-tags",{"title":36,"path":37,"stem":38,"icon":39},"Transactions","\u002Fen\u002Fguide\u002Ftransactions","en\u002F1.guide\u002F06.transactions","i-lucide-receipt",{"title":41,"path":42,"stem":43,"icon":44},"Transfers","\u002Fen\u002Fguide\u002Ftransfers","en\u002F1.guide\u002F07.transfers","i-lucide-arrow-left-right",{"title":46,"path":47,"stem":48,"icon":49},"Statistics","\u002Fen\u002Fguide\u002Fstatistics","en\u002F1.guide\u002F08.statistics","i-lucide-bar-chart-3",{"title":51,"path":52,"stem":53,"icon":54},"Theme","\u002Fen\u002Fguide\u002Ftheme","en\u002F1.guide\u002F09.theme","i-lucide-palette",{"title":56,"path":57,"stem":58,"icon":59},"Settings","\u002Fen\u002Fguide\u002Fsettings","en\u002F1.guide\u002F10.settings","i-lucide-settings",false,{"title":62,"icon":63,"path":64,"stem":65,"children":66,"page":60},"Development","i-lucide-code","\u002Fen\u002Fdevelopment","en\u002F2.development",[67,72,77,82,87,92,97,102,122],{"title":68,"path":69,"stem":70,"icon":71},"Installation","\u002Fen\u002Fdevelopment\u002Finstallation","en\u002F2.development\u002F01.installation","i-lucide-download",{"title":73,"path":74,"stem":75,"icon":76},"Codebase Graph","\u002Fen\u002Fdevelopment\u002Funderstand-anything","en\u002F2.development\u002F02.understand-anything","i-lucide-network",{"title":78,"path":79,"stem":80,"icon":81},"Offline & PWA","\u002Fen\u002Fdevelopment\u002Foffline","en\u002F2.development\u002F03.offline","i-lucide-wifi-off",{"title":83,"path":84,"stem":85,"icon":86},"Data Migration History","\u002Fen\u002Fdevelopment\u002Fmigration","en\u002F2.development\u002F04.migration","i-lucide-database",{"title":88,"path":89,"stem":90,"icon":91},"Deployment","\u002Fen\u002Fdevelopment\u002Fdeployment","en\u002F2.development\u002F05.deployment","i-lucide-rocket",{"title":93,"path":94,"stem":95,"icon":96},"Testing","\u002Fen\u002Fdevelopment\u002Ftesting","en\u002F2.development\u002F06.testing","i-lucide-flask-conical",{"title":98,"path":99,"stem":100,"icon":101},"Date Utilities","\u002Fen\u002Fdevelopment\u002Fdate-utilities","en\u002F2.development\u002F07.date-utilities","i-lucide-calendar",{"title":103,"path":104,"stem":105,"children":106,"page":60},"Ai Workflow","\u002Fen\u002Fdevelopment\u002Fai-workflow","en\u002F2.development\u002F08.ai-workflow",[107,112,117],{"title":108,"path":109,"stem":110,"icon":111},"Overview","\u002Fen\u002Fdevelopment\u002Fai-workflow\u002Foverview","en\u002F2.development\u002F08.ai-workflow\u002F01.overview","i-lucide-bot",{"title":113,"path":114,"stem":115,"icon":116},"Agents","\u002Fen\u002Fdevelopment\u002Fai-workflow\u002Fagents","en\u002F2.development\u002F08.ai-workflow\u002F02.agents","i-lucide-users",{"title":118,"path":119,"stem":120,"icon":121},"Skills","\u002Fen\u002Fdevelopment\u002Fai-workflow\u002Fskills","en\u002F2.development\u002F08.ai-workflow\u002F03.skills","i-lucide-lightbulb",{"title":123,"path":124,"stem":125,"icon":126},"Troubleshooting","\u002Fen\u002Fdevelopment\u002Ftroubleshooting","en\u002F2.development\u002F09.troubleshooting","i-lucide-life-buoy",{"title":128,"icon":129,"path":130,"stem":131,"children":132,"page":60},"Reference","i-lucide-file-code","\u002Fen\u002Freference","en\u002F3.reference",[133,138,142,147,152,156,161,166],{"title":134,"path":135,"stem":136,"icon":137},"Architecture","\u002Fen\u002Freference\u002Farchitecture","en\u002F3.reference\u002F01.architecture","i-lucide-boxes",{"title":139,"path":140,"stem":141,"icon":44},"Transaction Types","\u002Fen\u002Freference\u002Ftransaction-types","en\u002F3.reference\u002F02.transaction-types",{"title":143,"path":144,"stem":145,"icon":146},"Sync","\u002Fen\u002Freference\u002Fsync","en\u002F3.reference\u002F03.sync","i-lucide-refresh-cw",{"title":148,"path":149,"stem":150,"icon":151},"Offline-first","\u002Fen\u002Freference\u002Foffline-first","en\u002F3.reference\u002F04.offline-first","i-lucide-list-ordered",{"title":153,"path":154,"stem":155,"icon":121},"Technical Decisions","\u002Fen\u002Freference\u002Ftech-decisions","en\u002F3.reference\u002F05.tech-decisions",{"title":157,"path":158,"stem":159,"icon":160},"Validation Strategy","\u002Fen\u002Freference\u002Fvalidation-strategy","en\u002F3.reference\u002F06.validation-strategy","i-lucide-shield-check",{"title":162,"path":163,"stem":164,"icon":165},"What Changed Since Firebase","\u002Fen\u002Freference\u002Ffirebase-migration","en\u002F3.reference\u002F07.firebase-migration","i-lucide-hamburger",{"title":167,"path":168,"stem":169,"icon":170},"Performance","\u002Fen\u002Freference\u002Fperformance","en\u002F3.reference\u002F08.performance","i-lucide-gauge",{"title":172,"icon":173,"path":174,"stem":175,"children":176,"page":60},"Premium","i-lucide-star","\u002Fen\u002Fpremium","en\u002F4.premium",[177,181,186],{"title":108,"path":178,"stem":179,"icon":180},"\u002Fen\u002Fpremium\u002Foverview","en\u002F4.premium\u002F01.overview","i-lucide-layers",{"title":182,"path":183,"stem":184,"icon":185},"Telegram Bot","\u002Fen\u002Fpremium\u002Ftelegram-bot","en\u002F4.premium\u002F02.telegram-bot","i-lucide-send",{"title":187,"path":188,"stem":189,"icon":190},"AI Chat","\u002Fen\u002Fpremium\u002Fai-chat","en\u002F4.premium\u002F03.ai-chat","i-lucide-sparkles",{"id":192,"title":187,"body":193,"description":935,"extension":936,"links":937,"meta":938,"navigation":939,"path":188,"seo":940,"stem":189,"__hash__":942},"docs_en\u002Fen\u002F4.premium\u002F03.ai-chat.md",{"type":194,"value":195,"toc":913},"minimark",[196,200,223,227,265,268,278,282,293,297,362,365,401,404,420,424,444,447,466,470,477,528,532,538,556,559,563,569,597,601,611,615,683,690,694,701,727,730,734,854,858],[197,198,108],"h2",{"id":199},"overview",[201,202,203,204,211,212,217,218,222],"p",{},"Finapp ships a local AI assistant powered by ",[205,206,210],"a",{"href":207,"rel":208},"https:\u002F\u002Follama.com",[209],"nofollow","Ollama"," and ",[205,213,216],{"href":214,"rel":215},"https:\u002F\u002Ftanstack.com\u002Fai",[209],"@tanstack\u002Fai",". The chat lives in a slide-over panel (",[219,220,221],"code",{},"AiChatPanel.vue",") and exposes ~24 tools that wrap Pinia store mutations and queries. No data leaves the user's machine.",[197,224,226],{"id":225},"entry-points","Entry points",[228,229,230,242,256],"ul",{},[231,232,233,237,238,241],"li",{},[234,235,236],"strong",{},"FAB button"," (",[219,239,240],{},"AiFab.vue",") - floating action button on all authenticated pages",[231,243,244,247,248,251,252,255],{},[234,245,246],{},"Keyboard shortcut"," ",[219,249,250],{},"Cmd\u002FCtrl+I"," (see ",[219,253,254],{},"shortcuts.ts",")",[231,257,258,261,262],{},[234,259,260],{},"Slide-over panel"," - right side, ",[219,263,264],{},"sm:max-w-md",[197,266,134],{"id":267},"architecture",[269,270,275],"pre",{"className":271,"code":273,"language":274},[272],"language-text","User input → AiChatPanel\n  ├── useAiChat.send(text)\n  │   ├── pruneContext(messages) - sliding window + tool result compression\n  │   ├── chat() via @tanstack\u002Fai with Ollama adapter\n  │   ├── streams TOOL_CALL_START \u002F TOOL_CALL_ARGS \u002F TOOL_CALL_END \u002F TEXT_MESSAGE_CONTENT\n  │   ├── autoRetry - detects failed mutations + incomplete chains\n  │   ├── client-side fallback - directly executes mutations if model stalls\n  │   ├── toast notifications - visual feedback for mutations\n  │   └── lastAction tracker - enables undo\n  ├── AiToolCallsList.vue - renders rich cards per tool\n  └── AiMessageContent.vue - markdown assistant text\n","text",[219,276,273],{"__ignoreMap":277},"",[197,279,281],{"id":280},"tool-catalog","Tool catalog",[201,283,284,285,288,289,292],{},"All tools live in ",[219,286,287],{},"app\u002Fcomponents\u002Fai\u002Ftools\u002F"," and are registered via ",[219,290,291],{},"createAllTools()",".",[294,295,36],"h3",{"id":296},"transactions",[228,298,299,305,311,317,323,329,335,344,350,356],{},[231,300,301,304],{},[219,302,303],{},"create_trn"," - new expense or income",[231,306,307,310],{},[219,308,309],{},"create_adjustment"," - set wallet balance to target value (delta is computed)",[231,312,313,316],{},[219,314,315],{},"create_transfer"," - transfer between wallets (supports currency exchange)",[231,318,319,322],{},[219,320,321],{},"update_trn"," - patch fields on existing transaction by id",[231,324,325,328],{},[219,326,327],{},"delete_trn"," - delete by id",[231,330,331,334],{},[219,332,333],{},"duplicate_trn"," - clone a transaction with current date",[231,336,337,340,341,255],{},[219,338,339],{},"bulk_delete_trns"," - delete many by filter (safety cap via ",[219,342,343],{},"maxDelete",[231,345,346,349],{},[219,347,348],{},"list_trns"," - filter + aggregate",[231,351,352,355],{},[219,353,354],{},"search_trns"," - full-text search in descriptions",[231,357,358,361],{},[219,359,360],{},"undo_last_action"," - reverse last AI mutation",[294,363,26],{"id":364},"wallets",[228,366,367,382,391,396],{},[231,368,369,372,373,372,376,372,379],{},[219,370,371],{},"create_wallet",", ",[219,374,375],{},"update_wallet",[219,377,378],{},"delete_wallet",[219,380,381],{},"list_wallets",[231,383,384,387,388],{},[219,385,386],{},"archive_wallet"," \u002F ",[219,389,390],{},"unarchive_wallet",[231,392,393],{},[219,394,395],{},"set_wallet_exclude_in_total",[231,397,398],{},[219,399,400],{},"reorder_wallets",[294,402,31],{"id":403},"categories",[228,405,406],{},[231,407,408,372,411,372,414,372,417],{},[219,409,410],{},"create_category",[219,412,413],{},"update_category",[219,415,416],{},"delete_category",[219,418,419],{},"list_categories",[294,421,423],{"id":422},"analytics","Analytics",[228,425,426,432,438],{},[231,427,428,431],{},[219,429,430],{},"get_summary"," - totals, income\u002Fexpense, top N categories",[231,433,434,437],{},[219,435,436],{},"get_wallet_stats"," - single-wallet income\u002Fexpense\u002Fnet",[231,439,440,443],{},[219,441,442],{},"compare_periods"," - current vs previous period, delta and %",[294,445,56],{"id":446},"settings",[228,448,449,460],{},[231,450,451,372,454,372,457],{},[219,452,453],{},"set_base_currency",[219,455,456],{},"set_locale",[219,458,459],{},"get_settings",[231,461,462,465],{},[219,463,464],{},"set_theme"," - primary\u002Fneutral color, border radius, black-as-primary",[197,467,469],{"id":468},"system-prompt","System prompt",[201,471,472,473,476],{},"Built in ",[219,474,475],{},"useSystemPrompt.ts",". Key rules:",[228,478,479,485,491,506,512,518],{},[231,480,481,484],{},[234,482,483],{},"Tool-first:"," every factual question about wallets\u002Fcategories\u002Ftransactions MUST call a tool, not answer from memory",[231,486,487,490],{},[234,488,489],{},"Multi-turn:"," if required fields are missing (e.g. user said \"купил кофе\" without amount), ask ONE specific follow-up; merge on next turn",[231,492,493,247,496,387,498,387,500,502,503,505],{},[234,494,495],{},"Chain pattern:",[219,497,327],{},[219,499,321],{},[219,501,333],{}," require ",[219,504,348],{}," first to get a real id",[231,507,508,511],{},[234,509,510],{},"FORBIDDEN:"," inventing ids, asking user for ids, reusing past tool results",[231,513,514,517],{},[234,515,516],{},"Mutations:"," rules 12a-12i cover transfer, adjustment, settings, wallet management, ordering, undo",[231,519,520,523,524,527],{},[234,521,522],{},"DATE RULE:"," omit ",[219,525,526],{},"date"," unless user explicitly said one - tools default to now",[197,529,531],{"id":530},"context-pruning","Context pruning",[201,533,534,537],{},[219,535,536],{},"pruneContext.ts"," implements a sliding window + tool result compression:",[228,539,540,546],{},[231,541,542,545],{},[219,543,544],{},"maxContextTurns"," (default 6) - only the last N user+assistant pairs go to the model",[231,547,548,551,552,555],{},[219,549,550],{},"compressToolsAfterTurns"," (default 1) - older assistant messages keep tool_calls compressed to ",[219,553,554],{},"[tool_name: summary]"," strings",[201,557,558],{},"This prevents model \"I already did X\" hallucinations that appear in long sessions.",[197,560,562],{"id":561},"auto-retry-client-fallback","Auto-retry + client fallback",[201,564,565,568],{},[219,566,567],{},"useAiChat.ts"," implements two layers of robustness:",[570,571,572,584],"ol",{},[231,573,574,577,578,581,582],{},[234,575,576],{},"autoRetry"," - if tool call failed (validation error or ",[219,579,580],{},"ok: false","), send a retry hint with the real id from ",[219,583,348],{},[231,585,586,589,590,387,592,387,594,596],{},[234,587,588],{},"executeFallback"," - if model still stalls after retry on ",[219,591,333],{},[219,593,327],{},[219,595,360],{},", the client directly executes the mutation and injects the result as a synthetic tool_call. This bypasses model reliability issues.",[197,598,600],{"id":599},"idle-clear","Idle clear",[201,602,603,606,607,610],{},[219,604,605],{},"idleMinutesBeforeClear"," (default 30) - if the chat was idle for N minutes since last message, history is silently cleared on next ",[219,608,609],{},"send()",". Prevents context pollution across sessions.",[197,612,614],{"id":613},"model-recommendations","Model recommendations",[616,617,618,637],"table",{},[619,620,621],"thead",{},[622,623,624,628,631,634],"tr",{},[625,626,627],"th",{},"Model",[625,629,630],{},"Speed",[625,632,633],{},"Tools",[625,635,636],{},"Notes",[638,639,640,657,671],"tbody",{},[622,641,642,648,651,654],{},[643,644,645],"td",{},[234,646,647],{},"gemma4:latest",[643,649,650],{},"fast",[643,652,653],{},"excellent",[643,655,656],{},"Default. Best speed\u002Faccuracy balance",[622,658,659,662,665,668],{},[643,660,661],{},"gemma4:26b",[643,663,664],{},"medium",[643,666,667],{},"good",[643,669,670],{},"Use if RAM-rich and want higher accuracy",[622,672,673,676,678,680],{},[643,674,675],{},"qwen3:8b",[643,677,650],{},[643,679,653],{},[643,681,682],{},"Alternative with similar characteristics",[201,684,685,686,689],{},"See ",[219,687,688],{},"modelMeta.ts",". Other Ollama models can be used but are not validated.",[197,691,693],{"id":692},"customization","Customization",[201,695,696,697,700],{},"All tunable settings live in ",[219,698,699],{},"aiStore.settings",":",[228,702,703,719],{},[231,704,705,372,708,372,711,372,714,372,716],{},[219,706,707],{},"model",[219,709,710],{},"baseUrl",[219,712,713],{},"think",[219,715,576],{},[219,717,718],{},"debug",[231,720,721,372,723,372,725],{},[219,722,544],{},[219,724,550],{},[219,726,605],{},[201,728,729],{},"Accessible via the settings popover in the chat header.",[197,731,733],{"id":732},"known-limitations","Known limitations",[228,735,736,766,791,804,813,840],{},[231,737,738,744,745,747,748,750,751,754,755,758,759,762,763,765],{},[234,739,740,741,743],{},"Multi-turn ",[219,742,303],{}," is model-dependent."," On ",[219,746,647],{}," end-to-end follow-up collection (e.g. user says \"купил кофе\", assistant asks for amount\u002Fwallet, assistant calls ",[219,749,303],{}," after answers) succeeds in roughly 70% of attempts. The model sometimes mis-maps the answer to the wrong parameter (e.g. puts \"наличными\" into ",[219,752,753],{},"description"," instead of ",[219,756,757],{},"wallet",") or omits ",[219,760,761],{},"type",". For reliable multi-turn, prefer ",[219,764,675],{}," or provide all fields in one message.",[231,767,768,781,782,784,785,787,788,790],{},[234,769,770,771,372,773,372,775,777,778,780],{},"Chain tools (",[219,772,333],{},[219,774,327],{},[219,776,321],{},") can stall on ",[219,779,647],{}," in long sessions"," - the model sometimes replies in text asking for an id instead of chaining ",[219,783,348],{}," → mutation. This is mitigated by client-side fallback (",[219,786,588],{}," in ",[219,789,567],{},") which directly executes the mutation and injects the result as a synthetic tool_call.",[231,792,793,796,797,799,800,803],{},[234,794,795],{},"\"I already did that\" hallucinations"," can still appear if ",[219,798,544],{}," is set too high. The default ",[219,801,802],{},"compressToolsAfterTurns: 1"," compresses old tool results to prevent this, but raising the window beyond 8-10 turns brings the risk back.",[231,805,806,809,810,812],{},[234,807,808],{},"Local network dependency."," If Ollama is not running at ",[219,811,710],{},", the chat is unusable. There is no remote fallback by design - all inference stays local.",[231,814,815,820,821,824,825,828,829,832,833,835,836,839],{},[234,816,817,818],{},"Validation errors from ",[219,819,216],{}," are reported as ",[219,822,823],{},"state: 'done'"," (not ",[219,826,827],{},"error",") with ",[219,830,831],{},"{ error: \"...\" }"," in the result. ",[219,834,576],{}," handles this via the ",[219,837,838],{},"isTcFailed"," helper that inspects the result JSON.",[231,841,842,845,846,849,850,853],{},[234,843,844],{},"No bulk reorder of categories"," - ",[219,847,848],{},"useCategoriesStore"," does not expose a ",[219,851,852],{},"saveCategoriesOrder"," helper, so the AI cannot reorder categories.",[197,855,857],{"id":856},"adding-a-new-tool","Adding a new tool",[570,859,860,871,880,887,893,900,906],{},[231,861,862,863,866,867,870],{},"Create ",[219,864,865],{},"app\u002Fcomponents\u002Fai\u002Ftools\u002F\u003Cname>.ts"," exporting a ",[219,868,869],{},"create*Tools()"," function",[231,872,873,874,877,878],{},"Use ",[219,875,876],{},"toolDefinition({ description, inputSchema, name })"," from ",[219,879,216],{},[231,881,882,883,886],{},"Return the full result shape you want to render (include ",[219,884,885],{},"ok: true"," on success)",[231,888,889,890],{},"Register in ",[219,891,892],{},"tools\u002Findex.ts",[231,894,895,896,899],{},"Add a rich card in ",[219,897,898],{},"AiToolCallsList.richKind()"," if needed",[231,901,902,903,905],{},"Update ",[219,904,475],{}," with a rule describing when to use the tool",[231,907,908,909,912],{},"Add a bench case in ",[219,910,911],{},"\u002Ftmp\u002Fai-bench.mjs"," for regression testing",{"title":277,"searchDepth":914,"depth":914,"links":915},2,[916,917,918,919,927,928,929,930,931,932,933,934],{"id":199,"depth":914,"text":108},{"id":225,"depth":914,"text":226},{"id":267,"depth":914,"text":134},{"id":280,"depth":914,"text":281,"children":920},[921,923,924,925,926],{"id":296,"depth":922,"text":36},3,{"id":364,"depth":922,"text":26},{"id":403,"depth":922,"text":31},{"id":422,"depth":922,"text":423},{"id":446,"depth":922,"text":56},{"id":468,"depth":914,"text":469},{"id":530,"depth":914,"text":531},{"id":561,"depth":914,"text":562},{"id":599,"depth":914,"text":600},{"id":613,"depth":914,"text":614},{"id":692,"depth":914,"text":693},{"id":732,"depth":914,"text":733},{"id":856,"depth":914,"text":857},"Local LLM assistant for transactions, wallets, categories, and analytics.","md",null,{},{"icon":190},{"title":187,"description":941},"Finapp AI chat architecture, tools, prompts, model recommendations.","UG8W4GxZFDnLdsOXhfRmh6_Hgs9f9pFv1TGbNiI93xs",[944,937],{"title":182,"path":183,"stem":184,"description":945,"icon":185,"children":-1},"Add transactions directly from Telegram with text or receipt photos.",1782114345487]