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: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:

jobs:
sdk:
runs-on: ubuntu-latest
runs-on: ${{ (startsWith(vars.CI_RUNNER, 'blacksmith-') && vars.CI_RUNNER) || 'blacksmith-4vcpu-ubuntu-2404' }}
strategy:
fail-fast: false
matrix:
Expand All @@ -17,7 +17,7 @@ jobs:
run:
working-directory: sdks/typescript-sdk
steps:
- uses: actions/checkout@v4
- uses: useblacksmith/checkout@v1
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
Expand All @@ -42,9 +42,9 @@ jobs:
run: npm run lint

mcp:
runs-on: ubuntu-latest
runs-on: ${{ (startsWith(vars.CI_RUNNER, 'blacksmith-') && vars.CI_RUNNER) || 'blacksmith-4vcpu-ubuntu-2404' }}
steps:
- uses: actions/checkout@v4
- uses: useblacksmith/checkout@v1
- uses: actions/setup-node@v4
with:
node-version: 24
Expand Down
14 changes: 9 additions & 5 deletions .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,26 @@ jobs:
# github.event.pull_request.user.login == 'new-developer' ||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'

runs-on: ubuntu-latest
runs-on: ${{ (startsWith(vars.CI_RUNNER_SMALL, 'blacksmith-') && vars.CI_RUNNER_SMALL) || 'blacksmith-2vcpu-ubuntu-2404' }}
timeout-minutes: 30
permissions:
contents: read
pull-requests: read
pull-requests: write
issues: read
id-token: write
concurrency:
group: claude-review-${{ github.event.pull_request.number }}
cancel-in-progress: true

steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: useblacksmith/checkout@v1
with:
fetch-depth: 1
fetch-depth: 50

- name: Run Claude Code Review
id: claude-review
continue-on-error: true
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
Expand All @@ -41,4 +46,3 @@ jobs:
prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options

98 changes: 75 additions & 23 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
@@ -1,50 +1,102 @@
name: Claude Code
name: Claude Code (@claude)

on:
issue_comment:
types: [created]
types: [created, edited]
pull_request_review_comment:
types: [created]
types: [created, edited]
issues:
types: [opened, assigned]
types: [opened, assigned, edited]
pull_request_review:
types: [submitted]
types: [submitted, edited]

jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
github.actor != 'claude[bot]' && (
(
github.event_name == 'issue_comment' &&
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association) &&
contains(github.event.comment.body, '@claude')
) ||
(
github.event_name == 'pull_request_review_comment' &&
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association) &&
contains(github.event.comment.body, '@claude')
) ||
(
github.event_name == 'pull_request_review' &&
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.review.author_association) &&
contains(github.event.review.body, '@claude')
) ||
(
github.event_name == 'issues' &&
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.issue.author_association) &&
(contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))
)
)
runs-on: ${{ (startsWith(vars.CI_RUNNER_SMALL, 'blacksmith-') && vars.CI_RUNNER_SMALL) || 'blacksmith-2vcpu-ubuntu-2404' }}
timeout-minutes: 45
permissions:
contents: read
pull-requests: read
issues: read
contents: write
pull-requests: write
issues: write
id-token: write
actions: read # Required for Claude to read CI results on PRs
actions: read
checks: read
concurrency:
group: claude-interactive-${{ github.repository }}-${{ github.event.issue.number || github.event.pull_request.number || github.run_id }}
cancel-in-progress: false

steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: useblacksmith/checkout@v1
with:
fetch-depth: 1
fetch-depth: 50

- name: Verify Claude auth secret
env:
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
if [ -z "$CLAUDE_CODE_OAUTH_TOKEN" ] && [ -z "$ANTHROPIC_API_KEY" ]; then
echo "::error::Set CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_API_KEY in this repository's Actions secrets."
exit 1
fi

- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}

# This is an optional setting that allows Claude to read CI results on PRs
additional_permissions: |
actions: read
checks: read

