diff --git a/.github/workflows/deploy-github-pages.yml b/.github/workflows/deploy-github-pages.yml new file mode 100644 index 0000000..c871724 --- /dev/null +++ b/.github/workflows/deploy-github-pages.yml @@ -0,0 +1,76 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +name: Deployment to GitHub Pages + +on: + workflow_dispatch: + push: + branches: + - main + paths: + - 'site/**' + - 'docs/**' + - '.github/workflows/deploy-github-pages.yml' + pull_request: + paths: + - 'site/**' + - 'docs/**' + - '.github/workflows/deploy-github-pages.yml' + +permissions: + contents: write + +env: + REPO_NAME: ${{ github.event.repository.name }} + REPO_OWNER: ${{ github.repository_owner }} + +jobs: + deploy: + runs-on: ubuntu-latest + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod + submodules: recursive # Fetch any git submodules if configured + + - name: Setup Hugo + uses: peaceiris/actions-hugo@v3 + with: + hugo-version: '0.136.5' # Matching local Hugo version + extended: true + + - uses: actions/setup-node@v6 + with: + node-version: '20' + check-latest: true + + - name: Install PostCSS dependencies + run: | + npm init --yes + npm install --save-dev autoprefixer postcss-cli postcss + working-directory: ./site + + - name: Build Hugo Site + run: hugo --baseURL https://sam-mesh.dev --minify + working-directory: ./site + + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v4 + if: ${{ github.ref == 'refs/heads/main' && github.event_name != 'pull_request' }} + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./site/public + cname: sam-mesh.dev diff --git a/README.md b/README.md index af86918..772ac40 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # SAM: Sovereign Agent Mesh -SAM +SAM SAM is a smart network built for autonomous AI agents: @@ -24,14 +24,15 @@ Start exploring the Sovereign Agent Mesh: ### For Users & Operators Get a node running on the public testnet (`bananas.sam-mesh.dev`) in minutes: -- ๐Ÿš€ **[User Quick Start Guide](docs/quickstart.md)**: Connect and run a SAM node using Docker and query the local MCP server via `curl`. -- ๐Ÿ“– **[CLI Reference](docs/cli/reference.md)**: Comprehensive CLI reference and configurations. -- ๐Ÿ“ก **[Testnet Validation Tutorial](docs/testnet-validation.md)**: Real-time verification, remote tool invocation, and HTTP stream proxies. +- ๐Ÿš€ **[User Quick Start Guide](site/content/docs/quickstart.md)**: Connect and run a SAM node using binaries or Docker, and query the local MCP server. +- ๐Ÿค– **[Agent Integration Guides](site/content/docs/agent_integration.md)**: Connect Google Gemini, Claude, and other AI agents to your SAM node to dynamically discover and call tools across the mesh. +- ๐Ÿ“– **[CLI Reference](site/content/docs/cli/reference.md)**: Comprehensive CLI reference and configurations. +- ๐Ÿ“ก **[Testnet Validation Tutorial](site/content/docs/testnet-validation.md)**: Real-time verification, remote tool invocation, and HTTP stream proxies. ### For Developers & Contributors Compile from source, run local clusters, or execute tests: -- ๐Ÿ› ๏ธ **[Developer Guide](docs/development.md)**: Prereqs, compilation, local hub setup, and Kubernetes Kind deployment. -- ๐Ÿงช **[Testing Guide](docs/testing.md)**: Go tests, E2E BATS, and containerized mesh execution. +- ๐Ÿ› ๏ธ **[Developer Guide](site/content/docs/development.md)**: Prereqs, compilation, local hub setup, and Kubernetes Kind deployment. +- ๐Ÿงช **[Testing Guide](site/content/docs/testing.md)**: Go tests, E2E BATS, and containerized mesh execution. --- diff --git a/docs/_sidebar.md b/docs/_sidebar.md deleted file mode 100644 index 9c1aefd..0000000 --- a/docs/_sidebar.md +++ /dev/null @@ -1,7 +0,0 @@ -- [Overview](#/README.md) -- [Quick Start](#/quickstart.md) -- [Agent Integration](#/agent_integration.md) -- [CLI Reference](#/cli/reference.md) -- [Testing](#/testing.md) -- [Testnet Validation](#/testnet-validation.md) -- [License](https://github.com/google/sam/blob/main/LICENSE) diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index b7e48fc..0000000 --- a/docs/index.html +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - SAM - Sovereign Agent Mesh - - - - - - - - - - - - - - - -
Loading SAM documentation...
- - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/sam-mcp-python/examples/gemini_agent.py b/sam-mcp-python/examples/gemini_agent.py new file mode 100644 index 0000000..abac6c3 --- /dev/null +++ b/sam-mcp-python/examples/gemini_agent.py @@ -0,0 +1,148 @@ +import asyncio +import os +import sys +from google import genai +from google.genai import types +from sam_mcp.client import SamClient + +# Helper to recursively map MCP (JSON Schema) types to Gemini (OpenAPI Schema) types +def to_gemini_schema(mcp_schema: dict) -> dict: + if not isinstance(mcp_schema, dict): + return mcp_schema + + gemini_schema = {} + for k, v in mcp_schema.items(): + if k == "type" and isinstance(v, str): + # Gemini expects uppercase types (e.g. 'STRING', 'OBJECT') + gemini_schema[k] = v.upper() + elif k == "properties" and isinstance(v, dict): + gemini_schema[k] = {prop_name: to_gemini_schema(prop_val) for prop_name, prop_val in v.items()} + elif k == "items" and isinstance(v, dict): + gemini_schema[k] = to_gemini_schema(v) + else: + gemini_schema[k] = v + + return gemini_schema + +async def run_agent(): + # 1. Connect to local SAM Node + # By default, connects to http://localhost:8080/mcp/events + print("Connecting to local SAM Node...") + client = SamClient() + try: + await client.connect() + except Exception as e: + print(f"Error: Failed to connect to local SAM Node: {e}") + print("Make sure sam-node is running (e.g. 'sam-node run --bind-addr 127.0.0.1:8080')") + sys.exit(1) + + print("Successfully connected!") + + # 2. Get available tools from the Mesh + mcp_tools = await client.get_tools() + print(f"Discovered {len(mcp_tools)} tools in the mesh.") + for t in mcp_tools: + print(f" - {t['name']}: {t.get('description', '')}") + + # 3. Build Gemini Tool Declarations + gemini_functions = [] + for tool in mcp_tools: + # Build parameters schema + params_schema = to_gemini_schema(tool.get("inputSchema", {})) + + # Define the function declaration + decl = types.FunctionDeclaration( + name=tool["name"], + description=tool.get("description", ""), + parameters=params_schema + ) + gemini_functions.append(decl) + + # Wrap function declarations into a Gemini Tool + gemini_tools = [types.Tool(function_declarations=gemini_functions)] + + # 4. Initialize Gemini Client + # Requires GEMINI_API_KEY environment variable + api_key = os.environ.get("GEMINI_API_KEY") + if not api_key: + print("\nWarning: GEMINI_API_KEY environment variable not set.") + print("Please export it to run the AI agent: export GEMINI_API_KEY=\"your-key\"") + await client.close() + sys.exit(1) + + ai = genai.Client(api_key=api_key) + # Using the recommended model for function calling + model_name = "gemini-2.5-flash" + + print(f"\nInitialized Gemini Agent ({model_name}) with Mesh Tools.") + print("You can now ask questions! Type 'exit' or 'quit' to stop.") + print("-" * 60) + + # 5. Interactive Chat Loop + # We use chat session to maintain history + chat = ai.chats.create( + model=model_name, + config=types.GenerateContentConfig( + tools=gemini_tools, + system_instruction="You are an AI agent running inside the Sovereign Agent Mesh (SAM). " + "You have access to tools registered by other peers in the mesh. " + "If a user asks you to perform a task, check if there's a tool that can solve it. " + "Always prioritize using tools to explore or interact with the mesh." + ) + ) + + while True: + try: + user_input = await asyncio.to_thread(input, "\nYou > ") + if user_input.lower() in ["exit", "quit"]: + break + if not user_input.strip(): + continue + + # Send message to Gemini + response = chat.send_message(user_input) + + # Handle function calling loop (Gemini might make multiple calls sequentially) + while response.function_calls: + for call in response.function_calls: + print(f"\n[Agent wants to call tool: {call.name} with args: {call.args}]") + + # Convert Gemini args Map to normal dict + args = dict(call.args) if call.args else {} + + # Call the tool via local SAM Node + try: + result = await client.call_tool(call.name, args) + print(f"[Tool Result]: {result}") + + # Send tool response back to Gemini + response = chat.send_message( + types.Part.from_function_response( + name=call.name, + response={"result": result} + ) + ) + except Exception as tool_err: + print(f"[Tool Error]: {tool_err}") + # Send error back to model so it knows it failed + response = chat.send_message( + types.Part.from_function_response( + name=call.name, + response={"error": str(tool_err)} + ) + ) + + # Print Gemini's final response text + if response.text: + print(f"\nAgent > {response.text}") + + except KeyboardInterrupt: + break + except Exception as e: + print(f"Error during interaction: {e}") + + await client.close() + print("\nDisconnected. Goodbye!") + +if __name__ == "__main__": + asyncio.run(run_agent()) diff --git a/site/.gitignore b/site/.gitignore new file mode 100644 index 0000000..00046aa --- /dev/null +++ b/site/.gitignore @@ -0,0 +1,5 @@ +/public/ +/resources/ +/node_modules/ +package-lock.json +.hugo_build.lock diff --git a/site/archetypes/default.md b/site/archetypes/default.md new file mode 100644 index 0000000..25b6752 --- /dev/null +++ b/site/archetypes/default.md @@ -0,0 +1,5 @@ ++++ +date = '{{ .Date }}' +draft = true +title = '{{ replace .File.ContentBaseName "-" " " | title }}' ++++ diff --git a/site/assets/scss/_styles_project.scss b/site/assets/scss/_styles_project.scss new file mode 100644 index 0000000..8ebcf66 --- /dev/null +++ b/site/assets/scss/_styles_project.scss @@ -0,0 +1,28 @@ +.td-navbar { + border-bottom: 2px solid $primary-light; +} + +// Homepage cover block with SAM logo background +.td-cover-block { + background-color: #ffffff !important; + background-image: url('/sam_logo.png') !important; + background-repeat: no-repeat !important; + background-position: center 30% !important; // Pushes image slightly higher to leave room for buttons + background-size: contain !important; + + // Set minimum height to display the logo nicely + min-height: 75vh !important; + + // Layout to push buttons to the bottom + display: flex !important; + flex-direction: column !important; + justify-content: flex-end !important; + padding-bottom: 4rem !important; +} + +// Remove the default dark overlay shadow on the cover block +.td-overlay::before { + background: transparent !important; + opacity: 0 !important; +} + diff --git a/site/assets/scss/_variables_project.scss b/site/assets/scss/_variables_project.scss new file mode 100644 index 0000000..0f7530a --- /dev/null +++ b/site/assets/scss/_variables_project.scss @@ -0,0 +1,13 @@ +// SAM Logo Theme Color Overrides +$primary: #0a7080; // Deep teal (base of SAM text) +$primary-light: #00f0ff; // Cyberpunk glowing cyan (bananas' visors & wiring) +$yellow: #f6c344; // Banana yellow +$dark: #07131e; // Deep navy/charcoal (shield background and text) +$light: #f8fafc; // Off-white slate for body/sidebar backgrounds + +// Docsy theme mappings +$td-brand: $primary; +$td-sidebar-bg-color: $light; +$td-footer-bg-color: $dark; +$link-color: $primary; +$link-hover-color: lighten($primary, 15%); diff --git a/site/content/_index.md b/site/content/_index.md new file mode 100644 index 0000000..830fd9d --- /dev/null +++ b/site/content/_index.md @@ -0,0 +1,10 @@ +--- +title: SAM +--- + +{{< blocks/cover title="" image_anchor="top" height="full" >}} +
+ Read the Docs + GitHub Project +
+{{< /blocks/cover >}} diff --git a/docs/README.md b/site/content/docs/_index.md similarity index 100% rename from docs/README.md rename to site/content/docs/_index.md diff --git a/docs/agent_integration.md b/site/content/docs/agent_integration.md similarity index 79% rename from docs/agent_integration.md rename to site/content/docs/agent_integration.md index 3d40ced..9cc5290 100644 --- a/docs/agent_integration.md +++ b/site/content/docs/agent_integration.md @@ -8,6 +8,15 @@ Every `sam-node` runs a local MCP server that allows agents to: - Query mesh information (e.g. `get_mesh_info`). - Call tools remotely (via `call_remote_tool`). +## Supported Agent Integrations + +Explore the step-by-step guides to integrate SAM with your favorite AI Agent systems: + +- [Google Gemini](integrations/gemini.md): Build an interactive client using the official `google-genai` Python SDK. +- [Claude Code](integrations/claude-code.md): Connect your local node as a remote MCP server to Claude Code. +- [Claude Desktop](integrations/claude-desktop.md): Use SAM to expose the P2P tool mesh to Claude Desktop. +- [OpenClaw](integrations/openclaw.md): Integrate your node as a remote tool bridge for OpenClaw. + ## Connecting via MCP The `sam-node` exposes the MCP server over HTTP Server-Sent Events (SSE). By default, it listens at `127.0.0.1:8080`. @@ -60,7 +69,7 @@ if __name__ == "__main__": asyncio.run(main()) ``` -*(You can find this snippet at `docs/snippets/agent_demo.py`)* +*(You can find this snippet at `site/content/docs/snippets/agent_demo.py`)* ### Example Output diff --git a/docs/cli/reference.md b/site/content/docs/cli/reference.md similarity index 100% rename from docs/cli/reference.md rename to site/content/docs/cli/reference.md diff --git a/docs/development.md b/site/content/docs/development.md similarity index 100% rename from docs/development.md rename to site/content/docs/development.md diff --git a/docs/integrations/claude-code.md b/site/content/docs/integrations/claude-code.md similarity index 100% rename from docs/integrations/claude-code.md rename to site/content/docs/integrations/claude-code.md diff --git a/docs/integrations/claude-desktop.md b/site/content/docs/integrations/claude-desktop.md similarity index 100% rename from docs/integrations/claude-desktop.md rename to site/content/docs/integrations/claude-desktop.md diff --git a/site/content/docs/integrations/gemini.md b/site/content/docs/integrations/gemini.md new file mode 100644 index 0000000..105af25 --- /dev/null +++ b/site/content/docs/integrations/gemini.md @@ -0,0 +1,88 @@ +# Running a Gemini AI Agent on the Mesh + +This tutorial demonstrates how to connect a local AI Agent powered by Google Gemini (using the official `google-genai` SDK) to your local SAM node. + +By exposing the SAM Model Context Protocol (MCP) server to Gemini, the agent can dynamically discover tools hosted by other peers in the mesh, describe them, and execute them to solve tasks. + +--- + +## Prerequisites + +1. **Python 3.10+**: Ensure Python is installed on your host. +2. **SAM Node Running**: A local SAM node should be running and enrolled on the testnet (see the [Quick Start Guide](../quickstart.md)). +3. **Gemini API Key**: Obtain an API key from Google AI Studio and export it: + ```bash + export GEMINI_API_KEY="your-api-key-here" + ``` + +--- + +## 1. Setup the Python Client + +Go to the `sam-mcp-python` directory in the repository: + +```bash +cd sam-mcp-python +``` + +Create a virtual environment and install the required dependencies: + +```bash +# Create and activate virtual environment +python3 -m venv .venv +source .venv/bin/activate + +# Install the SAM Python SDK and Gemini SDK +pip install . google-genai +``` + +--- + +## 2. Run the Gemini Agent + +Start the interactive agent: + +```bash +python3 examples/gemini_agent.py +``` + +Upon starting, the script will: +1. Connect to the local SAM node's MCP server at `http://localhost:8080/mcp/events`. +2. Discover all tools currently available in the mesh. +3. Map the mesh tools to Gemini-compatible OpenAPI schemas. +4. Spin up a chat loop with Gemini (`gemini-2.5-flash`). + +--- + +## 3. Interact with the Agent + +Once the agent is online, you can prompt it in plain English. If a task requires tools registered in the mesh, Gemini will automatically call them. + +### Example 1: Explore the Mesh +Ask the agent what it can see in the mesh: +```text +You > How many nodes are currently connected to the mesh? And what are their Peer IDs? + +[Agent wants to call tool: get_mesh_info with args: {}] +[Tool Result]: {'connected_peers': ['12D3KooWD3m6Jfry...'], 'dht_size': 1, ...} + +Agent > There is currently 1 active peer connected to the mesh with Peer ID 12D3KooWD3m6Jfry... +``` + +### Example 2: Call Remote Tools Dynamically +If another node on the mesh is hosting a tool (e.g. `everything.get-sum`), you can ask Gemini to compute a sum. It will find the tool, query its schema, and execute it: + +```text +You > Can you sum 1234.5 and 5678.9 using a tool in the mesh? + +[Agent wants to call tool: find_remote_tools with args: {}] +[Tool Result]: ... 'name': 'everything.get-sum', 'description': 'Sums two floats', 'peer_id': '12D3KooWD3m6Jfry...' ... + +[Agent wants to call tool: describe_remote_tool with args: {'peer_id': '12D3KooWD3m6Jfry...', 'tool_name': 'everything.get-sum'}] +[Tool Result]: {'inputSchema': {'properties': {'a': {'type': 'number'}, 'b': {'type': 'number'}}, 'required': ['a', 'b']}} + +[Agent wants to call tool: call_remote_tool with args: {'peer_id': '12D3KooWD3m6Jfry...', 'tool_name': 'everything.get-sum', 'arguments': {'a': 1234.5, 'b': 5678.9}}] +[Tool Result]: {'result': {'sum': 6913.4}} + +Agent > The sum of 1234.5 and 5678.9 is 6913.4, calculated using the 'everything.get-sum' tool hosted on peer 12D3KooWD3m6Jfry... +``` diff --git a/docs/integrations/openclaw.md b/site/content/docs/integrations/openclaw.md similarity index 100% rename from docs/integrations/openclaw.md rename to site/content/docs/integrations/openclaw.md diff --git a/docs/kubernetes-deployment.md b/site/content/docs/kubernetes-deployment.md similarity index 100% rename from docs/kubernetes-deployment.md rename to site/content/docs/kubernetes-deployment.md diff --git a/docs/manifests/mock-oidc.yaml b/site/content/docs/manifests/mock-oidc.yaml similarity index 100% rename from docs/manifests/mock-oidc.yaml rename to site/content/docs/manifests/mock-oidc.yaml diff --git a/docs/manifests/sam-hub.yaml b/site/content/docs/manifests/sam-hub.yaml similarity index 100% rename from docs/manifests/sam-hub.yaml rename to site/content/docs/manifests/sam-hub.yaml diff --git a/docs/policy.md b/site/content/docs/policy.md similarity index 100% rename from docs/policy.md rename to site/content/docs/policy.md diff --git a/docs/quickstart.md b/site/content/docs/quickstart.md similarity index 73% rename from docs/quickstart.md rename to site/content/docs/quickstart.md index 0fa6007..0705af7 100644 --- a/docs/quickstart.md +++ b/site/content/docs/quickstart.md @@ -81,52 +81,40 @@ docker run -d \ ``` Verify the node is running with `docker logs sam-node`. ---- - ## 4. Query the Local MCP API -Your SAM node exposes a standard Model Context Protocol (MCP) server over HTTP Server-Sent Events (SSE) at `http://localhost:8080/mcp/message`. You can interact with it using simple `curl` commands. +Your SAM node exposes a standard Model Context Protocol (MCP) server. The easiest way to interact with it is using the `mcp-client` CLI tool (which is installed alongside `sam-node`): ### List Local Control Plane Tools Query the list of tools available on your local node (e.g. peer discovery, message broadcast, and remote tool execution): ```bash -curl -X POST \ - -H "Authorization: Bearer my-secret-token" \ - -H "Content-Type: application/json" \ - -d '{"jsonrpc":"2.0","method":"tools/list","id":1}' \ - http://localhost:8080/mcp/message +mcp-client -url http://localhost:8080/mcp/events -token my-secret-token -list ``` ### Discover Remote Services in the Mesh List active MCP services currently registered across the public mesh network: ```bash -curl -X POST \ - -H "Authorization: Bearer my-secret-token" \ - -H "Content-Type: application/json" \ - -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"discover_remote_services","arguments":{"type":"mcp"}},"id":2}' \ - http://localhost:8080/mcp/message +mcp-client -url http://localhost:8080/mcp/events \ + -tool discover_remote_services \ + -args '{"type":"mcp"}' ``` ### Find Remote Tools on a Peer Using a `peer_id` returned from the service discovery, find the tools available on that peer: ```bash -curl -X POST \ - -H "Authorization: Bearer my-secret-token" \ - -H "Content-Type: application/json" \ - -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"find_remote_tools","arguments":{"peer_id":""}},"id":3}' \ - http://localhost:8080/mcp/message +mcp-client -url http://localhost:8080/mcp/events \ + -tool find_remote_tools \ + -args '{"peer_id":""}' ``` ### Call a Remote Tool Call a tool hosted on a remote peer through your local node's P2P stream reverse proxy: ```bash -curl -X POST \ - -H "Authorization: Bearer my-secret-token" \ - -H "Content-Type: application/json" \ - -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"call_remote_tool","arguments":{"peer_id":"","tool_name":"everything.get-sum","arguments":{"a":12.5,"b":7.5}}},"id":4}' \ - http://localhost:8080/mcp/message +mcp-client -url http://localhost:8080/mcp/events \ + -tool call_remote_tool \ + -args '{"peer_id":"","tool_name":"everything.get-sum","arguments":{"a":12.5,"b":7.5}}' ``` diff --git a/docs/release-tracks.md b/site/content/docs/release-tracks.md similarity index 100% rename from docs/release-tracks.md rename to site/content/docs/release-tracks.md diff --git a/docs/sam_logo.png b/site/content/docs/sam_logo.png similarity index 100% rename from docs/sam_logo.png rename to site/content/docs/sam_logo.png diff --git a/docs/snippets/agent_demo.py b/site/content/docs/snippets/agent_demo.py similarity index 100% rename from docs/snippets/agent_demo.py rename to site/content/docs/snippets/agent_demo.py diff --git a/docs/snippets/banana_bot_playground.py b/site/content/docs/snippets/banana_bot_playground.py similarity index 100% rename from docs/snippets/banana_bot_playground.py rename to site/content/docs/snippets/banana_bot_playground.py diff --git a/docs/testing.md b/site/content/docs/testing.md similarity index 100% rename from docs/testing.md rename to site/content/docs/testing.md diff --git a/docs/testnet-validation.md b/site/content/docs/testnet-validation.md similarity index 100% rename from docs/testnet-validation.md rename to site/content/docs/testnet-validation.md diff --git a/site/go.mod b/site/go.mod new file mode 100644 index 0000000..648041a --- /dev/null +++ b/site/go.mod @@ -0,0 +1,8 @@ +module github.com/google/sam/site + +go 1.23.4 + +require ( + github.com/google/docsy v0.11.0 // indirect + github.com/google/docsy/dependencies v0.7.2 // indirect +) diff --git a/site/go.sum b/site/go.sum new file mode 100644 index 0000000..7d2f09f --- /dev/null +++ b/site/go.sum @@ -0,0 +1,8 @@ +github.com/FortAwesome/Font-Awesome v0.0.0-20230327165841-0698449d50f2/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo= +github.com/FortAwesome/Font-Awesome v0.0.0-20240716171331-37eff7fa00de/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo= +github.com/google/docsy v0.11.0 h1:QnV40cc28QwS++kP9qINtrIv4hlASruhC/K3FqkHAmM= +github.com/google/docsy v0.11.0/go.mod h1:hGGW0OjNuG5ZbH5JRtALY3yvN8ybbEP/v2iaK4bwOUI= +github.com/google/docsy/dependencies v0.7.2 h1:+t5ufoADQAj4XneFphz4A+UU0ICAxmNaRHVWtMYXPSI= +github.com/google/docsy/dependencies v0.7.2/go.mod h1:gihhs5gmgeO+wuoay4FwOzob+jYJVyQbNaQOh788lD4= +github.com/twbs/bootstrap v5.2.3+incompatible/go.mod h1:fZTSrkpSf0/HkL0IIJzvVspTt1r9zuf7XlZau8kpcY0= +github.com/twbs/bootstrap v5.3.3+incompatible/go.mod h1:fZTSrkpSf0/HkL0IIJzvVspTt1r9zuf7XlZau8kpcY0= diff --git a/site/hugo.toml b/site/hugo.toml new file mode 100644 index 0000000..3faafc1 --- /dev/null +++ b/site/hugo.toml @@ -0,0 +1,43 @@ +title = "SAM" +baseURL = "https://sam-mesh.dev" +languageCode = "en-us" + +enableRobotsTXT = true + +# Point to the content directory +contentDir = "content" + +[markup] + [markup.highlight] + codeFences = true + hl_Lines = "" + lineNoStart = 1 + lineNos = false + lineNumbersInTable = true + noClasses = false # Needed for dark mode theme switching + style = "vs" + tabWidth = 4 + + [markup.goldmark.renderer] + unsafe = true + +# Enable Docsy's navigation structure +sectionPagesMenu = "main" + +[module] + [[module.imports]] + path = "github.com/google/docsy" + [[module.imports]] + path = "github.com/google/docsy/dependencies" + +[params] + privacy_policy = "https://policies.google.com/privacy" + github_repo = "https://github.com/google/sam" + github_subdir = "docs" + github_branch = "main" + + # Logo & branding colors will be customized via project styles + +[services] + [services.googleAnalytics] + id = "G-F9G8NX0SBT" diff --git a/site/layouts/partials/hooks/head-end.html b/site/layouts/partials/hooks/head-end.html new file mode 100644 index 0000000..c1b043e --- /dev/null +++ b/site/layouts/partials/hooks/head-end.html @@ -0,0 +1,3 @@ + + + diff --git a/site/package.json b/site/package.json new file mode 100644 index 0000000..745711d --- /dev/null +++ b/site/package.json @@ -0,0 +1,17 @@ +{ + "name": "site", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "autoprefixer": "^10.5.2", + "postcss": "^8.5.15", + "postcss-cli": "^11.0.1" + } +} diff --git a/site/static/favicon.ico b/site/static/favicon.ico new file mode 100644 index 0000000..3d2a0db Binary files /dev/null and b/site/static/favicon.ico differ diff --git a/site/static/favicon.png b/site/static/favicon.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicon.png differ diff --git a/site/static/favicons/android-144x144.png b/site/static/favicons/android-144x144.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/android-144x144.png differ diff --git a/site/static/favicons/android-192x192.png b/site/static/favicons/android-192x192.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/android-192x192.png differ diff --git a/site/static/favicons/android-36x36.png b/site/static/favicons/android-36x36.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/android-36x36.png differ diff --git a/site/static/favicons/android-48x48.png b/site/static/favicons/android-48x48.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/android-48x48.png differ diff --git a/site/static/favicons/android-72x72.png b/site/static/favicons/android-72x72.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/android-72x72.png differ diff --git a/site/static/favicons/android-96x96.png b/site/static/favicons/android-96x96.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/android-96x96.png differ diff --git a/site/static/favicons/apple-touch-icon-180x180.png b/site/static/favicons/apple-touch-icon-180x180.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/apple-touch-icon-180x180.png differ diff --git a/site/static/favicons/apple-touch-icon.png b/site/static/favicons/apple-touch-icon.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/apple-touch-icon.png differ diff --git a/site/static/favicons/favicon-1024.png b/site/static/favicons/favicon-1024.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/favicon-1024.png differ diff --git a/site/static/favicons/favicon-16x16.png b/site/static/favicons/favicon-16x16.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/favicon-16x16.png differ diff --git a/site/static/favicons/favicon-256.png b/site/static/favicons/favicon-256.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/favicon-256.png differ diff --git a/site/static/favicons/favicon-32x32.png b/site/static/favicons/favicon-32x32.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/favicon-32x32.png differ diff --git a/site/static/favicons/favicon.ico b/site/static/favicons/favicon.ico new file mode 100644 index 0000000..3d2a0db Binary files /dev/null and b/site/static/favicons/favicon.ico differ diff --git a/site/static/favicons/favicon.png b/site/static/favicons/favicon.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/favicon.png differ diff --git a/site/static/favicons/pwa-192x192.png b/site/static/favicons/pwa-192x192.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/pwa-192x192.png differ diff --git a/site/static/favicons/pwa-512x512.png b/site/static/favicons/pwa-512x512.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/pwa-512x512.png differ diff --git a/site/static/favicons/tile150x150.png b/site/static/favicons/tile150x150.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/tile150x150.png differ diff --git a/site/static/favicons/tile310x150.png b/site/static/favicons/tile310x150.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/tile310x150.png differ diff --git a/site/static/favicons/tile310x310.png b/site/static/favicons/tile310x310.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/tile310x310.png differ diff --git a/site/static/favicons/tile70x70.png b/site/static/favicons/tile70x70.png new file mode 100644 index 0000000..55b4f61 Binary files /dev/null and b/site/static/favicons/tile70x70.png differ diff --git a/site/static/sam_logo.png b/site/static/sam_logo.png new file mode 100644 index 0000000..68b1ef2 Binary files /dev/null and b/site/static/sam_logo.png differ diff --git a/tests/e2e/docs_snippets.bats b/tests/e2e/docs_snippets.bats index 218ef36..6896ced 100644 --- a/tests/e2e/docs_snippets.bats +++ b/tests/e2e/docs_snippets.bats @@ -32,7 +32,7 @@ teardown() { run docker run --rm \ --network "${MESH_NETWORK}" \ -v "$(pwd)/sam-mcp-python:/sam-mcp-python" \ - -v "$(pwd)/docs/snippets:/snippets" \ + -v "$(pwd)/site/content/docs/snippets:/snippets" \ -e PYTHONPATH=/sam-mcp-python/src \ -e SAM_MCP_URL="http://sam-node-1:8080/mcp/events" \ python:3.12 \