Skip to content

TensorPM v1.5.0-beta.1 (Beta)

Pre-release
Pre-release

Choose a tag to compare

@Neo552 Neo552 released this 19 May 21:59
· 76 commits to main since this release

Changelog - v1.5.0-beta.1

The first beta after v1.4.0-beta.2. The headline change is TensorPM's
second connector
— Telegram — which graduates the connector framework
from "email-only, hardcoded" to a real multi-connector surface and lets
project participants interact with the in-app TensorPM agent over a chat
they already use every day.

This release also brings a proxy / BYOK Gemini upgrade (Google's
freshly-GA Gemini 3.5 Flash replaces the preview Flash models and becomes
the default), and a tidy-up of how credits are handled in the renderer.

🎉 New Features

Telegram Connector — Chat with Your Project Agent from Telegram

Project participants can now talk to the TensorPM agent from inside
Telegram. The connector is the second full citizen of the connector
framework (alongside Email) — same intake pipeline, same human-in-the-loop
distillation, same per-link tool policies — without needing the desktop
app open in front of you.

What users can do:

  • Set up a bot once per workspace. A new connector type "Telegram" in
    the Wizard takes a Telegram bot token (created via Telegram's
    @BotFather), validates it against https://api.telegram.org/getMe,
    stores it under the existing encrypted credential service, and starts a
    long-poll watcher on the desktop main process.
  • Invite contacts via deep link. Each project (or workspace, for
    shared scope) can mint short, single-use Telegram invite codes with an
    expiry. Sharing the generated https://t.me/<bot>?start=<code> link
    drops the recipient straight into a chat session that's already bound
    to the right project.
  • Self-introduction handshake. On first contact, the bot greets the
    user, asks how they'd like to be addressed (label + role), and stores
    the link in pending. The owner approves or revokes from the
    Telegram panel before anything reaches the project context.
  • Talk to the project agent in natural language. Approved links can
    send text, photos (with or without captions), documents, voice notes,
    and audio. Photos and documents land in the project intake just like
    email attachments.
  • Per-link tool policies. Each approved contact gets a tool allowlist
    configured by the owner. Defaults are conservative — only
    propose_updates (intake) is enabled out of the box, but the owner can
    selectively enable:
    • generateActionItems — create action items
    • updateActionItemFields — status / assignee / dates / effort
    • record_decision — write decisions into the trail
    • updateProjectSections — edit description, goal, scope, dependencies
    • updateTable — requirements, milestones, risks, methods
    • add_person — add people to the project
    • web_search — search the web while answering
  • Slash commands inside Telegram:
    • /new — start a fresh chat without dragging in the prior context
    • /help — re-show the help text
    • /stop — revoke your own link with the bot
  • DE / EN UI for the whole panel: invite list, link approval queue,
    active links, sync status, tool-permission editor.

Architecture (where to look in code):

  • Migration 030-add-telegram-intake adds three new local tables:
    • telegram_invites — pending / redeemed / expired / cancelled invite
      codes, scoped private or workspace
    • telegram_links — approved relationships between a Telegram user
      and a project, with status (pending / approved / revoked) and the
      self-introduction text
    • telegram_messages_local — local message queue with dedupe keys,
      pending / processing / distilled / rejected / ignored
      statuses, and a claim/lease mechanism for the watcher
  • All three tables are excludeFromSync: true — Telegram identifiers
    and message content do not flow to PowerSync. The connector lives
    on the local-first side of the boundary and no cloud sync schema
    change is required
    to ship this release.
  • Services:
    • TelegramConnectorService — long-poll watcher with reconnect
      back-off (5 s base, 5 min cap), bot validation, invite/link CRUD,
      HELP / /new / /stop handling.
    • TelegramChatBridgeService — routes incoming Telegram messages into
      the chat service with the right project/link context, builds
      attachment manifests, owns the prompt envelope.
    • TelegramIPCHandler + telegramSlice / telegramThunks — full
      typed IPC namespace (window.api.telegram.*) plus Redux store
      bindings.
  • Agent prompts: new TelegramAgentPromptGenerator (parallel to the
    Email/Distiller generators) carries link metadata, tool policy, and the
    self-introduction into the system prompt without bleeding it into other
    chats.
  • Intake & tool surface:
    • New ProposeUpdatesExecutor and propose_updates tool type — the
      locked, always-on tool that books raw Telegram messages into
      project_updates for human review through the existing Distiller.
    • ConnectorCredentialService extended to handle bot-token secrets
      alongside IMAP/SMTP passwords.

Security & guardrails:

  • Bot token never leaves the desktop main process. Renderer only sees a
    hasCredentials flag.
  • Long-poll uses allowed_updates: ['message']; no inline-queries, no
    channel posts, no member-update side channels.
  • Invite codes are short-lived, single-use, and bound to either a
    specific project (scope: 'private') or workspace (scope: 'workspace').
  • Per-link tool policies are server-side enforced at the chat service
    layer — toggling a switch in the UI changes which executors the agent
    is even allowed to call for that contact.
  • Messages from pending and revoked links never reach the agent. The
    agent's only response to a non-approved chat is the introduction
    prompt or a hard "you're not currently linked" message.
  • IntakeRepository and IntakeService gained telegram-aware queries
    so the Distiller IntakeIndicator surfaces Telegram messages with the
    right icon, source label, and routing.

