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
8 changes: 5 additions & 3 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.1.2/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"commit": true,
"fixed": [
[
"@speakeasy-api/docs-mcp-core",
Expand All @@ -15,5 +15,7 @@
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": ["@speakeasy-api/tsconfig"]
}
"ignore": [
"@speakeasy-api/tsconfig"
]
}
8 changes: 8 additions & 0 deletions .changeset/floppy-hairs-throw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@speakeasy-api/docs-mcp-server": patch
"@speakeasy-api/docs-mcp-core": patch
"@speakeasy-api/docs-mcp-eval": patch
"@speakeasy-api/docs-mcp-cli": patch
---

Fixed lint and test errors
59 changes: 59 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Pull Request
on:
pull_request:
branches:
- main
types: [opened, synchronize, reopened, labeled]
push:
branches:
- main

jobs:
build-lint-test:
runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
- name: Checkout
uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v5.0.0

- name: Setup Mise
uses: jdx/mise-action@6d1e696aa24c1aa1bcc1adea0212707c71ab78a8 # v3.6.1
with:
install: true
cache: true
env: false

- name: Prepare GitHub Actions environment
run: mise run github

- name: Cache PNPM
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
key: ${{ env.GH_CACHE_PNPM_KEY }}
restore-keys: |
${{ env.GH_CACHE_PNPM_KEY }}
${{ env.GH_CACHE_PNPM_KEY_PARTIAL }}
path: |
${{ env.PNPM_STORE_PATH }}

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Codegen
run: mise run codegen

- name: Build
run: pnpm build
env:
NODE_ENV: production

- name: Lint
run: pnpm lint

- name: Type check
run: pnpm typecheck

- name: Test
run: pnpm test

- name: Prune PNPM store
run: pnpm store prune
5 changes: 5 additions & 0 deletions .mise-tasks/codegen/_default
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
#MISE description="Run code generation tasks across the monorepo"
#MISE dir="{{ config_root }}"

pnpm run --filter ./packages/core generate:schema
18 changes: 18 additions & 0 deletions .mise-tasks/git/porcelain.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env bash

#MISE description="Check for file changes after a build"

set -e

git_status_output=$(git status --porcelain)

if [[ -n "$git_status_output" ]]; then
>&2 echo "$git_status_output"
>&2 git diff | cat
>&2 echo "🚨 FAIL: Build process resulted in file changes."
exit 1
else
echo "✅ OK: No file changes detected after build."
fi

exit 0
12 changes: 12 additions & 0 deletions .mise-tasks/github/_default
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
#MISE description="Prepare GitHub Actions environment"

set -e

echo Compute cache keys
echo ==================
mise run github:pre-cache
echo
echo Install scripting dependencies
echo ==============================
pnpm install --frozen-lockfile --filter @gram/workspace
48 changes: 48 additions & 0 deletions .mise-tasks/github/pre-cache.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env -S node

//MISE description="Generate caching information for Go to use in GitHub Actions"
//MISE hide=true

// 💡 It's not possible to use anything other than the Node.js standard library
// because these initialization scripts run _before_ `pnpm install` has run.

import fs from "node:fs/promises";
import crypto from "node:crypto";
import { execSync } from "node:child_process";

if (!process.env["GITHUB_ENV"]) {
console.error("GITHUB_ENV is not set");
console.error("Is this running in a GitHub Action?");
process.exit(1);
}

const env = process.env["GITHUB_ENV"];

