Skip to content

Commit

Permalink
docs: remove toc from first tool guide and add unique ids to markdown
Browse files Browse the repository at this point in the history
headers

- The default table of contents is incompatible with tabs, so remove it
  from the first-tool guide
- Auto-generated IDs for markdown headers in the first-tool page aren't
  unique, so generate unique IDs and inject them at snippet fetch time
- Re-fetch latest README.md files from `*-hash-tool` repos to fix
  guide doc formatting issues

Signed-off-by: Nick Hale <[email protected]>
  • Loading branch information
njhale committed Nov 20, 2024
1 parent 9d30f07 commit f1e12f1
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 37 deletions.
18 changes: 11 additions & 7 deletions docs/docs/03-guides/01-first-tool.mdx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
---
hide_table_of_contents: true
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

Expand All @@ -14,16 +18,16 @@ The following guides will show you how to write and package custom Tools in Pyth
unleashing the full potential of your Agents by enabling them to integrate with any data source, service,
or platform with just a few lines of code.

<Tabs>
<TabItem value="python" label="Python" default>
<PythonHashToolReadme />
<Tabs queryString="language">
<TabItem value="python" label="Python" id="python-tab">
<PythonHashToolReadme />
</TabItem>

<TabItem value="node" label="Node.js" default>
<NodeHashToolReadme />
<TabItem value="node" label="Node.js" id="node-tab">
<NodeHashToolReadme />
</TabItem>

<TabItem value="go" label="Go" default>
<GoHashToolReadme />
<TabItem value="go" label="Go" id="go-tab">
<GoHashToolReadme />
</TabItem>
</Tabs>
18 changes: 9 additions & 9 deletions docs/snippets/go-hash-tool-readme.md.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Writing your first tool in Go
## Writing your first tool in Go {#writing-your-first-tool-in-go-eb5bb8c4}