Connector Framework: From "Email Only" to Multi-Connector

Telegram is the first real second connector, so the framework itself was
unfrozen.

  • ConnectorType widened from 'email' to 'email' | 'telegram'.
  • ConnectorConfig is now a discriminated union of
    EmailConnectorConfig + TelegramConnectorConfig. Email config keeps
    its existing shape; Telegram config carries bot identity
    (botUsername, botUserId, botFirstName), the credential flag, the
    per-bot tool allowlist, and sync status.
  • ConnectorConfigRepository learned how to round-trip both shapes,
    including the JSON-encoded tool allowlist.
  • The Wizard's ConnectorOverviewPanel and ConnectorList now render
    both types side-by-side, with a dedicated TelegramConnectorPanel
    (962 lines of UI + a 590-line stylesheet) for setup, invite
    generation, link approval, and tool policy.
  • EmailConnectorSetupForm got matching visibility-label/hint copy
    updates so the two connectors feel like siblings, not stepchildren.
  • IntakeIndicator was upgraded with cross-connector grouping so a
    project that's receiving both email and Telegram traffic shows a
    unified pending queue.

The internal contract (ConnectorCredentialService, intake routing,
distillation hand-off) is now general enough that the next connector
(PlanRadar / Capmo / Procore / Slack / Calendar) can be added without
another framework rewrite.

Default Model: Gemini 3.5 Flash (GA)

Google's Gemini 3.5 Flash (GA on 2026-05-19) replaces the
preview-channel Flash models everywhere in the app.

  • BYOK Google users get gemini-3.5-flash as the new default model
    for both the primary and the "small" / utility slot.
  • Proxy backend advertises the same model as the default chat model
    (the Vertex AI proxy backend was already shipping Gemini 3.5 Flash —
    this aligns the BYOK side with proxy reality).
  • gemini-3-flash-preview and gemini-3.1-flash-lite-preview are
    removed from PROVIDER_CONFIGS.google.models and
    MODEL_CAPABILITIES. gemini-3.1-pro-preview stays as the heavy
    option.
  • MODEL_LIMITS updated: gemini-3.5-flash = 1,048,576 input / 65,535
    output tokens. Vision capability flag set on the new model.
  • GeminiProvider now decides whether to attach thinkingConfig based
    on the new model identifier (3.5 Flash has the thinking knob; older
    preview models did not). The proxy provider follows the same logic.
  • ClaudeProvider ships a small refactor along the way to centralise
    thinking-config decisions across providers.

Migration safety net: AppSettingsRepository.getSettings() now
validates each stored preferred_models[provider] against the current
PROVIDER_CONFIGS[provider].models list and falls back to the
provider's default if the stored model is no longer supported. So an
existing user whose preferences were last persisted as
gemini-3-flash-preview gets seamlessly upgraded to
gemini-3.5-flash on next launch — no orphaned setting, no broken
provider call.

Credit Summary Lives in Redux

The proxy credit balance (used by the AI Panel header pill and the
credit budget views) moved from a per-component useProxyCredits hook
that spoke directly to IPC, into a proper Redux slice.

  • New creditsSlice with summary, isLoading, error,
    lastFetchedAt, activeRequestId.
  • New creditsThunks.fetchCreditSummary with request-id de-duping so
    rapid renders don't pile up parallel API calls.
  • New creditsListener middleware: whenever a chat stream finishes
    (chatSlice.streamFinished action), the credit summary refreshes
    automatically — the header pill catches up without users having to
    open Settings.
  • useProxyCredits is now a thin selector over the slice, with login
    gating: if the user isn't authenticated to the proxy, no fetch is
    scheduled. Eliminates the "credit-summary 401 storm on logout" issue
    observed in dev logs.
  • subscriptionThunks triggers a credit refresh after subscription
    state changes so the UI stays consistent post-checkout.

Telegram Messages in Chat UI

When the project ChatPanel surfaces a chat thread that originated from
Telegram, individual messages now render with their Telegram identity:

  • Avatar + display name pulled from the TelegramLink (label,
    telegram_first_name, telegram_username).
  • A small "Telegram" source indicator on the message row.
  • The streaming-message component handles the case where the inbound
    half of the turn is a Telegram message and the outbound half is the
    agent reply, without confusing the alignment / avatar logic.

🏗️ Improvements

Iterative Chat Prompt Generator

The shared iterativeChatPromptGenerator was extended to be
language-aware in the same way baseChatPromptGenerator already was, and
to handle tool-call lists more deterministically. New unit coverage in
iterativeChatPromptGenerator.test.ts (87 lines) locks down both behaviours.

Renderer State Wiring

  • rootReducer now mounts the new credits and telegram slices.
  • chatSlice exposes a streamFinished action that other listeners
    (credits, intake) can subscribe to without poking into chat internals.
  • intakeSlice / intakeThunks learned the telegram source so the
    Distiller indicator badge counts Telegram messages alongside email.

