plasalid 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +213 -0
- package/README.md +176 -0
- package/dist/accounts/taxonomy.d.ts +31 -0
- package/dist/accounts/taxonomy.js +189 -0
- package/dist/ai/agent.d.ts +43 -0
- package/dist/ai/agent.js +155 -0
- package/dist/ai/context.d.ts +4 -0
- package/dist/ai/context.js +33 -0
- package/dist/ai/memory.d.ts +14 -0
- package/dist/ai/memory.js +12 -0
- package/dist/ai/provider.d.ts +67 -0
- package/dist/ai/provider.js +5 -0
- package/dist/ai/providers/anthropic.d.ts +5 -0
- package/dist/ai/providers/anthropic.js +49 -0
- package/dist/ai/providers/index.d.ts +2 -0
- package/dist/ai/providers/index.js +12 -0
- package/dist/ai/providers/openai-compat.d.ts +5 -0
- package/dist/ai/providers/openai-compat.js +147 -0
- package/dist/ai/providers/openai.d.ts +5 -0
- package/dist/ai/providers/openai.js +147 -0
- package/dist/ai/redactor.d.ts +2 -0
- package/dist/ai/redactor.js +91 -0
- package/dist/ai/sanitize.d.ts +14 -0
- package/dist/ai/sanitize.js +25 -0
- package/dist/ai/system-prompt.d.ts +13 -0
- package/dist/ai/system-prompt.js +174 -0
- package/dist/ai/thai-taxonomy-hint.d.ts +8 -0
- package/dist/ai/thai-taxonomy-hint.js +22 -0
- package/dist/ai/thinking-phrases.d.ts +7 -0
- package/dist/ai/thinking-phrases.js +15 -0
- package/dist/ai/thinking.d.ts +7 -0
- package/dist/ai/thinking.js +15 -0
- package/dist/ai/tools/common.d.ts +2 -0
- package/dist/ai/tools/common.js +83 -0
- package/dist/ai/tools/index.d.ts +8 -0
- package/dist/ai/tools/index.js +34 -0
- package/dist/ai/tools/ingest.d.ts +2 -0
- package/dist/ai/tools/ingest.js +202 -0
- package/dist/ai/tools/read.d.ts +2 -0
- package/dist/ai/tools/read.js +123 -0
- package/dist/ai/tools/reconcile.d.ts +2 -0
- package/dist/ai/tools/reconcile.js +227 -0
- package/dist/ai/tools/scan.d.ts +2 -0
- package/dist/ai/tools/scan.js +24 -0
- package/dist/ai/tools/types.d.ts +26 -0
- package/dist/ai/tools/types.js +1 -0
- package/dist/ai/tools.d.ts +18 -0
- package/dist/ai/tools.js +402 -0
- package/dist/cli/chat.d.ts +1 -0
- package/dist/cli/chat.js +28 -0
- package/dist/cli/commands/accounts.d.ts +1 -0
- package/dist/cli/commands/accounts.js +86 -0
- package/dist/cli/commands/data.d.ts +1 -0
- package/dist/cli/commands/data.js +28 -0
- package/dist/cli/commands/reconcile.d.ts +2 -0
- package/dist/cli/commands/reconcile.js +15 -0
- package/dist/cli/commands/revert.d.ts +1 -0
- package/dist/cli/commands/revert.js +68 -0
- package/dist/cli/commands/scan.d.ts +4 -0
- package/dist/cli/commands/scan.js +45 -0
- package/dist/cli/commands/status.d.ts +1 -0
- package/dist/cli/commands/status.js +22 -0
- package/dist/cli/commands/transactions.d.ts +8 -0
- package/dist/cli/commands/transactions.js +92 -0
- package/dist/cli/commands/undo.d.ts +1 -0
- package/dist/cli/commands/undo.js +38 -0
- package/dist/cli/commands.d.ts +14 -0
- package/dist/cli/commands.js +196 -0
- package/dist/cli/format.d.ts +8 -0
- package/dist/cli/format.js +109 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +126 -0
- package/dist/cli/ink/ChatApp.d.ts +8 -0
- package/dist/cli/ink/ChatApp.js +94 -0
- package/dist/cli/ink/PromptFrame.d.ts +10 -0
- package/dist/cli/ink/PromptFrame.js +11 -0
- package/dist/cli/ink/TextInput.d.ts +13 -0
- package/dist/cli/ink/TextInput.js +24 -0
- package/dist/cli/ink/hooks/useAgent.d.ts +27 -0
- package/dist/cli/ink/hooks/useAgent.js +65 -0
- package/dist/cli/ink/hooks/useCtrlCExit.d.ts +16 -0
- package/dist/cli/ink/hooks/useCtrlCExit.js +43 -0
- package/dist/cli/ink/hooks/useFooterText.d.ts +2 -0
- package/dist/cli/ink/hooks/useFooterText.js +43 -0
- package/dist/cli/ink/hooks/useTextInput.d.ts +32 -0
- package/dist/cli/ink/hooks/useTextInput.js +356 -0
- package/dist/cli/ink/messages/AssistantMessage.d.ts +3 -0
- package/dist/cli/ink/messages/AssistantMessage.js +6 -0
- package/dist/cli/ink/messages/ErrorMessage.d.ts +4 -0
- package/dist/cli/ink/messages/ErrorMessage.js +6 -0
- package/dist/cli/ink/messages/InterruptedMessage.d.ts +1 -0
- package/dist/cli/ink/messages/InterruptedMessage.js +6 -0
- package/dist/cli/ink/messages/ThinkingLine.d.ts +12 -0
- package/dist/cli/ink/messages/ThinkingLine.js +23 -0
- package/dist/cli/ink/messages/UserMessage.d.ts +4 -0
- package/dist/cli/ink/messages/UserMessage.js +15 -0
- package/dist/cli/ink/mount.d.ts +6 -0
- package/dist/cli/ink/mount.js +12 -0
- package/dist/cli/logo.d.ts +1 -0
- package/dist/cli/logo.js +20 -0
- package/dist/cli/setup.d.ts +2 -0
- package/dist/cli/setup.js +210 -0
- package/dist/cli/ux.d.ts +38 -0
- package/dist/cli/ux.js +104 -0
- package/dist/config.d.ts +21 -0
- package/dist/config.js +66 -0
- package/dist/currency.d.ts +6 -0
- package/dist/currency.js +19 -0
- package/dist/db/connection.d.ts +5 -0
- package/dist/db/connection.js +45 -0
- package/dist/db/encryption.d.ts +11 -0
- package/dist/db/encryption.js +45 -0
- package/dist/db/helpers.d.ts +16 -0
- package/dist/db/helpers.js +45 -0
- package/dist/db/queries/account_balance.d.ts +61 -0
- package/dist/db/queries/account_balance.js +146 -0
- package/dist/db/queries/journal.d.ts +95 -0
- package/dist/db/queries/journal.js +204 -0
- package/dist/db/queries/search.d.ts +7 -0
- package/dist/db/queries/search.js +19 -0
- package/dist/db/schema.d.ts +2 -0
- package/dist/db/schema.js +95 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/parser/pdf.d.ts +14 -0
- package/dist/parser/pdf.js +40 -0
- package/dist/parser/pipeline.d.ts +44 -0
- package/dist/parser/pipeline.js +160 -0
- package/dist/parser/prompts.d.ts +8 -0
- package/dist/parser/prompts.js +20 -0
- package/dist/parser/walker.d.ts +8 -0
- package/dist/parser/walker.js +42 -0
- package/dist/reconciler/pipeline.d.ts +17 -0
- package/dist/reconciler/pipeline.js +45 -0
- package/dist/reconciler/prompts.d.ts +12 -0
- package/dist/reconciler/prompts.js +22 -0
- package/dist/scanner/password-store.d.ts +34 -0
- package/dist/scanner/password-store.js +83 -0
- package/dist/scanner/pdf-unlock.d.ts +17 -0
- package/dist/scanner/pdf-unlock.js +48 -0
- package/dist/scanner/pdf.d.ts +17 -0
- package/dist/scanner/pdf.js +36 -0
- package/dist/scanner/pipeline.d.ts +32 -0
- package/dist/scanner/pipeline.js +137 -0
- package/dist/scanner/prompts.d.ts +8 -0
- package/dist/scanner/prompts.js +20 -0
- package/dist/scanner/state-machine.d.ts +60 -0
- package/dist/scanner/state-machine.js +64 -0
- package/dist/scanner/unlock.d.ts +24 -0
- package/dist/scanner/unlock.js +122 -0
- package/dist/scanner/walker.d.ts +8 -0
- package/dist/scanner/walker.js +42 -0
- package/package.json +65 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"Commons Clause" License Condition v1.0
|
|
2
|
+
|
|
3
|
+
The Software is provided to you by the Licensor under the License, as defined
|
|
4
|
+
below, subject to the following condition.
|
|
5
|
+
|
|
6
|
+
Without limiting other conditions in the License, the grant of rights under
|
|
7
|
+
the License will not include, and the License does not grant to you, the right
|
|
8
|
+
to Sell the Software.
|
|
9
|
+
|
|
10
|
+
For purposes of the foregoing, "Sell" means practicing any or all of the
|
|
11
|
+
rights granted to you under the License to provide to third parties, for a fee
|
|
12
|
+
or other consideration (including without limitation fees for hosting or
|
|
13
|
+
consulting/support services related to the Software), a product or service
|
|
14
|
+
whose value derives, entirely or substantially, from the functionality of the
|
|
15
|
+
Software. Any license notice or attribution required by the License must also
|
|
16
|
+
include this Commons Clause License Condition notice.
|
|
17
|
+
|
|
18
|
+
Software: Plasalid
|
|
19
|
+
License: Apache License, Version 2.0
|
|
20
|
+
Licensor: Phureewat A
|
|
21
|
+
|
|
22
|
+
----------------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
Apache License
|
|
25
|
+
Version 2.0, January 2004
|
|
26
|
+
http://www.apache.org/licenses/
|
|
27
|
+
|
|
28
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
29
|
+
|
|
30
|
+
1. Definitions.
|
|
31
|
+
|
|
32
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
33
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
34
|
+
|
|
35
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
36
|
+
the copyright owner that is granting the License.
|
|
37
|
+
|
|
38
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
39
|
+
other entities that control, are controlled by, or are under common
|
|
40
|
+
control with that entity. For the purposes of this definition,
|
|
41
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
42
|
+
direction or management of such entity, whether by contract or
|
|
43
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
44
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
45
|
+
|
|
46
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
47
|
+
exercising permissions granted by this License.
|
|
48
|
+
|
|
49
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
50
|
+
including but not limited to software source code, documentation
|
|
51
|
+
source, and configuration files.
|
|
52
|
+
|
|
53
|
+
"Object" form shall mean any form resulting from mechanical
|
|
54
|
+
transformation or translation of a Source form, including but
|
|
55
|
+
not limited to compiled object code, generated documentation,
|
|
56
|
+
and conversions to other media types.
|
|
57
|
+
|
|
58
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
59
|
+
Object form, made available under the License, as indicated by a
|
|
60
|
+
copyright notice that is included in or attached to the work
|
|
61
|
+
(an example is provided in the Appendix below).
|
|
62
|
+
|
|
63
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
64
|
+
form, that is based on (or derived from) the Work and for which the
|
|
65
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
66
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
67
|
+
of this License, Derivative Works shall not include works that remain
|
|
68
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
69
|
+
the Work and Derivative Works thereof.
|
|
70
|
+
|
|
71
|
+
"Contribution" shall mean any work of authorship, including
|
|
72
|
+
the original version of the Work and any modifications or additions
|
|
73
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
74
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
75
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
76
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
77
|
+
means any form of electronic, verbal, or written communication sent
|
|
78
|
+
to the Licensor or its representatives, including but not limited to
|
|
79
|
+
communication on electronic mailing lists, source code control systems,
|
|
80
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
81
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
82
|
+
excluding communication that is conspicuously marked or otherwise
|
|
83
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
84
|
+
|
|
85
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
86
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
87
|
+
subsequently incorporated within the Work.
|
|
88
|
+
|
|
89
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
90
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
91
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
92
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
93
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
94
|
+
Work and such Derivative Works in Source or Object form.
|
|
95
|
+
|
|
96
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
97
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
98
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
99
|
+
(except as stated in this section) patent license to make, have made,
|
|
100
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
101
|
+
where such license applies only to those patent claims licensable
|
|
102
|
+
by such Contributor that are necessarily infringed by their
|
|
103
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
104
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
105
|
+
institute patent litigation against any entity (including a
|
|
106
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
107
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
108
|
+
or contributory patent infringement, then any patent licenses
|
|
109
|
+
granted to You under this License for that Work shall terminate
|
|
110
|
+
as of the date such litigation is filed.
|
|
111
|
+
|
|
112
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
113
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
114
|
+
modifications, and in Source or Object form, provided that You
|
|
115
|
+
meet the following conditions:
|
|
116
|
+
|
|
117
|
+
(a) You must give any other recipients of the Work or
|
|
118
|
+
Derivative Works a copy of this License; and
|
|
119
|
+
|
|
120
|
+
(b) You must cause any modified files to carry prominent notices
|
|
121
|
+
stating that You changed the files; and
|
|
122
|
+
|
|
123
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
124
|
+
that You distribute, all copyright, patent, trademark, and
|
|
125
|
+
attribution notices from the Source form of the Work,
|
|
126
|
+
excluding those notices that do not pertain to any part of
|
|
127
|
+
the Derivative Works; and
|
|
128
|
+
|
|
129
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
130
|
+
distribution, then any Derivative Works that You distribute must
|
|
131
|
+
include a readable copy of the attribution notices contained
|
|
132
|
+
within such NOTICE file, excluding those notices that do not
|
|
133
|
+
pertain to any part of the Derivative Works, in at least one
|
|
134
|
+
of the following places: within a NOTICE text file distributed
|
|
135
|
+
as part of the Derivative Works; within the Source form or
|
|
136
|
+
documentation, if provided along with the Derivative Works; or,
|
|
137
|
+
within a display generated by the Derivative Works, if and
|
|
138
|
+
wherever such third-party notices normally appear. The contents
|
|
139
|
+
of the NOTICE file are for informational purposes only and
|
|
140
|
+
do not modify the License. You may add Your own attribution
|
|
141
|
+
notices within Derivative Works that You distribute, alongside
|
|
142
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
143
|
+
that such additional attribution notices cannot be construed
|
|
144
|
+
as modifying the License.
|
|
145
|
+
|
|
146
|
+
You may add Your own copyright statement to Your modifications and
|
|
147
|
+
may provide additional or different license terms and conditions
|
|
148
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
149
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
150
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
151
|
+
the conditions stated in this License.
|
|
152
|
+
|
|
153
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
154
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
155
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
156
|
+
this License, without any additional terms or conditions.
|
|
157
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
158
|
+
the terms of any separate license agreement you may have executed
|
|
159
|
+
with Licensor regarding such Contributions.
|
|
160
|
+
|
|
161
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
162
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
163
|
+
except as required for describing the origin of the Work and
|
|
164
|
+
reproducing the content of the NOTICE file.
|
|
165
|
+
|
|
166
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
167
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
168
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
169
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
170
|
+
implied, including, without limitation, any warranties or conditions
|
|
171
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
172
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
173
|
+
appropriateness of using or redistributing the Work and assume any
|
|
174
|
+
risks associated with Your exercise of permissions under this License.
|
|
175
|
+
|
|
176
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
177
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
178
|
+
unless required by applicable law (such as deliberate and grossly
|
|
179
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
180
|
+
liable to You for damages, including any direct, indirect, special,
|
|
181
|
+
incidental, or consequential damages of any character arising as a
|
|
182
|
+
result of this License or out of the use or inability to use the
|
|
183
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
184
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
185
|
+
other commercial damages or losses), even if such Contributor
|
|
186
|
+
has been advised of the possibility of such damages.
|
|
187
|
+
|
|
188
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
189
|
+
the Work or Derivative Works thereof, You may accept Support,
|
|
190
|
+
Warranty, Indemnity, or other liability obligations and/or rights
|
|
191
|
+
consistent with this License. However, in accepting such obligations,
|
|
192
|
+
You may only act on Your own behalf and on Your sole responsibility,
|
|
193
|
+
not on behalf of any other Contributor, and only if You agree to
|
|
194
|
+
indemnify, defend, and hold each Contributor harmless for any
|
|
195
|
+
liability incurred by, or claims asserted against, such Contributor
|
|
196
|
+
by reason of your accepting any such warranty or additional liability.
|
|
197
|
+
|
|
198
|
+
END OF TERMS AND CONDITIONS
|
|
199
|
+
|
|
200
|
+
Copyright 2026 Phureewat A
|
|
201
|
+
|
|
202
|
+
Licensed under the Apache License, Version 2.0 (the "License") with the
|
|
203
|
+
Commons Clause License Condition v1.0 as stated above; you may not use
|
|
204
|
+
this file except in compliance with the License.
|
|
205
|
+
You may obtain a copy of the License at
|
|
206
|
+
|
|
207
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
208
|
+
|
|
209
|
+
Unless required by applicable law or agreed to in writing, software
|
|
210
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
211
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
212
|
+
See the License for the specific language governing permissions and
|
|
213
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
<h1 align="center">Plasalid</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<strong>Talk to your money</strong>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
A local-first AI that reads every line of your transactions and coaches you the best move.
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
<br />
|
|
13
|
+
|
|
14
|
+
Plasalid lets you actually *talk* to your money. Drop the bank and credit-card statements you already receive into a folder; Plasalid scans them into a queryable, double-entry database on your own machine. Then chat with it — an AI partner that has read every line and tells you, sharply and proactively, what's going on with your money. Local, private, yours.
|
|
15
|
+
|
|
16
|
+
Plasalid exists because in markets like Thailand there's no Plaid: bank data is locked behind statement PDFs, and most people can't afford a real financial advisor either. Plasalid closes both gaps. Your statements become a database, and an AI that knows that database becomes the money coach you'd otherwise have to hire. Your machine, your encryption key, your data.
|
|
17
|
+
|
|
18
|
+
In Thailand, personal finance isn't taught in school. Fee-based advisors are out of reach for most households. The loudest "advice" channels are bank salespeople pitching their employer's products. Over 5 million people are already flagged as non-performing borrowers, and a generation that wants to manage money better has nowhere accessible to learn how. Plasalid's bet is that capable AI changes this — the same intelligence that can read a statement can also explain what the numbers mean, surface what's about to go wrong, and coach someone through real decisions about debt, budget, and savings. At zero marginal cost, in your language, on your own machine.
|
|
19
|
+
|
|
20
|
+
Plasalid can also scales upward in case financial survival isn't your question — help you setup a goal for vacation trip, building an emergency fund, choosing investments, planning a down payment or retirement, working toward the freedom to walk away from a bad job. From getting out of debt to financial freedom, Plasalid grows with you.
|
|
21
|
+
|
|
22
|
+
## Features
|
|
23
|
+
|
|
24
|
+
### Your personal money coach
|
|
25
|
+
|
|
26
|
+
- **Sees every balance, every transaction** — Plasalid's chat reads from your bank and credit-card statements, not generic categories. "Where did ฿14k go in March?" gets a specific answer.
|
|
27
|
+
- **Sharp and proactive** — Leads with the insight, not the breakdown. Flags concerning patterns (overdraft trajectory, unusual spending, payments due soon) even if you didn't ask.
|
|
28
|
+
- **Has a point of view** — When you ask "what should I do?", you get a recommendation, not a list of options.
|
|
29
|
+
- **Remembers what matters** — Persists biographical context (family, employer, goals) and per-statement scanning hints across sessions, so each conversation starts smarter than the last.
|
|
30
|
+
|
|
31
|
+
### A data harness AI can plug into
|
|
32
|
+
|
|
33
|
+
- **The missing aggregator** — In markets without Plaid, there's no bank API that easy to access. Plasalid turns the documents you already receive into a database that machine can read, so the data layer stops being the blocker.
|
|
34
|
+
- **Composable substrate** — Plasalid's local SQLite is plain, queryable double-entry data. Any tool that can read SQLite — Claude Code, MCP servers, your own scripts, dashboards — can build automations, alerts, exporters, or personalized analyses on top, with no further integration work.
|
|
35
|
+
- **No vendor lock, no rate limits** — Standard accounts and journal lines, your encryption key, your machine. Nothing to revoke, throttle, or paywall.
|
|
36
|
+
- **BYO model** — Pick Anthropic (Claude) or any OpenAI-compatible server (Ollama, OpenAI, LM Studio, vLLM, …) at setup time. Local models keep the conversation 100% on your machine.
|
|
37
|
+
|
|
38
|
+
### Drop documents in, get structured data out
|
|
39
|
+
|
|
40
|
+
- **Encrypted PDFs handled inline** — Statement password-protected? Plasalid prompts you once, then remembers the password (encrypted at rest) under a filename pattern so the next month's statement unlocks silently.
|
|
41
|
+
- **Asks instead of guessing** — Ambiguous row? The scanner pauses and prompts you.
|
|
42
|
+
- **Idempotent scan** — Files are hashed; re-running `plasalid scan` skips what it already scanned. `--force` cascade-deletes prior records before re-scanning.
|
|
43
|
+
- **Learns your statements** — Per-bank scanning hints persist across runs (the AI saves them in a local memory table) so each new statement scans more accurately than the last.
|
|
44
|
+
|
|
45
|
+
### Correctness, not vibes
|
|
46
|
+
|
|
47
|
+
- **Double-entry bookkeeping** — Every transaction balances enforced by standard double-entry accounting.
|
|
48
|
+
- **Account metadata preserved** — Bank, masked number, statement day, due day, points.
|
|
49
|
+
- **Dates normalized** — ISO Gregorian; Buddhist-Era dates converted automatically.
|
|
50
|
+
- **Reconcile pass** — `plasalid reconcile` surfaces duplicate entries, similar accounts, and unused accounts; merges, renames, and deletes happen only after explicit confirmation. `--dry-run` previews without writing.
|
|
51
|
+
|
|
52
|
+
### Your data never leaves your machine
|
|
53
|
+
|
|
54
|
+
- **Encrypted local database** — All data stays on your machine in an AES-256 encrypted SQLite database.
|
|
55
|
+
- **PII masking** — Names, national IDs, phones, full account/card numbers scrubbed before anything reaches the AI.
|
|
56
|
+
- **No telemetry. No analytics.** Only outbound traffic is to your configured AI provider.
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
## Install
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm install -g plasalid
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Requires Node ≥ 18.
|
|
66
|
+
|
|
67
|
+
## Quick Start
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
plasalid setup
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Then:
|
|
74
|
+
|
|
75
|
+
1. Drop any PDFs anywhere under `~/.plasalid/data/`. Subfolders are allowed but not interpreted — the AI infers account type from the document.
|
|
76
|
+
2. Run `plasalid scan` and answer any clarifying questions inline.
|
|
77
|
+
3. Run `plasalid` to chat with what was scanned.
|
|
78
|
+
|
|
79
|
+
Other day-to-day commands:
|
|
80
|
+
|
|
81
|
+
- `plasalid scan <regex>` — only scan files whose path matches the regex.
|
|
82
|
+
- `plasalid scan <regex> --force` — re-scan matching files (replaces prior records).
|
|
83
|
+
- `plasalid reconcile --dry-run` — periodically surface duplicate entries and similar accounts; re-run without `--dry-run` to apply fixes interactively.
|
|
84
|
+
- `plasalid revert <regex>` — delete scanned files matching the regex and every journal entry derived from them.
|
|
85
|
+
|
|
86
|
+
## Commands
|
|
87
|
+
|
|
88
|
+
Run `plasalid --help` to see all available commands.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
plasalid # Interactive TUI chat with your local data
|
|
92
|
+
plasalid setup # Configure API key, encryption, and data directory
|
|
93
|
+
plasalid data # Open the Plasalid data folder in your OS file explorer
|
|
94
|
+
plasalid accounts # Show the chart of accounts with balances
|
|
95
|
+
plasalid status # Net worth and this-month income/expense totals
|
|
96
|
+
plasalid transactions # List journal lines (filter by --account, --from, --to, --query, --limit)
|
|
97
|
+
plasalid scan [regex] [--force] # Scan new PDFs; --force cascade-deletes prior records before re-scanning
|
|
98
|
+
plasalid revert <regex> # Delete scanned files matching <regex> and their journal entries
|
|
99
|
+
plasalid reconcile [--dry-run] # Review the journal: duplicates, similar accounts, unused accounts (--account, --from, --to also accepted)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## How It Works
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
Bank statements · Credit-card statements
|
|
106
|
+
│
|
|
107
|
+
(drop PDFs)
|
|
108
|
+
│
|
|
109
|
+
┌──────────▼──────────┐
|
|
110
|
+
│ ~/.plasalid/data/ │
|
|
111
|
+
└──────────┬──────────┘
|
|
112
|
+
│
|
|
113
|
+
plasalid scan
|
|
114
|
+
│
|
|
115
|
+
Claude API (PII-redacted)
|
|
116
|
+
│
|
|
117
|
+
┌──────────▼──────────┐
|
|
118
|
+
│ Encrypted DB │◀──── plasalid reconcile
|
|
119
|
+
└──────────┬──────────┘
|
|
120
|
+
│
|
|
121
|
+
plasalid · chat
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Two outbound calls: the AI provider during scan, and the AI provider during chat. Both are PII-redacted. Your financial data is never stored off your machine. No telemetry. No analytics.
|
|
125
|
+
|
|
126
|
+
## Security & Privacy
|
|
127
|
+
|
|
128
|
+
- All financial data stored locally in `~/.plasalid/db.sqlite`
|
|
129
|
+
- Database encrypted with AES-256 (libsql)
|
|
130
|
+
- Config file stored with `0600` permissions
|
|
131
|
+
- PII redacted before sending to any AI provider
|
|
132
|
+
- Encrypted-PDF passwords are AES-GCM-encrypted inside `db.sqlite` under a filename pattern; never written to disk in plaintext.
|
|
133
|
+
- Only outbound traffic is to your configured AI provider
|
|
134
|
+
|
|
135
|
+
## Configuration
|
|
136
|
+
|
|
137
|
+
Plasalid stores everything in `~/.plasalid/`:
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
~/.plasalid/
|
|
141
|
+
config.json # API keys and preferences (0600 permissions)
|
|
142
|
+
context.md # Persistent personal context
|
|
143
|
+
db.sqlite # Encrypted SQLite database
|
|
144
|
+
data/ # Drop any PDFs here (subfolders allowed; AI classifies)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
`db.sqlite` holds the journal, chart of accounts, scan history, persisted long-term memories, and AES-GCM-encrypted PDF passwords keyed by filename pattern. Everything is wrapped in libsql's AES-256 page encryption.
|
|
148
|
+
|
|
149
|
+
### Environment Variables
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
ANTHROPIC_API_KEY= # Anthropic API key (required when provider is anthropic)
|
|
153
|
+
PLASALID_MODEL= # Model name; default for Anthropic: claude-sonnet-4-6
|
|
154
|
+
PLASALID_PROVIDER= # anthropic | openai-compatible. Default: anthropic
|
|
155
|
+
OPENAI_COMPATIBLE_BASE_URL= # e.g. http://localhost:11434/v1 (Ollama)
|
|
156
|
+
OPENAI_COMPATIBLE_API_KEY= # API key for the OpenAI-compatible server (often unused)
|
|
157
|
+
PLASALID_DB_ENCRYPTION_KEY= # DB encryption passphrase
|
|
158
|
+
PLASALID_DB_PATH= # Default: ~/.plasalid/db.sqlite
|
|
159
|
+
PLASALID_DATA_DIR= # Default: ~/.plasalid/data
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Contributing
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
git clone https://github.com/phureewat29/plasalid
|
|
166
|
+
cd plasalid
|
|
167
|
+
npm install
|
|
168
|
+
npm run build
|
|
169
|
+
npm link # makes 'plasalid' available globally
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## License
|
|
173
|
+
|
|
174
|
+
Plasalid is released under the [Apache License 2.0 with the Commons Clause](./LICENSE).
|
|
175
|
+
|
|
176
|
+
You're free to use, copy, modify, distribute, and fork it. The Commons Clause adds one restriction: **you may not Sell the Software** — that is, you may not provide a paid product or service whose value derives entirely or substantially from Plasalid's functionality (including paid hosting or support). For commercial-resale rights, contact the copyright holder to negotiate a separate license.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type AccountType = "asset" | "liability" | "income" | "expense" | "equity";
|
|
2
|
+
export type InstitutionKind = "bank" | "card_issuer" | "wallet" | "payment_rail" | "broker" | "crypto_exchange" | "insurer" | "gov" | "telco" | "utility";
|
|
3
|
+
export interface ThaiInstitution {
|
|
4
|
+
code: string;
|
|
5
|
+
label: string;
|
|
6
|
+
kind: InstitutionKind;
|
|
7
|
+
/** Optional disambiguating note for the AI (mergers, rebrands, regulatory status). */
|
|
8
|
+
notes?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const THAI_BANKS: ThaiInstitution[];
|
|
11
|
+
export declare const THAI_CARD_ISSUERS: ThaiInstitution[];
|
|
12
|
+
export declare const THAI_WALLETS: ThaiInstitution[];
|
|
13
|
+
export declare const THAI_PAYMENT_RAILS: ThaiInstitution[];
|
|
14
|
+
export declare const THAI_BROKERS: ThaiInstitution[];
|
|
15
|
+
export declare const THAI_CRYPTO_EXCHANGES: ThaiInstitution[];
|
|
16
|
+
export declare const THAI_INSURERS: ThaiInstitution[];
|
|
17
|
+
export declare const THAI_GOV: ThaiInstitution[];
|
|
18
|
+
export declare const THAI_UTILITIES: ThaiInstitution[];
|
|
19
|
+
export declare const THAI_TELCOS: ThaiInstitution[];
|
|
20
|
+
export declare const ALL_THAI_INSTITUTIONS: ThaiInstitution[];
|
|
21
|
+
export declare const ACCOUNT_TYPE_DESCRIPTIONS: Record<AccountType, string>;
|
|
22
|
+
export declare const SUGGESTED_ASSET_SUBTYPES: string[];
|
|
23
|
+
export declare const SUGGESTED_LIABILITY_SUBTYPES: string[];
|
|
24
|
+
export declare const SUGGESTED_EXPENSE_SUBTYPES: string[];
|
|
25
|
+
export declare const SUGGESTED_INCOME_SUBTYPES: string[];
|
|
26
|
+
/**
|
|
27
|
+
* Stringified Thai taxonomy block for the scan/reconcile system prompts.
|
|
28
|
+
* Lists known Thai institutions and suggested subtypes so the model picks
|
|
29
|
+
* consistent `bank_name` and `subtype` values across statements.
|
|
30
|
+
*/
|
|
31
|
+
export declare function getThaiTaxonomyHint(): string;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
export const THAI_BANKS = [
|
|
2
|
+
{ code: "KBANK", label: "Kasikornbank", kind: "bank" },
|
|
3
|
+
{ code: "SCB", label: "Siam Commercial Bank", kind: "bank" },
|
|
4
|
+
{ code: "BBL", label: "Bangkok Bank", kind: "bank" },
|
|
5
|
+
{ code: "KTB", label: "Krungthai Bank", kind: "bank", notes: "State-owned." },
|
|
6
|
+
{ code: "BAY", label: "Krungsri (Bank of Ayudhya)", kind: "bank" },
|
|
7
|
+
{ code: "TTB", label: "TMBThanachart Bank", kind: "bank", notes: "Result of TMB + Thanachart merger." },
|
|
8
|
+
{ code: "UOB-TH", label: "UOB Thailand", kind: "bank", notes: "Absorbed Citi Thailand's consumer banking (incl. cards) in Nov 2022." },
|
|
9
|
+
{ code: "CIMB-TH", label: "CIMB Thai", kind: "bank" },
|
|
10
|
+
{ code: "GHB", label: "Government Housing Bank", kind: "bank", notes: "State-owned, mortgage focus." },
|
|
11
|
+
{ code: "GSB", label: "Government Savings Bank", kind: "bank", notes: "State-owned." },
|
|
12
|
+
{ code: "LH-BANK", label: "Land and Houses Bank", kind: "bank" },
|
|
13
|
+
{ code: "KKP", label: "Kiatnakin Phatra Bank", kind: "bank", notes: "Merged 2020 from KK + Phatra." },
|
|
14
|
+
{ code: "TISCO", label: "TISCO Bank", kind: "bank" },
|
|
15
|
+
{ code: "IBT", label: "Islamic Bank of Thailand", kind: "bank", notes: "State-owned; serves all customers." },
|
|
16
|
+
{ code: "ICBC-TH", label: "ICBC (Thai)", kind: "bank", notes: "Subsidiary of ICBC China." },
|
|
17
|
+
{ code: "BAAC", label: "Bank for Agriculture and Agricultural Cooperatives", kind: "bank", notes: "State-owned, rural finance." },
|
|
18
|
+
];
|
|
19
|
+
export const THAI_CARD_ISSUERS = [
|
|
20
|
+
{ code: "KTC", label: "Krungthai Card", kind: "card_issuer", notes: "Listed subsidiary of KTB." },
|
|
21
|
+
{ code: "AEON", label: "AEON Thana Sinsap", kind: "card_issuer" },
|
|
22
|
+
{ code: "FIRSTCHOICE", label: "Krungsri First Choice", kind: "card_issuer" },
|
|
23
|
+
{ code: "CITI-TH", label: "Citibank Thailand", kind: "card_issuer", notes: "Consumer cards migrated to UOB-TH in Nov 2022; only historical statements still reference Citi." },
|
|
24
|
+
{ code: "AMEX-TH", label: "American Express Thailand", kind: "card_issuer" },
|
|
25
|
+
{ code: "CARDX", label: "CardX", kind: "card_issuer", notes: "SCB X consumer-card spinoff; issues cards previously branded SCB." },
|
|
26
|
+
{ code: "DINERS", label: "Diners Club Thailand", kind: "card_issuer" },
|
|
27
|
+
{ code: "UOB-TH", label: "UOB Thailand (Cards)", kind: "card_issuer", notes: "Same legal entity as the bank UOB-TH; now issues both its own card line (UOB Yolo, UOB Premier) and the migrated Citi consumer cards." },
|
|
28
|
+
];
|
|
29
|
+
export const THAI_WALLETS = [
|
|
30
|
+
{ code: "TRUEMONEY", label: "TrueMoney Wallet", kind: "wallet" },
|
|
31
|
+
{ code: "LINEPAY", label: "Rabbit LINE Pay", kind: "wallet" },
|
|
32
|
+
{ code: "SHOPEEPAY", label: "ShopeePay", kind: "wallet" },
|
|
33
|
+
{ code: "GRABPAY", label: "GrabPay (Thailand)", kind: "wallet" },
|
|
34
|
+
{ code: "DOLFIN", label: "Dolfin Wallet", kind: "wallet", notes: "Central Group + JD.com joint venture." },
|
|
35
|
+
{ code: "MPAY", label: "mPay", kind: "wallet", notes: "AIS-operated." },
|
|
36
|
+
{ code: "PAOTANG", label: "Paotang", kind: "wallet", notes: "Krungthai-operated; government-benefits and tax e-wallet." },
|
|
37
|
+
];
|
|
38
|
+
export const THAI_PAYMENT_RAILS = [
|
|
39
|
+
{ code: "PROMPTPAY", label: "PromptPay", kind: "payment_rail", notes: "National 24/7 interbank rail; appears on transfer slips, not an issuer." },
|
|
40
|
+
];
|
|
41
|
+
export const THAI_BROKERS = [
|
|
42
|
+
{ code: "INNOVESTX", label: "InnovestX Securities", kind: "broker", notes: "Former SCBS; SCBX subsidiary." },
|
|
43
|
+
{ code: "BLS", label: "Bualuang Securities", kind: "broker", notes: "BBL subsidiary." },
|
|
44
|
+
{ code: "KS", label: "Kasikorn Securities", kind: "broker", notes: "KBANK subsidiary." },
|
|
45
|
+
{ code: "KGI-TH", label: "KGI Securities (Thailand)", kind: "broker" },
|
|
46
|
+
{ code: "MAYBANK-SEC", label: "Maybank Securities (Thailand)", kind: "broker" },
|
|
47
|
+
{ code: "ASP", label: "Asia Plus Securities", kind: "broker" },
|
|
48
|
+
{ code: "TISCO-SEC", label: "TISCO Securities", kind: "broker" },
|
|
49
|
+
{ code: "KSS", label: "Krungsri Securities", kind: "broker", notes: "BAY subsidiary." },
|
|
50
|
+
{ code: "KKPS", label: "Kiatnakin Phatra Securities", kind: "broker", notes: "KKP subsidiary." },
|
|
51
|
+
{ code: "LH-SEC", label: "Land and Houses Securities", kind: "broker" },
|
|
52
|
+
{ code: "FINANSIA", label: "Finansia Syrus Securities", kind: "broker" },
|
|
53
|
+
{ code: "YUANTA-TH", label: "Yuanta Securities (Thailand)", kind: "broker" },
|
|
54
|
+
{ code: "DBSVICKERS", label: "DBS Vickers Securities (Thailand)", kind: "broker" },
|
|
55
|
+
{ code: "KTBST", label: "Krungthai Xspring Securities", kind: "broker", notes: "Formerly KTBST; KTB-affiliated." },
|
|
56
|
+
];
|
|
57
|
+
export const THAI_CRYPTO_EXCHANGES = [
|
|
58
|
+
{ code: "BITKUB", label: "Bitkub Exchange", kind: "crypto_exchange", notes: "SEC-licensed; dominant market share." },
|
|
59
|
+
{ code: "UPBIT-TH", label: "Upbit Thailand", kind: "crypto_exchange", notes: "SEC-licensed; subsidiary of South Korean Upbit." },
|
|
60
|
+
{ code: "ORBIX", label: "Orbix Trade", kind: "crypto_exchange", notes: "Former Satang Pro; rebranded under KBank ownership." },
|
|
61
|
+
{ code: "GULF-BINANCE", label: "Binance Thailand (Gulf Binance)", kind: "crypto_exchange", notes: "Binance + Gulf Innova JV; SEC-licensed." },
|
|
62
|
+
{ code: "KUCOIN-TH", label: "KuCoin Thailand", kind: "crypto_exchange", notes: "Former ERX; rebranded 2025 after KuCoin acquisition." },
|
|
63
|
+
{ code: "WAANX", label: "WaanX", kind: "crypto_exchange", notes: "SEC-licensed." },
|
|
64
|
+
{ code: "TDX", label: "Thai Digital Assets Exchange", kind: "crypto_exchange", notes: "SET Group subsidiary." },
|
|
65
|
+
{ code: "GMO-Z-EX", label: "Z.com EX (GMO-Z.com)", kind: "crypto_exchange", notes: "Japanese GMO subsidiary." },
|
|
66
|
+
{ code: "ZIPMEX", label: "Zipmex", kind: "crypto_exchange", notes: "Defunct since Nov 2023; statements only appear in historical files." },
|
|
67
|
+
];
|
|
68
|
+
export const THAI_INSURERS = [
|
|
69
|
+
// Life
|
|
70
|
+
{ code: "AIA-TH", label: "AIA Thailand", kind: "insurer", notes: "Life; market leader." },
|
|
71
|
+
{ code: "MUANG-THAI-LIFE", label: "Muang Thai Life Insurance", kind: "insurer", notes: "Life." },
|
|
72
|
+
{ code: "THAI-LIFE", label: "Thai Life Insurance", kind: "insurer", notes: "Life; listed (TLI)." },
|
|
73
|
+
{ code: "FWD-TH", label: "FWD Thailand", kind: "insurer", notes: "Life." },
|
|
74
|
+
{ code: "ALLIANZ-AYUDHYA-LIFE", label: "Allianz Ayudhya Assurance", kind: "insurer", notes: "Life; Allianz + BAY JV." },
|
|
75
|
+
{ code: "KTAXA", label: "Krungthai-AXA Life", kind: "insurer", notes: "Life; KTB + AXA JV." },
|
|
76
|
+
{ code: "BANGKOK-LIFE", label: "Bangkok Life Assurance", kind: "insurer", notes: "Life." },
|
|
77
|
+
{ code: "CHUBB-SAMAGGI", label: "Chubb Samaggi Insurance", kind: "insurer", notes: "Life and non-life." },
|
|
78
|
+
{ code: "GENERALI-TH", label: "Generali Thailand", kind: "insurer", notes: "Life." },
|
|
79
|
+
// Non-life
|
|
80
|
+
{ code: "DHIPAYA", label: "Dhipaya Insurance", kind: "insurer", notes: "Non-life." },
|
|
81
|
+
{ code: "BANGKOK-INS", label: "Bangkok Insurance", kind: "insurer", notes: "Non-life." },
|
|
82
|
+
{ code: "ALLIANZ-AYUDHYA-GENERAL", label: "Allianz Ayudhya General Insurance", kind: "insurer", notes: "Non-life." },
|
|
83
|
+
{ code: "VIRIYAH", label: "Viriyah Insurance", kind: "insurer", notes: "Non-life; #1 motor insurer." },
|
|
84
|
+
{ code: "TOKIO-MARINE", label: "Tokio Marine (Thailand)", kind: "insurer", notes: "Non-life." },
|
|
85
|
+
];
|
|
86
|
+
export const THAI_GOV = [
|
|
87
|
+
{ code: "REVDEPT", label: "Revenue Department (กรมสรรพากร)", kind: "gov", notes: "Income tax, VAT, excise." },
|
|
88
|
+
{ code: "SSO", label: "Social Security Office (สำนักงานประกันสังคม)", kind: "gov", notes: "Employee + self-employed social security contributions." },
|
|
89
|
+
{ code: "BOT", label: "Bank of Thailand", kind: "gov", notes: "Central bank; rarely on consumer statements outside of regulatory letters." },
|
|
90
|
+
{ code: "MOF", label: "Ministry of Finance", kind: "gov" },
|
|
91
|
+
{ code: "LDT", label: "Department of Lands (กรมที่ดิน)", kind: "gov", notes: "Land registration, property tax." },
|
|
92
|
+
{ code: "CUSTOMS", label: "Customs Department (กรมศุลกากร)", kind: "gov", notes: "Import/export duties." },
|
|
93
|
+
];
|
|
94
|
+
export const THAI_UTILITIES = [
|
|
95
|
+
{ code: "MEA", label: "Metropolitan Electricity Authority (กฟน.)", kind: "utility", notes: "Electricity for Bangkok, Nonthaburi, Samut Prakan." },
|
|
96
|
+
{ code: "PEA", label: "Provincial Electricity Authority (กฟภ.)", kind: "utility", notes: "Electricity for the rest of Thailand outside MEA's area." },
|
|
97
|
+
{ code: "MWA", label: "Metropolitan Waterworks Authority (กปน.)", kind: "utility", notes: "Water for Bangkok, Nonthaburi, Samut Prakan." },
|
|
98
|
+
{ code: "PWA", label: "Provincial Waterworks Authority (กปภ.)", kind: "utility", notes: "Water for the rest of Thailand." },
|
|
99
|
+
{ code: "EGAT", label: "Electricity Generating Authority of Thailand (กฟผ.)", kind: "utility", notes: "Power generation; rarely appears on consumer bills directly." },
|
|
100
|
+
];
|
|
101
|
+
export const THAI_TELCOS = [
|
|
102
|
+
{ code: "AIS", label: "Advanced Info Service (AIS)", kind: "telco" },
|
|
103
|
+
{ code: "TRUE-CORP", label: "True Corporation", kind: "telco", notes: "Merged entity of True + dtac since March 2023." },
|
|
104
|
+
{ code: "TRUEMOVE", label: "TrueMove H", kind: "telco", notes: "Brand retained under TRUE-CORP per NBTC ruling." },
|
|
105
|
+
{ code: "DTAC", label: "dtac", kind: "telco", notes: "Brand retained under TRUE-CORP per NBTC ruling." },
|
|
106
|
+
{ code: "NT", label: "National Telecom (NT)", kind: "telco", notes: "Former TOT; state-owned, minimal consumer presence." },
|
|
107
|
+
];
|
|
108
|
+
export const ALL_THAI_INSTITUTIONS = [
|
|
109
|
+
...THAI_BANKS,
|
|
110
|
+
...THAI_CARD_ISSUERS,
|
|
111
|
+
...THAI_WALLETS,
|
|
112
|
+
...THAI_PAYMENT_RAILS,
|
|
113
|
+
...THAI_BROKERS,
|
|
114
|
+
...THAI_CRYPTO_EXCHANGES,
|
|
115
|
+
...THAI_INSURERS,
|
|
116
|
+
...THAI_GOV,
|
|
117
|
+
...THAI_TELCOS,
|
|
118
|
+
...THAI_UTILITIES,
|
|
119
|
+
];
|
|
120
|
+
export const ACCOUNT_TYPE_DESCRIPTIONS = {
|
|
121
|
+
asset: "Bank accounts, cash, prepaid wallets, receivables.",
|
|
122
|
+
liability: "Credit cards, loans, mortgages, money the user owes.",
|
|
123
|
+
income: "Salary, side income, dividends, refunds.",
|
|
124
|
+
expense: "Spending categories (food, transport, utilities, etc.).",
|
|
125
|
+
equity: "Owner's equity / opening balance equity (for reconciliation).",
|
|
126
|
+
};
|
|
127
|
+
export const SUGGESTED_ASSET_SUBTYPES = [
|
|
128
|
+
"bank",
|
|
129
|
+
"cash",
|
|
130
|
+
"wallet",
|
|
131
|
+
"prepaid_card",
|
|
132
|
+
"brokerage",
|
|
133
|
+
"crypto",
|
|
134
|
+
"receivable",
|
|
135
|
+
];
|
|
136
|
+
export const SUGGESTED_LIABILITY_SUBTYPES = [
|
|
137
|
+
"credit_card",
|
|
138
|
+
"home_loan",
|
|
139
|
+
"auto_loan",
|
|
140
|
+
"personal_loan",
|
|
141
|
+
"student_loan",
|
|
142
|
+
"revolving",
|
|
143
|
+
"deferred_income",
|
|
144
|
+
];
|
|
145
|
+
export const SUGGESTED_EXPENSE_SUBTYPES = [
|
|
146
|
+
"food",
|
|
147
|
+
"transport",
|
|
148
|
+
"utilities",
|
|
149
|
+
"rent",
|
|
150
|
+
"housing",
|
|
151
|
+
"healthcare",
|
|
152
|
+
"entertainment",
|
|
153
|
+
"shopping",
|
|
154
|
+
"subscriptions",
|
|
155
|
+
"education",
|
|
156
|
+
"travel",
|
|
157
|
+
"fees_and_interest",
|
|
158
|
+
"tax",
|
|
159
|
+
"insurance",
|
|
160
|
+
"other",
|
|
161
|
+
];
|
|
162
|
+
export const SUGGESTED_INCOME_SUBTYPES = [
|
|
163
|
+
"salary",
|
|
164
|
+
"bonus",
|
|
165
|
+
"freelance",
|
|
166
|
+
"interest",
|
|
167
|
+
"dividend",
|
|
168
|
+
"refund",
|
|
169
|
+
"other",
|
|
170
|
+
];
|
|
171
|
+
/**
|
|
172
|
+
* Stringified Thai taxonomy block for the scan/reconcile system prompts.
|
|
173
|
+
* Lists known Thai institutions and suggested subtypes so the model picks
|
|
174
|
+
* consistent `bank_name` and `subtype` values across statements.
|
|
175
|
+
*/
|
|
176
|
+
export function getThaiTaxonomyHint() {
|
|
177
|
+
const institutions = ALL_THAI_INSTITUTIONS
|
|
178
|
+
.map(i => `${i.code} (${i.label}, ${i.kind})${i.notes ? ` — ${i.notes}` : ""}`)
|
|
179
|
+
.join("\n");
|
|
180
|
+
return [
|
|
181
|
+
`Known Thai institutions:`,
|
|
182
|
+
institutions,
|
|
183
|
+
``,
|
|
184
|
+
`Suggested asset subtypes: ${SUGGESTED_ASSET_SUBTYPES.join(", ")}`,
|
|
185
|
+
`Suggested liability subtypes: ${SUGGESTED_LIABILITY_SUBTYPES.join(", ")}`,
|
|
186
|
+
`Suggested expense subtypes: ${SUGGESTED_EXPENSE_SUBTYPES.join(", ")}`,
|
|
187
|
+
`Suggested income subtypes: ${SUGGESTED_INCOME_SUBTYPES.join(", ")}`,
|
|
188
|
+
].join("\n");
|
|
189
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type Database from "libsql";
|
|
2
|
+
import { type ScanPromptOptions, type ReconcilePromptOptions } from "./system-prompt.js";
|
|
3
|
+
import { type AgentExecutionContext } from "./tools/index.js";
|
|
4
|
+
import type { NormalizedMessage } from "./provider.js";
|
|
5
|
+
export type ProgressCallback = (event: {
|
|
6
|
+
phase: "tool" | "responding";
|
|
7
|
+
toolName?: string;
|
|
8
|
+
toolCount: number;
|
|
9
|
+
elapsedMs: number;
|
|
10
|
+
}) => void;
|
|
11
|
+
export declare class AbortedError extends Error {
|
|
12
|
+
constructor();
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Conversational chat used by the Ink TUI. Reuses conversation_history for context
|
|
16
|
+
* continuity, redacts PII on the way out, restores it on the way in for display.
|
|
17
|
+
*/
|
|
18
|
+
export declare function handleChatMessage(db: Database.Database, userMessage: string, onProgress?: ProgressCallback, signal?: AbortSignal): Promise<string>;
|
|
19
|
+
/**
|
|
20
|
+
* Scan-time agent loop. Caller supplies the initial user message (which carries
|
|
21
|
+
* the PDF as a content block) and a AgentExecutionContext that scopes the file
|
|
22
|
+
* id, scanner version, and interactivity for ask_user.
|
|
23
|
+
*/
|
|
24
|
+
export declare function runScanAgent(opts: {
|
|
25
|
+
db: Database.Database;
|
|
26
|
+
initialMessages: NormalizedMessage[];
|
|
27
|
+
prompt: ScanPromptOptions;
|
|
28
|
+
agentCtx: AgentExecutionContext;
|
|
29
|
+
onProgress?: ProgressCallback;
|
|
30
|
+
signal?: AbortSignal;
|
|
31
|
+
}): Promise<string>;
|
|
32
|
+
/**
|
|
33
|
+
* Reconcile-time agent loop. Walks the existing journal with the reconcile
|
|
34
|
+
* tool profile (read tools + write/merge/delete primitives).
|
|
35
|
+
*/
|
|
36
|
+
export declare function runReconcileAgent(opts: {
|
|
37
|
+
db: Database.Database;
|
|
38
|
+
initialMessages: NormalizedMessage[];
|
|
39
|
+
prompt: ReconcilePromptOptions;
|
|
40
|
+
agentCtx: AgentExecutionContext;
|
|
41
|
+
onProgress?: ProgressCallback;
|
|
42
|
+
signal?: AbortSignal;
|
|
43
|
+
}): Promise<string>;
|