talon-agent 1.12.0 → 1.34.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/README.md +111 -52
- package/package.json +39 -12
- package/prompts/README.md +112 -0
- package/prompts/base.md +12 -12
- package/prompts/discord.md +10 -47
- package/prompts/heartbeat.md +23 -8
- package/prompts/identity.md +12 -22
- package/prompts/native.md +23 -0
- package/prompts/system/contract-text-or-tools.md +8 -0
- package/prompts/system/contract-text-preferred.md +5 -0
- package/prompts/system/contract-tool-only.md +10 -0
- package/prompts/system/cron.md +3 -0
- package/prompts/system/daily-memory.md +3 -0
- package/prompts/system/goals.md +7 -0
- package/prompts/system/heartbeat-agent.md +44 -0
- package/prompts/system/persistent-memory.md +8 -0
- package/prompts/system/skills.md +9 -0
- package/prompts/system/triggers.md +5 -0
- package/prompts/system/workspace.md +9 -0
- package/prompts/teams.md +4 -14
- package/prompts/telegram.md +17 -89
- package/src/app.ts +278 -0
- package/src/backend/claude-sdk/constants.ts +22 -10
- package/src/backend/claude-sdk/factory.ts +79 -22
- package/src/backend/claude-sdk/handler.ts +431 -160
- package/src/backend/claude-sdk/index.ts +6 -2
- package/src/backend/claude-sdk/mcp-ready.ts +54 -0
- package/src/backend/claude-sdk/model-drift.ts +65 -0
- package/src/backend/claude-sdk/model-provider.ts +12 -6
- package/src/backend/claude-sdk/models/convert.ts +169 -0
- package/src/backend/claude-sdk/models/discovery.ts +203 -0
- package/src/backend/claude-sdk/models/index.ts +18 -0
- package/src/backend/claude-sdk/models/parsing.ts +264 -0
- package/src/backend/claude-sdk/models/static.ts +45 -0
- package/src/backend/claude-sdk/one-shot.ts +19 -13
- package/src/backend/claude-sdk/options.ts +228 -104
- package/src/backend/claude-sdk/state.ts +1 -1
- package/src/backend/claude-sdk/stream.ts +153 -45
- package/src/backend/claude-sdk/warm.ts +12 -5
- package/src/backend/codex/auth.ts +216 -40
- package/src/backend/codex/constants.ts +63 -22
- package/src/backend/codex/discovery.ts +427 -0
- package/src/backend/codex/factory.ts +63 -33
- package/src/backend/codex/handler/events.ts +239 -0
- package/src/backend/codex/handler/index.ts +15 -0
- package/src/backend/codex/handler/message.ts +669 -0
- package/src/backend/codex/handler/state.ts +14 -0
- package/src/backend/codex/handler/usage.ts +68 -0
- package/src/backend/codex/index.ts +2 -2
- package/src/backend/codex/init.ts +92 -11
- package/src/backend/codex/mcp-config.ts +89 -62
- package/src/backend/codex/models.ts +305 -54
- package/src/backend/codex/oauth-incompat.ts +302 -0
- package/src/backend/codex/one-shot.ts +91 -8
- package/src/backend/codex/state.ts +54 -3
- package/src/backend/codex/token-usage.ts +434 -0
- package/src/backend/kilo/factory.ts +60 -35
- package/src/backend/kilo/handler/index.ts +13 -0
- package/src/backend/kilo/handler/message.ts +317 -0
- package/src/backend/kilo/handler/state.ts +14 -0
- package/src/backend/kilo/handler/turn.ts +321 -0
- package/src/backend/kilo/index.ts +5 -5
- package/src/backend/kilo/model-provider.ts +26 -168
- package/src/backend/kilo/models/index.ts +52 -0
- package/src/backend/kilo/one-shot.ts +20 -142
- package/src/backend/kilo/server.ts +14 -21
- package/src/backend/openai-agents/builtins.ts +215 -114
- package/src/backend/openai-agents/constants.ts +41 -15
- package/src/backend/openai-agents/discovery.ts +332 -0
- package/src/backend/openai-agents/factory.ts +66 -28
- package/src/backend/openai-agents/handler/events.ts +170 -0
- package/src/backend/openai-agents/handler/index.ts +13 -0
- package/src/backend/openai-agents/handler/message.ts +527 -0
- package/src/backend/openai-agents/handler/state.ts +13 -0
- package/src/backend/openai-agents/index.ts +22 -4
- package/src/backend/openai-agents/init.ts +51 -88
- package/src/backend/openai-agents/mcp-pool.ts +252 -0
- package/src/backend/openai-agents/models.ts +118 -11
- package/src/backend/openai-agents/session.ts +277 -0
- package/src/backend/openai-agents/state.ts +82 -11
- package/src/backend/opencode/factory.ts +54 -25
- package/src/backend/opencode/handler/index.ts +13 -0
- package/src/backend/opencode/handler/message.ts +325 -0
- package/src/backend/opencode/handler/state.ts +14 -0
- package/src/backend/opencode/handler/turn.ts +304 -0
- package/src/backend/opencode/index.ts +2 -2
- package/src/backend/opencode/model-provider.ts +26 -168
- package/src/backend/opencode/models/index.ts +51 -0
- package/src/backend/opencode/one-shot.ts +20 -137
- package/src/backend/opencode/server.ts +12 -11
- package/src/backend/remote-server/client.ts +13 -6
- package/src/backend/remote-server/events.ts +59 -9
- package/src/backend/remote-server/lifecycle.ts +3 -1
- package/src/backend/remote-server/mcp.ts +52 -19
- package/src/backend/remote-server/model-catalog/catalog.ts +270 -0
- package/src/backend/remote-server/model-catalog/index.ts +100 -0
- package/src/backend/remote-server/model-catalog/presentation.ts +298 -0
- package/src/backend/remote-server/model-catalog/provider.ts +193 -0
- package/src/backend/remote-server/model-catalog/resolve.ts +225 -0
- package/src/backend/remote-server/model-catalog/types.ts +136 -0
- package/src/backend/remote-server/one-shot.ts +225 -0
- package/src/backend/remote-server/session-helpers.ts +3 -4
- package/src/backend/remote-server/state.ts +1 -1
- package/src/backend/shared/delivery-contract.ts +161 -0
- package/src/backend/shared/delivery.ts +49 -0
- package/src/backend/shared/flow-violation.ts +38 -7
- package/src/backend/shared/frontends.ts +66 -0
- package/src/backend/shared/handle-retry.ts +244 -0
- package/src/backend/shared/handler-to-events.ts +186 -0
- package/src/backend/shared/handler-types.ts +57 -0
- package/src/backend/shared/index.ts +51 -5
- package/src/backend/shared/metrics.ts +199 -0
- package/src/backend/shared/model-retry.ts +1 -1
- package/src/backend/shared/prompt-format.ts +69 -0
- package/src/backend/shared/session-name.ts +1 -1
- package/src/backend/shared/stream-state.ts +36 -2
- package/src/backend/shared/system-prompt.ts +200 -23
- package/src/bootstrap.ts +338 -38
- package/src/cli/chat.ts +49 -0
- package/src/cli/config-view.ts +100 -0
- package/src/cli/config.ts +105 -0
- package/src/cli/context.ts +23 -0
- package/src/cli/daemon.ts +95 -0
- package/src/cli/doctor.ts +53 -0
- package/src/cli/index.ts +139 -0
- package/src/cli/logs.ts +60 -0
- package/src/cli/menu.ts +104 -0
- package/src/cli/setup.ts +455 -0
- package/src/cli/status.ts +75 -0
- package/src/cli.ts +20 -1211
- package/src/core/agent-runtime/README.md +173 -0
- package/src/{backend/registry.ts → core/agent-runtime/backend-registry.ts} +15 -6
- package/src/core/agent-runtime/capabilities.ts +330 -0
- package/src/core/agent-runtime/contract-tests.ts +378 -0
- package/src/core/agent-runtime/events.ts +291 -0
- package/src/core/agent-runtime/index.ts +62 -0
- package/src/core/agent-runtime/model-ref.ts +130 -0
- package/src/core/background/cron.ts +469 -0
- package/src/core/{dream.ts → background/dream.ts} +118 -53
- package/src/core/background/heartbeat/agent.ts +333 -0
- package/src/core/background/heartbeat/index.ts +25 -0
- package/src/core/background/heartbeat/scheduler.ts +211 -0
- package/src/core/background/heartbeat/state.ts +153 -0
- package/src/core/background/index.ts +21 -0
- package/src/core/background/isolated-agent.ts +115 -0
- package/src/core/background/job-health.ts +140 -0
- package/src/core/background/job-oneshot.ts +165 -0
- package/src/core/background/job-prompt.ts +54 -0
- package/src/core/{pulse.ts → background/pulse.ts} +6 -5
- package/src/core/background/triggers/command.ts +60 -0
- package/src/core/background/triggers/exit.ts +202 -0
- package/src/core/background/triggers/index.ts +38 -0
- package/src/core/background/triggers/output.ts +142 -0
- package/src/core/background/triggers/resume.ts +127 -0
- package/src/core/background/triggers/spawn.ts +282 -0
- package/src/core/background/triggers/state.ts +52 -0
- package/src/core/constants.ts +57 -28
- package/src/core/daemon/control.ts +229 -0
- package/src/core/daemon/discovery.ts +169 -0
- package/src/core/daemon/pidfile.ts +98 -0
- package/src/core/doctor.ts +459 -0
- package/src/core/engine/backend-controller/holders.ts +17 -0
- package/src/core/engine/backend-controller/index.ts +71 -0
- package/src/core/engine/backend-controller/legacy.ts +111 -0
- package/src/core/engine/backend-controller/pool.ts +296 -0
- package/src/core/engine/backend-controller/rebind.ts +205 -0
- package/src/core/engine/backend-controller/state.ts +150 -0
- package/src/core/engine/backend-controller/types.ts +51 -0
- package/src/core/engine/dispatcher.ts +68 -0
- package/src/core/engine/gateway-actions/cron.ts +518 -0
- package/src/core/engine/gateway-actions/fetch-url.ts +120 -0
- package/src/core/engine/gateway-actions/goals.ts +178 -0
- package/src/core/engine/gateway-actions/history.ts +53 -0
- package/src/core/engine/gateway-actions/index.ts +60 -0
- package/src/core/engine/gateway-actions/models.ts +120 -0
- package/src/core/engine/gateway-actions/plugins.ts +83 -0
- package/src/core/engine/gateway-actions/scripts.ts +127 -0
- package/src/core/engine/gateway-actions/shared.ts +66 -0
- package/src/core/engine/gateway-actions/skills.ts +120 -0
- package/src/core/engine/gateway-actions/triggers.ts +237 -0
- package/src/core/engine/gateway-actions/types.ts +18 -0
- package/src/core/{gateway.ts → engine/gateway.ts} +223 -60
- package/src/core/engine/index.ts +20 -0
- package/src/core/engine/model-audit.ts +121 -0
- package/src/core/errors.ts +68 -6
- package/src/core/mcp-hub/children.ts +254 -0
- package/src/core/mcp-hub/index.ts +335 -0
- package/src/core/mcp-hub/proxy-server.ts +45 -0
- package/src/core/mcp-hub/talon-server.ts +71 -0
- package/src/core/memory/retrieval.ts +90 -0
- package/src/core/models/active-model.ts +441 -0
- package/src/core/{models.ts → models/catalog.ts} +6 -0
- package/src/core/models/index.ts +17 -0
- package/src/core/models/reasoning-levels.ts +57 -0
- package/src/core/plugin/actions.ts +32 -0
- package/src/core/plugin/builtins.ts +162 -0
- package/src/core/plugin/index.ts +37 -0
- package/src/core/plugin/loader.ts +289 -0
- package/src/core/plugin/mcp.ts +86 -0
- package/src/core/plugin/registry.ts +124 -0
- package/src/core/plugin/types.ts +126 -0
- package/src/core/prompt/assemble.ts +273 -0
- package/src/core/prompt/disk-prompts.ts +41 -0
- package/src/core/prompt/embed.ts +107 -0
- package/src/core/prompt/embedded-prompts.ts +85 -0
- package/src/core/prompt/index.ts +30 -0
- package/src/core/prompt/templates.ts +124 -0
- package/src/core/prompt/workspace-listing.ts +91 -0
- package/src/core/scripting/lua-runner.ts +210 -0
- package/src/core/scripts/runner.ts +125 -0
- package/src/core/soul/README.md +110 -0
- package/src/core/soul/RESEARCH.md +98 -0
- package/src/core/soul/associative.ts +98 -0
- package/src/core/soul/centrality.ts +98 -0
- package/src/core/soul/cluster.ts +83 -0
- package/src/core/soul/compiler.ts +207 -0
- package/src/core/soul/consolidate.ts +179 -0
- package/src/core/soul/critic.ts +159 -0
- package/src/core/soul/dag.ts +265 -0
- package/src/core/soul/delta.ts +123 -0
- package/src/core/soul/drift.ts +99 -0
- package/src/core/soul/embedder.ts +129 -0
- package/src/core/soul/emergent-critic.ts +96 -0
- package/src/core/soul/forgetting.ts +131 -0
- package/src/core/soul/governance.ts +93 -0
- package/src/core/soul/hash.ts +97 -0
- package/src/core/soul/hdc.ts +154 -0
- package/src/core/soul/index.ts +140 -0
- package/src/core/soul/kernel.ts +540 -0
- package/src/core/soul/lattice.ts +103 -0
- package/src/core/soul/lens.ts +110 -0
- package/src/core/soul/projector.ts +240 -0
- package/src/core/soul/reflect.ts +170 -0
- package/src/core/soul/reflex.ts +164 -0
- package/src/core/soul/retrieve.ts +146 -0
- package/src/core/soul/salience.ts +142 -0
- package/src/core/soul/service.ts +204 -0
- package/src/core/soul/settings.ts +47 -0
- package/src/core/soul/signals.ts +117 -0
- package/src/core/soul/talon-embedder.ts +80 -0
- package/src/core/soul/taps.ts +199 -0
- package/src/core/soul/types.ts +298 -0
- package/src/core/soul/valence.ts +83 -0
- package/src/core/tools/goals.ts +117 -0
- package/src/core/tools/index.ts +10 -0
- package/src/core/tools/mcp-env.ts +94 -0
- package/src/core/tools/mcp-server.ts +27 -4
- package/src/core/tools/messaging.ts +122 -29
- package/src/core/tools/models.ts +39 -0
- package/src/core/tools/scheduling.ts +133 -14
- package/src/core/tools/schemas.ts +16 -4
- package/src/core/tools/scripts.ts +78 -0
- package/src/core/tools/skills.ts +90 -0
- package/src/core/tools/stickers.ts +1 -1
- package/src/core/tools/triggers.ts +19 -3
- package/src/core/tools/types.ts +6 -6
- package/src/core/types.ts +62 -112
- package/src/core/update/self-update.ts +269 -0
- package/src/core/weaver/index.ts +10 -0
- package/src/core/weaver/loom.ts +125 -0
- package/src/core/weaver/thread-session.ts +51 -0
- package/src/core/weaver/thread.ts +196 -0
- package/src/core/weaver/weaver.ts +357 -0
- package/src/frontend/discord/actions/chat-info.ts +268 -0
- package/src/frontend/discord/actions/index.ts +77 -0
- package/src/frontend/discord/actions/media.ts +190 -0
- package/src/frontend/discord/actions/messaging.ts +277 -0
- package/src/frontend/discord/actions/shared.ts +100 -0
- package/src/frontend/discord/actions/types.ts +33 -0
- package/src/frontend/discord/admin.ts +13 -23
- package/src/frontend/discord/callbacks/autocomplete.ts +55 -0
- package/src/frontend/discord/{callbacks.ts → callbacks/components.ts} +150 -190
- package/src/frontend/discord/callbacks/index.ts +14 -0
- package/src/frontend/discord/callbacks/modals.ts +76 -0
- package/src/frontend/discord/callbacks/shared.ts +22 -0
- package/src/frontend/discord/commands/admin.ts +88 -0
- package/src/frontend/discord/commands/definitions.ts +200 -0
- package/src/frontend/discord/commands/index.ts +19 -0
- package/src/frontend/discord/commands/info.ts +106 -0
- package/src/frontend/discord/commands/router.ts +149 -0
- package/src/frontend/discord/commands/session.ts +89 -0
- package/src/frontend/discord/commands/settings.ts +405 -0
- package/src/frontend/discord/commands/shared.ts +50 -0
- package/src/frontend/discord/formatting.ts +8 -34
- package/src/frontend/discord/handlers/access.ts +248 -0
- package/src/frontend/discord/handlers/context.ts +161 -0
- package/src/frontend/discord/handlers/delivery.ts +94 -0
- package/src/frontend/discord/handlers/index.ts +34 -0
- package/src/frontend/discord/handlers/messages.ts +120 -0
- package/src/frontend/discord/handlers/queue.ts +135 -0
- package/src/frontend/discord/handlers/registry.ts +29 -0
- package/src/frontend/discord/handlers/state.ts +94 -0
- package/src/frontend/discord/helpers.ts +46 -57
- package/src/frontend/discord/index.ts +10 -7
- package/src/frontend/discord/middleware.ts +2 -2
- package/src/frontend/native/actions.ts +133 -0
- package/src/frontend/native/chats.ts +146 -0
- package/src/frontend/native/discovery.ts +50 -0
- package/src/frontend/native/index.ts +1227 -0
- package/src/frontend/native/logs.ts +95 -0
- package/src/frontend/native/protocol.ts +253 -0
- package/src/frontend/native/server.ts +612 -0
- package/src/frontend/native/settings.ts +205 -0
- package/src/frontend/native/turn-meta.ts +43 -0
- package/src/frontend/shared/format.ts +51 -0
- package/src/frontend/shared/reasoning-levels.ts +46 -0
- package/src/frontend/shared/session-status.ts +189 -0
- package/src/frontend/shared/status-context.ts +125 -0
- package/src/frontend/teams/actions.ts +7 -5
- package/src/frontend/teams/formatting.ts +7 -18
- package/src/frontend/teams/graph.ts +2 -1
- package/src/frontend/teams/index.ts +76 -54
- package/src/frontend/telegram/actions/chat-info.ts +323 -0
- package/src/frontend/telegram/actions/index.ts +68 -0
- package/src/frontend/telegram/actions/media.ts +224 -0
- package/src/frontend/telegram/actions/messaging.ts +295 -0
- package/src/frontend/telegram/actions/shared.ts +58 -0
- package/src/frontend/telegram/actions/types.ts +31 -0
- package/src/frontend/telegram/admin.ts +12 -22
- package/src/frontend/telegram/callbacks/effort.ts +68 -0
- package/src/frontend/telegram/callbacks/index.ts +68 -0
- package/src/frontend/telegram/callbacks/model.ts +311 -0
- package/src/frontend/telegram/callbacks/pulse.ts +50 -0
- package/src/frontend/telegram/callbacks/settings.ts +177 -0
- package/src/frontend/telegram/callbacks/shared.ts +71 -0
- package/src/frontend/telegram/commands/admin.ts +226 -0
- package/src/frontend/telegram/commands/definitions.ts +60 -0
- package/src/frontend/telegram/commands/index.ts +39 -0
- package/src/frontend/telegram/commands/info.ts +125 -0
- package/src/frontend/telegram/commands/session.ts +77 -0
- package/src/frontend/telegram/commands/settings.ts +345 -0
- package/src/frontend/telegram/commands/state.ts +34 -0
- package/src/frontend/telegram/formatting.ts +14 -25
- package/src/frontend/telegram/handlers/access.ts +287 -0
- package/src/frontend/telegram/handlers/context.ts +210 -0
- package/src/frontend/telegram/handlers/delivery.ts +236 -0
- package/src/frontend/telegram/handlers/index.ts +39 -0
- package/src/frontend/telegram/handlers/messages.ts +477 -0
- package/src/frontend/telegram/handlers/queue.ts +241 -0
- package/src/frontend/telegram/handlers/state.ts +75 -0
- package/src/frontend/telegram/helpers/diagnostics.ts +188 -0
- package/src/frontend/telegram/helpers/format.ts +41 -0
- package/src/frontend/telegram/helpers/index.ts +13 -0
- package/src/frontend/telegram/{helpers.ts → helpers/menu.ts} +209 -210
- package/src/frontend/telegram/index.ts +24 -27
- package/src/frontend/telegram/middleware.ts +16 -3
- package/src/frontend/telegram/model-callbacks.ts +14 -0
- package/src/frontend/telegram/model-menu.ts +317 -0
- package/src/frontend/telegram/sticker-library.ts +178 -0
- package/src/frontend/telegram/userbot.ts +2 -44
- package/src/frontend/terminal/commands.ts +47 -41
- package/src/frontend/terminal/index.ts +46 -31
- package/src/frontend/terminal/input.ts +5 -0
- package/src/frontend/terminal/renderer.ts +4 -2
- package/src/index.ts +13 -171
- package/src/login.ts +3 -2
- package/src/native/blake3-wasm-bytes.ts +7 -0
- package/src/native/blake3.ts +234 -0
- package/src/native/htmlents-wasm-bytes.ts +7 -0
- package/src/native/htmlents.ts +56 -0
- package/src/native/prelude.d.mts +168 -0
- package/src/native/prelude.mjs +1561 -0
- package/src/native/registry.ts +142 -0
- package/src/native/runtime.ts +164 -0
- package/src/native/scheduler-core/gleam.d.mts +2 -0
- package/src/native/scheduler-core/gleam.mjs +1 -0
- package/src/native/scheduler-core/scheduler_core.d.mts +76 -0
- package/src/native/scheduler-core/scheduler_core.mjs +252 -0
- package/src/native/scheduler-core.ts +124 -0
- package/src/native/sqlguard-wasm-bytes.ts +7 -0
- package/src/native/sqlguard.ts +107 -0
- package/src/native/strsim-wasm-bytes.ts +7 -0
- package/src/native/strsim.ts +98 -0
- package/src/native/textops-wasm-bytes.ts +7 -0
- package/src/native/textops.ts +83 -0
- package/src/native/warden.ts +287 -0
- package/src/plugins/github/index.ts +1 -1
- package/src/plugins/mempalace/index.ts +1 -1
- package/src/plugins/playwright/index.ts +1 -1
- package/src/storage/chat-settings.ts +335 -85
- package/src/storage/cron-store.ts +266 -109
- package/src/storage/daily-log.ts +15 -3
- package/src/storage/db.ts +206 -0
- package/src/storage/goal-store.ts +186 -0
- package/src/storage/history.ts +137 -188
- package/src/storage/kv.ts +52 -0
- package/src/storage/legacy-import.ts +47 -0
- package/src/storage/media-index.ts +118 -61
- package/src/storage/repositories/chat-settings-repo.ts +60 -0
- package/src/storage/repositories/cron-repo.ts +128 -0
- package/src/storage/repositories/goals-repo.ts +122 -0
- package/src/storage/repositories/history-repo.ts +207 -0
- package/src/storage/repositories/kv-repo.ts +25 -0
- package/src/storage/repositories/media-index-repo.ts +147 -0
- package/src/storage/repositories/scripts-repo.ts +81 -0
- package/src/storage/repositories/sessions-repo.ts +129 -0
- package/src/storage/repositories/triggers-repo.ts +158 -0
- package/src/storage/repositories/turn-meta-repo.ts +32 -0
- package/src/storage/scheduled-store.ts +84 -0
- package/src/storage/script-store.ts +198 -0
- package/src/storage/sessions.ts +227 -102
- package/src/storage/skill-store.ts +325 -0
- package/src/storage/sql/README.md +18 -0
- package/src/storage/sql/chat-settings.sql +11 -0
- package/src/storage/sql/cron.sql +40 -0
- package/src/storage/sql/db.sql +11 -0
- package/src/storage/sql/embed.ts +118 -0
- package/src/storage/sql/goals.sql +41 -0
- package/src/storage/sql/history.sql +83 -0
- package/src/storage/sql/kv.sql +11 -0
- package/src/storage/sql/media-index.sql +45 -0
- package/src/storage/sql/schema.sql +233 -0
- package/src/storage/sql/scripts.sql +28 -0
- package/src/storage/sql/sessions.sql +22 -0
- package/src/storage/sql/statements.generated.ts +500 -0
- package/src/storage/sql/triggers.sql +69 -0
- package/src/storage/sql/turn-meta.sql +24 -0
- package/src/storage/sticker-store.ts +141 -0
- package/src/storage/trigger-store.ts +104 -126
- package/src/storage/turn-meta.ts +118 -0
- package/src/util/chat-id.ts +30 -0
- package/src/util/config.ts +313 -195
- package/src/util/fs-path.ts +32 -0
- package/src/util/log.ts +53 -31
- package/src/util/mcp-launcher.ts +351 -33
- package/src/util/paths.ts +45 -17
- package/src/util/tail-file.ts +24 -0
- package/src/util/workspace.ts +161 -10
- package/tsconfig.json +1 -0
- package/src/backend/claude-sdk/models.ts +0 -501
- package/src/backend/codex/handler.ts +0 -595
- package/src/backend/kilo/handler.ts +0 -707
- package/src/backend/kilo/models.ts +0 -762
- package/src/backend/openai-agents/handler.ts +0 -539
- package/src/backend/openai-agents/mcp.ts +0 -139
- package/src/backend/opencode/handler.ts +0 -663
- package/src/backend/opencode/models.ts +0 -741
- package/src/core/cron.ts +0 -184
- package/src/core/dispatcher.ts +0 -144
- package/src/core/gateway-actions.ts +0 -603
- package/src/core/heartbeat.ts +0 -575
- package/src/core/plugin.ts +0 -776
- package/src/core/triggers.ts +0 -640
- package/src/frontend/discord/actions.ts +0 -729
- package/src/frontend/discord/commands.ts +0 -1036
- package/src/frontend/discord/handlers.ts +0 -798
- package/src/frontend/telegram/actions.ts +0 -731
- package/src/frontend/telegram/callbacks.ts +0 -419
- package/src/frontend/telegram/commands.ts +0 -642
- package/src/frontend/telegram/handlers.ts +0 -1352
- package/src/util/mcp-launcher.mjs +0 -140
package/README.md
CHANGED
|
@@ -2,26 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://nodejs.org)
|
|
4
4
|
[](https://www.typescriptlang.org/)
|
|
5
|
-
[](#backends)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
[](https://github.com/dylanneve1/talon/actions/workflows/ci.yml)
|
|
8
8
|
|
|
9
|
-
Multi-platform agentic AI harness. Runs on **Telegram**, **Discord**, **Microsoft Teams**,
|
|
9
|
+
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
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
## Features
|
|
14
14
|
|
|
15
|
-
| |
|
|
16
|
-
| --------------------- |
|
|
17
|
-
| **Multi-frontend** | Telegram (Grammy + GramJS userbot), Discord (discord.js), Microsoft Teams (Bot Framework), Terminal with live tool visibility
|
|
18
|
-
| **Pluggable backend** | Claude Agent SDK, Kilo, OpenCode, Codex — selectable per-process via `backend` config. Streaming, model fallback, context-overflow recovery. |
|
|
19
|
-
| **MCP tools** | Messaging, media, history, search, web fetch, cron jobs, triggers, stickers, file system, admin controls |
|
|
20
|
-
| **Plugins** | Hot-reloadable plugin system. Built-in: GitHub, MemPalace, Playwright, Brave Search
|
|
21
|
-
| **Background agents** | Heartbeat (
|
|
22
|
-
| **
|
|
23
|
-
| **
|
|
24
|
-
| **
|
|
15
|
+
| | |
|
|
16
|
+
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| **Multi-frontend** | Telegram (Grammy + GramJS userbot), Discord (discord.js), Microsoft Teams (Bot Framework), Terminal with live tool visibility, and a **Desktop/Mobile app** (Flutter) over a local/remote bridge |
|
|
18
|
+
| **Pluggable backend** | Claude Agent SDK, Kilo, OpenCode, Codex, OpenAI Agents — selectable per-process via `backend` config. Streaming, model fallback, context-overflow recovery. |
|
|
19
|
+
| **MCP tools** | Messaging, media, history, search, web fetch, cron jobs, triggers, goals, stickers, file system, admin controls |
|
|
20
|
+
| **Plugins** | Hot-reloadable plugin system. Built-in: GitHub, MemPalace, Playwright, Brave Search |
|
|
21
|
+
| **Background agents** | Heartbeat (hourly by default — advances goals, proactively messages when something matters) and Dream (memory consolidation + diary) |
|
|
22
|
+
| **Goals** | Persistent multi-day objectives the agent commits to in chat; every heartbeat run re-reads them, makes progress, and records what it did |
|
|
23
|
+
| **Skills** | Agent-authored reusable scripts (bash/python/node) — procedures worked out once get saved and replayed locally at zero token cost |
|
|
24
|
+
| **Triggers** | Self-authored watcher scripts (bash/python/node) that wake the bot when conditions are met |
|
|
25
|
+
| **Per-chat settings** | Model, effort level, and pulse toggle per conversation via inline keyboard |
|
|
26
|
+
| **Model registry** | Models discovered from the active backend at startup — new models appear in all pickers automatically |
|
|
25
27
|
|
|
26
28
|
---
|
|
27
29
|
|
|
@@ -41,13 +43,39 @@ npx talon chat # terminal chat mode
|
|
|
41
43
|
|
|
42
44
|
**Prerequisites:**
|
|
43
45
|
|
|
44
|
-
- [Node.js
|
|
46
|
+
- [Node.js 24+](https://nodejs.org/)
|
|
45
47
|
- Backend-specific:
|
|
46
48
|
- `claude` backend: [Claude Code](https://docs.anthropic.com/en/docs/claude-code) installed and authenticated (`claude` CLI on PATH).
|
|
47
49
|
- `kilo` backend: nothing extra — `@kilocode/sdk` spawns a local server. Free models are accessible without auth; routed models use Kilo's own credentials.
|
|
48
50
|
- `opencode` backend: nothing extra — `@opencode-ai/sdk` spawns a local server.
|
|
49
|
-
- `codex` backend: install the `codex` CLI (`npm i -g @openai/codex`) and authenticate with `codex login`
|
|
50
|
-
|
|
51
|
+
- `codex` backend: install the `codex` CLI (`npm i -g @openai/codex`) and authenticate with `codex login`, `CODEX_API_KEY`, `TALON_CODEX_KEY`, or `codexApiKey`. `OPENAI_API_KEY` is used only as a fallback when no Codex login exists.
|
|
52
|
+
|
|
53
|
+
### Standalone binary
|
|
54
|
+
|
|
55
|
+
Each release also ships self-contained binaries (no Node.js required) for
|
|
56
|
+
Linux and macOS (x64 + arm64) and Windows (x64). Prompts and all native
|
|
57
|
+
modules are embedded in the binary.
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Homebrew (macOS / Linux)
|
|
61
|
+
brew install dylanneve1/talon/talon
|
|
62
|
+
|
|
63
|
+
# Debian / Ubuntu — download the .deb for your arch from the release, then:
|
|
64
|
+
sudo apt install ./talon_<version>_amd64.deb # or _arm64.deb
|
|
65
|
+
|
|
66
|
+
# Direct download — grab talon-<os>-<arch> from the release, verify, run:
|
|
67
|
+
chmod +x talon-linux-x64 && ./talon-linux-x64 --version
|
|
68
|
+
# macOS, if Gatekeeper blocks an unsigned binary:
|
|
69
|
+
xattr -d com.apple.quarantine ./talon-darwin-arm64
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Verify a direct download against the release `SHA256SUMS`:
|
|
73
|
+
`sha256sum -c SHA256SUMS --ignore-missing`.
|
|
74
|
+
|
|
75
|
+
> The binary runs the full interactive/agent CLI (`setup`, `start`, `chat`,
|
|
76
|
+
> `doctor`, …). Hosting Talon's _own_ MCP server (`talon` as an MCP stdio
|
|
77
|
+
> server for another client) still needs the npm/Node install — it spawns a
|
|
78
|
+
> `tsx` loader that isn't present in a compiled binary.
|
|
51
79
|
|
|
52
80
|
---
|
|
53
81
|
|
|
@@ -57,58 +85,86 @@ npx talon chat # terminal chat mode
|
|
|
57
85
|
index.ts Composition root
|
|
58
86
|
|
|
|
59
87
|
+-- core/ Platform-agnostic engine
|
|
60
|
-
| +--
|
|
61
|
-
| +--
|
|
62
|
-
|
|
|
88
|
+
| +-- agent-runtime/ Backend capability interfaces, events, stores
|
|
89
|
+
| +-- models/ Model layer: catalog, per-chat active model,
|
|
90
|
+
| | reasoning-effort vocabulary
|
|
91
|
+
| +-- prompt/ System-prompt assembly + prompts/system templates
|
|
92
|
+
| +-- background/ Agents that run without a user message:
|
|
93
|
+
| | heartbeat, dream, pulse, cron, triggers
|
|
94
|
+
| +-- tools/ MCP tool definitions + spawn/env contract
|
|
95
|
+
| +-- engine/ Message flow: dispatcher (per-chat serial,
|
|
96
|
+
| | cross-chat parallel), HTTP gateway for MCP
|
|
97
|
+
| | tool calls, backend lifecycle controller
|
|
63
98
|
| +-- plugin.ts Plugin loader, registry, hot-reload
|
|
64
|
-
| +-- heartbeat.ts Periodic background agent
|
|
65
|
-
| +-- dream.ts Memory consolidation agent
|
|
66
|
-
| +-- pulse.ts Conversation-aware group engagement
|
|
67
|
-
| +-- cron.ts Persistent scheduled jobs
|
|
68
|
-
| +-- triggers.ts Self-authored watcher scripts
|
|
69
|
-
| +-- tools/ MCP tool definitions
|
|
70
99
|
|
|
|
71
100
|
+-- backend/
|
|
72
101
|
| +-- registry.ts Bootstrap-decoupled backend lookup
|
|
73
102
|
| +-- shared/ Cross-backend helpers (stream state, flow violation,
|
|
74
|
-
| |
|
|
103
|
+
| | delivery contract, metrics, prompt format,
|
|
104
|
+
| | model retry, system prompt, usage)
|
|
75
105
|
| +-- remote-server/ Shared infrastructure for agent-server backends
|
|
76
106
|
| | (MCP registration, sessions, providers, lifecycle)
|
|
77
107
|
| +-- claude-sdk/ Claude Agent SDK (in-process MCP, hooks)
|
|
78
108
|
| +-- kilo/ Kilo HTTP server backend (streaming via SSE)
|
|
79
109
|
| +-- opencode/ OpenCode HTTP server backend
|
|
80
110
|
| +-- codex/ Codex CLI backend (`@openai/codex-sdk`)
|
|
111
|
+
| +-- openai-agents/ OpenAI Agents SDK backend (Responses API)
|
|
81
112
|
|
|
|
82
113
|
+-- frontend/
|
|
114
|
+
| +-- shared/ Cross-frontend presentation helpers
|
|
83
115
|
| +-- telegram/ Grammy bot + GramJS userbot
|
|
84
116
|
| +-- discord/ discord.js v14
|
|
85
117
|
| +-- teams/ Bot Framework + Graph API
|
|
86
118
|
| +-- terminal/ Readline CLI with tool call visibility
|
|
119
|
+
| +-- desktop/ Client bridge (HTTP + SSE) for the companion app
|
|
87
120
|
|
|
|
88
121
|
+-- storage/ Sessions, history, chat settings,
|
|
89
122
|
| cron jobs, media index, daily logs
|
|
90
123
|
+-- util/ Config, logging, workspace, paths, time
|
|
91
124
|
```
|
|
92
125
|
|
|
93
|
-
**Dependency rule:** `core/` imports nothing from `frontend/` or `backend/`. Frontends and backends depend on core types, never on each other. All
|
|
126
|
+
**Dependency rule:** `core/` imports nothing from `frontend/` or `backend/`. Frontends and backends depend on core types, never on each other. All five backends (Claude SDK, Kilo, OpenCode, Codex, OpenAI Agents) implement the same `Backend` capability interface from `core/agent-runtime/capabilities.ts`. Kilo and OpenCode additionally share the `remote-server/` infrastructure because they wrap forks of the same upstream HTTP agent server.
|
|
127
|
+
|
|
128
|
+
**Prompts:** everything the model reads at session start is assembled by `core/prompt/` from the files in `prompts/` — see [prompts/README.md](prompts/README.md) for the assembly order, file ownership (user-editable vs package-owned templates), and the per-backend delivery contracts.
|
|
94
129
|
|
|
95
130
|
---
|
|
96
131
|
|
|
97
132
|
## Backends
|
|
98
133
|
|
|
99
|
-
Select via the `backend` field in `~/.talon/config.json`. All backends implement the same `
|
|
134
|
+
Select via the `backend` field in `~/.talon/config.json`. All backends implement the same `Backend` capability interface — heartbeat, dream, and chat handlers are backend-agnostic.
|
|
100
135
|
|
|
101
|
-
| Backend | `backend` value | Transport
|
|
102
|
-
| ---------- | --------------- |
|
|
103
|
-
| Claude SDK | `"claude"` | In-process via `@anthropic-ai/claude-agent-sdk`
|
|
104
|
-
| Kilo | `"kilo"` | Local HTTP server via `@kilocode/sdk`
|
|
105
|
-
| OpenCode | `"opencode"` | Local HTTP server via `@opencode-ai/sdk`
|
|
106
|
-
| Codex | `"codex"` | Per-turn subprocess via `@openai/codex-sdk`
|
|
136
|
+
| Backend | `backend` value | Transport | Notes |
|
|
137
|
+
| ---------- | --------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
138
|
+
| Claude SDK | `"claude"` | In-process via `@anthropic-ai/claude-agent-sdk` | Requires the `claude` CLI on `PATH`. Hook-based turn termination. |
|
|
139
|
+
| Kilo | `"kilo"` | Local HTTP server via `@kilocode/sdk` | SSE-streamed turns. Routes to many model providers via Kilo's auth. |
|
|
140
|
+
| OpenCode | `"opencode"` | Local HTTP server via `@opencode-ai/sdk` | SSE-streamed turns; same MCP and session shape as Kilo (upstream fork). |
|
|
141
|
+
| Codex | `"codex"` | Per-turn subprocess via `@openai/codex-sdk` | Requires the `codex` CLI from `@openai/codex` and Codex auth (`codex login`, `CODEX_API_KEY`, `TALON_CODEX_KEY`, or `codexApiKey`). MCP servers configured via TOML overrides at thread start. |
|
|
142
|
+
| OpenAI Agents | `"openai-agents"` | In-process via `@openai/agents` | Responses API (or any OpenAI-compatible endpoint via `TALON_AGENTS_URL` / `openaiBaseUrl`). Persistent per-chat MCP bundles. |
|
|
107
143
|
|
|
108
144
|
The Kilo and OpenCode backends share infrastructure (`backend/remote-server/`) since the upstream HTTP API is the same; each backend supplies its own SDK client, port, and delivery suffix. Codex is its own integration on top of the Codex CLI's JSONL event stream.
|
|
109
145
|
|
|
110
146
|
---
|
|
111
147
|
|
|
148
|
+
## Desktop & mobile app
|
|
149
|
+
|
|
150
|
+
The `desktop` frontend turns the daemon into a **client bridge** — a versioned HTTP + Server-Sent-Events JSON API (the _Talon Client Bridge Protocol_, `src/frontend/desktop/protocol.ts`) that any GUI client can speak. The reference client is **[Talon Companion](apps/companion/)**, a single Flutter codebase that runs on **Windows, macOS, Linux, and Android**.
|
|
151
|
+
|
|
152
|
+
```jsonc
|
|
153
|
+
// ~/.talon/config.json
|
|
154
|
+
{
|
|
155
|
+
"frontend": "desktop",
|
|
156
|
+
"desktop": { "host": "127.0.0.1", "port": 19880 }
|
|
157
|
+
// For remote (e.g. a phone): "host": "0.0.0.0", "token": "your-secret"
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
- **Local (desktop):** the app connects to a Talon on the same machine and launches one if needed (`TALON_FRONTEND_OVERRIDE=desktop`).
|
|
162
|
+
- **Remote (mobile/LAN):** point the app at `host:port` + token; the bridge requires `Authorization: Bearer …` (or `?token=` on the SSE stream) whenever a token is set.
|
|
163
|
+
|
|
164
|
+
The app provides multi-chat history, live streaming with reasoning + tool-call visibility, per-chat model/effort/pulse/reset, and **settings sync** — read and change the daemon's own config (default model, display name, timezone, pulse/heartbeat/dream) and restart it. See [apps/companion/README.md](apps/companion/README.md).
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
112
168
|
## Built-in Plugins
|
|
113
169
|
|
|
114
170
|
### GitHub
|
|
@@ -244,25 +300,28 @@ talon doctor Validate environment and dependencies
|
|
|
244
300
|
|
|
245
301
|
Config file: `~/.talon/config.json`
|
|
246
302
|
|
|
247
|
-
| Field | Default | Description
|
|
248
|
-
| -------------------------- | ------------ |
|
|
249
|
-
| `frontend` | `"telegram"` | `"telegram"`, `"discord"`, `"teams"`, `"terminal"`, or an array
|
|
250
|
-
| `backend` | `"claude"` | `"claude"`, `"kilo"`, `"opencode"`, or `"
|
|
251
|
-
| `botToken` | --- | Telegram bot token
|
|
252
|
-
| `model` | `"default"` | Default model. Interpretation depends on the active backend.
|
|
253
|
-
| `
|
|
254
|
-
| `
|
|
255
|
-
| `
|
|
256
|
-
| `
|
|
257
|
-
| `
|
|
258
|
-
| `
|
|
259
|
-
| `
|
|
260
|
-
| `
|
|
261
|
-
| `
|
|
262
|
-
| `
|
|
263
|
-
| `
|
|
264
|
-
| `
|
|
265
|
-
| `
|
|
303
|
+
| Field | Default | Description |
|
|
304
|
+
| -------------------------- | ------------ | ----------------------------------------------------------------------------------------------------------------------- |
|
|
305
|
+
| `frontend` | `"telegram"` | `"telegram"`, `"discord"`, `"teams"`, `"terminal"`, or an array |
|
|
306
|
+
| `backend` | `"claude"` | `"claude"`, `"kilo"`, `"opencode"`, `"codex"`, or `"openai-agents"` |
|
|
307
|
+
| `botToken` | --- | Telegram bot token |
|
|
308
|
+
| `model` | `"default"` | Default model. Interpretation depends on the active backend. |
|
|
309
|
+
| `codexApiKey` | --- | Codex-only OpenAI API key. Prefer this over `openaiApiKey` for Codex API-key auth. `codex login` takes precedence over shared `openaiApiKey`. |
|
|
310
|
+
| `concurrency` | `1` | Max concurrent AI queries (1--20) |
|
|
311
|
+
| `pulse` | `true` | Periodic group engagement |
|
|
312
|
+
| `heartbeat` | `false` | Background maintenance agent |
|
|
313
|
+
| `heartbeatIntervalMinutes` | `60` | Heartbeat interval |
|
|
314
|
+
| `braveApiKey` | --- | Brave Search API key |
|
|
315
|
+
| `timezone` | --- | IANA timezone (e.g. `"Europe/London"`) |
|
|
316
|
+
| `plugins` | `[]` | External plugin packages |
|
|
317
|
+
| `disabledToolTags` | --- | Hide whole tool groups from the model (e.g. `["stickers", "web"]`) — each registered tool costs context tokens per session |
|
|
318
|
+
| `disabledTools` | --- | Hide individual tools by name (`end_turn` cannot be disabled) |
|
|
319
|
+
| `adminUserId` | --- | Telegram user ID for `/admin` commands |
|
|
320
|
+
| `allowedUsers` | --- | Whitelist of Telegram user IDs |
|
|
321
|
+
| `apiId` / `apiHash` | --- | Telegram API credentials for full message history |
|
|
322
|
+
| `github` | --- | GitHub plugin config (see above) |
|
|
323
|
+
| `mempalace` | --- | MemPalace plugin config (see above) |
|
|
324
|
+
| `playwright` | --- | Playwright plugin config (see above) |
|
|
266
325
|
|
|
267
326
|
---
|
|
268
327
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "talon-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.34.0",
|
|
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",
|
|
@@ -18,26 +18,35 @@
|
|
|
18
18
|
"chatbot"
|
|
19
19
|
],
|
|
20
20
|
"engines": {
|
|
21
|
-
"node": ">=
|
|
21
|
+
"node": ">=24"
|
|
22
22
|
},
|
|
23
23
|
"type": "module",
|
|
24
24
|
"main": "./src/index.ts",
|
|
25
25
|
"exports": {
|
|
26
26
|
".": "./src/index.ts"
|
|
27
27
|
},
|
|
28
|
+
"imports": {
|
|
29
|
+
"#prompt-assets": {
|
|
30
|
+
"bun": "./src/core/prompt/embedded-prompts.ts",
|
|
31
|
+
"default": "./src/core/prompt/disk-prompts.ts"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
28
34
|
"bin": {
|
|
29
35
|
"talon": "./bin/talon.js"
|
|
30
36
|
},
|
|
31
37
|
"files": [
|
|
32
|
-
"bin/",
|
|
38
|
+
"bin/talon.js",
|
|
33
39
|
"src/backend/",
|
|
34
40
|
"src/core/",
|
|
35
41
|
"src/frontend/",
|
|
42
|
+
"src/native/",
|
|
36
43
|
"src/plugins/",
|
|
37
44
|
"src/storage/",
|
|
38
45
|
"src/util/",
|
|
46
|
+
"src/app.ts",
|
|
39
47
|
"src/bootstrap.ts",
|
|
40
48
|
"src/cli.ts",
|
|
49
|
+
"src/cli/",
|
|
41
50
|
"src/index.ts",
|
|
42
51
|
"src/login.ts",
|
|
43
52
|
"prompts/",
|
|
@@ -58,6 +67,10 @@
|
|
|
58
67
|
"test:kilo:backend": "vitest run --reporter=verbose --reporter=json --outputFile=kilo-backend-results.json src/__tests__/integration/kilo-live-discovery.test.ts",
|
|
59
68
|
"test:opencode:backend": "vitest run --reporter=verbose --reporter=json --outputFile=opencode-backend-results.json src/__tests__/integration/opencode-live-discovery.test.ts",
|
|
60
69
|
"test:codex:backend": "vitest run --reporter=verbose --reporter=json --outputFile=codex-backend-results.json src/__tests__/integration/codex-live-discovery.test.ts",
|
|
70
|
+
"test:openai-agents:backend": "vitest run --reporter=verbose --reporter=json --outputFile=openai-agents-backend-results.json src/__tests__/integration/openai-agents-live-discovery.test.ts",
|
|
71
|
+
"build:sql": "tsx scripts/embed-sql.ts",
|
|
72
|
+
"build:prompts": "tsx scripts/embed-prompts.ts",
|
|
73
|
+
"build:wasm": "node native/blake3-wasm/build.mjs",
|
|
61
74
|
"tarball:check": "node .github/scripts/tarball-check.mjs",
|
|
62
75
|
"build:stub-sea": "node src/__tests__/integration/stub-claude/build-sea.mjs",
|
|
63
76
|
"test:watch": "vitest",
|
|
@@ -67,26 +80,38 @@
|
|
|
67
80
|
"knip": "knip",
|
|
68
81
|
"format": "prettier --write src/ prompts/",
|
|
69
82
|
"format:check": "prettier --check src/ prompts/",
|
|
70
|
-
"ci:protect": "node .github/scripts/enforce-ci-gate.mjs"
|
|
83
|
+
"ci:protect": "node .github/scripts/enforce-ci-gate.mjs",
|
|
84
|
+
"build:gleam": "cd native/scheduler-core && gleam build --target javascript && node embed.mjs",
|
|
85
|
+
"build:zig": "node native/textops-wasm/build.mjs",
|
|
86
|
+
"build:c": "node native/strsim-c/build.mjs && node native/sqlguard-c/build.mjs",
|
|
87
|
+
"build:cpp": "node native/htmlents-cpp/build.mjs",
|
|
88
|
+
"build:native": "npm run build:wasm && npm run build:zig && npm run build:c && npm run build:cpp && npm run build:gleam",
|
|
89
|
+
"build:driver": "node native/talon-driver/build.mjs",
|
|
90
|
+
"build:driver:all": "node native/talon-driver/build.mjs --all",
|
|
91
|
+
"build:warden": "node native/talon-warden/build.mjs",
|
|
92
|
+
"build:napi": "node native/blake3-napi/build.mjs"
|
|
71
93
|
},
|
|
72
94
|
"dependencies": {
|
|
73
|
-
"@anthropic-ai/claude-agent-sdk": "^0.
|
|
74
|
-
"@anthropic-ai/sdk": "^0.
|
|
95
|
+
"@anthropic-ai/claude-agent-sdk": "^0.3.197",
|
|
96
|
+
"@anthropic-ai/sdk": "^0.104.1",
|
|
75
97
|
"@brave/brave-search-mcp-server": "^2.0.75",
|
|
76
98
|
"@clack/prompts": "^1.2.0",
|
|
77
99
|
"@grammyjs/auto-retry": "^2.0.2",
|
|
78
100
|
"@grammyjs/transformer-throttler": "^1.2.1",
|
|
79
101
|
"@kilocode/sdk": "^7.2.22",
|
|
80
102
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
81
|
-
"@openai/agents": "^0.
|
|
82
|
-
"@openai/codex-sdk": "^0.
|
|
83
|
-
"@opencode-ai/sdk": "^1.4
|
|
84
|
-
"@playwright/mcp": "^0.0.
|
|
103
|
+
"@openai/agents": "^0.12.0",
|
|
104
|
+
"@openai/codex-sdk": "^0.142.0",
|
|
105
|
+
"@opencode-ai/sdk": "^1.17.4",
|
|
106
|
+
"@playwright/mcp": "^0.0.77",
|
|
107
|
+
"@types/cross-spawn": "^6.0.6",
|
|
85
108
|
"big-integer": "^1.6.52",
|
|
86
109
|
"cheerio": "^1.2.0",
|
|
87
110
|
"croner": "^10.0.1",
|
|
111
|
+
"cross-spawn": "^7.0.6",
|
|
88
112
|
"discord.js": "^14.16.3",
|
|
89
113
|
"grammy": "^1.42.0",
|
|
114
|
+
"liquidjs": "^10.27.0",
|
|
90
115
|
"marked": "^18.0.0",
|
|
91
116
|
"p-retry": "^8.0.0",
|
|
92
117
|
"picocolors": "^1.1.1",
|
|
@@ -95,11 +120,13 @@
|
|
|
95
120
|
"telegram": "^2.26.22",
|
|
96
121
|
"tsx": "^4.21.0",
|
|
97
122
|
"undici": "^8.0.2",
|
|
123
|
+
"wasmoon": "^1.16.0",
|
|
98
124
|
"write-file-atomic": "^8.0.0",
|
|
125
|
+
"yaml": "^2.9.0",
|
|
99
126
|
"zod": "^4.3.6"
|
|
100
127
|
},
|
|
101
128
|
"devDependencies": {
|
|
102
|
-
"@types/node": "^
|
|
129
|
+
"@types/node": "^26.0.0",
|
|
103
130
|
"@types/write-file-atomic": "^4.0.3",
|
|
104
131
|
"@vitest/coverage-v8": "^4.1.3",
|
|
105
132
|
"fast-check": "^4.6.0",
|
|
@@ -110,7 +137,7 @@
|
|
|
110
137
|
"vitest": "^4.1.3"
|
|
111
138
|
},
|
|
112
139
|
"overrides": {
|
|
113
|
-
"@anthropic-ai/sdk": "^0.
|
|
140
|
+
"@anthropic-ai/sdk": "^0.104.1",
|
|
114
141
|
"ip-address": "^10.1.1",
|
|
115
142
|
"fast-uri": "^3.1.2"
|
|
116
143
|
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Talon prompt architecture
|
|
2
|
+
|
|
3
|
+
Everything the model reads at session start is assembled from the files in
|
|
4
|
+
this directory by `src/core/prompt/assemble.ts`. This README is the map.
|
|
5
|
+
|
|
6
|
+
## Assembly order
|
|
7
|
+
|
|
8
|
+
The system prompt is an ordered list of markdown sections joined by `---`
|
|
9
|
+
dividers, split into a **static** prefix (stable for a session's lifetime,
|
|
10
|
+
eligible for provider prompt caching) and a **dynamic** tail (volatile,
|
|
11
|
+
placed after the cache boundary):
|
|
12
|
+
|
|
13
|
+
| # | Section | Source | Part |
|
|
14
|
+
| --- | --------------------- | ---------------------------------------------------------------------- | ------------- |
|
|
15
|
+
| 1 | Identity | `identity.md` + `~/.talon/workspace/identity.md` | static |
|
|
16
|
+
| 2 | Core behaviour | `custom.md` (replaces `base.md` when present) | static |
|
|
17
|
+
| 3 | Frontend capabilities | `<frontend>.md` (telegram / discord / teams / terminal / native) | static |
|
|
18
|
+
| 4 | Persistent memory | `system/persistent-memory.md` wrapping `memory/memory.md`, size-capped | static |
|
|
19
|
+
| 5 | Capability docs | `system/workspace.md`, `system/cron.md`, `system/triggers.md` | static |
|
|
20
|
+
| 6 | Plugin additions | each plugin's `systemPrompt()` contribution | static |
|
|
21
|
+
| 7 | **Delivery contract** | `system/contract-*.md`, appended by the **backend** as its suffix | static (tail) |
|
|
22
|
+
| 8 | Daily-memory pointer | `system/daily-memory.md` (names today's file) | dynamic |
|
|
23
|
+
| 9 | Skills | generated index of `workspace/skills/<name>/SKILL.md` | dynamic |
|
|
24
|
+
| 10 | Workspace listing | generated tree of `~/.talon/workspace/` | dynamic |
|
|
25
|
+
|
|
26
|
+
The delivery contract is deliberately LAST in the static prefix: it is the
|
|
27
|
+
one section the model must not miss, and the end of the prompt is the
|
|
28
|
+
highest-salience position.
|
|
29
|
+
|
|
30
|
+
Skills are deliberately an index, not full bodies. The dynamic
|
|
31
|
+
prompt names saved SKILL.md workflows and their descriptions; agents use
|
|
32
|
+
`find_skills` to select a relevant workflow and `read_skill` to load the
|
|
33
|
+
full body (and discover any bundled files) before following it. Each skill
|
|
34
|
+
follows Anthropic's Agent Skills standard: a `skills/<name>/SKILL.md` folder
|
|
35
|
+
that may also bundle supporting files. This progressive-disclosure path is
|
|
36
|
+
backend-agnostic: Claude SDK, Codex, Kilo, OpenCode, and OpenAI Agents all
|
|
37
|
+
receive the same prompt index and call the same shared gateway tools, even
|
|
38
|
+
when a backend has no native "skills" feature.
|
|
39
|
+
|
|
40
|
+
## File ownership — two kinds of prompt files
|
|
41
|
+
|
|
42
|
+
**User-editable prompts** (everything at the top level of this directory:
|
|
43
|
+
`identity.md`, `base.md`, `custom.md`, `telegram.md`, `discord.md`,
|
|
44
|
+
`teams.md`, `terminal.md`, `native.md`, `heartbeat.md`, `dream.md`,
|
|
45
|
+
`mempalace.md`) are
|
|
46
|
+
seeded into `~/.talon/prompts/` on first run and read from there.
|
|
47
|
+
Seeding is upgrade-aware (dpkg-conffile semantics, tracked via a
|
|
48
|
+
`.seeded.json` hash manifest next to the seeded files): a file the user
|
|
49
|
+
has never edited is refreshed when a package update changes it, while a
|
|
50
|
+
file the user has touched is never overwritten again. Deployments that
|
|
51
|
+
predate the manifest keep their existing files as user-owned unless
|
|
52
|
+
byte-identical to the current package copy.
|
|
53
|
+
|
|
54
|
+
**System templates** (`system/*.md`) are read directly from the package and
|
|
55
|
+
are NOT seeded. They document runtime behaviour that is versioned with the
|
|
56
|
+
code — delivery tool names, flow enforcement, trigger limits. A stale
|
|
57
|
+
seeded copy would silently describe a contract the code no longer
|
|
58
|
+
implements, so these are not user-customisable.
|
|
59
|
+
|
|
60
|
+
System templates are [Liquid](https://liquidjs.com) (rendered by
|
|
61
|
+
`src/core/prompt/templates.ts`): `{{var}}` output (missing vars render
|
|
62
|
+
empty), `{% if var %}…{% else %}…{% endif %}` conditionals (JS
|
|
63
|
+
truthiness — `""` is falsy), and `{% render 'partial' %}` includes
|
|
64
|
+
resolved against `system/`. Prefer composing related sections inside
|
|
65
|
+
one file with conditionals over adding a new file per fragment —
|
|
66
|
+
`heartbeat-agent.md` (system prompt + goals-fallback section selected
|
|
67
|
+
via `mode`) is the pattern.
|
|
68
|
+
|
|
69
|
+
User-editable prompts are NOT Liquid: their consumers substitute
|
|
70
|
+
`{{var}}` placeholders with plain string replacement, so a user edit
|
|
71
|
+
can never break prompt assembly with a template syntax error.
|
|
72
|
+
|
|
73
|
+
## The delivery contract (response flow)
|
|
74
|
+
|
|
75
|
+
How a reply reaches the user is a property of the **backend**, not the
|
|
76
|
+
frontend, so it never belongs in the frontend `.md` files:
|
|
77
|
+
|
|
78
|
+
- `system/contract-tool-only.md` — claude-sdk, openai-agents. The output
|
|
79
|
+
stream is private scratchpad; replies MUST go through a delivery tool
|
|
80
|
+
(`end_turn` / `send` / `react`). A prose-only turn triggers one
|
|
81
|
+
`[FLOW VIOLATION]` re-prompt, then a silent drop.
|
|
82
|
+
- `system/contract-text-or-tools.md` — codex, kilo. Plain assistant text
|
|
83
|
+
is the reply; delivery tools add targeting / rich content.
|
|
84
|
+
- `system/contract-text-preferred.md` — opencode. Plain text is the
|
|
85
|
+
normal route; tools only for genuine side effects.
|
|
86
|
+
|
|
87
|
+
The delivery TOOL NAMES are per-frontend (`end_turn`/`send`/`react` on
|
|
88
|
+
telegram & discord, `end_turn`/`send_message`/`react` on native,
|
|
89
|
+
`end_turn`/`send_message` on teams) and are injected into the templates
|
|
90
|
+
by `src/backend/shared/delivery-contract.ts`, which is also where the
|
|
91
|
+
frontend-aware `[FLOW VIOLATION]` reminder and the first-turn nudge
|
|
92
|
+
(appended to the turn-0 user message) are built.
|
|
93
|
+
|
|
94
|
+
When editing frontend `.md` files, describe what the frontend can DO
|
|
95
|
+
(tools, formatting, culture); never re-state how replies are delivered —
|
|
96
|
+
the contract section wins, and duplicated contract text has already caused
|
|
97
|
+
contradictions between backends.
|
|
98
|
+
|
|
99
|
+
## Task prompts
|
|
100
|
+
|
|
101
|
+
`heartbeat.md` and `dream.md` are not part of the chat system prompt — they
|
|
102
|
+
are standalone prompts for the background heartbeat and memory-consolidation
|
|
103
|
+
(dream) agents, loaded by `src/core/background/heartbeat.ts` /
|
|
104
|
+
`src/core/background/dream.ts`.
|
|
105
|
+
|
|
106
|
+
## Token budget
|
|
107
|
+
|
|
108
|
+
The static prompt is read on EVERY session: every sentence must earn its
|
|
109
|
+
tokens. Per-tool parameter details and examples belong in the MCP tool
|
|
110
|
+
descriptions (which the model also has in context), not here. The memory
|
|
111
|
+
section is capped (`MEMORY_INJECT_MAX_CHARS`) and the workspace listing
|
|
112
|
+
collapses directories with more than 8 entries.
|
package/prompts/base.md
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
Be concise and direct.
|
|
1
|
+
Be concise and direct. Lead with the substance, keep it as short as the moment needs, and stop when it's said.
|
|
2
|
+
|
|
3
|
+
## Conversation
|
|
4
|
+
|
|
5
|
+
- Answer first; context and caveats after, and only when they change something for the reader.
|
|
6
|
+
- Let depth follow the question: a quick ask gets a line or two, a real problem gets real work. When unsure, start small — people ask for more when they want it.
|
|
7
|
+
- Chat is not a document. Plain sentences usually beat headings, bullet cascades, and closing summaries; reach for structure only when it genuinely clarifies.
|
|
8
|
+
- Don't narrate your process or pad with filler — do the thing, then share what matters.
|
|
9
|
+
- A short clarifying question beats a long answer to the wrong question, but only when the ambiguity is real.
|
|
2
10
|
|
|
3
11
|
## Tools
|
|
4
12
|
|
|
5
|
-
Only the tools the runtime registers for this turn are usable — the
|
|
6
|
-
list is attached to this prompt by the backend. Do not invent or
|
|
7
|
-
guess tool names from prior Talon configurations, other agents, or
|
|
8
|
-
typical AI tooling vocabularies; if a name isn't in the registered
|
|
9
|
-
list, calling it will fail the turn.
|
|
13
|
+
Only the tools the runtime registers for this turn are usable — the list is attached to this prompt by the backend. Don't invent or guess tool names from prior configurations, other agents, or typical AI tooling vocabularies; if a name isn't registered, calling it fails the turn. Some backends load plugin tools lazily behind a discovery/search step: if a capability should exist but its tool isn't in your loaded list yet, discover it first rather than calling the name blind — an undiscovered call fails even when the name is right.
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
plain conversation. Don't pretend to perform actions (reading a
|
|
13
|
-
file, running a command, browsing the web) you have no tool for —
|
|
14
|
-
say so plainly instead, and ask the user if you're unsure.
|
|
15
|
+
Prefer doing over describing: when a tool can check, fetch, or fix something, use it instead of speculating. When nothing fits, fall back to plain conversation — never pretend to perform actions (reading a file, running a command, browsing the web) you have no tool for. If a tool fails or a result surprises you, say so plainly rather than papering over it.
|
|
15
16
|
|
|
16
|
-
Workspace artifacts, when persistable for this backend, live under
|
|
17
|
-
`~/.talon/workspace/`.
|
|
17
|
+
Workspace artifacts, when persistable for this backend, live under `~/.talon/workspace/`.
|
package/prompts/discord.md
CHANGED
|
@@ -2,28 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
In servers (guilds), you'll see messages prefixed with [Name]: — use their name naturally. In DMs, just one user.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
How replies are delivered (end_turn / send / react and what counts as a valid turn) is defined in the **Response flow** section at the end of these instructions — that contract wins over anything here.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
### Tools
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
One tool for everything. Set `type` to choose what to send:
|
|
12
|
-
|
|
13
|
-
- `send(type="text", text="Hello!")` — send a message
|
|
14
|
-
- `send(type="text", text="Hey", reply_to="123456789012345678")` — reply to a specific message (Discord IDs are strings)
|
|
15
|
-
- `send(type="text", text="Pick", buttons=[[{"text":"A","callback_data":"a","style":"primary"}]])` — with buttons
|
|
16
|
-
- `send(type="text", text="Reminder", delay_seconds=60)` — schedule for later
|
|
17
|
-
- `send(type="photo", file_path="img.jpg", caption="Look!")` — send an image
|
|
18
|
-
- `send(type="file", file_path="report.pdf")` — send a document
|
|
19
|
-
- `send(type="video", file_path="clip.mp4")` — send a video
|
|
20
|
-
- `send(type="voice", file_path="audio.ogg")` — send an audio attachment
|
|
21
|
-
- `send(type="poll", question="Best?", options=["A","B","C"])` — create a poll
|
|
22
|
-
- `send(type="dice")` — roll dice
|
|
23
|
-
- `send(type="location", latitude=37.77, longitude=-122.42)` — share a Google Maps location link
|
|
24
|
-
- `send(type="contact", phone_number="+1234", first_name="John")` — share a contact card
|
|
25
|
-
|
|
26
|
-
ALL types support `reply_to` to reply to a specific message.
|
|
9
|
+
Your registered tool list covers the full Discord surface — rich sends (images, files, polls, scheduled messages), reactions, message management (edit/delete/pin), chat history and search, member info. Tool descriptions carry the parameters and examples; don't guess capabilities, check the list.
|
|
27
10
|
|
|
28
11
|
### Discord-specific
|
|
29
12
|
|
|
@@ -32,45 +15,25 @@ ALL types support `reply_to` to reply to a specific message.
|
|
|
32
15
|
- **Markdown is native:** `**bold**`, `*italic*`, `` `code` ``, ` ```fenced``` `, `# headings`, `> quotes`, `||spoilers||`, `[links](url)`. Discord renders these without translation.
|
|
33
16
|
- **Mentions:** the bot is configured to suppress all mentions (`@everyone`, `@here`, role/user pings) so you can't accidentally ping anyone. Don't worry about escaping.
|
|
34
17
|
- **Message limit:** 2000 chars per message. Long messages are auto-chunked at paragraph breaks.
|
|
35
|
-
|
|
36
|
-
### Other tools
|
|
37
|
-
|
|
38
|
-
- `react(message_id, emoji)` — react to a message (unicode emoji only on Discord; custom emojis need `<:name:id>` format)
|
|
39
|
-
- `edit_message(message_id, text)` — edit a sent message (max 2000 chars)
|
|
40
|
-
- `delete_message(message_id)` — delete a message
|
|
41
|
-
- `pin_message(message_id)` / `unpin_message()` — pin/unpin
|
|
42
|
-
- `read_chat_history(limit)` — read past messages from this channel
|
|
43
|
-
- `search_chat_history(query)` — search recent messages by keyword
|
|
44
|
-
- `list_chat_members()` — list members in this server (guild only)
|
|
45
|
-
- `get_member_info(user_id)` — detailed user info
|
|
46
|
-
- `online_count()` — approximate online member count
|
|
18
|
+
- **Reactions:** unicode emoji only; custom emojis need `<:name:id>` format.
|
|
47
19
|
|
|
48
20
|
### Message IDs
|
|
49
21
|
|
|
50
|
-
The user's message ID is in the prompt as msg_id:N (Discord snowflake string). Use with `reply_to` and `react`.
|
|
22
|
+
The user's message ID is in the prompt as msg_id:N (Discord snowflake string). Use it with `reply_to` and `react`.
|
|
51
23
|
|
|
52
24
|
### Choosing not to respond
|
|
53
25
|
|
|
54
|
-
You don't HAVE to respond to every message.
|
|
55
|
-
|
|
56
|
-
- React with an emoji using the `react` tool — preferred way to acknowledge without replying.
|
|
57
|
-
- Or simply don't call `send` and skip it entirely.
|
|
58
|
-
- In servers, prefer reactions over replies for simple acknowledgements.
|
|
59
|
-
|
|
60
|
-
### Reactions
|
|
61
|
-
|
|
62
|
-
Use naturally: 👍 ❤️ 🔥 😂 🎉 👀 💯. React AND reply when both feel right.
|
|
26
|
+
You don't HAVE to respond to every message. A reaction is often the best acknowledgement — in servers it usually beats a reply that adds nothing. Pick whatever emoji fits the moment. React AND reply when both feel right; stay silent when neither is needed.
|
|
63
27
|
|
|
64
28
|
### Buttons & Components
|
|
65
29
|
|
|
66
30
|
When a user presses a button, you'll receive "[Button pressed]" with the custom_id. Buttons can also be a select menu — those come through with the chosen value in the same format.
|
|
67
31
|
|
|
68
|
-
###
|
|
32
|
+
### Files & media
|
|
69
33
|
|
|
70
34
|
- Files users send are saved to `~/.talon/workspace/uploads/`.
|
|
71
|
-
-
|
|
35
|
+
- You can send files by workspace path or attach media straight from a public URL (handy for images and GIFs found online). You CAN send files — never claim otherwise.
|
|
72
36
|
- File limit depends on the server's boost tier: 10 MB (default), 25 MB (tier 1), 50 MB (tier 2), 100 MB (tier 3). DMs use 10 MB. Larger files get rejected with a clear error — split or upload externally.
|
|
73
|
-
- You CAN send files. NEVER say you can't.
|
|
74
37
|
|
|
75
38
|
### Servers vs DMs
|
|
76
39
|
|
|
@@ -79,6 +42,6 @@ When a user presses a button, you'll receive "[Button pressed]" with the custom_
|
|
|
79
42
|
|
|
80
43
|
### Style
|
|
81
44
|
|
|
82
|
-
- Concise. No filler.
|
|
83
|
-
-
|
|
45
|
+
- Concise. No filler. Discord markdown renders natively — use it.
|
|
46
|
+
- It's a chat: a couple of short messages often land better than one wall of text. Use `send` for extra bubbles when that pacing reads naturally.
|
|
84
47
|
- In servers, use names naturally.
|