@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.
Files changed (92) hide show
  1. package/dist/adapter.iife.js +1315 -545
  2. package/dist/adapter.iife.js.map +4 -4
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +23 -16
  6. package/dist/index.js.map +1 -1
  7. package/dist/tools/create-category-group.d.ts +11 -0
  8. package/dist/tools/create-category-group.d.ts.map +1 -0
  9. package/dist/tools/create-category-group.js +37 -0
  10. package/dist/tools/create-category-group.js.map +1 -0
  11. package/dist/tools/create-category.d.ts +59 -0
  12. package/dist/tools/create-category.d.ts.map +1 -0
  13. package/dist/tools/create-category.js +63 -0
  14. package/dist/tools/create-category.js.map +1 -0
  15. package/dist/tools/create-transaction.d.ts +2 -2
  16. package/dist/tools/create-transaction.d.ts.map +1 -1
  17. package/dist/tools/create-transaction.js +63 -22
  18. package/dist/tools/create-transaction.js.map +1 -1
  19. package/dist/tools/delete-category-group.d.ts +8 -0
  20. package/dist/tools/delete-category-group.d.ts.map +1 -0
  21. package/dist/tools/delete-category-group.js +33 -0
  22. package/dist/tools/delete-category-group.js.map +1 -0
  23. package/dist/tools/delete-category.d.ts +7 -0
  24. package/dist/tools/delete-category.d.ts.map +1 -0
  25. package/dist/tools/delete-category.js +28 -0
  26. package/dist/tools/delete-category.js.map +1 -0
  27. package/dist/tools/delete-transaction.d.ts.map +1 -1
  28. package/dist/tools/delete-transaction.js +22 -7
  29. package/dist/tools/delete-transaction.js.map +1 -1
  30. package/dist/tools/get-account.d.ts.map +1 -1
  31. package/dist/tools/get-account.js +3 -3
  32. package/dist/tools/get-account.js.map +1 -1
  33. package/dist/tools/get-month.d.ts +2 -1
  34. package/dist/tools/get-month.d.ts.map +1 -1
  35. package/dist/tools/get-month.js +10 -33
  36. package/dist/tools/get-month.js.map +1 -1
  37. package/dist/tools/get-plan.d.ts.map +1 -1
  38. package/dist/tools/get-plan.js +12 -5
  39. package/dist/tools/get-plan.js.map +1 -1
  40. package/dist/tools/get-transaction.d.ts +2 -2
  41. package/dist/tools/get-transaction.d.ts.map +1 -1
  42. package/dist/tools/get-transaction.js +5 -4
  43. package/dist/tools/get-transaction.js.map +1 -1
  44. package/dist/tools/list-accounts.d.ts.map +1 -1
  45. package/dist/tools/list-accounts.js +4 -4
  46. package/dist/tools/list-accounts.js.map +1 -1
  47. package/dist/tools/list-categories.d.ts.map +1 -1
  48. package/dist/tools/list-categories.js +9 -29
  49. package/dist/tools/list-categories.js.map +1 -1
  50. package/dist/tools/list-months.d.ts +1 -1
  51. package/dist/tools/list-months.d.ts.map +1 -1
  52. package/dist/tools/list-months.js +5 -14
  53. package/dist/tools/list-months.js.map +1 -1
  54. package/dist/tools/list-payees.d.ts.map +1 -1
  55. package/dist/tools/list-payees.js +3 -3
  56. package/dist/tools/list-payees.js.map +1 -1
  57. package/dist/tools/list-scheduled-transactions.d.ts.map +1 -1
  58. package/dist/tools/list-scheduled-transactions.js +7 -5
  59. package/dist/tools/list-scheduled-transactions.js.map +1 -1
  60. package/dist/tools/list-transactions.d.ts +4 -2
  61. package/dist/tools/list-transactions.d.ts.map +1 -1
  62. package/dist/tools/list-transactions.js +40 -8
  63. package/dist/tools/list-transactions.js.map +1 -1
  64. package/dist/tools/move-category-budget.d.ts +24 -0
  65. package/dist/tools/move-category-budget.d.ts.map +1 -0
  66. package/dist/tools/move-category-budget.js +100 -0
  67. package/dist/tools/move-category-budget.js.map +1 -0
  68. package/dist/tools/schemas.d.ts +185 -28
  69. package/dist/tools/schemas.d.ts.map +1 -1
  70. package/dist/tools/schemas.js +411 -28
  71. package/dist/tools/schemas.js.map +1 -1
  72. package/dist/tools/snooze-category-goal.d.ts +10 -0
  73. package/dist/tools/snooze-category-goal.d.ts.map +1 -0
  74. package/dist/tools/snooze-category-goal.js +53 -0
  75. package/dist/tools/snooze-category-goal.js.map +1 -0
  76. package/dist/tools/update-category-budget.d.ts.map +1 -1
  77. package/dist/tools/update-category-budget.js +51 -26
  78. package/dist/tools/update-category-budget.js.map +1 -1
  79. package/dist/tools/update-category.d.ts +61 -0
  80. package/dist/tools/update-category.d.ts.map +1 -0
  81. package/dist/tools/update-category.js +46 -0
  82. package/dist/tools/update-category.js.map +1 -0
  83. package/dist/tools/update-transaction.d.ts +3 -2
  84. package/dist/tools/update-transaction.d.ts.map +1 -1
  85. package/dist/tools/update-transaction.js +84 -31
  86. package/dist/tools/update-transaction.js.map +1 -1
  87. package/dist/tools.json +965 -43
  88. package/dist/ynab-api.d.ts +4 -1
  89. package/dist/ynab-api.d.ts.map +1 -1
  90. package/dist/ynab-api.js +47 -26
  91. package/dist/ynab-api.js.map +1 -1
  92. 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;AAIxB,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;kBA0D/B,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, mapCategory } from './schemas.js';
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.string().min(1).describe('Month in YYYY-MM format (e.g. 2026-03)'),
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 milliunits = Math.round(params.budgeted * 1000);
23
- // Month in budget IDs uses YYYY-MM format
24
- const monthKey = params.month.substring(0, 7);
25
- const budgetId = `mcb/${monthKey}/${params.category_id}`;
26
- const monthlyBudgetId = `mb/${monthKey}/${planId}`;
27
- const result = await syncWrite(planId, {
28
- be_monthly_subcategory_budgets: [
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: budgetId,
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
- // The sync write returns the updated budget entity
40
- const budgets = result.changed_entities?.be_monthly_subcategory_budgets;
41
- const updatedBudget = budgets?.[0]?.budgeted ?? milliunits;
42
- return {
43
- category: mapCategory({
44
- id: params.category_id,
45
- budgeted: updatedBudget,
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;AACtD,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,CAAC,MAAM,oBAAoB,GAAG,UAAU,CAAC;IAC7C,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EAAE,wBAAwB;IACrC,WAAW,EACT,yLAAyL;IAC3L,OAAO,EAAE,oCAAoC;IAC7C,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,YAAY;IACnB,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QAChE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,wCAAwC,CAAC;QAC3E,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wDAAwD,CAAC;KACxF,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,QAAQ,EAAE,cAAc;KACzB,CAAC;IACF,MAAM,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;QACrB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;QAEtD,0CAA0C;QAC1C,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,OAAO,QAAQ,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACzD,MAAM,eAAe,GAAG,MAAM,QAAQ,IAAI,MAAM,EAAE,CAAC;QAEnD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE;YACrC,8BAA8B,EAAE;gBAC9B;oBACE,EAAE,EAAE,QAAQ;oBACZ,0BAA0B,EAAE,eAAe;oBAC3C,uBAAuB,EAAE,MAAM,CAAC,WAAW;oBAC3C,QAAQ,EAAE,UAAU;oBACpB,qBAAqB,EAAE,eAAe;oBACtC,YAAY,EAAE,KAAK;iBACpB;aACF;SACF,CAAC,CAAC;QAEH,mDAAmD;QACnD,MAAM,OAAO,GACX,MAOD,CAAC,gBAAgB,EAAE,8BAA8B,CAAC;QAEnD,MAAM,aAAa,GAAG,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,IAAI,UAAU,CAAC;QAE3D,OAAO;YACL,QAAQ,EAAE,WAAW,CAAC;gBACpB,EAAE,EAAE,MAAM,CAAC,WAAW;gBACtB,QAAQ,EAAE,aAAa;aACxB,CAAC;SACH,CAAC;IACJ,CAAC;CACF,CAAC,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
- import_id: z.ZodString;
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;AAWxB,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAqD5B,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.enum(['red', 'orange', 'yellow', 'green', 'blue', 'purple']).optional().describe('New flag color'),
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 transaction = {
31
- id: params.transaction_id,
32
- entities_account_id: params.account_id,
33
- };
34
- if (params.date !== undefined)
35
- transaction.date = params.date;
36
- if (params.amount !== undefined)
37
- transaction.amount = Math.round(params.amount * 1000);
38
- if (params.payee_name !== undefined)
39
- transaction.payee_name = params.payee_name;
40
- if (params.payee_id !== undefined)
41
- transaction.entities_payee_id = params.payee_id;
42
- if (params.category_id !== undefined)
43
- transaction.entities_subcategory_id = params.category_id;
44
- if (params.memo !== undefined)
45
- transaction.memo = params.memo;
46
- if (params.cleared !== undefined)
47
- transaction.cleared = params.cleared;
48
- if (params.approved !== undefined)
49
- transaction.approved = params.approved;
50
- if (params.flag_color !== undefined)
51
- transaction.flag_color = params.flag_color;
52
- const result = await syncWrite(planId, {
53
- be_transactions: [transaction],
54
- });
55
- const saved = result.changed_entities?.be_transactions?.[0];
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":"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"}
1
+ {"version":3,"file":"update-transaction.js","sourceRoot":"","sources":["../../src/tools/update-transaction.ts"],"names":[],"mappings":"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"}