@opentabs-dev/opentabs-plugin-ynab 0.0.85 → 0.0.87
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/adapter.iife.js +1315 -545
- package/dist/adapter.iife.js.map +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -16
- package/dist/index.js.map +1 -1
- package/dist/tools/create-category-group.d.ts +11 -0
- package/dist/tools/create-category-group.d.ts.map +1 -0
- package/dist/tools/create-category-group.js +37 -0
- package/dist/tools/create-category-group.js.map +1 -0
- package/dist/tools/create-category.d.ts +59 -0
- package/dist/tools/create-category.d.ts.map +1 -0
- package/dist/tools/create-category.js +63 -0
- package/dist/tools/create-category.js.map +1 -0
- package/dist/tools/create-transaction.d.ts +2 -2
- package/dist/tools/create-transaction.d.ts.map +1 -1
- package/dist/tools/create-transaction.js +63 -22
- package/dist/tools/create-transaction.js.map +1 -1
- package/dist/tools/delete-category-group.d.ts +8 -0
- package/dist/tools/delete-category-group.d.ts.map +1 -0
- package/dist/tools/delete-category-group.js +33 -0
- package/dist/tools/delete-category-group.js.map +1 -0
- package/dist/tools/delete-category.d.ts +7 -0
- package/dist/tools/delete-category.d.ts.map +1 -0
- package/dist/tools/delete-category.js +28 -0
- package/dist/tools/delete-category.js.map +1 -0
- package/dist/tools/delete-transaction.d.ts.map +1 -1
- package/dist/tools/delete-transaction.js +22 -7
- package/dist/tools/delete-transaction.js.map +1 -1
- package/dist/tools/get-account.d.ts.map +1 -1
- package/dist/tools/get-account.js +3 -3
- package/dist/tools/get-account.js.map +1 -1
- package/dist/tools/get-month.d.ts +2 -1
- package/dist/tools/get-month.d.ts.map +1 -1
- package/dist/tools/get-month.js +10 -33
- package/dist/tools/get-month.js.map +1 -1
- package/dist/tools/get-plan.d.ts.map +1 -1
- package/dist/tools/get-plan.js +12 -5
- package/dist/tools/get-plan.js.map +1 -1
- package/dist/tools/get-transaction.d.ts +2 -2
- package/dist/tools/get-transaction.d.ts.map +1 -1
- package/dist/tools/get-transaction.js +5 -4
- package/dist/tools/get-transaction.js.map +1 -1
- package/dist/tools/list-accounts.d.ts.map +1 -1
- package/dist/tools/list-accounts.js +4 -4
- package/dist/tools/list-accounts.js.map +1 -1
- package/dist/tools/list-categories.d.ts.map +1 -1
- package/dist/tools/list-categories.js +9 -29
- package/dist/tools/list-categories.js.map +1 -1
- package/dist/tools/list-months.d.ts +1 -1
- package/dist/tools/list-months.d.ts.map +1 -1
- package/dist/tools/list-months.js +5 -14
- package/dist/tools/list-months.js.map +1 -1
- package/dist/tools/list-payees.d.ts.map +1 -1
- package/dist/tools/list-payees.js +3 -3
- package/dist/tools/list-payees.js.map +1 -1
- package/dist/tools/list-scheduled-transactions.d.ts.map +1 -1
- package/dist/tools/list-scheduled-transactions.js +7 -5
- package/dist/tools/list-scheduled-transactions.js.map +1 -1
- package/dist/tools/list-transactions.d.ts +4 -2
- package/dist/tools/list-transactions.d.ts.map +1 -1
- package/dist/tools/list-transactions.js +40 -8
- package/dist/tools/list-transactions.js.map +1 -1
- package/dist/tools/move-category-budget.d.ts +24 -0
- package/dist/tools/move-category-budget.d.ts.map +1 -0
- package/dist/tools/move-category-budget.js +100 -0
- package/dist/tools/move-category-budget.js.map +1 -0
- package/dist/tools/schemas.d.ts +185 -28
- package/dist/tools/schemas.d.ts.map +1 -1
- package/dist/tools/schemas.js +411 -28
- package/dist/tools/schemas.js.map +1 -1
- package/dist/tools/snooze-category-goal.d.ts +10 -0
- package/dist/tools/snooze-category-goal.d.ts.map +1 -0
- package/dist/tools/snooze-category-goal.js +53 -0
- package/dist/tools/snooze-category-goal.js.map +1 -0
- package/dist/tools/update-category-budget.d.ts.map +1 -1
- package/dist/tools/update-category-budget.js +51 -26
- package/dist/tools/update-category-budget.js.map +1 -1
- package/dist/tools/update-category.d.ts +61 -0
- package/dist/tools/update-category.d.ts.map +1 -0
- package/dist/tools/update-category.js +46 -0
- package/dist/tools/update-category.js.map +1 -0
- package/dist/tools/update-transaction.d.ts +3 -2
- package/dist/tools/update-transaction.d.ts.map +1 -1
- package/dist/tools/update-transaction.js +84 -31
- package/dist/tools/update-transaction.js.map +1 -1
- package/dist/tools.json +965 -43
- package/dist/ynab-api.d.ts +4 -1
- package/dist/ynab-api.d.ts.map +1 -1
- package/dist/ynab-api.js +47 -26
- package/dist/ynab-api.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { defineTool, ToolError } from '@opentabs-dev/plugin-sdk';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { getPlanId, syncBudget, syncWrite } from '../ynab-api.js';
|
|
4
|
+
import { findCategory, formatMonthlyBudgetId, formatSubcategoryBudgetId, notTombstone, toMonthKey } from './schemas.js';
|
|
5
|
+
export const snoozeCategoryGoal = defineTool({
|
|
6
|
+
name: 'snooze_category_goal',
|
|
7
|
+
displayName: 'Snooze Category Goal',
|
|
8
|
+
description: 'Snooze a category goal for a specific month so it does not appear as needing funding for that month. Pass snooze=false to un-snooze.',
|
|
9
|
+
summary: 'Snooze a category goal for a month',
|
|
10
|
+
icon: 'bell-off',
|
|
11
|
+
group: 'Categories',
|
|
12
|
+
input: z.object({
|
|
13
|
+
category_id: z.string().min(1).describe('Category ID whose goal to snooze'),
|
|
14
|
+
month: z
|
|
15
|
+
.string()
|
|
16
|
+
.regex(/^\d{4}-\d{2}(-\d{2})?$/, 'Month must be YYYY-MM or YYYY-MM-DD')
|
|
17
|
+
.describe('Month in YYYY-MM format (e.g. 2026-04)'),
|
|
18
|
+
snooze: z.boolean().optional().describe('true to snooze (default), false to un-snooze'),
|
|
19
|
+
}),
|
|
20
|
+
output: z.object({
|
|
21
|
+
success: z.boolean(),
|
|
22
|
+
snoozed_at: z.string().nullable().describe('ISO timestamp the goal was snoozed at, or null if un-snoozed'),
|
|
23
|
+
}),
|
|
24
|
+
handle: async (params) => {
|
|
25
|
+
const planId = getPlanId();
|
|
26
|
+
const monthKey = toMonthKey(params.month);
|
|
27
|
+
const budgetId = formatSubcategoryBudgetId(monthKey, params.category_id);
|
|
28
|
+
const monthlyBudgetId = formatMonthlyBudgetId(monthKey, planId);
|
|
29
|
+
const shouldSnooze = params.snooze ?? true;
|
|
30
|
+
const budget = await syncBudget(planId);
|
|
31
|
+
const serverKnowledge = budget.current_server_knowledge ?? 0;
|
|
32
|
+
const category = findCategory(budget.changed_entities, params.category_id);
|
|
33
|
+
if (!category.goal_type) {
|
|
34
|
+
throw ToolError.validation(`Category "${category.name}" has no goal to snooze.`);
|
|
35
|
+
}
|
|
36
|
+
const existing = (budget.changed_entities?.be_monthly_subcategory_budgets ?? []).find(b => b.id === budgetId && notTombstone(b));
|
|
37
|
+
const snoozedAt = shouldSnooze ? new Date().toISOString() : null;
|
|
38
|
+
// Preserve every field on the existing budget row so we don't accidentally
|
|
39
|
+
// wipe state by sending only the fields we care about.
|
|
40
|
+
const budgetEntry = {
|
|
41
|
+
...(existing ?? {}),
|
|
42
|
+
id: budgetId,
|
|
43
|
+
is_tombstone: false,
|
|
44
|
+
entities_monthly_budget_id: monthlyBudgetId,
|
|
45
|
+
entities_subcategory_id: params.category_id,
|
|
46
|
+
budgeted: existing?.budgeted ?? 0,
|
|
47
|
+
goal_snoozed_at: snoozedAt,
|
|
48
|
+
};
|
|
49
|
+
await syncWrite(planId, { be_monthly_subcategory_budgets: [budgetEntry] }, serverKnowledge);
|
|
50
|
+
return { success: true, snoozed_at: snoozedAt };
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=snooze-category-goal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snooze-category-goal.js","sourceRoot":"","sources":["../../src/tools/snooze-category-goal.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-category-budget.d.ts","sourceRoot":"","sources":["../../src/tools/update-category-budget.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"update-category-budget.d.ts","sourceRoot":"","sources":["../../src/tools/update-category-budget.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAiBxB,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;kBA6E/B,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineTool } from '@opentabs-dev/plugin-sdk';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { getPlanId, syncWrite } from '../ynab-api.js';
|
|
4
|
-
import { categorySchema,
|
|
3
|
+
import { getPlanId, getUserId, syncBudget, syncWrite } from '../ynab-api.js';
|
|
4
|
+
import { buildSubcategoryBudgetMap, buildSubcategoryCalcMap, categorySchema, findCategory, formatMonthlyBudgetId, formatSubcategoryBudgetId, MONEY_MOVEMENT_SOURCE, mapCategoryForMonth, notTombstone, toMilliunits, toMonthKey, } from './schemas.js';
|
|
5
5
|
export const updateCategoryBudget = defineTool({
|
|
6
6
|
name: 'update_category_budget',
|
|
7
7
|
displayName: 'Update Category Budget',
|
|
@@ -11,7 +11,10 @@ export const updateCategoryBudget = defineTool({
|
|
|
11
11
|
group: 'Categories',
|
|
12
12
|
input: z.object({
|
|
13
13
|
category_id: z.string().min(1).describe('Category ID to budget'),
|
|
14
|
-
month: z
|
|
14
|
+
month: z
|
|
15
|
+
.string()
|
|
16
|
+
.regex(/^\d{4}-\d{2}(-\d{2})?$/, 'Month must be YYYY-MM or YYYY-MM-DD')
|
|
17
|
+
.describe('Month in YYYY-MM format (e.g. 2026-03)'),
|
|
15
18
|
budgeted: z.number().describe('Amount to budget in currency units (e.g. 500 for $500)'),
|
|
16
19
|
}),
|
|
17
20
|
output: z.object({
|
|
@@ -19,32 +22,54 @@ export const updateCategoryBudget = defineTool({
|
|
|
19
22
|
}),
|
|
20
23
|
handle: async (params) => {
|
|
21
24
|
const planId = getPlanId();
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
const monthKey = params.month
|
|
25
|
-
const budgetId =
|
|
26
|
-
const monthlyBudgetId =
|
|
27
|
-
const
|
|
28
|
-
|
|
25
|
+
const userId = getUserId();
|
|
26
|
+
const milliunits = toMilliunits(params.budgeted);
|
|
27
|
+
const monthKey = toMonthKey(params.month);
|
|
28
|
+
const budgetId = formatSubcategoryBudgetId(monthKey, params.category_id);
|
|
29
|
+
const monthlyBudgetId = formatMonthlyBudgetId(monthKey, planId);
|
|
30
|
+
const budget = await syncBudget(planId);
|
|
31
|
+
const serverKnowledge = budget.current_server_knowledge ?? 0;
|
|
32
|
+
const category = findCategory(budget.changed_entities, params.category_id);
|
|
33
|
+
const existingBudget = (budget.changed_entities?.be_monthly_subcategory_budgets ?? []).find(b => b.id === budgetId && notTombstone(b));
|
|
34
|
+
const delta = milliunits - (existingBudget?.budgeted ?? 0);
|
|
35
|
+
const budgetEntry = {
|
|
36
|
+
id: budgetId,
|
|
37
|
+
is_tombstone: false,
|
|
38
|
+
entities_monthly_budget_id: monthlyBudgetId,
|
|
39
|
+
entities_subcategory_id: params.category_id,
|
|
40
|
+
budgeted: milliunits,
|
|
41
|
+
};
|
|
42
|
+
const changedEntities = { be_monthly_subcategory_budgets: [budgetEntry] };
|
|
43
|
+
// YNAB tracks budget changes as money movements; without this the write
|
|
44
|
+
// is silently rejected (the budget value reverts on the next sync).
|
|
45
|
+
// Direction is encoded via from/to (always positive amount).
|
|
46
|
+
if (delta !== 0) {
|
|
47
|
+
changedEntities.be_money_movements = [
|
|
29
48
|
{
|
|
30
|
-
id:
|
|
31
|
-
entities_monthly_budget_id: monthlyBudgetId,
|
|
32
|
-
entities_subcategory_id: params.category_id,
|
|
33
|
-
budgeted: milliunits,
|
|
34
|
-
overspending_handling: 'AffectsBuffer',
|
|
49
|
+
id: crypto.randomUUID(),
|
|
35
50
|
is_tombstone: false,
|
|
51
|
+
to_entities_monthly_subcategory_budget_id: delta > 0 ? budgetId : null,
|
|
52
|
+
from_entities_monthly_subcategory_budget_id: delta < 0 ? budgetId : null,
|
|
53
|
+
entities_money_movement_group_id: null,
|
|
54
|
+
amount: Math.abs(delta),
|
|
55
|
+
performed_by_user_id: userId,
|
|
56
|
+
note: null,
|
|
57
|
+
source: MONEY_MOVEMENT_SOURCE.ASSIGN,
|
|
58
|
+
move_started_at: new Date().toISOString(),
|
|
59
|
+
move_accepted_at: null,
|
|
36
60
|
},
|
|
37
|
-
]
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
const result = await syncWrite(planId, changedEntities, serverKnowledge);
|
|
64
|
+
const calcMap = buildSubcategoryCalcMap(result.changed_entities?.be_monthly_subcategory_budget_calculations ?? []);
|
|
65
|
+
// Prefer the server's echoed values — if a concurrent update from another
|
|
66
|
+
// client merged in, that change shows up here. Fall back to our local entry
|
|
67
|
+
// if the server didn't echo (shouldn't happen in practice).
|
|
68
|
+
const budgetMap = buildSubcategoryBudgetMap(result.changed_entities?.be_monthly_subcategory_budgets ?? []);
|
|
69
|
+
const key = `${monthKey}/${params.category_id}`;
|
|
70
|
+
if (!budgetMap.has(key))
|
|
71
|
+
budgetMap.set(key, budgetEntry);
|
|
72
|
+
return { category: mapCategoryForMonth(category, budgetMap, calcMap, monthKey) };
|
|
48
73
|
},
|
|
49
74
|
});
|
|
50
75
|
//# sourceMappingURL=update-category-budget.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-category-budget.js","sourceRoot":"","sources":["../../src/tools/update-category-budget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"update-category-budget.js","sourceRoot":"","sources":["../../src/tools/update-category-budget.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const updateCategory: import("@opentabs-dev/plugin-sdk").ToolDefinition<z.ZodObject<{
|
|
3
|
+
category_id: z.ZodString;
|
|
4
|
+
name: z.ZodOptional<z.ZodString>;
|
|
5
|
+
group_id: z.ZodOptional<z.ZodString>;
|
|
6
|
+
goal: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
7
|
+
target: z.ZodNumber;
|
|
8
|
+
cadence: z.ZodOptional<z.ZodEnum<{
|
|
9
|
+
weekly: "weekly";
|
|
10
|
+
monthly: "monthly";
|
|
11
|
+
yearly: "yearly";
|
|
12
|
+
}>>;
|
|
13
|
+
every: z.ZodOptional<z.ZodNumber>;
|
|
14
|
+
day: z.ZodOptional<z.ZodNumber>;
|
|
15
|
+
start_date: z.ZodOptional<z.ZodString>;
|
|
16
|
+
type: z.ZodLiteral<"set_aside">;
|
|
17
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
18
|
+
target: z.ZodNumber;
|
|
19
|
+
cadence: z.ZodOptional<z.ZodEnum<{
|
|
20
|
+
weekly: "weekly";
|
|
21
|
+
monthly: "monthly";
|
|
22
|
+
yearly: "yearly";
|
|
23
|
+
}>>;
|
|
24
|
+
every: z.ZodOptional<z.ZodNumber>;
|
|
25
|
+
day: z.ZodOptional<z.ZodNumber>;
|
|
26
|
+
start_date: z.ZodOptional<z.ZodString>;
|
|
27
|
+
type: z.ZodLiteral<"refill">;
|
|
28
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
29
|
+
type: z.ZodLiteral<"target_balance">;
|
|
30
|
+
target: z.ZodNumber;
|
|
31
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
32
|
+
type: z.ZodLiteral<"target_by_date">;
|
|
33
|
+
target: z.ZodNumber;
|
|
34
|
+
date: z.ZodString;
|
|
35
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
36
|
+
type: z.ZodLiteral<"debt">;
|
|
37
|
+
target: z.ZodNumber;
|
|
38
|
+
day: z.ZodOptional<z.ZodNumber>;
|
|
39
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
40
|
+
type: z.ZodLiteral<"none">;
|
|
41
|
+
}, z.core.$strict>], "type">>;
|
|
42
|
+
hidden: z.ZodOptional<z.ZodBoolean>;
|
|
43
|
+
note: z.ZodOptional<z.ZodString>;
|
|
44
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
45
|
+
category: z.ZodObject<{
|
|
46
|
+
id: z.ZodString;
|
|
47
|
+
category_group_id: z.ZodString;
|
|
48
|
+
name: z.ZodString;
|
|
49
|
+
hidden: z.ZodBoolean;
|
|
50
|
+
budgeted: z.ZodString;
|
|
51
|
+
activity: z.ZodString;
|
|
52
|
+
balance: z.ZodString;
|
|
53
|
+
budgeted_milliunits: z.ZodNumber;
|
|
54
|
+
activity_milliunits: z.ZodNumber;
|
|
55
|
+
balance_milliunits: z.ZodNumber;
|
|
56
|
+
goal_type: z.ZodString;
|
|
57
|
+
goal_target: z.ZodString;
|
|
58
|
+
goal_percentage_complete: z.ZodNumber;
|
|
59
|
+
}, z.core.$strip>;
|
|
60
|
+
}, z.core.$strip>>;
|
|
61
|
+
//# sourceMappingURL=update-category.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-category.d.ts","sourceRoot":"","sources":["../../src/tools/update-category.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA8CzB,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { defineTool, ToolError } from '@opentabs-dev/plugin-sdk';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { getPlanId, syncBudget, syncWrite } from '../ynab-api.js';
|
|
4
|
+
import { assertCategoryGroupDeletable, buildGoalFields, categorySchema, findCategory, findCategoryGroup, goalSpecSchema, mapCategory, } from './schemas.js';
|
|
5
|
+
export const updateCategory = defineTool({
|
|
6
|
+
name: 'update_category',
|
|
7
|
+
displayName: 'Update Category',
|
|
8
|
+
description: 'Rename a category, change its group, set/clear its goal, or hide/unhide it. Only specified fields change; omitted fields remain unchanged. Goal types: "set_aside" / "refill" (recurring NEED with optional cadence), "target_balance" (have $X), "target_by_date" (have $X by date), "debt" (recurring debt payment), or "none" to clear an existing goal.',
|
|
9
|
+
summary: 'Update a category',
|
|
10
|
+
icon: 'pencil',
|
|
11
|
+
group: 'Categories',
|
|
12
|
+
input: z.object({
|
|
13
|
+
category_id: z.string().min(1).describe('Category ID to update'),
|
|
14
|
+
name: z.string().min(1).optional().describe('New name'),
|
|
15
|
+
group_id: z.string().min(1).optional().describe('New parent category group ID (to move the category)'),
|
|
16
|
+
goal: goalSpecSchema.optional().describe('New goal definition. Pass { type: "none" } to clear the goal.'),
|
|
17
|
+
hidden: z.boolean().optional().describe('Hide or unhide the category'),
|
|
18
|
+
note: z.string().optional().describe('New note (pass empty string to clear)'),
|
|
19
|
+
}),
|
|
20
|
+
output: z.object({
|
|
21
|
+
category: categorySchema,
|
|
22
|
+
}),
|
|
23
|
+
handle: async (params) => {
|
|
24
|
+
const planId = getPlanId();
|
|
25
|
+
const budget = await syncBudget(planId);
|
|
26
|
+
const serverKnowledge = budget.current_server_knowledge ?? 0;
|
|
27
|
+
const existing = findCategory(budget.changed_entities, params.category_id);
|
|
28
|
+
if (params.group_id) {
|
|
29
|
+
assertCategoryGroupDeletable(findCategoryGroup(budget.changed_entities, params.group_id));
|
|
30
|
+
}
|
|
31
|
+
if (params.goal?.type === 'debt' && existing.entities_account_id == null) {
|
|
32
|
+
throw ToolError.validation('Debt goals can only be set on debt-account categories.');
|
|
33
|
+
}
|
|
34
|
+
const updated = {
|
|
35
|
+
...existing,
|
|
36
|
+
name: params.name ?? existing.name,
|
|
37
|
+
entities_master_category_id: params.group_id ?? existing.entities_master_category_id,
|
|
38
|
+
is_hidden: params.hidden ?? existing.is_hidden,
|
|
39
|
+
note: params.note ?? existing.note,
|
|
40
|
+
...(params.goal !== undefined ? buildGoalFields(params.goal) : {}),
|
|
41
|
+
};
|
|
42
|
+
await syncWrite(planId, { be_subcategories: [updated] }, serverKnowledge);
|
|
43
|
+
return { category: mapCategory(updated) };
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
//# sourceMappingURL=update-category.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-category.js","sourceRoot":"","sources":["../../src/tools/update-category.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,6 +21,7 @@ export declare const updateTransaction: import("@opentabs-dev/plugin-sdk").ToolD
|
|
|
21
21
|
green: "green";
|
|
22
22
|
blue: "blue";
|
|
23
23
|
purple: "purple";
|
|
24
|
+
none: "none";
|
|
24
25
|
}>>;
|
|
25
26
|
}, z.core.$strip>, z.ZodObject<{
|
|
26
27
|
transaction: z.ZodObject<{
|
|
@@ -32,7 +33,6 @@ export declare const updateTransaction: import("@opentabs-dev/plugin-sdk").ToolD
|
|
|
32
33
|
cleared: z.ZodString;
|
|
33
34
|
approved: z.ZodBoolean;
|
|
34
35
|
flag_color: z.ZodString;
|
|
35
|
-
flag_name: z.ZodString;
|
|
36
36
|
account_id: z.ZodString;
|
|
37
37
|
account_name: z.ZodString;
|
|
38
38
|
payee_id: z.ZodString;
|
|
@@ -40,7 +40,8 @@ export declare const updateTransaction: import("@opentabs-dev/plugin-sdk").ToolD
|
|
|
40
40
|
category_id: z.ZodString;
|
|
41
41
|
category_name: z.ZodString;
|
|
42
42
|
transfer_account_id: z.ZodString;
|
|
43
|
-
|
|
43
|
+
imported_payee: z.ZodString;
|
|
44
|
+
original_imported_payee: z.ZodString;
|
|
44
45
|
deleted: z.ZodBoolean;
|
|
45
46
|
}, z.core.$strip>;
|
|
46
47
|
}, z.core.$strip>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-transaction.d.ts","sourceRoot":"","sources":["../../src/tools/update-transaction.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"update-transaction.d.ts","sourceRoot":"","sources":["../../src/tools/update-transaction.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAwBxB,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA+G5B,CAAC"}
|
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import { defineTool, ToolError } from '@opentabs-dev/plugin-sdk';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { getPlanId, syncWrite } from '../ynab-api.js';
|
|
4
|
-
import { mapTransaction, transactionSchema } from './schemas.js';
|
|
3
|
+
import { getPlanId, syncBudget, syncWrite } from '../ynab-api.js';
|
|
4
|
+
import { buildLookups, CLEARED_MAP, FLAG_MAP, mapTransaction, resolvePayee, toMilliunits, transactionSchema, } from './schemas.js';
|
|
5
|
+
const resolveFlag = (requested, existing) => {
|
|
6
|
+
if (requested === 'none')
|
|
7
|
+
return null;
|
|
8
|
+
if (requested)
|
|
9
|
+
return FLAG_MAP[requested];
|
|
10
|
+
return existing ?? null;
|
|
11
|
+
};
|
|
12
|
+
const resolveCleared = (requested, existing) => {
|
|
13
|
+
if (requested)
|
|
14
|
+
return CLEARED_MAP[requested];
|
|
15
|
+
return existing ?? 'Uncleared';
|
|
16
|
+
};
|
|
5
17
|
export const updateTransaction = defineTool({
|
|
6
18
|
name: 'update_transaction',
|
|
7
19
|
displayName: 'Update Transaction',
|
|
8
|
-
description: 'Update an existing transaction in the active YNAB plan. Only specified fields are changed; omitted fields remain unchanged. Amount is in currency units (negative for expenses, positive for income).',
|
|
20
|
+
description: 'Update an existing transaction in the active YNAB plan. Only specified fields are changed; omitted fields remain unchanged. Amount is in currency units (negative for expenses, positive for income). Transfers and split transactions cannot be updated through this tool — edit them directly in YNAB.',
|
|
9
21
|
summary: 'Update a transaction',
|
|
10
22
|
icon: 'pencil',
|
|
11
23
|
group: 'Transactions',
|
|
@@ -20,43 +32,84 @@ export const updateTransaction = defineTool({
|
|
|
20
32
|
memo: z.string().optional().describe('New transaction memo'),
|
|
21
33
|
cleared: z.enum(['cleared', 'uncleared', 'reconciled']).optional().describe('New cleared status'),
|
|
22
34
|
approved: z.boolean().optional().describe('New approval status'),
|
|
23
|
-
flag_color: z
|
|
35
|
+
flag_color: z
|
|
36
|
+
.enum(['red', 'orange', 'yellow', 'green', 'blue', 'purple', 'none'])
|
|
37
|
+
.optional()
|
|
38
|
+
.describe('New flag color (pass "none" to clear)'),
|
|
24
39
|
}),
|
|
25
40
|
output: z.object({
|
|
26
41
|
transaction: transactionSchema,
|
|
27
42
|
}),
|
|
28
43
|
handle: async (params) => {
|
|
29
44
|
const planId = getPlanId();
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (params.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
const budget = await syncBudget(planId);
|
|
46
|
+
const serverKnowledge = budget.current_server_knowledge ?? 0;
|
|
47
|
+
const lookups = buildLookups(budget.changed_entities ?? {});
|
|
48
|
+
const existing = budget.changed_entities?.be_transactions?.find(t => t.id === params.transaction_id && !t.is_tombstone);
|
|
49
|
+
if (!existing) {
|
|
50
|
+
throw ToolError.notFound(`Transaction not found: ${params.transaction_id}`);
|
|
51
|
+
}
|
|
52
|
+
if (existing.transfer_account_id) {
|
|
53
|
+
throw ToolError.validation('Cannot update transfer transactions — edit them in YNAB directly.');
|
|
54
|
+
}
|
|
55
|
+
const hasSubtransactions = (budget.changed_entities?.be_subtransactions ?? []).some(s => s.entities_transaction_id === params.transaction_id && !s.is_tombstone);
|
|
56
|
+
if (hasSubtransactions) {
|
|
57
|
+
throw ToolError.validation('Cannot update split transactions — edit them in YNAB directly.');
|
|
58
|
+
}
|
|
59
|
+
const changedEntities = {};
|
|
60
|
+
let payeeId = params.payee_id ?? existing.entities_payee_id ?? null;
|
|
61
|
+
if (params.payee_name && !params.payee_id) {
|
|
62
|
+
const resolved = resolvePayee(budget.changed_entities?.be_payees ?? [], params.payee_name);
|
|
63
|
+
payeeId = resolved.payeeId;
|
|
64
|
+
if (resolved.newPayee) {
|
|
65
|
+
changedEntities.be_payees = [resolved.newPayee];
|
|
66
|
+
lookups.payees.set(resolved.payeeId, params.payee_name);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
changedEntities.be_transaction_groups = [
|
|
70
|
+
{
|
|
71
|
+
id: params.transaction_id,
|
|
72
|
+
be_transaction: {
|
|
73
|
+
id: params.transaction_id,
|
|
74
|
+
is_tombstone: false,
|
|
75
|
+
entities_account_id: params.account_id,
|
|
76
|
+
entities_payee_id: payeeId,
|
|
77
|
+
entities_subcategory_id: params.category_id ?? existing.entities_subcategory_id ?? null,
|
|
78
|
+
entities_scheduled_transaction_id: existing.entities_scheduled_transaction_id ?? null,
|
|
79
|
+
date: params.date ?? existing.date ?? '',
|
|
80
|
+
date_entered_from_schedule: null,
|
|
81
|
+
amount: params.amount !== undefined ? toMilliunits(params.amount) : (existing.amount ?? 0),
|
|
82
|
+
cash_amount: 0,
|
|
83
|
+
credit_amount: 0,
|
|
84
|
+
credit_amount_adjusted: 0,
|
|
85
|
+
subcategory_credit_amount_preceding: 0,
|
|
86
|
+
memo: params.memo ?? existing.memo ?? null,
|
|
87
|
+
cleared: resolveCleared(params.cleared, existing.cleared),
|
|
88
|
+
// YNAB's wire format calls this "accepted"; the public tool surface uses "approved".
|
|
89
|
+
accepted: params.approved ?? existing.accepted ?? false,
|
|
90
|
+
check_number: null,
|
|
91
|
+
flag: resolveFlag(params.flag_color, existing.flag),
|
|
92
|
+
transfer_account_id: existing.transfer_account_id ?? null,
|
|
93
|
+
transfer_transaction_id: null,
|
|
94
|
+
transfer_subtransaction_id: null,
|
|
95
|
+
matched_transaction_id: null,
|
|
96
|
+
ynab_id: existing.ynab_id ?? null,
|
|
97
|
+
imported_payee: existing.imported_payee ?? null,
|
|
98
|
+
imported_date: null,
|
|
99
|
+
original_imported_payee: existing.original_imported_payee ?? null,
|
|
100
|
+
provider_cleansed_payee: null,
|
|
101
|
+
source: existing.source ?? null,
|
|
102
|
+
debt_transaction_type: null,
|
|
103
|
+
},
|
|
104
|
+
be_subtransactions: null,
|
|
105
|
+
},
|
|
106
|
+
];
|
|
107
|
+
const result = await syncWrite(planId, changedEntities, serverKnowledge);
|
|
108
|
+
const saved = result.changed_entities?.be_transactions?.find(t => t.id === params.transaction_id);
|
|
56
109
|
if (!saved) {
|
|
57
110
|
throw ToolError.internal('Transaction was updated but no data was returned');
|
|
58
111
|
}
|
|
59
|
-
return { transaction: mapTransaction(saved) };
|
|
112
|
+
return { transaction: mapTransaction(saved, lookups) };
|
|
60
113
|
},
|
|
61
114
|
});
|
|
62
115
|
//# sourceMappingURL=update-transaction.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-transaction.js","sourceRoot":"","sources":["../../src/tools/update-transaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"update-transaction.js","sourceRoot":"","sources":["../../src/tools/update-transaction.ts"],"names":[],"mappings":"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"}
|