Skip to content

fix(webhooks): unify session-options factory across desktop/telegram/slack#28

Merged
OmGuptaIND merged 1 commit into
mainfrom
OmGuptaIND/unify-session-opts
May 4, 2026
Merged

fix(webhooks): unify session-options factory across desktop/telegram/slack#28
OmGuptaIND merged 1 commit into
mainfrom
OmGuptaIND/unify-session-opts

Conversation

@OmGuptaIND
Copy link
Copy Markdown
Contributor

Summary

Investigation triggered by a Telegram bug where the bot returned https://anton.computer/a/<slug> instead of the deployment's ANTON_HOST (e.g. itsomg.antoncomputer.in). Tracing the divergence revealed that the webhook session-options builder had drifted from AgentServer.buildSessionOptions(...) — and that the underlying createSession opts type silently dropped several fields on every Pi SDK session, desktop included.

This PR closes the drift class, ships a CI guard so it can't recur, and fixes the immediate Telegram URL bug along the way.

What was broken on Telegram/Slack (now fixed)

Field Before After
domain (publish URL) relative /a/<slug> canonical https://<host>/a/<slug>
resolveProviderToken web_search/web_research returned "not configured" wired
onActivateWorkflow tool hidden available
onSharedState, workflowId/Key dropped wired
onDeliverResult dropped wired
agentInstructions/agentMemory dropped on routine runs wired
thinkingLevel binding override ignored applied
liveConnectors "Active Anton Connectors" prompt block missing injected
/model after server restart silently ignored survives cold start (post-resume reconciliation)

What was also broken on desktop Pi SDK sessions (silent latent bug)

createSession's opts type omitted onActivateWorkflow, onSharedState, workflowId/Key, and thinkingLevel. buildSessionOptions returned them, but TypeScript's excess-property check is silent on object variables, so they were silently dropped. The harness path (Codex/Claude Code) worked because it reads from harnessSessionContexts directly — only Pi SDK was affected. This PR fixes the wiring as a side-effect of unifying the type.

Architectural changes (the structural fix)

  1. getPublicHost() helper in @anton/agent-config — 9 process.env.ANTON_HOST reads → 1 greppable consumer.
  2. Unified SessionOptions interface in @anton/agent-corecreateSession and resumeSession now accept the exact same shape; previously-dropped fields wired into ToolCallbacks / Session ctor.
  3. AgentServer.buildSessionOptions declares explicit : SessionOptions return type. Webhook closure delegates straight to it instead of carrying its own (drifty) shape.
  4. AgentServer.buildHarnessSessionContext extracted — harness sessions derive shared wiring (domain, project handlers, resolveProviderToken) from the same factory.
  5. buildCurrentContextLayer in prompt-layers.ts is now the single source of truth for the "Current Context" block. Pi SDK Session.getSystemPrompt() no longer inlines a duplicate. Adding a field there propagates to desktop, Telegram, Slack, and every harness CLI automatically.
  6. check-session-options drift guard — compile-time exhaustiveness via satisfies readonly (keyof SessionOptions)[] + runtime source scan. Adding a SessionOptions field without wiring it through every consumer is now a CI failure.

Side-fixes spotted along the way

  • Webhook sessions no longer wire onSubAgentEvent (the desktop AI-channel handler has no place on Telegram/Slack and risked leaking events into a desktop client sharing the same sessionId).
  • /model choice survives server restart (post-resume reconciliation: if resolved binding override differs from the persisted provider/model, session.switchModel(...) is called).
  • Scheduled-agent harness sessions no longer get recursive activate_workflow (matches the docstring's intent — harness wasn't enforcing it).
  • Scheduled-agent harness sessions correctly receive onDeliverResult (was previously dropped).

File map

