Class ActivityContext

java.lang.Object
dyntabs.ai.activity.ActivityContext

public final class ActivityContext extends Object
A reusable, lazily-evaluated description of "the recent activity to feed the assistant" — bind it to a ActivityStore once, say which session/tab and how far back to look, then call render() at each AI call to get fresh prompt text reflecting the latest activity.

What this class is for

This is the piece that makes the assistant context-aware. You attach an ActivityContext to a conversation or assistant builder (via .withActivityContext(...)); each time the AI is invoked, the framework calls render(), which queries the store for the recent slice and runs it through an ActivityRenderer to produce a short briefing. That briefing is injected into the system message, so when the user says "summarise this" the model already knows what "this" is.

Familiar analogy: a standing instruction to your assistant — "before every meeting, hand me a one-page brief of what I've been working on in this project for the last 30 minutes." You set the standing order once (build the context); the brief itself is produced fresh each time, so it is never stale. The ActivityContext is that standing order, not the brief.

Why lazy / re-evaluated

An ActivityContext holds only the recipe (store + filters + renderer), never a captured snapshot. Calling render() twice a minute apart yields two different briefings as the user keeps working. That is deliberate: the same context object can be reused across many turns and always reflects the present.

Defaults

Scope defaults to "everything" until you narrow it: set ActivityContext.Builder.forSession(String) and ActivityContext.Builder.forTab(String) to get the intended per-tab working memory. ActivityContext.Builder.window and ActivityContext.Builder.limit bound how much is shown (20 events by default); the renderer defaults to ActivityRenderer.compactDefault().

See Also:
  • Field Details

    • DEFAULT_LIMIT

      public static final int DEFAULT_LIMIT
      Default cap on how many recent events are rendered into the prompt.
      See Also:
  • Method Details

    • render

      public String render()
      Query the store for the configured slice and render it to prompt text, now.

      Who calls this, and exactly when

      You never call this yourself in normal use. Once an ActivityContext is attached via .withActivityContext(...) on ConversationBuilder or AssistantBuilder, the builder hands it to the underlying LangChain4J AI-service as part of its system-message provider — the small function LangChain4J evaluates afresh on every model call. Concretely:

      • For a Conversation, that is once per Conversation.send(String): just before the user's turn is dispatched to the model, the provider runs, calls render(), and stitches the result onto the base system message for that turn.
      • For an assistant built by AssistantBuilder, that is once per call to any of the assistant's methods — the same provider fires before each invocation.

      Because the provider is evaluated per call rather than captured once at build time, each turn sees a briefing that reflects whatever the user has done up to that exact moment — which is the whole point of rendering lazily rather than snapshotting.

      Returns an empty string when there is no matching activity, which signals the caller (the provider) to inject nothing rather than an empty "recent activity" heading.

      Returns:
      the rendered briefing, or an empty string if there is nothing to show; never null
    • sessionId

      public String sessionId()
      Returns:
      the session this context is scoped to, or null for any.
    • tabId

      public String tabId()
      Returns:
      the tab this context is scoped to, or null for any.
    • of

      public static ActivityContext.Builder of(ActivityStore store)
      Start building a context bound to the given store.
      Parameters:
      store - the activity store to read from; must not be null
      Returns:
      a new ActivityContext.Builder