Skip to content
Draft
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ go.work.sum

# Serena
.serena/

# Local agent / planning artifacts (not for public commits)
.claude/
docs/superpowers/
44 changes: 43 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ generate:
make generate-go

generate-go:
rm -rf router/gen && buf generate --path proto/wg/cosmo/node --path proto/wg/cosmo/common --path proto/wg/cosmo/graphqlmetrics --template buf.router.go.gen.yaml
rm -rf router/gen && buf generate --path proto/wg/cosmo/node --path proto/wg/cosmo/common --path proto/wg/cosmo/graphqlmetrics --path proto/wg/cosmo/code_mode/yoko/v1 --include-imports --template buf.router.go.gen.yaml
rm -rf graphqlmetrics/gen && buf generate --path proto/wg/cosmo/graphqlmetrics --path proto/wg/cosmo/common --template buf.graphqlmetrics.go.gen.yaml
rm -rf connect-go/wg && buf generate --path proto/wg/cosmo/platform --path proto/wg/cosmo/notifications --path proto/wg/cosmo/common --path proto/wg/cosmo/node --template buf.connect-go.go.gen.yaml

Expand Down Expand Up @@ -187,6 +187,48 @@ docker-build-minikube: docker-build-local
run-subgraphs-local:
cd demo && go run cmd/all/main.go

CODE_MODE_GOCACHE ?= /tmp/cosmo-code-mode-go-build-cache

.PHONY: code-mode-demo code-mode-demo-down code-mode-connect-demo code-mode-connect-demo-down

# Local Code Mode demo: federation of all non-EDFS demo subgraphs
# (employees, family, hobbies, products, test1, availability, mood, countries,
# plus the products_fg feature graph) + Cosmo Router with Code Mode and
# named operations. Router GraphQL on :3002, MCP on :5027. Yoko runs as a
# separate external service expected at http://127.0.0.1:3400 — start it
# before this target (override with YOKO_URL=...). Full instructions,
# prerequisites, and tear-down: demo/code-mode/README.md.
code-mode-demo:
mkdir -p $(CODE_MODE_GOCACHE)
GOCACHE=$(CODE_MODE_GOCACHE) $(MAKE) -C router build
GOCACHE=$(CODE_MODE_GOCACHE) $(MAKE) -C demo/code-mode build-stdio-proxy
$(MAKE) -C demo/code-mode compose
./demo/code-mode/start.sh

# Tear down anything left behind by code-mode-demo.
code-mode-demo-down:
./demo/code-mode/start.sh --down

# Runs the code-mode router from source against the yoko Connect supergraph
# (plugins + composed config live in $(YOKO_DIR)). Uses different router/MCP
# ports than code-mode-demo (router 3012, MCP 5037) so both can run at the
# same time, and shares the same external yoko service expected at
# http://127.0.0.1:3400 (override with YOKO_URL=...). Set YOKO_DIR to your
# local yoko checkout, e.g.
# `make code-mode-connect-demo YOKO_DIR=/path/to/yoko`.
# Full instructions and prerequisites: demo/code-mode-connect/README.md.
YOKO_DIR ?=

code-mode-connect-demo:
@if [ -z "$(YOKO_DIR)" ]; then echo "YOKO_DIR is required (path to your yoko checkout). See demo/code-mode-connect/README.md" >&2; exit 1; fi
mkdir -p $(CODE_MODE_GOCACHE)
GOCACHE=$(CODE_MODE_GOCACHE) $(MAKE) -C router build
YOKO_DIR=$(YOKO_DIR) ./demo/code-mode-connect/start.sh

# Tear down anything left behind by code-mode-connect-demo.
code-mode-connect-demo-down:
./demo/code-mode-connect/start.sh --down

sync-go-workspace:
cd router && go mod tidy
cd demo && make bump-deps
Expand Down
6 changes: 6 additions & 0 deletions buf.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Generated by buf. DO NOT EDIT.
version: v2
deps:
- name: buf.build/bufbuild/protovalidate
commit: 50325440f8f24053b047484a6bf60b76
digest: b5:74cb6f5c0853c3c10aafc701614194bbd63326bdb8ef4068214454b8894b03ba4113e04b3a33a8321cdf05336e37db4dc14a5e2495db8462566914f36086ba31
2 changes: 2 additions & 0 deletions buf.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
version: v2
modules:
- path: proto
deps:
- buf.build/bufbuild/protovalidate
lint:
disallow_comment_ignores: true
56 changes: 56 additions & 0 deletions demo/code-mode-connect/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Code Mode Connect Demo

This demo runs the Code Mode router against an external `yoko` Connect supergraph instead of the local employees federation used by `make code-mode-demo`.
It is useful when you want to exercise Code Mode against a richer set of plugins (Pylon, Linear, PostHog, Circleback, Slack, Notion) served by the `yoko` project.

