@anyshift/backstage-plugin-anyshift 0.1.0-beta.20 → 0.1.0-beta.21

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.
Files changed (49) hide show
  1. package/LICENSE +1 -0
  2. package/README.md +3 -11
  3. package/dist/api/AnyshiftApi.esm.js +5 -56
  4. package/dist/api/AnyshiftApi.esm.js.map +1 -1
  5. package/dist/components/cloud/CloudResourceContent.esm.js +45 -444
  6. package/dist/components/cloud/CloudResourceContent.esm.js.map +1 -1
  7. package/dist/components/entity/AnyshiftEntityContent.esm.js +23 -128
  8. package/dist/components/entity/AnyshiftEntityContent.esm.js.map +1 -1
  9. package/dist/components/entity/BriefSections.esm.js +4 -24
  10. package/dist/components/entity/BriefSections.esm.js.map +1 -1
  11. package/dist/components/entity/DatadogLiveSignal.esm.js +23 -85
  12. package/dist/components/entity/DatadogLiveSignal.esm.js.map +1 -1
  13. package/dist/components/entity/MermaidArchitecture.esm.js +43 -202
  14. package/dist/components/entity/MermaidArchitecture.esm.js.map +1 -1
  15. package/dist/components/entity/SectionPresenters.esm.js +82 -145
  16. package/dist/components/entity/SectionPresenters.esm.js.map +1 -1
  17. package/dist/components/entity/architectureDiagram.esm.js +15 -48
  18. package/dist/components/entity/architectureDiagram.esm.js.map +1 -1
  19. package/dist/components/explorer/AnyshiftExplorerPage.esm.js +19 -154
  20. package/dist/components/explorer/AnyshiftExplorerPage.esm.js.map +1 -1
  21. package/dist/components/explorer/DatadogOperationsRadar.esm.js +31 -92
  22. package/dist/components/explorer/DatadogOperationsRadar.esm.js.map +1 -1
  23. package/dist/index.d.ts +4 -18
  24. package/dist/index.esm.js +1 -1
  25. package/dist/package.json.esm.js +13 -13
  26. package/dist/plugin.esm.js +2 -6
  27. package/dist/plugin.esm.js.map +1 -1
  28. package/package.json +15 -15
  29. package/CHANGELOG.md +0 -87
  30. package/dist/components/ask/AskAnyshiftCard.esm.js +0 -348
  31. package/dist/components/ask/AskAnyshiftCard.esm.js.map +0 -1
  32. package/dist/components/ask/askPresenters.esm.js +0 -1203
  33. package/dist/components/ask/askPresenters.esm.js.map +0 -1
  34. package/dist/components/ask/askScope.esm.js +0 -27
  35. package/dist/components/ask/askScope.esm.js.map +0 -1
  36. package/dist/components/ask/askSuggestions.esm.js +0 -41
  37. package/dist/components/ask/askSuggestions.esm.js.map +0 -1
  38. package/dist/components/cloud/CloudImpactSection.esm.js +0 -54
  39. package/dist/components/cloud/CloudImpactSection.esm.js.map +0 -1
  40. package/dist/components/cloud/CloudRelationshipSections.esm.js +0 -43
  41. package/dist/components/cloud/CloudRelationshipSections.esm.js.map +0 -1
  42. package/dist/components/entity/ArchitectureOperationDetails.esm.js +0 -107
  43. package/dist/components/entity/ArchitectureOperationDetails.esm.js.map +0 -1
  44. package/dist/components/entity/architectureGraph.esm.js +0 -145
  45. package/dist/components/entity/architectureGraph.esm.js.map +0 -1
  46. package/dist/components/entity/entityIdentity.esm.js +0 -40
  47. package/dist/components/entity/entityIdentity.esm.js.map +0 -1
  48. package/dist/components/entity/relatedCatalogEntities.esm.js +0 -60
  49. package/dist/components/entity/relatedCatalogEntities.esm.js.map +0 -1
