@manta-eu/client 0.1.9 → 0.1.10
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 +21 -0
- package/dist/generated/graphql.d.ts +658 -1
- package/dist/generated/graphql.d.ts.map +1 -1
- package/dist/generated/graphql.js +371 -0
- package/dist/generated/graphql.js.map +1 -0
- package/dist/graphql-clients.d.ts +10 -1
- package/dist/graphql-clients.d.ts.map +1 -1
- package/dist/graphql-clients.js +25 -3
- package/dist/graphql-clients.js.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/shared/action-document.js +1 -0
- package/dist/shared/action-document.js.map +1 -0
- package/dist/shared/action-plan.js +1 -0
- package/dist/shared/action-plan.js.map +1 -0
- package/dist/shared/agent-mode.js +1 -0
- package/dist/shared/agent-mode.js.map +1 -0
- package/dist/shared/agent-types.js +1 -0
- package/dist/shared/agent-types.js.map +1 -0
- package/dist/shared/chat-context.js +1 -0
- package/dist/shared/chat-context.js.map +1 -0
- package/dist/shared/chat-manager.d.ts +2 -0
- package/dist/shared/chat-manager.d.ts.map +1 -1
- package/dist/shared/chat-manager.js +3 -0
- package/dist/shared/chat-manager.js.map +1 -0
- package/dist/shared/chat-turn-errors.js +1 -0
- package/dist/shared/chat-turn-errors.js.map +1 -0
- package/dist/shared/constants.js +1 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/shared/conversation-starter-defaults.js +1 -0
- package/dist/shared/conversation-starter-defaults.js.map +1 -0
- package/dist/shared/datastore-id.js +1 -0
- package/dist/shared/datastore-id.js.map +1 -0
- package/dist/shared/datastore-path.js +1 -0
- package/dist/shared/datastore-path.js.map +1 -0
- package/dist/shared/duration.js +1 -0
- package/dist/shared/duration.js.map +1 -0
- package/dist/shared/email.js +1 -0
- package/dist/shared/email.js.map +1 -0
- package/dist/shared/entity-set.js +1 -0
- package/dist/shared/entity-set.js.map +1 -0
- package/dist/shared/error-utils.js +1 -0
- package/dist/shared/error-utils.js.map +1 -0
- package/dist/shared/explorer-paths.js +1 -0
- package/dist/shared/explorer-paths.js.map +1 -0
- package/dist/shared/fileIri.js +1 -0
- package/dist/shared/fileIri.js.map +1 -0
- package/dist/shared/index.js +1 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/inferal-stream.js +1 -0
- package/dist/shared/inferal-stream.js.map +1 -0
- package/dist/shared/live-context.js +1 -0
- package/dist/shared/live-context.js.map +1 -0
- package/dist/shared/maintenance-schedule.js +1 -0
- package/dist/shared/maintenance-schedule.js.map +1 -0
- package/dist/shared/memory-citation-sampling.js +1 -0
- package/dist/shared/memory-citation-sampling.js.map +1 -0
- package/dist/shared/memory-confidence.js +1 -0
- package/dist/shared/memory-confidence.js.map +1 -0
- package/dist/shared/memory-consolidation-limits.js +1 -0
- package/dist/shared/memory-consolidation-limits.js.map +1 -0
- package/dist/shared/memory-dates.js +1 -0
- package/dist/shared/memory-dates.js.map +1 -0
- package/dist/shared/memory-decay.js +1 -0
- package/dist/shared/memory-decay.js.map +1 -0
- package/dist/shared/memory-diversity.js +1 -0
- package/dist/shared/memory-diversity.js.map +1 -0
- package/dist/shared/memory-entity-recall.js +1 -0
- package/dist/shared/memory-entity-recall.js.map +1 -0
- package/dist/shared/memory-importance.js +1 -0
- package/dist/shared/memory-importance.js.map +1 -0
- package/dist/shared/memory-keyword-recall.js +1 -0
- package/dist/shared/memory-keyword-recall.js.map +1 -0
- package/dist/shared/memory-kind-iris.js +1 -0
- package/dist/shared/memory-kind-iris.js.map +1 -0
- package/dist/shared/memory-preload-gate.js +1 -0
- package/dist/shared/memory-preload-gate.js.map +1 -0
- package/dist/shared/memory-sources.js +1 -0
- package/dist/shared/memory-sources.js.map +1 -0
- package/dist/shared/memory-teams.js +1 -0
- package/dist/shared/memory-teams.js.map +1 -0
- package/dist/shared/memory-token-budget.js +1 -0
- package/dist/shared/memory-token-budget.js.map +1 -0
- package/dist/shared/memory-volatility.js +1 -0
- package/dist/shared/memory-volatility.js.map +1 -0
- package/dist/shared/message-utils.js +1 -0
- package/dist/shared/message-utils.js.map +1 -0
- package/dist/shared/model.js +1 -0
- package/dist/shared/model.js.map +1 -0
- package/dist/shared/org-roles.js +1 -0
- package/dist/shared/org-roles.js.map +1 -0
- package/dist/shared/page-context.js +1 -0
- package/dist/shared/page-context.js.map +1 -0
- package/dist/shared/permissions.js +1 -0
- package/dist/shared/permissions.js.map +1 -0
- package/dist/shared/questionnaire.js +1 -0
- package/dist/shared/questionnaire.js.map +1 -0
- package/dist/shared/rdf-namespaces.js +1 -0
- package/dist/shared/rdf-namespaces.js.map +1 -0
- package/dist/shared/rule-iri.js +1 -0
- package/dist/shared/rule-iri.js.map +1 -0
- package/dist/shared/rule-search.js +1 -0
- package/dist/shared/rule-search.js.map +1 -0
- package/dist/shared/session-types.js +1 -0
- package/dist/shared/session-types.js.map +1 -0
- package/dist/shared/stakeholder-iri.js +1 -0
- package/dist/shared/stakeholder-iri.js.map +1 -0
- package/dist/shared/team-activation.js +1 -0
- package/dist/shared/team-activation.js.map +1 -0
- package/dist/shared/team-filters.js +1 -0
- package/dist/shared/team-filters.js.map +1 -0
- package/dist/shared/team.js +1 -0
- package/dist/shared/team.js.map +1 -0
- package/dist/shared/tools/coercers.js +1 -0
- package/dist/shared/tools/coercers.js.map +1 -0
- package/dist/shared/tools/index.js +1 -0
- package/dist/shared/tools/index.js.map +1 -0
- package/dist/shared/tools/metadata.js +1 -0
- package/dist/shared/tools/metadata.js.map +1 -0
- package/dist/shared/tools/test-triple.js +1 -0
- package/dist/shared/tools/test-triple.js.map +1 -0
- package/dist/shared/tools/types.js +1 -0
- package/dist/shared/tools/types.js.map +1 -0
- package/dist/shared/upload.js +1 -0
- package/dist/shared/upload.js.map +1 -0
- package/dist/shared/website-url.js +1 -0
- package/dist/shared/website-url.js.map +1 -0
- package/dist/shared/workspace-artifacts.js +1 -0
- package/dist/shared/workspace-artifacts.js.map +1 -0
- package/dist/shared/writable-shape-query.js +1 -0
- package/dist/shared/writable-shape-query.js.map +1 -0
- package/dist/types/jsonld.js +1 -0
- package/dist/types/jsonld.js.map +1 -0
- package/dist/types/sparql-types.js +1 -0
- package/dist/types/sparql-types.js.map +1 -0
- package/package.json +11 -6
- package/src/generated/graphql.ts +11329 -0
- package/src/graphql-clients.ts +67 -0
- package/src/index.ts +2 -0
- package/src/shared/action-document.ts +56 -0
- package/src/shared/action-plan.ts +1 -0
- package/src/shared/agent-mode.ts +46 -0
- package/src/shared/agent-types.ts +46 -0
- package/src/shared/chat-context.ts +47 -0
- package/src/shared/chat-manager.ts +197 -0
- package/src/shared/chat-turn-errors.ts +25 -0
- package/src/shared/constants.ts +17 -0
- package/src/shared/conversation-starter-defaults.ts +27 -0
- package/src/shared/datastore-id.ts +25 -0
- package/src/shared/datastore-path.ts +80 -0
- package/src/shared/duration.ts +61 -0
- package/src/shared/email.ts +54 -0
- package/src/shared/entity-set.ts +33 -0
- package/src/shared/error-utils.ts +79 -0
- package/src/shared/explorer-paths.ts +9 -0
- package/src/shared/fileIri.ts +25 -0
- package/src/shared/index.ts +31 -0
- package/src/shared/inferal-stream.ts +2 -0
- package/src/shared/live-context.ts +15 -0
- package/src/shared/maintenance-schedule.ts +47 -0
- package/src/shared/memory-citation-sampling.ts +26 -0
- package/src/shared/memory-confidence.ts +8 -0
- package/src/shared/memory-consolidation-limits.ts +9 -0
- package/src/shared/memory-dates.ts +7 -0
- package/src/shared/memory-decay.ts +70 -0
- package/src/shared/memory-diversity.ts +55 -0
- package/src/shared/memory-entity-recall.ts +26 -0
- package/src/shared/memory-importance.ts +12 -0
- package/src/shared/memory-keyword-recall.ts +149 -0
- package/src/shared/memory-kind-iris.ts +36 -0
- package/src/shared/memory-preload-gate.ts +150 -0
- package/src/shared/memory-sources.ts +5 -0
- package/src/shared/memory-teams.ts +3 -0
- package/src/shared/memory-token-budget.ts +31 -0
- package/src/shared/memory-volatility.ts +90 -0
- package/src/shared/message-utils.ts +37 -0
- package/src/shared/model.ts +117 -0
- package/src/shared/org-roles.ts +21 -0
- package/src/shared/page-context.ts +7 -0
- package/src/shared/permissions.ts +19 -0
- package/src/shared/questionnaire.ts +76 -0
- package/src/shared/rdf-namespaces.ts +62 -0
- package/src/shared/rule-iri.ts +15 -0
- package/src/shared/rule-search.ts +1 -0
- package/src/shared/session-types.ts +14 -0
- package/src/shared/stakeholder-iri.ts +23 -0
- package/src/shared/team-activation.ts +9 -0
- package/src/shared/team-filters.ts +33 -0
- package/src/shared/team.ts +243 -0
- package/src/shared/tools/coercers.ts +82 -0
- package/src/shared/tools/index.ts +49 -0
- package/src/shared/tools/metadata.ts +205 -0
- package/src/shared/tools/test-triple.ts +33 -0
- package/src/shared/tools/types.ts +302 -0
- package/src/shared/upload.ts +57 -0
- package/src/shared/website-url.ts +32 -0
- package/src/shared/workspace-artifacts.ts +68 -0
- package/src/shared/writable-shape-query.ts +24 -0
- package/src/types/jsonld.ts +19 -0
- package/src/types/sparql-types.ts +10 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const requestUserInputToolName = "requestUserInput";
|
|
4
|
+
export const requestUserInputToolPartType = `tool-${requestUserInputToolName}` as const;
|
|
5
|
+
|
|
6
|
+
const questionnaireOptionSchema = z.object({
|
|
7
|
+
label: z.string().trim().min(1).max(40).describe("Short user-facing option label"),
|
|
8
|
+
description: z.string().trim().min(1).max(120).describe("One sentence explaining the option"),
|
|
9
|
+
recommended: z.boolean().optional().describe("Whether this is the recommended option"),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const questionnaireQuestionSchema = z
|
|
13
|
+
.object({
|
|
14
|
+
id: z
|
|
15
|
+
.string()
|
|
16
|
+
.trim()
|
|
17
|
+
.regex(/^[a-z][a-z0-9_]*$/)
|
|
18
|
+
.describe("Stable snake_case identifier for mapping the answer"),
|
|
19
|
+
header: z.string().trim().min(1).max(24).describe("Short heading of one to four words"),
|
|
20
|
+
question: z.string().trim().min(1).max(200).describe("Single-sentence question shown to the user"),
|
|
21
|
+
options: z
|
|
22
|
+
.array(questionnaireOptionSchema)
|
|
23
|
+
.min(1)
|
|
24
|
+
.max(4)
|
|
25
|
+
.describe("One to four mutually exclusive predefined answers"),
|
|
26
|
+
})
|
|
27
|
+
.superRefine(({ options }, context) => {
|
|
28
|
+
if (options.filter(({ recommended }) => recommended).length <= 1) return;
|
|
29
|
+
context.addIssue({
|
|
30
|
+
code: "custom",
|
|
31
|
+
message: "At most one option can be recommended",
|
|
32
|
+
path: ["options"],
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export const questionnaireInputSchema = z
|
|
37
|
+
.object({
|
|
38
|
+
questions: z.array(questionnaireQuestionSchema).min(1).max(3),
|
|
39
|
+
})
|
|
40
|
+
.superRefine(({ questions }, context) => {
|
|
41
|
+
const questionIds = new Set<string>();
|
|
42
|
+
questions.forEach(({ id }, index) => {
|
|
43
|
+
if (questionIds.has(id)) {
|
|
44
|
+
context.addIssue({
|
|
45
|
+
code: "custom",
|
|
46
|
+
message: "Question IDs must be unique",
|
|
47
|
+
path: ["questions", index, "id"],
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
questionIds.add(id);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const questionnaireAnswerSchema = z.discriminatedUnion("source", [
|
|
55
|
+
z.object({
|
|
56
|
+
questionId: z.string().trim().min(1),
|
|
57
|
+
source: z.literal("option"),
|
|
58
|
+
value: z.string().trim().min(1),
|
|
59
|
+
}),
|
|
60
|
+
z.object({
|
|
61
|
+
questionId: z.string().trim().min(1),
|
|
62
|
+
source: z.literal("other"),
|
|
63
|
+
value: z.string().trim().min(1),
|
|
64
|
+
}),
|
|
65
|
+
z.object({
|
|
66
|
+
questionId: z.string().trim().min(1),
|
|
67
|
+
source: z.literal("skipped"),
|
|
68
|
+
}),
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
export const questionnaireOutputSchema = z.object({
|
|
72
|
+
answers: z.array(questionnaireAnswerSchema).min(1).max(3),
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
export type QuestionnaireInput = z.infer<typeof questionnaireInputSchema>;
|
|
76
|
+
export type QuestionnaireOutput = z.infer<typeof questionnaireOutputSchema>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {
|
|
2
|
+
encodeIriLocalName as encodeIriLocalNameValue,
|
|
3
|
+
expandPrefix as expandPrefixIri,
|
|
4
|
+
iriLocalName as iriLocalNameValue,
|
|
5
|
+
iriNamespace as iriNamespaceValue,
|
|
6
|
+
rdfoxDefaultBaseIri as rdfoxDefaultBaseIriValue,
|
|
7
|
+
shaclGraphIri as shaclGraphIriValue,
|
|
8
|
+
} from "@manta-eu/rdf-lib/namespaces";
|
|
9
|
+
|
|
10
|
+
export const rulesGraphIri = `${rdfoxDefaultBaseIriValue}rules`;
|
|
11
|
+
|
|
12
|
+
// KGC uploads the realm ontology here (kgc/kgc/realms/lib/ontology.py: realm_base + "ontology").
|
|
13
|
+
export const ontologyGraphIri = expandPrefixIri(":ontology");
|
|
14
|
+
|
|
15
|
+
// Field mutability Inferal publishes on its property shapes (DAT-577).
|
|
16
|
+
export const writeLifecycle = {
|
|
17
|
+
predicate: expandPrefixIri("relay:writeLifecycle"),
|
|
18
|
+
readOnly: expandPrefixIri("relay:ReadOnly"),
|
|
19
|
+
createOnly: expandPrefixIri("relay:CreateOnly"),
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const nonDataGraphIris = [ontologyGraphIri, shaclGraphIriValue, rulesGraphIri];
|
|
23
|
+
|
|
24
|
+
export function mintInstanceIri(classIri: string, localId: string): string {
|
|
25
|
+
return `${iriNamespaceValue(classIri)}${encodeIriLocalNameValue(`${iriLocalNameValue(classIri)}_${localId}`)}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export {
|
|
29
|
+
baseIri,
|
|
30
|
+
compactUri,
|
|
31
|
+
decodeIriLocalName,
|
|
32
|
+
encodeIriLocalName,
|
|
33
|
+
encodeIriUnsafeChars,
|
|
34
|
+
expandPrefix,
|
|
35
|
+
formatEntityName,
|
|
36
|
+
formatIriForRdfox,
|
|
37
|
+
getNamespaceValues,
|
|
38
|
+
isFullIri,
|
|
39
|
+
isValidFullIri,
|
|
40
|
+
isIri,
|
|
41
|
+
isIsoDatetime,
|
|
42
|
+
infrastructureNamespaces,
|
|
43
|
+
iriLocalName,
|
|
44
|
+
iriNamespace,
|
|
45
|
+
isOwlNothing,
|
|
46
|
+
owlNothingIri,
|
|
47
|
+
isPrefixedIri,
|
|
48
|
+
labeledNamespaces,
|
|
49
|
+
type LabeledNamespacePrefix,
|
|
50
|
+
namespaces,
|
|
51
|
+
type NamespaceMeta,
|
|
52
|
+
nfo,
|
|
53
|
+
parseEntityUri,
|
|
54
|
+
prependMissingSparqlPrefixes,
|
|
55
|
+
rdfoxDefaultBaseIri,
|
|
56
|
+
shaclGraphIri,
|
|
57
|
+
sh,
|
|
58
|
+
toTurtlePrefixes,
|
|
59
|
+
validateFullIri,
|
|
60
|
+
wellKnownPredicates,
|
|
61
|
+
type IRI,
|
|
62
|
+
} from "@manta-eu/rdf-lib/namespaces";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const ruleNameMaxLength = 255;
|
|
2
|
+
|
|
3
|
+
export function sanitizeRuleName(value: string): string {
|
|
4
|
+
return value
|
|
5
|
+
.trim()
|
|
6
|
+
.replace(/[^a-zA-Z0-9_-]+/g, "_")
|
|
7
|
+
.replace(/^[-_]+|[-_]+$/g, "");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function normalizeRuleLocalName(value: string): string | null {
|
|
11
|
+
const sanitizedName = sanitizeRuleName(value);
|
|
12
|
+
if (!sanitizedName) return null;
|
|
13
|
+
|
|
14
|
+
return sanitizedName.startsWith("Rule_") ? sanitizedName : `Rule_${sanitizedName}`;
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const ruleSearchMaxLength = 200;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type User = {
|
|
2
|
+
id: string;
|
|
3
|
+
email: string;
|
|
4
|
+
name?: string | null | undefined;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
/** Structurally the same as `@manta-eu/ldo-ui`'s picker row, so either satisfies the other. */
|
|
8
|
+
export type Datastore = {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
depth?: number;
|
|
12
|
+
selectable?: boolean;
|
|
13
|
+
badge?: string;
|
|
14
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { decodeIriLocalName, encodeIriLocalName, expandPrefix } from "./rdf-namespaces";
|
|
2
|
+
|
|
3
|
+
export const userIriPrefix = expandPrefix(":User_");
|
|
4
|
+
export const teamIriPrefix = expandPrefix(":Team_");
|
|
5
|
+
|
|
6
|
+
export function getUserIri(userId: string): string {
|
|
7
|
+
return `${userIriPrefix}${encodeIriLocalName(userId)}`;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function parseUserIdFromIri(iri: string): string | null {
|
|
11
|
+
if (!iri.startsWith(userIriPrefix)) return null;
|
|
12
|
+
return decodeIriLocalName(iri.slice(userIriPrefix.length));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Team paths are stored encodeURIComponent'd, so re-encoding them here would orphan existing nodes
|
|
16
|
+
export function getTeamIri(path: string): string {
|
|
17
|
+
return `${teamIriPrefix}${encodeURIComponent(path)}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function parseTeamPathFromIri(iri: string): string | null {
|
|
21
|
+
if (!iri.startsWith(teamIriPrefix)) return null;
|
|
22
|
+
return decodeIriLocalName(iri.slice(teamIriPrefix.length));
|
|
23
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type ActivationAccessArgs = {
|
|
2
|
+
realmAllows: boolean;
|
|
3
|
+
flagEnabled: boolean | undefined;
|
|
4
|
+
wholeOrg: boolean;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export function canManageActivation({ realmAllows, flagEnabled, wholeOrg }: ActivationAccessArgs): boolean {
|
|
8
|
+
return realmAllows && flagEnabled === true && wholeOrg;
|
|
9
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { isPresent } from "@manta-eu/lib/present";
|
|
2
|
+
import { plainMemberRole, type OrgRoleDefinition } from "./org-roles";
|
|
3
|
+
|
|
4
|
+
export const allRoles = "all";
|
|
5
|
+
|
|
6
|
+
export type RoleFilter = string;
|
|
7
|
+
|
|
8
|
+
export type ActivationFilter = "all" | "enabled" | "disabled";
|
|
9
|
+
|
|
10
|
+
export const activationFilters: readonly ActivationFilter[] = ["all", "enabled", "disabled"];
|
|
11
|
+
|
|
12
|
+
export function matchesActivationFilter(entry: { enabled: boolean }, filter: ActivationFilter): boolean {
|
|
13
|
+
if (filter === "all") return true;
|
|
14
|
+
return entry.enabled === (filter === "enabled");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function matchesRoleFilter(
|
|
18
|
+
member: { roles: readonly string[] },
|
|
19
|
+
filter: RoleFilter,
|
|
20
|
+
roles: readonly OrgRoleDefinition[],
|
|
21
|
+
): boolean {
|
|
22
|
+
if (filter === allRoles) return true;
|
|
23
|
+
|
|
24
|
+
const held = roles.some((role) => member.roles.includes(role.id));
|
|
25
|
+
return filter === plainMemberRole ? !held : member.roles.includes(filter);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function matchesSearch(haystack: (string | undefined)[], query: string | undefined): boolean {
|
|
29
|
+
if (!isPresent(query)) return true;
|
|
30
|
+
|
|
31
|
+
const needle = query.trim().toLowerCase();
|
|
32
|
+
return haystack.some((value) => (value ?? "").toLowerCase().includes(needle));
|
|
33
|
+
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { isPresent } from "@manta-eu/lib/present";
|
|
2
|
+
import { splitEvery } from "ramda";
|
|
3
|
+
|
|
4
|
+
export type TeamRole = string;
|
|
5
|
+
|
|
6
|
+
export type TeamMember = {
|
|
7
|
+
id: string;
|
|
8
|
+
email?: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
roles: string[];
|
|
11
|
+
pending: boolean;
|
|
12
|
+
expired?: boolean;
|
|
13
|
+
inviteUrl?: string;
|
|
14
|
+
teams: string[];
|
|
15
|
+
federated?: boolean;
|
|
16
|
+
// Keycloak deletes a managed member's account when they leave the organization.
|
|
17
|
+
managed?: true;
|
|
18
|
+
enabled: boolean;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type TeamOrganization = {
|
|
22
|
+
alias?: string;
|
|
23
|
+
name?: string;
|
|
24
|
+
managed: boolean;
|
|
25
|
+
mirrored: boolean;
|
|
26
|
+
inviteCarriesGrants?: true;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type TeamRoster = {
|
|
30
|
+
members: TeamMember[];
|
|
31
|
+
truncated: boolean;
|
|
32
|
+
organization?: TeamOrganization;
|
|
33
|
+
total?: number;
|
|
34
|
+
unfilteredTotal?: number;
|
|
35
|
+
hasMore?: boolean;
|
|
36
|
+
snapshot?: string;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const rosterPageSize = 20;
|
|
40
|
+
|
|
41
|
+
export const maxRosterPageSize = 100;
|
|
42
|
+
|
|
43
|
+
export type TeamGroup = { name: string; path: string; depth: number; selectable?: boolean };
|
|
44
|
+
|
|
45
|
+
export type UserLabelSource = { id: string; name?: string; email?: string; username?: string };
|
|
46
|
+
|
|
47
|
+
export function userLabel(user: UserLabelSource): string {
|
|
48
|
+
return user.name ?? user.email ?? user.username ?? user.id;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type DirectoryMembership = { org: string; name?: string; groups: string[]; managed?: true };
|
|
52
|
+
|
|
53
|
+
export type DirectoryUser = {
|
|
54
|
+
id: string;
|
|
55
|
+
username?: string;
|
|
56
|
+
email?: string;
|
|
57
|
+
name?: string;
|
|
58
|
+
firstName?: string;
|
|
59
|
+
lastName?: string;
|
|
60
|
+
memberships: DirectoryMembership[];
|
|
61
|
+
pending?: boolean;
|
|
62
|
+
inviteUrl?: string;
|
|
63
|
+
invitedTo?: DirectoryMembership[];
|
|
64
|
+
federated?: boolean;
|
|
65
|
+
nameReadOnly?: boolean;
|
|
66
|
+
enabled: boolean;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export type TeamDirectory = {
|
|
70
|
+
users: DirectoryUser[];
|
|
71
|
+
truncated: boolean;
|
|
72
|
+
/** Rows matching the query across the realm, or undefined when Keycloak could not count them. */
|
|
73
|
+
total?: number;
|
|
74
|
+
hasMore: boolean;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const directoryPageSize = 20;
|
|
78
|
+
|
|
79
|
+
export const auth0NameLimits = { part: 150, whole: 300 } as const;
|
|
80
|
+
|
|
81
|
+
export const maxDirectoryPageSize = 100;
|
|
82
|
+
|
|
83
|
+
export type AssignableGroup = { path: string; name: string; depth: number; selectable?: boolean };
|
|
84
|
+
|
|
85
|
+
// `groups` is absent until the org's tree is fetched on demand: loading every org's up front is O(orgs x groups).
|
|
86
|
+
export type AssignableOrganization = {
|
|
87
|
+
alias: string;
|
|
88
|
+
name?: string;
|
|
89
|
+
wholeOrg?: boolean;
|
|
90
|
+
groups?: AssignableGroup[];
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export type AssignTarget = { org: string; group?: string };
|
|
94
|
+
|
|
95
|
+
export type BulkMutationFailure = { id: string; message: string };
|
|
96
|
+
|
|
97
|
+
export type AssignmentOutcome = "assigned" | "already" | "failed";
|
|
98
|
+
|
|
99
|
+
export type AssignmentResult = AssignTarget & {
|
|
100
|
+
userId: string;
|
|
101
|
+
outcome: AssignmentOutcome;
|
|
102
|
+
message?: string;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export type AssignmentSummary = {
|
|
106
|
+
results: AssignmentResult[];
|
|
107
|
+
assigned: number;
|
|
108
|
+
skipped: number;
|
|
109
|
+
failed: number;
|
|
110
|
+
roleFailures: BulkMutationFailure[];
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export type AssignmentRole = { userId: string; role: string };
|
|
114
|
+
|
|
115
|
+
export type BulkMutationResult = {
|
|
116
|
+
attempted: number;
|
|
117
|
+
changed: number;
|
|
118
|
+
failures: BulkMutationFailure[];
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export type BulkUserOrgPair = { userId: string; org?: string };
|
|
122
|
+
|
|
123
|
+
export function bulkPairId(pair: BulkUserOrgPair): string {
|
|
124
|
+
return `${pair.userId}:${pair.org}`;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function pathSegments(path: string): string[] {
|
|
128
|
+
return path.split("/").filter(isPresent);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Mirrors manta-clj's normalization, so client-side comparisons match its replies. */
|
|
132
|
+
export function normalizeGroupPath(path: string): string {
|
|
133
|
+
return `/${pathSegments(path).join("/")}`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function namesAGroup(path: string | undefined): boolean {
|
|
137
|
+
return path !== undefined && isPresent(pathSegments(path));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function ancestorPaths(path: string): string[] {
|
|
141
|
+
const segments = pathSegments(path);
|
|
142
|
+
return segments.slice(0, -1).map((_, index) => normalizeGroupPath(segments.slice(0, index + 1).join("/")));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Keycloak forbids "/" in group names, so the last segment is unambiguously the group's own name.
|
|
146
|
+
export function groupNameFromPath(path: string): string {
|
|
147
|
+
return pathSegments(path).at(-1) ?? path;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function groupDepthFromPath(path: string): number {
|
|
151
|
+
return pathSegments(path).length;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function chunk<T>(items: T[], size: number): T[][] {
|
|
155
|
+
return splitEvery(size, items);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export const waveSize = 8;
|
|
159
|
+
|
|
160
|
+
export async function mapInWaves<T, R>(items: T[], fn: (item: T) => Promise<R>, size: number = waveSize): Promise<R[]> {
|
|
161
|
+
const results: R[] = [];
|
|
162
|
+
for (const wave of chunk(items, size)) {
|
|
163
|
+
results.push(...(await Promise.all(wave.map(fn))));
|
|
164
|
+
}
|
|
165
|
+
return results;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export const maxAssignmentPairs = 200;
|
|
169
|
+
|
|
170
|
+
export const maxBulkMembers = 300;
|
|
171
|
+
|
|
172
|
+
export function assignTargetKey(target: AssignTarget): string {
|
|
173
|
+
return namesAGroup(target.group) ? `${target.org}${normalizeGroupPath(target.group ?? "")}` : target.org;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export type InviteOutcome = "invited" | "already" | "failed";
|
|
177
|
+
|
|
178
|
+
export type InviteGrantOutcome = "applied" | "recorded" | "dropped";
|
|
179
|
+
|
|
180
|
+
export type InviteResult = {
|
|
181
|
+
email: string;
|
|
182
|
+
id?: string;
|
|
183
|
+
pending?: boolean;
|
|
184
|
+
outcome: InviteOutcome;
|
|
185
|
+
message?: string;
|
|
186
|
+
grant?: InviteGrantOutcome;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
export type InviteSummary = {
|
|
190
|
+
results: InviteResult[];
|
|
191
|
+
invited: number;
|
|
192
|
+
skipped: number;
|
|
193
|
+
failed: number;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// Same shape as metric.spec.core/email-regex, so client and server reject the same addresses.
|
|
197
|
+
const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}$/;
|
|
198
|
+
|
|
199
|
+
export function isEmailAddress(value: string): boolean {
|
|
200
|
+
return emailPattern.test(value);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const pastedContact = /([^,;<]*)<([^>]*)>/g;
|
|
204
|
+
|
|
205
|
+
function extractContacts(raw: string): { entries: string[]; rest: string } {
|
|
206
|
+
const entries: string[] = [];
|
|
207
|
+
const rest = raw.replace(pastedContact, (match, _label: string, address: string) => {
|
|
208
|
+
const trimmed = address.trim();
|
|
209
|
+
entries.push(isEmailAddress(trimmed) ? trimmed : match.trim());
|
|
210
|
+
return " ";
|
|
211
|
+
});
|
|
212
|
+
return { entries, rest };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export type EmailListParse = {
|
|
216
|
+
emails: string[];
|
|
217
|
+
invalid: string[];
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
/** Folds like manta-clj's distinct-emails: case-insensitively, first spelling wins. */
|
|
221
|
+
export function parseEmailList(raw: string): EmailListParse {
|
|
222
|
+
const seen = new Set<string>();
|
|
223
|
+
const emails: string[] = [];
|
|
224
|
+
const invalid: string[] = [];
|
|
225
|
+
|
|
226
|
+
function take(entry: string): void {
|
|
227
|
+
if (!isPresent(entry)) return;
|
|
228
|
+
if (!isEmailAddress(entry)) {
|
|
229
|
+
if (!invalid.includes(entry)) invalid.push(entry);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const key = entry.toLowerCase();
|
|
233
|
+
if (seen.has(key)) return;
|
|
234
|
+
seen.add(key);
|
|
235
|
+
emails.push(entry);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const { entries, rest } = extractContacts(raw);
|
|
239
|
+
for (const entry of entries) take(entry);
|
|
240
|
+
for (const entry of rest.split(/[,;\s]+/)) take(entry.trim());
|
|
241
|
+
|
|
242
|
+
return { emails, invalid };
|
|
243
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
RDFoxFactsOutput,
|
|
3
|
+
ShowEntitiesOutput,
|
|
4
|
+
SparqlJsonResults,
|
|
5
|
+
ToolErrorResult,
|
|
6
|
+
ToolName,
|
|
7
|
+
ToolOutputCoercer,
|
|
8
|
+
ToolOutputType,
|
|
9
|
+
} from "./types";
|
|
10
|
+
import { isJsonLdGraphDocument } from "#types/jsonld";
|
|
11
|
+
|
|
12
|
+
export function isErrorToolResult(data: unknown): data is ToolErrorResult {
|
|
13
|
+
return typeof data === "object" && data !== null && "is_error" in data && (data as ToolErrorResult).is_error === true;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function isSparqlJsonResults(data: unknown): data is SparqlJsonResults {
|
|
17
|
+
return (
|
|
18
|
+
typeof data === "object" &&
|
|
19
|
+
data !== null &&
|
|
20
|
+
"head" in data &&
|
|
21
|
+
"results" in data &&
|
|
22
|
+
typeof (data as SparqlJsonResults).head === "object" &&
|
|
23
|
+
typeof (data as SparqlJsonResults).results === "object"
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function coerceWith<T>(
|
|
28
|
+
toolName: ToolName,
|
|
29
|
+
raw: unknown,
|
|
30
|
+
guards: Array<(value: unknown) => value is T>,
|
|
31
|
+
): T | ToolErrorResult {
|
|
32
|
+
if (typeof raw === "string") {
|
|
33
|
+
try {
|
|
34
|
+
raw = JSON.parse(raw);
|
|
35
|
+
} catch {
|
|
36
|
+
return { is_error: true, content: `Failed to parse tool output: ${raw}` };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (isErrorToolResult(raw)) return raw;
|
|
40
|
+
for (const guard of guards) {
|
|
41
|
+
if (guard(raw)) return raw;
|
|
42
|
+
}
|
|
43
|
+
return { is_error: true, content: `Unexpected ${toolName} output format` };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function coerceRDFoxFactsOutput(raw: unknown): RDFoxFactsOutput {
|
|
47
|
+
return coerceWith<RDFoxFactsOutput>("getRDFoxFacts", raw, [isSparqlJsonResults, isJsonLdGraphDocument]);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function isShowEntitiesResult(data: unknown): data is Exclude<ShowEntitiesOutput, ToolErrorResult> {
|
|
51
|
+
if (typeof data !== "object" || data === null) return false;
|
|
52
|
+
if (!("entityIris" in data) || !("graph" in data)) return false;
|
|
53
|
+
return (
|
|
54
|
+
Array.isArray(data.entityIris) &&
|
|
55
|
+
data.entityIris.every((iri) => typeof iri === "string") &&
|
|
56
|
+
isJsonLdGraphDocument(data.graph)
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function coerceShowEntitiesOutput(raw: unknown): ShowEntitiesOutput {
|
|
61
|
+
return coerceWith<ShowEntitiesOutput>("showEntities", raw, [isShowEntitiesResult]);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const coercers: Partial<Record<ToolName, ToolOutputCoercer<ToolName>>> = {
|
|
65
|
+
getRDFoxFacts: coerceRDFoxFactsOutput as ToolOutputCoercer<"getRDFoxFacts">,
|
|
66
|
+
showEntities: coerceShowEntitiesOutput as ToolOutputCoercer<"showEntities">,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export function coerceToolOutput<T extends ToolName>(toolName: T, raw: unknown): ToolOutputType<T> {
|
|
70
|
+
const coercer = coercers[toolName] as ToolOutputCoercer<T> | undefined;
|
|
71
|
+
if (coercer) {
|
|
72
|
+
return coercer(raw);
|
|
73
|
+
}
|
|
74
|
+
if (typeof raw === "string") {
|
|
75
|
+
try {
|
|
76
|
+
return JSON.parse(raw) as ToolOutputType<T>;
|
|
77
|
+
} catch {
|
|
78
|
+
return raw as ToolOutputType<T>;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return raw as ToolOutputType<T>;
|
|
82
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export { coerceToolOutput, isErrorToolResult, isShowEntitiesResult, isSparqlJsonResults } from "./coercers";
|
|
2
|
+
export {
|
|
3
|
+
allToolNames,
|
|
4
|
+
assertValidToolName,
|
|
5
|
+
getHumanToolName,
|
|
6
|
+
getSkillToolLabel,
|
|
7
|
+
getToolMetadata,
|
|
8
|
+
getToolUIPartLabel,
|
|
9
|
+
isValidToolName,
|
|
10
|
+
toolMetadata,
|
|
11
|
+
} from "./metadata";
|
|
12
|
+
export type {
|
|
13
|
+
ActionPlanShowcaseInput,
|
|
14
|
+
ActionPlanShowcaseOutput,
|
|
15
|
+
ActionPlanStatus,
|
|
16
|
+
AddRDFoxFactsInput,
|
|
17
|
+
AddRDFoxFactsOutput,
|
|
18
|
+
CancelScheduleInput,
|
|
19
|
+
CancelScheduleOutput,
|
|
20
|
+
ExecuteActionPlanInput,
|
|
21
|
+
ExecuteActionPlanOutput,
|
|
22
|
+
ExplainRDFoxRulesInput,
|
|
23
|
+
ExplainRDFoxRulesOutput,
|
|
24
|
+
GenerateChartInput,
|
|
25
|
+
GenerateChartOutput,
|
|
26
|
+
GetRDFoxRulesInput,
|
|
27
|
+
GetRDFoxRulesOutput,
|
|
28
|
+
ListScheduledTasksInput,
|
|
29
|
+
ListScheduledTasksOutput,
|
|
30
|
+
RDFoxFactsInput,
|
|
31
|
+
RDFoxFactsOutput,
|
|
32
|
+
ScheduleTaskInput,
|
|
33
|
+
ScheduleTaskOutput,
|
|
34
|
+
ShowEntitiesInput,
|
|
35
|
+
ShowEntitiesOutput,
|
|
36
|
+
SparqlJsonBinding,
|
|
37
|
+
SparqlJsonResults,
|
|
38
|
+
SparqlValue,
|
|
39
|
+
ToolCategory,
|
|
40
|
+
ToolDefinition,
|
|
41
|
+
ToolDefinitions,
|
|
42
|
+
ToolErrorResult,
|
|
43
|
+
ToolInputSchema,
|
|
44
|
+
ToolMetadata,
|
|
45
|
+
ToolName,
|
|
46
|
+
ToolOutput,
|
|
47
|
+
ToolOutputCoercer,
|
|
48
|
+
ToolOutputType,
|
|
49
|
+
} from "./types";
|