@fuzzle/opencode-accountant 0.4.6-next.1 → 0.4.6

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.
@@ -18,8 +18,6 @@ This tool is **restricted to the accountant agent only**.
18
18
  - `{paths.pending}` = `import/pending`
19
19
  - `{paths.unrecognized}` = `import/unrecognized`
20
20
 
21
- **Note on Context IDs:** Each classified file receives a unique `contextId` (UUID). This ID references an import context file stored in `.memory/{uuid}.json` that tracks the file's metadata and progress through the import pipeline. The context is used by subsequent tools (`import-statements`, `reconcile-statement`) to locate files and retrieve metadata. See [Import Context Architecture](../architecture/import-context.md) for details.
22
-
23
21
  ### Success - All Files Classified
24
22
 
25
23
  When all CSV files are successfully classified:
@@ -32,15 +30,13 @@ When all CSV files are successfully classified:
32
30
  "filename": "transactions-ubs-2026-02.csv",
33
31
  "provider": "ubs",
34
32
  "currency": "chf",
35
- "targetPath": "{paths.pending}/ubs/chf/transactions-ubs-2026-02.csv",
36
- "contextId": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
33
+ "targetPath": "{paths.pending}/ubs/chf/transactions-ubs-2026-02.csv"
37
34
  },
38
35
  {
39
36
  "filename": "account-statement_2026-02.csv",
40
37
  "provider": "revolut",
41
38
  "currency": "eur",
42
- "targetPath": "{paths.pending}/revolut/eur/account-statement_2026-02.csv",
43
- "contextId": "8b3e9c21-1a4f-4d89-b123-9f8e7d6c5b4a"
39
+ "targetPath": "{paths.pending}/revolut/eur/account-statement_2026-02.csv"
44
40
  }
45
41
  ],
46
42
  "unrecognized": [],
@@ -65,8 +61,7 @@ When provider config includes `renamePattern` with metadata extraction:
65
61
  "originalFilename": "export.csv",
66
62
  "provider": "ubs",
67
63
  "currency": "chf",
68
- "targetPath": "{paths.pending}/ubs/chf/transactions-ubs-0235-90250546.csv",
69
- "contextId": "a1b2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6"
64
+ "targetPath": "{paths.pending}/ubs/chf/transactions-ubs-0235-90250546.csv"
70
65
  }
71
66
  ],
72
67
  "unrecognized": [],
@@ -92,8 +87,7 @@ When some files cannot be classified:
92
87
  "filename": "transactions-ubs-2026-02.csv",
93
88
  "provider": "ubs",
94
89
  "currency": "chf",
95
- "targetPath": "{paths.pending}/ubs/chf/transactions-ubs-2026-02.csv",
96
- "contextId": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
90
+ "targetPath": "{paths.pending}/ubs/chf/transactions-ubs-2026-02.csv"
97
91
  }
98
92
  ],
