tiger-agent 0.2.3 → 0.2.4
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/README.md +30 -2
- package/package.json +1 -1
- package/src/agent/reflectionAgent.js +14 -2
- package/src/agent/reflectionScheduler.js +19 -3
package/README.md
CHANGED
|
@@ -10,13 +10,20 @@ Made by **AI Research Group, Department of Civil Engineering, KMUTT**
|
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
## 🆕 What's New — v0.2.
|
|
13
|
+
## 🆕 What's New — v0.2.4
|
|
14
|
+
|
|
15
|
+
- **ClawHub skill install fixed** — `clawhub_install` and `clawhub_search` now work correctly when installed via `npm install -g`
|
|
16
|
+
- **No required API keys** — `tiger onboard` skips providers with no key; any single provider is enough to start
|
|
17
|
+
- **`/limit` Telegram command** — set per-provider daily token limits from chat without restarting
|
|
18
|
+
- **Soul & ownskill refresh fixed** — 24-hour regeneration timer now uses DB timestamps, not file mtime, so reflection appends no longer block the update cycle
|
|
19
|
+
|
|
20
|
+
### v0.2.0
|
|
14
21
|
|
|
15
22
|
- **npm global install** — `npm install -g tiger-agent`, no git clone needed
|
|
16
23
|
- **Multi-provider LLM** — 5 providers (Kimi, Z.ai, MiniMax, Claude, Moonshot) with auto-fallback
|
|
17
24
|
- **Daily token limits** — per-provider limits with automatic switching at UTC midnight
|
|
18
25
|
- **`tiger` CLI** — unified command: `tiger onboard`, `tiger start`, `tiger telegram`, `tiger stop`
|
|
19
|
-
- **Telegram `/api
|
|
26
|
+
- **Telegram `/api`, `/tokens`, `/limit`** — manage providers and usage from chat
|
|
20
27
|
- **Encrypted secrets** — optional at-rest encryption for API keys
|
|
21
28
|
|
|
22
29
|
---
|
|
@@ -259,6 +266,27 @@ Without it, Tiger falls back to cosine similarity in Python — slower but fully
|
|
|
259
266
|
| **Skills** | `list_skills`, `load_skill`, `clawhub_search`, `clawhub_install` |
|
|
260
267
|
| **Orchestration** | `run_sub_agents` |
|
|
261
268
|
|
|
269
|
+
### ClawHub Skills
|
|
270
|
+
|
|
271
|
+
Tiger can search and install skills from [ClawHub](https://clawhub.dev) — a community registry of reusable agent skills. The `clawhub` CLI is bundled with Tiger, no separate install needed.
|
|
272
|
+
|
|
273
|
+
Enable skill install in `~/.tiger/.env`:
|
|
274
|
+
|
|
275
|
+
```env
|
|
276
|
+
ALLOW_SKILL_INSTALL=true
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Then just ask Tiger in chat:
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
Search for a web search skill on clawhub
|
|
283
|
+
Install the web-search skill
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Skills are installed to `~/.tiger/skills/` and loaded automatically on demand.
|
|
287
|
+
|
|
288
|
+
> **Note:** `ALLOW_SKILL_INSTALL=true` must be set during `tiger onboard` or added manually to `~/.tiger/.env`.
|
|
289
|
+
|
|
262
290
|
---
|
|
263
291
|
|
|
264
292
|
## 🔒 Security
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const { chatCompletion, embedText } = require('../llmClient');
|
|
4
|
-
const { dataDir, embeddingsEnabled } = require('../config');
|
|
4
|
+
const { dataDir, embeddingsEnabled, reflectionUpdateHours } = require('../config');
|
|
5
5
|
const { addMemory, getMeta, setMeta, getMessagesSince, getRecentMessagesAll } = require('./db');
|
|
6
6
|
|
|
7
7
|
const REFLECTION_META_KEY = 'memory_reflection_last_run_ts';
|
|
@@ -80,7 +80,7 @@ function appendHuman2Update(filePath, payload, stampIso) {
|
|
|
80
80
|
for (const w of payload.successfulWorkflows) lines.push(`- Workflow: ${w}`);
|
|
81
81
|
if (!lines.length) return;
|
|
82
82
|
const block = `\n## Update ${stampIso}\n${lines.join('\n')}\n`;
|
|
83
|
-
fs.writeFileSync(full, `${existing.trimEnd()}
|
|
83
|
+
fs.writeFileSync(full, `${existing.trimEnd()}${block}`, 'utf8');
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
async function generateReflection(rows, sinceIso, untilIso) {
|
|
@@ -123,9 +123,20 @@ async function generateReflection(rows, sinceIso, untilIso) {
|
|
|
123
123
|
};
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
function shouldRunReflectionCycle(lastRunTs) {
|
|
127
|
+
if (!lastRunTs) return true;
|
|
128
|
+
const hoursPassed = (nowTs() - lastRunTs) / (60 * 60 * 1000);
|
|
129
|
+
return hoursPassed >= reflectionUpdateHours;
|
|
130
|
+
}
|
|
131
|
+
|
|
126
132
|
async function maybeRunReflectionCycle({ force = false } = {}) {
|
|
127
133
|
const startedAt = nowTs();
|
|
128
134
|
const lastRunTs = Number(getMeta(REFLECTION_META_KEY, 0) || 0);
|
|
135
|
+
|
|
136
|
+
if (!force && !shouldRunReflectionCycle(lastRunTs)) {
|
|
137
|
+
return { ok: true, skipped: true, reason: 'not_yet_due' };
|
|
138
|
+
}
|
|
139
|
+
|
|
129
140
|
const rows = lastRunTs
|
|
130
141
|
? getMessagesSince(lastRunTs, MAX_MESSAGE_SCAN)
|
|
131
142
|
: getRecentMessagesAll(Math.min(MAX_MESSAGE_SCAN, 240));
|
|
@@ -185,6 +196,7 @@ async function maybeRunReflectionCycle({ force = false } = {}) {
|
|
|
185
196
|
}
|
|
186
197
|
|
|
187
198
|
setMeta(REFLECTION_META_KEY, startedAt);
|
|
199
|
+
console.log(`[ReflectionCycle] Completed at ${stampIso} (${rows.length} messages processed)`);
|
|
188
200
|
return { ok: true, skipped: false, at: stampIso };
|
|
189
201
|
}
|
|
190
202
|
|
|
@@ -8,14 +8,30 @@ function startReflectionScheduler() {
|
|
|
8
8
|
|
|
9
9
|
const everyMs = Math.max(1, Number(reflectionUpdateHours || 12)) * 60 * 60 * 1000;
|
|
10
10
|
|
|
11
|
+
console.log(`[ReflectionScheduler] Starting with interval: ${reflectionUpdateHours || 12} hours (${everyMs}ms)`);
|
|
12
|
+
|
|
11
13
|
// Kick one asynchronous check on startup.
|
|
12
|
-
maybeRunReflectionCycle().catch(() => {
|
|
14
|
+
maybeRunReflectionCycle().catch((err) => {
|
|
15
|
+
console.error('[ReflectionScheduler] Startup check failed:', err.message);
|
|
16
|
+
});
|
|
13
17
|
|
|
14
18
|
intervalHandle = setInterval(() => {
|
|
15
|
-
|
|
19
|
+
console.log('[ReflectionScheduler] Running scheduled reflection cycle...');
|
|
20
|
+
maybeRunReflectionCycle().catch((err) => {
|
|
21
|
+
console.error('[ReflectionScheduler] Scheduled cycle failed:', err.message);
|
|
22
|
+
});
|
|
16
23
|
}, everyMs);
|
|
17
24
|
}
|
|
18
25
|
|
|
26
|
+
function stopReflectionScheduler() {
|
|
27
|
+
if (intervalHandle) {
|
|
28
|
+
clearInterval(intervalHandle);
|
|
29
|
+
intervalHandle = null;
|
|
30
|
+
console.log('[ReflectionScheduler] Stopped');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
19
34
|
module.exports = {
|
|
20
|
-
startReflectionScheduler
|
|
35
|
+
startReflectionScheduler,
|
|
36
|
+
stopReflectionScheduler
|
|
21
37
|
};
|