talon-agent 3.5.0 → 3.6.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/README.md CHANGED
@@ -5,6 +5,7 @@
5
5
  [![Backends](https://img.shields.io/badge/backends-Claude_%7C_Kilo_%7C_OpenCode_%7C_Codex_%7C_OpenAI_Agents-D97706)](#backends)
6
6
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
7
  [![CI](https://github.com/dylanneve1/talon/actions/workflows/ci.yml/badge.svg)](https://github.com/dylanneve1/talon/actions/workflows/ci.yml)
8
+ [![Sponsor](https://img.shields.io/badge/Sponsor-%E2%9D%A4-db61a2?logo=githubsponsors&logoColor=white)](https://github.com/sponsors/dylanneve1)
8
9
 
9
10
  Multi-platform agentic AI harness. Runs on **Telegram**, **Discord**, **Microsoft Teams**, the **Terminal**, and a **cross-platform Desktop/Mobile companion app** (Flutter), with a pluggable backend (**Claude Agent SDK**, **Kilo**, **OpenCode**, **Codex**, or **OpenAI Agents**) and full tool access through MCP.
10
11
 
@@ -438,6 +439,16 @@ npm run format # prettier --write
438
439
 
439
440
  ---
440
441
 
442
+ ## Support
443
+
444
+ Talon is free and MIT-licensed, built and maintained in the open. If it's useful to you, sponsoring helps cover hosting and model costs and funds continued development — and keeps it free for everyone.
445
+
446
+ **[❤️ Sponsor Talon on GitHub](https://github.com/sponsors/dylanneve1)**
447
+
448
+ Even a one-time tip makes a difference, and every sponsor is appreciated. Starring the repo helps too.
449
+
450
+ ---
451
+
441
452
  ## License
442
453
 
443
454
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "talon-agent",
3
- "version": "3.5.0",
3
+ "version": "3.6.1",
4
4
  "description": "Multi-frontend AI agent with full tool access, streaming, cron jobs, and plugin system",
5
5
  "author": "Dylan Neve",
6
6
  "license": "MIT",
@@ -2,6 +2,6 @@
2
2
 
3
3
  For outcomes that outlive this conversation ("get the release out", "keep chasing that refund until it lands"): commit to a goal with `add_goal`. Goals survive restarts, and the background heartbeat agent re-reads every open goal on each of its runs, makes incremental progress, and records what it did — so a goal keeps moving even when nobody is chatting. Record progress with `update_goal` (always leave a `progress_note` — the next run starts from it), and close goals out with status `completed` or `abandoned`. Manage with `list_goals`, `delete_goal`.
4
4
 
5
- Rule of thumb: time-driven → cron; condition-watching → trigger; outcome-driven, needs judgment across multiple sessions → goal. When the user asks you to pursue or keep track of something long-running, create a goal rather than relying on conversation memory. Limit: {{maxOpenGoals}} open goals per chat.
5
+ Rule of thumb: time-driven → cron; condition-watching → trigger; outcome-driven, needs judgment across multiple sessions → goal. When the user asks you to pursue or keep track of something long-running, create a goal rather than relying on conversation memory. There is no cap on open goals create as many as you genuinely need, and keep the list healthy by closing finished ones (`completed`/`abandoned`).
6
6
 
7
7
  **Never promise without a mechanism.** If you tell someone you'll do something later — "I'll check back on that", "I'll remind you tomorrow", "I'll keep an eye on it" — create the goal, cron job, or trigger in the SAME turn. A promise that lives only in conversation text evaporates when the turn ends; the user hears a commitment, so back it with the machinery that actually keeps it.
@@ -5,7 +5,6 @@
5
5
 
6
6
  import {
7
7
  addGoal,
8
- countOpenGoalsForChat,
9
8
  deleteGoal,
10
9
  formatGoal,
11
10
  generateGoalId,
@@ -18,7 +17,6 @@ import {
18
17
  validateProgressNote,
19
18
  validateTitle,
20
19
  GOAL_STATUSES,
21
- MAX_OPEN_GOALS_PER_CHAT,
22
20
  OPEN_GOAL_STATUSES,
23
21
  type Goal,
24
22
  type GoalStatus,
@@ -51,13 +49,8 @@ export const goalHandlers: SharedActionHandlers = {
51
49
  }
52
50
 
53
51
  const chatIdStr = String(chatId);
54
- const openCount = countOpenGoalsForChat(chatIdStr);
55
- if (openCount >= MAX_OPEN_GOALS_PER_CHAT) {
56
- return {
57
- ok: false,
58
- error: `Per-chat open-goal cap reached (${MAX_OPEN_GOALS_PER_CHAT}). Complete or abandon one before adding another.`,
59
- };
60
- }
52
+ // No open-goal cap: goals grow freely. The heartbeat re-reads every open
53
+ // goal, so keep them tidy by closing finished ones (completed/abandoned).
61
54
 
62
55
  const now = Date.now();
63
56
  const goal: Goal = {
@@ -58,7 +58,6 @@ import { todayAndYesterday } from "../../util/time.js";
58
58
  import { log } from "../../util/log.js";
59
59
  import { loadSystemTemplate } from "./templates.js";
60
60
  import { renderWorkspaceListing } from "./workspace-listing.js";
61
- import { MAX_OPEN_GOALS_PER_CHAT } from "../../storage/goal-store.js";
62
61
  import { renderSkillsPrompt } from "../../storage/skill-store.js";
63
62
  import { renderStickerLibraryPrompt } from "../../storage/sticker-store.js";
64
63
  import { getSoul } from "../soul/service.js";
@@ -216,9 +215,7 @@ export function assembleSystemPrompt(
216
215
  loadSystemTemplate("workspace"),
217
216
  loadSystemTemplate("cron"),
218
217
  loadSystemTemplate("triggers"),
219
- loadSystemTemplate("goals", {
220
- maxOpenGoals: String(MAX_OPEN_GOALS_PER_CHAT),
221
- }),
218
+ loadSystemTemplate("goals"),
222
219
  loadSystemTemplate("skills"),
223
220
  );
224
221
 
@@ -43,7 +43,6 @@ export const GOAL_PRIORITIES: readonly GoalPriority[] = [
43
43
  /** Statuses that count as "open" — shown to the heartbeat and listings. */
44
44
  export const OPEN_GOAL_STATUSES: readonly GoalStatus[] = ["active", "paused"];
45
45
 
46
- export const MAX_OPEN_GOALS_PER_CHAT = 25;
47
46
  export const MAX_TITLE_LENGTH = 200;
48
47
  export const MAX_DESCRIPTION_LENGTH = 2_000;
49
48
  export const MAX_PROGRESS_NOTE_LENGTH = 1_000;