99
93
  "unrecognized": [
@@ -213,74 +207,13 @@ ubs:
213
207
 
214
208
  This extracts metadata from the CSV (e.g., account number from row 0, column 1) and uses it in the output filename.
215
209
 
216
- ## Import Context
217
-
218
- Each classified file gets an **import context** - a JSON file stored in `.memory/{contextId}.json` that tracks the file's metadata and progress through the import pipeline.
219
-
220
- ### What Gets Stored in the Context
221
-
222
- When a CSV is classified, the context is created with:
223
-
224
- - **File tracking**: filename, file path, original filename (if renamed)
225
- - **Provider detection**: provider, currency, account number
226
- - **CSV metadata**: transaction date range (from-date, until-date), opening/closing balances
227
- - **Timestamps**: creation and last update times
228
-
229
- ### Example Context File
230
-
231
- `.memory/f47ac10b-58cc-4372-a567-0e02b2c3d479.json`:
232
-
233
- ```json
234
- {
235
- "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
236
- "createdAt": "2026-02-28T10:30:00.000Z",
237
- "updatedAt": "2026-02-28T10:30:00.000Z",
238
-
239
- "filename": "ubs-0235-90250546.1-transactions-2026-02-22-to-2026-02-24.csv",
240
- "filePath": "import/pending/ubs/chf/ubs-0235-90250546.1-transactions-2026-02-22-to-2026-02-24.csv",
241
- "originalFilename": "transactions-0235-90250546.1-2026-02.csv",
242
-
243
- "provider": "ubs",
244
- "currency": "chf",
245
- "accountNumber": "0235-90250546.1",
246
-
247
- "fromDate": "2026-02-22",
248
- "untilDate": "2026-02-24",
249
- "openingBalance": "4001.55",
250
- "closingBalance": "9001.55"
251
- }
252
- ```
253
-
254
- ### Context Lifecycle
255
-
256
- 1. **Created by classify-statements**: Initial context with provider/currency/metadata
257
- 2. **Updated by import-statements**: Adds rules file, year journal, transaction count
258
- 3. **Updated by reconcile-statement**: Adds reconciliation results
259
- 4. **Persisted**: Remains in `.memory/` for audit/debugging
260
-
261
- ### Why Context IDs Matter
262
-
263
- Context IDs solve the **multi-account problem**: when you have multiple accounts from the same provider/currency (e.g., UBS checking `.0` and savings `.1`), the context ID ensures each file is tracked independently and reconciled against the correct account.
264
-
265
- **Without contexts**: Tools would select CSVs by timestamp → wrong account reconciled ❌
266
-
267
- **With contexts**: Each CSV has an `accountNumber` in its context → correct account reconciled ✓
268
-
269
- See [Import Context Architecture](../architecture/import-context.md) for complete technical details.
270
-
271
210
  ## Directory Structure
272
211
 
273
212
  ```
274
213
  your-project/
275
- ├── .memory/ # Import context files (created by classify-statements)
276
- │ ├── f47ac10b-58cc-4372-a567-0e02b2c3d479.json # Context for UBS checking
277
- │ ├── 8b3e9c21-1a4f-4d89-b123-9f8e7d6c5b4a.json # Context for UBS savings
278
- │ └── a1b2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6.json # Context for Revolut EUR
279
-
280
214
  ├── config/
281
215
  │ └── import/
282
216
  │ └── providers.yaml # Defines all paths and detection rules
283
-
284
217
  ├── {paths.import}/ # Drop CSV files here (default: import/incoming)
285
218
  │ ├── bank1.csv
286
219
  │ └── bank2.csv
@@ -291,8 +224,7 @@ your-project/
291
224
  │ │ └── classified.csv
292
225
  │ ├── ubs/
293
226
  │ │ └── chf/
294
- │ │ ├── ubs-0235-90250546.0-transactions-2026-02.csv # Checking
295
- │ │ └── ubs-0235-90250546.1-transactions-2026-02.csv # Savings
227
+ │ │ └── transactions-ubs-0235-90250546.csv
296
228
  │ └── revolut/
297
229
  │ └── eur/
298
230
  │ └── account-statement_2026-02.csv
@@ -301,13 +233,6 @@ your-project/
301
233
  └── mystery-bank.csv
302
234
  ```
303
235
 
304
- **Note on `.memory/` directory:**
305
-
306
- - Contains import context JSON files (one per classified CSV)
307
- - Each context tracks metadata and progress through the pipeline
308
- - Files persist for audit/debugging (not auto-deleted)
309
- - Directory is gitignored (contexts are local/temporary)
310
-
311
236
  ## Typical Workflow
312
237
 
313
238
  ### Scenario 1: Successful Classification
@@ -315,10 +240,8 @@ your-project/
315
240
  1. Drop CSV files into `{paths.import}/` (e.g., `import/incoming/`)
316
241
  2. Run `classify-statements` tool (no arguments)
317
242
  3. Check output - all files classified successfully
318
- 4. **Each file gets a unique contextId** stored in `.memory/{uuid}.json`
319
- 5. Files organized in `{paths.pending}/<provider>/<currency>/`
320
- 6. **Context IDs are passed automatically to subsequent steps** when using `import-pipeline`
321
- 7. Proceed to `import-statements` or `import-pipeline` tool
243
+ 4. Files organized in `{paths.pending}/<provider>/<currency>/`
244
+ 5. Proceed to `import-statements` tool
322
245
 
323
246
  ### Scenario 2: Handling Unrecognized Files
324
247
 
@@ -5,8 +5,6 @@ The `import-statements` tool imports classified CSV bank statements into hledger
5
5
  - **Check mode** (`checkOnly: true`, default): Validates transactions and reports any that cannot be categorized
6
6
  - **Import mode** (`checkOnly: false`): Imports validated transactions and moves processed files to the done directory
7
7
 
8
- **Important**: This tool requires a `contextId` from a prior `classify-statements` run. The context provides the file path and metadata needed for import. See [Import Context Architecture](../architecture/import-context.md) for details.
9
-
10
8
  ## Year-Based Journal Routing
11
9
 
12
10
  Transactions are automatically routed to year-specific journal files based on transaction dates:
@@ -21,47 +19,13 @@ Transactions are automatically routed to year-specific journal files based on tr
21
19
 
22
20
  **Constraint:** Each CSV file must contain transactions from a single year. CSVs with transactions spanning multiple years are rejected during check mode with an error message listing the years found.
23
21
 
24
- ## Using Context IDs
25
-
26
- The tool uses import contexts to locate CSV files and access metadata:
27
-
28
- ### How It Works
29
-
30
- 1. **classify-statements** creates a context for each CSV with a unique ID
31
- 2. **import-statements** receives the contextId (via import-pipeline or manual invocation)
32
- 3. Tool loads the context from `.memory/{contextId}.json`
33
- 4. Context provides the file path to the CSV (no need to search by provider/currency)
34
- 5. After import, tool updates context with results (rules file, year journal, transaction count)
35
-
36
- ### Manual Invocation Example
37
-
38
- ```bash
39
- # Step 1: Classify statements
40
- classify-statements
41
- # Output: { "classified": [{ "contextId": "abc123-...", ... }] }
42
-
43
- # Step 2: Import using contextId
44
- import-statements --contextId "abc123-..." --checkOnly false
45
- ```
46
-
47
- ### Automatic Invocation via Pipeline
48
-
49
- When using `import-pipeline`, context IDs are passed automatically:
50
-
51
- ```bash
52
- # Pipeline handles everything
53
- import-pipeline
54
- # Internally: classify → get contextIds → import each context → reconcile each context
55
- ```
56
-
57
22
  ## Arguments
58
23
 
59
- | Argument | Type | Required | Default | Description |
60
- | ----------- | ------- | -------- | ------- | -------------------------------------------------- |
61
- | `contextId` | string | Yes | - | Context ID from `classify-statements` (e.g., UUID) |
62
- | `checkOnly` | boolean | No | `true` | If true, only validate without importing |
63
-
64
- **Note**: When called via `import-pipeline`, the `contextId` is passed automatically. For manual invocation, get the `contextId` from `classify-statements` output.
24
+ | Argument | Type | Default | Description |
25
+ | ----------- | ------- | ------- | ------------------------------------------- |
26
+ | `provider` | string | - | Filter by provider (e.g., `revolut`, `ubs`) |
27
+ | `currency` | string | - | Filter by currency (e.g., `chf`, `eur`) |
28
+ | `checkOnly` | boolean | `true` | If true, only validate without importing |
65
29
 
66
30
  ## Output Format
67
31
 
@@ -97,8 +61,6 @@ When all transactions have matching rules:
97
61
  }