claude_args: |
--append-system-prompt "Read AGENTS.md before making changes and follow the documentation repository rules.

This is the public Terminal49 API documentation repository.

Project structure:
- docs/ contains the Mintlify site content and configuration.
- docs/openapi.json is the source of truth for API reference content.
- Terminal49-API.postman_collection.json is generated from docs/openapi.json and must not be edited manually.
- WRITING_GUIDE.md contains writing standards, voice, terminology, and content guidelines.
- docs/AGENTS.md may contain more specific rules for docs/ changes.

# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
# prompt: 'Update the pull request description to include a summary of changes.'
Safety and security:
- Do not commit API keys, internal URLs, customer data, or proprietary information.
- Use placeholders such as Token YOUR_API_KEY in examples.
- Keep changes narrow and docs-focused unless the user explicitly asks for broader work.

# Optional: Add claude_args to customize behavior and configuration
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options
# claude_args: '--allowed-tools Bash(gh pr *)'
Useful commands:
- cd docs && mintlify dev
- spectral lint --ruleset .spectral.mjs docs/openapi.json
- openapi2postmanv2 -s docs/openapi.json -o Terminal49-API.postman_collection.json -p -O folderStrategy=Tags

If API behavior or schemas change, update docs/openapi.json first. Regenerate the Postman collection only when explicitly needed.
Shell execution is disabled for public-repository safety; when validation needs shell commands, report the exact commands for a maintainer to run."
--allowedTools Glob,Grep,Read,Write,Edit,Task
6 changes: 3 additions & 3 deletions .github/workflows/deploy_postman.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ on:

jobs:
deploy-postman-collection:
runs-on: ubuntu-latest
runs-on: ${{ (startsWith(vars.CI_RUNNER_SMALL, 'blacksmith-') && vars.CI_RUNNER_SMALL) || 'blacksmith-2vcpu-ubuntu-2404' }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: useblacksmith/checkout@v1

- name: Install jq (for Postman API call)
run: sudo apt-get update && sudo apt-get install -y jq
Expand Down Expand Up @@ -52,4 +52,4 @@ jobs:
else
echo "❌ Error: Failed to update Postman collection via API."
exit 1
fi
fi
5 changes: 2 additions & 3 deletions .github/workflows/generate_postman.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ on:

jobs:
generate-postman-collection:
runs-on: ubuntu-latest
runs-on: ${{ (startsWith(vars.CI_RUNNER_SMALL, 'blacksmith-') && vars.CI_RUNNER_SMALL) || 'blacksmith-2vcpu-ubuntu-2404' }}
permissions:
contents: write # Needed for committing back to the repo
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: useblacksmith/checkout@v1
with:
fetch-depth: 0 # Full history for proper diffing

Expand Down Expand Up @@ -49,4 +49,3 @@ jobs:
run: |
echo "Pushing updated collection to ${{ github.ref_name }}..."
git push origin HEAD:${{ github.ref_name }}

4 changes: 2 additions & 2 deletions .github/workflows/publish_typescript_sdk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ permissions:

jobs:
publish:
runs-on: ubuntu-latest
runs-on: ${{ (startsWith(vars.CI_RUNNER_SMALL, 'blacksmith-') && vars.CI_RUNNER_SMALL) || 'blacksmith-2vcpu-ubuntu-2404' }}
steps:
- name: Resolve release tag
id: release-tag
run: echo "tag=${{ github.event.release.tag_name || inputs.tag }}" >> "$GITHUB_OUTPUT"

- name: Checkout
uses: actions/checkout@v4
uses: useblacksmith/checkout@v1
with:
ref: ${{ steps.release-tag.outputs.tag }}

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release_please_sdk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ permissions:

jobs:
release-please:
runs-on: ubuntu-latest
runs-on: ${{ (startsWith(vars.CI_RUNNER_SMALL, 'blacksmith-') && vars.CI_RUNNER_SMALL) || 'blacksmith-2vcpu-ubuntu-2404' }}
steps:
- uses: googleapis/release-please-action@v4
id: release
Expand Down
12 changes: 6 additions & 6 deletions packages/mcp/TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,12 +301,12 @@ name: Test MCP Server

on: [push, pull_request]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
jobs:
test:
runs-on: blacksmith-2vcpu-ubuntu-2404
steps:
- uses: useblacksmith/checkout@v1
- uses: actions/setup-node@v4
with:
node-version: '20'

Expand Down
34 changes: 34 additions & 0 deletions sdks/typescript-sdk/scripts/clean-generated-docs.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,45 @@
/** Wipe the TypeDoc output directory before regeneration. */
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const outputDir = path.resolve(__dirname, '../../../docs/sdk/reference');
const frontmatterCachePath = path.join(
os.tmpdir(),
'terminal49-sdk-docs-frontmatter-cache.json',
);

function listMdxFiles(dir) {
if (!fs.existsSync(dir)) return [];
const entries = fs.readdirSync(dir, { withFileTypes: true });
return entries.flatMap((entry) => {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) return listMdxFiles(fullPath);
return entry.isFile() && entry.name.endsWith('.mdx') ? [fullPath] : [];
});
}