async function setupPNPMCaching() {
const storePath = execSync("pnpm store path", { encoding: "utf8" }).trim();

await fs.appendFile(env, `PNPM_STORE_PATH=${storePath}\n`);

const os = process.platform;
const arch = process.arch;

const hash = crypto.createHash("sha256");

console.log("Hashing:", "pnpm-lock.yaml");
const pnpmLock = await fs.readFile("pnpm-lock.yaml");
hash.update(pnpmLock);

const pnpmHash = hash.digest("hex");

const version = 1; // Increment this if you need to bust the cache
const cacheKey = `${version}-${os}-${arch}-${pnpmHash}`;
const partialKey = `${version}-${os}-${arch}-`;
await fs.appendFile(env, `GH_CACHE_PNPM_KEY=pnpm-${cacheKey}\n`);
await fs.appendFile(env, `GH_CACHE_PNPM_KEY_PARTIAL=pnpm-${partialKey}\n`);

console.log(`PNPM store path: ${storePath}`);
console.log(`GitHub PNPM cache key: ${cacheKey}`);
console.log(`GitHub PNPM partial cache key: ${partialKey}`);
}

await setupPNPMCaching();
2 changes: 2 additions & 0 deletions mise.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Environment setup: copy mise.local.toml.example → mise.local.toml and fill in API keys.
[tools]
hk = "1.36.0"
jq = "1.8.1"
node = "24.13.1"
pkl = "0.30.2"
pnpm = "10.30.2"

[tasks."index-fixtures"]
description = "Build test fixture index from tests/fixtures/docs"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"eslint": "^9.22.0",
"prettier": "^3.8.1",
"turbo": "^2.4.4",
"typescript": "^5.8.2",
"typescript": "^5.9.3",
"vitest": "^3.0.9"
},
"engines": {
Expand Down
4 changes: 3 additions & 1 deletion packages/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,9 @@ program
await rm(lanceDbOldPath, { recursive: true, force: true });
try {
await rename(lanceDbPath, lanceDbOldPath);
} catch {}
} catch {
// lanceDbPath may not exist on first run; safe to ignore
}
await rename(lanceDbTmpPath, lanceDbPath);
await rm(lanceDbOldPath, { recursive: true, force: true }).catch(() => {});

