@slothmoney/agent-cli 0.3.0 → 0.3.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.3.1 - 2026-07-31
6
+
7
+ - Coordinate transaction reads with the Sloth Budget daily refresh process.
8
+ - Wait up to 45 seconds for fresh persisted data, then return readable cached
9
+ transactions with structured refresh status when work continues or fails.
10
+ - Validate the additive transaction refresh response contract.
11
+
5
12
  ## 0.3.0 - 2026-07-30
6
13
 
7
14
  - Add command-specific help for every command and auth subcommand, including
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.3.0 -- sloth-agent --help
18
+ npm exec --yes --package=@slothmoney/agent-cli@0.3.1 -- sloth-agent --help
19
19
  ```
20
20
 
21
21
  ## Authenticate
@@ -221,6 +221,25 @@ Read uncategorised contributions to the joint budget:
221
221
  sloth-agent transactions --assignment-scope joint --uncategorized
222
222
  ```
223
223
 
224
+ The first transaction read after the UTC day changes may refresh linked bank
225
+ data. The CLI waits up to 45 seconds for that refresh to persist, then returns
226
+ the requested booked transactions. If the refresh is still running, partially
227
+ fails, or fails globally, readable cached transactions are still returned with
228
+ a structured `refresh` object:
229
+
230
+ ```json
231
+ {
232
+ "refresh": {
233
+ "status": "in_progress",
234
+ "reason": "wait_timeout",
235
+ "utcDate": "2026-07-31"
236
+ }
237
+ }
238
+ ```
239
+
240
+ Re-run the transaction query later to observe the completed refresh. A partial
241
+ account failure remains eligible for an automatic retry.
242
+
224
243
  Set `"assignmentScope": "joint"` on an assignment to categorise the eligible
225
244
  shared portion for the joint budget.
226
245
 
package/dist/cli.js CHANGED
@@ -3,8 +3,8 @@ import { parseArgs, resolveBaseUrl, } from './args.js';
3
3
  import { parseApiResponse, validateAssignmentPayload, validateJointBudgetSettingsResponse, } from './contracts.js';
4
4
  import { createSystemCredentialStore, secureStorageUnavailableError, } from './credential-store.js';
5
5
  import { ApiError, CliError, ConfigError, UsageError, } from './errors.js';
6
- export const CLI_VERSION = '0.3.0';
7
- const REQUEST_TIMEOUT_MS = 30_000;
6
+ export const CLI_VERSION = '0.3.1';
7
+ const REQUEST_TIMEOUT_MS = 60_000;
8
8
  const API_ORIGIN_HELP_LINES = [
9
9
  '',
10
10
  'API origin:',
@@ -208,10 +208,14 @@ export function transactionsHelpText() {
208
208
  'Constraints:',
209
209
  ' All filters are omitted by default.',
210
210
  ' --end-date must not be before --start-date.',
211
- ' This command is read-only.',
211
+ ' The first transaction read each UTC day may refresh linked bank data.',
212
+ ' Refresh remotely persists booked transactions and account balances.',
213
+ ' The command waits up to 45 seconds, then returns cached data if refresh continues.',
212
214
  '',
213
215
  'Output:',
214
- ' JSON containing transactions and nextCursor. Use nextCursor with --cursor',
216
+ ' JSON containing transactions, nextCursor, and structured refresh status.',
217
+ ' Refresh failures do not hide readable cached transactions.',
218
+ ' Use nextCursor with --cursor',
215
219
  ' to request the next page. A null nextCursor means there are no more pages.',
216
220
  '',
217
221
  'Examples:',
@@ -905,7 +909,9 @@ export async function runCli(argv = process.argv.slice(2), options = {}) {
905
909
  })()}`;
906
910
  const response = await fetchImplementation(`${baseUrl}${path}`, {
907
911
  method: 'GET',
908
- headers,
912
+ headers: parsed.command === 'transactions'
913
+ ? { ...headers, Prefer: 'wait=45' }
914
+ : headers,
909
915
  signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
910
916
  });
911
917
  const data = parseApiResponse(parsed.command, await parseHttpResponse(response, token));
package/dist/contracts.js CHANGED
@@ -2,6 +2,12 @@ import { ApiError, UsageError, } from './errors.js';
2
2
  function isObject(value) {
3
3
  return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
4
4
  }
5
+ function isIsoDate(value) {
6
+ if (typeof value !== 'string' || !/^\d{4}-\d{2}-\d{2}$/.test(value))
7
+ return false;
8
+ const parsed = new Date(`${value}T00:00:00.000Z`);
9
+ return !Number.isNaN(parsed.valueOf()) && parsed.toISOString().slice(0, 10) === value;
10
+ }
5
11
  function requireObject(value, label) {
6
12
  if (!isObject(value))
7
13
  throw new UsageError(`${label} must be an object`);
@@ -158,10 +164,27 @@ function isTransaction(value) {
158
164
  || value.incomeSubtype === 'interest'));
159
165
  }
160
166
  function isTransactionsResponse(value) {
167
+ const validStatuses = new Set(['skipped', 'completed', 'in_progress', 'partial', 'failed']);
168
+ const validReasons = new Set([
169
+ 'all_fetched_today',
170
+ 'no_api_connections',
171
+ 'no_selected_accounts',
172
+ 'refreshed',
173
+ 'wait_timeout',
174
+ 'account_failures',
175
+ 'refresh_error',
176
+ ]);
177
+ const refresh = isObject(value) ? value.refresh : undefined;
161
178
  return (isObject(value)
162
179
  && Array.isArray(value.transactions)
163
180
  && value.transactions.every(isTransaction)
164
- && (value.nextCursor === null || typeof value.nextCursor === 'string'));
181
+ && (value.nextCursor === null || typeof value.nextCursor === 'string')
182
+ && isObject(refresh)
183
+ && typeof refresh.status === 'string'
184
+ && validStatuses.has(refresh.status)
185
+ && typeof refresh.reason === 'string'
186
+ && validReasons.has(refresh.reason)
187
+ && isIsoDate(refresh.utcDate));
165
188
  }
166
189
  function isAssignmentResponse(value) {
167
190
  return (isObject(value)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slothmoney/agent-cli",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Command-line access to the Sloth Money Agent API.",
5
5
  "type": "module",
6
6
  "bin": {