financialclaw 1.0.0 → 1.0.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.
@@ -22,9 +22,20 @@
22
22
  */
23
23
 
24
24
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
25
+ import { createInterface } from "node:readline";
25
26
  import { homedir } from "node:os";
26
27
  import { join, dirname } from "node:path";
27
28
 
29
+ function confirm(question) {
30
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
31
+ return new Promise((resolve) => {
32
+ rl.question(`${question} [y/N] `, (answer) => {
33
+ rl.close();
34
+ resolve(answer.trim().toLowerCase() === "y");
35
+ });
36
+ });
37
+ }
38
+
28
39
  function parseArg(name) {
29
40
  const i = process.argv.indexOf(name);
30
41
  return i !== -1 && process.argv[i + 1] ? process.argv[i + 1] : null;
@@ -72,13 +83,17 @@ const dbPath =
72
83
  parseArg("--db-path") ??
73
84
  join(homedir(), ".openclaw", "workspace", "financialclaw.db");
74
85
 
86
+ const skipConfirm = process.argv.includes("--yes") || process.argv.includes("-y");
87
+
75
88
  const cfg = JSON.parse(readFileSync(configPath, "utf-8"));
76
89
  const plugins = (cfg.plugins ??= {});
90
+ const changes = [];
77
91
 
78
92
  // 1. Ensure plugins.allow includes financialclaw and all active entries
79
93
  // Always rediscover active channels and plugins so re-runs fix missing entries
80
94
  {
81
- const allow = new Set(plugins.allow ?? []);
95
+ const prevAllow = new Set(plugins.allow ?? []);
96
+ const allow = new Set(prevAllow);
82
97
  allow.add("financialclaw");
83
98
 
84
99
  if (cfg.channels) {
@@ -94,7 +109,10 @@ const plugins = (cfg.plugins ??= {});
94
109
  }
95
110
 
96
111
  plugins.allow = [...allow];
97
- console.log(`Updated plugins.allow:`, JSON.stringify(plugins.allow));
112
+ const newEntries = [...allow].filter((e) => !prevAllow.has(e));
113
+ if (newEntries.length > 0) {
114
+ changes.push(`Add to plugins.allow: ${newEntries.join(", ")}`);
115
+ }
98
116
  }
99
117
 
100
118
  // 2. Set dbPath in plugins.entries.financialclaw.config if not already set
@@ -102,12 +120,11 @@ const entries = (plugins.entries ??= {});
102
120
  const fc = (entries.financialclaw ??= { enabled: true, config: {} });
103
121
  fc.config ??= {};
104
122
 
123
+ let dbPathChanged = false;
105
124
  if (!fc.config.dbPath) {
106
- mkdirSync(dirname(dbPath), { recursive: true });
107
125
  fc.config.dbPath = dbPath;
108
- console.log(`Set dbPath: ${dbPath}`);
109
- } else {
110
- console.log(`dbPath already set: ${fc.config.dbPath}`);
126
+ dbPathChanged = true;
127
+ changes.push(`Set database path: ${dbPath}`);
111
128
  }
112
129
 
113
130
  // 3. Ensure tools.profile is "full" so plugin tools are visible to the agent
@@ -115,14 +132,13 @@ if (!fc.config.dbPath) {
115
132
  {
116
133
  const tools = (cfg.tools ??= {});
117
134
  const prev = tools.profile;
118
- if (prev && prev !== "full") {
119
- tools.profile = "full";
120
- console.log(`Updated tools.profile: "${prev}" -> "full" (required for plugin tools)`);
121
- } else if (!prev) {
135
+ if (prev !== "full") {
136
+ changes.push(
137
+ prev
138
+ ? `Change tools.profile: "${prev}" "full" (required for plugin tools to be visible)`
139
+ : `Set tools.profile: "full" (required for plugin tools to be visible)`
140
+ );
122
141
  tools.profile = "full";
123
- console.log(`Set tools.profile: "full"`);
124
- } else {
125
- console.log(`tools.profile already "full"`);
126
142
  }
127
143
  }
128
144
 
@@ -130,10 +146,44 @@ if (!fc.config.dbPath) {
130
146
  {
131
147
  const tools = (cfg.tools ??= {});
132
148
  const toolsAllow = new Set(tools.allow ?? []);
149
+ if (!toolsAllow.has("financialclaw")) {
150
+ changes.push(`Add "financialclaw" to tools.allow`);
151
+ }
133
152
  toolsAllow.add("financialclaw");
134
153
  tools.allow = [...toolsAllow];
135
- console.log(`Updated tools.allow:`, JSON.stringify(tools.allow));
154
+ }
155
+
156
+ // Show summary and confirm before writing
157
+ if (changes.length === 0) {
158
+ console.log("Nothing to change — financialclaw is already configured.");
159
+ process.exit(0);
160
+ }
161
+
162
+ console.log(`\nThe following changes will be applied to ${configPath}:\n`);
163
+ for (const change of changes) {
164
+ console.log(` • ${change}`);
165
+ }
166
+ console.log();
167
+
168
+ if (!skipConfirm) {
169
+ const ok = await confirm("Apply these changes?");
170
+ if (!ok) {
171
+ console.log("\nAborted. No changes were made.");
172
+ console.log("\nTo configure financialclaw manually, add the following to your OpenClaw config:\n");
173
+ console.log(` 1. Add "financialclaw" to plugins.allow`);
174
+ console.log(` 2. Add "financialclaw" to tools.allow`);
175
+ console.log(` 3. Set tools.profile to "full"`);
176
+ console.log(` 4. Set plugins.entries.financialclaw.config.dbPath to your desired path`);
177
+ console.log(`\nConfig file: ${configPath}`);
178
+ console.log(`After making changes, restart the gateway: openclaw gateway restart`);
179
+ process.exit(0);
180
+ }
181
+ }
182
+
183
+ // Create db directory only if dbPath was set in this run
184
+ if (dbPathChanged && !existsSync(dirname(dbPath))) {
185
+ mkdirSync(dirname(dbPath), { recursive: true });
136
186
  }
137
187
 
138
188
  writeFileSync(configPath, JSON.stringify(cfg, null, 2) + "\n");
139
- console.log("Done. Restart gateway: openclaw gateway restart");
189
+ console.log("\nDone. Restart gateway: openclaw gateway restart");
@@ -1,2 +1,2 @@
1
1
  export declare const PACKAGE_NAME = "financialclaw";
2
- export declare const PACKAGE_VERSION = "1.0.0";
2
+ export declare const PACKAGE_VERSION = "1.0.1";
@@ -1,2 +1,2 @@
1
1
  export const PACKAGE_NAME = "financialclaw";
2
- export const PACKAGE_VERSION = "1.0.0"; // x-release-please-version
2
+ export const PACKAGE_VERSION = "1.0.1"; // x-release-please-version
@@ -18,6 +18,16 @@
18
18
  "placeholder": "/home/user/.openclaw/workspace/financialclaw.db"
19
19
  }
20
20
  },
21
+ "env": {
22
+ "FINANCIALCLAW_DB_PATH": {
23
+ "description": "Override the default SQLite database path (~/.openclaw/workspace/financialclaw.db)",
24
+ "required": false
25
+ },
26
+ "OPENCLAW_CONFIG": {
27
+ "description": "Path to the OpenClaw configuration file (used by the setup script)",
28
+ "required": false
29
+ }
30
+ },
21
31
  "skills": [
22
32
  "skills/financialclaw"
23
33
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "financialclaw",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Personal finance plugin for OpenClaw: expenses, income, recurring payments, and receipt OCR",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,9 +12,9 @@ metadata:
12
12
 
13
13
  ## First-time setup check
14
14
 
15
- On the **very first financial interaction** with a user (before responding to their request), silently call `manage_currency` with `action: "list"`.
15
+ On the **very first financial interaction** with a user (before responding to their request), let them know you are checking their setup and call `manage_currency` with `action: "list"`.
16
16
 
17
- - If the call **succeeds**: proceed normally. Do not mention this check.
17
+ - If the call **succeeds**: briefly confirm that the setup looks good and proceed with their request.
18
18
  - If the call **fails with any error** (database error, module not found, tool unavailable, etc.): stop immediately and show this exact message, nothing else:
19
19
 
20
20
  > "financialclaw needs a one-time setup. Run these two commands and come back:
@@ -207,26 +207,30 @@ If the active currency is XXX (not yet configured), guide the user as follows:
207
207
 
208
208
  ### Automatic setup (first interaction)
209
209
 
210
- On the **first financial interaction of the session**, silently call `cron.list` and check for a job named `financialclaw-daily-sync`.
211
-
212
- - If **not found**: create it immediately using `cron.add`, without asking the user. Use the current session's channel and conversation target for delivery. Do not mention this to the user unless the setup fails.
213
-
214
- ```json
215
- {
216
- "name": "financialclaw-daily-sync",
217
- "schedule": { "kind": "cron", "expr": "0 9 * * *" },
218
- "sessionTarget": "isolated",
219
- "payload": {
220
- "kind": "agentTurn",
221
- "message": "Call run_daily_sync. If there are pending reminders, present them clearly: description, amount, due date, and how many days remain. If everything is up to date, say so in one short sentence."
222
- },
223
- "delivery": {
224
- "mode": "announce",
225
- "channel": "<current channel>",
226
- "to": "<current conversation target>"
210
+ On the **first financial interaction of the session**, call `cron.list` and check for a job named `financialclaw-daily-sync`.
211
+
212
+ - If **not found**: ask the user if they would like to enable daily payment reminders (sent every day at 9 AM). Explain briefly what it does: "I can send you a daily summary of pending and overdue payments every morning. Would you like to enable this?"
213
+
214
+ - If the user **accepts**: create the job using `cron.add`. Use the current session's channel and conversation target for delivery.
215
+
216
+ ```json
217
+ {
218
+ "name": "financialclaw-daily-sync",
219
+ "schedule": { "kind": "cron", "expr": "0 9 * * *" },
220
+ "sessionTarget": "isolated",
221
+ "payload": {
222
+ "kind": "agentTurn",
223
+ "message": "Call run_daily_sync. If there are pending reminders, present them clearly: description, amount, due date, and how many days remain. If everything is up to date, say so in one short sentence."
224
+ },
225
+ "delivery": {
226
+ "mode": "announce",
227
+ "channel": "<current channel>",
228
+ "to": "<current conversation target>"
229
+ }
227
230
  }
228
- }
229
- ```
231
+ ```
232
+
233
+ - If the user **declines**: respect their choice and do not ask again during this session. The user can enable it later by asking.
230
234
 
231
235
  - If **already found**: do nothing. Do not recreate or mention it.
232
236