It is designed to coexist with `make code-mode-demo`: it uses different router/MCP ports (router 3012, MCP 5037), and both demos share the same external Yoko service at `http://127.0.0.1:3400` (override with `YOKO_URL=...`).

## Prerequisites

- A local checkout of the `yoko` Connect supergraph project (separate repository).
Inside that checkout you must already have built the plugins and composed the supergraph so that the directory contains:
- `config.json` — the composed router config for the yoko supergraph.
- `plugins/` — the plugin binaries the router will load.
- Go (toolchain matching the repo `go.mod`).
- A running Yoko service reachable at `http://127.0.0.1:3400` (override with `YOKO_URL=...`).
The router calls Yoko for query generation; without it, `code_mode_search_tools` cannot generate operations.

## Run

From the repository root, set `YOKO_DIR` to your local yoko checkout and run:

```sh
make code-mode-connect-demo YOKO_DIR=/path/to/yoko
```

`YOKO_DIR` is required.
The target fails fast with a clear error if it is missing or if the directory does not contain `config.json`.

What the target does:

1. Builds `router/router`.
2. Health-checks the external Yoko service at `$YOKO_URL/health` (default `http://127.0.0.1:3400`).
3. Starts the router with `YOKO_DIR` as its working directory and `demo/code-mode-connect/router-config.yaml` as its config.
The router resolves `config.json` and `plugins/` relative to that CWD, which is why `YOKO_DIR` must be a real composed yoko checkout.

Expected ports:

- Router GraphQL: `http://localhost:3012/graphql`
- Code Mode MCP: `http://127.0.0.1:5037/mcp`
- Yoko (external): `http://127.0.0.1:3400`

## Tearing down

Press Ctrl-C in the foreground terminal.
If anything is left behind, run:

```sh
make code-mode-connect-demo-down
```

The process logs for background services are written to `/tmp/cosmo-code-mode-connect-demo-logs`.

## Auth headers

`router-config.yaml` propagates the auth headers expected by the yoko plugins (`X-Pylon-Token`, `X-Linear-Token`, `X-Posthog-Token`, `X-Circleback-Token`, `X-Slack-Token`, `X-Notion-Token`, etc.).
Provide values for these on the request side when calling the router so the plugins can reach their upstream services.
82 changes: 82 additions & 0 deletions demo/code-mode-connect/router-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
version: "1"

# Different router/MCP ports than demo/code-mode/router-config.yaml so both
# demos can run side-by-side. They share the same external yoko service
# (http://127.0.0.1:3400) — start.sh no longer launches a local yoko-mock.
listen_addr: "localhost:3012"
graphql_path: "/graphql"
playground_enabled: false
json_log: false
log_level: info
dev_mode: true
router_registration: false

# These paths are resolved relative to the router's CWD. start.sh runs the
# router from inside the yoko project dir, so "config.json" and "plugins" are
# the composed supergraph and the plugin binaries that ship with that repo.
execution_config:
file:
path: "config.json"
watch: false

plugins:
enabled: true
path: "plugins"

# Header propagation for the yoko plugins. Mirrors yoko/config.yaml so the
# plugins receive the same auth headers when the code-mode router fronts them.
headers:
all:
request:
- op: propagate
named: X-Pylon-Token
- op: propagate
named: X-Linear-Token
- op: propagate
named: X-Linear-Auth-Scheme
- op: propagate
named: X-Posthog-Token
- op: propagate
named: X-Posthog-Host
- op: propagate
named: X-Posthog-Project-Id
- op: propagate
named: X-Circleback-Token
- op: propagate
named: X-Slack-Token
- op: propagate
named: X-Notion-Token

graphql_metrics:
enabled: false

telemetry:
tracing:
enabled: false
metrics:
otlp:
enabled: false
prometheus:
enabled: false

mcp:
enabled: false
graph_name: code-mode-connect-demo
router_url: http://localhost:3012/graphql
session:
stateless: false
code_mode:
enabled: true
server:
# IPv4-only bind, see demo/code-mode/router-config.yaml for the why.
listen_addr: 127.0.0.1:5037
require_mutation_approval: true
sandbox:
timeout: 180s
query_generation:
enabled: true
endpoint: http://127.0.0.1:3400
timeout: 180s
execute_timeout: 180s
named_ops:
enabled: true
159 changes: 159 additions & 0 deletions demo/code-mode-connect/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#!/usr/bin/env bash

set -Eeuo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
DEMO_DIR="$ROOT_DIR/demo"
CONNECT_DIR="$DEMO_DIR/code-mode-connect"
PID_FILE="/tmp/cosmo-code-mode-connect-demo.pids"
LOG_DIR="/tmp/cosmo-code-mode-connect-demo-logs"
GOCACHE_DIR="${GOCACHE:-/tmp/cosmo-code-mode-go-build-cache}"