package/CHANGELOG.md DELETED
@@ -1,87 +0,0 @@
1
- # Changelog
2
-
3
- ## Unreleased
4
-
5
- ## 0.1.0-beta.16
6
-
7
- - Retry unresolved cloud-change evidence with the provider-native ARN while keeping the stable
8
- catalog identity and existing entity URLs unchanged.
9
-
10
- ## 0.1.0-beta.15
11
-
12
- - Resolve Affected footprint entries against one Backstage catalog snapshot and link only entities
13
- that are proven to exist.
14
- - Repair stale runtime-namespace links, de-duplicate logical names, and keep unresolved graph
15
- evidence visible as plain text instead of dead links.
16
-
17
- ## 0.1.0-beta.14
18
-
19
- - Expose available APM HTTP methods and templated paths from service `CALLS_TO` edges through a compact architecture-diagram affordance and source-grouped evidence inspector.
20
- - Keep missing operation or observation metadata explicitly unknown without changing legacy edge rendering or adding per-edge Graph API requests.
21
-
22
- ## 0.1.0-beta.13
23
-
24
- - Keep zero-event cloud-resource pages quiet: identity-completeness codes do not become alerts
25
- without a returned event, while source and status limits remain one evidence caveat.
26
-
27
- ## 0.1.0-beta.12
28
-
29
- - Render cloud Resources through shared Cloud and Anyshift evidence cards, with direct catalog
30
- dependencies, typed potential impact, cloud changes, IaC evidence, and ARN-scoped Ask.
31
- - Keep cloud evidence separate from workload/Kubernetes safeguards and make absent catalog, change,
32
- IaC, or impact evidence explicitly unknown rather than healthy.
33
-
34
- ## 0.1.0-beta.11
35
-
36
- - Add one reusable Ask Anyshift card to the estate dashboard and supported entity pages.
37
- - Render bounded typed evidence, visible entity scope, effective interpretation, uncertainty, and safe error states.
38
- - Keep viewer Ask availability independent from operator-only Advanced Query.
39
-
40
- ## 0.1.0-beta.10
41
-
42
- - Render why-now evidence immediately after the entity overview without claiming causality.
43
- - Link affected service footprints to related Backstage catalog entities.
44
- - Add estate evidence coverage, blind spots, freshness, and scoped retry to the Anyshift dashboard.
45
-
46
- ## 0.1.0-beta.9
47
-
48
- - Render configured callers and dependencies separately from observed APM traffic.
49
- - Resolve ECS configuration evidence through a dedicated runtime identity annotation.
50
-
51
- ## 0.1.0-beta.8
52
-
53
- - Render cloud evidence timestamps with bracketed time-zone identifiers without
54
- displaying `Invalid Date`.
55
- - Preserve unrecognized timestamp evidence as its original value instead of
56
- inventing a time.
57
-
58
- ## 0.1.0-beta.7
59
-
60
- - Load normalized cloud changes, Terraform provenance, and drift evidence on cloud Resource pages.
61
- - Resolve stable Anyshift resource identity before provider-native ARN fallback.
62
- - Preserve successful evidence sections across partial upstream failures and render unknown drift neutrally.
63
-
64
- ## 0.1.0-beta.6
65
-
66
- - Add a discoverable global Cloud inventory page.
67
- - Add generic cloud Resource content with identity, ownership, relations, ARN, and console links.
68
-
69
- ## 0.1.0-beta.5
70
-
71
- - Hide entity content for catalog resources without a supported Anyshift brief kind.
72
- - Preserve the default workload view for GitHub-owned Components.
73
-
74
- ## 0.1.0-beta.3
75
-
76
- - Show durable catalog reconciliation status on the global dashboard.
77
- - Add a permission-aware **Reconcile now** operator action.
78
-
79
- ## 0.1.0-beta.2
80
-
81
- - Coordinate the frontend package with the trusted catalog synchronization beta.
82
- - Show configured, excluded, active, unclassified, and managed catalog coverage.
83
-
84
- ## 0.1.0-beta.1
85
-
86
- - Add discoverable dashboard, navigation, API, and entity-content extensions.
87
- - Add permission-aware rendering for estate data and deterministic queries.
@@ -1,348 +0,0 @@
1
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { Card, CardContent, Typography, Box, Chip, Button, TextField, CircularProgress } from '@material-ui/core';
3
- import { useApi } from '@backstage/frontend-plugin-api';
4
- import { useRef, useState, useLayoutEffect } from 'react';
5
- import { anyshiftApiRef, AnyshiftRequestError } from '../../api/AnyshiftApi.esm.js';
6
- import { scopedSuggestions, estateSuggestions, followUpsForIntent } from './askSuggestions.esm.js';
7
- import { presentAskResult, AskResultPresenter } from './askPresenters.esm.js';
8
-
9
- const MAX_QUESTION_CODE_POINTS = 500;
10
- const MAX_SCOPE_TARGET_CODE_POINTS = 200;
11
- const IDLE_HELPER_TEXT = "Read-only answers from your connected graph. Do not include secrets.";
12
- const AskAnyshiftCard = ({
13
- context,
14
- scope,
15
- scopeLabel
16
- }) => {
17
- const api = useApi(anyshiftApiRef);
18
- const validPropScope = context === "entity" && isValidScope(scope) ? scope : void 0;
19
- const propScopeIdentity = context === "entity" && scope?.entityRef.trim() ? scope.entityRef : void 0;
20
- const mountedIdentity = context === "estate" ? "estate" : `entity:${propScopeIdentity ?? ""}`;
21
- const previousMountedIdentity = useRef(mountedIdentity);
22
- const requestGeneration = useRef(0);
23
- const activeRequest = useRef();
24
- const [question, setQuestion] = useState("");
25
- const [validationError, setValidationError] = useState();
26
- const [state, setState] = useState({ status: "idle" });
27
- const [scopeRemoved, setScopeRemoved] = useState(false);
28
- const localScope = scopeRemoved ? void 0 : validPropScope;
29
- const restorableScope = validPropScope;
30
- const visibleScopeLabel = scopeLabel?.trim() || localScope?.target;
31
- const restorableScopeLabel = scopeLabel?.trim() || restorableScope?.target;
32
- const requestContext = requestContextKey(
33
- context,
34
- propScopeIdentity,
35
- localScope
36
- );
37
- const previousRequestContext = useRef(requestContext);
38
- useLayoutEffect(() => {
39
- if (previousMountedIdentity.current === mountedIdentity) return;
40
- previousMountedIdentity.current = mountedIdentity;
41
- requestGeneration.current += 1;
42
- activeRequest.current = void 0;
43
- setState({ status: "idle" });
44
- setValidationError(void 0);
45
- setScopeRemoved(false);
46
- }, [mountedIdentity]);
47
- useLayoutEffect(() => {
48
- if (previousRequestContext.current === requestContext) return;
49
- previousRequestContext.current = requestContext;
50
- requestGeneration.current += 1;
51
- if (!activeRequest.current) return;
52
- activeRequest.current = void 0;
53
- setState(
54
- (current) => current.status === "loading" ? { status: "idle" } : current
55
- );
56
- setValidationError(void 0);
57
- }, [requestContext]);
58
- const loading = state.status === "loading";
59
- const examples = localScope ? scopedSuggestions : estateSuggestions;
60
- const visibleAnswer = answerForState(state);
61
- const previousAnswer = state.status === "loading" || state.status === "error" ? state.previous : void 0;
62
- const submitQuestion = async (explicitQuestion = question) => {
63
- if (activeRequest.current?.requestContext === requestContext) return;
64
- const clientError = validateQuestion(explicitQuestion);
65
- if (clientError) {
66
- setValidationError(clientError);
67
- return;
68
- }
69
- setValidationError(void 0);
70
- const generation = requestGeneration.current + 1;
71
- requestGeneration.current = generation;
72
- activeRequest.current = { generation, requestContext };
73
- const previous = visibleAnswer;
74
- setState({ status: "loading", previous });
75
- try {
76
- const request = localScope ? { question: explicitQuestion, scope: localScope } : { question: explicitQuestion };
77
- const answer = await api.ask(request);
78
- if (ownsActiveRequest(activeRequest.current, generation, requestContext)) {
79
- setState({ status: "success", answer });
80
- }
81
- } catch (error) {
82
- if (ownsActiveRequest(activeRequest.current, generation, requestContext)) {
83
- setState({
84
- status: "error",
85
- error: safeRequestError(error),
86
- previous
87
- });
88
- }
89
- } finally {
90
- if (ownsActiveRequest(activeRequest.current, generation, requestContext)) {
91
- activeRequest.current = void 0;
92
- }
93
- }
94
- };
95
- const submitExplicitQuestion = (nextQuestion) => {
96
- if (activeRequest.current?.requestContext === requestContext) return;
97
- setQuestion(nextQuestion);
98
- void submitQuestion(nextQuestion);
99
- };
100
- const onSubmit = (event) => {
101
- event.preventDefault();
102
- void submitQuestion();
103
- };
104
- const onQuestionKeyDown = (event) => {
105
- if (event.key !== "Enter" || !event.metaKey && !event.ctrlKey) return;
106
- event.preventDefault();
107
- void submitQuestion();
108
- };
109
- return /* @__PURE__ */ jsx(Card, { variant: "outlined", children: /* @__PURE__ */ jsxs(CardContent, { children: [
110
- /* @__PURE__ */ jsx(Typography, { component: "h2", variant: "h6", gutterBottom: true, children: "Ask Anyshift" }),
111
- context === "entity" && /* @__PURE__ */ jsx(
112
- Box,
113
- {
114
- mb: 2,
115
- display: "flex",
116
- alignItems: "center",
117
- flexWrap: "wrap",
118
- gridGap: 8,
119
- children: localScope ? /* @__PURE__ */ jsxs(Fragment, { children: [
120
- /* @__PURE__ */ jsx(
121
- Chip,
122
- {
123
- size: "small",
124
- color: "primary",
125
- variant: "outlined",
126
- label: `Scope \xB7 ${visibleScopeLabel}`
127
- }
128
- ),
129
- /* @__PURE__ */ jsx(
130
- Button,
131
- {
132
- type: "button",
133
- size: "small",
134
- disabled: loading,
135
- onClick: () => setScopeRemoved(true),
136
- "aria-label": `Remove ${visibleScopeLabel} scope`,
137
- children: "Remove"
138
- }
139
- )
140
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
141
- /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "textSecondary", children: "Searching the whole connected project" }),
142
- restorableScope && /* @__PURE__ */ jsx(
143
- Button,
144
- {
145
- type: "button",
146
- size: "small",
147
- disabled: loading,
148
- onClick: () => setScopeRemoved(false),
149
- "aria-label": `Restore ${restorableScopeLabel} scope`,
150
- children: "Restore scope"
151
- }
152
- )
153
- ] })
154
- }
155
- ),
156
- /* @__PURE__ */ jsxs("form", { onSubmit, noValidate: true, children: [
157
- /* @__PURE__ */ jsx(
158
- TextField,
159
- {
160
- id: "ask-anyshift-question",
161
- label: "Question",
162
- value: question,
163
- onChange: (event) => {
164
- setQuestion(event.target.value);
165
- if (validationError) setValidationError(void 0);
166
- },
167
- onKeyDown: onQuestionKeyDown,
168
- disabled: loading,
169
- error: Boolean(validationError),
170
- helperText: validationError ?? IDLE_HELPER_TEXT,
171
- multiline: true,
172
- minRows: 2,
173
- fullWidth: true,
174
- variant: "outlined"
175
- }
176
- ),
177
- /* @__PURE__ */ jsx(Box, { mt: 1, display: "flex", justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
178
- Button,
179
- {
180
- type: "submit",
181
- color: "primary",
182
- variant: "contained",
183
- disabled: loading,
184
- startIcon: loading ? /* @__PURE__ */ jsx(CircularProgress, { size: 16 }) : void 0,
185
- children: loading ? "Asking\u2026" : "Ask"
186
- }
187
- ) })
188
- ] }),
189
- /* @__PURE__ */ jsx(
190
- QuestionChoices,
191
- {
192
- title: "Try an example",
193
- questions: examples,
194
- disabled: loading,
195
- onQuestion: submitExplicitQuestion
196
- }
197
- ),
198
- state.status === "error" && /* @__PURE__ */ jsxs(Box, { mt: 2, role: "alert", "aria-live": "polite", children: [
199
- /* @__PURE__ */ jsx(Typography, { color: "error", children: errorCopy(state.error) }),
200
- isRetryable(state.error) && /* @__PURE__ */ jsx(Box, { mt: 1, children: /* @__PURE__ */ jsx(
201
- Button,
202
- {
203
- type: "button",
204
- size: "small",
205
- variant: "outlined",
206
- onClick: () => void submitQuestion(),
207
- children: "Retry"
208
- }
209
- ) })
210
- ] }),
211
- loading && /* @__PURE__ */ jsx(Typography, { role: "status", variant: "body2", color: "textSecondary", children: "Searching the connected graph\u2026" }),
212
- visibleAnswer && /* @__PURE__ */ jsxs(Box, { mt: 3, children: [
213
- previousAnswer && /* @__PURE__ */ jsx(Typography, { component: "h3", variant: "subtitle2", gutterBottom: true, children: "Previous answer" }),
214
- /* @__PURE__ */ jsx(
215
- SafeAnswer,
216
- {
217
- answer: visibleAnswer,
218
- onQuestion: loading ? void 0 : submitExplicitQuestion
219
- }
220
- ),
221
- !loading && /* @__PURE__ */ jsx(
222
- QuestionChoices,
223
- {
224
- title: "Ask another question",
225
- questions: followUpsForIntent(
226
- visibleAnswer.result.intent,
227
- Boolean(localScope)
228
- ),
229
- disabled: false,
230
- onQuestion: submitExplicitQuestion
231
- }
232
- )
233
- ] })
234
- ] }) });
235
- };
236
- const QuestionChoices = ({
237
- title,
238
- questions,
239
- disabled,
240
- onQuestion
241
- }) => /* @__PURE__ */ jsxs(Box, { mt: 2, children: [
242
- /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", gutterBottom: true, children: title }),
243
- /* @__PURE__ */ jsx(Box, { display: "flex", flexWrap: "wrap", gridGap: 8, children: questions.map((suggestion) => /* @__PURE__ */ jsx(
244
- Button,
245
- {
246
- type: "button",
247
- size: "small",
248
- variant: "outlined",
249
- disabled,
250
- onClick: () => onQuestion(suggestion),
251
- children: suggestion
252
- },
253
- suggestion
254
- )) })
255
- ] });
256
- const SafeAnswer = ({
257
- answer,
258
- onQuestion
259
- }) => {
260
- try {
261
- presentAskResult(answer.result);
262
- } catch {
263
- return /* @__PURE__ */ jsxs(Box, { "aria-label": "Anyshift answer", children: [
264
- /* @__PURE__ */ jsx(Typography, { variant: "body1", children: answer.result.summary }),
265
- /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "textSecondary", children: "Detailed evidence is not supported by this Backstage version." })
266
- ] });
267
- }
268
- return /* @__PURE__ */ jsx(
269
- AskResultPresenter,
270
- {
271
- result: answer.result,
272
- effectiveQuestion: answer.effectiveQuestion,
273
- answeredAt: answer.answeredAt,
274
- onQuestion
275
- }
276
- );
277
- };
278
- function answerForState(state) {
279
- switch (state.status) {
280
- case "success":
281
- return state.answer;
282
- case "loading":
283
- case "error":
284
- return state.previous;
285
- case "idle":
286
- return void 0;
287
- default:
288
- return assertNever(state);
289
- }
290
- }
291
- function ownsActiveRequest(activeRequest, generation, requestContext) {
292
- return activeRequest?.generation === generation && activeRequest.requestContext === requestContext;
293
- }
294
- function requestContextKey(context, entityRef, scope) {
295
- if (context === "estate") return "estate";
296
- const identity = entityRef?.trim() ?? "";
297
- return scope ? `entity:${identity}:target:${scope.target.trim()}` : `entity:${identity}:unscoped`;
298
- }
299
- function validateQuestion(value) {
300
- if (!value.trim()) return "Enter a question.";
301
- if (Array.from(value).length > MAX_QUESTION_CODE_POINTS) {
302
- return "Questions must be 500 characters or fewer.";
303
- }
304
- return void 0;
305
- }
306
- function isValidScope(scope) {
307
- if (!scope?.entityRef.trim() || !scope.target.trim()) return false;
308
- if (Array.from(scope.target).length > MAX_SCOPE_TARGET_CODE_POINTS) {
309
- return false;
310
- }
311
- return !Array.from(scope.target).some((character) => {
312
- const codePoint = character.codePointAt(0);
313
- return codePoint !== void 0 && (codePoint <= 31 || codePoint >= 127 && codePoint <= 159);
314
- });
315
- }
316
- function safeRequestError(error) {
317
- return error instanceof AnyshiftRequestError ? error : new AnyshiftRequestError(0, "unavailable", "Unavailable");
318
- }
319
- function errorCopy(error) {
320
- if (error.status === 400 || error.code === "bad_request") {
321
- return "Ask Anyshift could not answer that question. Try rephrasing it or choose an example.";
322
- }
323
- if (error.status === 403 || error.code === "forbidden") {
324
- return "Ask Anyshift access is unavailable for your account.";
325
- }
326
- if (error.status === 413 || error.code === "payload_too_large") {
327
- return "Questions must be 500 characters or fewer.";
328
- }
329
- if (error.status === 429 || error.code === "rate_limited") {
330
- return typeof error.retryAfterSeconds === "number" ? `Ask Anyshift is temporarily rate limited. Try again in ${error.retryAfterSeconds} seconds.` : "Ask Anyshift is temporarily rate limited. Try again shortly.";
331
- }
332
- if (error.status === 504 || error.code === "timeout") {
333
- return "The graph question timed out. Try again.";
334
- }
335
- if (error.status === 0 || error.status === 502 || error.status === 503 || error.code === "unavailable" || error.code === "upstream_unavailable" || error.code === "request_failed") {
336
- return "Ask Anyshift is temporarily unavailable. Try again.";
337
- }
338
- return "Ask Anyshift could not complete the question. Try again.";
339
- }
340
- function isRetryable(error) {
341
- return error.status === 0 || error.status === 429 || error.status === 502 || error.status === 503 || error.status === 504 || error.code === "timeout" || error.code === "unavailable" || error.code === "upstream_unavailable" || error.code === "request_failed";
342
- }
343
- function assertNever(value) {
344
- throw new Error(`Unsupported Ask card state: ${String(value)}`);
345
- }
346
-
347
- export { AskAnyshiftCard };
348
- //# sourceMappingURL=AskAnyshiftCard.esm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AskAnyshiftCard.esm.js","sources":["../../../src/components/ask/AskAnyshiftCard.tsx"],"sourcesContent":["import {\n Box,\n Button,\n Card,\n CardContent,\n Chip,\n CircularProgress,\n TextField,\n Typography,\n} from '@material-ui/core';\nimport { useApi } from '@backstage/frontend-plugin-api';\nimport {\n FormEvent,\n KeyboardEvent,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport { anyshiftApiRef, AnyshiftRequestError } from '../../api/AnyshiftApi';\nimport type { AskAnyshiftResponse, AskScope } from '../../api/types';\nimport {\n estateSuggestions,\n followUpsForIntent,\n scopedSuggestions,\n} from './askSuggestions';\nimport { AskResultPresenter, presentAskResult } from './askPresenters';\n\nconst MAX_QUESTION_CODE_POINTS = 500;\nconst MAX_SCOPE_TARGET_CODE_POINTS = 200;\nconst IDLE_HELPER_TEXT =\n 'Read-only answers from your connected graph. Do not include secrets.';\n\ntype AskCardState =\n | { status: 'idle' }\n | { status: 'loading'; previous?: AskAnyshiftResponse }\n | { status: 'success'; answer: AskAnyshiftResponse }\n | {\n status: 'error';\n error: AnyshiftRequestError;\n previous?: AskAnyshiftResponse;\n };\n\nexport interface AskAnyshiftCardProps {\n context: 'estate' | 'entity';\n scope?: AskScope;\n scopeLabel?: string;\n}\n\nexport const AskAnyshiftCard = ({\n context,\n scope,\n scopeLabel,\n}: AskAnyshiftCardProps) => {\n const api = useApi(anyshiftApiRef);\n const validPropScope =\n context === 'entity' && isValidScope(scope) ? scope : undefined;\n const propScopeIdentity =\n context === 'entity' && scope?.entityRef.trim()\n ? scope.entityRef\n : undefined;\n const mountedIdentity =\n context === 'estate' ? 'estate' : `entity:${propScopeIdentity ?? ''}`;\n const previousMountedIdentity = useRef(mountedIdentity);\n const requestGeneration = useRef(0);\n const activeRequest = useRef<{\n generation: number;\n requestContext: string;\n }>();\n const [question, setQuestion] = useState('');\n const [validationError, setValidationError] = useState<string>();\n const [state, setState] = useState<AskCardState>({ status: 'idle' });\n const [scopeRemoved, setScopeRemoved] = useState(false);\n const localScope = scopeRemoved ? undefined : validPropScope;\n const restorableScope = validPropScope;\n const visibleScopeLabel = scopeLabel?.trim() || localScope?.target;\n const restorableScopeLabel = scopeLabel?.trim() || restorableScope?.target;\n const requestContext = requestContextKey(\n context,\n propScopeIdentity,\n localScope,\n );\n const previousRequestContext = useRef(requestContext);\n\n useLayoutEffect(() => {\n if (previousMountedIdentity.current === mountedIdentity) return;\n previousMountedIdentity.current = mountedIdentity;\n requestGeneration.current += 1;\n activeRequest.current = undefined;\n setState({ status: 'idle' });\n setValidationError(undefined);\n setScopeRemoved(false);\n }, [mountedIdentity]);\n\n useLayoutEffect(() => {\n if (previousRequestContext.current === requestContext) return;\n previousRequestContext.current = requestContext;\n requestGeneration.current += 1;\n if (!activeRequest.current) return;\n activeRequest.current = undefined;\n setState(current =>\n current.status === 'loading' ? { status: 'idle' } : current,\n );\n setValidationError(undefined);\n }, [requestContext]);\n\n const loading = state.status === 'loading';\n const examples = localScope ? scopedSuggestions : estateSuggestions;\n const visibleAnswer = answerForState(state);\n const previousAnswer =\n state.status === 'loading' || state.status === 'error'\n ? state.previous\n : undefined;\n\n const submitQuestion = async (explicitQuestion = question) => {\n if (activeRequest.current?.requestContext === requestContext) return;\n const clientError = validateQuestion(explicitQuestion);\n if (clientError) {\n setValidationError(clientError);\n return;\n }\n\n setValidationError(undefined);\n const generation = requestGeneration.current + 1;\n requestGeneration.current = generation;\n activeRequest.current = { generation, requestContext };\n const previous = visibleAnswer;\n setState({ status: 'loading', previous });\n try {\n const request = localScope\n ? { question: explicitQuestion, scope: localScope }\n : { question: explicitQuestion };\n const answer = await api.ask(request);\n if (\n ownsActiveRequest(activeRequest.current, generation, requestContext)\n ) {\n setState({ status: 'success', answer });\n }\n } catch (error) {\n if (\n ownsActiveRequest(activeRequest.current, generation, requestContext)\n ) {\n setState({\n status: 'error',\n error: safeRequestError(error),\n previous,\n });\n }\n } finally {\n if (\n ownsActiveRequest(activeRequest.current, generation, requestContext)\n ) {\n activeRequest.current = undefined;\n }\n }\n };\n\n const submitExplicitQuestion = (nextQuestion: string) => {\n if (activeRequest.current?.requestContext === requestContext) return;\n setQuestion(nextQuestion);\n void submitQuestion(nextQuestion);\n };\n\n const onSubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n void submitQuestion();\n };\n\n const onQuestionKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.key !== 'Enter' || (!event.metaKey && !event.ctrlKey)) return;\n event.preventDefault();\n void submitQuestion();\n };\n\n return (\n <Card variant=\"outlined\">\n <CardContent>\n <Typography component=\"h2\" variant=\"h6\" gutterBottom>\n Ask Anyshift\n </Typography>\n\n {context === 'entity' && (\n <Box\n mb={2}\n display=\"flex\"\n alignItems=\"center\"\n flexWrap=\"wrap\"\n gridGap={8}\n >\n {localScope ? (\n <>\n <Chip\n size=\"small\"\n color=\"primary\"\n variant=\"outlined\"\n label={`Scope · ${visibleScopeLabel}`}\n />\n <Button\n type=\"button\"\n size=\"small\"\n disabled={loading}\n onClick={() => setScopeRemoved(true)}\n aria-label={`Remove ${visibleScopeLabel} scope`}\n >\n Remove\n </Button>\n </>\n ) : (\n <>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Searching the whole connected project\n </Typography>\n {restorableScope && (\n <Button\n type=\"button\"\n size=\"small\"\n disabled={loading}\n onClick={() => setScopeRemoved(false)}\n aria-label={`Restore ${restorableScopeLabel} scope`}\n >\n Restore scope\n </Button>\n )}\n </>\n )}\n </Box>\n )}\n\n <form onSubmit={onSubmit} noValidate>\n <TextField\n id=\"ask-anyshift-question\"\n label=\"Question\"\n value={question}\n onChange={event => {\n setQuestion(event.target.value);\n if (validationError) setValidationError(undefined);\n }}\n onKeyDown={onQuestionKeyDown}\n disabled={loading}\n error={Boolean(validationError)}\n helperText={validationError ?? IDLE_HELPER_TEXT}\n multiline\n minRows={2}\n fullWidth\n variant=\"outlined\"\n />\n <Box mt={1} display=\"flex\" justifyContent=\"flex-end\">\n <Button\n type=\"submit\"\n color=\"primary\"\n variant=\"contained\"\n disabled={loading}\n startIcon={loading ? <CircularProgress size={16} /> : undefined}\n >\n {loading ? 'Asking…' : 'Ask'}\n </Button>\n </Box>\n </form>\n\n <QuestionChoices\n title=\"Try an example\"\n questions={examples}\n disabled={loading}\n onQuestion={submitExplicitQuestion}\n />\n\n {state.status === 'error' && (\n <Box mt={2} role=\"alert\" aria-live=\"polite\">\n <Typography color=\"error\">{errorCopy(state.error)}</Typography>\n {isRetryable(state.error) && (\n <Box mt={1}>\n <Button\n type=\"button\"\n size=\"small\"\n variant=\"outlined\"\n onClick={() => void submitQuestion()}\n >\n Retry\n </Button>\n </Box>\n )}\n </Box>\n )}\n\n {loading && (\n <Typography role=\"status\" variant=\"body2\" color=\"textSecondary\">\n Searching the connected graph…\n </Typography>\n )}\n\n {visibleAnswer && (\n <Box mt={3}>\n {previousAnswer && (\n <Typography component=\"h3\" variant=\"subtitle2\" gutterBottom>\n Previous answer\n </Typography>\n )}\n <SafeAnswer\n answer={visibleAnswer}\n onQuestion={loading ? undefined : submitExplicitQuestion}\n />\n {!loading && (\n <QuestionChoices\n title=\"Ask another question\"\n questions={followUpsForIntent(\n visibleAnswer.result.intent,\n Boolean(localScope),\n )}\n disabled={false}\n onQuestion={submitExplicitQuestion}\n />\n )}\n </Box>\n )}\n </CardContent>\n </Card>\n );\n};\n\nconst QuestionChoices = ({\n title,\n questions,\n disabled,\n onQuestion,\n}: {\n title: string;\n questions: readonly string[];\n disabled: boolean;\n onQuestion: (question: string) => void;\n}) => (\n <Box mt={2}>\n <Typography variant=\"subtitle2\" gutterBottom>\n {title}\n </Typography>\n <Box display=\"flex\" flexWrap=\"wrap\" gridGap={8}>\n {questions.map(suggestion => (\n <Button\n key={suggestion}\n type=\"button\"\n size=\"small\"\n variant=\"outlined\"\n disabled={disabled}\n onClick={() => onQuestion(suggestion)}\n >\n {suggestion}\n </Button>\n ))}\n </Box>\n </Box>\n);\n\nconst SafeAnswer = ({\n answer,\n onQuestion,\n}: {\n answer: AskAnyshiftResponse;\n onQuestion?: (question: string) => void;\n}) => {\n try {\n presentAskResult(answer.result);\n } catch {\n return (\n <Box aria-label=\"Anyshift answer\">\n <Typography variant=\"body1\">{answer.result.summary}</Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Detailed evidence is not supported by this Backstage version.\n </Typography>\n </Box>\n );\n }\n\n return (\n <AskResultPresenter\n result={answer.result}\n effectiveQuestion={answer.effectiveQuestion}\n answeredAt={answer.answeredAt}\n onQuestion={onQuestion}\n />\n );\n};\n\nfunction answerForState(state: AskCardState): AskAnyshiftResponse | undefined {\n switch (state.status) {\n case 'success':\n return state.answer;\n case 'loading':\n case 'error':\n return state.previous;\n case 'idle':\n return undefined;\n default:\n return assertNever(state);\n }\n}\n\nfunction ownsActiveRequest(\n activeRequest: { generation: number; requestContext: string } | undefined,\n generation: number,\n requestContext: string,\n): boolean {\n return (\n activeRequest?.generation === generation &&\n activeRequest.requestContext === requestContext\n );\n}\n\nfunction requestContextKey(\n context: 'estate' | 'entity',\n entityRef: string | undefined,\n scope: AskScope | undefined,\n): string {\n if (context === 'estate') return 'estate';\n const identity = entityRef?.trim() ?? '';\n return scope\n ? `entity:${identity}:target:${scope.target.trim()}`\n : `entity:${identity}:unscoped`;\n}\n\nfunction validateQuestion(value: string): string | undefined {\n if (!value.trim()) return 'Enter a question.';\n if (Array.from(value).length > MAX_QUESTION_CODE_POINTS) {\n return 'Questions must be 500 characters or fewer.';\n }\n return undefined;\n}\n\nfunction isValidScope(scope: AskScope | undefined): scope is AskScope {\n if (!scope?.entityRef.trim() || !scope.target.trim()) return false;\n if (Array.from(scope.target).length > MAX_SCOPE_TARGET_CODE_POINTS) {\n return false;\n }\n return !Array.from(scope.target).some(character => {\n const codePoint = character.codePointAt(0);\n return (\n codePoint !== undefined &&\n (codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f))\n );\n });\n}\n\nfunction safeRequestError(error: unknown): AnyshiftRequestError {\n return error instanceof AnyshiftRequestError\n ? error\n : new AnyshiftRequestError(0, 'unavailable', 'Unavailable');\n}\n\nfunction errorCopy(error: AnyshiftRequestError): string {\n if (error.status === 400 || error.code === 'bad_request') {\n return 'Ask Anyshift could not answer that question. Try rephrasing it or choose an example.';\n }\n if (error.status === 403 || error.code === 'forbidden') {\n return 'Ask Anyshift access is unavailable for your account.';\n }\n if (error.status === 413 || error.code === 'payload_too_large') {\n return 'Questions must be 500 characters or fewer.';\n }\n if (error.status === 429 || error.code === 'rate_limited') {\n return typeof error.retryAfterSeconds === 'number'\n ? `Ask Anyshift is temporarily rate limited. Try again in ${error.retryAfterSeconds} seconds.`\n : 'Ask Anyshift is temporarily rate limited. Try again shortly.';\n }\n if (error.status === 504 || error.code === 'timeout') {\n return 'The graph question timed out. Try again.';\n }\n if (\n error.status === 0 ||\n error.status === 502 ||\n error.status === 503 ||\n error.code === 'unavailable' ||\n error.code === 'upstream_unavailable' ||\n error.code === 'request_failed'\n ) {\n return 'Ask Anyshift is temporarily unavailable. Try again.';\n }\n return 'Ask Anyshift could not complete the question. Try again.';\n}\n\nfunction isRetryable(error: AnyshiftRequestError): boolean {\n return (\n error.status === 0 ||\n error.status === 429 ||\n error.status === 502 ||\n error.status === 503 ||\n error.status === 504 ||\n error.code === 'timeout' ||\n error.code === 'unavailable' ||\n error.code === 'upstream_unavailable' ||\n error.code === 'request_failed'\n );\n}\n\nfunction assertNever(value: never): never {\n throw new Error(`Unsupported Ask card state: ${String(value)}`);\n}\n"],"names":[],"mappings":"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"}