@graphlit/agent-tools 1.0.20260611003
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/LICENSE +21 -0
- package/README.md +129 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5 -0
- package/dist/tools/ingest-url.d.ts +35 -0
- package/dist/tools/ingest-url.js +39 -0
- package/dist/tools/inspect-content.d.ts +35 -0
- package/dist/tools/inspect-content.js +78 -0
- package/dist/tools/retrieve-contents.d.ts +68 -0
- package/dist/tools/retrieve-contents.js +170 -0
- package/dist/tools/wait-content-done.d.ts +30 -0
- package/dist/tools/wait-content-done.js +72 -0
- package/dist/tools/web-search.d.ts +34 -0
- package/dist/tools/web-search.js +52 -0
- package/dist/types.d.ts +11 -0
- package/dist/types.js +1 -0
- package/dist/utils/abort.d.ts +2 -0
- package/dist/utils/abort.js +26 -0
- package/dist/utils/clamp.d.ts +1 -0
- package/dist/utils/clamp.js +4 -0
- package/dist/utils/content.d.ts +14 -0
- package/dist/utils/content.js +27 -0
- package/dist/utils/schema.d.ts +4 -0
- package/dist/utils/schema.js +32 -0
- package/dist/utils/text.d.ts +4 -0
- package/dist/utils/text.js +10 -0
- package/package.json +62 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Graphlit
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# @graphlit/agent-tools
|
|
2
|
+
|
|
3
|
+
Top-level Graphlit tool factories for TypeScript apps that use `streamAgent()`.
|
|
4
|
+
|
|
5
|
+
This package gives developers a small set of Graphlit-backed tools they can choose from directly. It does not provide tool discovery, MCP server wrappers, approval middleware, or convenience bundles.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install graphlit-client @graphlit/agent-tools
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Basic `streamAgent()` Usage
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { Graphlit } from "graphlit-client";
|
|
17
|
+
import {
|
|
18
|
+
createInspectContentTool,
|
|
19
|
+
createRetrieveContentsTool,
|
|
20
|
+
createWebSearchTool,
|
|
21
|
+
} from "@graphlit/agent-tools";
|
|
22
|
+
|
|
23
|
+
const client = new Graphlit(
|
|
24
|
+
process.env.GRAPHLIT_ORGANIZATION_ID!,
|
|
25
|
+
process.env.GRAPHLIT_ENVIRONMENT_ID!,
|
|
26
|
+
process.env.GRAPHLIT_JWT_SECRET!,
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const retrieveContents = createRetrieveContentsTool(client);
|
|
30
|
+
const inspectContent = createInspectContentTool(client);
|
|
31
|
+
const webSearch = createWebSearchTool(client);
|
|
32
|
+
|
|
33
|
+
const selectedTools = [retrieveContents, inspectContent, webSearch];
|
|
34
|
+
|
|
35
|
+
await client.streamAgent(
|
|
36
|
+
"What customer emails from last week mention onboarding risk?",
|
|
37
|
+
(event) => {
|
|
38
|
+
// Stream events to your UI.
|
|
39
|
+
},
|
|
40
|
+
undefined,
|
|
41
|
+
undefined,
|
|
42
|
+
selectedTools.map((tool) => tool.tool),
|
|
43
|
+
Object.fromEntries(selectedTools.map((tool) => [tool.tool.name, tool.handler])),
|
|
44
|
+
{
|
|
45
|
+
maxToolRounds: 8,
|
|
46
|
+
},
|
|
47
|
+
undefined,
|
|
48
|
+
undefined,
|
|
49
|
+
undefined,
|
|
50
|
+
undefined,
|
|
51
|
+
undefined,
|
|
52
|
+
undefined,
|
|
53
|
+
[
|
|
54
|
+
"Use retrieve_contents before answering questions that depend on ingested Graphlit content.",
|
|
55
|
+
"Use inspect_content when a retrieved result needs fuller text before making a source-backed claim.",
|
|
56
|
+
"If retrieved evidence is weak or missing, say so plainly.",
|
|
57
|
+
].join(" "),
|
|
58
|
+
);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Realistic Retrieval Examples
|
|
62
|
+
|
|
63
|
+
`retrieve_contents` supports both semantic retrieval and filter-only content lookup.
|
|
64
|
+
|
|
65
|
+
For a model prompt such as “show me all emails from last week,” the tool can be called without a text search:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
await retrieveContents.handler({
|
|
69
|
+
type: "EMAIL",
|
|
70
|
+
inLast: "P7D",
|
|
71
|
+
limit: 25,
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
For RAG over specific content text, pass `search`:
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
await retrieveContents.handler({
|
|
79
|
+
search: "onboarding risk renewal blocker",
|
|
80
|
+
type: "EMAIL",
|
|
81
|
+
inLast: "P30D",
|
|
82
|
+
limit: 10,
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
For upcoming calendar context:
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
await retrieveContents.handler({
|
|
90
|
+
type: "EVENT",
|
|
91
|
+
inNext: "P7D",
|
|
92
|
+
limit: 20,
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
When answer-critical evidence needs more context, inspect the `contents://...` reference returned by retrieval:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
await inspectContent.handler({
|
|
100
|
+
resourceUri: "contents://content-id-from-retrieve-contents",
|
|
101
|
+
mode: "markdown",
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Tools
|
|
106
|
+
|
|
107
|
+
| Factory | Tool name | SDK operation |
|
|
108
|
+
| --- | --- | --- |
|
|
109
|
+
| `createRetrieveContentsTool()` | `retrieve_contents` | `retrieveSources`, `lookupContents`, `queryContents` |
|
|
110
|
+
| `createInspectContentTool()` | `inspect_content` | `getContent` |
|
|
111
|
+
| `createWebSearchTool()` | `web_search` | `searchWeb` |
|
|
112
|
+
| `createIngestUrlTool()` | `ingest_url` | `ingestUri` |
|
|
113
|
+
| `createWaitContentDoneTool()` | `wait_content_done` | `isContentDone` |
|
|
114
|
+
|
|
115
|
+
Each factory returns:
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
type GraphlitAgentTool = {
|
|
119
|
+
tool: Types.ToolDefinitionInput;
|
|
120
|
+
handler: NonNullable<Parameters<Graphlit["streamAgent"]>[5]>[string];
|
|
121
|
+
};
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Notes
|
|
125
|
+
|
|
126
|
+
- Run these tools server-side with Graphlit credentials.
|
|
127
|
+
- Tool schemas are authored with Zod and converted to Graphlit `ToolDefinitionInput`.
|
|
128
|
+
- Public options reuse `graphlit-client` SDK types where possible, including `Types.ContentFilter`, `Types.EntityReferenceInput`, `Types.RetrievalStrategyInput`, and `Types.RerankingStrategyInput`.
|
|
129
|
+
- Returned retrieval results include `contents://...` resource URIs for UI source rendering and follow-up inspection.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type { ContentReference, GraphlitAgentTool, GraphlitClient, GraphlitToolHandler, StreamAgentArtifactCollector, StreamAgentToolHandler, StreamAgentToolHandlers, } from "./types.js";
|
|
2
|
+
export { createIngestUrlTool, IngestUrlInputSchema, type IngestUrlArgs, type IngestUrlResult, type IngestUrlToolOptions, } from "./tools/ingest-url.js";
|
|
3
|
+
export { createInspectContentTool, InspectContentInputSchema, type InspectContentArgs, type InspectContentResult, type InspectContentToolOptions, } from "./tools/inspect-content.js";
|
|
4
|
+
export { createRetrieveContentsTool, RetrieveContentsInputSchema, type RetrieveContentsArgs, type RetrievedContentResult, type RetrieveContentsResult, type RetrieveContentsToolOptions, } from "./tools/retrieve-contents.js";
|
|
5
|
+
export { createWaitContentDoneTool, WaitContentDoneInputSchema, type WaitContentDoneArgs, type WaitContentDoneResult, type WaitContentDoneToolOptions, } from "./tools/wait-content-done.js";
|
|
6
|
+
export { createWebSearchTool, WebSearchInputSchema, type WebSearchArgs, type WebSearchToolOptions, type WebSearchToolResult, } from "./tools/web-search.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createIngestUrlTool, IngestUrlInputSchema, } from "./tools/ingest-url.js";
|
|
2
|
+
export { createInspectContentTool, InspectContentInputSchema, } from "./tools/inspect-content.js";
|
|
3
|
+
export { createRetrieveContentsTool, RetrieveContentsInputSchema, } from "./tools/retrieve-contents.js";
|
|
4
|
+
export { createWaitContentDoneTool, WaitContentDoneInputSchema, } from "./tools/wait-content-done.js";
|
|
5
|
+
export { createWebSearchTool, WebSearchInputSchema, } from "./tools/web-search.js";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ContentReference, GraphlitAgentTool, GraphlitClient } from "../types.js";
|
|
3
|
+
import type { Types } from "graphlit-client";
|
|
4
|
+
export declare const IngestUrlInputSchema: z.ZodObject<{
|
|
5
|
+
url: z.ZodString;
|
|
6
|
+
name: z.ZodOptional<z.ZodString>;
|
|
7
|
+
waitForCompletion: z.ZodOptional<z.ZodBoolean>;
|
|
8
|
+
}, "strip", z.ZodTypeAny, {
|
|
9
|
+
url: string;
|
|
10
|
+
name?: string | undefined;
|
|
11
|
+
waitForCompletion?: boolean | undefined;
|
|
12
|
+
}, {
|
|
13
|
+
url: string;
|
|
14
|
+
name?: string | undefined;
|
|
15
|
+
waitForCompletion?: boolean | undefined;
|
|
16
|
+
}>;
|
|
17
|
+
export type IngestUrlArgs = z.infer<typeof IngestUrlInputSchema>;
|
|
18
|
+
export interface IngestUrlToolOptions {
|
|
19
|
+
collections?: ContentReference[];
|
|
20
|
+
workflow?: Types.EntityReferenceInput;
|
|
21
|
+
defaultWaitForCompletion?: boolean;
|
|
22
|
+
correlationId?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface IngestUrlResult {
|
|
25
|
+
id: string;
|
|
26
|
+
resourceUri: string;
|
|
27
|
+
name: string;
|
|
28
|
+
uri?: string | null;
|
|
29
|
+
state?: string | null;
|
|
30
|
+
type?: string | null;
|
|
31
|
+
fileType?: string | null;
|
|
32
|
+
mimeType?: string | null;
|
|
33
|
+
waitForCompletion: boolean;
|
|
34
|
+
}
|
|
35
|
+
export declare function createIngestUrlTool(client: GraphlitClient, options?: IngestUrlToolOptions): GraphlitAgentTool<IngestUrlArgs, IngestUrlResult>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { throwIfAborted } from "../utils/abort.js";
|
|
3
|
+
import { contentName, scalarToString, toContentResourceUri } from "../utils/content.js";
|
|
4
|
+
import { createToolDefinition } from "../utils/schema.js";
|
|
5
|
+
export const IngestUrlInputSchema = z.object({
|
|
6
|
+
url: z.string().trim().url().describe("Public URL to ingest into Graphlit."),
|
|
7
|
+
name: z.string().trim().min(1).optional().describe("Optional content name."),
|
|
8
|
+
waitForCompletion: z
|
|
9
|
+
.boolean()
|
|
10
|
+
.optional()
|
|
11
|
+
.describe("Whether Graphlit should process the URL synchronously."),
|
|
12
|
+
});
|
|
13
|
+
export function createIngestUrlTool(client, options = {}) {
|
|
14
|
+
return {
|
|
15
|
+
tool: createToolDefinition("ingest_url", "Ingest a public URL into Graphlit so it can be retrieved by later agent turns.", IngestUrlInputSchema),
|
|
16
|
+
handler: async (rawArgs, artifacts, abortSignal) => {
|
|
17
|
+
throwIfAborted(abortSignal);
|
|
18
|
+
const args = IngestUrlInputSchema.parse(rawArgs);
|
|
19
|
+
const waitForCompletion = args.waitForCompletion ?? options.defaultWaitForCompletion ?? false;
|
|
20
|
+
const response = await client.ingestUri(args.url, args.name, undefined, undefined, waitForCompletion, options.workflow, options.collections, undefined, options.correlationId);
|
|
21
|
+
const content = response.ingestUri;
|
|
22
|
+
if (!content) {
|
|
23
|
+
throw new Error(`Failed to ingest URL: ${args.url}`);
|
|
24
|
+
}
|
|
25
|
+
artifacts?.addPending(Promise.resolve({ id: content.id }));
|
|
26
|
+
return {
|
|
27
|
+
id: content.id,
|
|
28
|
+
resourceUri: toContentResourceUri(content.id) ?? `contents://${content.id}`,
|
|
29
|
+
name: contentName(content),
|
|
30
|
+
uri: scalarToString(content.uri),
|
|
31
|
+
state: content.state,
|
|
32
|
+
type: content.type,
|
|
33
|
+
fileType: content.fileType,
|
|
34
|
+
mimeType: content.mimeType,
|
|
35
|
+
waitForCompletion,
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { GraphlitAgentTool, GraphlitClient } from "../types.js";
|
|
3
|
+
export declare const InspectContentInputSchema: z.ZodObject<{
|
|
4
|
+
id: z.ZodOptional<z.ZodString>;
|
|
5
|
+
resourceUri: z.ZodOptional<z.ZodString>;
|
|
6
|
+
mode: z.ZodOptional<z.ZodEnum<["auto", "summary", "markdown"]>>;
|
|
7
|
+
maxTextLength: z.ZodOptional<z.ZodNumber>;
|
|
8
|
+
}, "strip", z.ZodTypeAny, {
|
|
9
|
+
id?: string | undefined;
|
|
10
|
+
resourceUri?: string | undefined;
|
|
11
|
+
mode?: "auto" | "summary" | "markdown" | undefined;
|
|
12
|
+
maxTextLength?: number | undefined;
|
|
13
|
+
}, {
|
|
14
|
+
id?: string | undefined;
|
|
15
|
+
resourceUri?: string | undefined;
|
|
16
|
+
mode?: "auto" | "summary" | "markdown" | undefined;
|
|
17
|
+
maxTextLength?: number | undefined;
|
|
18
|
+
}>;
|
|
19
|
+
export type InspectContentArgs = z.infer<typeof InspectContentInputSchema>;
|
|
20
|
+
export interface InspectContentToolOptions {
|
|
21
|
+
maxTextLength?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface InspectContentResult {
|
|
24
|
+
id: string;
|
|
25
|
+
resourceUri: string;
|
|
26
|
+
name: string;
|
|
27
|
+
uri?: string | null;
|
|
28
|
+
type?: string | null;
|
|
29
|
+
fileType?: string | null;
|
|
30
|
+
mimeType?: string | null;
|
|
31
|
+
mode: "auto" | "summary" | "markdown";
|
|
32
|
+
text: string;
|
|
33
|
+
truncated: boolean;
|
|
34
|
+
}
|
|
35
|
+
export declare function createInspectContentTool(client: GraphlitClient, options?: InspectContentToolOptions): GraphlitAgentTool<InspectContentArgs, InspectContentResult>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { throwIfAborted } from "../utils/abort.js";
|
|
3
|
+
import { contentName, parseContentResourceUri, scalarToString, toContentResourceUri, } from "../utils/content.js";
|
|
4
|
+
import { createToolDefinition } from "../utils/schema.js";
|
|
5
|
+
import { truncateText } from "../utils/text.js";
|
|
6
|
+
const DEFAULT_MAX_TEXT_LENGTH = 12_000;
|
|
7
|
+
export const InspectContentInputSchema = z.object({
|
|
8
|
+
id: z.string().trim().min(1).optional().describe("Graphlit content ID."),
|
|
9
|
+
resourceUri: z
|
|
10
|
+
.string()
|
|
11
|
+
.trim()
|
|
12
|
+
.min(1)
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Graphlit content resource URI, such as contents://content-id."),
|
|
15
|
+
mode: z
|
|
16
|
+
.enum(["auto", "summary", "markdown"])
|
|
17
|
+
.optional()
|
|
18
|
+
.describe("Text to return. Defaults to auto."),
|
|
19
|
+
maxTextLength: z
|
|
20
|
+
.number()
|
|
21
|
+
.int()
|
|
22
|
+
.min(1)
|
|
23
|
+
.optional()
|
|
24
|
+
.describe("Maximum text length to return."),
|
|
25
|
+
});
|
|
26
|
+
function resolveContentId(args) {
|
|
27
|
+
const id = args.id ?? parseContentResourceUri(args.resourceUri);
|
|
28
|
+
if (!id) {
|
|
29
|
+
throw new Error("Provide either id or resourceUri.");
|
|
30
|
+
}
|
|
31
|
+
return id;
|
|
32
|
+
}
|
|
33
|
+
export function createInspectContentTool(client, options = {}) {
|
|
34
|
+
return {
|
|
35
|
+
tool: createToolDefinition("inspect_content", "Inspect one Graphlit content item returned by retrieve_contents, using its id or contents:// resource URI.", InspectContentInputSchema),
|
|
36
|
+
handler: async (rawArgs, _artifacts, abortSignal) => {
|
|
37
|
+
throwIfAborted(abortSignal);
|
|
38
|
+
const args = InspectContentInputSchema.parse(rawArgs);
|
|
39
|
+
const id = resolveContentId(args);
|
|
40
|
+
const response = await client.getContent(id);
|
|
41
|
+
const content = response.content;
|
|
42
|
+
if (!content) {
|
|
43
|
+
throw new Error(`Content not found: ${id}`);
|
|
44
|
+
}
|
|
45
|
+
const mode = args.mode ?? "auto";
|
|
46
|
+
const maxTextLength = args.maxTextLength ?? options.maxTextLength ?? DEFAULT_MAX_TEXT_LENGTH;
|
|
47
|
+
const textSource = mode === "summary"
|
|
48
|
+
? (content.customSummary ??
|
|
49
|
+
content.summary ??
|
|
50
|
+
content.snippet ??
|
|
51
|
+
content.description)
|
|
52
|
+
: mode === "markdown"
|
|
53
|
+
? (content.markdown ??
|
|
54
|
+
content.customSummary ??
|
|
55
|
+
content.summary ??
|
|
56
|
+
content.snippet ??
|
|
57
|
+
content.description)
|
|
58
|
+
: (content.markdown ??
|
|
59
|
+
content.customSummary ??
|
|
60
|
+
content.summary ??
|
|
61
|
+
content.snippet ??
|
|
62
|
+
content.description);
|
|
63
|
+
const { text, truncated } = truncateText(textSource ?? "", maxTextLength);
|
|
64
|
+
return {
|
|
65
|
+
id: content.id,
|
|
66
|
+
resourceUri: toContentResourceUri(content.id) ?? `contents://${content.id}`,
|
|
67
|
+
name: contentName(content),
|
|
68
|
+
uri: scalarToString(content.uri),
|
|
69
|
+
type: content.type,
|
|
70
|
+
fileType: content.fileType,
|
|
71
|
+
mimeType: content.mimeType,
|
|
72
|
+
mode,
|
|
73
|
+
text,
|
|
74
|
+
truncated,
|
|
75
|
+
};
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Types } from "graphlit-client";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { ContentReference, GraphlitAgentTool, GraphlitClient } from "../types.js";
|
|
4
|
+
export declare const RetrieveContentsInputSchema: z.ZodObject<{
|
|
5
|
+
search: z.ZodOptional<z.ZodString>;
|
|
6
|
+
inLast: z.ZodOptional<z.ZodString>;
|
|
7
|
+
inNext: z.ZodOptional<z.ZodString>;
|
|
8
|
+
type: z.ZodOptional<z.ZodNativeEnum<typeof Types.ContentTypes>>;
|
|
9
|
+
fileType: z.ZodOptional<z.ZodNativeEnum<typeof Types.FileTypes>>;
|
|
10
|
+
offset: z.ZodOptional<z.ZodNumber>;
|
|
11
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
12
|
+
}, "strip", z.ZodTypeAny, {
|
|
13
|
+
type?: Types.ContentTypes | undefined;
|
|
14
|
+
fileType?: Types.FileTypes | undefined;
|
|
15
|
+
search?: string | undefined;
|
|
16
|
+
inLast?: string | undefined;
|
|
17
|
+
inNext?: string | undefined;
|
|
18
|
+
offset?: number | undefined;
|
|
19
|
+
limit?: number | undefined;
|
|
20
|
+
}, {
|
|
21
|
+
type?: Types.ContentTypes | undefined;
|
|
22
|
+
fileType?: Types.FileTypes | undefined;
|
|
23
|
+
search?: string | undefined;
|
|
24
|
+
inLast?: string | undefined;
|
|
25
|
+
inNext?: string | undefined;
|
|
26
|
+
offset?: number | undefined;
|
|
27
|
+
limit?: number | undefined;
|
|
28
|
+
}>;
|
|
29
|
+
export type RetrieveContentsArgs = z.infer<typeof RetrieveContentsInputSchema>;
|
|
30
|
+
export interface RetrieveContentsToolOptions {
|
|
31
|
+
collectionId?: string;
|
|
32
|
+
collections?: ContentReference[];
|
|
33
|
+
baseFilter?: Types.ContentFilter;
|
|
34
|
+
defaultLimit?: number;
|
|
35
|
+
maxLimit?: number;
|
|
36
|
+
maxTextLength?: number;
|
|
37
|
+
searchType?: Types.SearchTypes;
|
|
38
|
+
retrievalStrategy?: Types.RetrievalStrategyInput;
|
|
39
|
+
rerankingStrategy?: Types.RerankingStrategyInput;
|
|
40
|
+
correlationId?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface RetrievedContentResult {
|
|
43
|
+
id: string;
|
|
44
|
+
resourceUri: string;
|
|
45
|
+
name: string;
|
|
46
|
+
uri?: string | null;
|
|
47
|
+
type?: Types.ContentTypes | null;
|
|
48
|
+
fileType?: Types.FileTypes | null;
|
|
49
|
+
mimeType?: string | null;
|
|
50
|
+
creationDate?: string | null;
|
|
51
|
+
originalDate?: string | null;
|
|
52
|
+
relevance?: number | null;
|
|
53
|
+
text: string;
|
|
54
|
+
truncated: boolean;
|
|
55
|
+
source?: {
|
|
56
|
+
metadata?: string | null;
|
|
57
|
+
pageNumber?: number | null;
|
|
58
|
+
frameNumber?: number | null;
|
|
59
|
+
startTime?: string | null;
|
|
60
|
+
endTime?: string | null;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export interface RetrieveContentsResult {
|
|
64
|
+
search: string | null;
|
|
65
|
+
collectionIds: string[];
|
|
66
|
+
results: RetrievedContentResult[];
|
|
67
|
+
}
|
|
68
|
+
export declare function createRetrieveContentsTool(client: GraphlitClient, options?: RetrieveContentsToolOptions): GraphlitAgentTool<RetrieveContentsArgs, RetrieveContentsResult>;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { Types } from "graphlit-client";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { throwIfAborted } from "../utils/abort.js";
|
|
4
|
+
import { clampInteger } from "../utils/clamp.js";
|
|
5
|
+
import { collectionIds, contentName, normalizeCollections, scalarToString, toContentResourceUri, } from "../utils/content.js";
|
|
6
|
+
import { createToolDefinition } from "../utils/schema.js";
|
|
7
|
+
import { truncateText } from "../utils/text.js";
|
|
8
|
+
const DEFAULT_LIMIT = 10;
|
|
9
|
+
const DEFAULT_MAX_LIMIT = 100;
|
|
10
|
+
const DEFAULT_MAX_TEXT_LENGTH = 4_000;
|
|
11
|
+
export const RetrieveContentsInputSchema = z.object({
|
|
12
|
+
search: z
|
|
13
|
+
.string()
|
|
14
|
+
.trim()
|
|
15
|
+
.min(1)
|
|
16
|
+
.optional()
|
|
17
|
+
.describe("Specific text to match against content. Omit for filter-only lookups like all emails in the last week."),
|
|
18
|
+
inLast: z
|
|
19
|
+
.string()
|
|
20
|
+
.trim()
|
|
21
|
+
.min(1)
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Backward-looking original-date filter as an ISO 8601 duration, such as P7D for the last 7 days."),
|
|
24
|
+
inNext: z
|
|
25
|
+
.string()
|
|
26
|
+
.trim()
|
|
27
|
+
.min(1)
|
|
28
|
+
.optional()
|
|
29
|
+
.describe("Forward-looking original-date filter as an ISO 8601 duration, such as P3D for the next 3 days."),
|
|
30
|
+
type: z
|
|
31
|
+
.nativeEnum(Types.ContentTypes)
|
|
32
|
+
.optional()
|
|
33
|
+
.describe("Graphlit content type, such as EMAIL, EVENT, FILE, PAGE, or TEXT."),
|
|
34
|
+
fileType: z
|
|
35
|
+
.nativeEnum(Types.FileTypes)
|
|
36
|
+
.optional()
|
|
37
|
+
.describe("Graphlit file type, such as DOCUMENT, IMAGE, AUDIO, or VIDEO."),
|
|
38
|
+
offset: z
|
|
39
|
+
.number()
|
|
40
|
+
.int()
|
|
41
|
+
.min(0)
|
|
42
|
+
.optional()
|
|
43
|
+
.describe("Number of results to skip for filter-only pagination."),
|
|
44
|
+
limit: z
|
|
45
|
+
.number()
|
|
46
|
+
.int()
|
|
47
|
+
.min(1)
|
|
48
|
+
.max(DEFAULT_MAX_LIMIT)
|
|
49
|
+
.optional()
|
|
50
|
+
.describe("Maximum number of results. Defaults to 10."),
|
|
51
|
+
});
|
|
52
|
+
function buildFilter(args, options, limit) {
|
|
53
|
+
const collections = normalizeCollections(options);
|
|
54
|
+
return {
|
|
55
|
+
...options.baseFilter,
|
|
56
|
+
searchType: args.search
|
|
57
|
+
? (options.searchType ?? options.baseFilter?.searchType ?? Types.SearchTypes.Hybrid)
|
|
58
|
+
: options.baseFilter?.searchType,
|
|
59
|
+
disableInheritance: options.baseFilter?.disableInheritance ?? true,
|
|
60
|
+
collections: collections ?? options.baseFilter?.collections,
|
|
61
|
+
inLast: args.inLast ?? options.baseFilter?.inLast,
|
|
62
|
+
inNext: args.inNext ?? options.baseFilter?.inNext,
|
|
63
|
+
types: args.type ? [args.type] : options.baseFilter?.types,
|
|
64
|
+
fileTypes: args.fileType ? [args.fileType] : options.baseFilter?.fileTypes,
|
|
65
|
+
offset: args.search ? options.baseFilter?.offset : (args.offset ?? options.baseFilter?.offset),
|
|
66
|
+
limit,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function mapContentMetadata(content) {
|
|
70
|
+
return {
|
|
71
|
+
id: content.id,
|
|
72
|
+
resourceUri: toContentResourceUri(content.id) ?? `contents://${content.id}`,
|
|
73
|
+
name: contentName(content),
|
|
74
|
+
uri: scalarToString(content.uri),
|
|
75
|
+
type: content.type,
|
|
76
|
+
fileType: content.fileType,
|
|
77
|
+
mimeType: content.mimeType,
|
|
78
|
+
creationDate: scalarToString(content.creationDate),
|
|
79
|
+
originalDate: scalarToString(content.originalDate),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function summarizeContent(content, maxTextLength) {
|
|
83
|
+
return truncateText(content.customSummary ??
|
|
84
|
+
content.summary ??
|
|
85
|
+
content.snippet ??
|
|
86
|
+
content.description ??
|
|
87
|
+
"", maxTextLength);
|
|
88
|
+
}
|
|
89
|
+
function mapQueryContent(content, maxTextLength) {
|
|
90
|
+
const { text, truncated } = summarizeContent(content, maxTextLength);
|
|
91
|
+
return {
|
|
92
|
+
...mapContentMetadata(content),
|
|
93
|
+
relevance: content.relevance,
|
|
94
|
+
text,
|
|
95
|
+
truncated,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function mapRetrievedSource(source, content, maxTextLength) {
|
|
99
|
+
const fallback = summarizeContent(content, maxTextLength);
|
|
100
|
+
const sourceText = truncateText(source.text ?? fallback.text, maxTextLength);
|
|
101
|
+
return {
|
|
102
|
+
...mapContentMetadata(content),
|
|
103
|
+
relevance: source.relevance,
|
|
104
|
+
text: sourceText.text,
|
|
105
|
+
truncated: sourceText.truncated || fallback.truncated,
|
|
106
|
+
source: {
|
|
107
|
+
metadata: source.metadata,
|
|
108
|
+
pageNumber: source.pageNumber,
|
|
109
|
+
frameNumber: source.frameNumber,
|
|
110
|
+
startTime: scalarToString(source.startTime),
|
|
111
|
+
endTime: scalarToString(source.endTime),
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
export function createRetrieveContentsTool(client, options = {}) {
|
|
116
|
+
const defaultLimit = options.defaultLimit ?? DEFAULT_LIMIT;
|
|
117
|
+
const maxLimit = options.maxLimit ?? DEFAULT_MAX_LIMIT;
|
|
118
|
+
const maxTextLength = options.maxTextLength ?? DEFAULT_MAX_TEXT_LENGTH;
|
|
119
|
+
return {
|
|
120
|
+
tool: createToolDefinition("retrieve_contents", "Retrieve Graphlit-ingested content for RAG. Use search for text matching, or omit search for filter-only requests such as all emails in the last week.", RetrieveContentsInputSchema),
|
|
121
|
+
handler: async (rawArgs, _artifacts, abortSignal) => {
|
|
122
|
+
throwIfAborted(abortSignal);
|
|
123
|
+
const args = RetrieveContentsInputSchema.parse(rawArgs);
|
|
124
|
+
const limit = clampInteger(args.limit, defaultLimit, 1, maxLimit);
|
|
125
|
+
const filter = buildFilter(args, options, limit);
|
|
126
|
+
const collections = normalizeCollections(options);
|
|
127
|
+
if (!args.search) {
|
|
128
|
+
const response = await client.queryContents(filter);
|
|
129
|
+
const results = response.contents?.results
|
|
130
|
+
?.filter((content) => content != null)
|
|
131
|
+
.map((content) => mapQueryContent(content, maxTextLength)) ?? [];
|
|
132
|
+
return {
|
|
133
|
+
search: null,
|
|
134
|
+
collectionIds: collectionIds(collections),
|
|
135
|
+
results,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
const retrievalStrategy = options.retrievalStrategy ?? {
|
|
139
|
+
type: Types.RetrievalStrategyTypes.Section,
|
|
140
|
+
contentLimit: limit,
|
|
141
|
+
disableFallback: true,
|
|
142
|
+
};
|
|
143
|
+
const rerankingStrategy = options.rerankingStrategy ?? {
|
|
144
|
+
serviceType: Types.RerankingModelServiceTypes.Cohere,
|
|
145
|
+
};
|
|
146
|
+
const retrieved = await client.retrieveSources(args.search, filter, undefined, retrievalStrategy, rerankingStrategy, options.correlationId);
|
|
147
|
+
const sources = retrieved.retrieveSources?.results?.filter((source) => Boolean(source?.content?.id)) ?? [];
|
|
148
|
+
const contentIds = [
|
|
149
|
+
...new Set(sources.map((source) => source.content.id)),
|
|
150
|
+
];
|
|
151
|
+
const lookup = contentIds.length > 0 ? await client.lookupContents(contentIds) : undefined;
|
|
152
|
+
const contentMap = new Map((lookup?.lookupContents?.results ?? [])
|
|
153
|
+
.filter((content) => content != null)
|
|
154
|
+
.map((content) => [content.id, content]));
|
|
155
|
+
const results = sources
|
|
156
|
+
.map((source) => {
|
|
157
|
+
const content = contentMap.get(source.content.id);
|
|
158
|
+
return content
|
|
159
|
+
? mapRetrievedSource(source, content, maxTextLength)
|
|
160
|
+
: null;
|
|
161
|
+
})
|
|
162
|
+
.filter((result) => result != null);
|
|
163
|
+
return {
|
|
164
|
+
search: args.search,
|
|
165
|
+
collectionIds: collectionIds(collections),
|
|
166
|
+
results,
|
|
167
|
+
};
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { GraphlitAgentTool, GraphlitClient } from "../types.js";
|
|
3
|
+
export declare const WaitContentDoneInputSchema: z.ZodObject<{
|
|
4
|
+
id: z.ZodOptional<z.ZodString>;
|
|
5
|
+
resourceUri: z.ZodOptional<z.ZodString>;
|
|
6
|
+
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
7
|
+
pollIntervalMs: z.ZodOptional<z.ZodNumber>;
|
|
8
|
+
}, "strip", z.ZodTypeAny, {
|
|
9
|
+
id?: string | undefined;
|
|
10
|
+
resourceUri?: string | undefined;
|
|
11
|
+
timeoutMs?: number | undefined;
|
|
12
|
+
pollIntervalMs?: number | undefined;
|
|
13
|
+
}, {
|
|
14
|
+
id?: string | undefined;
|
|
15
|
+
resourceUri?: string | undefined;
|
|
16
|
+
timeoutMs?: number | undefined;
|
|
17
|
+
pollIntervalMs?: number | undefined;
|
|
18
|
+
}>;
|
|
19
|
+
export type WaitContentDoneArgs = z.infer<typeof WaitContentDoneInputSchema>;
|
|
20
|
+
export interface WaitContentDoneToolOptions {
|
|
21
|
+
defaultTimeoutMs?: number;
|
|
22
|
+
defaultPollIntervalMs?: number;
|
|
23
|
+
}
|
|
24
|
+
export interface WaitContentDoneResult {
|
|
25
|
+
id: string;
|
|
26
|
+
done: boolean;
|
|
27
|
+
attempts: number;
|
|
28
|
+
elapsedMs: number;
|
|
29
|
+
}
|
|
30
|
+
export declare function createWaitContentDoneTool(client: GraphlitClient, options?: WaitContentDoneToolOptions): GraphlitAgentTool<WaitContentDoneArgs, WaitContentDoneResult>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { delay, throwIfAborted } from "../utils/abort.js";
|
|
3
|
+
import { clampInteger } from "../utils/clamp.js";
|
|
4
|
+
import { parseContentResourceUri } from "../utils/content.js";
|
|
5
|
+
import { createToolDefinition } from "../utils/schema.js";
|
|
6
|
+
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
7
|
+
const DEFAULT_POLL_INTERVAL_MS = 2_000;
|
|
8
|
+
const MIN_POLL_INTERVAL_MS = 250;
|
|
9
|
+
const MAX_TIMEOUT_MS = 300_000;
|
|
10
|
+
export const WaitContentDoneInputSchema = z.object({
|
|
11
|
+
id: z.string().trim().min(1).optional().describe("Graphlit content ID."),
|
|
12
|
+
resourceUri: z
|
|
13
|
+
.string()
|
|
14
|
+
.trim()
|
|
15
|
+
.min(1)
|
|
16
|
+
.optional()
|
|
17
|
+
.describe("Graphlit content resource URI, such as contents://content-id."),
|
|
18
|
+
timeoutMs: z
|
|
19
|
+
.number()
|
|
20
|
+
.int()
|
|
21
|
+
.min(1)
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Maximum time to wait in milliseconds."),
|
|
24
|
+
pollIntervalMs: z
|
|
25
|
+
.number()
|
|
26
|
+
.int()
|
|
27
|
+
.min(MIN_POLL_INTERVAL_MS)
|
|
28
|
+
.optional()
|
|
29
|
+
.describe("Polling interval in milliseconds."),
|
|
30
|
+
});
|
|
31
|
+
function resolveContentId(args) {
|
|
32
|
+
const id = args.id ?? parseContentResourceUri(args.resourceUri);
|
|
33
|
+
if (!id) {
|
|
34
|
+
throw new Error("Provide either id or resourceUri.");
|
|
35
|
+
}
|
|
36
|
+
return id;
|
|
37
|
+
}
|
|
38
|
+
export function createWaitContentDoneTool(client, options = {}) {
|
|
39
|
+
return {
|
|
40
|
+
tool: createToolDefinition("wait_content_done", "Wait until a Graphlit content item has finished processing.", WaitContentDoneInputSchema),
|
|
41
|
+
handler: async (rawArgs, _artifacts, abortSignal) => {
|
|
42
|
+
throwIfAborted(abortSignal);
|
|
43
|
+
const args = WaitContentDoneInputSchema.parse(rawArgs);
|
|
44
|
+
const id = resolveContentId(args);
|
|
45
|
+
const timeoutMs = clampInteger(args.timeoutMs, options.defaultTimeoutMs ?? DEFAULT_TIMEOUT_MS, 1, MAX_TIMEOUT_MS);
|
|
46
|
+
const pollIntervalMs = clampInteger(args.pollIntervalMs, options.defaultPollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS, MIN_POLL_INTERVAL_MS, timeoutMs);
|
|
47
|
+
const startedAt = Date.now();
|
|
48
|
+
let attempts = 0;
|
|
49
|
+
while (Date.now() - startedAt <= timeoutMs) {
|
|
50
|
+
throwIfAborted(abortSignal);
|
|
51
|
+
attempts += 1;
|
|
52
|
+
const response = await client.isContentDone(id);
|
|
53
|
+
const done = response.isContentDone?.result === true;
|
|
54
|
+
if (done) {
|
|
55
|
+
return {
|
|
56
|
+
id,
|
|
57
|
+
done: true,
|
|
58
|
+
attempts,
|
|
59
|
+
elapsedMs: Date.now() - startedAt,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
await delay(pollIntervalMs, abortSignal);
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
id,
|
|
66
|
+
done: false,
|
|
67
|
+
attempts,
|
|
68
|
+
elapsedMs: Date.now() - startedAt,
|
|
69
|
+
};
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Types } from "graphlit-client";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { GraphlitAgentTool, GraphlitClient } from "../types.js";
|
|
4
|
+
export declare const WebSearchInputSchema: z.ZodObject<{
|
|
5
|
+
query: z.ZodString;
|
|
6
|
+
searchService: z.ZodOptional<z.ZodNativeEnum<typeof Types.SearchServiceTypes>>;
|
|
7
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
8
|
+
}, "strip", z.ZodTypeAny, {
|
|
9
|
+
query: string;
|
|
10
|
+
limit?: number | undefined;
|
|
11
|
+
searchService?: Types.SearchServiceTypes | undefined;
|
|
12
|
+
}, {
|
|
13
|
+
query: string;
|
|
14
|
+
limit?: number | undefined;
|
|
15
|
+
searchService?: Types.SearchServiceTypes | undefined;
|
|
16
|
+
}>;
|
|
17
|
+
export type WebSearchArgs = z.infer<typeof WebSearchInputSchema>;
|
|
18
|
+
export interface WebSearchToolOptions {
|
|
19
|
+
defaultSearchService?: Types.SearchServiceTypes;
|
|
20
|
+
defaultLimit?: number;
|
|
21
|
+
maxLimit?: number;
|
|
22
|
+
correlationId?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface WebSearchToolResult {
|
|
25
|
+
query: string;
|
|
26
|
+
searchService: Types.SearchServiceTypes;
|
|
27
|
+
results: Array<{
|
|
28
|
+
title?: string | null;
|
|
29
|
+
uri?: string | null;
|
|
30
|
+
text?: string | null;
|
|
31
|
+
score?: number | null;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
export declare function createWebSearchTool(client: GraphlitClient, options?: WebSearchToolOptions): GraphlitAgentTool<WebSearchArgs, WebSearchToolResult>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Types } from "graphlit-client";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { throwIfAborted } from "../utils/abort.js";
|
|
4
|
+
import { clampInteger } from "../utils/clamp.js";
|
|
5
|
+
import { scalarToString } from "../utils/content.js";
|
|
6
|
+
import { createToolDefinition } from "../utils/schema.js";
|
|
7
|
+
const DEFAULT_LIMIT = 10;
|
|
8
|
+
const DEFAULT_MAX_LIMIT = 20;
|
|
9
|
+
export const WebSearchInputSchema = z.object({
|
|
10
|
+
query: z.string().trim().min(1).describe("Search query."),
|
|
11
|
+
searchService: z
|
|
12
|
+
.nativeEnum(Types.SearchServiceTypes)
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Search service. Defaults to PARALLEL."),
|
|
15
|
+
limit: z
|
|
16
|
+
.number()
|
|
17
|
+
.int()
|
|
18
|
+
.min(1)
|
|
19
|
+
.max(DEFAULT_MAX_LIMIT)
|
|
20
|
+
.optional()
|
|
21
|
+
.describe("Maximum results. Defaults to 10."),
|
|
22
|
+
});
|
|
23
|
+
function mapWebSearchResult(result) {
|
|
24
|
+
return {
|
|
25
|
+
title: result.title,
|
|
26
|
+
uri: scalarToString(result.uri),
|
|
27
|
+
text: result.text,
|
|
28
|
+
score: result.score,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export function createWebSearchTool(client, options = {}) {
|
|
32
|
+
const defaultSearchService = options.defaultSearchService ?? Types.SearchServiceTypes.Parallel;
|
|
33
|
+
const defaultLimit = options.defaultLimit ?? DEFAULT_LIMIT;
|
|
34
|
+
const maxLimit = options.maxLimit ?? DEFAULT_MAX_LIMIT;
|
|
35
|
+
return {
|
|
36
|
+
tool: createToolDefinition("web_search", "Search the public web for current information. Returns URLs, titles, and snippets; it does not ingest results.", WebSearchInputSchema),
|
|
37
|
+
handler: async (rawArgs, _artifacts, abortSignal) => {
|
|
38
|
+
throwIfAborted(abortSignal);
|
|
39
|
+
const args = WebSearchInputSchema.parse(rawArgs);
|
|
40
|
+
const searchService = args.searchService ?? defaultSearchService;
|
|
41
|
+
const limit = clampInteger(args.limit, defaultLimit, 1, maxLimit);
|
|
42
|
+
const response = await client.searchWeb(args.query, searchService, limit, options.correlationId);
|
|
43
|
+
return {
|
|
44
|
+
query: args.query,
|
|
45
|
+
searchService,
|
|
46
|
+
results: response.searchWeb?.results
|
|
47
|
+
?.filter((result) => result != null)
|
|
48
|
+
.map(mapWebSearchResult) ?? [],
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Graphlit, Types } from "graphlit-client";
|
|
2
|
+
export type GraphlitClient = Graphlit;
|
|
3
|
+
export type StreamAgentToolHandlers = NonNullable<Parameters<Graphlit["streamAgent"]>[5]>;
|
|
4
|
+
export type StreamAgentToolHandler = StreamAgentToolHandlers[string];
|
|
5
|
+
export type StreamAgentArtifactCollector = Parameters<StreamAgentToolHandler>[1];
|
|
6
|
+
export type GraphlitToolHandler<TArgs = unknown, TResult = unknown> = (args: TArgs, artifacts?: StreamAgentArtifactCollector, abortSignal?: AbortSignal) => Promise<TResult>;
|
|
7
|
+
export interface GraphlitAgentTool<TArgs = unknown, TResult = unknown> {
|
|
8
|
+
tool: Types.ToolDefinitionInput;
|
|
9
|
+
handler: GraphlitToolHandler<TArgs, TResult>;
|
|
10
|
+
}
|
|
11
|
+
export type ContentReference = Types.EntityReferenceInput;
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function throwIfAborted(abortSignal) {
|
|
2
|
+
if (abortSignal?.aborted) {
|
|
3
|
+
throw new Error("Operation aborted");
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
export function delay(ms, abortSignal) {
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
if (abortSignal?.aborted) {
|
|
9
|
+
reject(new Error("Operation aborted"));
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const timeout = setTimeout(() => {
|
|
13
|
+
cleanup();
|
|
14
|
+
resolve();
|
|
15
|
+
}, ms);
|
|
16
|
+
const onAbort = () => {
|
|
17
|
+
clearTimeout(timeout);
|
|
18
|
+
cleanup();
|
|
19
|
+
reject(new Error("Operation aborted"));
|
|
20
|
+
};
|
|
21
|
+
const cleanup = () => {
|
|
22
|
+
abortSignal?.removeEventListener("abort", onAbort);
|
|
23
|
+
};
|
|
24
|
+
abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
25
|
+
});
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function clampInteger(value: number | undefined, fallback: number, minimum: number, maximum: number): number;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Types } from "graphlit-client";
|
|
2
|
+
import type { ContentReference } from "../types.js";
|
|
3
|
+
export declare function toContentResourceUri(id: string | null | undefined): string | null;
|
|
4
|
+
export declare function parseContentResourceUri(uri: string | null | undefined): string | null;
|
|
5
|
+
export declare function contentName(content: {
|
|
6
|
+
fileName?: string | null;
|
|
7
|
+
name?: string | null;
|
|
8
|
+
}): string;
|
|
9
|
+
export declare function normalizeCollections(options: {
|
|
10
|
+
collectionId?: string;
|
|
11
|
+
collections?: ContentReference[];
|
|
12
|
+
}): Types.EntityReferenceInput[] | undefined;
|
|
13
|
+
export declare function collectionIds(collections: Types.EntityReferenceInput[] | undefined): string[];
|
|
14
|
+
export declare function scalarToString(value: unknown): string | null;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function toContentResourceUri(id) {
|
|
2
|
+
return id ? `contents://${id}` : null;
|
|
3
|
+
}
|
|
4
|
+
export function parseContentResourceUri(uri) {
|
|
5
|
+
if (!uri) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
return uri.startsWith("contents://") ? uri.slice("contents://".length) : null;
|
|
9
|
+
}
|
|
10
|
+
export function contentName(content) {
|
|
11
|
+
return content.fileName || content.name || "Untitled content";
|
|
12
|
+
}
|
|
13
|
+
export function normalizeCollections(options) {
|
|
14
|
+
if (options.collections?.length) {
|
|
15
|
+
return options.collections.map(({ id }) => ({ id }));
|
|
16
|
+
}
|
|
17
|
+
return options.collectionId ? [{ id: options.collectionId }] : undefined;
|
|
18
|
+
}
|
|
19
|
+
export function collectionIds(collections) {
|
|
20
|
+
return collections?.map((collection) => collection.id).filter(Boolean) ?? [];
|
|
21
|
+
}
|
|
22
|
+
export function scalarToString(value) {
|
|
23
|
+
if (value === null || value === undefined) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
return typeof value === "string" ? value : String(value);
|
|
27
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Types } from "graphlit-client";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
export declare function toToolSchema(schema: z.ZodTypeAny): string;
|
|
4
|
+
export declare function createToolDefinition(name: string, description: string, schema: z.ZodTypeAny): Types.ToolDefinitionInput;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
2
|
+
function stripUnsupportedSchemaFields(value) {
|
|
3
|
+
if (Array.isArray(value)) {
|
|
4
|
+
return value.map(stripUnsupportedSchemaFields);
|
|
5
|
+
}
|
|
6
|
+
if (!value || typeof value !== "object") {
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
const input = value;
|
|
10
|
+
const output = {};
|
|
11
|
+
for (const [key, nestedValue] of Object.entries(input)) {
|
|
12
|
+
if (key === "$schema" || key === "definitions" || key === "$defs") {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
output[key] = stripUnsupportedSchemaFields(nestedValue);
|
|
16
|
+
}
|
|
17
|
+
return output;
|
|
18
|
+
}
|
|
19
|
+
export function toToolSchema(schema) {
|
|
20
|
+
const jsonSchema = zodToJsonSchema(schema, {
|
|
21
|
+
$refStrategy: "none",
|
|
22
|
+
target: "jsonSchema7",
|
|
23
|
+
});
|
|
24
|
+
return JSON.stringify(stripUnsupportedSchemaFields(jsonSchema));
|
|
25
|
+
}
|
|
26
|
+
export function createToolDefinition(name, description, schema) {
|
|
27
|
+
return {
|
|
28
|
+
name,
|
|
29
|
+
description,
|
|
30
|
+
schema: toToolSchema(schema),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function truncateText(text, maxLength) {
|
|
2
|
+
const value = text?.trim() ?? "";
|
|
3
|
+
if (!value || value.length <= maxLength) {
|
|
4
|
+
return { text: value, truncated: false };
|
|
5
|
+
}
|
|
6
|
+
return {
|
|
7
|
+
text: `${value.slice(0, Math.max(0, maxLength - 3))}...`,
|
|
8
|
+
truncated: true,
|
|
9
|
+
};
|
|
10
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@graphlit/agent-tools",
|
|
3
|
+
"version": "1.0.20260611003",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Top-level Graphlit tool factories for TypeScript streamAgent applications",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public",
|
|
20
|
+
"registry": "https://registry.npmjs.org/"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/graphlit/graphlit-agent-tools.git"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"Graphlit",
|
|
28
|
+
"agents",
|
|
29
|
+
"tools",
|
|
30
|
+
"RAG",
|
|
31
|
+
"streamAgent",
|
|
32
|
+
"LLM"
|
|
33
|
+
],
|
|
34
|
+
"author": "Unstruk Data Inc.",
|
|
35
|
+
"contributors": [
|
|
36
|
+
"Kirk Marple (https://github.com/kirk-marple)"
|
|
37
|
+
],
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=20.0.0"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsc -p tsconfig.json",
|
|
44
|
+
"format": "prettier --write .",
|
|
45
|
+
"test": "vitest run",
|
|
46
|
+
"prepublishOnly": "npm run build && npm test"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"zod": "^3.25.76",
|
|
50
|
+
"zod-to-json-schema": "^3.24.6"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"graphlit-client": ">=1.0.20260609001"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/node": "^20.19.27",
|
|
57
|
+
"graphlit-client": "^1.0.20260609001",
|
|
58
|
+
"prettier": "^3.7.4",
|
|
59
|
+
"typescript": "^5.9.3",
|
|
60
|
+
"vitest": "^3.2.4"
|
|
61
|
+
}
|
|
62
|
+
}
|