function frontmatterFor(content) {
return content.match(/^---\n([\s\S]*?)\n---\n/)?.[1];
}

const frontmatterByPath = {};
for (const filePath of listMdxFiles(outputDir)) {
const content = fs.readFileSync(filePath, 'utf8');
const frontmatter = frontmatterFor(content);
if (!frontmatter) continue;

const relativePath = path
.relative(outputDir, filePath)
.split(path.sep)
.join(path.posix.sep);
frontmatterByPath[relativePath] = frontmatter;
}

fs.writeFileSync(frontmatterCachePath, JSON.stringify(frontmatterByPath));

fs.rmSync(outputDir, { recursive: true, force: true });
fs.mkdirSync(outputDir, { recursive: true });
24 changes: 24 additions & 0 deletions sdks/typescript-sdk/scripts/postprocess-generated-docs.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@
* 3. Cleans up module page titles (e.g. "client" → "Client Module").
*/
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const outputDir = path.resolve(__dirname, '../../../docs/sdk/reference');
const routePrefix = '/sdk/reference';
const frontmatterCachePath = path.join(
os.tmpdir(),
'terminal49-sdk-docs-frontmatter-cache.json',
);

/** Human-readable overrides for module index page titles. */
const MODULE_TITLE_OVERRIDES = {
Expand All @@ -22,6 +27,10 @@ const MODULE_TITLE_OVERRIDES = {
options: 'Options',
};

const frontmatterByPath = fs.existsSync(frontmatterCachePath)
? JSON.parse(fs.readFileSync(frontmatterCachePath, 'utf8'))
: {};

function listMdxFiles(dir) {
const entries = fs.readdirSync(dir, { withFileTypes: true });
return entries.flatMap((entry) => {
Expand Down Expand Up @@ -64,7 +73,20 @@ function rewriteMdxLinks(content, filePath) {
});
}

function stripFrontmatter(content) {
return content.replace(/^---\n[\s\S]*?\n---\n+/, '');
}

function ensureFrontmatter(content, filePath) {
const relativePath = path
.relative(outputDir, filePath)
.split(path.sep)
.join(path.posix.sep);
const cachedFrontmatter = frontmatterByPath[relativePath];
if (cachedFrontmatter) {
return `---\n${cachedFrontmatter}\n---\n\n${stripFrontmatter(content)}`;
}

if (content.startsWith('---\n')) return content;
const title = frontmatterTitle(content, filePath);
return `---\ntitle: ${JSON.stringify(title)}\n---\n\n${content}`;
Expand All @@ -76,3 +98,5 @@ for (const filePath of listMdxFiles(outputDir)) {
const withFrontmatter = ensureFrontmatter(withLinks, filePath);
fs.writeFileSync(filePath, withFrontmatter);
}

fs.rmSync(frontmatterCachePath, { force: true });
Loading