Skip to content

Feature/post tool text and concurrent threads#94

Open
Gourav-InfoTech wants to merge 6 commits into
YourGPT:betafrom
Gourav-InfoTech:feature/postToolTextAndConcurrentThreads
Open

Feature/post tool text and concurrent threads#94
Gourav-InfoTech wants to merge 6 commits into
YourGPT:betafrom
Gourav-InfoTech:feature/postToolTextAndConcurrentThreads

Conversation

@Gourav-InfoTech
Copy link
Copy Markdown
Contributor

Description

Fixes #

Changes

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Refactoring (no functional changes)

Testing

  • I've tested this locally
  • I've added/updated tests
  • All existing tests pass

Checklist

  • My code follows the project's style guidelines
  • I've updated the documentation (if needed)
  • I've added tests that prove my fix/feature works
  • New and existing tests pass locally

Screenshots (if applicable)

- Introduced a mechanism to handle post-tool text streaming when a message:delta is received without a preceding message:start, allowing for live updates.
- Added a guard to prevent duplicate insertion of assistant messages that follow tool results, ensuring proper message flow.
- Improved debug logging for better traceability of streaming state changes.

This update refines the chat experience by ensuring that tool responses are integrated seamlessly into the conversation flow.
Adds an opt-in mode where multiple threads can stream at the same time.
Users can switch away from a generating thread, start a second one, and
have both run in parallel. Single-thread mode (default) is byte-for-byte
unchanged.

Provider-side:
- Instance registry keyed by thread id behind `concurrentThreads` flag
- `busyThreadIds: ReadonlySet<string>` for per-thread picker spinners
- `assignLocalThreadId(id)` so the hook can bind a locally-minted id to
  the active pending instance mid-stream (for backends that only emit
  the session id in the final `done` chunk)
- `disposeThreadInstance(id)` for clean teardown on thread delete
- Provider-level shared registries (tools, skills, system context) so
  new instances inherit the right state; register/unregister fan out
  to every live instance
- `handleInstanceThreadAssigned` re-keys only when leaving an internal
  slot in multi-thread mode — preserves the stable UI id when a session
  creator isn't in play

Chat/agent-loop:
- `getThreadId?` override on `ChatWithToolsConfig` so the provider can
  surface its registry key (the stable UI id) to tool handlers instead
  of `chat.config.threadId`
- Public `get threadId()` on `AbstractChat`
- Tool context carries `threadId` for per-thread state

Hook (`useInternalThreadManager`):
- In multi-thread mode, dispatches the first-response transition as
  soon as streaming starts so the picker row appears immediately
- Defers when `sessionStatus === "creating"` so `yourgptConfig` /
  `onCreateSession` consumers keep their server `session_uid` as the
  thread id (preserves the pre-multi-thread contract)
- Mints a local id and calls `assignLocalThreadId` when no session
  creator is configured

Backward compatibility:
- `concurrentThreads` defaults to `false`; existing consumers run the
  original single-instance path unchanged
- `handleInstanceThreadAssigned` skip is gated on `concurrentThreads`
  so `renewSession()` in single-thread mode still propagates the new
  server id to `useCopilot().threadId` and the `onThreadChange` prop
- `getThreadId` override is opt-in on config; direct `ChatWithTools`
  consumers without the provider keep the old `() => chat.threadId`
isBusy now respects `concurrentThreads` — when enabled, ThreadPicker
and NewChat stay interactive while the active thread streams, which is
the whole point of the feature. Single-thread behavior unchanged.

Also wire the playground to exercise both `concurrentThreads` and
`yourgptConfig`:

- Switch playground to `workspace:*` so it consumes the local SDK
  (matching every other example in examples/*).
- Add Concurrent Threads toggle and YourGPT Auth section (apiKey +
  widgetUid inputs, stored in localStorage) to the Beta panel.
- Pass `concurrentThreads` + conditional `yourgptConfig` to the
  CopilotProvider; include both in the remount key.
…state

In concurrent-threads mode, a background instance can enter
approval-required while the user is on a different thread. The
existing pendingApprovals (line 1373 area) reflects only the active
instance's toolExecutions, so consumers had no way to see that a
background thread was blocked.

Add a reactive ReadonlyMap<threadId, ToolExecution[]> that scans every
instance in instancesRef, filtering by approvalStatus === "required",
following the existing busyThreadIds pattern. Recomputed from
notifyStateChange, from the eager recompute sites in
handleInstanceThreadAssigned / disposeThreadInstance /
assignLocalThreadId, and — crucially — directly from the per-instance
onToolExecutionsChange and onApprovalRequired callbacks. The reactState
subscribe channel only fires on message changes, so tool-execution
transitions on background instances wouldn't otherwise trigger a
recompute.

Exposed on CopilotContextValue so consumers can read it via
useCopilot(). UI in the downstream extension now lights up an
indicator on the thread picker for threads whose pending executions
aren't already covered by a session grant.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 6, 2026

@Gourav-InfoTech is attempting to deploy a commit to the Delta4 Infotech Team on Vercel.

A member of the Team first needs to authorize it.

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