@yadsh/dsh-qa-surface 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +251 -12
- package/lib/access/service.js +49 -10
- package/lib/access/service.js.map +1 -1
- package/lib/account-remotes.js +41 -0
- package/lib/account-remotes.js.map +1 -1
- package/lib/accounts/database.js +140 -0
- package/lib/accounts/database.js.map +1 -1
- package/lib/accounts/errors.js.map +1 -1
- package/lib/accounts/service-token.js +103 -0
- package/lib/accounts/service-token.js.map +1 -0
- package/lib/accounts/store.js +291 -5
- package/lib/accounts/store.js.map +1 -1
- package/lib/admin/conversation-log.js +14 -8
- package/lib/admin/conversation-log.js.map +1 -1
- package/lib/admin/permissions.js +5 -0
- package/lib/admin/permissions.js.map +1 -1
- package/lib/admin/quality-store.js +4 -0
- package/lib/admin/quality-store.js.map +1 -1
- package/lib/admin/service.js +173 -0
- package/lib/admin/service.js.map +1 -1
- package/lib/admin/session-log.js +39 -8
- package/lib/admin/session-log.js.map +1 -1
- package/lib/attachment-rules.js +39 -6
- package/lib/attachment-rules.js.map +1 -1
- package/lib/cli.js +83 -1
- package/lib/cli.js.map +1 -1
- package/lib/client/QaAccountsController.js +213 -4
- package/lib/client/QaAccountsController.js.map +1 -1
- package/lib/client/QaSessionController.js +37 -21
- package/lib/client/QaSessionController.js.map +1 -1
- package/lib/client/QaSurface.js +28 -4
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/admin/QaAdmin.js +9 -1
- package/lib/client/admin/QaAdmin.js.map +1 -1
- package/lib/client/admin/pages/SkillFiles.js +78 -0
- package/lib/client/admin/pages/SkillFiles.js.map +1 -0
- package/lib/client/admin/pages/Users.js +65 -1
- package/lib/client/admin/pages/Users.js.map +1 -1
- package/lib/client/admin/routes.js +8 -1
- package/lib/client/admin/routes.js.map +1 -1
- package/lib/client/admin/styles.js +2 -0
- package/lib/client/admin/styles.js.map +1 -1
- package/lib/client/attachments.js +41 -11
- package/lib/client/attachments.js.map +1 -1
- package/lib/client/components/QaAuthGate.js +19 -10
- package/lib/client/components/QaAuthGate.js.map +1 -1
- package/lib/client/components/QaChangelog.js +27 -0
- package/lib/client/components/QaChangelog.js.map +1 -1
- package/lib/client/index.js +13 -0
- package/lib/client/index.js.map +1 -1
- package/lib/client/lineage.js +64 -0
- package/lib/client/lineage.js.map +1 -1
- package/lib/client/settings/sections/attachments.js +6 -5
- package/lib/client/settings/sections/attachments.js.map +1 -1
- package/lib/client/settings/sections/notes.js +22 -4
- package/lib/client/settings/sections/notes.js.map +1 -1
- package/lib/client/styles.js +9 -0
- package/lib/client/styles.js.map +1 -1
- package/lib/client/types.js.map +1 -1
- package/lib/client/user-settings/IntegrationTokensPage.js +150 -0
- package/lib/client/user-settings/IntegrationTokensPage.js.map +1 -0
- package/lib/client/user-settings/PasswordSettingsPage.js +48 -0
- package/lib/client/user-settings/PasswordSettingsPage.js.map +1 -0
- package/lib/client/user-settings/SkillCatalog.js +2 -2
- package/lib/client/user-settings/SkillCatalog.js.map +1 -1
- package/lib/client/user-settings/UserSettingsDialog.js +17 -2
- package/lib/client/user-settings/UserSettingsDialog.js.map +1 -1
- package/lib/client/user-settings/copy.js +20 -0
- package/lib/client/user-settings/copy.js.map +1 -1
- package/lib/client.js +2466 -137
- package/lib/client.js.map +1 -1
- package/lib/config-resolvers/attachments.js +6 -5
- package/lib/config-resolvers/attachments.js.map +1 -1
- package/lib/config-resolvers/defaults.js +23 -2
- package/lib/config-resolvers/defaults.js.map +1 -1
- package/lib/config-resolvers/integration.js +94 -0
- package/lib/config-resolvers/integration.js.map +1 -0
- package/lib/config-resolvers/notes.js +2 -0
- package/lib/config-resolvers/notes.js.map +1 -1
- package/lib/config.js +72 -0
- package/lib/config.js.map +1 -1
- package/lib/index.js +197 -2
- package/lib/index.js.map +1 -1
- package/lib/integration/answer.js +100 -0
- package/lib/integration/answer.js.map +1 -0
- package/lib/integration/attachments.js +231 -0
- package/lib/integration/attachments.js.map +1 -0
- package/lib/integration/contract.js +53 -0
- package/lib/integration/contract.js.map +1 -0
- package/lib/integration/host-runner.js +243 -0
- package/lib/integration/host-runner.js.map +1 -0
- package/lib/integration/http.js +538 -0
- package/lib/integration/http.js.map +1 -0
- package/lib/integration/service.js +331 -0
- package/lib/integration/service.js.map +1 -0
- package/lib/integration/transcript-reader.js +202 -0
- package/lib/integration/transcript-reader.js.map +1 -0
- package/lib/integration/transcript.js +148 -0
- package/lib/integration/transcript.js.map +1 -0
- package/lib/personal-skills/index.js +2 -2
- package/lib/personal-skills/index.js.map +1 -1
- package/lib/personal-skills/paths.js +14 -8
- package/lib/personal-skills/paths.js.map +1 -1
- package/lib/personal-skills/provider.js +16 -4
- package/lib/personal-skills/provider.js.map +1 -1
- package/lib/personal-skills/service.js +240 -30
- package/lib/personal-skills/service.js.map +1 -1
- package/lib/prompt-notes.js +58 -0
- package/lib/prompt-notes.js.map +1 -1
- package/lib/provenance/document-preview.js +10 -1
- package/lib/provenance/document-preview.js.map +1 -1
- package/lib/qa-tools/catalog.js +12 -1
- package/lib/qa-tools/catalog.js.map +1 -1
- package/lib/qa-tools/docs-tools.js +563 -0
- package/lib/qa-tools/docs-tools.js.map +1 -0
- package/lib/resolve-config.js +4 -0
- package/lib/resolve-config.js.map +1 -1
- package/lib/secure-session.js +83 -3
- package/lib/secure-session.js.map +1 -1
- package/lib/shared/integration-tokens.js +23 -0
- package/lib/shared/integration-tokens.js.map +1 -0
- package/lib/typert.host.js +1176 -213
- package/lib/typert.remote-client.d.ts +27 -1
- package/lib/typert.remote-client.js +911 -69
- package/lib/types/access/service.d.ts +33 -2
- package/lib/types/account-remotes.d.ts +30 -1
- package/lib/types/accounts/database.d.ts +53 -0
- package/lib/types/accounts/errors.d.ts +5 -1
- package/lib/types/accounts/service-token.d.ts +70 -0
- package/lib/types/accounts/store.d.ts +131 -1
- package/lib/types/admin/conversation-log.d.ts +12 -0
- package/lib/types/admin/service.d.ts +56 -1
- package/lib/types/admin/session-log.d.ts +21 -0
- package/lib/types/attachment-rules.d.ts +26 -3
- package/lib/types/client/QaAccountsController.d.ts +64 -5
- package/lib/types/client/QaSessionController.d.ts +24 -2
- package/lib/types/client/admin/pages/SkillFiles.d.ts +17 -0
- package/lib/types/client/admin/routes.d.ts +2 -0
- package/lib/types/client/attachments.d.ts +21 -4
- package/lib/types/client/lineage.d.ts +42 -0
- package/lib/types/client/settings/sections/notes.d.ts +5 -3
- package/lib/types/client/types.d.ts +71 -1
- package/lib/types/client/user-settings/IntegrationTokensPage.d.ts +21 -0
- package/lib/types/client/user-settings/PasswordSettingsPage.d.ts +19 -0
- package/lib/types/client/user-settings/UserSettingsDialog.d.ts +11 -2
- package/lib/types/client/user-settings/copy.d.ts +10 -1
- package/lib/types/config-resolvers/integration.d.ts +47 -0
- package/lib/types/config.d.ts +10 -0
- package/lib/types/index.d.ts +73 -1
- package/lib/types/integration/answer.d.ts +65 -0
- package/lib/types/integration/attachments.d.ts +85 -0
- package/lib/types/integration/contract.d.ts +196 -0
- package/lib/types/integration/host-runner.d.ts +44 -0
- package/lib/types/integration/http.d.ts +79 -0
- package/lib/types/integration/service.d.ts +120 -0
- package/lib/types/integration/transcript-reader.d.ts +100 -0
- package/lib/types/integration/transcript.d.ts +59 -0
- package/lib/types/personal-skills/index.d.ts +2 -2
- package/lib/types/personal-skills/paths.d.ts +15 -3
- package/lib/types/personal-skills/provider.d.ts +14 -2
- package/lib/types/personal-skills/service.d.ts +89 -14
- package/lib/types/prompt-notes.d.ts +28 -0
- package/lib/types/provenance/document-preview.d.ts +4 -0
- package/lib/types/qa-tools/catalog.d.ts +1 -1
- package/lib/types/qa-tools/docs-tools.d.ts +160 -0
- package/lib/types/secure-session.d.ts +52 -1
- package/lib/types/shared/integration-tokens.d.ts +24 -0
- package/lib/types/types.d.ts +170 -2
- package/package.json +4 -4
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { PluginLogger } from "@yadsh/dsh-plugin-log";
|
|
2
|
+
import type { QaAccounts } from "../accounts/store.js";
|
|
3
|
+
import { type QaServiceTokenScope } from "../accounts/service-token.js";
|
|
4
|
+
import type { QaSourceReference } from "../provenance/types.js";
|
|
5
|
+
import type { ResolvedQaSurfaceConfig } from "../types.js";
|
|
6
|
+
import { type QaAskAnswer, type QaAskRequest, type QaHealth, type QaIntegrationRunner, type QaIntegrationTranscript } from "./contract.js";
|
|
7
|
+
/**
|
|
8
|
+
* The integration API's brain: credential, budget, and one answered turn.
|
|
9
|
+
*
|
|
10
|
+
* The service owns everything that must be identical for every transport —
|
|
11
|
+
* who is allowed to ask, how often, how many at once, what a refusal means and
|
|
12
|
+
* how an answered turn is shaped into the contract. The HTTP layer owns bytes
|
|
13
|
+
* and status codes, the runner owns sessions and agents. That split is what
|
|
14
|
+
* lets the mechanics be tested without a web server, a model or a database.
|
|
15
|
+
*
|
|
16
|
+
* Two limits, deliberately different in kind. Concurrency (`maxConcurrent`)
|
|
17
|
+
* protects the deployment: a bridge that fires a hundred questions must not
|
|
18
|
+
* open a hundred agent turns. Rate (`requestsPerMinute`) protects the account:
|
|
19
|
+
* one token cannot spend the deployment's whole budget. Both refuse with 429,
|
|
20
|
+
* which the bridge already retries.
|
|
21
|
+
*/
|
|
22
|
+
/** The bridge publishes a handful of citations; more is noise in a Jira note. */
|
|
23
|
+
export declare const QA_INTEGRATION_MAX_CITATIONS = 5;
|
|
24
|
+
/**
|
|
25
|
+
* One citation string per source, in the bridge's own style: the document plus
|
|
26
|
+
* where in it the evidence sits, so a reader can open the right page.
|
|
27
|
+
*
|
|
28
|
+
* @param sources - the turn's evidence, best first.
|
|
29
|
+
* @returns bounded citation strings.
|
|
30
|
+
*/
|
|
31
|
+
export declare function sourceCitations(sources: readonly QaSourceReference[]): readonly string[];
|
|
32
|
+
/** Who a presented credential turned out to be. */
|
|
33
|
+
export interface QaIntegrationIdentity {
|
|
34
|
+
readonly tokenId: string;
|
|
35
|
+
readonly userId: string;
|
|
36
|
+
readonly scopes: readonly QaServiceTokenScope[];
|
|
37
|
+
}
|
|
38
|
+
export interface QaIntegrationServiceOptions {
|
|
39
|
+
getConfig(): ResolvedQaSurfaceConfig;
|
|
40
|
+
/** The accounts store, or undefined while accounts are disabled. */
|
|
41
|
+
accounts(): QaAccounts | undefined;
|
|
42
|
+
runner: QaIntegrationRunner;
|
|
43
|
+
logger: PluginLogger;
|
|
44
|
+
/** Package version the health payload reports. */
|
|
45
|
+
version: string;
|
|
46
|
+
now?(): number;
|
|
47
|
+
}
|
|
48
|
+
export declare class QaIntegrationService {
|
|
49
|
+
private readonly deps;
|
|
50
|
+
private readonly now;
|
|
51
|
+
private readonly startedAt;
|
|
52
|
+
/** Recent request timestamps per token id, pruned to the rolling minute. */
|
|
53
|
+
private readonly recent;
|
|
54
|
+
private inFlight;
|
|
55
|
+
constructor(deps: QaIntegrationServiceOptions);
|
|
56
|
+
/** Requests currently inside `ask`; the console shows this as load. */
|
|
57
|
+
get busy(): number;
|
|
58
|
+
/**
|
|
59
|
+
* Resolve a bearer credential to its token, or refuse.
|
|
60
|
+
*
|
|
61
|
+
* A malformed, unknown, expired, revoked or disabled-account token is one
|
|
62
|
+
* answer — 401 — because telling them apart would let an unauthenticated
|
|
63
|
+
* caller enumerate token ids. A valid token missing the scope is 403: the
|
|
64
|
+
* caller proved who it is, and the refusal is about rights, not identity.
|
|
65
|
+
*/
|
|
66
|
+
authenticate(authorization: string | undefined, required: QaServiceTokenScope | null): QaIntegrationIdentity;
|
|
67
|
+
/**
|
|
68
|
+
* Answer one question, or refuse before a turn is ever opened.
|
|
69
|
+
*
|
|
70
|
+
* @param authorization - the raw `Authorization` header value.
|
|
71
|
+
* @param request - the parsed body.
|
|
72
|
+
* @param signal - the request's own lifetime; a dropped connection stops the wait.
|
|
73
|
+
* @returns the answer the bridge publishes.
|
|
74
|
+
*/
|
|
75
|
+
ask(authorization: string | undefined, request: QaAskRequest, signal: AbortSignal): Promise<QaAskAnswer>;
|
|
76
|
+
/**
|
|
77
|
+
* Read one conversation back for the application that started it.
|
|
78
|
+
*
|
|
79
|
+
* This is what `sessions:read` is for. A bridge that escalated a question,
|
|
80
|
+
* or that has to show a specialist what was already said, reads the chat it
|
|
81
|
+
* owns instead of asking the same question again — which would spend a turn
|
|
82
|
+
* and produce a second answer to a question that already has one.
|
|
83
|
+
*
|
|
84
|
+
* The ownership rule is the same one `ask` applies when it continues a chat:
|
|
85
|
+
* the account the token belongs to has to own the conversation. A chat that
|
|
86
|
+
* does not exist and a chat that belongs to somebody else get one answer, so
|
|
87
|
+
* an id alone never confirms that another account's conversation exists.
|
|
88
|
+
*
|
|
89
|
+
* @param authorization - the raw `Authorization` header value.
|
|
90
|
+
* @param query - the chat, the caller's cursor and the page size.
|
|
91
|
+
* @returns the window of messages, with the caller's new cursor.
|
|
92
|
+
*/
|
|
93
|
+
session(authorization: string | undefined, query: {
|
|
94
|
+
readonly chatId: string;
|
|
95
|
+
readonly after: number;
|
|
96
|
+
readonly limit: number;
|
|
97
|
+
}): Promise<QaIntegrationTranscript>;
|
|
98
|
+
/**
|
|
99
|
+
* Liveness and routing facts for the bridge's own UI.
|
|
100
|
+
* @param authorization - the raw `Authorization` header value.
|
|
101
|
+
* @returns the health payload; `ok` is true whenever it is answered at all.
|
|
102
|
+
*/
|
|
103
|
+
health(authorization: string | undefined): Promise<QaHealth>;
|
|
104
|
+
/** One refusal shaped as an answer: empty text, escalated, no citations. */
|
|
105
|
+
private escalated;
|
|
106
|
+
/** Refuse with `rate-limited` once a token spends its minute's budget. */
|
|
107
|
+
private assertRate;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* The credential in one `Authorization` value, or null.
|
|
111
|
+
*
|
|
112
|
+
* `Bearer` is matched case-insensitively, as HTTP authentication schemes are,
|
|
113
|
+
* and the token itself is never trimmed: whitespace inside a credential is
|
|
114
|
+
* part of it, and accepting a padded variant would accept a token the store
|
|
115
|
+
* never minted.
|
|
116
|
+
* @param authorization - the raw header, when the caller sent one.
|
|
117
|
+
* @returns the token, or null.
|
|
118
|
+
*/
|
|
119
|
+
export declare function bearerToken(authorization: string | undefined): string | null;
|
|
120
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { PluginLogger } from "@yadsh/dsh-plugin-log";
|
|
2
|
+
import type { QaSessionLogReader } from "../admin/session-log.js";
|
|
3
|
+
import type { QaIntegrationTranscript } from "./contract.js";
|
|
4
|
+
/**
|
|
5
|
+
* A conversation read warm, for an application that pages through it.
|
|
6
|
+
*
|
|
7
|
+
* The projection itself (`transcript.ts`) answers one page from a log. That is
|
|
8
|
+
* the right shape for a review page opened once and the wrong one for a caller
|
|
9
|
+
* that follows a cursor: every read of a long chat would load the stored log
|
|
10
|
+
* and flatten every message in it to hand back the newest fifty, so a bridge
|
|
11
|
+
* paging through a two-year-old conversation pays for the whole conversation
|
|
12
|
+
* per page, and pays it again on the next poll.
|
|
13
|
+
*
|
|
14
|
+
* What is kept here is the window itself — the newest messages, already
|
|
15
|
+
* flattened — plus the newest seq below it, which is all the arithmetic a page
|
|
16
|
+
* needs to be exact. A page is then either served from that window or, when the
|
|
17
|
+
* window cannot answer for the caller's cursor, read from the log.
|
|
18
|
+
*
|
|
19
|
+
* Two things decide whether the window may be trusted:
|
|
20
|
+
*
|
|
21
|
+
* - **A chat this process holds is probed in memory.** The Harness is the
|
|
22
|
+
* writer, so its in-memory events answer \"has anything been appended?\" with
|
|
23
|
+
* no stored read at all, and only the appended events are projected. This is
|
|
24
|
+
* the common case: the bridge reads back the chat it just asked in.
|
|
25
|
+
* - **A chat this process does not hold is trusted for a bounded time.** Nobody
|
|
26
|
+
* in this process can append to it, so the window can only be wrong about a
|
|
27
|
+
* write from somewhere else sharing the same storage — which no page read can
|
|
28
|
+
* distinguish either. The bound is deliberately the same budget the review
|
|
29
|
+
* console gives its own transcript cache, so the two answer a reviewer the
|
|
30
|
+
* same way.
|
|
31
|
+
*
|
|
32
|
+
* A window is never *replaced* by an in-memory snapshot, only extended from it:
|
|
33
|
+
* a session that outlived a process restart, or a very long one, may hold only
|
|
34
|
+
* part of its history in memory, and a read that trusted it as the whole log
|
|
35
|
+
* would answer a page from half a conversation.
|
|
36
|
+
*
|
|
37
|
+
* What it costs: at most one window per conversation, and a window is at most
|
|
38
|
+
* one maximal page — so the memory this keeps is bounded by
|
|
39
|
+
* {@link QA_INTEGRATION_TRANSCRIPT_CACHE_CHATS} pages of conversation, and a
|
|
40
|
+
* page a caller would have received anyway. An old chat's *first* read is still
|
|
41
|
+
* a stored read, and its projection walks back only as far as the window it is
|
|
42
|
+
* building: the whole log of a long conversation is never flattened to answer a
|
|
43
|
+
* page of it.
|
|
44
|
+
*/
|
|
45
|
+
/** How long a window is trusted for a chat this process does not hold. */
|
|
46
|
+
export declare const QA_INTEGRATION_TRANSCRIPT_TTL_MS = 30000;
|
|
47
|
+
/** How many conversations keep a warm window. */
|
|
48
|
+
export declare const QA_INTEGRATION_TRANSCRIPT_CACHE_CHATS = 128;
|
|
49
|
+
export interface QaIntegrationTranscriptReaderOptions {
|
|
50
|
+
/** The deployment's conversations, as the Host reads them. */
|
|
51
|
+
log: QaSessionLogReader;
|
|
52
|
+
logger?: PluginLogger;
|
|
53
|
+
/** Injectable clock, so the trust window is testable without waiting. */
|
|
54
|
+
now?: () => number;
|
|
55
|
+
ttlMs?: number;
|
|
56
|
+
maxChats?: number;
|
|
57
|
+
/** Ceiling on the messages a window holds; one maximal page by default. */
|
|
58
|
+
maxMessages?: number;
|
|
59
|
+
}
|
|
60
|
+
export declare class QaIntegrationTranscriptReader {
|
|
61
|
+
private readonly windows;
|
|
62
|
+
private readonly log;
|
|
63
|
+
private readonly logger;
|
|
64
|
+
private readonly now;
|
|
65
|
+
private readonly ttlMs;
|
|
66
|
+
private readonly maxChats;
|
|
67
|
+
private readonly maxMessages;
|
|
68
|
+
constructor(options: QaIntegrationTranscriptReaderOptions);
|
|
69
|
+
/**
|
|
70
|
+
* One page of a conversation, from the window when the window can answer it.
|
|
71
|
+
* @param chatId - the conversation; the caller's ownership of it is the
|
|
72
|
+
* service's business, and this reader only reads it.
|
|
73
|
+
* @param query - the caller's exclusive cursor and the page size it wants.
|
|
74
|
+
* @returns the newest page after the cursor, with its new cursor.
|
|
75
|
+
*/
|
|
76
|
+
page(chatId: string, query: {
|
|
77
|
+
readonly after: number;
|
|
78
|
+
readonly limit: number;
|
|
79
|
+
}): Promise<QaIntegrationTranscript>;
|
|
80
|
+
/** One page out of a window: exact, whatever the caller's cursor is. */
|
|
81
|
+
private pageOf;
|
|
82
|
+
/**
|
|
83
|
+
* Fold what the Harness is holding into a window, projecting only the events
|
|
84
|
+
* the window has not covered yet.
|
|
85
|
+
* @returns whether the window absorbed the update; false means the delta is
|
|
86
|
+
* larger than a whole window, so the log has to answer instead.
|
|
87
|
+
*/
|
|
88
|
+
private merge;
|
|
89
|
+
/**
|
|
90
|
+
* The newest published seq a window has covered, which is also the cursor a
|
|
91
|
+
* probe is asked from: `undefined` while the window holds nothing, where the
|
|
92
|
+
* question is "what has this chat published at all".
|
|
93
|
+
*/
|
|
94
|
+
private covered;
|
|
95
|
+
/** Read the log and remember what it says, for the pages that follow. */
|
|
96
|
+
private readLog;
|
|
97
|
+
/** Keep a bounded number of conversations warm, oldest window first. */
|
|
98
|
+
private remember;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=transcript-reader.d.ts.map
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { StoredSessionEvent } from "../admin/conversation-log.js";
|
|
2
|
+
import type { QaIntegrationMessage, QaIntegrationTranscript } from "./contract.js";
|
|
3
|
+
/**
|
|
4
|
+
* Reading a conversation back out of its durable log, for the application that
|
|
5
|
+
* started it.
|
|
6
|
+
*
|
|
7
|
+
* This is deliberately not the admin viewer's projection. That one answers a
|
|
8
|
+
* reviewer and carries what a review needs — tool calls, ratings, the redaction
|
|
9
|
+
* policy — none of which an external caller may see or has any use for. What
|
|
10
|
+
* this projector shares with the rest of the API is the flattening rule
|
|
11
|
+
* (`messageContentText`): the text a caller reads here is the same text it
|
|
12
|
+
* would have received as an answer, so the two never disagree about what a
|
|
13
|
+
* message says.
|
|
14
|
+
*
|
|
15
|
+
* Only human prompts and assistant messages are published. Injected context —
|
|
16
|
+
* identity notes, skill payloads, a slash command's expanded body — is model
|
|
17
|
+
* input recorded as a user message, and handing it back would show the caller
|
|
18
|
+
* instructions it never wrote. Tool traffic is model plumbing: the answer is
|
|
19
|
+
* already the result of it.
|
|
20
|
+
*/
|
|
21
|
+
/** Newest messages one read returns; more than a page is a different tool. */
|
|
22
|
+
export declare const QA_INTEGRATION_MAX_TRANSCRIPT_MESSAGES = 200;
|
|
23
|
+
/**
|
|
24
|
+
* The newest published messages of a log, and what was left below them.
|
|
25
|
+
*
|
|
26
|
+
* This is the primitive both readers are built on, and it walks the events
|
|
27
|
+
* **newest first**: a page of a hundred-message conversation costs a hundred
|
|
28
|
+
* messages flattened, not the whole log, which is what makes a long chat's
|
|
29
|
+
* page cheap. Only the events below the cursor are considered, and the walk
|
|
30
|
+
* stops as soon as the window is full — the one message after that is enough
|
|
31
|
+
* to know that more exists, and `below` records its seq.
|
|
32
|
+
*
|
|
33
|
+
* @param chatId - the conversation being read; echoed back for correlation.
|
|
34
|
+
* @param events - the log's events, in any order.
|
|
35
|
+
* @param query - the cursor (exclusive) and how many messages to cover; the
|
|
36
|
+
* cursor is `undefined` for "from the end", which a warm window asks for.
|
|
37
|
+
* @returns the window, oldest first, and the newest seq left below it.
|
|
38
|
+
*/
|
|
39
|
+
export declare function integrationMessageWindow(chatId: string, events: readonly StoredSessionEvent[], query: {
|
|
40
|
+
readonly after: number | undefined;
|
|
41
|
+
readonly cover: number;
|
|
42
|
+
}): {
|
|
43
|
+
readonly chatId: string;
|
|
44
|
+
readonly messages: readonly QaIntegrationMessage[];
|
|
45
|
+
readonly below: number | undefined;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Project the log into one page of a caller's transcript.
|
|
49
|
+
*
|
|
50
|
+
* @param chatId - the conversation being read; echoed back for correlation.
|
|
51
|
+
* @param events - durable events, in any order.
|
|
52
|
+
* @param query - the caller's cursor and page size; both are already bounded.
|
|
53
|
+
* @returns the window with the caller's new cursor.
|
|
54
|
+
*/
|
|
55
|
+
export declare function projectIntegrationTranscript(chatId: string, events: readonly StoredSessionEvent[], query: {
|
|
56
|
+
readonly after: number;
|
|
57
|
+
readonly limit: number;
|
|
58
|
+
}): QaIntegrationTranscript;
|
|
59
|
+
//# sourceMappingURL=transcript.d.ts.map
|
|
@@ -2,8 +2,8 @@ export { QaPersonalSkillError, type QaPersonalSkillErrorReason, } from "./errors
|
|
|
2
2
|
export { QA_SKILL_TRASH_SUFFIX, resolveSkillRoots, skillDirectory, skillFilePath, type QaSkillRoots, } from "./paths.js";
|
|
3
3
|
export { normalizeAllowedTools, parseSkillFile, serializeSkillFile, skillFileBody, skillNameProblem, toJsonValue, type QaSkillFileContents, type QaSkillFileDraft, type QaSkillFileParse, } from "./skill-file.js";
|
|
4
4
|
export { skillFileBytes, skillRelativeRootProblem, skillRelativeRootSegments, validateSkillDraft, QA_SKILL_DEFAULT_RELATIVE_ROOT, QA_SKILL_DESCRIPTION_MAX, QA_SKILL_ENABLED_BY_DEFAULT, QA_SKILL_FILE_MAX_BYTES, QA_SKILL_MAX_BYTES_MAX, QA_SKILL_MAX_BYTES_MIN, QA_SKILL_MAX_TOOLS, QA_SKILL_NAME_MAX, QA_SKILL_NAME_PATTERN, QA_SKILL_WHEN_TO_USE_MAX, type QaSkillValidationInput, } from "./skill-format.js";
|
|
5
|
-
export { QA_USER_SKILLS_PROVIDER, QA_USER_SKILLS_RANK, QA_USER_SKILLS_SOURCE, createQaUserSkillProvider, } from "./provider.js";
|
|
6
|
-
export { QaPersonalSkills, type QaPersonalSkillContext, type QaPersonalSkillsOptions, type QaStoredSkill, } from "./service.js";
|
|
5
|
+
export { QA_SHARED_SKILLS_RANK, QA_SHARED_SKILLS_SOURCE, QA_USER_SKILLS_PROVIDER, QA_USER_SKILLS_RANK, QA_USER_SKILLS_SOURCE, createQaUserSkillProvider, } from "./provider.js";
|
|
6
|
+
export { QA_SKILL_ADMIN_EDITS_FILE, QaPersonalSkills, type QaPersonalSkillContext, type QaPersonalSkillsOptions, type QaSharedSkillContext, type QaSkillScope, type QaSkillWriteOrigin, type QaStoredSkill, } from "./service.js";
|
|
7
7
|
export { createQaPersonalSkillRemotes, type QaPersonalSkillRemotes, } from "./remotes.js";
|
|
8
8
|
export { QaPersonalSkillsHost } from "./host.js";
|
|
9
9
|
export { QaSkillWatcher } from "./watcher.js";
|
|
@@ -20,11 +20,23 @@ export interface QaSkillRoots {
|
|
|
20
20
|
readonly skills: string;
|
|
21
21
|
/** The canonical directory a removed skill directory is moved into. */
|
|
22
22
|
readonly trash: string;
|
|
23
|
+
/**
|
|
24
|
+
* Whether these roots are the deployment-wide store rather than one
|
|
25
|
+
* account's. The geometry is identical, so the flag travels with the roots
|
|
26
|
+
* instead of being re-derived from them at every use.
|
|
27
|
+
*/
|
|
28
|
+
readonly shared: boolean;
|
|
23
29
|
}
|
|
24
30
|
/** Derive and verify every directory the feature touches for one account. */
|
|
25
|
-
export declare function resolveSkillRoots(personalRoot: string, relativeRoot: string
|
|
26
|
-
/**
|
|
27
|
-
|
|
31
|
+
export declare function resolveSkillRoots(personalRoot: string, relativeRoot: string,
|
|
32
|
+
/**
|
|
33
|
+
* What the boundary refuses to leave, for the message an operator reads.
|
|
34
|
+
* The same resolution serves an account directory and the deployment-wide
|
|
35
|
+
* shared root, which have different owners but identical geometry.
|
|
36
|
+
*/
|
|
37
|
+
boundary?: string): QaSkillRoots;
|
|
38
|
+
/** The directory of one skill, validated against the scope's skills root. */
|
|
39
|
+
export declare function skillDirectory(roots: QaSkillRoots, name: string, boundary?: string): string;
|
|
28
40
|
export declare function skillFilePath(roots: QaSkillRoots, name: string): string;
|
|
29
41
|
/** Whether the directory exists at all, without following a symlink. */
|
|
30
42
|
export declare function directoryExists(input: string): boolean;
|
|
@@ -7,8 +7,11 @@ import type { QaPersonalSkills } from "./service.js";
|
|
|
7
7
|
* through the nearest `.git`, which for a personal QA directory inside a larger
|
|
8
8
|
* checkout would climb above the account and mix users together. This provider
|
|
9
9
|
* reads exactly one place — `<cwd>/.dsh/skills` where the cwd is a provisioned
|
|
10
|
-
* `.qa-users/<uuid>` directory — and
|
|
11
|
-
*
|
|
10
|
+
* `.qa-users/<uuid>` directory — and the deployment's shared root beside the
|
|
11
|
+
* registered workspace, replacing the filesystem layer inside the QA scope
|
|
12
|
+
* rather than adding a second one beside it. A shared skill is labelled and
|
|
13
|
+
* ranked distinctly, so a load can tell the deployment's own instructions from
|
|
14
|
+
* the account's.
|
|
12
15
|
*/
|
|
13
16
|
export declare const QA_USER_SKILLS_PROVIDER = "qa-user-skills";
|
|
14
17
|
/** Prompt-visible provenance label for a skill stored in an account directory. */
|
|
@@ -18,6 +21,15 @@ export declare const QA_USER_SKILLS_SOURCE = "qa-user";
|
|
|
18
21
|
* QA scope a personal skill wins a same-named duplicate from any other layer.
|
|
19
22
|
*/
|
|
20
23
|
export declare const QA_USER_SKILLS_RANK = 50;
|
|
24
|
+
/** Prompt-visible provenance label for a deployment-wide shared skill. */
|
|
25
|
+
export declare const QA_SHARED_SKILLS_SOURCE = "qa-shared";
|
|
26
|
+
/**
|
|
27
|
+
* Rank between the personal layer (50) and the project layer (100). A shared
|
|
28
|
+
* skill is curated for the whole deployment, so it outranks what a checkout
|
|
29
|
+
* happens to carry — but one account's own copy of the same name still wins,
|
|
30
|
+
* because that is the layer a person deliberately edited about themselves.
|
|
31
|
+
*/
|
|
32
|
+
export declare const QA_SHARED_SKILLS_RANK = 60;
|
|
21
33
|
/**
|
|
22
34
|
* Build the provider for one registration. The factory runs synchronously
|
|
23
35
|
* during `registerProvider` and all filesystem work stays inside
|
|
@@ -2,15 +2,48 @@ import type { Context } from "@deepseek-ai/cordis";
|
|
|
2
2
|
import type { PluginLogger } from "@yadsh/dsh-plugin-log";
|
|
3
3
|
import type { QaSkillDiagnostic, QaSkillDocument, QaSkillDraftInput, QaSkillRemoval, QaSkillSummary, QaSkillToolDescriptor, QaSkillValidation, ResolvedQaSurfaceConfig } from "../types.js";
|
|
4
4
|
import { type QaSkillFileContents } from "./skill-file.js";
|
|
5
|
+
/**
|
|
6
|
+
* Name of the sidecar that records which skills an administrator wrote. It
|
|
7
|
+
* sits beside the skill directories, and everything that enumerates skills
|
|
8
|
+
* ignores dot entries — so the record never becomes a skill and never reaches
|
|
9
|
+
* the model.
|
|
10
|
+
*/
|
|
11
|
+
export declare const QA_SKILL_ADMIN_EDITS_FILE = ".admin-edits.json";
|
|
5
12
|
/** Per-account identity of the skill storage boundary. */
|
|
6
13
|
export interface QaPersonalSkillContext {
|
|
7
14
|
/** The authenticated account id whose personal root holds these skills. */
|
|
8
15
|
readonly userId: string;
|
|
9
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* The deployment-wide store: skills every account may read, which only an
|
|
19
|
+
* administrator writes. It is resolved against the registered workspace (the
|
|
20
|
+
* same relative root, a different owner), so the two scopes have identical
|
|
21
|
+
* geometry and identical path checks.
|
|
22
|
+
*/
|
|
23
|
+
export interface QaSharedSkillContext {
|
|
24
|
+
readonly shared: true;
|
|
25
|
+
}
|
|
26
|
+
/** Which store a call reads or writes. */
|
|
27
|
+
export type QaSkillScope = QaPersonalSkillContext | QaSharedSkillContext;
|
|
28
|
+
/**
|
|
29
|
+
* What a save must record about itself beyond the draft.
|
|
30
|
+
*
|
|
31
|
+
* `actorId` is the administrator behind an administrator's write. An owner's
|
|
32
|
+
* own save passes nothing, which clears whatever mark the skill carried: the
|
|
33
|
+
* stored revision is theirs again, and the badge is a statement about the
|
|
34
|
+
* bytes on disk rather than a history nobody can act on. Removal takes no
|
|
35
|
+
* origin because a removed skill has no bytes left to mark — the audit row the
|
|
36
|
+
* console writes is where that actor is named.
|
|
37
|
+
*/
|
|
38
|
+
export interface QaSkillWriteOrigin {
|
|
39
|
+
readonly actorId?: string;
|
|
40
|
+
}
|
|
10
41
|
/** One stored skill: its parsed contents plus the facts a DTO needs. */
|
|
11
42
|
export interface QaStoredSkill {
|
|
12
43
|
/** Whether the skill directory itself exists. */
|
|
13
44
|
readonly exists: boolean;
|
|
45
|
+
/** Whether the skill came from the deployment-wide store. */
|
|
46
|
+
readonly shared: boolean;
|
|
14
47
|
/** Directory name; the skill's identity for every write. */
|
|
15
48
|
readonly directoryName: string;
|
|
16
49
|
readonly directory: string;
|
|
@@ -34,9 +67,9 @@ export interface QaPersonalSkillsOptions {
|
|
|
34
67
|
readonly onRootDiscovered?: (root: string) => void;
|
|
35
68
|
}
|
|
36
69
|
/**
|
|
37
|
-
*
|
|
70
|
+
* Skills over one directory: an account's own, or the deployment's shared one.
|
|
38
71
|
*
|
|
39
|
-
* The service is the only writer: it derives every path from the
|
|
72
|
+
* The service is the only writer: it derives every path from the scope,
|
|
40
73
|
* validates a draft before touching the disk, writes `SKILL.md` through a
|
|
41
74
|
* temporary file and a rename, and keeps a removed skill recoverable in the
|
|
42
75
|
* trash beside its skills root. Reading is deliberately permissive — a skill
|
|
@@ -49,8 +82,19 @@ export declare class QaPersonalSkills {
|
|
|
49
82
|
constructor(ctx: Context, options: QaPersonalSkillsOptions);
|
|
50
83
|
/** Whether the feature is available on this deployment at all. */
|
|
51
84
|
get enabled(): boolean;
|
|
52
|
-
/** Resolve one
|
|
85
|
+
/** Resolve one scope's storage roots, or refuse the operation. */
|
|
53
86
|
private rootsFor;
|
|
87
|
+
/** The deployment's own skills root, below the registered workspace. */
|
|
88
|
+
private sharedRoots;
|
|
89
|
+
private requireEnabled;
|
|
90
|
+
/** The registered workspace every scope is resolved against, or a refusal. */
|
|
91
|
+
private requireWorkspacePath;
|
|
92
|
+
/**
|
|
93
|
+
* The absolute directory a scope reads and writes. The console names it so
|
|
94
|
+
* an operator can open the same path in a file manager; nothing in the wire
|
|
95
|
+
* contract can name a path the service did not derive itself.
|
|
96
|
+
*/
|
|
97
|
+
rootPath(scope: QaSkillScope): string;
|
|
54
98
|
/**
|
|
55
99
|
* Resolve the storage roots a session cwd names. This is the discovery
|
|
56
100
|
* provider's entry point and takes no account token: the cwd itself is the
|
|
@@ -58,10 +102,10 @@ export declare class QaPersonalSkills {
|
|
|
58
102
|
* directory, so no arbitrary directory can name another account's storage.
|
|
59
103
|
*/
|
|
60
104
|
private rootsForCwd;
|
|
61
|
-
/** Every skill of one
|
|
62
|
-
list(context:
|
|
105
|
+
/** Every skill of one scope, sorted by directory name. */
|
|
106
|
+
list(context: QaSkillScope): readonly QaSkillSummary[];
|
|
63
107
|
/** One skill with everything the editor needs. */
|
|
64
|
-
get(context:
|
|
108
|
+
get(context: QaSkillScope, name: string): QaSkillDocument;
|
|
65
109
|
/**
|
|
66
110
|
* Check one unsaved draft without touching storage: the serializer is the
|
|
67
111
|
* one a Save uses and the preserved frontmatter is the stored file's, so the
|
|
@@ -69,25 +113,25 @@ export declare class QaPersonalSkills {
|
|
|
69
113
|
* and the diagnostics carry the operator's own limit (which the browser
|
|
70
114
|
* cannot know). `name` is the stored skill being edited, or null to create.
|
|
71
115
|
*/
|
|
72
|
-
validate(context:
|
|
73
|
-
/** Whether one
|
|
74
|
-
has(context:
|
|
116
|
+
validate(context: QaSkillScope, name: string | null, input: QaSkillDraftInput): QaSkillValidation;
|
|
117
|
+
/** Whether one scope stores a skill under this name. */
|
|
118
|
+
has(context: QaSkillScope, name: string): boolean;
|
|
75
119
|
/** Create one skill directory and its `SKILL.md`. */
|
|
76
|
-
create(context:
|
|
120
|
+
create(context: QaSkillScope, input: QaSkillDraftInput, origin?: QaSkillWriteOrigin): QaSkillDocument;
|
|
77
121
|
/**
|
|
78
122
|
* Replace one skill's file, preserving the frontmatter fields this editor
|
|
79
123
|
* does not own and moving the whole directory when the name changed.
|
|
80
124
|
*/
|
|
81
|
-
update(context:
|
|
125
|
+
update(context: QaSkillScope, name: string, input: QaSkillDraftInput, origin?: QaSkillWriteOrigin): QaSkillDocument;
|
|
82
126
|
/** Move one skill directory into the trash beside its skills root. */
|
|
83
|
-
remove(context:
|
|
127
|
+
remove(context: QaSkillScope, name: string, expectedRevision: string | null): QaSkillRemoval;
|
|
84
128
|
/**
|
|
85
129
|
* The tool catalog the picker offers. Availability is the QA session's own
|
|
86
130
|
* scope — the deployment's reviewed allow-list — never a suggestion of what
|
|
87
131
|
* a skill may grant: a declared tool the scope excludes stays listed and
|
|
88
132
|
* stays unavailable.
|
|
89
133
|
*/
|
|
90
|
-
tools(context:
|
|
134
|
+
tools(context: QaSkillScope): readonly QaSkillToolDescriptor[];
|
|
91
135
|
/**
|
|
92
136
|
* The skills one session cwd exposes to DSH. A file the parser rejects, or
|
|
93
137
|
* one whose name disagrees with its directory, is reported in the editor and
|
|
@@ -99,8 +143,18 @@ export declare class QaPersonalSkills {
|
|
|
99
143
|
* from every session — not just this account's skills.
|
|
100
144
|
*/
|
|
101
145
|
discover(cwd: string): readonly QaStoredSkill[];
|
|
146
|
+
/** One roots pair's discoverable skills; never throws. */
|
|
147
|
+
private discoverIn;
|
|
148
|
+
/**
|
|
149
|
+
* The deployment's shared root for one cwd-scoped read, or undefined. It
|
|
150
|
+
* answers undefined when shared skills cannot be resolved at all, and when
|
|
151
|
+
* the shared root is the root the personal read already covered — a session
|
|
152
|
+
* pinned to the workspace root would otherwise list everything twice.
|
|
153
|
+
*/
|
|
154
|
+
private sharedRootsForDiscovery;
|
|
102
155
|
/** Re-read one skill of a session cwd, re-checking the same boundary. */
|
|
103
156
|
read(cwd: string, directoryName: string): QaStoredSkill | undefined;
|
|
157
|
+
private readFrom;
|
|
104
158
|
private observe;
|
|
105
159
|
private isDiscoverable;
|
|
106
160
|
private availableTools;
|
|
@@ -120,7 +174,7 @@ export declare class QaPersonalSkills {
|
|
|
120
174
|
/** Move a renamed skill's whole directory, resources included. */
|
|
121
175
|
private renameSkillDirectory;
|
|
122
176
|
/** Write one file through a temporary sibling and a rename. */
|
|
123
|
-
private
|
|
177
|
+
private writeAtomic;
|
|
124
178
|
private trashTarget;
|
|
125
179
|
private assertRevision;
|
|
126
180
|
private summarize;
|
|
@@ -132,5 +186,26 @@ export declare class QaPersonalSkills {
|
|
|
132
186
|
* is still stored, and the deployment needs to see which half broke.
|
|
133
187
|
*/
|
|
134
188
|
private refreshCatalog;
|
|
189
|
+
/**
|
|
190
|
+
* The administrator marks stored beside one skills root.
|
|
191
|
+
*
|
|
192
|
+
* The sidecar is advisory: a mark that cannot be read or written never fails
|
|
193
|
+
* a save, because losing a badge is a smaller failure than losing an edit.
|
|
194
|
+
* Each mark names the revision it describes, so a mark whose content has
|
|
195
|
+
* since changed reports as absent rather than as a claim about the present.
|
|
196
|
+
*/
|
|
197
|
+
private adminEdits;
|
|
198
|
+
/** The mark to report for one stored skill: absent unless it still matches. */
|
|
199
|
+
private adminEditOf;
|
|
200
|
+
/**
|
|
201
|
+
* Record one administrator write, or clear the mark when the owner wrote.
|
|
202
|
+
* `previousName` is the directory the skill had before the write, so a
|
|
203
|
+
* rename by an administrator moves the mark with the skill instead of
|
|
204
|
+
* leaving one behind for a name nothing answers to any more.
|
|
205
|
+
*/
|
|
206
|
+
private rememberWrite;
|
|
207
|
+
/** Drop the mark of a skill that no longer exists. */
|
|
208
|
+
private forgetWrite;
|
|
209
|
+
private writeAdminEdits;
|
|
135
210
|
}
|
|
136
211
|
//# sourceMappingURL=service.d.ts.map
|
|
@@ -14,6 +14,10 @@ export declare const QA_IDENTITY_NOTE = "dsh-qa-surface:user-identity";
|
|
|
14
14
|
export declare const QA_SOURCES_NOTE = "dsh-qa-surface:structured-sources";
|
|
15
15
|
/** Note name asking the model to name its delegations. */
|
|
16
16
|
export declare const QA_DELEGATION_NOTE = "dsh-qa-surface:delegation-naming";
|
|
17
|
+
/** Note name routing an attached office document to the document pipeline. */
|
|
18
|
+
export declare const QA_DOCUMENTS_NOTE = "dsh-qa-surface:attached-documents";
|
|
19
|
+
/** Note name carrying the deployment's rule about where an answer comes from. */
|
|
20
|
+
export declare const QA_SOURCE_PRIORITY_NOTE = "dsh-qa-surface:source-priority";
|
|
17
21
|
/**
|
|
18
22
|
* Built-in note texts. Each is the fallback for its settings template
|
|
19
23
|
* (`notes.*.template`); the placeholders mark the parts the injector
|
|
@@ -23,6 +27,8 @@ export declare const QA_IDENTITY_NOTE_TEMPLATE = "{identity}\n\n{instructions}";
|
|
|
23
27
|
export declare const QA_SOURCES_NOTE_TEMPLATE = "Source provenance is collected automatically from your tool calls; the QA surface lists what it collected beside the answer. Do not append a manual Sources/\u0418\u0441\u0442\u043E\u0447\u043D\u0438\u043A\u0438 bibliography of your own.";
|
|
24
28
|
export declare const QA_SOURCES_FALLBACK_TEMPLATE = "A delegated run whose provider cannot expose tool events must call {reportTool} before finishing.";
|
|
25
29
|
export declare const QA_DELEGATION_NOTE_TEMPLATE = "When you start a background subagent, give the delegation a short vivid name in its description field: two or three words in the user's language that say what the run is for (\u00AB\u0421\u0432\u0435\u0440\u043A\u0430 \u043E\u0442\u0447\u0451\u0442\u043E\u0432\u00BB, \"Log triage\"). The QA surface shows that description as the subagent's display name in the operator's panel and completion notices.";
|
|
30
|
+
export declare const QA_DOCUMENTS_NOTE_TEMPLATE = "A document a chat user attached is a path on disk, not text: read it with the deployment's document pipeline \u2014 `document_inspect` says what a DOCX or PDF is, `document_to_markdown` extracts its text, `document_from_url` stores the text of an attachment that only exists behind a URL. The plain file reader refuses those formats as binary, so that refusal is expected and is not a hint to go looking for the file somewhere else. When the pipeline itself refuses a path, report the refusal and the path it named instead of trying another reader.";
|
|
31
|
+
export declare const QA_SOURCE_PRIORITY_NOTE_TEMPLATE = "Answer from the source that owns the question: read what the conversation and its attachments already carry, then search the product documentation and ask the domain expert, and only then look in memory. Recalled memory is background from earlier sessions \u2014 a miss there is not evidence that no source exists, and it is not where a document, a page or a product fact should be looked up.";
|
|
26
32
|
export interface QaIdentityRenderInput {
|
|
27
33
|
/** The owner's account address; the one fact accounts always provide. */
|
|
28
34
|
readonly email: string;
|
|
@@ -107,6 +113,28 @@ export declare class QaPromptNotes {
|
|
|
107
113
|
* the difference between a panel of hashes and a panel of tasks.
|
|
108
114
|
*/
|
|
109
115
|
private delegationNotes;
|
|
116
|
+
/**
|
|
117
|
+
* Which reader an attached document belongs to.
|
|
118
|
+
*
|
|
119
|
+
* A chat user's `.docx` or `.pdf` arrives as a path into the attachment
|
|
120
|
+
* store, and the reader the model reaches for by habit answers `binary file`
|
|
121
|
+
* for it. That answer is a fact about the format, not about the file being
|
|
122
|
+
* missing, and a run that reads it as the second one searches the workspace
|
|
123
|
+
* for a document it was already handed. The note names the pipeline and both
|
|
124
|
+
* halves of the trap: the plain reader's refusal is expected, and the
|
|
125
|
+
* pipeline's own refusal is a report to make, not a reason to try a third
|
|
126
|
+
* reader.
|
|
127
|
+
*/
|
|
128
|
+
private documentsNotes;
|
|
129
|
+
/**
|
|
130
|
+
* Where an answer comes from, in this deployment's terms.
|
|
131
|
+
*
|
|
132
|
+
* The memory plugin's own skill says the same thing in its own words, but a
|
|
133
|
+
* persona may be the entire system prompt and a skill is read only once the
|
|
134
|
+
* model decides to reach for it: the rule that outlives both is the one
|
|
135
|
+
* delivered as a note, ahead of the first tool call that would break it.
|
|
136
|
+
*/
|
|
137
|
+
private sourcePriorityNotes;
|
|
110
138
|
private carriedKey;
|
|
111
139
|
/**
|
|
112
140
|
* The text one note already carries in this agent's conversation. Process
|
|
@@ -19,6 +19,10 @@ export interface QaDocumentPreviewRequest extends QaAllowedFileRequest {
|
|
|
19
19
|
* refuses with `unsupported` rather than growing a second converter here. The
|
|
20
20
|
* input path passes the same containment check the panel's other reads use, so
|
|
21
21
|
* a preview cannot read what a listing could not reach.
|
|
22
|
+
*
|
|
23
|
+
* The resolved root the check opened is handed to the pipeline as well (§26.2):
|
|
24
|
+
* an uploaded Word file lives in the attachment store, and a pipeline that is
|
|
25
|
+
* not told about that root refuses the file this check just accepted.
|
|
22
26
|
*/
|
|
23
27
|
export declare function previewConvertibleDocument({ documents, sessionId, maxBytes, ...file }: QaDocumentPreviewRequest): Promise<QaDocumentPreview>;
|
|
24
28
|
//# sourceMappingURL=document-preview.d.ts.map
|
|
@@ -8,7 +8,7 @@ import type { QaToolDescriptor } from "./types.js";
|
|
|
8
8
|
*
|
|
9
9
|
* Bump it whenever the catalog's tool set or their schemas change.
|
|
10
10
|
*/
|
|
11
|
-
export declare const QA_TOOL_CATALOG_VERSION = "
|
|
11
|
+
export declare const QA_TOOL_CATALOG_VERSION = "3";
|
|
12
12
|
/** One QA tool reports the activation state of whichever agent calls it. */
|
|
13
13
|
export interface QaToolsSelfcheckDeps {
|
|
14
14
|
readonly catalogVersion: string;
|