File Change
packages/agent-config/src/config.ts getPublicHost()
packages/agent-core/src/index.ts export SessionOptions
packages/agent-core/src/prompt-layers.ts unified buildCurrentContextLayer
packages/agent-core/src/session.ts SessionOptions type, wired fields
packages/agent-server/package.json check:session-options script
packages/agent-server/src/server.ts unified factory, harness-context builder, webhook overrides
packages/agent-server/src/webhooks/agent-runner.ts WebhookSessionOptions = SessionOptions, post-resume reconciliation
(new) packages/agent-server/src/__fixtures__/check-session-options.ts drift guard

8 files, +706 / −196.

Test plan

  • pnpm --filter @anton/agent-core build clean
  • pnpm --filter @anton/agent-server build clean
  • pnpm --filter @anton/agent-core check:harness77/77 cross-surface checks pass
  • pnpm --filter @anton/agent-server check:session-options27/27 drift-guard fields verified
  • Drift guard manually validated: commenting out onActivateWorkflow: opts?.onActivateWorkflow in createSession causes the script to exit non-zero with the exact field name flagged.
  • Smoke-test on a deployment with ANTON_HOST=itsomg.antoncomputer.in: the Telegram bot's publish URL should now point at https://itsomg.antoncomputer.in/a/<slug>, and the model recalling a previously-published artifact from ~/.anton/published/ should reference the same host (not anton.computer).
  • Smoke-test /model openrouter/... on Telegram, restart the server, send another message — should still use the override.
  • Smoke-test web_search and web_research on Telegram (previously returned "not configured").

🤖 Generated with Claude Code

…slack

Telegram/Slack `publish` URLs were resolving to `https://anton.computer/...`
instead of the deployment's `ANTON_HOST` (e.g. `itsomg.antoncomputer.in`).
Root cause was webhook sessions never receiving `domain` — and the deeper
issue that the webhook code path was a separate session-options builder
that had drifted from `AgentServer.buildSessionOptions(...)`. Tracing the
divergence surfaced several silently-dropped fields on every Pi SDK
session (desktop included): `onActivateWorkflow`, `onSharedState`,
`workflowId/Key`, `thinkingLevel`.

Changes:
  - getPublicHost() helper in @anton/agent-config; 9 process.env reads
    collapsed to one greppable consumer.
  - Unified SessionOptions interface in @anton/agent-core, used by both
    createSession and resumeSession; previously-dropped fields wired
    into ToolCallbacks / Session ctor.
  - AgentServer.buildSessionOptions now returns SessionOptions
    explicitly; webhook closure delegates to it instead of carrying its
    own shape.
  - AgentServer.buildHarnessSessionContext extracted; harness
    (Codex/Claude Code) sessions derive shared wiring (domain, project
    handlers, resolveProviderToken) from the same factory.
  - Pi SDK Session.getSystemPrompt now calls buildCurrentContextLayer
    instead of inlining a duplicate; "Public hostname" line surfaced so
    the model never hallucinates a domain when constructing URLs from
    ~/.anton/published/.
  - check-session-options drift guard runs as
    `pnpm --filter @anton/agent-server check:session-options`, with
    compile-time exhaustiveness + runtime source scan over 27 fields.
  - Webhook closure clears onSubAgentEvent (desktop-AI-channel handler
    has no place on Telegram/Slack).
  - getOrCreateSession reconciles resumed sessions with the binding
    /model override so the choice survives a server restart.

Verification:
  - 77/77 cross-surface checks pass (check:harness)
  - 27/27 drift-guard fields verified (check:session-options)
  - @anton/agent-core, @anton/agent-server build clean

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@OmGuptaIND OmGuptaIND merged commit 13044ca into main May 4, 2026
OmGuptaIND added a commit that referenced this pull request May 5, 2026
### Fixes
- docx rendering and fileupload flow
- issues

### Other
- Fix universal upload progress (#31)
- Polish markdown table typography
- Structure file artifacts (#29)
- fix(routines): add missing .conv-back styles so back buttons render inline (#27)
- fix(webhooks): unify session-options factory across desktop/telegram/slack (#28)
- observability: add per-turn telemetry to harness sessions (#26)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant