@fuzzle/opencode-accountant 0.10.7 → 0.10.8-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +74 -13
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2739,6 +2739,19 @@ var init_agentLoader = __esm(() => {
2739
2739
  ]);
2740
2740
  });
2741
2741
 
2742
+ // src/utils/journalMatchers.ts
2743
+ function extractAccount(line, pattern) {
2744
+ const match = line.match(pattern);
2745
+ return match ? match[1].trim() : null;
2746
+ }
2747
+ var JOURNAL_ACCOUNT_DECL, RULES_ACCOUNT_DIRECTIVE, RULES_ACCOUNT2_DIRECTIVE, TX_HEADER_PATTERN;
2748
+ var init_journalMatchers = __esm(() => {
2749
+ JOURNAL_ACCOUNT_DECL = /^account\s+(.+)$/;
2750
+ RULES_ACCOUNT_DIRECTIVE = /^account\d+\s+(.+)$/;
2751
+ RULES_ACCOUNT2_DIRECTIVE = /^\s*account2\s+(.+)$/;
2752
+ TX_HEADER_PATTERN = /^(\d{4})-(\d{2}-\d{2})(\s+(.+))?$/;
2753
+ });
2754
+
2742
2755
  // node_modules/papaparse/papaparse.js
2743
2756
  var require_papaparse = __commonJS((exports, module) => {
2744
2757
  (function(root, factory) {
@@ -4287,9 +4300,9 @@ function loadExistingAccounts(yearJournalPath) {
4287
4300
  for (const line of lines) {
4288
4301
  const trimmed = line.trim();
4289
4302
  if (trimmed.startsWith("account ")) {
4290
- const match2 = trimmed.match(/^account\s+(.+?)(?:\s+|$)/);
4291
- if (match2) {
4292
- accounts.push(match2[1].trim());
4303
+ const accountName = extractAccount(trimmed, JOURNAL_ACCOUNT_DECL);
4304
+ if (accountName) {
4305
+ accounts.push(accountName);
4293
4306
  }
4294
4307
  }
4295
4308
  }
@@ -4314,11 +4327,11 @@ function extractRulePatternsFromFile(rulesPath) {
4314
4327
  currentCondition = ifMatch[1].trim();
4315
4328
  continue;
4316
4329
  }
4317
- const account2Match = trimmed.match(/^\s*account2\s+(.+?)(?:\s+|$)/);
4318
- if (account2Match && currentCondition) {
4330
+ const account2Name = extractAccount(trimmed, RULES_ACCOUNT2_DIRECTIVE);
4331
+ if (account2Name && currentCondition) {
4319
4332
  patterns.push({
4320
4333
  condition: currentCondition,
4321
- account: account2Match[1].trim()
4334
+ account: account2Name
4322
4335
  });
4323
4336
  currentCondition = null;
4324
4337
  continue;
@@ -4504,6 +4517,7 @@ function generateMockSuggestions(postings) {
4504
4517
  var EXAMPLE_PATTERN_SAMPLE_SIZE = 10, suggestionCache, RESPONSE_FORMAT_SECTION;
4505
4518
  var init_accountSuggester = __esm(() => {
4506
4519
  init_agentLoader();
4520
+ init_journalMatchers();
4507
4521
  suggestionCache = {};
4508
4522
  RESPONSE_FORMAT_SECTION = [
4509
4523
  `## Task
@@ -16998,6 +17012,7 @@ function ensureDirectory(dirPath) {
16998
17012
  }
16999
17013
 
17000
17014
  // src/utils/journalUtils.ts
17015
+ init_journalMatchers();
17001
17016
  function extractDateFromPriceLine(line) {
17002
17017
  return line.split(" ")[1];
17003
17018
  }
@@ -17083,6 +17098,37 @@ function ensureCommodityDeclarations(commodityJournalPath, symbols, logger) {
17083
17098
  logger?.info(`Commodity declarations: added ${missing.length} (${missing.join(", ")})`);
17084
17099
  return { added: missing.sort(), updated: true };
17085
17100
  }
17101
+ function ensureInvestmentAccountDeclarations(accountJournalPath, accounts, logger) {
17102
+ const existing = new Set;
17103
+ if (fs4.existsSync(accountJournalPath)) {
17104
+ const content2 = fs4.readFileSync(accountJournalPath, "utf-8");
17105
+ for (const line of content2.split(`
17106
+ `)) {
17107
+ const match = line.trim().match(JOURNAL_ACCOUNT_DECL);
17108
+ if (match) {
17109
+ existing.add(match[1]);
17110
+ }
17111
+ }
17112
+ }
17113
+ const missing = [];
17114
+ for (const account of accounts) {
17115
+ if (!existing.has(account)) {
17116
+ missing.push(account);
17117
+ existing.add(account);
17118
+ }
17119
+ }
17120
+ if (missing.length === 0) {
17121
+ return { added: [], updated: false };
17122
+ }
17123
+ const sorted = Array.from(existing).sort((a, b) => a.localeCompare(b));
17124
+ const content = sorted.map((a) => `account ${a}`).join(`
17125
+ `) + `
17126
+ `;
17127
+ ensureDirectory(path3.dirname(accountJournalPath));
17128
+ fs4.writeFileSync(accountJournalPath, content);
17129
+ logger?.info(`Account declarations: added ${missing.length} (${missing.join(", ")})`);
17130
+ return { added: missing.sort(), updated: true };
17131
+ }
17086
17132
 
17087
17133
  // src/utils/dateUtils.ts
17088
17134
  function formatDateISO(date5) {
@@ -23123,7 +23169,7 @@ function findRulesForCsv(csvPath, mapping) {
23123
23169
 
23124
23170
  // src/utils/hledgerExecutor.ts
23125
23171
  var {$: $2 } = globalThis.Bun;
23126
- var TX_HEADER_PATTERN = /^(\d{4})-(\d{2}-\d{2})(\s+(.+))?$/;
23172
+ init_journalMatchers();
23127
23173
  async function defaultHledgerExecutor(cmdArgs) {
23128
23174
  try {
23129
23175
  const result = await $2`hledger ${cmdArgs}`.quiet().nothrow();
@@ -24150,6 +24196,7 @@ import * as fs20 from "fs";
24150
24196
  import * as path14 from "path";
24151
24197
 
24152
24198
  // src/utils/accountDeclarations.ts
24199
+ init_journalMatchers();
24153
24200
  import * as fs12 from "fs";
24154
24201
  function extractAccountsFromRulesFile(rulesPath) {
24155
24202
  const accounts = new Set;
@@ -24164,9 +24211,9 @@ function extractAccountsFromRulesFile(rulesPath) {
24164
24211
  if (trimmed.startsWith("#") || trimmed.startsWith(";") || trimmed === "") {
24165
24212
  continue;
24166
24213
  }
24167
- const accountMatch = trimmed.match(/^account\d+\s+(.+?)(?:\s+|$)/);
24168
- if (accountMatch) {
24169
- accounts.add(accountMatch[1].trim());
24214
+ const accountName = extractAccount(trimmed, RULES_ACCOUNT_DIRECTIVE);
24215
+ if (accountName) {
24216
+ accounts.add(accountName);
24170
24217
  continue;
24171
24218
  }
24172
24219
  }
@@ -24201,9 +24248,9 @@ function parseJournalSections(content) {
24201
24248
  }
24202
24249
  if (trimmed.startsWith("account ")) {
24203
24250
  inAccountSection = true;
24204
- const accountMatch = trimmed.match(/^account\s+(.+?)(?:\s+|$)/);
24205
- if (accountMatch) {
24206
- existingAccounts.add(accountMatch[1].trim());
24251
+ const accountName = extractAccount(trimmed, JOURNAL_ACCOUNT_DECL);
24252
+ if (accountName) {
24253
+ existingAccounts.add(accountName);
24207
24254
  }
24208
24255
  continue;
24209
24256
  }
@@ -25815,6 +25862,20 @@ async function preprocessSwissquote(csvPath, projectDir, currency, year, lotInve
25815
25862
  if (stockSymbols.size > 0) {
25816
25863
  const commodityJournalPath = path13.join(projectDir, "ledger", "investments", "commodities.journal");
25817
25864
  ensureCommodityDeclarations(commodityJournalPath, stockSymbols, logger);
25865
+ const accountJournalPath = path13.join(projectDir, "ledger", "investments", "accounts.journal");
25866
+ const investmentAccounts = new Set;
25867
+ for (const symbol2 of stockSymbols) {
25868
+ investmentAccounts.add(`assets:investments:stocks:${symbol2}`);
25869
+ investmentAccounts.add(`income:dividends:${symbol2}`);
25870
+ }
25871
+ investmentAccounts.add(`assets:broker:swissquote:${currency.toLowerCase()}`);
25872
+ investmentAccounts.add("expenses:fees:trading:swissquote");
25873
+ investmentAccounts.add("expenses:taxes:withholding");
25874
+ investmentAccounts.add("income:capital-gains:realized");
25875
+ investmentAccounts.add("income:capital-gains:rights-distribution");
25876
+ investmentAccounts.add("expenses:losses:capital");
25877
+ investmentAccounts.add("equity:conversion");
25878
+ ensureInvestmentAccountDeclarations(accountJournalPath, investmentAccounts, logger);
25818
25879
  }
25819
25880
  logger?.logResult({
25820
25881
  totalRows: stats.totalRows,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fuzzle/opencode-accountant",
3
- "version": "0.10.7",
3
+ "version": "0.10.8-next.1",
4
4
  "description": "An OpenCode accounting agent, specialized in double-entry-bookkepping with hledger",
5
5
  "author": {
6
6
  "name": "ali bengali",