@fibukiapp/openclaw-plugin 0.1.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/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # FiBuKI OpenClaw Plugin
2
+
3
+ Manage your FiBuKI tax accounting data through AI assistants.
4
+
5
+ ## What Claude Can Do
6
+
7
+ | Task | Tools Used |
8
+ |------|------------|
9
+ | **View bank accounts** | `list_sources`, `get_source` |
10
+ | **Browse transactions** | `list_transactions`, `get_transaction` |
11
+ | **Find incomplete work** | `list_transactions` (isComplete=false), `list_transactions_needing_files` |
12
+ | **Match receipts** | `list_files`, `connect_file_to_transaction`, `auto_connect_file_suggestions` |
13
+ | **Categorize transactions** | `list_no_receipt_categories`, `assign_no_receipt_category` |
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ # From npm (when published)
19
+ openclaw plugins install @fibuki/openclaw-plugin
20
+
21
+ # Or link locally for development
22
+ cd integrations/openclaw-plugin
23
+ openclaw plugins install -l .
24
+ ```
25
+
26
+ ## Configuration
27
+
28
+ 1. **Generate an API Key** in FiBuKI:
29
+ - Go to **Settings > Integrations > AI Agents**
30
+ - Click "Create API Key"
31
+ - Copy the key (starts with `fk_`)
32
+
33
+ 2. **Add to OpenClaw config:**
34
+
35
+ ```json5
36
+ {
37
+ plugins: {
38
+ entries: {
39
+ "fibuki": {
40
+ enabled: true,
41
+ config: {
42
+ apiKey: "fk_your_api_key_here"
43
+ }
44
+ }
45
+ }
46
+ }
47
+ }
48
+ ```
49
+
50
+ ## Available Tools
51
+
52
+ ### Bank Accounts
53
+ - `list_sources` - List all connected bank accounts
54
+ - `get_source` - Get details of a specific account
55
+
56
+ ### Transactions
57
+ - `list_transactions` - Search/filter transactions (use `isComplete: false` for incomplete)
58
+ - `get_transaction` - Get full transaction details
59
+ - `update_transaction` - Update description, mark complete
60
+
61
+ ### Files (Receipts/Invoices)
62
+ - `list_files` - List uploaded files with match suggestions
63
+ - `get_file` - Get file details including extracted data
64
+ - `connect_file_to_transaction` - Link file to transaction
65
+ - `disconnect_file_from_transaction` - Unlink file
66
+ - `list_transactions_needing_files` - Find transactions without receipts
67
+ - `auto_connect_file_suggestions` - Bulk-connect high-confidence matches
68
+
69
+ ### No-Receipt Categories
70
+ - `list_no_receipt_categories` - List categories (bank fees, payroll, etc.)
71
+ - `assign_no_receipt_category` - Mark transaction as not needing receipt
72
+ - `remove_no_receipt_category` - Remove category from transaction
73
+
74
+ ## Example Conversations
75
+
76
+ **User:** "Show me incomplete transactions from last month"
77
+ ```
78
+ Claude uses: list_transactions with isComplete=false, dateFrom, dateTo
79
+ ```
80
+
81
+ **User:** "Match all my unconnected receipts"
82
+ ```
83
+ Claude uses: auto_connect_file_suggestions
84
+ ```
85
+
86
+ **User:** "The bank fee doesn't need a receipt"
87
+ ```
88
+ Claude uses: list_no_receipt_categories, then assign_no_receipt_category
89
+ ```
90
+
91
+ ## API Key Security
92
+
93
+ - API keys are hashed before storage (we never store the raw key)
94
+ - Keys can be revoked anytime in Settings
95
+ - Each key tracks last used time and usage count
96
+ - Maximum 5 active keys per user
97
+ - Optional expiry dates supported
98
+
99
+ ## Domain Context
100
+
101
+ The plugin includes a skills file (`skills/fibuki-guide/SKILL.md`) that gives Claude context about:
102
+ - FiBuKI's data model (sources, transactions, files, partners)
103
+ - Transaction completion logic
104
+ - Amount handling (cents, not euros!)
105
+ - Common workflows
@@ -0,0 +1,27 @@
1
+ {
2
+ "id": "fibuki",
3
+ "name": "FiBuKI Tax Studio",
4
+ "description": "Manage bank transactions, receipts, files, and tax categorization through FiBuKI. 15+ tools for transactions, files, and categories.",
5
+ "skills": ["skills/fibuki-guide"],
6
+ "channel": {
7
+ "docsPath": "/integrations/fibuki",
8
+ "blurb": "German tax accounting automation"
9
+ },
10
+ "configSchema": {
11
+ "type": "object",
12
+ "properties": {
13
+ "apiKey": {
14
+ "type": "string",
15
+ "description": "Your FiBuKI API key (generate at Settings > Integrations > AI Agents)"
16
+ }
17
+ },
18
+ "required": ["apiKey"]
19
+ },
20
+ "uiHints": {
21
+ "apiKey": {
22
+ "label": "API Key",
23
+ "placeholder": "fk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
24
+ "sensitive": true
25
+ }
26
+ }
27
+ }
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@fibukiapp/openclaw-plugin",
3
+ "version": "0.1.0",
4
+ "description": "FiBuKI Tax Studio plugin for OpenClaw - manage transactions, receipts, and tax categorization",
5
+ "type": "module",
6
+ "main": "src/index.ts",
7
+ "openclaw": {
8
+ "extensions": ["./src/index.ts"]
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/fibuki/openclaw-plugin"
13
+ },
14
+ "keywords": ["openclaw", "fibuki", "tax", "accounting", "receipts", "invoices"],
15
+ "author": "FiBuKI",
16
+ "license": "MIT",
17
+ "scripts": {
18
+ "typecheck": "tsc --noEmit"
19
+ },
20
+ "devDependencies": {
21
+ "@types/node": "^20.0.0",
22
+ "typescript": "^5.9.0"
23
+ }
24
+ }
@@ -0,0 +1,97 @@
1
+ # FiBuKI Tax Accounting Guide
2
+
3
+ You are helping manage a FiBuKI tax accounting account. This guide explains the domain.
4
+
5
+ ## What is FiBuKI?
6
+
7
+ FiBuKI is a German tax accounting tool for small businesses and freelancers. It helps users:
8
+ - Import bank transactions (via CSV or Open Banking)
9
+ - Upload and match receipts/invoices to transactions
10
+ - Categorize transactions for tax purposes
11
+ - Track completion status for bookkeeping
12
+
13
+ ## Core Data Model
14
+
15
+ ### Sources (Bank Accounts)
16
+ - Represent bank accounts or credit cards
17
+ - Transactions are imported from sources
18
+ - Types: `bank_account`, `credit_card`
19
+ - Can be connected via CSV upload or Open Banking (GoCardless)
20
+
21
+ ### Transactions
22
+ - Individual bank movements (debits/credits)
23
+ - Have: date, amount (in cents!), name, partner
24
+ - **Cannot be individually deleted** (accounting integrity)
25
+ - Complete when they have a file OR a no-receipt category
26
+
27
+ ### Files (Receipts/Invoices)
28
+ - Uploaded PDFs or images
29
+ - AI extracts: amount, date, VAT, partner
30
+ - System suggests matching transactions (transactionSuggestions)
31
+ - Many-to-many relationship with transactions
32
+
33
+ ### Partners
34
+ - Companies or people the user transacts with
35
+ - Examples: "Amazon", "REWE", "Deutsche Telekom"
36
+ - System auto-detects partners from transaction names
37
+
38
+ ### No-Receipt Categories
39
+ - For transactions that don't need receipts
40
+ - Examples: Bank fees, Interest, Internal transfers, Payroll, Taxes
41
+ - Assigning a category marks the transaction complete
42
+
43
+ ## Transaction Completion Logic
44
+
45
+ A transaction is **complete** (isComplete=true) when:
46
+ 1. It has at least one connected file (fileIds.length > 0), OR
47
+ 2. It has a no-receipt category assigned (noReceiptCategoryId is set)
48
+
49
+ Your goal: Help the user get all transactions to complete status.
50
+
51
+ ## Common Workflows
52
+
53
+ ### 1. Review Incomplete Transactions
54
+ ```
55
+ list_transactions with isComplete=false
56
+ ```
57
+
58
+ ### 2. Match Files to Transactions
59
+ ```
60
+ 1. list_files with hasConnections=false (unmatched files)
61
+ 2. Look at transactionSuggestions on each file
62
+ 3. connect_file_to_transaction for good matches
63
+ 4. Or use auto_connect_file_suggestions for bulk matching
64
+ ```
65
+
66
+ ### 3. Categorize No-Receipt Transactions
67
+ ```
68
+ 1. list_no_receipt_categories (get available categories)
69
+ 2. assign_no_receipt_category for bank fees, transfers, etc.
70
+ ```
71
+
72
+ ### 4. Find Transactions Needing Receipts
73
+ ```
74
+ list_transactions_needing_files
75
+ ```
76
+ Returns transactions without files AND without no-receipt categories.
77
+
78
+ ## Amount Handling
79
+
80
+ **All amounts are in CENTS (integer)**
81
+ - 10.50 EUR = 1050
82
+ - -25.00 EUR = -2500 (negative = expense)
83
+ - When displaying to user, divide by 100
84
+
85
+ ## Date Handling
86
+
87
+ All dates are ISO 8601 format:
88
+ - `2024-01-15` for date-only
89
+ - `2024-01-15T10:30:00Z` for timestamps
90
+
91
+ ## Important Rules
92
+
93
+ 1. **Never delete individual transactions** - They must be deleted with their source
94
+ 2. **Amounts are in cents** - Always divide by 100 for display
95
+ 3. **Files can connect to multiple transactions** - Many-to-many relationship
96
+ 4. **Trust transactionSuggestions** - Server-side matching is accurate
97
+ 5. **High confidence = 85+** - Auto-connect suggestions above this threshold
package/src/index.ts ADDED
@@ -0,0 +1,287 @@
1
+ /**
2
+ * FiBuKI OpenClaw Plugin
3
+ *
4
+ * Exposes FiBuKI tools as OpenClaw agent tools via the FiBuKI HTTP API.
5
+ * Users authenticate with an API key generated in FiBuKI Settings.
6
+ */
7
+
8
+ const API_BASE_URL = "https://europe-west1-taxstudio-f12fb.cloudfunctions.net";
9
+
10
+ // OpenClaw plugin API types
11
+ interface OpenClawApi {
12
+ config: PluginConfig;
13
+ logger: {
14
+ info: (msg: string) => void;
15
+ error: (msg: string) => void;
16
+ debug: (msg: string) => void;
17
+ };
18
+ registerAgentTool: (tool: AgentTool) => void;
19
+ registerService: (service: Service) => void;
20
+ }
21
+
22
+ interface PluginConfig {
23
+ apiKey?: string;
24
+ }
25
+
26
+ interface AgentTool {
27
+ name: string;
28
+ description: string;
29
+ inputSchema: Record<string, unknown>;
30
+ handler: (args: Record<string, unknown>) => Promise<string>;
31
+ }
32
+
33
+ interface Service {
34
+ id: string;
35
+ start: () => void;
36
+ stop: () => void;
37
+ }
38
+
39
+ // Tool definitions with full documentation for Claude
40
+ const TOOL_DEFINITIONS: AgentTool[] = [
41
+ // ========== SOURCES ==========
42
+ {
43
+ name: "list_sources",
44
+ description: "List all bank accounts/sources for the user. Returns account names, IBANs, types (bank_account/credit_card), and currency.",
45
+ inputSchema: { type: "object", properties: {} },
46
+ handler: async () => "", // Placeholder, replaced at registration
47
+ },
48
+ {
49
+ name: "get_source",
50
+ description: "Get details of a specific bank account/source by ID.",
51
+ inputSchema: {
52
+ type: "object",
53
+ properties: {
54
+ sourceId: { type: "string", description: "The bank account/source ID" },
55
+ },
56
+ required: ["sourceId"],
57
+ },
58
+ handler: async () => "",
59
+ },
60
+
61
+ // ========== TRANSACTIONS ==========
62
+ {
63
+ name: "list_transactions",
64
+ description:
65
+ "List transactions with optional filters. Returns date, amount (in cents!), partner, description, completion status. Use isComplete=false to find incomplete transactions.",
66
+ inputSchema: {
67
+ type: "object",
68
+ properties: {
69
+ sourceId: { type: "string", description: "Filter by bank account ID" },
70
+ dateFrom: { type: "string", description: "Start date (ISO format: 2024-01-01)" },
71
+ dateTo: { type: "string", description: "End date (ISO format)" },
72
+ search: { type: "string", description: "Search in name, description, partner" },
73
+ isComplete: { type: "boolean", description: "Filter by completion status" },
74
+ limit: { type: "number", description: "Max results (default 50, max 100)" },
75
+ },
76
+ },
77
+ handler: async () => "",
78
+ },
79
+ {
80
+ name: "get_transaction",
81
+ description: "Get full details of a specific transaction including partner suggestions and file attachments.",
82
+ inputSchema: {
83
+ type: "object",
84
+ properties: {
85
+ transactionId: { type: "string", description: "The transaction ID" },
86
+ },
87
+ required: ["transactionId"],
88
+ },
89
+ handler: async () => "",
90
+ },
91
+ {
92
+ name: "update_transaction",
93
+ description: "Update a transaction's description or completion status. Use for adding tax-relevant notes.",
94
+ inputSchema: {
95
+ type: "object",
96
+ properties: {
97
+ transactionId: { type: "string", description: "The transaction ID" },
98
+ description: { type: "string", description: "Description for tax purposes" },
99
+ isComplete: { type: "boolean", description: "Mark as complete/incomplete" },
100
+ },
101
+ required: ["transactionId"],
102
+ },
103
+ handler: async () => "",
104
+ },
105
+
106
+ // ========== FILES ==========
107
+ {
108
+ name: "list_files",
109
+ description:
110
+ "List uploaded files (receipts/invoices) with match suggestions. Files have transactionSuggestions with confidence scores. Use hasConnections=false to find unmatched files.",
111
+ inputSchema: {
112
+ type: "object",
113
+ properties: {
114
+ hasConnections: { type: "boolean", description: "true = matched files, false = unmatched" },
115
+ hasSuggestions: { type: "boolean", description: "Filter by whether file has transaction suggestions" },
116
+ limit: { type: "number", description: "Max results (default 50)" },
117
+ },
118
+ },
119
+ handler: async () => "",
120
+ },
121
+ {
122
+ name: "get_file",
123
+ description: "Get full details of a file including extracted data (amount, date, partner) and transaction suggestions.",
124
+ inputSchema: {
125
+ type: "object",
126
+ properties: {
127
+ fileId: { type: "string", description: "The file ID" },
128
+ },
129
+ required: ["fileId"],
130
+ },
131
+ handler: async () => "",
132
+ },
133
+ {
134
+ name: "connect_file_to_transaction",
135
+ description:
136
+ "Connect a file (receipt) to a transaction. This marks the transaction as complete. Use when you've confirmed a file matches a transaction.",
137
+ inputSchema: {
138
+ type: "object",
139
+ properties: {
140
+ fileId: { type: "string", description: "The file ID to connect" },
141
+ transactionId: { type: "string", description: "The transaction ID to connect to" },
142
+ },
143
+ required: ["fileId", "transactionId"],
144
+ },
145
+ handler: async () => "",
146
+ },
147
+ {
148
+ name: "disconnect_file_from_transaction",
149
+ description: "Disconnect a file from a transaction. Use when a match was incorrect.",
150
+ inputSchema: {
151
+ type: "object",
152
+ properties: {
153
+ fileId: { type: "string", description: "The file ID" },
154
+ transactionId: { type: "string", description: "The transaction ID" },
155
+ },
156
+ required: ["fileId", "transactionId"],
157
+ },
158
+ handler: async () => "",
159
+ },
160
+ {
161
+ name: "list_transactions_needing_files",
162
+ description:
163
+ "Find transactions without receipts (no files connected AND no no-receipt category). These need action.",
164
+ inputSchema: {
165
+ type: "object",
166
+ properties: {
167
+ minAmount: { type: "number", description: "Minimum amount in cents (absolute value)" },
168
+ limit: { type: "number", description: "Max results (default 50)" },
169
+ },
170
+ },
171
+ handler: async () => "",
172
+ },
173
+ {
174
+ name: "auto_connect_file_suggestions",
175
+ description:
176
+ "Automatically connect files to transactions where suggestion confidence is above threshold. Great for bulk matching. Default threshold is 89%.",
177
+ inputSchema: {
178
+ type: "object",
179
+ properties: {
180
+ fileId: { type: "string", description: "Specific file ID, or omit for all unmatched files" },
181
+ minConfidence: { type: "number", description: "Minimum confidence 0-100 (default 89)" },
182
+ },
183
+ },
184
+ handler: async () => "",
185
+ },
186
+
187
+ // ========== CATEGORIES ==========
188
+ {
189
+ name: "list_no_receipt_categories",
190
+ description:
191
+ "List categories for transactions that don't need receipts: Bank fees, Interest, Internal transfers, Payroll, Taxes, etc.",
192
+ inputSchema: { type: "object", properties: {} },
193
+ handler: async () => "",
194
+ },
195
+ {
196
+ name: "assign_no_receipt_category",
197
+ description:
198
+ "Assign a no-receipt category to a transaction. This marks it complete without needing a file. Use for bank fees, interest, internal transfers, etc.",
199
+ inputSchema: {
200
+ type: "object",
201
+ properties: {
202
+ transactionId: { type: "string", description: "The transaction ID" },
203
+ categoryId: { type: "string", description: "The category ID to assign" },
204
+ },
205
+ required: ["transactionId", "categoryId"],
206
+ },
207
+ handler: async () => "",
208
+ },
209
+ {
210
+ name: "remove_no_receipt_category",
211
+ description: "Remove a no-receipt category from a transaction.",
212
+ inputSchema: {
213
+ type: "object",
214
+ properties: {
215
+ transactionId: { type: "string", description: "The transaction ID" },
216
+ },
217
+ required: ["transactionId"],
218
+ },
219
+ handler: async () => "",
220
+ },
221
+ ];
222
+
223
+ /**
224
+ * Call the FiBuKI MCP API
225
+ */
226
+ async function callApi(
227
+ apiKey: string,
228
+ tool: string,
229
+ args: Record<string, unknown>
230
+ ): Promise<string> {
231
+ const response = await fetch(`${API_BASE_URL}/mcpApi`, {
232
+ method: "POST",
233
+ headers: {
234
+ "Content-Type": "application/json",
235
+ Authorization: `Bearer ${apiKey}`,
236
+ },
237
+ body: JSON.stringify({ tool, arguments: args }),
238
+ });
239
+
240
+ const data = await response.json();
241
+
242
+ if (!response.ok || !data.success) {
243
+ throw new Error(data.error || `API error: ${response.status}`);
244
+ }
245
+
246
+ return JSON.stringify(data.result, null, 2);
247
+ }
248
+
249
+ /**
250
+ * Main plugin registration function
251
+ */
252
+ export default function register(api: OpenClawApi) {
253
+ const { config, logger } = api;
254
+
255
+ // Validate required config
256
+ if (!config.apiKey) {
257
+ logger.error("FiBuKI plugin requires apiKey in config. Generate one at Settings > Integrations > AI Agents");
258
+ return;
259
+ }
260
+
261
+ const apiKey = config.apiKey;
262
+ logger.info("FiBuKI plugin initializing...");
263
+
264
+ // Register all tools
265
+ for (const toolDef of TOOL_DEFINITIONS) {
266
+ api.registerAgentTool({
267
+ name: toolDef.name,
268
+ description: toolDef.description,
269
+ inputSchema: toolDef.inputSchema,
270
+ handler: async (args) => {
271
+ try {
272
+ return await callApi(apiKey, toolDef.name, args);
273
+ } catch (error) {
274
+ const msg = error instanceof Error ? error.message : "Unknown error";
275
+ return `Error: ${msg}`;
276
+ }
277
+ },
278
+ });
279
+ logger.debug(`Registered tool: ${toolDef.name}`);
280
+ }
281
+
282
+ logger.info(`FiBuKI plugin loaded with ${TOOL_DEFINITIONS.length} tools`);
283
+ }
284
+
285
+ // Export plugin metadata
286
+ export const id = "fibuki";
287
+ export const name = "FiBuKI Tax Studio";
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "esModuleInterop": true,
7
+ "strict": true,
8
+ "skipLibCheck": true,
9
+ "outDir": "dist",
10
+ "declaration": true,
11
+ "resolveJsonModule": true
12
+ },
13
+ "include": ["src/**/*"]
14
+ }