@manta-eu/client 0.1.9 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/README.md +21 -0
  2. package/dist/generated/graphql.d.ts +1132 -2
  3. package/dist/generated/graphql.d.ts.map +1 -1
  4. package/dist/generated/graphql.js +637 -0
  5. package/dist/generated/graphql.js.map +1 -0
  6. package/dist/graphql-clients.d.ts +10 -1
  7. package/dist/graphql-clients.d.ts.map +1 -1
  8. package/dist/graphql-clients.js +25 -3
  9. package/dist/graphql-clients.js.map +1 -0
  10. package/dist/index.js +1 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/shared/action-document.js +1 -0
  13. package/dist/shared/action-document.js.map +1 -0
  14. package/dist/shared/action-plan.js +1 -0
  15. package/dist/shared/action-plan.js.map +1 -0
  16. package/dist/shared/agent-mode.js +1 -0
  17. package/dist/shared/agent-mode.js.map +1 -0
  18. package/dist/shared/agent-types.js +1 -0
  19. package/dist/shared/agent-types.js.map +1 -0
  20. package/dist/shared/chat-context.js +1 -0
  21. package/dist/shared/chat-context.js.map +1 -0
  22. package/dist/shared/chat-manager.d.ts +6 -0
  23. package/dist/shared/chat-manager.d.ts.map +1 -1
  24. package/dist/shared/chat-manager.js +5 -0
  25. package/dist/shared/chat-manager.js.map +1 -0
  26. package/dist/shared/chat-turn-errors.d.ts +10 -0
  27. package/dist/shared/chat-turn-errors.d.ts.map +1 -1
  28. package/dist/shared/chat-turn-errors.js +11 -0
  29. package/dist/shared/chat-turn-errors.js.map +1 -0
  30. package/dist/shared/constants.d.ts +1 -0
  31. package/dist/shared/constants.d.ts.map +1 -1
  32. package/dist/shared/constants.js +2 -0
  33. package/dist/shared/constants.js.map +1 -0
  34. package/dist/shared/conversation-starter-defaults.js +1 -0
  35. package/dist/shared/conversation-starter-defaults.js.map +1 -0
  36. package/dist/shared/datastore-id.js +1 -0
  37. package/dist/shared/datastore-id.js.map +1 -0
  38. package/dist/shared/datastore-path.js +1 -0
  39. package/dist/shared/datastore-path.js.map +1 -0
  40. package/dist/shared/duration.js +1 -0
  41. package/dist/shared/duration.js.map +1 -0
  42. package/dist/shared/email.js +1 -0
  43. package/dist/shared/email.js.map +1 -0
  44. package/dist/shared/entity-set.js +1 -0
  45. package/dist/shared/entity-set.js.map +1 -0
  46. package/dist/shared/error-utils.js +1 -0
  47. package/dist/shared/error-utils.js.map +1 -0
  48. package/dist/shared/explorer-paths.js +1 -0
  49. package/dist/shared/explorer-paths.js.map +1 -0
  50. package/dist/shared/fileIri.js +1 -0
  51. package/dist/shared/fileIri.js.map +1 -0
  52. package/dist/shared/index.js +1 -0
  53. package/dist/shared/index.js.map +1 -0
  54. package/dist/shared/inferal-stream.js +1 -0
  55. package/dist/shared/inferal-stream.js.map +1 -0
  56. package/dist/shared/live-context.js +1 -0
  57. package/dist/shared/live-context.js.map +1 -0
  58. package/dist/shared/maintenance-schedule.js +1 -0
  59. package/dist/shared/maintenance-schedule.js.map +1 -0
  60. package/dist/shared/memory-citation-sampling.js +1 -0
  61. package/dist/shared/memory-citation-sampling.js.map +1 -0
  62. package/dist/shared/memory-confidence.js +1 -0
  63. package/dist/shared/memory-confidence.js.map +1 -0
  64. package/dist/shared/memory-consolidation-limits.js +1 -0
  65. package/dist/shared/memory-consolidation-limits.js.map +1 -0
  66. package/dist/shared/memory-dates.js +1 -0
  67. package/dist/shared/memory-dates.js.map +1 -0
  68. package/dist/shared/memory-decay.js +1 -0
  69. package/dist/shared/memory-decay.js.map +1 -0
  70. package/dist/shared/memory-diversity.js +1 -0
  71. package/dist/shared/memory-diversity.js.map +1 -0
  72. package/dist/shared/memory-entity-recall.js +1 -0
  73. package/dist/shared/memory-entity-recall.js.map +1 -0
  74. package/dist/shared/memory-importance.js +1 -0
  75. package/dist/shared/memory-importance.js.map +1 -0
  76. package/dist/shared/memory-keyword-recall.js +1 -0
  77. package/dist/shared/memory-keyword-recall.js.map +1 -0
  78. package/dist/shared/memory-kind-iris.js +1 -0
  79. package/dist/shared/memory-kind-iris.js.map +1 -0
  80. package/dist/shared/memory-preload-gate.js +1 -0
  81. package/dist/shared/memory-preload-gate.js.map +1 -0
  82. package/dist/shared/memory-sources.js +1 -0
  83. package/dist/shared/memory-sources.js.map +1 -0
  84. package/dist/shared/memory-teams.js +1 -0
  85. package/dist/shared/memory-teams.js.map +1 -0
  86. package/dist/shared/memory-token-budget.js +1 -0
  87. package/dist/shared/memory-token-budget.js.map +1 -0
  88. package/dist/shared/memory-volatility.js +1 -0
  89. package/dist/shared/memory-volatility.js.map +1 -0
  90. package/dist/shared/message-utils.js +1 -0
  91. package/dist/shared/message-utils.js.map +1 -0
  92. package/dist/shared/model.js +1 -0
  93. package/dist/shared/model.js.map +1 -0
  94. package/dist/shared/org-roles.js +1 -0
  95. package/dist/shared/org-roles.js.map +1 -0
  96. package/dist/shared/page-context.js +1 -0
  97. package/dist/shared/page-context.js.map +1 -0
  98. package/dist/shared/permissions.js +1 -0
  99. package/dist/shared/permissions.js.map +1 -0
  100. package/dist/shared/questionnaire.js +1 -0
  101. package/dist/shared/questionnaire.js.map +1 -0
  102. package/dist/shared/rdf-namespaces.js +1 -0
  103. package/dist/shared/rdf-namespaces.js.map +1 -0
  104. package/dist/shared/rule-iri.js +1 -0
  105. package/dist/shared/rule-iri.js.map +1 -0
  106. package/dist/shared/rule-search.js +1 -0
  107. package/dist/shared/rule-search.js.map +1 -0
  108. package/dist/shared/session-types.js +1 -0
  109. package/dist/shared/session-types.js.map +1 -0
  110. package/dist/shared/stakeholder-iri.js +1 -0
  111. package/dist/shared/stakeholder-iri.js.map +1 -0
  112. package/dist/shared/team-activation.js +1 -0
  113. package/dist/shared/team-activation.js.map +1 -0
  114. package/dist/shared/team-filters.js +1 -0
  115. package/dist/shared/team-filters.js.map +1 -0
  116. package/dist/shared/team.d.ts +1 -0
  117. package/dist/shared/team.d.ts.map +1 -1
  118. package/dist/shared/team.js +1 -0
  119. package/dist/shared/team.js.map +1 -0
  120. package/dist/shared/tools/coercers.js +1 -0
  121. package/dist/shared/tools/coercers.js.map +1 -0
  122. package/dist/shared/tools/index.js +1 -0
  123. package/dist/shared/tools/index.js.map +1 -0
  124. package/dist/shared/tools/metadata.js +1 -0
  125. package/dist/shared/tools/metadata.js.map +1 -0
  126. package/dist/shared/tools/test-triple.js +1 -0
  127. package/dist/shared/tools/test-triple.js.map +1 -0
  128. package/dist/shared/tools/types.js +1 -0
  129. package/dist/shared/tools/types.js.map +1 -0
  130. package/dist/shared/upload.js +1 -0
  131. package/dist/shared/upload.js.map +1 -0
  132. package/dist/shared/website-url.js +1 -0
  133. package/dist/shared/website-url.js.map +1 -0
  134. package/dist/shared/workspace-artifacts.js +1 -0
  135. package/dist/shared/workspace-artifacts.js.map +1 -0
  136. package/dist/shared/writable-shape-query.js +1 -0
  137. package/dist/shared/writable-shape-query.js.map +1 -0
  138. package/dist/types/jsonld.js +1 -0
  139. package/dist/types/jsonld.js.map +1 -0
  140. package/dist/types/sparql-types.js +1 -0
  141. package/dist/types/sparql-types.js.map +1 -0
  142. package/package.json +11 -6
  143. package/src/generated/graphql.ts +12158 -0
  144. package/src/graphql-clients.ts +67 -0
  145. package/src/index.ts +2 -0
  146. package/src/shared/action-document.ts +56 -0
  147. package/src/shared/action-plan.ts +1 -0
  148. package/src/shared/agent-mode.ts +46 -0
  149. package/src/shared/agent-types.ts +46 -0
  150. package/src/shared/chat-context.ts +47 -0
  151. package/src/shared/chat-manager.ts +199 -0
  152. package/src/shared/chat-turn-errors.ts +35 -0
  153. package/src/shared/constants.ts +19 -0
  154. package/src/shared/conversation-starter-defaults.ts +27 -0
  155. package/src/shared/datastore-id.ts +25 -0
  156. package/src/shared/datastore-path.ts +80 -0
  157. package/src/shared/duration.ts +61 -0
  158. package/src/shared/email.ts +54 -0
  159. package/src/shared/entity-set.ts +33 -0
  160. package/src/shared/error-utils.ts +79 -0
  161. package/src/shared/explorer-paths.ts +9 -0
  162. package/src/shared/fileIri.ts +25 -0
  163. package/src/shared/index.ts +31 -0
  164. package/src/shared/inferal-stream.ts +2 -0
  165. package/src/shared/live-context.ts +15 -0
  166. package/src/shared/maintenance-schedule.ts +47 -0
  167. package/src/shared/memory-citation-sampling.ts +26 -0
  168. package/src/shared/memory-confidence.ts +8 -0
  169. package/src/shared/memory-consolidation-limits.ts +9 -0
  170. package/src/shared/memory-dates.ts +7 -0
  171. package/src/shared/memory-decay.ts +70 -0
  172. package/src/shared/memory-diversity.ts +55 -0
  173. package/src/shared/memory-entity-recall.ts +26 -0
  174. package/src/shared/memory-importance.ts +12 -0
  175. package/src/shared/memory-keyword-recall.ts +149 -0
  176. package/src/shared/memory-kind-iris.ts +36 -0
  177. package/src/shared/memory-preload-gate.ts +150 -0
  178. package/src/shared/memory-sources.ts +5 -0
  179. package/src/shared/memory-teams.ts +3 -0
  180. package/src/shared/memory-token-budget.ts +31 -0
  181. package/src/shared/memory-volatility.ts +90 -0
  182. package/src/shared/message-utils.ts +37 -0
  183. package/src/shared/model.ts +117 -0
  184. package/src/shared/org-roles.ts +21 -0
  185. package/src/shared/page-context.ts +7 -0
  186. package/src/shared/permissions.ts +19 -0
  187. package/src/shared/questionnaire.ts +76 -0
  188. package/src/shared/rdf-namespaces.ts +62 -0
  189. package/src/shared/rule-iri.ts +15 -0
  190. package/src/shared/rule-search.ts +1 -0
  191. package/src/shared/session-types.ts +14 -0
  192. package/src/shared/stakeholder-iri.ts +23 -0
  193. package/src/shared/team-activation.ts +9 -0
  194. package/src/shared/team-filters.ts +33 -0
  195. package/src/shared/team.ts +244 -0
  196. package/src/shared/tools/coercers.ts +82 -0
  197. package/src/shared/tools/index.ts +49 -0
  198. package/src/shared/tools/metadata.ts +205 -0
  199. package/src/shared/tools/test-triple.ts +33 -0
  200. package/src/shared/tools/types.ts +302 -0
  201. package/src/shared/upload.ts +57 -0
  202. package/src/shared/website-url.ts +32 -0
  203. package/src/shared/workspace-artifacts.ts +68 -0
  204. package/src/shared/writable-shape-query.ts +24 -0
  205. package/src/types/jsonld.ts +19 -0
  206. package/src/types/sparql-types.ts +10 -0
