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 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.0
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` & `/tokens`** — switch providers and monitor usage from chat
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,6 +1,6 @@
1
1
  {
2
2
  "name": "tiger-agent",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "Cognitive AI agent with persistent memory, multi-provider LLM, and Telegram bot",
5
5
  "type": "commonjs",
6
6
  "main": "src/cli.js",
@@ -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()}\n${block}`, 'utf8');
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
- maybeRunReflectionCycle().catch(() => {});
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
  };