[go-hash-tool](https://github.com/otto8-ai/go-hash-tool) contains a reference `Go` implementation of the `Hash` Tool.

Expand All @@ -12,7 +12,7 @@ git clone [email protected]:otto8-ai/go-hash-tool

<br/>

## Tool Repo Structure
## Tool Repo Structure {#tool-repo-structure-eb5bb8c4}

The directory tree below highlights the files required to implement `Hash` in Go and package it for `Otto8`.

Expand All @@ -30,7 +30,7 @@ go-hash-tool
<br/>

## Defining the `Hash` Tool
## Defining the `Hash` Tool {#defining-the-hash-tool-eb5bb8c4}

The `tool.gpt` file contains [GPTScript Tool Definitions](https://docs.gptscript.ai/tools/gpt-file-reference) which describe a set of Tools that can be used by Agents in `Otto8`.
Every Tool repository must have a `tool.gpt` file in its root directory.
Expand Down Expand Up @@ -89,7 +89,7 @@ Param: algo: The algorithm to generate a hash with. Default is "sha256". Support

<br/>

## Tool Metadata
## Tool Metadata {#tool-metadata-eb5bb8c4}

The `tool.gpt` file also provides the following metadata for use in `Otto8`:

Expand Down Expand Up @@ -150,7 +150,7 @@ https://cdn.jsdelivr.net/npm/@phosphor-icons/core@2/assets/duotone/fingerprint-d

<br/>

## Implementing Business Logic
## Implementing Business Logic {#implementing-business-logic-eb5bb8c4}

The `main.go` file is the entry point of the `gptscript-go-tool` binary that is executed by `Otto8` when the `Hash` Tool is called.

Expand Down Expand Up @@ -202,7 +202,7 @@ The Body of the `Verify` Tool definition would then simply pass `verify` to `gpt

```yaml
Name: Verify
# ...
# ... {#-eb5bb8c4}
#!{GPTSCRIPT_TOOL_DIR}/bin/gptscript-go-tool verify
```
Expand Down Expand Up @@ -371,7 +371,7 @@ func keys[V any](m map[string]V) []string {

<br/>

## Testing `main.go` Locally
## Testing `main.go` Locally {#testing-main-go-locally-eb5bb8c4}

Before adding a Tool to `Otto8`, verify that the Go business logic works on your machine.

Expand All @@ -394,7 +394,7 @@ To do this, run through the following steps in the root of your local fork:

<br/>

## Adding The `Hash` Tool to `Otto8`
## Adding The `Hash` Tool to `Otto8` {#adding-the-hash-tool-to-otto8-eb5bb8c4}

Before a Tool can be used by an Agent, an admin must first add the Tool to `Otto8` by performing the steps below:

Expand Down Expand Up @@ -432,7 +432,7 @@ Before a Tool can be used by an Agent, an admin must first add the Tool to `Otto
</div>
</details>

## Using The `Hash` Tool in an Agent
## Using The `Hash` Tool in an Agent {#using-the-hash-tool-in-an-agent-eb5bb8c4}

To use the `Hash` Tool in an Agent, open the Agent's Edit page, then:

Expand Down
18 changes: 9 additions & 9 deletions docs/snippets/node-hash-tool-readme.md.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Writing your first tool in Node.js (with Typescript)
## Writing your first tool in Node.js (with Typescript) {#writing-your-first-tool-in-node-js-with-typescript-aeed7f15}

[node-hash-tool](https://github.com/otto8-ai/node-hash-tool) contains a reference Typescript `Node.js` implementation of the `Hash` Tool.

Expand All @@ -11,7 +11,7 @@ git clone [email protected]:otto8-ai/node-hash-tool
```
<br/>

## Tool Repo Structure
## Tool Repo Structure {#tool-repo-structure-aeed7f15}

The directory tree below highlights the files required to implement `Hash` in Typescript and package it for `Otto8`.

Expand All @@ -31,7 +31,7 @@ node-hash-tool
<br/>

## Defining the `Hash` Tool
## Defining the `Hash` Tool {#defining-the-hash-tool-aeed7f15}

The `tool.gpt` file contains [GPTScript Tool Definitions](https://docs.gptscript.ai/tools/gpt-file-reference) which describe a set of Tools that can be used by Agents in `Otto8`.
Every Tool repository must have a `tool.gpt` file in its root directory.
Expand Down Expand Up @@ -90,7 +90,7 @@ Param: algo: The algorithm to generate a hash with. Default is "sha256". Support

<br/>

## Tool Metadata
## Tool Metadata {#tool-metadata-aeed7f15}

The `tool.gpt` file also provides the following metadata for use in `Otto8`:

Expand Down Expand Up @@ -151,7 +151,7 @@ https://cdn.jsdelivr.net/npm/@phosphor-icons/core@2/assets/duotone/fingerprint-d

<br/>

## Implementing Business Logic
## Implementing Business Logic {#implementing-business-logic-aeed7f15}

As we saw earlier, the `npm` command invoked by the `Tool Body` passes `hash` as an argument to the `tool` script.

Expand Down Expand Up @@ -226,7 +226,7 @@ And the Body of the `Verify` Tool would pass `verify` to the `tool` script inste

```yaml
Name: Verify
# ...
# ... {#-aeed7f15}

#!/usr/bin/env npm --silent --prefix ${GPTSCRIPT_TOOL_DIR} run tool -- verify
```
Expand Down Expand Up @@ -351,7 +351,7 @@ export function hash(data: string = '', algo = 'sha256'): string {

<br/>

## Testing `src/tools.ts` and `src/hash.ts` Locally
## Testing `src/tools.ts` and `src/hash.ts` Locally {#testing-src-tools-ts-and-src-hash-ts-locally-aeed7f15}

Before adding a Tool to `Otto8`, verify that the Typescript business logic works on your machine.

Expand All @@ -374,7 +374,7 @@ To do this, run through the following steps in the root of your local fork:

<br/>

## Adding The `Hash` Tool to `Otto8`
## Adding The `Hash` Tool to `Otto8` {#adding-the-hash-tool-to-otto8-aeed7f15}

Before a Tool can be used by an Agent, an admin must first add the Tool to `Otto8` by performing the steps below:

Expand Down Expand Up @@ -412,7 +412,7 @@ Before a Tool can be used by an Agent, an admin must first add the Tool to `Otto
</div>
</details>

## Using The `Hash` Tool in an Agent
## Using The `Hash` Tool in an Agent {#using-the-hash-tool-in-an-agent-aeed7f15}

To use the `Hash` Tool in an Agent, open the Agent's Edit page, then:

Expand Down
16 changes: 8 additions & 8 deletions docs/snippets/python-hash-tool-readme.md.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Writing your first tool in Python
## Writing your first tool in Python {#writing-your-first-tool-in-python-28572835}

[python-hash-tool](https://github.com/otto8-ai/python-hash-tool) contains a reference `Python` implementation of the `Hash` Tool.

Expand All @@ -12,7 +12,7 @@ git clone [email protected]:otto8-ai/python-hash-tool

<br/>

## Tool Repo Structure
## Tool Repo Structure {#tool-repo-structure-28572835}

The directory tree below highlights the files required to implement `Hash` in Python and package it for `Otto8`.

Expand All @@ -24,7 +24,7 @@ python-hash-tool
```
<br/>

## Defining the `Hash` Tool
## Defining the `Hash` Tool {#defining-the-hash-tool-28572835}

The `tool.gpt` file contains [GPTScript Tool Definitions](https://docs.gptscript.ai/tools/gpt-file-reference) which describe a set of Tools that can be used by Agents in `Otto8`.
Every Tool repository must have a `tool.gpt` file in its root directory.
Expand Down Expand Up @@ -84,7 +84,7 @@ Param: algo: The algorithm to generate a hash with. Default is "sha256". Support

<br/>

## Tool Metadata
## Tool Metadata {#tool-metadata-28572835}

The `tool.gpt` file also provides the following metadata for use in `Otto8`:

Expand Down Expand Up @@ -144,7 +144,7 @@ https://cdn.jsdelivr.net/npm/@phosphor-icons/core@2/assets/duotone/fingerprint-d

<br/>

## Implementing Business Logic
## Implementing Business Logic {#implementing-business-logic-28572835}

The `hash.py` file executed by the `Tool Body` is the concrete implementation of the Tool's business logic.

Expand Down Expand Up @@ -261,7 +261,7 @@ if __name__ == '__main__':

<br/>

## Testing `hash.py` Locally
## Testing `hash.py` Locally {#testing-hash-py-locally-28572835}

Before adding a Tool to `Otto8`, verify that the Python business logic works on your machine.

Expand Down Expand Up @@ -298,7 +298,7 @@ To do this, run through the following steps in the root of your local fork:

<br/>

## Adding The `Hash` Tool to `Otto8`
## Adding The `Hash` Tool to `Otto8` {#adding-the-hash-tool-to-otto8-28572835}

Before a Tool can be used by an Agent, an admin must first add the Tool to `Otto8` by performing the steps below:

Expand Down Expand Up @@ -336,7 +336,7 @@ Before a Tool can be used by an Agent, an admin must first add the Tool to `Otto
</div>
</details>

## Using The `Hash` Tool in an Agent
## Using The `Hash` Tool in an Agent {#using-the-hash-tool-in-an-agent-28572835}

To use the `Hash` Tool in an Agent, open the Agent's Edit page, then:

Expand Down
29 changes: 25 additions & 4 deletions docs/src/plugins/fetch-snippets/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import fs from 'fs';
import path from 'path';
import axios from 'axios';
import crypto from 'crypto';
import { LoadContext, Plugin } from '@docusaurus/types';

// Array of permalinks to raw files in different repositories
const FILE_URLS = [
'https://raw.githubusercontent.com/otto8-ai/python-hash-tool/main/README.md',
'https://raw.githubusercontent.com/otto8-ai/go-hash-tool/main/README.md',
'https://raw.githubusercontent.com/otto8-ai/node-hash-tool/main/README.md',
];

// Mapping of file extensions to code block languages for syntax highlighting
const EXTENSION_LANGUAGE_MAP: Record<string, string> = {
'.py': 'python',
'.go': 'go',
Expand Down Expand Up @@ -46,10 +45,13 @@ async function fetchFiles(outputDir: string) {
const ext = path.extname(filePath);
const language = EXTENSION_LANGUAGE_MAP[ext] || ''; // Default to plain text if extension is unknown

// Wrap content in a Markdown code block for supported file types
let wrappedContent = data;
if (language != 'markdown') {
if (language !== 'markdown') {
// Wrap content in a Markdown code block for supported file types
wrappedContent = language ? `\`\`\`${language}\n${data}\n\`\`\`` : data;
} else {
// Add unique and explicit IDs to all headers in Markdown content
wrappedContent = addUniqueHeaderIds(url, data);
}

const outputFilePath = path.join(outputDir, `${repoName}-${filePath}.mdx`);
Expand All @@ -62,6 +64,25 @@ async function fetchFiles(outputDir: string) {
);
}

// Function to add unique IDs to Markdown headers
function addUniqueHeaderIds(url, markdown: string): string {
const urlHash = crypto.createHash('sha256').update(url).digest('hex').substring(0, 8);

let headerCounts: Record<string, number> = {};
return markdown.replace(/^(#{1,6})\s+(.+)$/gm, (match, hashes, title) => {
const slugBase = title.toLowerCase().replace(/[^\w]+/g, '-').replace(/^-|-$/g, '');
const count = headerCounts[slugBase] || 0;
const uniqueSlug = count ? `${slugBase}-${urlHash}-${count}` : `${slugBase}-${urlHash}`;
headerCounts[slugBase] = count + 1;

return `${hashes} ${title} {#${uniqueSlug}}`;
});
}

function getShortHash(input: string): string {
return crypto.createHash('sha256').update(input).digest('hex').substring(0, 8);
}

export default function pluginFetchSnippets(context: LoadContext): Plugin {
return {
name: 'fetch-snippets',
Expand Down

0 comments on commit f1e12f1

Please sign in to comment.