@fuzzle/opencode-accountant 0.1.1-next.1 → 0.1.2
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/dist/index.js +198 -178
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -17679,6 +17679,18 @@ function isInWorktree(directory) {
|
|
|
17679
17679
|
return false;
|
|
17680
17680
|
}
|
|
17681
17681
|
}
|
|
17682
|
+
async function withWorktree(directory, operation) {
|
|
17683
|
+
let createdWorktree = null;
|
|
17684
|
+
try {
|
|
17685
|
+
createdWorktree = createImportWorktree(directory);
|
|
17686
|
+
const result = await operation(createdWorktree);
|
|
17687
|
+
return result;
|
|
17688
|
+
} finally {
|
|
17689
|
+
if (createdWorktree) {
|
|
17690
|
+
removeWorktree(createdWorktree, true);
|
|
17691
|
+
}
|
|
17692
|
+
}
|
|
17693
|
+
}
|
|
17682
17694
|
|
|
17683
17695
|
// src/utils/fileUtils.ts
|
|
17684
17696
|
import * as fs5 from "fs";
|
|
@@ -18635,9 +18647,10 @@ function determineClosingBalance(csvFile, config2, options, relativeCsvPath) {
|
|
|
18635
18647
|
}
|
|
18636
18648
|
let closingBalance = options.closingBalance;
|
|
18637
18649
|
if (!closingBalance && metadata?.closing_balance) {
|
|
18638
|
-
|
|
18639
|
-
|
|
18640
|
-
|
|
18650
|
+
const { closing_balance, currency } = metadata;
|
|
18651
|
+
closingBalance = closing_balance;
|
|
18652
|
+
if (currency && !closingBalance.includes(currency)) {
|
|
18653
|
+
closingBalance = `${currency} ${closingBalance}`;
|
|
18641
18654
|
}
|
|
18642
18655
|
}
|
|
18643
18656
|
if (!closingBalance) {
|
|
@@ -18676,7 +18689,7 @@ function determineAccount(csvFile, rulesDir, options, relativeCsvPath, metadata)
|
|
|
18676
18689
|
}
|
|
18677
18690
|
return { account };
|
|
18678
18691
|
}
|
|
18679
|
-
async function
|
|
18692
|
+
async function reconcileStatement(directory, agent, options, configLoader = loadImportConfig, hledgerExecutor = defaultHledgerExecutor, worktreeChecker = isInWorktree) {
|
|
18680
18693
|
const restrictionError = checkAccountantAgent(agent, "reconcile statement");
|
|
18681
18694
|
if (restrictionError) {
|
|
18682
18695
|
return restrictionError;
|
|
@@ -18807,7 +18820,7 @@ It must be run inside an import worktree (use import-pipeline for the full workf
|
|
|
18807
18820
|
},
|
|
18808
18821
|
async execute(params, context) {
|
|
18809
18822
|
const { directory, agent } = context;
|
|
18810
|
-
return
|
|
18823
|
+
return reconcileStatement(directory, agent, {
|
|
18811
18824
|
provider: params.provider,
|
|
18812
18825
|
currency: params.currency,
|
|
18813
18826
|
closingBalance: params.closingBalance,
|
|
@@ -18816,34 +18829,157 @@ It must be run inside an import worktree (use import-pipeline for the full workf
|
|
|
18816
18829
|
}
|
|
18817
18830
|
});
|
|
18818
18831
|
// src/tools/import-pipeline.ts
|
|
18819
|
-
|
|
18820
|
-
|
|
18821
|
-
|
|
18822
|
-
|
|
18823
|
-
fromDate: parsed.metadata?.from_date,
|
|
18824
|
-
untilDate: parsed.metadata?.until_date,
|
|
18825
|
-
transactionCount: undefined
|
|
18826
|
-
};
|
|
18827
|
-
} catch {
|
|
18828
|
-
return {};
|
|
18832
|
+
class NoTransactionsError extends Error {
|
|
18833
|
+
constructor() {
|
|
18834
|
+
super("No transactions to import");
|
|
18835
|
+
this.name = "NoTransactionsError";
|
|
18829
18836
|
}
|
|
18830
18837
|
}
|
|
18831
|
-
function
|
|
18832
|
-
|
|
18833
|
-
|
|
18834
|
-
|
|
18835
|
-
}
|
|
18836
|
-
|
|
18838
|
+
function buildStepResult(success2, message, details) {
|
|
18839
|
+
const result = { success: success2, message };
|
|
18840
|
+
if (details !== undefined) {
|
|
18841
|
+
result.details = details;
|
|
18842
|
+
}
|
|
18843
|
+
return result;
|
|
18844
|
+
}
|
|
18845
|
+
function buildSuccessResult5(result, summary) {
|
|
18846
|
+
result.success = true;
|
|
18847
|
+
result.summary = summary;
|
|
18848
|
+
return JSON.stringify(result);
|
|
18849
|
+
}
|
|
18850
|
+
function buildErrorResult5(result, error45, hint) {
|
|
18851
|
+
result.success = false;
|
|
18852
|
+
result.error = error45;
|
|
18853
|
+
if (hint) {
|
|
18854
|
+
result.hint = hint;
|
|
18837
18855
|
}
|
|
18856
|
+
return JSON.stringify(result);
|
|
18838
18857
|
}
|
|
18839
18858
|
function buildCommitMessage(provider, currency, fromDate, untilDate, transactionCount) {
|
|
18840
18859
|
const providerStr = provider?.toUpperCase() || "statements";
|
|
18841
|
-
const currencyStr = currency?.toUpperCase()
|
|
18860
|
+
const currencyStr = currency?.toUpperCase();
|
|
18842
18861
|
const dateRange = fromDate && untilDate ? ` ${fromDate} to ${untilDate}` : "";
|
|
18843
18862
|
const txStr = transactionCount > 0 ? ` (${transactionCount} transactions)` : "";
|
|
18844
|
-
|
|
18863
|
+
const parts = ["Import:", providerStr];
|
|
18864
|
+
if (currencyStr) {
|
|
18865
|
+
parts.push(currencyStr);
|
|
18866
|
+
}
|
|
18867
|
+
return `${parts.join(" ")}${dateRange}${txStr}`;
|
|
18845
18868
|
}
|
|
18846
|
-
async function
|
|
18869
|
+
async function executeClassifyStep(context, worktree) {
|
|
18870
|
+
if (context.options.skipClassify) {
|
|
18871
|
+
context.result.steps.classify = buildStepResult(true, "Classification skipped (skipClassify: true)");
|
|
18872
|
+
return;
|
|
18873
|
+
}
|
|
18874
|
+
const inWorktree = () => true;
|
|
18875
|
+
const classifyResult = await classifyStatements(worktree.path, context.agent, context.configLoader, inWorktree);
|
|
18876
|
+
const classifyParsed = JSON.parse(classifyResult);
|
|
18877
|
+
const success2 = classifyParsed.success !== false;
|
|
18878
|
+
let message = success2 ? "Classification complete" : "Classification had issues";
|
|
18879
|
+
if (classifyParsed.unrecognized?.length > 0) {
|
|
18880
|
+
message = `Classification complete with ${classifyParsed.unrecognized.length} unrecognized file(s)`;
|
|
18881
|
+
}
|
|
18882
|
+
const details = {
|
|
18883
|
+
success: success2,
|
|
18884
|
+
unrecognized: classifyParsed.unrecognized,
|
|
18885
|
+
classified: classifyParsed
|
|
18886
|
+
};
|
|
18887
|
+
context.result.steps.classify = buildStepResult(success2, message, details);
|
|
18888
|
+
}
|
|
18889
|
+
async function executeDryRunStep(context, worktree) {
|
|
18890
|
+
const inWorktree = () => true;
|
|
18891
|
+
const dryRunResult = await importStatements(worktree.path, context.agent, {
|
|
18892
|
+
provider: context.options.provider,
|
|
18893
|
+
currency: context.options.currency,
|
|
18894
|
+
checkOnly: true
|
|
18895
|
+
}, context.configLoader, context.hledgerExecutor, inWorktree);
|
|
18896
|
+
const dryRunParsed = JSON.parse(dryRunResult);
|
|
18897
|
+
const message = dryRunParsed.success ? `Dry run passed: ${dryRunParsed.summary?.totalTransactions || 0} transactions ready` : `Dry run failed: ${dryRunParsed.summary?.unknown || 0} unknown account(s)`;
|
|
18898
|
+
context.result.steps.dryRun = buildStepResult(dryRunParsed.success, message, {
|
|
18899
|
+
success: dryRunParsed.success,
|
|
18900
|
+
summary: dryRunParsed.summary
|
|
18901
|
+
});
|
|
18902
|
+
if (!dryRunParsed.success) {
|
|
18903
|
+
context.result.error = "Dry run found unknown accounts or errors";
|
|
18904
|
+
context.result.hint = "Add rules to categorize unknown transactions, then retry";
|
|
18905
|
+
throw new Error("Dry run failed");
|
|
18906
|
+
}
|
|
18907
|
+
if (dryRunParsed.summary?.totalTransactions === 0) {
|
|
18908
|
+
throw new NoTransactionsError;
|
|
18909
|
+
}
|
|
18910
|
+
}
|
|
18911
|
+
async function executeImportStep(context, worktree) {
|
|
18912
|
+
const inWorktree = () => true;
|
|
18913
|
+
const importResult = await importStatements(worktree.path, context.agent, {
|
|
18914
|
+
provider: context.options.provider,
|
|
18915
|
+
currency: context.options.currency,
|
|
18916
|
+
checkOnly: false
|
|
18917
|
+
}, context.configLoader, context.hledgerExecutor, inWorktree);
|
|
18918
|
+
const importParsed = JSON.parse(importResult);
|
|
18919
|
+
const message = importParsed.success ? `Imported ${importParsed.summary?.totalTransactions || 0} transactions` : `Import failed: ${importParsed.error || "Unknown error"}`;
|
|
18920
|
+
context.result.steps.import = buildStepResult(importParsed.success, message, {
|
|
18921
|
+
success: importParsed.success,
|
|
18922
|
+
summary: importParsed.summary,
|
|
18923
|
+
error: importParsed.error
|
|
18924
|
+
});
|
|
18925
|
+
if (!importParsed.success) {
|
|
18926
|
+
context.result.error = `Import failed: ${importParsed.error || "Unknown error"}`;
|
|
18927
|
+
throw new Error("Import failed");
|
|
18928
|
+
}
|
|
18929
|
+
}
|
|
18930
|
+
async function executeReconcileStep(context, worktree) {
|
|
18931
|
+
const inWorktree = () => true;
|
|
18932
|
+
const reconcileResult = await reconcileStatement(worktree.path, context.agent, {
|
|
18933
|
+
provider: context.options.provider,
|
|
18934
|
+
currency: context.options.currency,
|
|
18935
|
+
closingBalance: context.options.closingBalance,
|
|
18936
|
+
account: context.options.account
|
|
18937
|
+
}, context.configLoader, context.hledgerExecutor, inWorktree);
|
|
18938
|
+
const reconcileParsed = JSON.parse(reconcileResult);
|
|
18939
|
+
const message = reconcileParsed.success ? `Balance reconciled: ${reconcileParsed.actualBalance}` : `Balance mismatch: expected ${reconcileParsed.expectedBalance}, got ${reconcileParsed.actualBalance}`;
|
|
18940
|
+
context.result.steps.reconcile = buildStepResult(reconcileParsed.success, message, {
|
|
18941
|
+
success: reconcileParsed.success,
|
|
18942
|
+
actualBalance: reconcileParsed.actualBalance,
|
|
18943
|
+
expectedBalance: reconcileParsed.expectedBalance,
|
|
18944
|
+
metadata: reconcileParsed.metadata,
|
|
18945
|
+
error: reconcileParsed.error
|
|
18946
|
+
});
|
|
18947
|
+
if (!reconcileParsed.success) {
|
|
18948
|
+
context.result.error = `Reconciliation failed: ${reconcileParsed.error || "Balance mismatch"}`;
|
|
18949
|
+
context.result.hint = "Check for missing transactions or incorrect rules";
|
|
18950
|
+
throw new Error("Reconciliation failed");
|
|
18951
|
+
}
|
|
18952
|
+
}
|
|
18953
|
+
async function executeMergeStep(context, worktree) {
|
|
18954
|
+
const importDetails = context.result.steps.import?.details;
|
|
18955
|
+
const reconcileDetails = context.result.steps.reconcile?.details;
|
|
18956
|
+
if (!importDetails || !reconcileDetails) {
|
|
18957
|
+
throw new Error("Import or reconcile step not completed before merge");
|
|
18958
|
+
}
|
|
18959
|
+
const commitInfo = {
|
|
18960
|
+
fromDate: reconcileDetails.metadata?.from_date,
|
|
18961
|
+
untilDate: reconcileDetails.metadata?.until_date
|
|
18962
|
+
};
|
|
18963
|
+
const transactionCount = importDetails.summary?.totalTransactions || 0;
|
|
18964
|
+
const commitMessage = buildCommitMessage(context.options.provider, context.options.currency, commitInfo.fromDate, commitInfo.untilDate, transactionCount);
|
|
18965
|
+
try {
|
|
18966
|
+
mergeWorktree(worktree, commitMessage);
|
|
18967
|
+
const mergeDetails = { commitMessage };
|
|
18968
|
+
context.result.steps.merge = buildStepResult(true, `Merged to main: "${commitMessage}"`, mergeDetails);
|
|
18969
|
+
} catch (error45) {
|
|
18970
|
+
const message = `Merge failed: ${error45 instanceof Error ? error45.message : String(error45)}`;
|
|
18971
|
+
context.result.steps.merge = buildStepResult(false, message);
|
|
18972
|
+
context.result.error = "Merge to main branch failed";
|
|
18973
|
+
throw new Error("Merge failed");
|
|
18974
|
+
}
|
|
18975
|
+
}
|
|
18976
|
+
function handleNoTransactions(result) {
|
|
18977
|
+
result.steps.import = buildStepResult(true, "No transactions to import");
|
|
18978
|
+
result.steps.reconcile = buildStepResult(true, "Reconciliation skipped (no transactions)");
|
|
18979
|
+
result.steps.merge = buildStepResult(true, "Merge skipped (no changes)");
|
|
18980
|
+
return buildSuccessResult5(result, "No transactions found to import");
|
|
18981
|
+
}
|
|
18982
|
+
async function importPipeline(directory, agent, options, configLoader = loadImportConfig, hledgerExecutor = defaultHledgerExecutor) {
|
|
18847
18983
|
const restrictionError = checkAccountantAgent(agent, "import pipeline");
|
|
18848
18984
|
if (restrictionError) {
|
|
18849
18985
|
return restrictionError;
|
|
@@ -18852,163 +18988,47 @@ async function importPipelineCore(directory, agent, options, configLoader = load
|
|
|
18852
18988
|
success: false,
|
|
18853
18989
|
steps: {}
|
|
18854
18990
|
};
|
|
18855
|
-
|
|
18991
|
+
const context = {
|
|
18992
|
+
directory,
|
|
18993
|
+
agent,
|
|
18994
|
+
options,
|
|
18995
|
+
configLoader,
|
|
18996
|
+
hledgerExecutor,
|
|
18997
|
+
result
|
|
18998
|
+
};
|
|
18856
18999
|
try {
|
|
18857
|
-
|
|
18858
|
-
worktree = createImportWorktree(directory);
|
|
19000
|
+
return await withWorktree(directory, async (worktree) => {
|
|
18859
19001
|
result.worktreeId = worktree.uuid;
|
|
18860
|
-
result.steps.worktree = {
|
|
18861
|
-
|
|
18862
|
-
|
|
18863
|
-
|
|
18864
|
-
};
|
|
18865
|
-
} catch (error45) {
|
|
18866
|
-
result.steps.worktree = {
|
|
18867
|
-
success: false,
|
|
18868
|
-
message: `Failed to create worktree: ${error45 instanceof Error ? error45.message : String(error45)}`
|
|
18869
|
-
};
|
|
18870
|
-
throw new Error("Failed to create worktree");
|
|
18871
|
-
}
|
|
18872
|
-
const inWorktree = () => true;
|
|
18873
|
-
if (!options.skipClassify) {
|
|
18874
|
-
const classifyResult = await classifyStatements(worktree.path, agent, configLoader, inWorktree);
|
|
18875
|
-
const classifyParsed = JSON.parse(classifyResult);
|
|
18876
|
-
result.steps.classify = {
|
|
18877
|
-
success: classifyParsed.success !== false,
|
|
18878
|
-
message: classifyParsed.success !== false ? "Classification complete" : "Classification had issues",
|
|
18879
|
-
details: classifyParsed
|
|
18880
|
-
};
|
|
18881
|
-
if (classifyParsed.unrecognized?.length > 0) {
|
|
18882
|
-
result.steps.classify.message = `Classification complete with ${classifyParsed.unrecognized.length} unrecognized file(s)`;
|
|
18883
|
-
}
|
|
18884
|
-
} else {
|
|
18885
|
-
result.steps.classify = {
|
|
18886
|
-
success: true,
|
|
18887
|
-
message: "Classification skipped (skipClassify: true)"
|
|
18888
|
-
};
|
|
18889
|
-
}
|
|
18890
|
-
const dryRunResult = await importStatements(worktree.path, agent, {
|
|
18891
|
-
provider: options.provider,
|
|
18892
|
-
currency: options.currency,
|
|
18893
|
-
checkOnly: true
|
|
18894
|
-
}, configLoader, hledgerExecutor, inWorktree);
|
|
18895
|
-
const dryRunParsed = JSON.parse(dryRunResult);
|
|
18896
|
-
result.steps.dryRun = {
|
|
18897
|
-
success: dryRunParsed.success,
|
|
18898
|
-
message: dryRunParsed.success ? `Dry run passed: ${dryRunParsed.summary?.totalTransactions || 0} transactions ready` : `Dry run failed: ${dryRunParsed.summary?.unknown || 0} unknown account(s)`,
|
|
18899
|
-
details: dryRunParsed
|
|
18900
|
-
};
|
|
18901
|
-
if (!dryRunParsed.success) {
|
|
18902
|
-
result.error = "Dry run found unknown accounts or errors";
|
|
18903
|
-
result.hint = "Add rules to categorize unknown transactions, then retry";
|
|
18904
|
-
throw new Error("Dry run failed");
|
|
18905
|
-
}
|
|
18906
|
-
if (dryRunParsed.summary?.totalTransactions === 0) {
|
|
18907
|
-
result.steps.import = {
|
|
18908
|
-
success: true,
|
|
18909
|
-
message: "No transactions to import"
|
|
18910
|
-
};
|
|
18911
|
-
result.steps.reconcile = {
|
|
18912
|
-
success: true,
|
|
18913
|
-
message: "Reconciliation skipped (no transactions)"
|
|
18914
|
-
};
|
|
18915
|
-
result.steps.merge = {
|
|
18916
|
-
success: true,
|
|
18917
|
-
message: "Merge skipped (no changes)"
|
|
18918
|
-
};
|
|
18919
|
-
result.success = true;
|
|
18920
|
-
result.summary = "No transactions found to import";
|
|
18921
|
-
removeWorktree(worktree, true);
|
|
18922
|
-
result.steps.cleanup = {
|
|
18923
|
-
success: true,
|
|
18924
|
-
message: "Worktree cleaned up"
|
|
18925
|
-
};
|
|
18926
|
-
return JSON.stringify(result);
|
|
18927
|
-
}
|
|
18928
|
-
const importResult = await importStatements(worktree.path, agent, {
|
|
18929
|
-
provider: options.provider,
|
|
18930
|
-
currency: options.currency,
|
|
18931
|
-
checkOnly: false
|
|
18932
|
-
}, configLoader, hledgerExecutor, inWorktree);
|
|
18933
|
-
const importParsed = JSON.parse(importResult);
|
|
18934
|
-
result.steps.import = {
|
|
18935
|
-
success: importParsed.success,
|
|
18936
|
-
message: importParsed.success ? `Imported ${importParsed.summary?.totalTransactions || 0} transactions` : `Import failed: ${importParsed.error || "Unknown error"}`,
|
|
18937
|
-
details: importParsed
|
|
18938
|
-
};
|
|
18939
|
-
if (!importParsed.success) {
|
|
18940
|
-
result.error = `Import failed: ${importParsed.error || "Unknown error"}`;
|
|
18941
|
-
throw new Error("Import failed");
|
|
18942
|
-
}
|
|
18943
|
-
const reconcileResult = await reconcileStatementCore(worktree.path, agent, {
|
|
18944
|
-
provider: options.provider,
|
|
18945
|
-
currency: options.currency,
|
|
18946
|
-
closingBalance: options.closingBalance,
|
|
18947
|
-
account: options.account
|
|
18948
|
-
}, configLoader, hledgerExecutor, inWorktree);
|
|
18949
|
-
const reconcileParsed = JSON.parse(reconcileResult);
|
|
18950
|
-
result.steps.reconcile = {
|
|
18951
|
-
success: reconcileParsed.success,
|
|
18952
|
-
message: reconcileParsed.success ? `Balance reconciled: ${reconcileParsed.actualBalance}` : `Balance mismatch: expected ${reconcileParsed.expectedBalance}, got ${reconcileParsed.actualBalance}`,
|
|
18953
|
-
details: reconcileParsed
|
|
18954
|
-
};
|
|
18955
|
-
if (!reconcileParsed.success) {
|
|
18956
|
-
result.error = `Reconciliation failed: ${reconcileParsed.error || "Balance mismatch"}`;
|
|
18957
|
-
result.hint = "Check for missing transactions or incorrect rules";
|
|
18958
|
-
throw new Error("Reconciliation failed");
|
|
18959
|
-
}
|
|
18960
|
-
const commitInfo = extractCommitInfo(reconcileResult);
|
|
18961
|
-
const transactionCount = extractTransactionCount(importResult);
|
|
18962
|
-
const commitMessage = buildCommitMessage(options.provider, options.currency, commitInfo.fromDate, commitInfo.untilDate, transactionCount);
|
|
18963
|
-
try {
|
|
18964
|
-
mergeWorktree(worktree, commitMessage);
|
|
18965
|
-
result.steps.merge = {
|
|
18966
|
-
success: true,
|
|
18967
|
-
message: `Merged to main: "${commitMessage}"`,
|
|
18968
|
-
details: { commitMessage }
|
|
18969
|
-
};
|
|
18970
|
-
} catch (error45) {
|
|
18971
|
-
result.steps.merge = {
|
|
18972
|
-
success: false,
|
|
18973
|
-
message: `Merge failed: ${error45 instanceof Error ? error45.message : String(error45)}`
|
|
18974
|
-
};
|
|
18975
|
-
result.error = "Merge to main branch failed";
|
|
18976
|
-
throw new Error("Merge failed");
|
|
18977
|
-
}
|
|
18978
|
-
try {
|
|
18979
|
-
removeWorktree(worktree, true);
|
|
18980
|
-
result.steps.cleanup = {
|
|
18981
|
-
success: true,
|
|
18982
|
-
message: "Worktree cleaned up"
|
|
18983
|
-
};
|
|
18984
|
-
} catch (error45) {
|
|
18985
|
-
result.steps.cleanup = {
|
|
18986
|
-
success: false,
|
|
18987
|
-
message: `Cleanup warning: ${error45 instanceof Error ? error45.message : String(error45)}`
|
|
18988
|
-
};
|
|
18989
|
-
}
|
|
18990
|
-
result.success = true;
|
|
18991
|
-
result.summary = `Successfully imported ${transactionCount} transaction(s)`;
|
|
18992
|
-
return JSON.stringify(result);
|
|
18993
|
-
} catch (error45) {
|
|
18994
|
-
if (worktree) {
|
|
19002
|
+
result.steps.worktree = buildStepResult(true, `Created worktree at ${worktree.path}`, {
|
|
19003
|
+
path: worktree.path,
|
|
19004
|
+
branch: worktree.branch
|
|
19005
|
+
});
|
|
18995
19006
|
try {
|
|
18996
|
-
|
|
18997
|
-
|
|
18998
|
-
|
|
18999
|
-
|
|
19000
|
-
|
|
19001
|
-
|
|
19002
|
-
|
|
19003
|
-
|
|
19004
|
-
|
|
19005
|
-
};
|
|
19007
|
+
await executeClassifyStep(context, worktree);
|
|
19008
|
+
await executeDryRunStep(context, worktree);
|
|
19009
|
+
await executeImportStep(context, worktree);
|
|
19010
|
+
await executeReconcileStep(context, worktree);
|
|
19011
|
+
await executeMergeStep(context, worktree);
|
|
19012
|
+
result.steps.cleanup = buildStepResult(true, "Worktree cleaned up", {
|
|
19013
|
+
cleanedAfterSuccess: true
|
|
19014
|
+
});
|
|
19015
|
+
const transactionCount = context.result.steps.import?.details?.summary?.totalTransactions || 0;
|
|
19016
|
+
return buildSuccessResult5(result, `Successfully imported ${transactionCount} transaction(s)`);
|
|
19017
|
+
} catch (error45) {
|
|
19018
|
+
result.steps.cleanup = buildStepResult(true, "Worktree cleaned up after failure", { cleanedAfterFailure: true });
|
|
19019
|
+
if (error45 instanceof NoTransactionsError) {
|
|
19020
|
+
return handleNoTransactions(result);
|
|
19021
|
+
}
|
|
19022
|
+
if (!result.error) {
|
|
19023
|
+
result.error = error45 instanceof Error ? error45.message : String(error45);
|
|
19024
|
+
}
|
|
19025
|
+
return buildErrorResult5(result, result.error, result.hint);
|
|
19006
19026
|
}
|
|
19007
|
-
}
|
|
19008
|
-
|
|
19009
|
-
|
|
19010
|
-
|
|
19011
|
-
return
|
|
19027
|
+
});
|
|
19028
|
+
} catch (error45) {
|
|
19029
|
+
result.steps.worktree = buildStepResult(false, `Failed to create worktree: ${error45 instanceof Error ? error45.message : String(error45)}`);
|
|
19030
|
+
result.error = "Failed to create worktree";
|
|
19031
|
+
return buildErrorResult5(result, result.error);
|
|
19012
19032
|
}
|
|
19013
19033
|
}
|
|
19014
19034
|
var import_pipeline_default = tool({
|
|
@@ -19045,7 +19065,7 @@ This tool orchestrates the full import workflow in an isolated git worktree:
|
|
|
19045
19065
|
},
|
|
19046
19066
|
async execute(params, context) {
|
|
19047
19067
|
const { directory, agent } = context;
|
|
19048
|
-
return
|
|
19068
|
+
return importPipeline(directory, agent, {
|
|
19049
19069
|
provider: params.provider,
|
|
19050
19070
|
currency: params.currency,
|
|
19051
19071
|
closingBalance: params.closingBalance,
|