@f5-sales-demo/xcsh 22.2.1 → 22.3.3
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/CHANGELOG.md +3 -0
- package/package.json +8 -8
- package/src/cli/plugin-cli.ts +17 -7
- package/src/cli/update-recommendation.ts +1 -7
- package/src/extensibility/plugins/marketplace/builtin-marketplace-snapshot.ts +1 -1
- package/src/extensibility/plugins/marketplace/builtin-marketplace.provenance.json +3 -3
- package/src/internal-urls/api-catalog-qmd-index.generated.ts +2 -2
- package/src/internal-urls/build-info.generated.ts +8 -8
- package/src/internal-urls/documentation-repository.ts +45 -7
- package/src/internal-urls/documentation-resolve.ts +1 -1
- package/src/internal-urls/documentation-snapshot.ts +28 -1
- package/src/internal-urls/knowledge-classifier.ts +19 -5
- package/src/modes/components/model-selector.ts +148 -40
- package/src/modes/controllers/input-controller.ts +13 -13
- package/src/modes/controllers/model-selection.ts +35 -4
- package/src/prompts/rules/llms-search.md +3 -1
- package/src/prompts/system/system-prompt.md +2 -0
- package/src/qmd-smoke.ts +58 -15
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
For conceptual, product, operational, and support questions, search `xcsh://documentation/?search=<query>` first.
|
|
4
4
|
Select the best result and read its exact follow-up URL,
|
|
5
5
|
`xcsh://documentation/<source>/<stable-path>/index.md`, before answering. Use the source filter when the question
|
|
6
|
-
clearly targets `docs-cloud-f5-com` or `
|
|
6
|
+
clearly targets `docs-cloud-f5-com`, `my-f5-com`, or `www-f5-com`. Prefer `www-f5-com` for conceptual and product
|
|
7
|
+
questions, `docs-cloud-f5-com` for configuration and procedures, and `my-f5-com` for troubleshooting and support.
|
|
8
|
+
An explicit source filter is authoritative.
|
|
7
9
|
|
|
8
10
|
Render documentation images only when the user explicitly asks to see them. Extract all unique Markdown image references
|
|
9
11
|
from the exact document, resolve relative references against its exact `xcsh://documentation/` URI, and
|
|
@@ -494,6 +494,8 @@ For conceptual, product, operational, or support questions about F5 Distributed
|
|
|
494
494
|
search `xcsh://documentation/?search=<query>` first, then read the exact
|
|
495
495
|
`xcsh://documentation/<source>/<stable-path>/index.md` result before answering. The search result
|
|
496
496
|
is discovery; the exact Markdown document is the evidence.
|
|
497
|
+
Prefer `www-f5-com` for conceptual and product questions, `docs-cloud-f5-com` for configuration and
|
|
498
|
+
procedural questions, and `my-f5-com` for troubleshooting and support. An explicit source filter is authoritative.
|
|
497
499
|
|
|
498
500
|
### Documentation images
|
|
499
501
|
|
package/src/qmd-smoke.ts
CHANGED
|
@@ -6,7 +6,11 @@ import {
|
|
|
6
6
|
createEmbeddedDocumentationRepository,
|
|
7
7
|
type EmbeddedDocumentationRepository,
|
|
8
8
|
} from "./internal-urls/documentation-repository";
|
|
9
|
-
import type {
|
|
9
|
+
import type {
|
|
10
|
+
DocumentationRepository,
|
|
11
|
+
DocumentationSearchResult,
|
|
12
|
+
DocumentationSource,
|
|
13
|
+
} from "./internal-urls/documentation-resolve";
|
|
10
14
|
import { convertToPng } from "./utils/image-convert";
|
|
11
15
|
|
|
12
16
|
export const QMD_SMOKE_SUCCESS = "XCSH_QMD_SMOKE_OK";
|
|
@@ -17,6 +21,10 @@ const EXPECTED_CATEGORY = "dns-dns-zone-clone-from-dns-domain";
|
|
|
17
21
|
const WAF_QUERY = "configure web application firewall";
|
|
18
22
|
const WAF_PATH = "docs/how-to/app-security/web-app-firewall";
|
|
19
23
|
const WAF_TITLE = "Create Web Application Firewall";
|
|
24
|
+
const MARKETING_QUERY = "what is client side defense";
|
|
25
|
+
const MARKETING_PATH = "products/distributed-cloud-services/client-side-defense";
|
|
26
|
+
const MARKETING_TITLE = "F5 Distributed Cloud Client-Side Defense";
|
|
27
|
+
const MARKETING_SOURCE = "www-f5-com" as const;
|
|
20
28
|
const DNS_QUERY = "set up DNS load balancer";
|
|
21
29
|
const DNS_PATH = "dns-management/how-to/configure-dns-load-balancer";
|
|
22
30
|
const DNS_TITLE = "Set Up DNS Load Balancer";
|
|
@@ -31,6 +39,8 @@ const EXPECTED_EVENTS = [
|
|
|
31
39
|
"api-catalog-rank",
|
|
32
40
|
"documentation-search",
|
|
33
41
|
"documentation-read",
|
|
42
|
+
"documentation-marketing-search",
|
|
43
|
+
"documentation-marketing-read",
|
|
34
44
|
"documentation-search",
|
|
35
45
|
"documentation-read",
|
|
36
46
|
"documentation-follow-up-read",
|
|
@@ -47,7 +57,7 @@ export interface QmdSmokeTraceEntry {
|
|
|
47
57
|
readonly event: QmdSmokeEvent;
|
|
48
58
|
readonly resource?: string;
|
|
49
59
|
readonly title?: string;
|
|
50
|
-
readonly source?:
|
|
60
|
+
readonly source?: DocumentationSource;
|
|
51
61
|
readonly category?: string;
|
|
52
62
|
readonly outcome?: string;
|
|
53
63
|
}
|
|
@@ -59,12 +69,12 @@ export interface QmdSmokeOptions {
|
|
|
59
69
|
documentationRepository?: DocumentationRepository;
|
|
60
70
|
}
|
|
61
71
|
|
|
62
|
-
function searchUri(query: string): string {
|
|
63
|
-
return `xcsh://documentation/?search=${encodeURIComponent(query)}&source=${
|
|
72
|
+
function searchUri(query: string, source: DocumentationSource = SOURCE): string {
|
|
73
|
+
return `xcsh://documentation/?search=${encodeURIComponent(query)}&source=${source}&limit=1`;
|
|
64
74
|
}
|
|
65
75
|
|
|
66
|
-
function documentUri(stablePath: string): string {
|
|
67
|
-
return `xcsh://documentation/${
|
|
76
|
+
function documentUri(stablePath: string, source: DocumentationSource = SOURCE): string {
|
|
77
|
+
return `xcsh://documentation/${source}/${stablePath}/index.md`;
|
|
68
78
|
}
|
|
69
79
|
|
|
70
80
|
function assetUri(stablePath: string, filename: string): string {
|
|
@@ -75,11 +85,12 @@ function assertSearchResult(
|
|
|
75
85
|
result: DocumentationSearchResult | undefined,
|
|
76
86
|
expectedPath: string,
|
|
77
87
|
expectedTitle: string,
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
88
|
+
expectedSource: DocumentationSource = SOURCE,
|
|
89
|
+
): DocumentationSearchResult {
|
|
90
|
+
if (result?.source !== expectedSource || result.stablePath !== expectedPath || result.title !== expectedTitle) {
|
|
91
|
+
throw new Error(`Documentation QMD smoke expected ${expectedTitle} at ${expectedSource}/${expectedPath}`);
|
|
81
92
|
}
|
|
82
|
-
return result
|
|
93
|
+
return result;
|
|
83
94
|
}
|
|
84
95
|
|
|
85
96
|
/** Parse and strictly validate stdout from the installed-binary QMD smoke driver. */
|
|
@@ -109,6 +120,8 @@ export function parseQmdSmokeOutput(output: string): QmdSmokeTraceEntry[] {
|
|
|
109
120
|
const expectedResources = [
|
|
110
121
|
searchUri(WAF_QUERY),
|
|
111
122
|
documentUri(WAF_PATH),
|
|
123
|
+
searchUri(MARKETING_QUERY, MARKETING_SOURCE),
|
|
124
|
+
documentUri(MARKETING_PATH, MARKETING_SOURCE),
|
|
112
125
|
searchUri(DNS_QUERY),
|
|
113
126
|
documentUri(DNS_PATH),
|
|
114
127
|
documentUri(DNS_PATH),
|
|
@@ -126,16 +139,20 @@ export function parseQmdSmokeOutput(output: string): QmdSmokeTraceEntry[] {
|
|
|
126
139
|
if (trace[index]?.title !== WAF_TITLE || trace[index]?.source !== SOURCE)
|
|
127
140
|
throw new Error("QMD smoke trace contains unexpected WAF identity");
|
|
128
141
|
}
|
|
129
|
-
for (const index of [3, 4
|
|
142
|
+
for (const index of [3, 4]) {
|
|
143
|
+
if (trace[index]?.title !== MARKETING_TITLE || trace[index]?.source !== MARKETING_SOURCE)
|
|
144
|
+
throw new Error("QMD smoke trace contains unexpected marketing identity");
|
|
145
|
+
}
|
|
146
|
+
for (const index of [5, 6, 7]) {
|
|
130
147
|
if (trace[index]?.title !== DNS_TITLE || trace[index]?.source !== SOURCE)
|
|
131
148
|
throw new Error("QMD smoke trace contains unexpected DNS identity");
|
|
132
149
|
}
|
|
133
|
-
if (trace[
|
|
134
|
-
if (trace[
|
|
150
|
+
if (trace[8]?.outcome !== "no-match-no-fetch") throw new Error("QMD smoke trace did not fail closed");
|
|
151
|
+
if (trace[9]?.outcome !== DOCUMENTATION_TOOLS_DISABLED_MESSAGE)
|
|
135
152
|
throw new Error("QMD smoke trace omitted the tools-disabled explanation");
|
|
136
|
-
if (trace[
|
|
153
|
+
if (trace[10]?.source !== SOURCE || trace[10].outcome !== "image/png")
|
|
137
154
|
throw new Error("QMD smoke trace contains an unexpected SVG conversion result");
|
|
138
|
-
if (trace[
|
|
155
|
+
if (trace[11]?.outcome !== "ok") throw new Error("QMD smoke trace did not confirm SQLite startup");
|
|
139
156
|
return trace;
|
|
140
157
|
}
|
|
141
158
|
|
|
@@ -173,6 +190,32 @@ export async function runQmdSmoke(options: QmdSmokeOptions = {}): Promise<string
|
|
|
173
190
|
}
|
|
174
191
|
emit({ event: "documentation-read", resource: documentUri(WAF_PATH), title: wafDocument.title, source: SOURCE });
|
|
175
192
|
|
|
193
|
+
const marketing = assertSearchResult(
|
|
194
|
+
(await documentation.search(MARKETING_QUERY, MARKETING_SOURCE, 1))[0],
|
|
195
|
+
MARKETING_PATH,
|
|
196
|
+
MARKETING_TITLE,
|
|
197
|
+
MARKETING_SOURCE,
|
|
198
|
+
);
|
|
199
|
+
emit({
|
|
200
|
+
event: "documentation-marketing-search",
|
|
201
|
+
resource: searchUri(MARKETING_QUERY, MARKETING_SOURCE),
|
|
202
|
+
title: marketing.title,
|
|
203
|
+
source: marketing.source,
|
|
204
|
+
});
|
|
205
|
+
const marketingDocument = await documentation.readDocument(MARKETING_SOURCE, MARKETING_PATH);
|
|
206
|
+
if (
|
|
207
|
+
marketingDocument?.title !== MARKETING_TITLE ||
|
|
208
|
+
!marketingDocument.markdown.includes("# F5 Client-Side Defense")
|
|
209
|
+
) {
|
|
210
|
+
throw new Error("Documentation QMD smoke could not read exact marketing Markdown");
|
|
211
|
+
}
|
|
212
|
+
emit({
|
|
213
|
+
event: "documentation-marketing-read",
|
|
214
|
+
resource: documentUri(MARKETING_PATH, MARKETING_SOURCE),
|
|
215
|
+
title: marketingDocument.title,
|
|
216
|
+
source: MARKETING_SOURCE,
|
|
217
|
+
});
|
|
218
|
+
|
|
176
219
|
const dns = assertSearchResult((await documentation.search(DNS_QUERY, SOURCE, 1))[0], DNS_PATH, DNS_TITLE);
|
|
177
220
|
emit({ event: "documentation-search", resource: searchUri(DNS_QUERY), title: dns.title, source: dns.source });
|
|
178
221
|
const dnsDocument = await documentation.readDocument(SOURCE, DNS_PATH);
|