Connects the inbound SenderID, which was already carried end-to-end via
InboundContext to PromptBuildRequest, into the per-turn user message so
historical messages remember who said what.
- userPromptMessage gains a senderID parameter. Real human IDs are
sanitized via SanitizeMessageName; synthetic triggers (cron,
heartbeat, async:*) are filtered out via IsSystemSenderID so they
do not surface as distinct users.
- pipeline_setup.go now passes ts.opts.Dispatch.SenderID() and uses
AddFullMessage unconditionally. The previous AddMessage(role,
content) shortcut for media-less turns silently dropped the new
Name field, breaking history disambiguation.
- context.go (BuildMessagesFromPrompt) propagates req.SenderID onto
the current-turn user message that goes to the LLM.
After this commit, sessions persist sender attribution and provider
adapters receive it on each user message. Adapters that consume Name
(OpenAI native field, Anthropic-style content prefix) land in
follow-up commits.
The existing "## Current Sender" block in buildDynamicContext is
unchanged; it continues to describe the latest speaker in the system
prompt while Name covers the per-message channel for history.
Refs #2702.
Two more helpers needed for end-to-end multi-user attribution:
- IsSystemSenderID filters synthetic trigger sources (cron, heartbeat,
async:* tool callbacks, system channel) so internal events do not
surface as distinct human users in the conversation. Without this,
cron-triggered messages would carry attribution like cron, producing
a confusing [cron] [System: cron] ... double prefix on adapters that
fall back to in-content rendering.
- ApplyUserNamePrefix renders msg.Name as a [name] prefix on user
content for adapters whose APIs do not support a per-message author
identity (Anthropic, Bedrock, OpenAI Responses). The persisted
message is never mutated; only the wire payload carries the prefix.
Tool result messages and non-user roles pass through unchanged.
These helpers are pure and independently testable; they will be wired
into the agent and provider adapters in subsequent commits.
Refs #2702.
OpenAI's Chat Completions name field requires ^[a-zA-Z0-9_-]{1,64}$.
Real-world sender IDs (Discord alice#1234, numeric Telegram IDs, Slack
U07AB12C3DEF, free-form CLI names) often violate this, so a sanitizer
sits between the raw inbound ID and any wire payload.
Disallowed characters collapse into a single underscore, leading and
trailing underscores are trimmed, and the result is byte-safely
truncated to 64 (output is pure ASCII).
This helper will be wired into the agent pipeline in a later commit.
Refs #2702.
Adds an optional Name field on providers.Message so per-message sender
attribution can be carried through the persistence layer and onto the
wire. The field is JSON-tagged `name,omitempty`, so:
- the OpenAI Chat Completions wire format will be able to emit the
native `name` field that disambiguates participants in multi-user
conversations;
- session stores that round-trip messages via json.Marshal preserve
the field with no extra plumbing;
- existing session files load cleanly with Name = "".
This is the schema-only change. Adapters and the agent pipeline are
updated in subsequent commits.
Refs #2702.
* feat(tools): add cross-platform serial hardware tool
* feat(config): wire serial tool into runtime and dashboard
* hardware/serial: tighten validation and error handling
* hardware/serial: improve unix cancellation and timeout polling
* hardware/serial: improve windows I/O handling
* hardware/serial: fix darwin cross-compilation build
* docs(design): summarize hardware support and serial limits
* build: keep go generate on host during cross builds
* onboard: drop unrelated go generate change from serial work
* style(tools): wrap serial lines for golines
* refactor(pico): unify message kind handling of tool_calls and thought
* fix(pico): add legacy compatibility for thought payload in Send method
Co-authored-by: Copilot <copilot@github.com>
---------
Co-authored-by: Copilot <copilot@github.com>
- pid: When a container stops and leaves behind a PID file with PID 1
on a shared volume, the host's init process (PID 1) passes the
isProcessRunning check, blocking new gateway starts. Treat recorded
PID 1 as always stale in both WritePidFile and ReadPidFileWithCheck.
Added unit tests covering the PID=1 container leftover scenario.
- isolation: Fix govet shadow warning on platform_windows.go line 105
where := shadows the outer err variable. Changed to = assignment.
- gitattributes: Enforce LF line endings for shell scripts to prevent
CRLF issues when checking out on Windows (breaks Docker entrypoint).
Co-authored-by: BeaconCat <BeaconCat@users.noreply.github.com>
The launcher wired UI language changes into a process-global backend
switch that changed auto web-search provider selection and the
reported current service for every handler in the same process.
This narrows the fix to the validated leak: remove backend sync from
frontend locale changes, drop the now-unused UI endpoint, and make
auto selection fall back to a stable default when the query itself
does not contain a script hint.
Constraint: Keep the patch small and mergeable without redesigning per-user preference storage
Rejected: Add per-user backend language state | larger scope than the validated bug and unclear maintainer preference
Rejected: Persist preferred language in config | still shares mutable state across clients of the same instance
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If locale-aware provider routing is reintroduced later, scope it to explicit config or request context instead of package-global state
Tested: go test ./web/backend/api ./pkg/tools -count=1; pnpm lint; pnpm build
Not-tested: Full make check; live multi-browser manual launcher run after the backend endpoint removal
- centralize web search provider readiness and resolution logic
- fall back when the configured provider is unavailable or invalid
- allow native-search-capable models to use built-in search without the client tool
- simplify the tools page and add direct access to web search settings
- add backend, agent, and integration tests for the new selection behavior