@@ -0,0 +1,205 @@
1
+ import { humanCount } from "@manta-eu/lib/humanize";
2
+ import { isPresent } from "@manta-eu/lib/present";
3
+ import type { ToolUIPart } from "ai";
4
+ import { match, P } from "ts-pattern";
5
+ import { iriLocalName } from "../rdf-namespaces";
6
+ import type { ToolMetadata, ToolName } from "./types";
7
+
8
+ export const toolMetadata: ToolMetadata = {
9
+ getRDFoxFacts: {
10
+ name: "getRDFoxFacts",
11
+ category: "rdfox",
12
+ humanName: "Query knowledge base",
13
+ description: "Retrieve facts from RDFox knowledge base using SPARQL",
14
+ getHumanName: (input) => {
15
+ return input?.humanIntent || "Querying...";
16
+ },
17
+ },
18
+ addRDFoxFacts: {
19
+ name: "addRDFoxFacts",
20
+ category: "rdfox",
21
+ humanName: "Add facts",
22
+ description: "Add facts to RDFox knowledge base as Turtle",
23
+ getHumanName: (input) => {
24
+ return input?.humanIntent || "Adding facts...";
25
+ },
26
+ },
27
+ getRDFoxRules: {
28
+ name: "getRDFoxRules",
29
+ category: "rdfox",
30
+ humanName: "Check rules",
31
+ description:
32
+ "Retrieve Datalog rules from RDFox with optional filters (named graph, rdf:type, limit) to avoid context overflow",
33
+ getHumanName: (input) => {
34
+ const parts: string[] = [];
35
+ if (input?.namedGraphIri) parts.push(`plan: ${input.namedGraphIri}`);
36
+ if (isPresent(input?.rdfTypes)) parts.push(`types: ${input.rdfTypes.join(", ")}`);
37
+ if (!isPresent(parts)) return "Checking rules...";
38
+ return `Checking rules ${parts.join(" + ")}`;
39
+ },
40
+ },
41
+ explainRDFoxRules: {
42
+ name: "explainRDFoxRules",
43
+ category: "rdfox",
44
+ humanName: "Explain reasoning",
45
+ description: "Explain how facts are derived using rules",
46
+ getHumanName: () => "Explaining reasoning...",
47
+ },
48
+ scheduleTask: {
49
+ name: "scheduleTask",
50
+ category: "scheduler",
51
+ humanName: "Schedule task",
52
+ description: "Schedule a task for future execution",
53
+ getHumanName: (input) => {
54
+ return input?.description ? `Schedule: ${input.description}` : "Scheduling...";
55
+ },
56
+ },
57
+ listScheduledTasks: {
58
+ name: "listScheduledTasks",
59
+ category: "scheduler",
60
+ humanName: "List scheduled tasks",
61
+ description: "List all scheduled tasks",
62
+ getHumanName: () => "List scheduled tasks",
63
+ },
64
+ cancelSchedule: {
65
+ name: "cancelSchedule",
66
+ category: "scheduler",
67
+ humanName: "Cancel task",
68
+ description: "Cancel a scheduled task",
69
+ getHumanName: (input) => {
70
+ return input?.id ? `Cancel task: ${input.id}` : "Canceling task...";
71
+ },
72
+ },
73
+ generateChart: {
74
+ name: "generateChart",
75
+ category: "charts",
76
+ humanName: "Generate chart",
77
+ description: "Create interactive charts for data visualization",
78
+ getHumanName: (input) => {
79
+ return input?.title ? `Chart: ${input.title}` : "Charting...";
80
+ },
81
+ },
82
+ executeActionPlan: {
83
+ name: "executeActionPlan",
84
+ category: "action",
85
+ humanName: "Execute action plan",
86
+ description: "Execute semantic action plans with SHACL validation and multi-platform orchestration",
87
+ getHumanName: (input) => {
88
+ return input?.namedGraphIri ? `Execute plan: ${input.namedGraphIri}` : "Executing action plan...";
89
+ },
90
+ },
91
+ manageRDFoxRules: {
92
+ name: "manageRDFoxRules",
93
+ category: "rdfox",
94
+ humanName: "Manage rules",
95
+ description: "Add, change, or remove Datalog rules in RDFox knowledge base",
96
+ getHumanName: (input) => {
97
+ return input?.humanIntent || "Managing rules...";
98
+ },
99
+ },
100
+ manageRDFoxFacts: {
101
+ name: "manageRDFoxFacts",
102
+ category: "rdfox",
103
+ humanName: "Manage facts",
104
+ description: "Add, change facts in RDFox knowledge",
105
+ getHumanName: (input) => {
106
+ return input?.humanIntent || "Managing facts...";
107
+ },
108
+ },
109
+ actionPlanShowcase: {
110
+ name: "actionPlanShowcase",
111
+ category: "action",
112
+ humanName: "Show action plan",
113
+ description: "Display a summary card for an action plan with steps and navigation CTA",
114
+ getHumanName: (input) => {
115
+ if (input?.actionPlanIRI) {
116
+ const fragment = iriLocalName(input.actionPlanIRI);
117
+ return fragment ? `Showcasing plan: ${fragment}` : "Showing action plan...";
118
+ }
119
+ return "Showing action plan...";
120
+ },
121
+ },
122
+ showEntities: {
123
+ name: "showEntities",
124
+ category: "action",
125
+ humanName: "Show entities",
126
+ description: "Display one or several knowledge-graph entities inline in one call",
127
+ getHumanName: (input) => {
128
+ if (!isPresent(input?.entityIris)) return "Showing entities...";
129
+ return `Showing: ${humanCount(input.entityIris.length, "entity")}`;
130
+ },
131
+ },
132
+ checkAutoPilotStatus: {
133
+ name: "checkAutoPilotStatus",
134
+ category: "auto-pilot",
135
+ humanName: "Check auto-pilot status",
136
+ description: "Check whether auto-pilot is enabled and review cadence and execution history",
137
+ getHumanName: (input) => input?.humanIntent || "Checking auto-pilot status...",
138
+ },
139
+ setDailyChangeLimit: {
140
+ name: "setDailyChangeLimit",
141
+ category: "auto-pilot",
142
+ humanName: "Set daily limit",
143
+ description: "Change how many actions of an action plan's kinds may start per day",
144
+ getHumanName: (input) => input?.humanIntent || "Updating daily limit...",
145
+ },
146
+ markAsLowRisk: {
147
+ name: "markAsLowRisk",
148
+ category: "auto-pilot",
149
+ humanName: "Mark as low-risk",
150
+ description: "Mark an action plan as trusted, so a rule may arm auto-pilot on it",
151
+ getHumanName: (input) => input?.humanIntent || "Marking plan as low-risk...",
152
+ },
153
+ readUploadedFile: {
154
+ name: "readUploadedFile",
155
+ category: "action",
156
+ humanName: "Read attachment",
157
+ description: "Read the contents of a file the user uploaded to this conversation",
158
+ getHumanName: () => "Reading attachment...",
159
+ },
160
+ } satisfies ToolMetadata;
161
+
162
+ export function getToolMetadata<T extends ToolName>(toolName: T): ToolMetadata[T] {
163
+ return toolMetadata[toolName];
164
+ }
165
+
166
+ export type GetHumanToolNameInput<T extends ToolName> = Parameters<ToolMetadata[T]["getHumanName"]>[0];
167
+
168
+ export function getHumanToolName<T extends ToolName>(toolName: T, input?: Record<string, unknown>): string {
169
+ const metadata = getToolMetadata(toolName);
170
+ return metadata.getHumanName(input as GetHumanToolNameInput<T>);
171
+ }
172
+
173
+ export function isValidToolName(toolName: string): toolName is ToolName {
174
+ return Object.prototype.hasOwnProperty.call(toolMetadata, toolName);
175
+ }
176
+
177
+ export function getSkillToolLabel(toolUIPart: ToolUIPart): string | undefined {
178
+ return match(toolUIPart)
179
+ .with({ type: "tool-activate_skill", input: { name: P.string } }, ({ input }) => `Reading skill: ${input.name}`)
180
+ .with({ type: "tool-activate_skill" }, () => "Reading skill...")
181
+ .with(
182
+ { type: "tool-read_skill_resource", input: { path: P.string } },
183
+ ({ input }) => `Reading resource: ${input.path}`,
184
+ )
185
+ .with({ type: "tool-read_skill_resource" }, () => "Reading resource...")
186
+ .otherwise(() => undefined);
187
+ }
188
+
189
+ export function getToolUIPartLabel(toolUIPart: ToolUIPart): string {
190
+ const skillLabel = getSkillToolLabel(toolUIPart);
191
+ if (skillLabel) return skillLabel;
192
+
193
+ const toolName = toolUIPart.type.replace("tool-", "");
194
+ if (!isValidToolName(toolName)) return toolName;
195
+ const input = toolUIPart.input as Record<string, unknown> | undefined;
196
+ return input ? getHumanToolName(toolName, input) : getToolMetadata(toolName).humanName;
197
+ }
198
+
199
+ export function assertValidToolName(toolName: string): asserts toolName is ToolName {
200
+ if (!isValidToolName(toolName)) {
201
+ throw new Error(`Unknown tool: ${toolName}. Add it to shared/tools/types.ts and metadata.ts`);
202
+ }
203
+ }
204
+
205
+ export const allToolNames: readonly ToolName[] = Object.keys(toolMetadata) as ToolName[];
@@ -0,0 +1,33 @@
1
+ import { z } from "zod/v4";
2
+
3
+ const iriValueSchema = z.string().min(1).describe("Full HTTP(S) or known prefixed IRI, without SPARQL brackets");
4
+
5
+ const iriObjectInputSchema = z.object({
6
+ type: z.literal("iri"),
7
+ value: iriValueSchema,
8
+ });
9
+
10
+ const languageTagPattern = /^[A-Za-z]+(?:-[A-Za-z0-9]+)*$/;
11
+
12
+ const literalTermInputSchema = z
13
+ .object({
14
+ type: z.literal("literal"),
15
+ value: z.string().describe("Literal lexical value, without SPARQL quotes"),
16
+ datatype: z.string().min(1).optional().describe("Optional full or known prefixed datatype IRI"),
17
+ language: z
18
+ .string()
19
+ .regex(languageTagPattern, "Invalid language tag")
20
+ .optional()
21
+ .describe("Optional BCP 47 language tag"),
22
+ })
23
+ .refine(({ datatype, language }) => !(datatype && language), {
24
+ message: "A literal cannot have both datatype and language",
25
+ });
26
+
27
+ export const testTripleInputSchema = z.object({
28
+ subject: iriValueSchema.describe("Expected triple subject IRI"),
29
+ predicate: iriValueSchema.describe("Expected triple predicate IRI"),
30
+ object: z.discriminatedUnion("type", [iriObjectInputSchema, literalTermInputSchema]),
31
+ });
32
+
33
+ export type TestTripleInput = z.infer<typeof testTripleInputSchema>;
@@ -0,0 +1,302 @@
1
+ import type { DatalogRule, InferenceVerificationResult } from "@manta-eu/datalog-parser";
2
+ import type { z } from "zod/v4";
3
+ import type { TestTripleInput } from "./test-triple";
4
+ import type { JsonLdGraphDocument } from "#types/jsonld";
5
+ import type { SparqlBinding, SparqlJsonResults } from "#types/sparql-types";
6
+
7
+ export type { SparqlBinding, SparqlJsonResults, SparqlValue } from "#types/sparql-types";
8
+ export type { TestTripleInput };
9
+
10
+ export type SparqlJsonBinding = SparqlBinding;
11
+
12
+ export type ToolName =
13
+ | "getRDFoxFacts"
14
+ | "addRDFoxFacts"
15
+ | "getRDFoxRules"
16
+ | "explainRDFoxRules"
17
+ | "scheduleTask"
18
+ | "listScheduledTasks"
19
+ | "cancelSchedule"
20
+ | "generateChart"
21
+ | "executeActionPlan"
22
+ | "manageRDFoxRules"
23
+ | "manageRDFoxFacts"
24
+ | "actionPlanShowcase"
25
+ | "showEntities"
26
+ | "checkAutoPilotStatus"
27
+ | "setDailyChangeLimit"
28
+ | "markAsLowRisk"
29
+ | "readUploadedFile";
30
+
31
+ export type ToolCategory = "rdfox" | "scheduler" | "charts" | "action" | "auto-pilot";
32
+
33
+ export type ToolInputSchema<T = unknown> = z.ZodSchema<T>;
34
+
35
+ export type ToolOutput<T = unknown> = T | ToolErrorResult;
36
+
37
+ export type ToolErrorResult = {
38
+ is_error: true;
39
+ content: string;
40
+ };
41
+
42
+ export type RDFoxFactsInput = {
43
+ humanIntent: string;
44
+ sparql: string;
45
+ keepPrefixes?: boolean;
46
+ };
47
+
48
+ export type RDFoxFactsOutput = JsonLdGraphDocument | SparqlJsonResults | ToolErrorResult;
49
+
50
+ export type AddRDFoxFactsInput = {
51
+ facts: string;
52
+ humanIntent: string;
53
+ };
54
+
55
+ export type AddRDFoxFactsOutput = string | ToolErrorResult;
56
+
57
+ export type GetRDFoxRulesInput = {
58
+ namedGraphIri?: string;
59
+ rdfTypes?: string[];
60
+ limit?: number;
61
+ };
62
+
63
+ export type GetRDFoxRulesOutputSuccess = {
64
+ rules: string[] | string | Record<string, unknown>[]; // TODO: standardize on RuleInfo type
65
+ totalCount: number;
66
+ truncated?: boolean;
67
+ };
68
+
69
+ export type GetRDFoxRulesOutput = GetRDFoxRulesOutputSuccess | ToolErrorResult;
70
+
71
+ export type ExplainRDFoxRulesInput = {
72
+ subject: string;
73
+ predicate?: string;
74
+ object: string;
75
+ };
76
+
77
+ export type ToolObjectOutput = object | ToolErrorResult;
78
+
79
+ export type ExplainRDFoxRulesOutput = ToolObjectOutput;
80
+
81
+ export type ScheduleTaskInput = {
82
+ when: "scheduled" | "delayed" | "cron";
83
+ description: string;
84
+ [key: string]: unknown;
85
+ };
86
+
87
+ export type ScheduleTaskOutput = ToolObjectOutput;
88
+
89
+ export type ListScheduledTasksInput = Record<string, never>;
90
+
91
+ export type ListScheduledTasksOutput = Array<object> | ToolErrorResult;
92
+
93
+ export type CancelScheduleInput = {
94
+ id: string;
95
+ };
96
+
97
+ export type CancelScheduleOutput = ToolObjectOutput;
98
+
99
+ export type GenerateChartInputData = {
100
+ x?: string | number;
101
+ y?: number;
102
+ name?: string;
103
+ value?: number;
104
+ subject?: string;
105
+ barValue?: number;
106
+ lineValue?: number;
107
+ };
108
+
109
+ export type GenerateChartType = "line" | "area" | "bar" | "pie" | "scatter" | "radar" | "composed";
110
+
111
+ export type GenerateChartInput = {
112
+ type: GenerateChartType;
113
+ title?: string;
114
+ data: GenerateChartInputData[];
115
+ height?: number;
116
+ xAxisLabel?: string;
117
+ yAxisLabel?: string;
118
+ barLabel?: string;
119
+ lineLabel?: string;
120
+ };
121
+
122
+ export type GenerateChartOutput = {
123
+ type: "chart";
124
+ chartType: GenerateChartType;
125
+ data: object;
126
+ message: string;
127
+ };
128
+
129
+ export type ExecuteActionPlanInput = {
130
+ namedGraphIri: string;
131
+ shaclShapeIri?: string;
132
+ dryRun?: boolean;
133
+ autoApprove?: boolean;
134
+ };
135
+
136
+ export type ExecuteActionPlanOutput =
137
+ | {
138
+ planValidation?: {
139
+ valid: boolean;
140
+ completeness: number;
141
+ issues?: string[];
142
+ };
143
+ semanticDiff?: {
144
+ creates: number;
145
+ updates: number;
146
+ deletes: number;
147
+ operations: unknown[];
148
+ };
149
+ workflowId?: string;
150
+ data?: unknown;
151
+ }
152
+ | ToolErrorResult;
153
+
154
+ export type ManageRDFoxRulesInput = {
155
+ humanIntent: string;
156
+ operation: "add" | "change" | "remove";
157
+ ruleIri?: string;
158
+ newRule?: string;
159
+ testTriple?: TestTripleInput;
160
+ expectNoInference?: boolean;
161
+ dryRun?: boolean;
162
+ stageOnly?: boolean;
163
+ };
164
+ export type ManageRDFoxRulesSuccess = {
165
+ success: true;
166
+ ruleIri: string;
167
+ parsedRule: DatalogRule | null;
168
+ content: string;
169
+ };
170
+
171
+ export type ManageRDFoxRulesOutput =
172
+ | (ManageRDFoxRulesSuccess & { dryRun: true })
173
+ | (ManageRDFoxRulesSuccess & { staged: true })
174
+ | (ManageRDFoxRulesSuccess & {
175
+ ruleText: string;
176
+ inferenceVerified: boolean;
177
+ inferenceVerification: InferenceVerificationResult | null;
178
+ commitSummary: {
179
+ rulesAdded: number;
180
+ rulesUpdated: number;
181
+ rulesDeleted: number;
182
+ };
183
+ })
184
+ | ToolErrorResult;
185
+
186
+ export type ManageRDFoxFactsInput = {
187
+ humanIntent: string;
188
+ facts: string;
189
+ namedGraphIri?: string;
190
+ operation?: "add" | "update";
191
+ etag?: string;
192
+ };
193
+
194
+ export type ManageRDFoxFactsOutput =
195
+ | {
196
+ content: string;
197
+ is_error: boolean;
198
+ }
199
+ | ToolErrorResult;
200
+
201
+ export type ActionPlanStatus = "DRAFT" | "RUNNING" | "COMPLETED" | "FAILED" | "TIMED_OUT";
202
+
203
+ export type ActionPlanShowcaseInput = {
204
+ actionPlanIRI: string;
205
+ };
206
+
207
+ export type ActionPlanShowcaseOutput =
208
+ | {
209
+ planIri: string;
210
+ planName: string;
211
+ status: ActionPlanStatus;
212
+ }
213
+ | ToolErrorResult;
214
+
215
+ export type ShowEntitiesInput = {
216
+ entityIris: string[];
217
+ };
218
+
219
+ export type ShowEntitiesOutput =
220
+ | {
221
+ entityIris: string[];
222
+ graph: JsonLdGraphDocument;
223
+ message?: string;
224
+ }
225
+ | ToolErrorResult;
226
+
227
+ export type ReadUploadedFileInput = {
228
+ fileIri: string;
229
+ };
230
+
231
+ export type ReadUploadedFileOutput = string | ToolErrorResult;
232
+
233
+ export type ToolDefinition<TInput = unknown, _TOutput = unknown> = {
234
+ name: ToolName;
235
+ category: ToolCategory;
236
+ description: string;
237
+ inputSchema: ToolInputSchema<TInput>;
238
+ humanName: string;
239
+ getHumanName: (input?: TInput) => string;
240
+ };
241
+
242
+ export type AutoPilotInput = {
243
+ humanIntent: string;
244
+ planId: string;
245
+ };
246
+
247
+ export type SetDailyChangeLimitInput = AutoPilotInput & { dailyChangeLimit?: number };
248
+
249
+ export type AutoPilotActionPlan = {
250
+ namedGraphIri: string;
251
+ autoPilotEnabled?: boolean | null;
252
+ scheduledCadence?: string | null;
253
+ scheduledCron?: string | null;
254
+ scheduleTimezone?: string | null;
255
+ executionCount?: number | null;
256
+ lastExecutedAt?: string | null;
257
+ hasTrustThreshold?: boolean | null;
258
+ isLowRisk?: boolean | null;
259
+ maxChangesPerPass?: number | null;
260
+ dailyChangeLimit?: number | null;
261
+ };
262
+
263
+ export type AutoPilotOutput = ({ success: true } & AutoPilotActionPlan) | ToolErrorResult;
264
+
265
+ export type CheckAutoPilotStatusOutput = AutoPilotActionPlan | ToolErrorResult;
266
+
267
+ export type ToolDefinitions = {
268
+ getRDFoxFacts: ToolDefinition<RDFoxFactsInput, RDFoxFactsOutput>;
269
+ addRDFoxFacts: ToolDefinition<AddRDFoxFactsInput, AddRDFoxFactsOutput>;
270
+ getRDFoxRules: ToolDefinition<GetRDFoxRulesInput, GetRDFoxRulesOutput>;
271
+ explainRDFoxRules: ToolDefinition<ExplainRDFoxRulesInput, ExplainRDFoxRulesOutput>;
272
+ scheduleTask: ToolDefinition<ScheduleTaskInput, ScheduleTaskOutput>;
273
+ listScheduledTasks: ToolDefinition<ListScheduledTasksInput, ListScheduledTasksOutput>;
274
+ cancelSchedule: ToolDefinition<CancelScheduleInput, CancelScheduleOutput>;
275
+ generateChart: ToolDefinition<GenerateChartInput, GenerateChartOutput>;
276
+ executeActionPlan: ToolDefinition<ExecuteActionPlanInput, ExecuteActionPlanOutput>;
277
+ manageRDFoxRules: ToolDefinition<ManageRDFoxRulesInput, ManageRDFoxRulesOutput>;
278
+ manageRDFoxFacts: ToolDefinition<ManageRDFoxFactsInput, ManageRDFoxFactsOutput>;
279
+ actionPlanShowcase: ToolDefinition<ActionPlanShowcaseInput, ActionPlanShowcaseOutput>;
280
+ showEntities: ToolDefinition<ShowEntitiesInput, ShowEntitiesOutput>;
281
+ checkAutoPilotStatus: ToolDefinition<AutoPilotInput, CheckAutoPilotStatusOutput>;
282
+ setDailyChangeLimit: ToolDefinition<SetDailyChangeLimitInput, AutoPilotOutput>;
283
+ markAsLowRisk: ToolDefinition<AutoPilotInput, AutoPilotOutput>;
284
+ readUploadedFile: ToolDefinition<ReadUploadedFileInput, ReadUploadedFileOutput>;
285
+ };
286
+
287
+ export type ToolMetadata = {
288
+ [K in ToolName]: {
289
+ name: K;
290
+ category: ToolCategory;
291
+ humanName: string;
292
+ description: string;
293
+ getHumanName: (
294
+ input?: ToolDefinitions[K] extends ToolDefinition<infer TInput, unknown> ? TInput : unknown,
295
+ ) => string;
296
+ };
297
+ };
298
+
299
+ export type ToolOutputType<T extends ToolName> =
300
+ ToolDefinitions[T] extends ToolDefinition<unknown, infer TOutput> ? TOutput : unknown;
301
+
302
+ export type ToolOutputCoercer<T extends ToolName> = (raw: unknown) => ToolOutputType<T>;
@@ -0,0 +1,57 @@
1
+ import { getExtension } from "@manta-eu/lib/file";
2
+ import mime from "mime";
3
+ import { MIMEType } from "whatwg-mimetype";
4
+
5
+ export const uploadPartSize = 8 * 1024 * 1024;
6
+
7
+ export function bytesToHex(buffer: ArrayBuffer) {
8
+ return [...new Uint8Array(buffer)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
9
+ }
10
+
11
+ export async function sha256Hex(bytes: BufferSource) {
12
+ const digest = await crypto.subtle.digest("SHA-256", bytes);
13
+
14
+ return bytesToHex(digest);
15
+ }
16
+
17
+ export type FileFacts = {
18
+ byteSize: number;
19
+ sha256?: string;
20
+ width?: number;
21
+ height?: number;
22
+ };
23
+
24
+ export type UploadedPartEtag = {
25
+ partNumber: number;
26
+ etag: string;
27
+ };
28
+
29
+ export type UploadedFileReference = {
30
+ fileIri: string;
31
+ storageKey: string;
32
+ fileName: string;
33
+ mediaType: string;
34
+ byteSize: number;
35
+ };
36
+
37
+ const maxMediaTypeLength = 255;
38
+
39
+ export function normalizeMediaType(mediaType: string) {
40
+ const essence = MIMEType.parse(mediaType)?.essence ?? "";
41
+
42
+ return essence.length > maxMediaTypeLength ? "" : essence;
43
+ }
44
+
45
+ export const maxFileNameBytes = 255;
46
+
47
+ export function isFileNameTooLong(fileName: string) {
48
+ return new TextEncoder().encode(fileName).length > maxFileNameBytes;
49
+ }
50
+
51
+ export function mediaTypeFromExtension(extension: string | undefined) {
52
+ return (extension ? mime.getType(extension) : undefined) ?? "application/octet-stream";
53
+ }
54
+
55
+ export function mediaTypeFromFileName(fileName: string) {
56
+ return mediaTypeFromExtension(getExtension(fileName));
57
+ }
@@ -0,0 +1,32 @@
1
+ import { isPresent } from "@manta-eu/lib/present";
2
+
3
+ export function withHttpsScheme(raw: string): string {
4
+ const trimmed = raw.trim();
5
+ return /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
6
+ }
7
+
8
+ // Not round-tripped through URL, which would append a path the graph's existing subjects lack.
9
+ export function websiteUrl(raw: string | null | undefined): string | undefined {
10
+ if (!isPresent(raw?.trim())) return undefined;
11
+ return withHttpsScheme(raw);
12
+ }
13
+
14
+ export function validWebsiteUrl(raw: string | null | undefined): string | undefined {
15
+ const candidate = websiteUrl(raw);
16
+ if (!isPresent(candidate)) return undefined;
17
+
18
+ try {
19
+ const url = new URL(candidate);
20
+ return url.protocol === "http:" || url.protocol === "https:" ? url.toString() : undefined;
21
+ } catch {
22
+ return undefined;
23
+ }
24
+ }
25
+
26
+ export function websiteHost(raw: string): string {
27
+ try {
28
+ return new URL(withHttpsScheme(raw)).hostname.replace(/^www\./, "");
29
+ } catch {
30
+ return raw;
31
+ }
32
+ }
@@ -0,0 +1,68 @@
1
+ import { z } from "zod/v4";
2
+ import { chatIdSchema, chatManagerBasePath, thinkChatFacetPath } from "./chat-manager";
3
+ import { normalizeMediaType } from "./upload";
4
+
5
+ // Changing this value requires `pnpm db:generate:chat-think` so the SQLite CHECK constraint stays in sync.
6
+ export const workspaceArtifactMaxByteSize = 1_500_000;
7
+ const workspaceArtifactRoutePrefix = `/${chatManagerBasePath}/sub/${thinkChatFacetPath}/`;
8
+ const workspaceArtifactInlineMediaTypes: ReadonlySet<string> = new Set([
9
+ "image/avif",
10
+ "image/gif",
11
+ "image/jpeg",
12
+ "image/png",
13
+ "image/webp",
14
+ ]);
15
+
16
+ export function isWorkspaceArtifactInlineMediaType(mediaType: string): boolean {
17
+ return workspaceArtifactInlineMediaTypes.has(mediaType);
18
+ }
19
+
20
+ export const workspaceArtifactIdSchema = z.uuid();
21
+
22
+ function isWorkspaceArtifactUrl(input: { artifactId: string; url: string }): boolean {
23
+ if (!input.url.startsWith(workspaceArtifactRoutePrefix)) return false;
24
+
25
+ const segments = input.url.slice(workspaceArtifactRoutePrefix.length).split("/");
26
+ if (segments.length !== 3) return false;
27
+
28
+ const [encodedConversationId, artifactMarker, artifactId] = segments;
29
+ if (artifactMarker !== "artifacts" || artifactId !== input.artifactId) {
30
+ return false;
31
+ }
32
+
33
+ try {
34
+ return chatIdSchema.safeParse(decodeURIComponent(encodedConversationId ?? "")).success;
35
+ } catch {
36
+ return false;
37
+ }
38
+ }
39
+
40
+ export const workspaceArtifactSchema = z
41
+ .strictObject({
42
+ type: z.literal("workspace-artifact"),
43
+ artifactId: workspaceArtifactIdSchema,
44
+ filename: z.string().trim().min(1).max(255),
45
+ mediaType: z
46
+ .string()
47
+ .min(1)
48
+ .max(255)
49
+ .refine((mediaType) => normalizeMediaType(mediaType) === mediaType, {
50
+ message: "Media type must be a normalized MIME essence",
51
+ }),
52
+ byteSize: z.number().int().nonnegative().max(workspaceArtifactMaxByteSize),
53
+ url: z.string(),
54
+ })
55
+ .refine(isWorkspaceArtifactUrl, {
56
+ message: "Artifact URL must match its conversation-scoped artifact route",
57
+ path: ["url"],
58
+ });
59
+
60
+ export type WorkspaceArtifact = z.infer<typeof workspaceArtifactSchema>;
61
+
62
+ export const publishWorkspaceFileInputSchema = z.strictObject({
63
+ path: z.string().trim().min(1).max(4096),
64
+ });
65
+
66
+ export function buildWorkspaceArtifactUrl(input: { conversationId: string; artifactId: string }): string {
67
+ return `${workspaceArtifactRoutePrefix}${encodeURIComponent(input.conversationId)}/artifacts/${input.artifactId}`;
68
+ }