@slothmoney/agent-cli 0.13.0 → 0.14.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.14.0 - 2026-08-20
4
+
5
+ - Add `transactions --account-ref REF` using the opaque reference returned by
6
+ `sloth-agent accounts`, while retaining `--account-id` for compatibility.
7
+ - Require every transaction result to include its matching `accountRef`.
8
+
3
9
  ## 0.13.0 - 2026-08-19
4
10
 
5
11
  - Let `assign` share or unshare an owned booked personal transaction, update
package/README.md CHANGED
@@ -15,7 +15,7 @@ sloth-agent --version
15
15
  For a one-off pinned run:
16
16
 
17
17
  ```bash
18
- npm exec --yes --package=@slothmoney/agent-cli@0.13.0 -- sloth-agent --help
18
+ npm exec --yes --package=@slothmoney/agent-cli@0.14.0 -- sloth-agent --help
19
19
  ```
20
20
 
21
21
  ## Authenticate
@@ -471,6 +471,20 @@ Missing values are JSON
471
471
  are excluded, while enabled shared joint accounts follow Sloth's existing
472
472
  visibility rules.
473
473
 
474
+ Use an account's opaque reference to read only its transactions. Transaction
475
+ rows return the same `accountRef`, so pagination and follow-up reads keep the
476
+ account boundary explicit:
477
+
478
+ ```bash
479
+ sloth-agent transactions \
480
+ --account-ref PASTE_THE_EXACT_ACCOUNT_REF_HERE \
481
+ --limit 50
482
+ ```
483
+
484
+ Copy the value from `sloth-agent accounts`. The older `--account-id` filter is
485
+ still accepted for compatibility, but new workflows should use
486
+ `--account-ref`. Do not provide both filters in one command.
487
+
474
488
  Account changes are previews unless `--apply` is present. Connected accounts
475
489
  support only goal-savings membership. Manual current accounts support their
476
490
  institution, name, currency, and ownership. Manual balance accounts also
@@ -0,0 +1,4 @@
1
+ const ACCOUNT_REF_PATTERN = /^sloth_account_v1_[A-Za-z0-9_-]{43}$/;
2
+ export function isAccountRef(value) {
3
+ return typeof value === 'string' && ACCOUNT_REF_PATTERN.test(value);
4
+ }
package/dist/args.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { UsageError } from './errors.js';
2
+ import { isAccountRef } from './account-ref.js';
2
3
  import { CATEGORY_TYPES, ICON_KEYS, } from './category-metadata.js';
3
4
  import { isGoalType, } from './goal-metadata.js';
4
5
  const PRODUCTION_BASE_URL = 'https://budget.slothmoney.app';