Backend Cleanups Bundled with the Feature

  • ChatRepository got minor query additions for cross-connector chat
    retrieval.
  • IntakeService and chatService were refactored to accept a generic
    external-source descriptor instead of the email-shaped one — required
    by Telegram but useful for any future connector.
  • coreToolModule registers the new propose_updates tool centrally,
    rather than each connector having to wire it up.
  • All five primary AI providers (ChatGPTProvider, ClaudeProvider,
    GeminiProvider, LocalAIProvider, MistralProvider, plus the
    proxy proxyProvider) had a small symmetric tidy of how they
    consume thinking-config / tool-result shape, removing the last
    Gemini-preview-only conditionals.

🐛 Bug Fixes

  • Credit pill spam on logout / startup. useProxyCredits no longer
    fetches before the user is authenticated to the proxy, and the slice
    swallows the inevitable startup 401s instead of surfacing them as a
    toast.
  • Interrupt rendering for Telegram bridged messages. ChatMessage
    correctly suppresses the stop-marker when a Telegram-originated user
    message follows an interrupted assistant message (mirrors the fix
    shipped for normal chat in beta.2).
  • Stale model preferences. Users who had gemini-3-flash-preview
    saved as a preference no longer hit a "model not available" error on
    startup — the AppSettingsRepository validator now silently substitutes
    the new default.
  • ConnectorIndicator label drift. Visibility labels and hints in the
    Email connector setup form were briefly worded inconsistently with the
    Telegram panel; they now share copy.
  • IntakeIndicator pending-queue sort. Pending-queue sort now
    reliably orders mixed-source items (email + Telegram) by received-at,
    with deterministic tiebreaks. New pendingQueueSort.test.ts.

📦 Database & Sync

New Migration: 030-add-telegram-intake

Adds three local-only tables:

Table Purpose
telegram_invites Single-use invite codes (private / workspace scope)
telegram_links Telegram user ↔ project relationships and tool policy
telegram_messages_local Inbound message queue with dedupe + claim/lease state

All three are excludeFromSync: true. Telegram identifiers, message
text, and attachments are local-only by design — they never reach
the PowerSync cloud. The desktop binary is the source of truth for this
connector.

No Cloud Sync Migration Required

Unlike v1.4.0-beta.2 (which needed add-material-items.sql applied to
the sync backend before shipping the desktop release), this release
does not require a TensorPMSync schema change
. The release pipeline
order simplifies:

  1. Ship the desktop binary.
  2. (No sync side-step.)

If a future Telegram-via-cloud-workspace feature is built, the schema
will need to be opened up at that point — but as of 1.5.0-beta.1 the
intent is to keep Telegram identifiers and message contents on-device.

📝 Notes

Bot Setup Prerequisite

Telegram setup requires the user to create a bot via Telegram's official
@BotFather flow and paste the bot token into TensorPM. There is no
TensorPM-owned default bot — every workspace runs its own. This avoids:

  • Centralised token compromise blast radius
  • TensorPM seeing third-party message content
  • Telegram rate-limit cross-talk between unrelated workspaces

The Wizard surface includes a one-click open of the @BotFather
conversation and a short setup checklist in both DE and EN.

Tool Policy Defaults

Out of the box, the only tool a freshly-approved Telegram contact can
trigger is propose_updates — i.e. drop their message into the project
intake queue for the owner to review through the Distiller. Everything
else (action items, decisions, project edits, web search) requires the
owner to explicitly opt that contact in. This matches the "distillation
is always human-in-the-loop" guardrail; a Telegram message is treated
as a raw signal, not as direct authority to mutate the project graph.

MCP / Skills Surface Unchanged

This release does not change the Skill manifest format, the Skill
catalog endpoint, the trust model, the sandbox limits, or the
describe_skill / execute_code tools. It also does not change the
MCP write tools (decisions, action items, project, workspace, billing,
feedback, etc.). External MCP and A2A clients require no migration.

Provider Vision-Loop Scope

Still limited to Anthropic and Gemini wire formats, as in v1.4.0-beta.2.
The newly-default gemini-3.5-flash continues to fully support the
render → inline-image → vision-loop pattern, including via proxy.

Known Follow-Ups

Not blockers for this beta:

  • Voice/audio Telegram messages are received and queued, but the
    out-of-the-box Distiller pipeline still treats them primarily as
    "raw text via caption / transcription stub". Richer voice-note
    handling (Whisper-style transcription) is the next obvious win.
  • The connector framework now has email + Telegram. The next
    abstraction step — pulling the bot watcher loop and the
    ConnectorIndicator routing into a fully type-parameterised base —
    remains open.
  • /new resets conversational context but does not clear pending
    proposed updates from earlier in the thread; those still go through
    normal Distiller review.

📅 Release Info

  • Version: 1.5.0-beta.1
  • Release Date: May 19, 2026
  • Previous Version: 1.4.0-beta.2
  • Type: Beta Minor Release (new Telegram connector, default Gemini
    model bump to GA gemini-3.5-flash, credits-Redux refactor)