Table of Contents

Interface ISupportResponder

Namespace
Tharga.Team
Assembly
Tharga.Team.dll

Answers a support case on behalf of an assistant.

public interface ISupportResponder

Remarks

A port, in the domain's language. It names cases and answers; it knows nothing of models, prompts, tokens or chat completions. That is what keeps the choice of provider — a local model, a self-hosted one, or a hosted API — entirely the host's, and keeps every one of those words out of this package.

It answers; it does not act. An implementation reads to answer well, but closing, assigning and reopening a case stay with people. An assistant that can close its own cases can close the ones it answered badly.

Declining is an answer. A responder that cannot help says so and the case goes to a person, which is an ordinary outcome rather than a failure — so it is a returned value and not an exception.

Methods

AnswerAsync(SupportCase, IReadOnlyList<SupportMessage>, IProgress<SupportAssistantProgress>, CancellationToken)

Answers as AnswerAsync(SupportCase, IReadOnlyList<SupportMessage>, CancellationToken) does, reporting how far it has got while it works: the round, the tools running, and the answer as written so far.

Task<SupportAnswer> AnswerAsync(SupportCase supportCase, IReadOnlyList<SupportMessage> transcript, IProgress<SupportAssistantProgress> progress, CancellationToken cancellationToken = default)

Parameters

supportCase SupportCase
transcript IReadOnlyList<SupportMessage>
progress IProgress<SupportAssistantProgress>
cancellationToken CancellationToken

Returns

Task<SupportAnswer>

Remarks

Each report is the whole state, the text so far included, not what changed, so a reader that misses one still shows the answer as it stands. What is returned is what is kept: a report is a preview, and an answer that is then declined was never given.

A default member answering in one piece and reporting nothing, so a responder written before streaming keeps compiling and answering as it did.

AnswerAsync(SupportCase, IReadOnlyList<SupportMessage>, CancellationToken)

Answers the newest message on a case, or declines to.

Task<SupportAnswer> AnswerAsync(SupportCase supportCase, IReadOnlyList<SupportMessage> transcript, CancellationToken cancellationToken = default)

Parameters

supportCase SupportCase
transcript IReadOnlyList<SupportMessage>
cancellationToken CancellationToken

Returns

Task<SupportAnswer>

Remarks

The case and its transcript are handed in, not fetched. The responder is given exactly what the authorized caller had already read, so it cannot reach further even if it tried — an assistant with a wider view than its user would be a data leak wearing a helpful face. It also keeps the port free of the service that calls it, which would otherwise be a dependency cycle.

GetReadinessAsync(string, CancellationToken)

Whether this responder can answer for a team, and if not, why.

Task<SupportAssistantReadiness> GetReadinessAsync(string teamKey, CancellationToken cancellationToken = default)

Parameters

teamKey string
cancellationToken CancellationToken

Returns

Task<SupportAssistantReadiness>

Remarks

Asked before a case is handed to the assistant and before the assistant is offered, so a team the responder cannot answer for is never offered it. A default member answering Ready, so a responder written before readiness existed keeps compiling and keeps answering for every team, as it did.

Answer Ready or NotConfigured. NotRegistered means there is no responder, so from a responder it reads as ready: it is what a test double returns when it does not run this default.

Throwing reads as NotConfigured, so a case is still raised, for a person, when the responder's settings cannot be read. Log the cause here; the caller cannot.