@@ -175,6 +176,7 @@ function parseTransactions(args) {
175
176
  '--start-date',
176
177
  '--end-date',
177
178
  '--q',
179
+ '--account-ref',
178
180
  '--account-id',
179
181
  '--category-id',
180
182
  '--line-item-id',
@@ -208,6 +210,9 @@ function parseTransactions(args) {
208
210
  else if (name === '--q') {
209
211
  filters.q = setOnce(filters.q, value, name);
210
212
  }
213
+ else if (name === '--account-ref') {
214
+ filters.accountRef = setOnce(filters.accountRef, parseAccountRef(value), name);
215
+ }
211
216
  else if (name === '--account-id') {
212
217
  filters.accountId = setOnce(filters.accountId, value, name);
213
218
  }
@@ -232,6 +237,9 @@ function parseTransactions(args) {
232
237
  && filters.endDate < filters.startDate) {
233
238
  throw new UsageError('--end-date must not be before --start-date');
234
239
  }
240
+ if (filters.accountRef !== undefined && filters.accountId !== undefined) {
241
+ throw new UsageError('Use either --account-ref or --account-id, not both');
242
+ }
235
243
  return filters;
236
244
  }
237
245
  function parseNamedOptions(args, commandLabel, allowed) {
@@ -267,7 +275,7 @@ function requiredOption(values, option, commandLabel) {
267
275
  return value;
268
276
  }
269
277
  function parseAccountRef(value) {
270
- if (!/^sloth_account_v1_[A-Za-z0-9_-]{43}$/.test(value)) {
278
+ if (!isAccountRef(value)) {
271
279
  throw new UsageError('--account-ref must be a valid accountRef from sloth-agent accounts');
272
280
  }
273
281
  return value;
package/dist/cli.js CHANGED
@@ -4,7 +4,7 @@ import { ICON_KEYS } from './category-metadata.js';
4
4
  import { parseApiResponse, validateAssignmentPayload, validateBudgetMovementResponse, validateBudgetUpdatePayload, } from './contracts.js';
5
5
  import { createSystemCredentialStore, secureStorageUnavailableError, } from './credential-store.js';
6
6
  import { ApiError, CliError, ConfigError, UsageError, } from './errors.js';
7
- export const CLI_VERSION = '0.13.0';
7
+ export const CLI_VERSION = '0.14.0';
8
8
  const REQUEST_TIMEOUT_MS = 60_000;
9
9
  const API_ORIGIN_HELP_LINES = [
10
10
  '',
@@ -42,7 +42,7 @@ export function usageText() {
42
42
  ' sloth-agent line-items rename --scope personal|joint --category-id ID --line-item-id ID --name NAME [--apply]',
43
43
  ' sloth-agent transactions [--uncategorized[=true|false]] [--shared[=true|false]] [--limit N]',
44
44
  ' [--start-date YYYY-MM-DD] [--end-date YYYY-MM-DD] [--q TEXT]',
45
- ' [--account-id ID] [--category-id ID] [--line-item-id ID]',
45
+ ' [--account-ref REF] [--account-id ID] [--category-id ID] [--line-item-id ID]',
46
46
  ' [--cursor CURSOR] [--base-url URL]',
47
47
  ' sloth-agent assign --input assignments.json [--apply] [--base-url URL]',
48
48
  ' sloth-agent goals [list] [--base-url URL]',
@@ -547,7 +547,9 @@ export function transactionsHelpText() {
547
547
  ' --start-date YYYY-MM-DD Optional. Include transactions on or after this date.',
548
548
  ' --end-date YYYY-MM-DD Optional. Include transactions on or before this date.',
549
549
  ' --q TEXT Optional. Search transactions by text.',
550
- ' --account-id ID Optional. Filter by account ID.',
550
+ ' --account-ref REF Optional. Filter by the opaque accountRef from sloth-agent accounts.',
551
+ ' Copy the exact sloth_account_v1_... value.',
552
+ ' --account-id ID Optional legacy filter by provider or stored account ID.',
551
553
  ' --category-id ID Optional. Filter by category ID.',
552
554
  ' --line-item-id ID Optional. Filter primary or split assignments by line-item ID.',
553
555
  ' --assignment-scope SCOPE Optional. Filter assignments by personal or joint.',
@@ -559,6 +561,7 @@ export function transactionsHelpText() {
559
561
  '',
560
562
  'Constraints:',
561
563
  ' All filters are omitted by default.',
564
+ ' Use either --account-ref or --account-id, not both.',
562
565
  ' --end-date must not be before --start-date.',
563
566
  ' The first transaction read each UTC day may refresh linked bank data.',
564
567
  ' Refresh remotely persists booked transactions and account balances.',
@@ -566,6 +569,7 @@ export function transactionsHelpText() {
566
569
  '',
567
570
  'Output:',
568
571
  ' JSON containing transactions, nextCursor, and structured refresh status.',
572
+ ' Every transaction includes accountRef for its originating account.',
569
573
  ' Refresh failures do not hide readable cached transactions.',
570
574
  ' Personal assignments use the top-level categoryId, lineItemId, and categorySplits.',
571
575
  ' Joint assignments appear under jointBudgetContribution.',
@@ -1034,6 +1038,8 @@ function buildTransactionsQuery(filters) {
1034
1038
  params.set('endDate', filters.endDate);
1035
1039
  if (filters.q !== undefined)
1036
1040
  params.set('q', filters.q);
1041
+ if (filters.accountRef !== undefined)
1042
+ params.set('accountRef', filters.accountRef);
1037
1043
  if (filters.accountId !== undefined)
1038
1044
  params.set('accountId', filters.accountId);
1039
1045
  if (filters.categoryId !== undefined)
package/dist/contracts.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { ApiError, UsageError, } from './errors.js';
2
+ import { isAccountRef } from './account-ref.js';
2
3
  import { CATEGORY_TYPES, ICON_KEYS } from './category-metadata.js';
3
4
  import { isGoalType } from './goal-metadata.js';
4
5
  function isObject(value) {
@@ -252,6 +253,7 @@ function isTransaction(value) {
252
253
  && typeof value.currency === 'string'
253
254
  && typeof value.date === 'string'
254
255
  && value.status === 'booked'
256
+ && isAccountRef(value.accountRef)
255
257
  && typeof value.accountId === 'string'
256
258
  && typeof value.accountDocId === 'string'
257
259
  && typeof value.requisitionId === 'string'
@@ -621,8 +623,7 @@ function isAccount(value) {
621
623
  'connectionState',
622
624
  'isGoalSavingsSource',
623
625
  ])
624
- && typeof value.accountRef === 'string'
625
- && /^sloth_account_v1_[A-Za-z0-9_-]{43}$/.test(value.accountRef)
626
+ && isAccountRef(value.accountRef)
626
627
  && isNullableNonEmptyString(value.accountName)
627
628
  && isNullableNonEmptyString(value.institutionName)
628
629
  && (value.accountType === 'current'
@@ -659,8 +660,7 @@ function isAccountRemovalResponse(value) {
659
660
  && hasOnlyFields(value, ['removed', 'changed', 'accountRef'])
660
661
  && value.removed === true
661
662
  && typeof value.changed === 'boolean'
662
- && typeof value.accountRef === 'string'
663
- && /^sloth_account_v1_[A-Za-z0-9_-]{43}$/.test(value.accountRef));
663
+ && isAccountRef(value.accountRef));
664
664
  }
665
665
  function isInvestmentHolding(value) {
666
666
  return (isObject(value)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slothmoney/agent-cli",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "Command-line access to the Sloth Money Agent API.",
5
5
  "type": "module",
6
6
  "bin": {