@anyshift/backstage-plugin-anyshift 0.1.0-beta.23 → 0.1.0-beta.25
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 +8 -0
- package/dist/components/ask/AskAnyshiftCard.esm.js +4 -1
- package/dist/components/ask/AskAnyshiftCard.esm.js.map +1 -1
- package/dist/components/ask/askScope.esm.js +10 -1
- package/dist/components/ask/askScope.esm.js.map +1 -1
- package/dist/package.json.esm.js +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.0-beta.25
|
|
4
|
+
|
|
5
|
+
- Use exact runtime identity for entity-scoped Ask while retaining readable labels and rejecting stale answers after identity changes.
|
|
6
|
+
|
|
7
|
+
## 0.1.0-beta.24
|
|
8
|
+
|
|
9
|
+
- Align with the runtime-identity and bounded alert-cause backend release.
|
|
10
|
+
|
|
3
11
|
## 0.1.0-beta.22
|
|
4
12
|
|
|
5
13
|
- Publish a consumer-ready package manifest with resolved workspace dependencies.
|
|
@@ -5,6 +5,7 @@ import { useRef, useState, useLayoutEffect } from 'react';
|
|
|
5
5
|
import { anyshiftApiRef, AnyshiftRequestError } from '../../api/AnyshiftApi.esm.js';
|
|
6
6
|
import { scopedSuggestions, estateSuggestions, followUpsForIntent } from './askSuggestions.esm.js';
|
|
7
7
|
import { presentAskResult, AskResultPresenter } from './askPresenters.esm.js';
|
|
8
|
+
import { isValidAskResourceId } from './askScope.esm.js';
|
|
8
9
|
|
|
9
10
|
const MAX_QUESTION_CODE_POINTS = 500;
|
|
10
11
|
const MAX_SCOPE_TARGET_CODE_POINTS = 200;
|
|
@@ -288,7 +289,7 @@ function ownsActiveRequest(activeRequest, generation, requestContext) {
|
|
|
288
289
|
function requestContextKey(context, entityRef, scope) {
|
|
289
290
|
if (context === "estate") return "estate";
|
|
290
291
|
const identity = entityRef?.trim() ?? "";
|
|
291
|
-
return scope ?
|
|
292
|
+
return scope ? JSON.stringify([identity, scope.target.trim(), scope.resourceId?.trim()]) : `entity:${identity}:unscoped`;
|
|
292
293
|
}
|
|
293
294
|
function validateQuestion(value) {
|
|
294
295
|
if (!value.trim()) return "Enter a question.";
|
|
@@ -299,6 +300,8 @@ function validateQuestion(value) {
|
|
|
299
300
|
}
|
|
300
301
|
function isValidScope(scope) {
|
|
301
302
|
if (!scope?.entityRef.trim() || !scope.target.trim()) return false;
|
|
303
|
+
if (scope.resourceId !== void 0 && !isValidAskResourceId(scope.resourceId))
|
|
304
|
+
return false;
|
|
302
305
|
if (Array.from(scope.target).length > MAX_SCOPE_TARGET_CODE_POINTS) {
|
|
303
306
|
return false;
|
|
304
307
|
}
|
|
@@ -1 +1 @@
|
|
|
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}\n\nexport const AskAnyshiftCard = ({ context, scope }: 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 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 · ${localScope.target}`}\n />\n <Button\n type=\"button\"\n size=\"small\"\n disabled={loading}\n onClick={() => setScopeRemoved(true)}\n aria-label={`Remove ${localScope.target} 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 ${restorableScope.target} 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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"}
|
|
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';\nimport { isValidAskResourceId } from './askScope';\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}\n\nexport const AskAnyshiftCard = ({ context, scope }: 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 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 · ${localScope.target}`}\n />\n <Button\n type=\"button\"\n size=\"small\"\n disabled={loading}\n onClick={() => setScopeRemoved(true)}\n aria-label={`Remove ${localScope.target} 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 ${restorableScope.target} 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 ? JSON.stringify([identity, scope.target.trim(), scope.resourceId?.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 (scope.resourceId !== undefined && !isValidAskResourceId(scope.resourceId))\n 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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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { stringifyEntityRef } from '@backstage/catalog-model';
|
|
2
|
+
import { ANYSHIFT_RUNTIME_RESOURCE_ID_ANNOTATION, ANYSHIFT_RESOURCE_ID_ANNOTATION } from '@anyshift/backstage-plugin-anyshift-common';
|
|
2
3
|
import { isCloudResourceEntity, cloudResourceAskTarget, entityTarget } from '../entity/entityIdentity.esm.js';
|
|
3
4
|
|
|
4
5
|
const MAX_TARGET_CODE_POINTS = 200;
|
|
@@ -6,7 +7,12 @@ function askScopeForEntity(entity) {
|
|
|
6
7
|
const target = isCloudResourceEntity(entity) ? cloudResourceAskTarget(entity) : entityTarget(entity);
|
|
7
8
|
if (!target) return void 0;
|
|
8
9
|
if (!isValidTarget(target)) return void 0;
|
|
10
|
+
const annotations = entity.metadata.annotations ?? {};
|
|
11
|
+
const resourceId = annotations[ANYSHIFT_RUNTIME_RESOURCE_ID_ANNOTATION] ?? (isCloudResourceEntity(entity) ? void 0 : annotations[ANYSHIFT_RESOURCE_ID_ANNOTATION]);
|
|
12
|
+
if (resourceId !== void 0 && !isValidAskResourceId(resourceId))
|
|
13
|
+
return void 0;
|
|
9
14
|
return {
|
|
15
|
+
...resourceId === void 0 ? {} : { resourceId: resourceId.trim() },
|
|
10
16
|
entityRef: stringifyEntityRef(entity),
|
|
11
17
|
target
|
|
12
18
|
};
|
|
@@ -20,6 +26,9 @@ function hasControlCharacter(value) {
|
|
|
20
26
|
return codePoint !== void 0 && (codePoint <= 31 || codePoint >= 127 && codePoint <= 159);
|
|
21
27
|
});
|
|
22
28
|
}
|
|
29
|
+
function isValidAskResourceId(value) {
|
|
30
|
+
return Boolean(value.trim()) && value.trim().length <= 500 && !hasControlCharacter(value);
|
|
31
|
+
}
|
|
23
32
|
|
|
24
|
-
export { askScopeForEntity };
|
|
33
|
+
export { askScopeForEntity, isValidAskResourceId };
|
|
25
34
|
//# sourceMappingURL=askScope.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"askScope.esm.js","sources":["../../../src/components/ask/askScope.ts"],"sourcesContent":["import { stringifyEntityRef, type Entity } from '@backstage/catalog-model';\nimport type { AskScope } from '../../api/types';\nimport {\n cloudResourceAskTarget,\n entityTarget,\n isCloudResourceEntity,\n} from '../entity/entityIdentity';\n\nconst MAX_TARGET_CODE_POINTS = 200;\n\nexport function askScopeForEntity(entity: Entity): AskScope | undefined {\n const target = isCloudResourceEntity(entity)\n ? cloudResourceAskTarget(entity)\n : entityTarget(entity);\n if (!target) return undefined;\n if (!isValidTarget(target)) return undefined;\n\n return {\n entityRef: stringifyEntityRef(entity),\n target,\n };\n}\n\nfunction isValidTarget(target: string): boolean {\n return (\n Boolean(target.trim()) &&\n Array.from(target).length <= MAX_TARGET_CODE_POINTS &&\n !hasControlCharacter(target)\n );\n}\n\nfunction hasControlCharacter(value: string): boolean {\n return Array.from(value).some(character => {\n const codePoint = character.codePointAt(0);\n return (\n codePoint !== undefined &&\n (codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f))\n );\n });\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"askScope.esm.js","sources":["../../../src/components/ask/askScope.ts"],"sourcesContent":["import { stringifyEntityRef, type Entity } from '@backstage/catalog-model';\nimport {\n ANYSHIFT_RUNTIME_RESOURCE_ID_ANNOTATION,\n ANYSHIFT_RESOURCE_ID_ANNOTATION,\n} from '@anyshift/backstage-plugin-anyshift-common';\nimport type { AskScope } from '../../api/types';\nimport {\n cloudResourceAskTarget,\n entityTarget,\n isCloudResourceEntity,\n} from '../entity/entityIdentity';\n\nconst MAX_TARGET_CODE_POINTS = 200;\n\nexport function askScopeForEntity(entity: Entity): AskScope | undefined {\n const target = isCloudResourceEntity(entity)\n ? cloudResourceAskTarget(entity)\n : entityTarget(entity);\n if (!target) return undefined;\n if (!isValidTarget(target)) return undefined;\n\n const annotations = entity.metadata.annotations ?? {};\n const resourceId =\n annotations[ANYSHIFT_RUNTIME_RESOURCE_ID_ANNOTATION] ??\n (isCloudResourceEntity(entity)\n ? undefined\n : annotations[ANYSHIFT_RESOURCE_ID_ANNOTATION]);\n if (resourceId !== undefined && !isValidAskResourceId(resourceId))\n return undefined;\n\n return {\n ...(resourceId === undefined ? {} : { resourceId: resourceId.trim() }),\n entityRef: stringifyEntityRef(entity),\n target,\n };\n}\n\nfunction isValidTarget(target: string): boolean {\n return (\n Boolean(target.trim()) &&\n Array.from(target).length <= MAX_TARGET_CODE_POINTS &&\n !hasControlCharacter(target)\n );\n}\n\nfunction hasControlCharacter(value: string): boolean {\n return Array.from(value).some(character => {\n const codePoint = character.codePointAt(0);\n return (\n codePoint !== undefined &&\n (codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f))\n );\n });\n}\n\nexport function isValidAskResourceId(value: string): boolean {\n return (\n Boolean(value.trim()) &&\n value.trim().length <= 500 &&\n !hasControlCharacter(value)\n );\n}\n"],"names":[],"mappings":";;;;AAYA,MAAM,sBAAA,GAAyB,GAAA;AAExB,SAAS,kBAAkB,MAAA,EAAsC;AACtE,EAAA,MAAM,MAAA,GAAS,sBAAsB,MAAM,CAAA,GACvC,uBAAuB,MAAM,CAAA,GAC7B,aAAa,MAAM,CAAA;AACvB,EAAA,IAAI,CAAC,QAAQ,OAAO,MAAA;AACpB,EAAA,IAAI,CAAC,aAAA,CAAc,MAAM,CAAA,EAAG,OAAO,MAAA;AAEnC,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,QAAA,CAAS,WAAA,IAAe,EAAC;AACpD,EAAA,MAAM,UAAA,GACJ,YAAY,uCAAuC,CAAA,KAClD,sBAAsB,MAAM,CAAA,GACzB,MAAA,GACA,WAAA,CAAY,+BAA+B,CAAA,CAAA;AACjD,EAAA,IAAI,UAAA,KAAe,MAAA,IAAa,CAAC,oBAAA,CAAqB,UAAU,CAAA;AAC9D,IAAA,OAAO,MAAA;AAET,EAAA,OAAO;AAAA,IACL,GAAI,eAAe,MAAA,GAAY,KAAK,EAAE,UAAA,EAAY,UAAA,CAAW,IAAA,EAAK,EAAE;AAAA,IACpE,SAAA,EAAW,mBAAmB,MAAM,CAAA;AAAA,IACpC;AAAA,GACF;AACF;AAEA,SAAS,cAAc,MAAA,EAAyB;AAC9C,EAAA,OACE,OAAA,CAAQ,MAAA,CAAO,IAAA,EAAM,CAAA,IACrB,KAAA,CAAM,IAAA,CAAK,MAAM,CAAA,CAAE,MAAA,IAAU,sBAAA,IAC7B,CAAC,oBAAoB,MAAM,CAAA;AAE/B;AAEA,SAAS,oBAAoB,KAAA,EAAwB;AACnD,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,KAAK,CAAA,CAAE,KAAK,CAAA,SAAA,KAAa;AACzC,IAAA,MAAM,SAAA,GAAY,SAAA,CAAU,WAAA,CAAY,CAAC,CAAA;AACzC,IAAA,OACE,cAAc,MAAA,KACb,SAAA,IAAa,EAAA,IAAS,SAAA,IAAa,OAAQ,SAAA,IAAa,GAAA,CAAA;AAAA,EAE7D,CAAC,CAAA;AACH;AAEO,SAAS,qBAAqB,KAAA,EAAwB;AAC3D,EAAA,OACE,OAAA,CAAQ,KAAA,CAAM,IAAA,EAAM,CAAA,IACpB,KAAA,CAAM,IAAA,EAAK,CAAE,MAAA,IAAU,GAAA,IACvB,CAAC,mBAAA,CAAoB,KAAK,CAAA;AAE9B;;;;"}
|
package/dist/package.json.esm.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anyshift/backstage-plugin-anyshift",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.25",
|
|
4
4
|
"description": "Read-only Anyshift infrastructure context for Backstage",
|
|
5
5
|
"main": "dist/index.esm.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"clean": "backstage-cli package clean"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@anyshift/backstage-plugin-anyshift-common": "^0.1.0-beta.
|
|
48
|
+
"@anyshift/backstage-plugin-anyshift-common": "^0.1.0-beta.19",
|
|
49
49
|
"@backstage/catalog-model": "^1.9.0",
|
|
50
50
|
"@backstage/core-components": "^0.18.11",
|
|
51
51
|
"@backstage/frontend-plugin-api": "^0.17.2",
|