98
62
  ```
99
63
 
100
- **Note**: When invoked via `import-pipeline`, the CSV file path comes from the import context (loaded via `contextId`). The context also provides metadata like account number and closing balance.
101
-
102
64
  ### Check Mode - Unknown Postings Found
103
65
 
104
66
  When transactions don't match any `if` pattern in the rules file, the tool returns the full CSV row data for each unknown posting to provide context for classification:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fuzzle/opencode-accountant",
3
- "version": "0.4.6-next.1",
3
+ "version": "0.4.6",
4
4
  "description": "An OpenCode accounting agent, specialized in double-entry-bookkepping with hledger",
5
5
  "author": {
6
6
  "name": "ali bengali",
@@ -28,7 +28,8 @@
28
28
  "docs"
29
29
  ],
30
30
  "dependencies": {
31
- "@opencode-ai/plugin": "^1.2.6",
31
+ "@opencode-ai/plugin": "latest",
32
+ "convert-csv-to-json": "^3.20.0",
32
33
  "glob": "^10.3.10",
33
34
  "js-yaml": "^4.1.0",
34
35
  "minimatch": "^9.0.3",
@@ -43,7 +44,7 @@
43
44
  "@types/uuid": "^11.0.0",
44
45
  "@typescript-eslint/eslint-plugin": "8.47.0",
45
46
  "@typescript-eslint/parser": "8.47.0",
46
- "bun-types": "^1.3.9",
47
+ "bun-types": "latest",
47
48
  "eslint": "^9.39.1",
48
49
  "eslint-config-prettier": "10.1.8",
49
50
  "eslint-plugin-prettier": "^5.1.3",