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
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite connection + schema setup — the high-performance data
|
|
3
|
+
* layer's entry point.
|
|
4
|
+
*
|
|
5
|
+
* One database at ~/.talon/data/talon.db, opened through the runtime's
|
|
6
|
+
* built-in SQLite: `node:sqlite` (stable since Node 23.4) under node,
|
|
7
|
+
* `bun:sqlite` under bun — so compiled single binaries need no native
|
|
8
|
+
* addon and there is nothing on disk to resolve. The heavy lifting —
|
|
9
|
+
* storage engine, indexes, FTS5 full-text search — is battle-tested C,
|
|
10
|
+
* orchestrated from TypeScript.
|
|
11
|
+
*
|
|
12
|
+
* Layering (keep it this way):
|
|
13
|
+
* - sql/schema.sql all DDL, idempotent, ensured on open
|
|
14
|
+
* - sql/<store>.sql every statement for one store
|
|
15
|
+
* - sql/statements.generated.ts committed embed of the above
|
|
16
|
+
* (`npm run build:sql`, see sql/embed.ts)
|
|
17
|
+
* - repositories/<store>.ts statement execution for one store, typed rows
|
|
18
|
+
* - <store>.ts public API + domain logic, ZERO SQL
|
|
19
|
+
* - db.ts (this file) connection, pragmas, schema setup
|
|
20
|
+
*
|
|
21
|
+
* Why this over the JSON stores it replaces: transactional row writes
|
|
22
|
+
* instead of rewrite-the-whole-file flush timers, indexed reads instead
|
|
23
|
+
* of in-memory scans (so retention needn't be capped), and FTS5 where
|
|
24
|
+
* stores need real search.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { mkdirSync } from "node:fs";
|
|
28
|
+
import { dirname } from "node:path";
|
|
29
|
+
import { files } from "../util/paths.js";
|
|
30
|
+
import { log, logError } from "../util/log.js";
|
|
31
|
+
import { SCHEMA, dbSql } from "./sql/statements.generated.js";
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The driver surface the repositories use — the intersection of
|
|
35
|
+
* node:sqlite's DatabaseSync and bun:sqlite's Database, which are
|
|
36
|
+
* API-compatible for exactly this set (verified empirically: prepared
|
|
37
|
+
* statements with positional params, identical row object shapes,
|
|
38
|
+
* multi-statement exec, FTS5 virtual tables).
|
|
39
|
+
*/
|
|
40
|
+
export type SqlStatement = {
|
|
41
|
+
get(...params: unknown[]): unknown;
|
|
42
|
+
all(...params: unknown[]): unknown[];
|
|
43
|
+
run(...params: unknown[]): unknown;
|
|
44
|
+
};
|
|
45
|
+
export type SqlDatabase = {
|
|
46
|
+
prepare(sql: string): SqlStatement;
|
|
47
|
+
exec(sql: string): void;
|
|
48
|
+
close(): void;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// bun (≤1.3.x) does not implement node:sqlite — a compiled binary dies
|
|
52
|
+
// at startup with "No such built-in module: node:sqlite". Both
|
|
53
|
+
// runtimes ship a native SQLite builtin, so pick at load time. The
|
|
54
|
+
// non-literal import specifier keeps tsc and bundlers from trying to
|
|
55
|
+
// resolve the module that doesn't exist on the other runtime.
|
|
56
|
+
const IS_BUN = typeof (globalThis as { Bun?: unknown }).Bun !== "undefined";
|
|
57
|
+
const sqliteModule = (await import(
|
|
58
|
+
IS_BUN ? "bun:sqlite" : "node:sqlite"
|
|
59
|
+
)) as Record<string, new (path: string) => SqlDatabase>;
|
|
60
|
+
const Database = IS_BUN ? sqliteModule.Database : sqliteModule.DatabaseSync;
|
|
61
|
+
|
|
62
|
+
let db: SqlDatabase | null = null;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Apply the complete schema. Every statement is IF NOT EXISTS, so this
|
|
66
|
+
* is a no-op on an up-to-date database and creates exactly what's
|
|
67
|
+
* missing on a fresh or older one.
|
|
68
|
+
*
|
|
69
|
+
* Column reconciliation runs first: `ALTER TABLE … ADD COLUMN` has no
|
|
70
|
+
* IF NOT EXISTS form, so columns added to already-shipped tables
|
|
71
|
+
* (media_index.content_hash) are ensured by attempting the ALTER and
|
|
72
|
+
* swallowing the two expected failures — "duplicate column name"
|
|
73
|
+
* (column already there) and "no such table" (fresh database; the
|
|
74
|
+
* CREATE TABLE in schema.sql includes the column).
|
|
75
|
+
*/
|
|
76
|
+
function ensureSchema(database: SqlDatabase): void {
|
|
77
|
+
const row = database
|
|
78
|
+
.prepare(
|
|
79
|
+
"SELECT COUNT(*) AS tables FROM sqlite_master WHERE type = 'table'",
|
|
80
|
+
)
|
|
81
|
+
.get() as { tables: number };
|
|
82
|
+
try {
|
|
83
|
+
database.exec(dbSql.addMediaContentHashColumn);
|
|
84
|
+
} catch {
|
|
85
|
+
/* duplicate column or no such table — both mean nothing to do */
|
|
86
|
+
}
|
|
87
|
+
database.exec("BEGIN");
|
|
88
|
+
try {
|
|
89
|
+
database.exec(SCHEMA);
|
|
90
|
+
database.exec("COMMIT");
|
|
91
|
+
} catch (err) {
|
|
92
|
+
database.exec("ROLLBACK");
|
|
93
|
+
throw err;
|
|
94
|
+
}
|
|
95
|
+
if (row.tables === 0) log("db", "Initialized database schema");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function defaultPath(): string {
|
|
99
|
+
// Test isolation: the vitest setup file points every worker at a
|
|
100
|
+
// throwaway database so suites never touch ~/.talon/data/talon.db.
|
|
101
|
+
return process.env.TALON_DB_PATH || files.database;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Open (or return) the process-wide database. The first call wins the
|
|
106
|
+
* path; tests pass an explicit tmp path and call closeDatabase() in
|
|
107
|
+
* teardown.
|
|
108
|
+
*/
|
|
109
|
+
export function getDatabase(path: string = defaultPath()): SqlDatabase {
|
|
110
|
+
if (db) return db;
|
|
111
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
112
|
+
const database = new Database(path);
|
|
113
|
+
try {
|
|
114
|
+
// WAL: readers don't block the writer, and crash recovery is
|
|
115
|
+
// journal-based instead of "hope the rename was atomic".
|
|
116
|
+
database.exec("PRAGMA journal_mode = WAL");
|
|
117
|
+
database.exec("PRAGMA synchronous = NORMAL");
|
|
118
|
+
database.exec("PRAGMA foreign_keys = ON");
|
|
119
|
+
ensureSchema(database);
|
|
120
|
+
} catch (err) {
|
|
121
|
+
// Setup failed — close the handle so a retry doesn't leak one
|
|
122
|
+
// open file descriptor (and WAL sidecar) per attempt.
|
|
123
|
+
try {
|
|
124
|
+
database.close();
|
|
125
|
+
} catch {
|
|
126
|
+
/* already closed */
|
|
127
|
+
}
|
|
128
|
+
throw err;
|
|
129
|
+
}
|
|
130
|
+
db = database;
|
|
131
|
+
return database;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
let transactionDepth = 0;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Best-effort rollback: a ROLLBACK that itself throws (database closed,
|
|
138
|
+
* I/O error) must not mask the original error from `fn`, and must not
|
|
139
|
+
* skip the depth bookkeeping — a stuck depth would silently turn every
|
|
140
|
+
* later top-level transaction into a savepoint.
|
|
141
|
+
*/
|
|
142
|
+
function tryExec(database: SqlDatabase, sql: string): void {
|
|
143
|
+
try {
|
|
144
|
+
database.exec(sql);
|
|
145
|
+
} catch (err) {
|
|
146
|
+
logError("db", `Transaction cleanup failed (${sql})`, err);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Run `fn` inside a transaction; rolls back on throw. Nested calls use SAVEPOINTs. */
|
|
151
|
+
export function inTransaction<T>(fn: () => T): T {
|
|
152
|
+
const database = getDatabase();
|
|
153
|
+
if (transactionDepth > 0) {
|
|
154
|
+
const sp = `sp${transactionDepth}`;
|
|
155
|
+
database.exec(`SAVEPOINT "${sp}"`);
|
|
156
|
+
transactionDepth++;
|
|
157
|
+
try {
|
|
158
|
+
const result = fn();
|
|
159
|
+
database.exec(`RELEASE "${sp}"`);
|
|
160
|
+
return result;
|
|
161
|
+
} catch (err) {
|
|
162
|
+
tryExec(database, `ROLLBACK TO "${sp}"`);
|
|
163
|
+
tryExec(database, `RELEASE "${sp}"`);
|
|
164
|
+
throw err;
|
|
165
|
+
} finally {
|
|
166
|
+
transactionDepth--;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
database.exec("BEGIN");
|
|
170
|
+
transactionDepth++;
|
|
171
|
+
try {
|
|
172
|
+
const result = fn();
|
|
173
|
+
database.exec("COMMIT");
|
|
174
|
+
return result;
|
|
175
|
+
} catch (err) {
|
|
176
|
+
tryExec(database, "ROLLBACK");
|
|
177
|
+
throw err;
|
|
178
|
+
} finally {
|
|
179
|
+
transactionDepth--;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Compact the WAL into the main database file. SQLite commits on
|
|
185
|
+
* every write, so there is no dirty buffer to flush — the shutdown
|
|
186
|
+
* and fatal-error paths call this once for the whole database
|
|
187
|
+
* (replacing the per-store flush functions of the JSON era).
|
|
188
|
+
*/
|
|
189
|
+
export function flushDatabase(): void {
|
|
190
|
+
if (!db) return;
|
|
191
|
+
try {
|
|
192
|
+
db.exec(dbSql.walCheckpoint);
|
|
193
|
+
} catch {
|
|
194
|
+
/* shutting down — best effort */
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function closeDatabase(): void {
|
|
199
|
+
if (!db) return;
|
|
200
|
+
try {
|
|
201
|
+
db.close();
|
|
202
|
+
} catch {
|
|
203
|
+
/* already closed */
|
|
204
|
+
}
|
|
205
|
+
db = null;
|
|
206
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistent goal store — multi-turn objectives the agent commits to
|
|
3
|
+
* and pursues across sessions.
|
|
4
|
+
*
|
|
5
|
+
* Goals are the agency primitive: a chat conversation (or the agent
|
|
6
|
+
* itself) records "keep an eye on X" / "finish Y by Friday" here, and
|
|
7
|
+
* the heartbeat agent reads the open set on every run to decide what
|
|
8
|
+
* to make progress on. Each goal carries a rolling last-progress note
|
|
9
|
+
* so a heartbeat can pick up where the previous one left off.
|
|
10
|
+
*
|
|
11
|
+
* SQLite-backed (see repositories/goals-repo.ts for the statements;
|
|
12
|
+
* this module holds the domain API and validation — no SQL here).
|
|
13
|
+
* Goals are low-frequency data: reads go straight to the database,
|
|
14
|
+
* no in-memory cache.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { randomUUID } from "node:crypto";
|
|
18
|
+
import * as repo from "./repositories/goals-repo.js";
|
|
19
|
+
|
|
20
|
+
export type GoalStatus = "active" | "paused" | "completed" | "abandoned";
|
|
21
|
+
export type GoalPriority = "low" | "normal" | "high";
|
|
22
|
+
|
|
23
|
+
export type Goal = {
|
|
24
|
+
id: string;
|
|
25
|
+
/** Chat the goal belongs to — progress reports route back here. */
|
|
26
|
+
chatId: string;
|
|
27
|
+
title: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
status: GoalStatus;
|
|
30
|
+
priority: GoalPriority;
|
|
31
|
+
createdAt: number;
|
|
32
|
+
updatedAt: number;
|
|
33
|
+
/** Optional soft deadline (unix ms). */
|
|
34
|
+
dueAt?: number;
|
|
35
|
+
/** Rolling note from the last progress update. */
|
|
36
|
+
lastProgressNote?: string;
|
|
37
|
+
lastProgressAt?: number;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const GOAL_STATUSES: readonly GoalStatus[] = [
|
|
41
|
+
"active",
|
|
42
|
+
"paused",
|
|
43
|
+
"completed",
|
|
44
|
+
"abandoned",
|
|
45
|
+
];
|
|
46
|
+
export const GOAL_PRIORITIES: readonly GoalPriority[] = [
|
|
47
|
+
"low",
|
|
48
|
+
"normal",
|
|
49
|
+
"high",
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
/** Statuses that count as "open" — shown to the heartbeat and listings. */
|
|
53
|
+
export const OPEN_GOAL_STATUSES: readonly GoalStatus[] = ["active", "paused"];
|
|
54
|
+
|
|
55
|
+
export const MAX_OPEN_GOALS_PER_CHAT = 25;
|
|
56
|
+
export const MAX_TITLE_LENGTH = 200;
|
|
57
|
+
export const MAX_DESCRIPTION_LENGTH = 2_000;
|
|
58
|
+
export const MAX_PROGRESS_NOTE_LENGTH = 1_000;
|
|
59
|
+
|
|
60
|
+
// ── Validation ──────────────────────────────────────────────────────────────
|
|
61
|
+
|
|
62
|
+
export function isGoalStatus(value: unknown): value is GoalStatus {
|
|
63
|
+
return GOAL_STATUSES.includes(value as GoalStatus);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function isGoalPriority(value: unknown): value is GoalPriority {
|
|
67
|
+
return GOAL_PRIORITIES.includes(value as GoalPriority);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function validateTitle(title: string): string | null {
|
|
71
|
+
if (!title.trim()) return "Goal title must not be empty";
|
|
72
|
+
if (title.length > MAX_TITLE_LENGTH)
|
|
73
|
+
return `Goal title too long (max ${MAX_TITLE_LENGTH} chars)`;
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function validateDescription(
|
|
78
|
+
description: string | undefined,
|
|
79
|
+
): string | null {
|
|
80
|
+
if (description && description.length > MAX_DESCRIPTION_LENGTH)
|
|
81
|
+
return `Goal description too long (max ${MAX_DESCRIPTION_LENGTH} chars)`;
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function validateProgressNote(note: string | undefined): string | null {
|
|
86
|
+
if (note && note.length > MAX_PROGRESS_NOTE_LENGTH)
|
|
87
|
+
return `Progress note too long (max ${MAX_PROGRESS_NOTE_LENGTH} chars)`;
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ── ID generation ───────────────────────────────────────────────────────────
|
|
92
|
+
|
|
93
|
+
export function generateGoalId(): string {
|
|
94
|
+
return `goal_${randomUUID()}`;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ── CRUD ────────────────────────────────────────────────────────────────────
|
|
98
|
+
|
|
99
|
+
export function addGoal(goal: Goal): void {
|
|
100
|
+
repo.upsert(goal);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function getGoal(id: string): Goal | undefined {
|
|
104
|
+
return repo.get(id);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** All goals for one chat, optionally filtered by status. */
|
|
108
|
+
export function getGoalsForChat(
|
|
109
|
+
chatId: string,
|
|
110
|
+
statuses?: readonly GoalStatus[],
|
|
111
|
+
): Goal[] {
|
|
112
|
+
return repo.listByChat(chatId, statuses);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Open (active + paused) goals across every chat — the heartbeat's view. */
|
|
116
|
+
export function getOpenGoals(): Goal[] {
|
|
117
|
+
return repo.listByStatus(OPEN_GOAL_STATUSES);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function countOpenGoalsForChat(chatId: string): number {
|
|
121
|
+
return repo.countByChatAndStatus(chatId, OPEN_GOAL_STATUSES);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Apply a partial update. `updatedAt` is always bumped; a progress
|
|
126
|
+
* note also stamps `lastProgressAt`. `dueAt: null` clears the
|
|
127
|
+
* deadline (undefined leaves it untouched). Returns the updated
|
|
128
|
+
* goal, or undefined when the id doesn't exist.
|
|
129
|
+
*/
|
|
130
|
+
export function updateGoal(
|
|
131
|
+
id: string,
|
|
132
|
+
updates: Partial<
|
|
133
|
+
Pick<Goal, "title" | "description" | "status" | "priority">
|
|
134
|
+
> & { dueAt?: number | null; progressNote?: string },
|
|
135
|
+
): Goal | undefined {
|
|
136
|
+
const existing = repo.get(id);
|
|
137
|
+
if (!existing) return undefined;
|
|
138
|
+
const now = Date.now();
|
|
139
|
+
const next: Goal = {
|
|
140
|
+
...existing,
|
|
141
|
+
...(updates.title !== undefined ? { title: updates.title } : {}),
|
|
142
|
+
...(updates.description !== undefined
|
|
143
|
+
? { description: updates.description }
|
|
144
|
+
: {}),
|
|
145
|
+
...(updates.status !== undefined ? { status: updates.status } : {}),
|
|
146
|
+
...(updates.priority !== undefined ? { priority: updates.priority } : {}),
|
|
147
|
+
...(updates.dueAt !== undefined
|
|
148
|
+
? { dueAt: updates.dueAt ?? undefined }
|
|
149
|
+
: {}),
|
|
150
|
+
...(updates.progressNote !== undefined
|
|
151
|
+
? { lastProgressNote: updates.progressNote, lastProgressAt: now }
|
|
152
|
+
: {}),
|
|
153
|
+
updatedAt: now,
|
|
154
|
+
};
|
|
155
|
+
repo.upsert(next);
|
|
156
|
+
return next;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function deleteGoal(id: string): boolean {
|
|
160
|
+
return repo.remove(id);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// ── Formatting ──────────────────────────────────────────────────────────────
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Render one goal as a compact multi-line block — shared by the
|
|
167
|
+
* `list_goals` tool output and the heartbeat prompt section so both
|
|
168
|
+
* surfaces describe goals identically.
|
|
169
|
+
*/
|
|
170
|
+
export function formatGoal(
|
|
171
|
+
goal: Goal,
|
|
172
|
+
opts?: { withChatId?: boolean },
|
|
173
|
+
): string {
|
|
174
|
+
const lines = [
|
|
175
|
+
`- ${goal.title} [${goal.status}${goal.priority !== "normal" ? `, ${goal.priority} priority` : ""}]`,
|
|
176
|
+
` ID: ${goal.id}${opts?.withChatId ? ` | Chat: ${goal.chatId}` : ""}`,
|
|
177
|
+
];
|
|
178
|
+
if (goal.description) lines.push(` Detail: ${goal.description}`);
|
|
179
|
+
if (goal.dueAt) lines.push(` Due: ${new Date(goal.dueAt).toISOString()}`);
|
|
180
|
+
lines.push(
|
|
181
|
+
goal.lastProgressNote
|
|
182
|
+
? ` Last progress (${goal.lastProgressAt ? new Date(goal.lastProgressAt).toISOString() : "unknown"}): ${goal.lastProgressNote}`
|
|
183
|
+
: ` Last progress: none recorded yet (created ${new Date(goal.createdAt).toISOString()})`,
|
|
184
|
+
);
|
|
185
|
+
return lines.join("\n");
|
|
186
|
+
}
|