Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion examples/01-agent-code-skill/01-prompting.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Agent } from '@smythos/sdk';
import { Agent, Scope } from '@smythos/sdk';

async function main() {
const agent = new Agent({
id: 'crypto-market-assistant',
teamId: 'the-matrix',
name: 'CryptoMarket Assistant',
behavior: 'You are a crypto price tracker. You are given a coin id and you need to get the price of the coin in USD',
model: 'gpt-4o',
Expand All @@ -18,6 +20,9 @@ async function main() {
},
});

const storage = agent.storage.LocalStorage({ scope: Scope.TEAM });
await storage.write('test0001.txt', 'Hello, world!');

//this will prompt the agent and use the agent's LLM to determine which skill to use
const promptResult = await agent.prompt('What are the current prices of Bitcoin and Ethereum ?');
//the response comes back in natural language
Expand Down
3 changes: 0 additions & 3 deletions examples/02-agent-smyth-file/01-load-prompt-smyth-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ async function main() {

console.log(result);

const mcpUrl = await agent.mcp(MCPTransport.SSE, 3399);

console.log(`MCP server started on ${mcpUrl}`);
}

main();
17 changes: 17 additions & 0 deletions examples/06-Storage-no-agent/01-localstorage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Storage } from '@smythos/sdk';

async function main() {
const localStorage = Storage.LocalStorage();

await localStorage.write('test.txt', 'Hello, world!');

const data = await localStorage.read('test.txt');

const dataAsString = data.toString();

console.log(dataAsString);


}

main();
21 changes: 21 additions & 0 deletions examples/06-Storage-no-agent/02-S3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Storage } from '@smythos/sdk';

async function main() {
const localStorage = Storage.S3({
region: process.env.AWS_REGION,
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
bucket: process.env.AWS_BUCKET_NAME
})

await localStorage.write('test.txt', 'Hello, world!');

const data = await localStorage.read('test.txt');

const dataAsString = data.toString();

console.log(dataAsString);

}

main();
54 changes: 54 additions & 0 deletions examples/07-Storage-with-agent/01-data-isolation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Agent, Scope } from '@smythos/sdk';

async function main() {

const agentNeo = new Agent({
id: 'agent-neo',
teamId: 'the-matrix',
name: 'Agent Neo',
behavior: 'You are a helpful assistant that can answer questions and help with tasks.',
model: 'gpt-4o',
});

const agentTrinity = new Agent({
id: 'agent-trinity',
teamId: 'the-matrix',
name: 'Agent Trinity',
behavior: 'You are a helpful assistant that can answer questions and help with tasks.',
model: 'gpt-4o',
});



//in this first part, the scopes are isolated because we use the default storage scope
const NeoStorage = agentNeo.storage.LocalStorage();
const TrinityStorage = agentTrinity.storage.LocalStorage();


await NeoStorage.write('neo.txt', 'Hello, Neo!');


const neo_data = await NeoStorage.read('neo.txt');
const trinity_data = await TrinityStorage.read('neo.txt');

console.log('Neo reading neo.txt', neo_data?.toString()); //data = 'Hello, Neo!'
console.log('Trinity reading neo.txt', trinity_data?.toString()); //data is empty



//in this second part, the scopes are shared because we explicitly set the scope to Scope.TEAM
//this means that all the agents in the same team share the same storage
const neoSharedStorage = agentNeo.storage.LocalStorage({}, Scope.TEAM);
const trinitySharedStorage = agentTrinity.storage.LocalStorage({}, Scope.TEAM);

await neoSharedStorage.write('team.txt', 'Hello, Team!');

const neo_data2 = await neoSharedStorage.read('team.txt');
const trinity_data2 = await trinitySharedStorage.read('team.txt');

console.log('Neo reading neo.txt', neo_data2?.toString()); //data = 'Hello, Team!'
console.log('Trinity reading neo.txt', trinity_data2?.toString()); //data = 'Hello, Team!'

}

main();
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sre",
"version": "0.0.7",
"version": "0.0.9",
"description": "",
"author": "Alaa-eddine KADDOURI",
"license": "MIT",
Expand Down
23 changes: 20 additions & 3 deletions packages/core/src/subsystems/IO/Storage.service/SmythFS.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,24 @@ export class SmythFS {
return data ? this.toBuffer(data) : null;
}

