@slothmoney/agent-cli 0.7.0 → 0.8.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 +7 -0
- package/README.md +14 -3
- package/dist/args.js +26 -2
- package/dist/cli.js +35 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.8.0 - 2026-08-12
|
|
6
|
+
|
|
7
|
+
- Read each goal's one-based priority and move one goal to a new position with
|
|
8
|
+
automatic shifting of the intervening goals.
|
|
9
|
+
|
|
10
|
+
## 0.7.0 - 2026-08-09
|
|
11
|
+
|
|
5
12
|
- Read personal or joint budget periods with categories, line items, funding,
|
|
6
13
|
and planned amounts.
|
|
7
14
|
- Preview or apply planned line-item updates that overwrite the selected period
|
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.
|
|
18
|
+
npm exec --yes --package=@slothmoney/agent-cli@0.8.0 -- sloth-agent --help
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
## Authenticate
|
|
@@ -355,7 +355,7 @@ sloth-agent goals create \
|
|
|
355
355
|
--apply
|
|
356
356
|
```
|
|
357
357
|
|
|
358
|
-
Use the `id` from list or create output to update or delete
|
|
358
|
+
Use the `id` from list or create output to update or delete goals:
|
|
359
359
|
|
|
360
360
|
```bash
|
|
361
361
|
sloth-agent goals update \
|
|
@@ -365,6 +365,11 @@ sloth-agent goals update \
|
|
|
365
365
|
--achieved=false \
|
|
366
366
|
--apply
|
|
367
367
|
|
|
368
|
+
sloth-agent goals update \
|
|
369
|
+
--goal-id house-goal-id \
|
|
370
|
+
--priority 2 \
|
|
371
|
+
--apply
|
|
372
|
+
|
|
368
373
|
sloth-agent goals delete --goal-id goal-id --apply
|
|
369
374
|
```
|
|
370
375
|
|
|
@@ -373,7 +378,13 @@ remove an optional value. Marking a goal achieved removes its forecast
|
|
|
373
378
|
assignment. Deleting a goal also removes its forecast assignments and drift
|
|
374
379
|
history. Goal sharing remains app-managed. Change an active shared goal's
|
|
375
380
|
pot-tracked target amount in the Sloth Budget app, where account balances can
|
|
376
|
-
be reallocated across goals in priority order.
|
|
381
|
+
be reallocated across goals in priority order. Goal list output includes a
|
|
382
|
+
one-based `priority`; `1` is highest. Moving one goal automatically shifts the
|
|
383
|
+
goals between its old and new positions. The
|
|
384
|
+
priority option must be used on its own, and the write persists immediately.
|
|
385
|
+
Forecast assignments and shared pot
|
|
386
|
+
progress are browser-owned derived state and refresh when the owner next opens
|
|
387
|
+
the Forecast screen.
|
|
377
388
|
|
|
378
389
|
Read uncategorised contributions to the joint budget:
|
|
379
390
|
|
package/dist/args.js
CHANGED
|
@@ -64,6 +64,16 @@ function parseGoalMonthKey(value, name) {
|
|
|
64
64
|
}
|
|
65
65
|
return value;
|
|
66
66
|
}
|
|
67
|
+
function parseGoalPriority(value) {
|
|
68
|
+
if (!/^[1-9]\d*$/.test(value)) {
|
|
69
|
+
throw new UsageError('--priority must be a positive whole-number position');
|
|
70
|
+
}
|
|
71
|
+
const priority = Number(value);
|
|
72
|
+
if (!Number.isSafeInteger(priority)) {
|
|
73
|
+
throw new UsageError('--priority must be a positive whole-number position');
|
|
74
|
+
}
|
|
75
|
+
return priority;
|
|
76
|
+
}
|
|
67
77
|
function parseExplicitBoolean(value, name) {
|
|
68
78
|
if (value !== 'true' && value !== 'false') {
|
|
69
79
|
throw new UsageError(`${name} must be true or false`);
|
|
@@ -467,6 +477,7 @@ function parseGoals(args, baseUrl) {
|
|
|
467
477
|
let targetAmount;
|
|
468
478
|
let targetMonthKey;
|
|
469
479
|
let isAchieved;
|
|
480
|
+
let priority;
|
|
470
481
|
let apply = false;
|
|
471
482
|
for (let index = 0; index < args.length; index += 1) {
|
|
472
483
|
const argument = args[index];
|
|
@@ -497,7 +508,8 @@ function parseGoals(args, baseUrl) {
|
|
|
497
508
|
&& option !== '--name'
|
|
498
509
|
&& option !== '--target-amount'
|
|
499
510
|
&& option !== '--target-month'
|
|
500
|
-
&& option !== '--achieved'
|
|
511
|
+
&& option !== '--achieved'
|
|
512
|
+
&& option !== '--priority') {
|
|
501
513
|
throw new UsageError(`Unknown goals update option: ${argument}`);
|
|
502
514
|
}
|
|
503
515
|
const value = requireNonEmpty(inlineValue ?? readOptionValue(args, index, option), option);
|
|
@@ -521,6 +533,9 @@ function parseGoals(args, baseUrl) {
|
|
|
521
533
|
}
|
|
522
534
|
targetMonthKey = parseGoalMonthKey(value, option);
|
|
523
535
|
}
|
|
536
|
+
else if (option === '--priority') {
|
|
537
|
+
priority = setOnce(priority, parseGoalPriority(value), option);
|
|
538
|
+
}
|
|
524
539
|
else {
|
|
525
540
|
isAchieved = setOnce(isAchieved, parseExplicitBoolean(value, option), option);
|
|
526
541
|
}
|
|
@@ -530,9 +545,17 @@ function parseGoals(args, baseUrl) {
|
|
|
530
545
|
if (name === undefined
|
|
531
546
|
&& targetAmount === undefined
|
|
532
547
|
&& targetMonthKey === undefined
|
|
533
|
-
&& isAchieved === undefined
|
|
548
|
+
&& isAchieved === undefined
|
|
549
|
+
&& priority === undefined) {
|
|
534
550
|
throw new UsageError('goals update requires at least one field to update');
|
|
535
551
|
}
|
|
552
|
+
if (priority !== undefined
|
|
553
|
+
&& (name !== undefined
|
|
554
|
+
|| targetAmount !== undefined
|
|
555
|
+
|| targetMonthKey !== undefined
|
|
556
|
+
|| isAchieved !== undefined)) {
|
|
557
|
+
throw new UsageError('--priority must be used on its own');
|
|
558
|
+
}
|
|
536
559
|
return withBaseUrl({
|
|
537
560
|
command: 'goals-update',
|
|
538
561
|
goalId,
|
|
@@ -540,6 +563,7 @@ function parseGoals(args, baseUrl) {
|
|
|
540
563
|
...(targetAmount === undefined ? {} : { targetAmount }),
|
|
541
564
|
...(targetMonthKey === undefined ? {} : { targetMonthKey }),
|
|
542
565
|
...(isAchieved === undefined ? {} : { isAchieved }),
|
|
566
|
+
...(priority === undefined ? {} : { priority }),
|
|
543
567
|
apply,
|
|
544
568
|
}, baseUrl);
|
|
545
569
|
}
|
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import { ICON_KEYS } from './category-metadata.js';
|
|
|
4
4
|
import { parseApiResponse, validateAssignmentPayload, 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.
|
|
7
|
+
export const CLI_VERSION = '0.8.0';
|
|
8
8
|
const REQUEST_TIMEOUT_MS = 60_000;
|
|
9
9
|
const API_ORIGIN_HELP_LINES = [
|
|
10
10
|
'',
|
|
@@ -562,7 +562,7 @@ export function goalsListHelpText() {
|
|
|
562
562
|
' This command is read-only.',
|
|
563
563
|
'',
|
|
564
564
|
'Output:',
|
|
565
|
-
' JSON containing currency and goals. Each goal contains id, name,',
|
|
565
|
+
' JSON containing currency and goals. Each goal contains id, name, priority,',
|
|
566
566
|
' targetAmount, targetMonthKey, isAchieved, and sharedWithPartner.',
|
|
567
567
|
].join('\n');
|
|
568
568
|
}
|
|
@@ -615,6 +615,7 @@ export function goalsUpdateHelpText() {
|
|
|
615
615
|
' --target-month YYYY-MM Optional. Replace the target month.',
|
|
616
616
|
' --clear-target-month Optional. Remove the target month.',
|
|
617
617
|
' --achieved=true|false Optional. Mark the goal achieved or active.',
|
|
618
|
+
' --priority POSITION Optional. Positive whole-number position; 1 is highest.',
|
|
618
619
|
' --apply Optional. Write the partial update.',
|
|
619
620
|
' --base-url URL Optional. Override the API origin.',
|
|
620
621
|
' -h, --help Show this help.',
|
|
@@ -622,6 +623,11 @@ export function goalsUpdateHelpText() {
|
|
|
622
623
|
'',
|
|
623
624
|
'Constraints:',
|
|
624
625
|
' Provide at least one field to update.',
|
|
626
|
+
' Priority must be updated on its own.',
|
|
627
|
+
' Priority 1 is highest. The position cannot exceed the current goal count.',
|
|
628
|
+
' Moving a goal shifts the intervening goals automatically.',
|
|
629
|
+
' Forecast assignments and shared progress refresh when the owner next opens',
|
|
630
|
+
' the Forecast screen.',
|
|
625
631
|
' Set and clear options for the same field are mutually exclusive.',
|
|
626
632
|
' Marking a goal achieved removes its forecast assignment.',
|
|
627
633
|
' Marking it active again does not restore the previous assignment.',
|
|
@@ -634,6 +640,9 @@ export function goalsUpdateHelpText() {
|
|
|
634
640
|
' Without --apply, the command returns a dry-run preview and does not write.',
|
|
635
641
|
' Applying requires a write-enabled token created with Allow changes.',
|
|
636
642
|
'',
|
|
643
|
+
'Example:',
|
|
644
|
+
' sloth-agent goals update --goal-id goal-3 --priority 2 --apply',
|
|
645
|
+
'',
|
|
637
646
|
'Output:',
|
|
638
647
|
' Preview mode returns dryRun, method, endpoint, and payload.',
|
|
639
648
|
' Apply mode returns the complete persisted goal and currency.',
|
|
@@ -724,6 +733,23 @@ export function commandHelpText(topic) {
|
|
|
724
733
|
function writeJson(write, data) {
|
|
725
734
|
write(`${JSON.stringify(data, null, 2)}\n`);
|
|
726
735
|
}
|
|
736
|
+
function withListedGoalPriorities(value) {
|
|
737
|
+
const response = value;
|
|
738
|
+
return {
|
|
739
|
+
...response,
|
|
740
|
+
goals: response.goals.map((goal, index) => ({
|
|
741
|
+
...goal,
|
|
742
|
+
priority: index + 1,
|
|
743
|
+
})),
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
function withUpdatedGoalPriority(value, priority) {
|
|
747
|
+
const response = value;
|
|
748
|
+
return {
|
|
749
|
+
...response,
|
|
750
|
+
goal: { ...response.goal, priority },
|
|
751
|
+
};
|
|
752
|
+
}
|
|
727
753
|
function redact(value, token) {
|
|
728
754
|
return token ? value.split(token).join('[REDACTED]') : value;
|
|
729
755
|
}
|
|
@@ -1104,6 +1130,9 @@ export async function runCli(argv = process.argv.slice(2), options = {}) {
|
|
|
1104
1130
|
...(parsed.isAchieved === undefined
|
|
1105
1131
|
? {}
|
|
1106
1132
|
: { isAchieved: parsed.isAchieved }),
|
|
1133
|
+
...(parsed.priority === undefined
|
|
1134
|
+
? {}
|
|
1135
|
+
: { priority: parsed.priority }),
|
|
1107
1136
|
};
|
|
1108
1137
|
if (!parsed.apply) {
|
|
1109
1138
|
writeJson(writeStdout, {
|
|
@@ -1124,7 +1153,9 @@ export async function runCli(argv = process.argv.slice(2), options = {}) {
|
|
|
1124
1153
|
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
1125
1154
|
});
|
|
1126
1155
|
const data = parseApiResponse('goals-update', await parseHttpResponse(response, token));
|
|
1127
|
-
writeJson(writeStdout,
|
|
1156
|
+
writeJson(writeStdout, parsed.priority === undefined
|
|
1157
|
+
? data
|
|
1158
|
+
: withUpdatedGoalPriority(data, parsed.priority));
|
|
1128
1159
|
return 0;
|
|
1129
1160
|
}
|
|
1130
1161
|
if (parsed.command === 'goals-delete') {
|
|
@@ -1187,7 +1218,7 @@ export async function runCli(argv = process.argv.slice(2), options = {}) {
|
|
|
1187
1218
|
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
1188
1219
|
});
|
|
1189
1220
|
const data = parseApiResponse('goals-list', await parseHttpResponse(response, token));
|
|
1190
|
-
writeJson(writeStdout, data);
|
|
1221
|
+
writeJson(writeStdout, withListedGoalPriorities(data));
|
|
1191
1222
|
return 0;
|
|
1192
1223
|
}
|
|
1193
1224
|
if (parsed.command === 'budget') {
|