From da11f975b68f344fa5f4a29b8daa919042b2d98f Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 17:58:58 +0100 Subject: [PATCH 01/21] add action --- .github/workflows/auto-llms-txt.yml | 105 ++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 .github/workflows/auto-llms-txt.yml diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml new file mode 100644 index 00000000..2f60de77 --- /dev/null +++ b/.github/workflows/auto-llms-txt.yml @@ -0,0 +1,105 @@ +name: Auto Update LLMs.txt Files + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + paths: + - 'docs/base-account/**' + - 'docs/base-app/**' + - 'docs/base-chain/**' + - 'docs/cookbook/**' + - 'docs/get-started/**' + - 'docs/learn/**' + - 'docs/mini-apps/**' + - 'docs/onchainkit/**' + +permissions: + contents: write + pull-requests: write + +jobs: + update-llms-txt: + if: ${{ !startsWith(github.head_ref, 'auto-llms/') }} + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Install Cursor CLI + run: | + curl https://cursor.com/install -fsS | bash + echo "$HOME/.cursor/bin" >> $GITHUB_PATH + + - name: Configure git + run: | + git config user.name "Cursor Agent" + git config user.email "cursoragent@cursor.com" + + - name: Update LLMs.txt files + env: + MODEL: gpt-5 + CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BRANCH_PREFIX: auto-llms + run: | + cursor-agent -p "You are operating in a GitHub Actions runner to automatically update llms.txt and llms-full.txt files. + + The GitHub CLI is available as \`gh\` and authenticated via \`GH_TOKEN\`. Git is available. You have write access to repository contents and can comment on pull requests, but you must not create or edit PRs directly. + + # Context: + - Repo: ${{ github.repository }} + - Owner: ${{ github.repository_owner }} + - PR Number: ${{ github.event.pull_request.number }} + - Base Ref: ${{ github.base_ref }} + - Head Ref: ${{ github.head_ref }} + - Branch Prefix: ${{ env.BRANCH_PREFIX }} + + # Documentation Structure: + This is a docs repository with the following main directories that each contain llms.txt and llms-full.txt files: + - docs/base-account/ + - docs/base-app/ + - docs/base-chain/ + - docs/cookbook/ + - docs/get-started/ + - docs/learn/ + - docs/mini-apps/ + - docs/onchainkit/ + + # Goal: + Analyze changes in the original PR and determine if they are significant enough to warrant updating the llms.txt and llms-full.txt files for the affected directories. If so, create a separate PR with the updates. + + # Requirements: + 1) Use \`gh pr diff\` to analyze what changed in the original PR + 2) Determine which documentation directories are affected by the changes + 3) Assess if the changes are significant enough to update the llms.txt files (new content, major restructuring, new features, etc.) + 4) If changes are significant: + - Create or update a persistent branch named \`${{ env.BRANCH_PREFIX }}/pr-${{ github.event.pull_request.number }}\` + - Update the relevant llms.txt and llms-full.txt files to reflect the new documentation structure and content + - Push the changes to the branch + - Comment on the original PR with a summary and a compare link to create the PR + 5) If changes are not significant: + - Comment on the original PR explaining that no llms.txt updates are needed + + # File Format Guidelines: + - llms.txt files should be concise, focused summaries with key links + - llms-full.txt files should be comprehensive with all documentation links + - Follow the existing format and style of the current files + - Include proper section headers and descriptions + - Use relative links in the format: https://docs.base.org/[path] + + # Significance Criteria: + Consider changes significant if they involve: + - New documentation files or sections + - Major content restructuring + - New features or API endpoints + - Changes to core concepts or workflows + - New guides or tutorials + + # Deliverables: + - If updates needed: Pushed commits to the persistent branch and a PR comment with compare link + - If no updates needed: A brief comment explaining why no updates are required + - Keep all changes minimal and consistent with existing documentation style + " --force --model "$MODEL" --output-format=text From f923ca7db1a5e473877b1b12baf57e638ed60dde Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 18:03:01 +0100 Subject: [PATCH 02/21] test commit --- .../guides/advanced-authentication.mdx | 475 ++++++++++++++++++ docs/cookbook/build-cross-chain-apps.mdx | 357 +++++++++++++ 2 files changed, 832 insertions(+) create mode 100644 docs/base-account/guides/advanced-authentication.mdx create mode 100644 docs/cookbook/build-cross-chain-apps.mdx diff --git a/docs/base-account/guides/advanced-authentication.mdx b/docs/base-account/guides/advanced-authentication.mdx new file mode 100644 index 00000000..54f7d1a1 --- /dev/null +++ b/docs/base-account/guides/advanced-authentication.mdx @@ -0,0 +1,475 @@ +--- +title: "Advanced Authentication Patterns" +description: "Implement sophisticated authentication flows with Base Account including multi-factor authentication, session management, and enterprise integrations." +--- + +# Advanced Authentication Patterns + +Base Account provides powerful authentication capabilities beyond basic wallet connection. This guide covers advanced patterns for building secure, enterprise-ready authentication systems. + +## Multi-Factor Authentication (MFA) + +### Passkey + Biometric Authentication + +Combine passkeys with device biometrics for enhanced security: + +```typescript +import { createBaseAccount } from '@base-account/core' + +const account = await createBaseAccount({ + authentication: { + primary: 'passkey', + secondary: 'biometric', + fallback: 'recovery-phrase' + } +}) + +// Authenticate with both factors +const session = await account.authenticate({ + requireBoth: true, + biometricPrompt: 'Confirm your identity' +}) +``` + +### Time-Based One-Time Passwords (TOTP) + +Integrate TOTP for additional security: + +```typescript +import { generateTOTPSecret, verifyTOTP } from '@base-account/totp' + +class TOTPAuthenticator { + async setupTOTP(account: BaseAccount) { + const secret = generateTOTPSecret() + + // Store encrypted secret + await account.secureStorage.set('totp_secret', secret, { + encrypted: true, + requireAuth: true + }) + + return { + secret, + qrCode: this.generateQRCode(secret, account.address) + } + } + + async verifyTOTP(account: BaseAccount, token: string) { + const secret = await account.secureStorage.get('totp_secret') + return verifyTOTP(secret, token) + } +} +``` + +## Session Management + +### Secure Session Tokens + +Implement secure, time-limited sessions: + +```typescript +interface SessionConfig { + duration: number // milliseconds + refreshable: boolean + deviceBinding: boolean + ipRestriction?: string[] +} + +class SessionManager { + async createSession( + account: BaseAccount, + config: SessionConfig + ): Promise { + const sessionId = crypto.randomUUID() + const expiresAt = Date.now() + config.duration + + const session = { + id: sessionId, + accountAddress: account.address, + expiresAt, + deviceFingerprint: config.deviceBinding ? + await this.getDeviceFingerprint() : null, + allowedIPs: config.ipRestriction + } + + // Store session securely + await this.storeSession(session) + + return this.generateJWT(session) + } + + async refreshSession(token: SessionToken): Promise { + const session = await this.validateAndGetSession(token) + + if (!session.refreshable) { + throw new Error('Session not refreshable') + } + + return this.createSession(session.account, { + duration: session.originalDuration, + refreshable: true, + deviceBinding: session.deviceBinding + }) + } +} +``` + +### Cross-Device Session Sync + +Synchronize sessions across user devices: + +```typescript +class CrossDeviceSessionManager { + async syncSessions(account: BaseAccount) { + // Get all active sessions for account + const sessions = await this.getActiveSessions(account.address) + + // Sync to secure cloud storage + await account.cloudSync.set('active_sessions', sessions, { + encrypted: true, + requireConsent: true + }) + } + + async authorizeNewDevice( + account: BaseAccount, + deviceInfo: DeviceInfo + ): Promise { + // Require approval from existing device + const approval = await this.requestDeviceApproval( + account, + deviceInfo + ) + + if (approval.approved) { + await this.addAuthorizedDevice(account, deviceInfo) + return true + } + + return false + } +} +``` + +## Enterprise Integration + +### SAML SSO Integration + +Integrate with enterprise SAML providers: + +```typescript +import { SAMLProvider } from '@base-account/enterprise' + +class EnterpriseAuth { + async configureSAML(config: SAMLConfig) { + const provider = new SAMLProvider({ + entityId: config.entityId, + ssoUrl: config.ssoUrl, + certificate: config.certificate, + attributeMapping: { + email: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress', + name: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name', + department: 'http://schemas.example.com/department' + } + }) + + return provider + } + + async authenticateWithSAML( + samlResponse: string, + account: BaseAccount + ) { + const provider = this.getSAMLProvider() + const assertion = await provider.validateResponse(samlResponse) + + // Link SAML identity to Base Account + await account.linkIdentity('saml', { + nameId: assertion.nameId, + attributes: assertion.attributes, + sessionIndex: assertion.sessionIndex + }) + + return assertion + } +} +``` + +### OAuth 2.0 / OpenID Connect + +Support OAuth providers: + +```typescript +class OAuthIntegration { + async configureOAuth(provider: OAuthProvider) { + return { + clientId: provider.clientId, + redirectUri: provider.redirectUri, + scopes: ['openid', 'profile', 'email'], + pkceEnabled: true + } + } + + async handleOAuthCallback( + code: string, + state: string, + account: BaseAccount + ) { + // Exchange code for tokens + const tokens = await this.exchangeCodeForTokens(code, state) + + // Get user info + const userInfo = await this.getUserInfo(tokens.accessToken) + + // Link to Base Account + await account.linkIdentity('oauth', { + provider: this.providerName, + subject: userInfo.sub, + profile: userInfo + }) + + return { tokens, userInfo } + } +} +``` + +## Advanced Security Features + +### Risk-Based Authentication + +Implement adaptive authentication based on risk factors: + +```typescript +class RiskAssessment { + async assessRisk( + account: BaseAccount, + context: AuthContext + ): Promise { + const factors = { + deviceTrust: await this.assessDeviceTrust(context.device), + locationRisk: await this.assessLocationRisk(context.location), + behaviorPattern: await this.assessBehaviorPattern( + account, + context.behavior + ), + networkRisk: await this.assessNetworkRisk(context.network) + } + + const score = this.calculateRiskScore(factors) + + return { + score, + factors, + recommendation: this.getRecommendation(score) + } + } + + getRecommendation(score: number): AuthRecommendation { + if (score < 0.3) return 'ALLOW' + if (score < 0.7) return 'CHALLENGE' + return 'DENY' + } +} +``` + +### Zero-Knowledge Proofs + +Implement privacy-preserving authentication: + +```typescript +import { generateProof, verifyProof } from '@base-account/zk' + +class ZKAuthentication { + async generateIdentityProof( + account: BaseAccount, + claim: IdentityClaim + ): Promise { + const circuit = await this.loadCircuit('identity-verification') + + const proof = await generateProof(circuit, { + privateInputs: { + identity: account.identity, + secret: account.zkSecret + }, + publicInputs: { + claim: claim, + timestamp: Date.now() + } + }) + + return proof + } + + async verifyIdentityProof(proof: ZKProof): Promise { + const circuit = await this.loadCircuit('identity-verification') + return verifyProof(circuit, proof) + } +} +``` + +## Audit and Compliance + +### Authentication Logging + +Comprehensive audit logging: + +```typescript +class AuthenticationAuditor { + async logAuthEvent(event: AuthEvent) { + const auditLog = { + timestamp: new Date().toISOString(), + eventType: event.type, + accountAddress: event.account, + deviceId: event.deviceId, + ipAddress: event.ipAddress, + userAgent: event.userAgent, + success: event.success, + failureReason: event.failureReason, + riskScore: event.riskScore, + metadata: event.metadata + } + + // Store in immutable audit log + await this.auditStorage.append(auditLog) + + // Alert on suspicious activity + if (this.isSuspicious(event)) { + await this.alertSecurityTeam(auditLog) + } + } + + async generateComplianceReport( + startDate: Date, + endDate: Date + ): Promise { + const logs = await this.auditStorage.query({ + timestamp: { $gte: startDate, $lte: endDate } + }) + + return { + totalAuthentications: logs.length, + successfulAuthentications: logs.filter(l => l.success).length, + failedAuthentications: logs.filter(l => !l.success).length, + uniqueUsers: new Set(logs.map(l => l.accountAddress)).size, + riskDistribution: this.calculateRiskDistribution(logs), + complianceStatus: this.assessCompliance(logs) + } + } +} +``` + +### GDPR Compliance + +Implement privacy controls: + +```typescript +class PrivacyManager { + async handleDataRequest( + account: BaseAccount, + requestType: 'export' | 'delete' | 'rectify' + ) { + switch (requestType) { + case 'export': + return this.exportUserData(account) + case 'delete': + return this.deleteUserData(account) + case 'rectify': + return this.rectifyUserData(account) + } + } + + async exportUserData(account: BaseAccount) { + const data = { + profile: await account.getProfile(), + authHistory: await this.getAuthHistory(account), + linkedIdentities: await account.getLinkedIdentities(), + preferences: await account.getPreferences() + } + + // Anonymize sensitive data + return this.anonymizeExport(data) + } + + async deleteUserData(account: BaseAccount) { + // Soft delete with retention policy + await account.markForDeletion({ + retentionPeriod: 90, // days + preserveAuditTrail: true + }) + + // Remove from active systems + await this.removeFromActiveSystems(account) + } +} +``` + +## Testing Advanced Authentication + +### Unit Tests + +```typescript +describe('Advanced Authentication', () => { + describe('MFA', () => { + it('should require both passkey and TOTP', async () => { + const account = await createTestAccount() + const mfa = new MultiFactorAuth() + + await mfa.setupTOTP(account) + + const result = await mfa.authenticate(account, { + passkey: validPasskey, + totp: validTOTP + }) + + expect(result.success).toBe(true) + expect(result.factors).toHaveLength(2) + }) + }) + + describe('Session Management', () => { + it('should refresh sessions before expiry', async () => { + const sessionManager = new SessionManager() + const session = await sessionManager.createSession(account, { + duration: 3600000, // 1 hour + refreshable: true + }) + + // Fast-forward time + jest.advanceTimersByTime(3000000) // 50 minutes + + const refreshed = await sessionManager.refreshSession(session) + expect(refreshed).toBeDefined() + expect(refreshed.expiresAt).toBeGreaterThan(session.expiresAt) + }) + }) +}) +``` + +## Best Practices + +### Security Guidelines + +1. **Defense in Depth**: Layer multiple authentication factors +2. **Zero Trust**: Verify every request regardless of source +3. **Least Privilege**: Grant minimal necessary permissions +4. **Regular Rotation**: Rotate secrets and tokens regularly + +### Performance Optimization + +1. **Cache Wisely**: Cache non-sensitive authentication data +2. **Async Operations**: Use async patterns for auth flows +3. **Connection Pooling**: Pool database connections +4. **Rate Limiting**: Implement intelligent rate limiting + +### User Experience + +1. **Progressive Enhancement**: Start simple, add complexity gradually +2. **Clear Communication**: Explain security requirements +3. **Fallback Options**: Always provide recovery mechanisms +4. **Responsive Design**: Work across all device types + +## Conclusion + +Advanced authentication patterns enable you to build secure, enterprise-ready applications while maintaining excellent user experience. Start with basic patterns and gradually implement more sophisticated features as your application grows. + +Remember to always prioritize security while keeping the user experience smooth and intuitive. diff --git a/docs/cookbook/build-cross-chain-apps.mdx b/docs/cookbook/build-cross-chain-apps.mdx new file mode 100644 index 00000000..d9fcd473 --- /dev/null +++ b/docs/cookbook/build-cross-chain-apps.mdx @@ -0,0 +1,357 @@ +--- +title: "Build Cross-Chain Applications" +description: "Learn how to build applications that work seamlessly across multiple blockchain networks using Base as your primary chain." +--- + +# Build Cross-Chain Applications + +Building applications that work across multiple blockchain networks is essential for reaching users wherever they are. This guide shows you how to create cross-chain applications using Base as your primary chain while integrating with other networks. + +## Overview + +Cross-chain applications allow users to interact with multiple blockchain networks from a single interface. By building on Base, you get the benefits of low fees and fast transactions while maintaining compatibility with the broader Ethereum ecosystem. + +## Key Benefits + +- **Expanded user base**: Reach users across different blockchain networks +- **Enhanced liquidity**: Access assets from multiple chains +- **Improved user experience**: Seamless interactions without manual bridging +- **Future-proof architecture**: Ready for a multi-chain world + +## Architecture Patterns + +### 1. Hub and Spoke Model + +Use Base as your primary hub while connecting to other chains: + +```typescript +// Base as the primary chain +const baseConfig = { + chainId: 8453, + name: 'Base', + contracts: { + multicall: '0x...', + registry: '0x...' + } +} + +// Connected chains +const supportedChains = [ + { chainId: 1, name: 'Ethereum' }, + { chainId: 137, name: 'Polygon' }, + { chainId: 42161, name: 'Arbitrum' } +] +``` + +### 2. Multi-Chain State Management + +Synchronize state across chains: + +```typescript +interface CrossChainState { + baseState: BaseChainState + remoteStates: Map + pendingBridges: BridgeTransaction[] +} + +class CrossChainManager { + async syncState(chainId: number) { + const remoteState = await this.fetchRemoteState(chainId) + this.updateState(chainId, remoteState) + } +} +``` + +## Implementation Steps + +### Step 1: Set Up Multi-Chain Configuration + +Configure your application to support multiple networks: + +```typescript +import { createConfig, http } from 'wagmi' +import { base, mainnet, polygon, arbitrum } from 'wagmi/chains' + +const config = createConfig({ + chains: [base, mainnet, polygon, arbitrum], + transports: { + [base.id]: http(), + [mainnet.id]: http(), + [polygon.id]: http(), + [arbitrum.id]: http(), + }, +}) +``` + +### Step 2: Implement Bridge Integration + +Integrate with bridge protocols for asset transfers: + +```typescript +import { LayerZero, Stargate } from '@layerzerolabs/sdk' + +class BridgeService { + async bridgeAssets( + fromChain: number, + toChain: number, + asset: string, + amount: bigint + ) { + // Use LayerZero for messaging + const lzEndpoint = this.getLZEndpoint(fromChain) + + // Bridge assets using Stargate + const bridgeTx = await this.stargate.swap( + fromChain, + toChain, + asset, + amount + ) + + return bridgeTx + } +} +``` + +### Step 3: Create Unified User Interface + +Build a single interface that works across chains: + +```typescript +function CrossChainDashboard() { + const [selectedChain, setSelectedChain] = useState(base.id) + const { data: balances } = useMultiChainBalances() + + return ( +
+ + +
+ ) +} +``` + +## Advanced Features + +### Cross-Chain Messaging + +Implement messaging between chains: + +```solidity +// CrossChainMessenger.sol +contract CrossChainMessenger { + mapping(uint16 => address) public trustedRemotes; + + function sendMessage( + uint16 _dstChainId, + bytes memory _message + ) external payable { + _lzSend( + _dstChainId, + _message, + payable(msg.sender), + address(0x0), + bytes(""), + msg.value + ); + } +} +``` + +### Unified Asset Management + +Create a unified view of assets across chains: + +```typescript +class AssetManager { + async getUnifiedPortfolio(userAddress: string) { + const chains = [base.id, mainnet.id, polygon.id] + + const portfolios = await Promise.all( + chains.map(chainId => + this.getChainPortfolio(chainId, userAddress) + ) + ) + + return this.consolidatePortfolios(portfolios) + } +} +``` + +## Best Practices + +### 1. Gas Optimization + +- Use Base for frequent operations due to low gas costs +- Batch transactions when possible +- Implement gas estimation across chains + +### 2. Security Considerations + +- Validate cross-chain messages +- Implement timeouts for bridge transactions +- Use trusted bridge protocols + +### 3. User Experience + +- Show clear bridging status +- Provide gas estimates +- Handle failed transactions gracefully + +## Testing Strategy + +### Unit Tests + +Test individual components: + +```typescript +describe('CrossChainManager', () => { + it('should sync state across chains', async () => { + const manager = new CrossChainManager() + await manager.syncState(polygon.id) + + expect(manager.getState(polygon.id)).toBeDefined() + }) +}) +``` + +### Integration Tests + +Test cross-chain flows: + +```typescript +describe('Bridge Integration', () => { + it('should bridge assets from Base to Ethereum', async () => { + const bridgeService = new BridgeService() + + const tx = await bridgeService.bridgeAssets( + base.id, + mainnet.id, + 'USDC', + parseUnits('100', 6) + ) + + expect(tx).toBeDefined() + }) +}) +``` + +## Monitoring and Analytics + +### Track Cross-Chain Metrics + +```typescript +class CrossChainAnalytics { + trackBridgeTransaction( + fromChain: number, + toChain: number, + asset: string, + amount: bigint + ) { + this.analytics.track('bridge_transaction', { + from_chain: fromChain, + to_chain: toChain, + asset, + amount: amount.toString() + }) + } +} +``` + +### Health Monitoring + +Monitor bridge and RPC health: + +```typescript +class HealthMonitor { + async checkChainHealth(chainId: number) { + try { + const latestBlock = await this.getLatestBlock(chainId) + const blockAge = Date.now() - latestBlock.timestamp * 1000 + + return { + healthy: blockAge < 60000, // 1 minute + blockAge, + chainId + } + } catch (error) { + return { healthy: false, error, chainId } + } + } +} +``` + +## Deployment Considerations + +### Multi-Chain Deployment + +Deploy contracts across supported chains: + +```typescript +// deploy.ts +async function deployMultiChain() { + const chains = [base, polygon, arbitrum] + + for (const chain of chains) { + await deployToChain(chain.id) + } +} +``` + +### Configuration Management + +Manage chain-specific configurations: + +```typescript +const chainConfigs = { + [base.id]: { + rpcUrl: process.env.BASE_RPC_URL, + contracts: { /* Base contracts */ } + }, + [polygon.id]: { + rpcUrl: process.env.POLYGON_RPC_URL, + contracts: { /* Polygon contracts */ } + } +} +``` + +## Common Challenges and Solutions + +### 1. Bridge Delays + +**Challenge**: Bridge transactions can take time +**Solution**: Implement optimistic UX with proper status tracking + +### 2. Gas Price Variations + +**Challenge**: Different gas costs across chains +**Solution**: Dynamic gas estimation and user warnings + +### 3. Chain Reliability + +**Challenge**: RPC endpoints can be unreliable +**Solution**: Implement fallback RPC providers + +## Resources + +- [LayerZero Documentation](https://layerzero.gitbook.io/) +- [Stargate Finance](https://stargate.finance/) +- [Chainlink CCIP](https://docs.chain.link/ccip) +- [Hyperlane Protocol](https://docs.hyperlane.xyz/) + +## Next Steps + +1. Choose your bridge protocol +2. Set up multi-chain configuration +3. Implement core bridging functionality +4. Add monitoring and analytics +5. Test thoroughly across all supported chains +6. Deploy and monitor + +Building cross-chain applications opens up new possibilities for user engagement and liquidity access. Start with Base as your primary chain and gradually expand to other networks as your application grows. From 518ccf1ebb0ecaf8e1c525abd244bd3b312214ad Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 18:17:48 +0100 Subject: [PATCH 03/21] update to add possibility to kill --- .github/workflows/auto-llms-txt.yml | 41 +++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index 2f60de77..a9f800de 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -38,17 +38,58 @@ jobs: git config user.name "Cursor Agent" git config user.email "cursoragent@cursor.com" + - name: Post initial comment + run: | + COMMENT_ID=$(gh pr comment ${{ github.event.pull_request.number }} --body "🤖 **LLMs.txt Auto-Update** + + Analyzing documentation changes to update llms.txt files... + + 💡 **Want to stop this process?** Comment \`stop\` below and I'll cancel the analysis. + + âąī¸ This will timeout after 30 minutes." --json id --jq '.id') + echo "COMMENT_ID=$COMMENT_ID" >> $GITHUB_ENV + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Update LLMs.txt files + timeout-minutes: 30 env: MODEL: gpt-5 CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} BRANCH_PREFIX: auto-llms run: | + # Check for stop command every 30 seconds + check_stop() { + if gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.author.login == "github-actions[bot]" and (.body | contains("stop")))' | grep -q stop; then + gh pr comment ${{ github.event.pull_request.number }} --body "âšī¸ **Analysis Stopped** + + LLMs.txt analysis cancelled per user request." + exit 0 + fi + } + + # Run stop check in background + while true; do + sleep 30 + check_stop + done & + STOP_PID=$! + + # Cleanup function + cleanup() { + kill $STOP_PID 2>/dev/null || true + } + trap cleanup EXIT + cursor-agent -p "You are operating in a GitHub Actions runner to automatically update llms.txt and llms-full.txt files. The GitHub CLI is available as \`gh\` and authenticated via \`GH_TOKEN\`. Git is available. You have write access to repository contents and can comment on pull requests, but you must not create or edit PRs directly. + IMPORTANT: Check for stop commands by running this periodically during your analysis: + \`gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.body | contains(\"stop\"))'\` + If any comment contains 'stop', immediately exit with a cancellation message. + # Context: - Repo: ${{ github.repository }} - Owner: ${{ github.repository_owner }} From bb5a779eb81f1ceea7804052fd275422edf223c1 Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 18:20:23 +0100 Subject: [PATCH 04/21] update --- .github/workflows/auto-llms-txt.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index a9f800de..1e2a073a 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -40,14 +40,13 @@ jobs: - name: Post initial comment run: | - COMMENT_ID=$(gh pr comment ${{ github.event.pull_request.number }} --body "🤖 **LLMs.txt Auto-Update** + gh pr comment ${{ github.event.pull_request.number }} --body "🤖 **LLMs.txt Auto-Update** Analyzing documentation changes to update llms.txt files... 💡 **Want to stop this process?** Comment \`stop\` below and I'll cancel the analysis. - âąī¸ This will timeout after 30 minutes." --json id --jq '.id') - echo "COMMENT_ID=$COMMENT_ID" >> $GITHUB_ENV + âąī¸ This will timeout after 30 minutes." env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -61,7 +60,7 @@ jobs: run: | # Check for stop command every 30 seconds check_stop() { - if gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.author.login == "github-actions[bot]" and (.body | contains("stop")))' | grep -q stop; then + if gh pr view ${{ github.event.pull_request.number }} --json comments --jq -r '.comments[] | select(.body | contains("stop")) | .body' | grep -q stop; then gh pr comment ${{ github.event.pull_request.number }} --body "âšī¸ **Analysis Stopped** LLMs.txt analysis cancelled per user request." From 0cac5400457917e52c8042fecb27a9ac73cb11b1 Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 18:27:23 +0100 Subject: [PATCH 05/21] update workflow --- .github/workflows/auto-llms-txt.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index 1e2a073a..d58734d0 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -85,9 +85,10 @@ jobs: The GitHub CLI is available as \`gh\` and authenticated via \`GH_TOKEN\`. Git is available. You have write access to repository contents and can comment on pull requests, but you must not create or edit PRs directly. - IMPORTANT: Check for stop commands by running this periodically during your analysis: - \`gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.body | contains(\"stop\"))'\` - If any comment contains 'stop', immediately exit with a cancellation message. + IMPORTANT: Before starting your analysis, check if the user wants to stop by running: + gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.body | contains(\"stop\"))' + + If this returns any results, immediately post a cancellation comment and exit. Otherwise, proceed with your analysis. # Context: - Repo: ${{ github.repository }} @@ -142,4 +143,6 @@ jobs: - If updates needed: Pushed commits to the persistent branch and a PR comment with compare link - If no updates needed: A brief comment explaining why no updates are required - Keep all changes minimal and consistent with existing documentation style + + CRITICAL: After completing ANY of the above actions (stop command, updates completed, or no updates needed), you MUST immediately exit by running 'exit 0'. Do not continue running or wait for additional input. " --force --model "$MODEL" --output-format=text From 158c98dcf6dc8adee70fb7c5acda1baed81cb734 Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 18:31:58 +0100 Subject: [PATCH 06/21] remove comment --- .github/workflows/auto-llms-txt.yml | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index d58734d0..4be8121f 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -58,29 +58,6 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} BRANCH_PREFIX: auto-llms run: | - # Check for stop command every 30 seconds - check_stop() { - if gh pr view ${{ github.event.pull_request.number }} --json comments --jq -r '.comments[] | select(.body | contains("stop")) | .body' | grep -q stop; then - gh pr comment ${{ github.event.pull_request.number }} --body "âšī¸ **Analysis Stopped** - - LLMs.txt analysis cancelled per user request." - exit 0 - fi - } - - # Run stop check in background - while true; do - sleep 30 - check_stop - done & - STOP_PID=$! - - # Cleanup function - cleanup() { - kill $STOP_PID 2>/dev/null || true - } - trap cleanup EXIT - cursor-agent -p "You are operating in a GitHub Actions runner to automatically update llms.txt and llms-full.txt files. The GitHub CLI is available as \`gh\` and authenticated via \`GH_TOKEN\`. Git is available. You have write access to repository contents and can comment on pull requests, but you must not create or edit PRs directly. From f54c91e722e49bde656e0d9c6c31779844de85c7 Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 19:07:19 +0100 Subject: [PATCH 07/21] update to json --- .github/workflows/auto-llms-txt.yml | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index 4be8121f..2a364829 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -58,22 +58,30 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} BRANCH_PREFIX: auto-llms run: | + # Expand variables for the agent + REPO="${{ github.repository }}" + OWNER="${{ github.repository_owner }}" + PR_NUMBER="${{ github.event.pull_request.number }}" + BASE_REF="${{ github.base_ref }}" + HEAD_REF="${{ github.head_ref }}" + BRANCH_PREFIX="${{ env.BRANCH_PREFIX }}" + cursor-agent -p "You are operating in a GitHub Actions runner to automatically update llms.txt and llms-full.txt files. The GitHub CLI is available as \`gh\` and authenticated via \`GH_TOKEN\`. Git is available. You have write access to repository contents and can comment on pull requests, but you must not create or edit PRs directly. IMPORTANT: Before starting your analysis, check if the user wants to stop by running: - gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.body | contains(\"stop\"))' + gh pr view ${PR_NUMBER} --json comments --jq '.comments[] | select(.body | contains(\"stop\"))' If this returns any results, immediately post a cancellation comment and exit. Otherwise, proceed with your analysis. # Context: - - Repo: ${{ github.repository }} - - Owner: ${{ github.repository_owner }} - - PR Number: ${{ github.event.pull_request.number }} - - Base Ref: ${{ github.base_ref }} - - Head Ref: ${{ github.head_ref }} - - Branch Prefix: ${{ env.BRANCH_PREFIX }} + - Repo: ${REPO} + - Owner: ${OWNER} + - PR Number: ${PR_NUMBER} + - Base Ref: ${BASE_REF} + - Head Ref: ${HEAD_REF} + - Branch Prefix: ${BRANCH_PREFIX} # Documentation Structure: This is a docs repository with the following main directories that each contain llms.txt and llms-full.txt files: @@ -94,7 +102,7 @@ jobs: 2) Determine which documentation directories are affected by the changes 3) Assess if the changes are significant enough to update the llms.txt files (new content, major restructuring, new features, etc.) 4) If changes are significant: - - Create or update a persistent branch named \`${{ env.BRANCH_PREFIX }}/pr-${{ github.event.pull_request.number }}\` + - Create or update a persistent branch named \`${BRANCH_PREFIX}/pr-${PR_NUMBER}\` - Update the relevant llms.txt and llms-full.txt files to reflect the new documentation structure and content - Push the changes to the branch - Comment on the original PR with a summary and a compare link to create the PR @@ -122,4 +130,4 @@ jobs: - Keep all changes minimal and consistent with existing documentation style CRITICAL: After completing ANY of the above actions (stop command, updates completed, or no updates needed), you MUST immediately exit by running 'exit 0'. Do not continue running or wait for additional input. - " --force --model "$MODEL" --output-format=text + " --force --model "$MODEL" --output-format=json From e153967bb153f8833a3ed72273b7b3526eb8b63c Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 19:12:59 +0100 Subject: [PATCH 08/21] add json parsing --- .github/workflows/auto-llms-txt.yml | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index 2a364829..b5ea5404 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -66,7 +66,8 @@ jobs: HEAD_REF="${{ github.head_ref }}" BRANCH_PREFIX="${{ env.BRANCH_PREFIX }}" - cursor-agent -p "You are operating in a GitHub Actions runner to automatically update llms.txt and llms-full.txt files. + # Run cursor-agent and capture output + AGENT_OUTPUT=$(cursor-agent -p "You are operating in a GitHub Actions runner to automatically update llms.txt and llms-full.txt files. The GitHub CLI is available as \`gh\` and authenticated via \`GH_TOKEN\`. Git is available. You have write access to repository contents and can comment on pull requests, but you must not create or edit PRs directly. @@ -130,4 +131,24 @@ jobs: - Keep all changes minimal and consistent with existing documentation style CRITICAL: After completing ANY of the above actions (stop command, updates completed, or no updates needed), you MUST immediately exit by running 'exit 0'. Do not continue running or wait for additional input. - " --force --model "$MODEL" --output-format=json + " --force --model "$MODEL" --output-format=json) + + # Parse the JSON response + echo "Agent output: $AGENT_OUTPUT" + + # Check if the agent completed successfully + if echo "$AGENT_OUTPUT" | jq -e '.type == "result" and .subtype == "success"' > /dev/null; then + echo "✅ Agent completed successfully" + + # Extract the result message + RESULT_MESSAGE=$(echo "$AGENT_OUTPUT" | jq -r '.result') + echo "Result: $RESULT_MESSAGE" + + # Force exit the action + echo "🏁 Forcing action to exit" + exit 0 + else + echo "❌ Agent did not complete successfully" + echo "Raw output: $AGENT_OUTPUT" + exit 1 + fi From 301cd7e3b67c4ac6aa8fb77341d622f536480a18 Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 19:19:37 +0100 Subject: [PATCH 09/21] add line --- .github/workflows/auto-llms-txt.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index b5ea5404..21915788 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -129,6 +129,7 @@ jobs: - If updates needed: Pushed commits to the persistent branch and a PR comment with compare link - If no updates needed: A brief comment explaining why no updates are required - Keep all changes minimal and consistent with existing documentation style + - Keep the changes to the minimum necessary to update the llms.txt and llms-full.txt files CRITICAL: After completing ANY of the above actions (stop command, updates completed, or no updates needed), you MUST immediately exit by running 'exit 0'. Do not continue running or wait for additional input. " --force --model "$MODEL" --output-format=json) From f36485b7f24801d407a0c32148ba0ee20079069f Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 19:26:49 +0100 Subject: [PATCH 10/21] update --- .github/workflows/auto-llms-txt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index 21915788..c80fd393 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -131,7 +131,7 @@ jobs: - Keep all changes minimal and consistent with existing documentation style - Keep the changes to the minimum necessary to update the llms.txt and llms-full.txt files - CRITICAL: After completing ANY of the above actions (stop command, updates completed, or no updates needed), you MUST immediately exit by running 'exit 0'. Do not continue running or wait for additional input. + CRITICAL: After completing ANY of the above actions (stop command, updates completed, or no updates needed), you MUST immediately use the run_terminal_cmd tool to execute 'exit 0'. This will terminate the process. Do not continue running or wait for additional input. " --force --model "$MODEL" --output-format=json) # Parse the JSON response From 1dfb5cb915d964fe76c19cb78eafff148939d3d3 Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 19:27:42 +0100 Subject: [PATCH 11/21] update --- .github/workflows/auto-llms-txt.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index c80fd393..aa1b4dde 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -66,8 +66,7 @@ jobs: HEAD_REF="${{ github.head_ref }}" BRANCH_PREFIX="${{ env.BRANCH_PREFIX }}" - # Run cursor-agent and capture output - AGENT_OUTPUT=$(cursor-agent -p "You are operating in a GitHub Actions runner to automatically update llms.txt and llms-full.txt files. + cursor-agent -p "You are operating in a GitHub Actions runner to automatically update llms.txt and llms-full.txt files. The GitHub CLI is available as \`gh\` and authenticated via \`GH_TOKEN\`. Git is available. You have write access to repository contents and can comment on pull requests, but you must not create or edit PRs directly. From c3c4f01e559d2dace32c74c1f05c2e1684e5eff8 Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 19:27:53 +0100 Subject: [PATCH 12/21] remove --- .github/workflows/auto-llms-txt.yml | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index aa1b4dde..579b9d68 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -131,24 +131,4 @@ jobs: - Keep the changes to the minimum necessary to update the llms.txt and llms-full.txt files CRITICAL: After completing ANY of the above actions (stop command, updates completed, or no updates needed), you MUST immediately use the run_terminal_cmd tool to execute 'exit 0'. This will terminate the process. Do not continue running or wait for additional input. - " --force --model "$MODEL" --output-format=json) - - # Parse the JSON response - echo "Agent output: $AGENT_OUTPUT" - - # Check if the agent completed successfully - if echo "$AGENT_OUTPUT" | jq -e '.type == "result" and .subtype == "success"' > /dev/null; then - echo "✅ Agent completed successfully" - - # Extract the result message - RESULT_MESSAGE=$(echo "$AGENT_OUTPUT" | jq -r '.result') - echo "Result: $RESULT_MESSAGE" - - # Force exit the action - echo "🏁 Forcing action to exit" - exit 0 - else - echo "❌ Agent did not complete successfully" - echo "Raw output: $AGENT_OUTPUT" - exit 1 - fi + " --force --model "$MODEL" --output-format=text From ec573b5d86693434474f09250d88a552051c1990 Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 19:28:02 +0100 Subject: [PATCH 13/21] add tools --- .github/workflows/auto-llms-txt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index 579b9d68..26d8c88f 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -70,10 +70,10 @@ jobs: The GitHub CLI is available as \`gh\` and authenticated via \`GH_TOKEN\`. Git is available. You have write access to repository contents and can comment on pull requests, but you must not create or edit PRs directly. - IMPORTANT: Before starting your analysis, check if the user wants to stop by running: + IMPORTANT: Before starting your analysis, use the run_terminal_cmd tool to execute: gh pr view ${PR_NUMBER} --json comments --jq '.comments[] | select(.body | contains(\"stop\"))' - If this returns any results, immediately post a cancellation comment and exit. Otherwise, proceed with your analysis. + If this command returns any results, use run_terminal_cmd to post a cancellation comment on the PR and then use run_terminal_cmd to execute 'exit 0'. Otherwise, proceed with your analysis. # Context: - Repo: ${REPO} From f9e4f4a03f3d87e82d3c51735f980e413f3a6c67 Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 19:28:20 +0100 Subject: [PATCH 14/21] update language --- .github/workflows/auto-llms-txt.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index 26d8c88f..ecacd280 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -98,16 +98,17 @@ jobs: Analyze changes in the original PR and determine if they are significant enough to warrant updating the llms.txt and llms-full.txt files for the affected directories. If so, create a separate PR with the updates. # Requirements: - 1) Use \`gh pr diff\` to analyze what changed in the original PR + 1) Use run_terminal_cmd to execute \`gh pr diff ${PR_NUMBER}\` to analyze what changed in the original PR 2) Determine which documentation directories are affected by the changes 3) Assess if the changes are significant enough to update the llms.txt files (new content, major restructuring, new features, etc.) 4) If changes are significant: - - Create or update a persistent branch named \`${BRANCH_PREFIX}/pr-${PR_NUMBER}\` - - Update the relevant llms.txt and llms-full.txt files to reflect the new documentation structure and content - - Push the changes to the branch - - Comment on the original PR with a summary and a compare link to create the PR + - Use run_terminal_cmd to create or update a persistent branch named \`${BRANCH_PREFIX}/pr-${PR_NUMBER}\` + - Use read_file to read existing llms.txt and llms-full.txt files + - Use search_replace or write to update the relevant llms.txt and llms-full.txt files + - Use run_terminal_cmd to push the changes to the branch + - Use run_terminal_cmd to comment on the original PR with a summary and a compare link 5) If changes are not significant: - - Comment on the original PR explaining that no llms.txt updates are needed + - Use run_terminal_cmd to comment on the original PR explaining that no llms.txt updates are needed # File Format Guidelines: - llms.txt files should be concise, focused summaries with key links From d1e23f1c1c10557c1924afc843a6f32ae77b7d6f Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 19:33:26 +0100 Subject: [PATCH 15/21] 30seconds --- .github/workflows/auto-llms-txt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index ecacd280..7786a5e3 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -131,5 +131,5 @@ jobs: - Keep all changes minimal and consistent with existing documentation style - Keep the changes to the minimum necessary to update the llms.txt and llms-full.txt files - CRITICAL: After completing ANY of the above actions (stop command, updates completed, or no updates needed), you MUST immediately use the run_terminal_cmd tool to execute 'exit 0'. This will terminate the process. Do not continue running or wait for additional input. + CRITICAL: After completing ANY of the above actions (stop command, updates completed, or no updates needed), wait 30 seconds and then terminate the process. Do not continue running or use any more tools. " --force --model "$MODEL" --output-format=text From 178ecefbdd7a01879ca1a091674e35f23a5ee009 Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 19:46:04 +0100 Subject: [PATCH 16/21] update the docs --- .github/workflows/auto-llms-txt.yml | 63 +++++++++++++++-------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index 7786a5e3..52ebb01f 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -38,50 +38,55 @@ jobs: git config user.name "Cursor Agent" git config user.email "cursoragent@cursor.com" + - name: Check if already commented + id: check_comment + run: | + EXISTING_COMMENT=$(gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.author.login == "github-actions[bot]" and (.body | contains("🤖 **LLMs.txt Auto-Update**")))') + if [ -n "$EXISTING_COMMENT" ]; then + echo "already_commented=true" >> $GITHUB_OUTPUT + else + echo "already_commented=false" >> $GITHUB_OUTPUT + fi + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Post initial comment + if: steps.check_comment.outputs.already_commented == 'false' run: | gh pr comment ${{ github.event.pull_request.number }} --body "🤖 **LLMs.txt Auto-Update** Analyzing documentation changes to update llms.txt files... - 💡 **Want to stop this process?** Comment \`stop\` below and I'll cancel the analysis. + 💡 **Want to stop this process?** Comment \`STOP CURSOR\` below and I'll cancel the analysis. - âąī¸ This will timeout after 30 minutes." + âąī¸ This will timeout after 20 minutes." env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Update LLMs.txt files - timeout-minutes: 30 + timeout-minutes: 20 env: MODEL: gpt-5 CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} BRANCH_PREFIX: auto-llms run: | - # Expand variables for the agent - REPO="${{ github.repository }}" - OWNER="${{ github.repository_owner }}" - PR_NUMBER="${{ github.event.pull_request.number }}" - BASE_REF="${{ github.base_ref }}" - HEAD_REF="${{ github.head_ref }}" - BRANCH_PREFIX="${{ env.BRANCH_PREFIX }}" - cursor-agent -p "You are operating in a GitHub Actions runner to automatically update llms.txt and llms-full.txt files. The GitHub CLI is available as \`gh\` and authenticated via \`GH_TOKEN\`. Git is available. You have write access to repository contents and can comment on pull requests, but you must not create or edit PRs directly. - IMPORTANT: Before starting your analysis, use the run_terminal_cmd tool to execute: - gh pr view ${PR_NUMBER} --json comments --jq '.comments[] | select(.body | contains(\"stop\"))' + IMPORTANT: Before starting your analysis, check if the user wants to stop by running: + gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.body | contains(\"STOP CURSOR\"))' - If this command returns any results, use run_terminal_cmd to post a cancellation comment on the PR and then use run_terminal_cmd to execute 'exit 0'. Otherwise, proceed with your analysis. + If this returns any results, immediately post a cancellation comment and exit. Otherwise, proceed with your analysis. # Context: - - Repo: ${REPO} - - Owner: ${OWNER} - - PR Number: ${PR_NUMBER} - - Base Ref: ${BASE_REF} - - Head Ref: ${HEAD_REF} - - Branch Prefix: ${BRANCH_PREFIX} + - Repo: ${{ github.repository }} + - Owner: ${{ github.repository_owner }} + - PR Number: ${{ github.event.pull_request.number }} + - Base Ref: ${{ github.base_ref }} + - Head Ref: ${{ github.head_ref }} + - Branch Prefix: ${{ env.BRANCH_PREFIX }} # Documentation Structure: This is a docs repository with the following main directories that each contain llms.txt and llms-full.txt files: @@ -98,17 +103,16 @@ jobs: Analyze changes in the original PR and determine if they are significant enough to warrant updating the llms.txt and llms-full.txt files for the affected directories. If so, create a separate PR with the updates. # Requirements: - 1) Use run_terminal_cmd to execute \`gh pr diff ${PR_NUMBER}\` to analyze what changed in the original PR + 1) Use \`gh pr diff\` to analyze what changed in the original PR 2) Determine which documentation directories are affected by the changes 3) Assess if the changes are significant enough to update the llms.txt files (new content, major restructuring, new features, etc.) 4) If changes are significant: - - Use run_terminal_cmd to create or update a persistent branch named \`${BRANCH_PREFIX}/pr-${PR_NUMBER}\` - - Use read_file to read existing llms.txt and llms-full.txt files - - Use search_replace or write to update the relevant llms.txt and llms-full.txt files - - Use run_terminal_cmd to push the changes to the branch - - Use run_terminal_cmd to comment on the original PR with a summary and a compare link + - Create or update a persistent branch named \`${{ env.BRANCH_PREFIX }}/pr-${{ github.event.pull_request.number }}\` + - Update the relevant llms.txt and llms-full.txt files to reflect the new documentation structure and content + - Push the changes to the branch + - Comment on the original PR with a summary and a compare link to create the PR 5) If changes are not significant: - - Use run_terminal_cmd to comment on the original PR explaining that no llms.txt updates are needed + - Comment on the original PR explaining that no llms.txt updates are needed # File Format Guidelines: - llms.txt files should be concise, focused summaries with key links @@ -129,7 +133,4 @@ jobs: - If updates needed: Pushed commits to the persistent branch and a PR comment with compare link - If no updates needed: A brief comment explaining why no updates are required - Keep all changes minimal and consistent with existing documentation style - - Keep the changes to the minimum necessary to update the llms.txt and llms-full.txt files - - CRITICAL: After completing ANY of the above actions (stop command, updates completed, or no updates needed), wait 30 seconds and then terminate the process. Do not continue running or use any more tools. - " --force --model "$MODEL" --output-format=text + " --force --model "$MODEL" --output-format=text \ No newline at end of file From cff917020f8c16b7dfe06356a1ffed2c1a1deab3 Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 19:56:30 +0100 Subject: [PATCH 17/21] go back to initial --- .github/workflows/auto-llms-txt.yml | 30 ----------------------------- 1 file changed, 30 deletions(-) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index 52ebb01f..7a1ed487 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -38,31 +38,6 @@ jobs: git config user.name "Cursor Agent" git config user.email "cursoragent@cursor.com" - - name: Check if already commented - id: check_comment - run: | - EXISTING_COMMENT=$(gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.author.login == "github-actions[bot]" and (.body | contains("🤖 **LLMs.txt Auto-Update**")))') - if [ -n "$EXISTING_COMMENT" ]; then - echo "already_commented=true" >> $GITHUB_OUTPUT - else - echo "already_commented=false" >> $GITHUB_OUTPUT - fi - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Post initial comment - if: steps.check_comment.outputs.already_commented == 'false' - run: | - gh pr comment ${{ github.event.pull_request.number }} --body "🤖 **LLMs.txt Auto-Update** - - Analyzing documentation changes to update llms.txt files... - - 💡 **Want to stop this process?** Comment \`STOP CURSOR\` below and I'll cancel the analysis. - - âąī¸ This will timeout after 20 minutes." - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Update LLMs.txt files timeout-minutes: 20 env: @@ -75,11 +50,6 @@ jobs: The GitHub CLI is available as \`gh\` and authenticated via \`GH_TOKEN\`. Git is available. You have write access to repository contents and can comment on pull requests, but you must not create or edit PRs directly. - IMPORTANT: Before starting your analysis, check if the user wants to stop by running: - gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.body | contains(\"STOP CURSOR\"))' - - If this returns any results, immediately post a cancellation comment and exit. Otherwise, proceed with your analysis. - # Context: - Repo: ${{ github.repository }} - Owner: ${{ github.repository_owner }} From 56d5edb752743402c0702c7c319e68969db3ac32 Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 21:47:50 +0100 Subject: [PATCH 18/21] add timeout update --- .github/workflows/auto-llms-txt.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index 7a1ed487..6642076e 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -48,6 +48,8 @@ jobs: run: | cursor-agent -p "You are operating in a GitHub Actions runner to automatically update llms.txt and llms-full.txt files. + YOU SHOULD TIMEOUT AFTER 2 MINUTES AND THEN EXIT. + The GitHub CLI is available as \`gh\` and authenticated via \`GH_TOKEN\`. Git is available. You have write access to repository contents and can comment on pull requests, but you must not create or edit PRs directly. # Context: From abc8a7c685f21eacc6b6d5ce1a39d626aea8b42e Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 21:51:57 +0100 Subject: [PATCH 19/21] try timeout success --- .github/workflows/auto-llms-txt.yml | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index 6642076e..7277a851 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -39,7 +39,9 @@ jobs: git config user.email "cursoragent@cursor.com" - name: Update LLMs.txt files - timeout-minutes: 20 + timeout-minutes: 1 + continue-on-error: true + id: agent_run env: MODEL: gpt-5 CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }} @@ -48,8 +50,6 @@ jobs: run: | cursor-agent -p "You are operating in a GitHub Actions runner to automatically update llms.txt and llms-full.txt files. - YOU SHOULD TIMEOUT AFTER 2 MINUTES AND THEN EXIT. - The GitHub CLI is available as \`gh\` and authenticated via \`GH_TOKEN\`. Git is available. You have write access to repository contents and can comment on pull requests, but you must not create or edit PRs directly. # Context: @@ -105,4 +105,18 @@ jobs: - If updates needed: Pushed commits to the persistent branch and a PR comment with compare link - If no updates needed: A brief comment explaining why no updates are required - Keep all changes minimal and consistent with existing documentation style - " --force --model "$MODEL" --output-format=text \ No newline at end of file + " --force --model "$MODEL" --output-format=text + + - name: Handle timeout or completion + if: always() + run: | + if [ "${{ steps.agent_run.outcome }}" == "failure" ]; then + echo "⏰ Agent timed out after 20 minutes - this is expected for long-running analysis" + gh pr comment ${{ github.event.pull_request.number }} --body "⏰ **LLMs.txt Auto-Update Timeout** + + The automated analysis timed out after 20 minutes. This can happen with large documentation changes. The process has been stopped safely." || true + else + echo "✅ Agent completed successfully" + fi + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 5d1def521c954c19df3b0fc271874248c9fae027 Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 21:54:01 +0100 Subject: [PATCH 20/21] add update to timeout --- .github/workflows/auto-llms-txt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index 7277a851..46abe88c 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -39,7 +39,7 @@ jobs: git config user.email "cursoragent@cursor.com" - name: Update LLMs.txt files - timeout-minutes: 1 + timeout-minutes: 20 continue-on-error: true id: agent_run env: From f8aac1688cf4e5d950048f67bc6466121c9b9fb9 Mon Sep 17 00:00:00 2001 From: youssefea Date: Sun, 28 Sep 2025 21:55:10 +0100 Subject: [PATCH 21/21] update --- .github/workflows/auto-llms-txt.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/auto-llms-txt.yml b/.github/workflows/auto-llms-txt.yml index 46abe88c..6073cdf0 100644 --- a/.github/workflows/auto-llms-txt.yml +++ b/.github/workflows/auto-llms-txt.yml @@ -112,11 +112,6 @@ jobs: run: | if [ "${{ steps.agent_run.outcome }}" == "failure" ]; then echo "⏰ Agent timed out after 20 minutes - this is expected for long-running analysis" - gh pr comment ${{ github.event.pull_request.number }} --body "⏰ **LLMs.txt Auto-Update Timeout** - - The automated analysis timed out after 20 minutes. This can happen with large documentation changes. The process has been stopped safely." || true else echo "✅ Agent completed successfully" - fi - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + fi \ No newline at end of file