Expand Down
1 change: 1 addition & 0 deletions packages/core/src/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export function parseManifest(input: unknown): Manifest {
} catch (err) {
throw new Error(
`Invalid taxonomy config: ${err instanceof Error ? err.message : String(err)}`,
{ cause: err },
);
}
}
Expand Down
9 changes: 3 additions & 6 deletions packages/core/test/embedding.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ describe("embedding providers", () => {
);

// Verify the text was actually truncated in the request
const requestBody = JSON.parse((fetchMock.mock.calls[0]![1] as RequestInit).body as string) as {
const requestBody = JSON.parse(
(fetchMock.mock.calls[0]![1] as globalThis.RequestInit).body as string,
) as {
input: string[];
};
expect(requestBody.input[0]).toHaveLength(24_000);
Expand Down Expand Up @@ -294,11 +296,6 @@ describe("embedding providers", () => {
// so two providers with the same config and inputs produce the same SHA.
// We'll build the expected SHA by constructing a second provider.
const { sha256hex } = await import("../src/embedding.js");
const refProvider = new OpenAIEmbeddingProvider({
apiKey: "test-key",
dimensions: 2,
batchApiThreshold: 2,
});
// Build the JSONL the provider would create (access via same logic)
const expectedJsonl = [
JSON.stringify({
Expand Down
4 changes: 2 additions & 2 deletions packages/eval/src/agent/assertions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ async function evaluateFileContains(
: `File "${assertion.path}" does not contain "${assertion.value}"`,
};
} catch (err) {
const code = (err as NodeJS.ErrnoException).code;
const code = (err as globalThis.NodeJS.ErrnoException).code;
return {
assertion,
passed: false,
Expand Down Expand Up @@ -137,7 +137,7 @@ async function evaluateFileMatches(
: `File "${assertion.path}" does not match /${assertion.pattern}/${assertion.flags ?? ""}`,
};
} catch (err) {
const code = (err as NodeJS.ErrnoException).code;
const code = (err as globalThis.NodeJS.ErrnoException).code;
return {
assertion,
passed: false,
Expand Down
3 changes: 1 addition & 2 deletions packages/eval/src/bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { fileURLToPath } from "node:url";
import { Command } from "commander";
import { ensureIndex } from "./agent/build-cache.js";
import { loadPreviousResult, saveResult, generateTrendSummary } from "./agent/history.js";
import { ConsoleObserver, NoopObserver } from "./agent/observer.js";
import { ConsoleObserver } from "./agent/observer.js";
import { ensureRepo } from "./agent/repo-cache.js";
import { defaultModelForProvider, resolveAgentProvider } from "./agent/provider.js";
import { runAgentEval } from "./agent/runner.js";
Expand All @@ -26,7 +26,6 @@ const __dirname = path.dirname(__filename);
const EVAL_PKG_ROOT = path.resolve(__dirname, "..");
const FIXTURES_DIR = path.join(EVAL_PKG_ROOT, "fixtures", "agent-scenarios");
const CLI_BIN_PATH = path.resolve(EVAL_PKG_ROOT, "..", "cli", "dist", "index.js");
const SERVER_BIN_PATH = path.resolve(EVAL_PKG_ROOT, "..", "server", "dist", "bin.js");

const program = new Command();

Expand Down
4 changes: 1 addition & 3 deletions packages/server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,7 @@ export class McpDocsServer implements ToolProvider {

console.log("Looking up resource for filepath:", filepath);
const entries = await this.index.listFilepaths({
filters: {
filepath,
},
filters: {},
});

const entry = entries.find((e) => e.filepath === filepath);
Expand Down
4 changes: 2 additions & 2 deletions packages/server/test/http.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ describe("MCP HTTP transport resources", () => {

const { resources } = await client.listResources();
expect(resources).toHaveLength(1);
expect(resources[0].uri).toBe("docs://language/typescript/guides/ts.md");
expect(resources[0].uri).toBe("docs:///guides/ts.md");
expect(resources[0].name).toBe("guides/ts.md");
expect(resources[0].mimeType).toBe("text/markdown");

Expand All @@ -265,7 +265,7 @@ describe("MCP HTTP transport resources", () => {
await client.connect(transport);

const result = await client.readResource({
uri: "docs://language/typescript/guides/ts.md",
uri: "docs:///guides/ts.md",
});
expect(result.contents).toHaveLength(1);
expect(result.contents[0].text).toContain("TypeScript retry");
Expand Down
8 changes: 4 additions & 4 deletions packages/server/test/server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ describe("McpDocsServer resources", () => {

const resources = await server.getResources();
expect(resources).toHaveLength(1);
expect(resources[0].uri).toBe("docs://language/typescript/guides/ts.md");
expect(resources[0].uri).toBe("docs:///guides/ts.md");
expect(resources[0].name).toBe("guides/ts.md");
expect(resources[0].mimeType).toBe("text/markdown");
});
Expand Down Expand Up @@ -257,7 +257,7 @@ describe("McpDocsServer resources", () => {
metadata: metadataWithResources,
});

const result = await server.readResource("docs://language/typescript/guides/ts.md");
const result = await server.readResource("docs:///guides/ts.md");
expect(result.contents).toHaveLength(1);
expect(result.contents[0].text).toContain("TypeScript retry");
expect(result.contents[0].mimeType).toBe("text/markdown");
Expand Down Expand Up @@ -292,7 +292,7 @@ describe("McpDocsServer resources", () => {
metadata: metadataWithResources,
});

await expect(server.readResource("docs://language/typescript/nonexistent.md")).rejects.toThrow(
await expect(server.readResource("docs:///nonexistent.md")).rejects.toThrow(
/Resource not found/,
);
});
Expand All @@ -303,6 +303,6 @@ describe("McpDocsServer resources", () => {
metadata,
});

await expect(server.readResource("invalid://uri")).rejects.toThrow(/Invalid resource URI/);
await expect(server.readResource("invalid://uri")).rejects.toThrow(/Invalid URI scheme/);
});
});
2 changes: 1 addition & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.