# Yoko project that owns the supergraph + plugin binaries. Required:
# YOKO_DIR=/path/to/yoko ./start.sh
YOKO_DIR="${YOKO_DIR:?YOKO_DIR is required (path to your yoko checkout)}"

ROUTER_BIN="$ROOT_DIR/router/router"
ROUTER_CONFIG="$CONNECT_DIR/router-config.yaml"

# Yoko is a separate service expected at http://127.0.0.1:3400. start.sh no
# longer launches a local mock — bring up your real yoko service before running.
YOKO_URL="${YOKO_URL:-http://127.0.0.1:3400}"

append_pid() {
local name="$1"
local pid="$2"
printf '%s %s\n' "$name" "$pid" >> "$PID_FILE"
}

kill_pid_file() {
if [ ! -f "$PID_FILE" ]; then
echo "No code-mode-connect demo PID file found at $PID_FILE"
return 0
fi

while read -r name pid; do
[ -n "${pid:-}" ] || continue
if kill -0 "$pid" 2>/dev/null; then
echo "Stopping $name pid=$pid"
kill "$pid" 2>/dev/null || true
fi
done < "$PID_FILE"

sleep 1

while read -r name pid; do
[ -n "${pid:-}" ] || continue
if kill -0 "$pid" 2>/dev/null; then
echo "Force stopping $name pid=$pid"
kill -KILL "$pid" 2>/dev/null || true
fi
done < "$PID_FILE"

rm -f "$PID_FILE"
}

cleanup() {
local status=$?
trap - EXIT INT TERM
kill_pid_file
exit "$status"
}

on_signal() {
trap - EXIT INT TERM
kill_pid_file
exit 0
}

wait_url() {
local name="$1"
local url="$2"
local timeout="${3:-90}"
local start
start="$(date +%s)"

while true; do
if curl -fsS "$url" >/dev/null 2>&1; then
echo "$name is ready at $url"
return 0
fi

if [ "$(( $(date +%s) - start ))" -ge "$timeout" ]; then
echo "Timed out waiting for $name at $url" >&2
echo "Logs are in $LOG_DIR" >&2
return 1
fi

sleep 1
done
}

start_background_root() {
local name="$1"
shift

echo "Starting $name"
# exec replaces the subshell with the binary, so $! is the binary's pid.
# Without exec, the subshell forks the binary and `--down` ends up signalling
# an already-exited subshell while the real process keeps running.
(
cd "$ROOT_DIR"
exec "$@"
) > "$LOG_DIR/$name.log" 2>&1 &
append_pid "$name" "$!"
}

if [ "${1:-}" = "--down" ]; then
kill_pid_file
exit 0
fi

if [ ! -d "$YOKO_DIR" ]; then
echo "Yoko project directory not found: $YOKO_DIR" >&2
echo "Set YOKO_DIR to override." >&2
exit 1
fi

if [ ! -x "$ROUTER_BIN" ]; then
echo "Router binary not found or not executable: $ROUTER_BIN" >&2
echo "Run: cd router && make build" >&2
exit 1
fi

if [ ! -f "$YOKO_DIR/config.json" ]; then
echo "Composed yoko supergraph not found: $YOKO_DIR/config.json" >&2
echo "Run: cd $YOKO_DIR && make compose" >&2
exit 1
fi

mkdir -p "$LOG_DIR"
mkdir -p "$GOCACHE_DIR"
rm -f "$PID_FILE"
trap cleanup EXIT
trap on_signal INT TERM

# Verify the external yoko service is reachable. We don't probe a specific
# path because the real service doesn't necessarily expose /health — just
# confirm the TCP/HTTP socket accepts a connection. Any HTTP response (200,
# 404, 405 …) means the server is up; only a connection failure aborts.
# Override with YOKO_URL when yoko runs at a different address.
if ! curl -sS -o /dev/null --max-time 3 "$YOKO_URL" >/dev/null 2>&1; then
echo "Yoko service is not reachable at $YOKO_URL" >&2
echo "Start your yoko service (or set YOKO_URL=...) before running this demo." >&2
exit 1
fi
echo "yoko is ready at $YOKO_URL"

echo "Starting router in foreground (CWD=$YOKO_DIR)"
echo "Router output is being teed to $LOG_DIR/router.log"
# Tee stdout+stderr so the user still sees live output AND we keep a persistent
# log for post-mortem debugging when the router exits unexpectedly.
(
cd "$YOKO_DIR"
exec "$ROUTER_BIN" -config "$ROUTER_CONFIG"
) 2>&1 | tee "$LOG_DIR/router.log" &
router_pid="$!"
append_pid router "$router_pid"

wait "$router_pid"
2 changes: 2 additions & 0 deletions demo/code-mode/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mcp-stdio-proxy/mcp-stdio-proxy
schemas/
Loading
Loading