@moss-tools/mastra 0.1.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.
- package/LICENSE +25 -0
- package/README.md +117 -0
- package/dist/index.d.ts +63 -0
- package/dist/index.js +63 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
BSD 2-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025, InferEdge Inc.
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
17
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
18
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
19
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
20
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
21
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
22
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
23
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
24
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
25
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# @moss-tools/mastra
|
|
2
|
+
|
|
3
|
+
Moss semantic search tools for [Mastra](https://mastra.ai) agents.
|
|
4
|
+
|
|
5
|
+
Wraps Moss into `createTool()` primitives that drop straight into any Mastra agent. Sub-10ms lookups, no external embedder, no vector database to run.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @moss-tools/mastra @moss-dev/moss @mastra/core zod
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Prerequisites
|
|
14
|
+
|
|
15
|
+
- Moss project ID and project key — get them from the [Moss Portal](https://portal.usemoss.dev)
|
|
16
|
+
- Node.js 18+
|
|
17
|
+
|
|
18
|
+
## Quickstart
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { Agent } from '@mastra/core/agent';
|
|
22
|
+
import { MossClient } from '@moss-dev/moss';
|
|
23
|
+
import { mossSearchTool } from '@moss-tools/mastra';
|
|
24
|
+
|
|
25
|
+
const client = new MossClient(
|
|
26
|
+
process.env.MOSS_PROJECT_ID!,
|
|
27
|
+
process.env.MOSS_PROJECT_KEY!
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
// Load the index once at startup for sub-10ms queries
|
|
31
|
+
await client.loadIndex('my-index');
|
|
32
|
+
|
|
33
|
+
const agent = new Agent({
|
|
34
|
+
id: 'support-agent',
|
|
35
|
+
name: 'Knowledge Support Copilot',
|
|
36
|
+
instructions: 'Use moss_search to find relevant information before answering.',
|
|
37
|
+
model: 'openai/gpt-4.1-mini',
|
|
38
|
+
tools: {
|
|
39
|
+
search: mossSearchTool({ client, indexName: 'my-index' }),
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const response = await agent.generate('What is your refund policy?');
|
|
44
|
+
console.log(response.text);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Available tools
|
|
48
|
+
|
|
49
|
+
### `mossSearchTool`
|
|
50
|
+
|
|
51
|
+
Searches a Moss index and returns ranked documents.
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { mossSearchTool } from '@moss-tools/mastra';
|
|
55
|
+
|
|
56
|
+
// Pre-bound to an index — LLM only needs to supply { query }
|
|
57
|
+
const searchBound = mossSearchTool({ client, indexName: 'my-index' });
|
|
58
|
+
|
|
59
|
+
// Dynamic — LLM supplies { indexName, query }
|
|
60
|
+
const searchDynamic = mossSearchTool({ client });
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Options:**
|
|
64
|
+
|
|
65
|
+
| Option | Default | Description |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| `client` | (required) | `MossClient` instance |
|
|
68
|
+
| `indexName` | — | Pre-bind to an index; when omitted the LLM must provide it |
|
|
69
|
+
| `topK` | `5` | Number of results to return |
|
|
70
|
+
| `alpha` | `0.8` | Search blend: 1.0 = semantic only, 0.0 = keyword only |
|
|
71
|
+
| `id` | `"moss_search"` | Mastra tool ID |
|
|
72
|
+
| `description` | *(auto)* | Tool description shown to the LLM |
|
|
73
|
+
|
|
74
|
+
### `mossAddDocsTool`
|
|
75
|
+
|
|
76
|
+
Adds or upserts documents into a Moss index. Useful for agents that learn and store information during a conversation.
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { mossAddDocsTool } from '@moss-tools/mastra';
|
|
80
|
+
|
|
81
|
+
const addDocs = mossAddDocsTool({ client, indexName: 'my-index' });
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Options:**
|
|
85
|
+
|
|
86
|
+
| Option | Default | Description |
|
|
87
|
+
|---|---|---|
|
|
88
|
+
| `client` | (required) | `MossClient` instance |
|
|
89
|
+
| `indexName` | — | Pre-bind to an index |
|
|
90
|
+
| `id` | `"moss_add_docs"` | Mastra tool ID |
|
|
91
|
+
| `description` | *(auto)* | Tool description shown to the LLM |
|
|
92
|
+
|
|
93
|
+
## Agent with both tools
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
const agent = new Agent({
|
|
97
|
+
id: 'learning-agent',
|
|
98
|
+
instructions:
|
|
99
|
+
'You are a support assistant. Search the knowledge base with moss_search. ' +
|
|
100
|
+
'If you learn something new that should be remembered, store it with moss_add_docs.',
|
|
101
|
+
model: 'openai/gpt-4.1-mini',
|
|
102
|
+
tools: {
|
|
103
|
+
search: mossSearchTool({ client, indexName: 'support-kb' }),
|
|
104
|
+
addDocs: mossAddDocsTool({ client, indexName: 'support-kb' }),
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
BSD 2-Clause — see [LICENSE](LICENSE).
|
|
112
|
+
|
|
113
|
+
## Support
|
|
114
|
+
|
|
115
|
+
- [Moss Docs](https://docs.moss.dev)
|
|
116
|
+
- [Moss Discord](https://discord.gg/eMXExuafBR)
|
|
117
|
+
- [Mastra Docs](https://mastra.ai/docs)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as _mastra_core_tools from '@mastra/core/tools';
|
|
2
|
+
import { MossClient } from '@moss-dev/moss';
|
|
3
|
+
|
|
4
|
+
interface MossSearchToolOptions {
|
|
5
|
+
/** Moss client instance. */
|
|
6
|
+
client: MossClient;
|
|
7
|
+
/** Pre-bind to a specific index. When omitted the LLM must supply `indexName`. */
|
|
8
|
+
indexName?: string;
|
|
9
|
+
/** Number of results to return (default: 5). */
|
|
10
|
+
topK?: number;
|
|
11
|
+
/** Hybrid search blend — 1.0 = semantic only, 0.0 = keyword only (default: 0.8). */
|
|
12
|
+
alpha?: number;
|
|
13
|
+
/** Override the Mastra tool `id`. */
|
|
14
|
+
id?: string;
|
|
15
|
+
/** Override the tool description shown to the LLM. */
|
|
16
|
+
description?: string;
|
|
17
|
+
}
|
|
18
|
+
interface MossAddDocsToolOptions {
|
|
19
|
+
/** Moss client instance. */
|
|
20
|
+
client: MossClient;
|
|
21
|
+
/** Pre-bind to a specific index. When omitted the LLM must supply `indexName`. */
|
|
22
|
+
indexName?: string;
|
|
23
|
+
/** Override the Mastra tool `id`. */
|
|
24
|
+
id?: string;
|
|
25
|
+
/** Override the tool description shown to the LLM. */
|
|
26
|
+
description?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Creates a Mastra tool that searches a Moss index.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { Agent } from '@mastra/core/agent';
|
|
34
|
+
* import { MossClient } from '@moss-dev/moss';
|
|
35
|
+
* import { mossSearchTool } from '@moss-tools/mastra';
|
|
36
|
+
*
|
|
37
|
+
* const client = new MossClient(process.env.MOSS_PROJECT_ID!, process.env.MOSS_PROJECT_KEY!);
|
|
38
|
+
* await client.loadIndex('my-index');
|
|
39
|
+
*
|
|
40
|
+
* const agent = new Agent({
|
|
41
|
+
* id: 'support-agent',
|
|
42
|
+
* instructions: 'Use moss_search to answer questions from the knowledge base.',
|
|
43
|
+
* model: 'openai/gpt-4.1-mini',
|
|
44
|
+
* tools: { search: mossSearchTool({ client, indexName: 'my-index' }) },
|
|
45
|
+
* });
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
declare function mossSearchTool(options: MossSearchToolOptions): _mastra_core_tools.Tool<{
|
|
49
|
+
query: string;
|
|
50
|
+
}, unknown, unknown, unknown, _mastra_core_tools.ToolExecutionContext<unknown, unknown, unknown>, string, unknown>;
|
|
51
|
+
/**
|
|
52
|
+
* Creates a Mastra tool that adds or upserts documents into a Moss index.
|
|
53
|
+
* Useful for agents that learn and store new information during a conversation.
|
|
54
|
+
*/
|
|
55
|
+
declare function mossAddDocsTool(options: MossAddDocsToolOptions): _mastra_core_tools.Tool<{
|
|
56
|
+
docs: {
|
|
57
|
+
id: string;
|
|
58
|
+
text: string;
|
|
59
|
+
metadata?: Record<string, string> | undefined;
|
|
60
|
+
}[];
|
|
61
|
+
}, unknown, unknown, unknown, _mastra_core_tools.ToolExecutionContext<unknown, unknown, unknown>, string, unknown>;
|
|
62
|
+
|
|
63
|
+
export { type MossAddDocsToolOptions, type MossSearchToolOptions, mossAddDocsTool, mossSearchTool };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// src/tools.ts
|
|
2
|
+
import { createTool } from "@mastra/core/tools";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
var docSchema = z.object({
|
|
5
|
+
id: z.string().describe("Unique document identifier."),
|
|
6
|
+
text: z.string().describe("Text content to embed and store."),
|
|
7
|
+
metadata: z.record(z.string()).optional().describe("Optional key-value metadata.")
|
|
8
|
+
});
|
|
9
|
+
function mossSearchTool(options) {
|
|
10
|
+
const {
|
|
11
|
+
client,
|
|
12
|
+
indexName: boundIndex,
|
|
13
|
+
topK = 5,
|
|
14
|
+
alpha = 0.8,
|
|
15
|
+
id = "moss_search",
|
|
16
|
+
description
|
|
17
|
+
} = options;
|
|
18
|
+
const baseFields = {
|
|
19
|
+
query: z.string().describe("The semantic search query.")
|
|
20
|
+
};
|
|
21
|
+
const inputSchema = boundIndex != null ? z.object(baseFields) : z.object({
|
|
22
|
+
indexName: z.string().describe("Name of the Moss index to search."),
|
|
23
|
+
...baseFields
|
|
24
|
+
});
|
|
25
|
+
return createTool({
|
|
26
|
+
id,
|
|
27
|
+
description: description ?? "Search the knowledge base using Moss semantic search. Returns the most relevant documents for a given query.",
|
|
28
|
+
inputSchema,
|
|
29
|
+
execute: async (input) => {
|
|
30
|
+
const index = boundIndex ?? input.indexName;
|
|
31
|
+
const result = await client.query(index, input.query, { topK, alpha });
|
|
32
|
+
return result.docs.map((doc) => ({
|
|
33
|
+
text: doc.text,
|
|
34
|
+
score: doc.score,
|
|
35
|
+
...doc.metadata ? { metadata: doc.metadata } : {}
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function mossAddDocsTool(options) {
|
|
41
|
+
const { client, indexName: boundIndex, id = "moss_add_docs", description } = options;
|
|
42
|
+
const baseFields = {
|
|
43
|
+
docs: z.array(docSchema).min(1).max(50).describe("Documents to add or update in the index (1-50).")
|
|
44
|
+
};
|
|
45
|
+
const inputSchema = boundIndex != null ? z.object(baseFields) : z.object({
|
|
46
|
+
indexName: z.string().describe("Name of the Moss index to add documents to."),
|
|
47
|
+
...baseFields
|
|
48
|
+
});
|
|
49
|
+
return createTool({
|
|
50
|
+
id,
|
|
51
|
+
description: description ?? "Add or update documents in a Moss knowledge base index. Use this to store new information for future retrieval.",
|
|
52
|
+
inputSchema,
|
|
53
|
+
execute: async (input) => {
|
|
54
|
+
const index = boundIndex ?? input.indexName;
|
|
55
|
+
const result = await client.addDocs(index, input.docs, { upsert: true });
|
|
56
|
+
return { jobId: result.jobId, docCount: result.docCount };
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
export {
|
|
61
|
+
mossAddDocsTool,
|
|
62
|
+
mossSearchTool
|
|
63
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@moss-tools/mastra",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Moss semantic search tools for Mastra agents",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup src/index.ts --format esm --dts --clean",
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"test": "vitest run"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"mastra",
|
|
25
|
+
"moss",
|
|
26
|
+
"semantic-search",
|
|
27
|
+
"rag",
|
|
28
|
+
"ai-agent",
|
|
29
|
+
"inferedge"
|
|
30
|
+
],
|
|
31
|
+
"author": "InferEdge Inc.",
|
|
32
|
+
"license": "BSD-2-Clause",
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@mastra/core": ">=1.0.0",
|
|
35
|
+
"@moss-dev/moss": "^1.0.0",
|
|
36
|
+
"zod": "^3.0.0 || ^4.0.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@mastra/core": "1.26.0",
|
|
40
|
+
"@moss-dev/moss": "1.0.0",
|
|
41
|
+
"@types/node": "22.13.14",
|
|
42
|
+
"tsup": "8.4.0",
|
|
43
|
+
"typescript": "5.8.2",
|
|
44
|
+
"vitest": "3.1.1",
|
|
45
|
+
"zod": "3.25.76"
|
|
46
|
+
}
|
|
47
|
+
}
|