public async write(uri: string, data: any, candidate?: IAccessCandidate, metadata?: StorageMetadata, ttl?: number) {

public async getMetadata(uri: string, candidate?: IAccessCandidate) {
const smythURI = await this.URIParser(uri);
if (!smythURI) throw new Error('Invalid Resource URI');
candidate = candidate || smythURI.defaultCandidate; //fallback to default candidate if not provided

const accountConnector = ConnectorService.getAccountConnector();
const isMember = await accountConnector.isTeamMember(smythURI.team, candidate);
if (!isMember) throw new Error('Access Denied');

const resourceId = `teams/${smythURI.team}${smythURI.path}`;

const _candidate = candidate instanceof AccessCandidate ? candidate : new AccessCandidate(candidate);

return await this.storage.requester(_candidate).getMetadata(resourceId);
}

public async write(uri: string, data: StorageData, candidate?: IAccessCandidate, metadata?: StorageMetadata, ttl?: number) {
const smythURI = await this.URIParser(uri);
if (!smythURI) throw new Error('Invalid Resource URI');
candidate = candidate || smythURI.defaultCandidate; //fallback to default candidate if not provided
Expand Down Expand Up @@ -380,10 +397,10 @@ export class SmythFS {
let candidate: IAccessCandidate;
if (user) {
candidate = AccessCandidate.user(user);
basePath = '/' + user;
basePath = '.user/' + user;
} else if (agent) {
candidate = AccessCandidate.agent(agent);
basePath = '/' + agent;
basePath = '.agent/' + agent;
}

if (candidate) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export type LocalStorageConfig = {
folder?: string;
};

//TODO : detect and store ContentType metadata when saving

export class LocalStorage extends StorageConnector {
public name = 'LocalStorage';
private folder: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,15 @@ import { ConnectorService } from '@sre/Core/ConnectorsService';

const console = Logger('S3Storage');

export type S3Config = AWSCredentials & AWSRegionConfig & { bucket: string };
//export type S3Config = AWSCredentials & AWSRegionConfig & { bucket: string };

//We need to flatten the S3Config type in order to make it work with the SDK
export type S3Config = {
region: string;
accessKeyId: string;
secretAccessKey: string;
bucket: string;
};

export class S3Storage extends StorageConnector {
public name = 'S3Storage';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ export class AccessCandidate implements IAccessCandidate {
//this._candidate = candidate || { role: TAccessRole.Public, id: '' };

this.role = candidate ? candidate.role : TAccessRole.Public;
this.id = candidate ? candidate.id : '';
this.id = candidate ? this._validateId(candidate.id) : '';
}

private _validateId(id: string) {
if (/[^a-zA-Z0-9-]/.test(id))
throw new Error('Access Candidate ID can only contain alphanumeric characters and hyphens');
return id;
}

public toString(): string {
Expand Down
92 changes: 0 additions & 92 deletions packages/sdk/docs/08-advanced-topics.md
Original file line number Diff line number Diff line change
@@ -1,92 +0,0 @@
# Advanced Topics

This section covers more specialized features of the SmythOS SDK that you can use to build even more sophisticated applications.

## Team Management

In SmythOS, agents can be grouped into **Teams**. A Team provides a shared context and resources for a group of agents. For example, all agents within a team can share the same Storage and Vector Database instances, allowing them to collaborate and share knowledge seamlessly.

Every agent belongs to a team. By default, agents are assigned to a default team, but you can create and manage teams for more complex, multi-agent scenarios.

### Accessing Team Resources

You can access a team's shared resources through the `agent.team` property. This is particularly useful for managing team-level data that should be accessible to all agents in that team.

```typescript
import { Agent, Team } from '@smythos/sdk';

async function main() {
// Create a new team. In a real app, this ID would be persisted.
const devTeam = new Team('dev-team-01');

// Create an agent and assign it to the team by passing the teamId
const agent = new Agent({
name: 'Team Lead',
model: 'gpt-4o',
teamId: devTeam.id,
});

// Access the team's shared storage via the agent
const teamStorage = agent.team.storage.LocalStorage();

// Write a file to the team's storage
await teamStorage.write('project-docs.txt', 'Project Phoenix kickoff is Monday.');
console.log('Shared document saved to team storage.');

// Another agent on the same team could now access this file.
}

main();
```

## Document Parsing

The SDK includes a powerful and extensible document parsing engine. This allows you to easily extract text and metadata from various file formats, which is a common first step for populating a Vector Database or feeding information to an agent.

The `DocParser` can be used to automatically detect the file type and use the correct parser.

### Supported Formats

- PDF
- DOCX (Microsoft Word)
- Markdown
- Plain Text

### Example

Here's how you can use the `DocParser` to extract the content of a PDF file:

```typescript
import { DocParser } from '@smythos/sdk';
import fs from 'fs';
import path from 'path';

async function main() {
// Create a dummy PDF file for the example
const pdfPath = path.resolve(__dirname, 'sample.pdf');
// In a real scenario, you would have an actual PDF file here.
// For this example, we'll just pretend the buffer is from a PDF.
const pdfBuffer = Buffer.from('This is a sample PDF content.');

// 1. Create a parser instance
const parser = new DocParser();

// 2. Parse the document from a buffer
// The parser will inspect the buffer to determine the file type.
const doc = await parser.parse(pdfBuffer);

// 3. Access the extracted content
console.log('--- Document Metadata ---');
console.log(doc.metadata);
console.log('\n--- Document Content ---');
console.log(doc.content);

// The 'doc' object can now be used, for example,
// to insert its content into a Vector Database.
// await vectorDB.insertDoc('my-pdf-doc', doc.content);
}

main();
```

More guides on deployment, custom components, and best practices will be published here as the SDK matures.
Loading