Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
168ab32
wip: docs generation action
maxnorm Dec 6, 2025
ceab589
Merge branch 'Perfect-Abstractions:main' into main
maxnorm Dec 7, 2025
12871fa
rename old ref
maxnorm Dec 7, 2025
7ae5ad6
Merge branch 'main' of https://github.com/maxnorm/Compose
maxnorm Dec 7, 2025
7050baa
readd pages folder
maxnorm Dec 7, 2025
eabc77b
add mod to contract type detection
maxnorm Dec 7, 2025
53f6ebd
update PR content
maxnorm Dec 7, 2025
120348a
fix modules var def
maxnorm Dec 7, 2025
420273f
chnage template engine toe handlebars engine
maxnorm Dec 8, 2025
e7d449f
update template
maxnorm Dec 8, 2025
bd92d89
update git ignore
maxnorm Dec 8, 2025
0d2a3c5
fix formatting
maxnorm Dec 8, 2025
71d9f8e
improve page template
maxnorm Dec 8, 2025
91e3fa5
improve prompt
maxnorm Dec 9, 2025
47f1e42
Merge branch 'Perfect-Abstractions:main' into main
maxnorm Dec 12, 2025
dc1eea8
fix edit links rendering
maxnorm Dec 15, 2025
c96b0cf
add new trigger input to specified files
maxnorm Dec 15, 2025
117a9e5
improve rate limiting
maxnorm Dec 15, 2025
326d9e4
add better log for debug
maxnorm Dec 15, 2025
c7bcb22
add token rate limiter
maxnorm Dec 16, 2025
56196d9
improve rate limiter
maxnorm Dec 16, 2025
215af44
try fix ai output
maxnorm Dec 16, 2025
bbed36d
add modular ai providers
maxnorm Dec 17, 2025
35c4fb1
add debug logs
maxnorm Dec 17, 2025
272e731
update names
maxnorm Dec 19, 2025
d060588
remove condition to debug
maxnorm Dec 19, 2025
6981272
remove secret debug step
maxnorm Dec 19, 2025
d090880
change default gemini model
maxnorm Dec 19, 2025
7cec432
remove redundant check and default models setting
maxnorm Dec 19, 2025
a9f2657
docs: auto-generate contracts docs from NatSpec
maxnorm Dec 19, 2025
5477ea0
improve PR content
maxnorm Dec 19, 2025
49e8bc1
Merge pull request #14 from maxnorm/docs/auto-generated-8
maxnorm Dec 19, 2025
35e7cf1
improve forge doc extraction
maxnorm Dec 19, 2025
8fd3d0c
remove old page for regen
maxnorm Dec 19, 2025
93dd936
docs: auto-generate docs pages from NatSpec
maxnorm Dec 19, 2025
80ed875
Merge pull request #15 from maxnorm/docs/auto-generated-9
maxnorm Dec 19, 2025
2cd017b
improve parsing again
maxnorm Dec 19, 2025
4f58223
remove old generated pages
maxnorm Dec 19, 2025
1de8582
docs: auto-generate docs pages from NatSpec
maxnorm Dec 19, 2025
4225e70
Merge pull request #16 from maxnorm/docs/auto-generated-10
maxnorm Dec 19, 2025
dd42995
fix storage location rendering
maxnorm Dec 20, 2025
fa8f8e1
remove storage info
maxnorm Dec 20, 2025
8fcbb81
remove old pages
maxnorm Dec 20, 2025
990e38d
docs: auto-generate docs pages from NatSpec
maxnorm Dec 20, 2025
0d57b62
Merge pull request #17 from maxnorm/docs/auto-generated-11
maxnorm Dec 20, 2025
00106e3
try mirroring /src to docs
maxnorm Dec 20, 2025
79890ba
docs: auto-generate docs pages from NatSpec
maxnorm Dec 20, 2025
6b4bc88
Merge pull request #18 from maxnorm/docs/auto-generated-12
maxnorm Dec 20, 2025
ff6fa83
chnage generation to library dir
maxnorm Dec 21, 2025
c291a2b
docs: auto-generate docs pages from NatSpec
maxnorm Dec 21, 2025
57eab20
Merge pull request #19 from maxnorm/docs/auto-generated-13
maxnorm Dec 21, 2025
32bcbbc
imoprove category-generator
maxnorm Dec 21, 2025
859edf4
remove lib pages
maxnorm Dec 21, 2025
75e2e68
fix sync generator
maxnorm Dec 21, 2025
e6108ae
docs: auto-generate docs pages from NatSpec
maxnorm Dec 21, 2025
f1680ed
Merge pull request #20 from maxnorm/docs/auto-generated-15
maxnorm Dec 21, 2025
106f91d
improve category idx pages
maxnorm Dec 21, 2025
fc8e867
remove lib pages
maxnorm Dec 21, 2025
2ca753d
docs: auto-generate docs pages from NatSpec
maxnorm Dec 21, 2025
af2d93d
Merge pull request #21 from maxnorm/docs/auto-generated-16
maxnorm Dec 21, 2025
2dfa9eb
generate index after pages
maxnorm Dec 21, 2025
fb2d50b
docs: auto-generate docs pages from NatSpec
maxnorm Dec 21, 2025
f39f8e6
Merge pull request #22 from maxnorm/docs/auto-generated-17
maxnorm Dec 21, 2025
7e2dd82
Merge branch 'Perfect-Abstractions:main' into main
maxnorm Dec 21, 2025
c62e8e2
docs: auto-generate docs pages from NatSpec
maxnorm Dec 21, 2025
c0c3f4f
Merge pull request #23 from maxnorm/docs/auto-generated-18
maxnorm Dec 21, 2025
5736454
improve struct parsing
maxnorm Dec 21, 2025
4cc421d
docs: auto-generate docs pages from NatSpec
maxnorm Dec 21, 2025
8a1e52e
Merge pull request #25 from maxnorm/docs/auto-generated-20
maxnorm Dec 21, 2025
9657916
remove library page into library cat
maxnorm Dec 21, 2025
48e00c6
change API to contract
maxnorm Dec 21, 2025
cf7b95f
adjust sidebar redirect for lib
maxnorm Dec 21, 2025
c85b8ef
remove table columns gap
maxnorm Dec 21, 2025
5e06458
add state var value, fix code highligh in table
maxnorm Dec 22, 2025
2d9c1bb
update contract template
maxnorm Dec 22, 2025
eb64451
improve table style
maxnorm Dec 22, 2025
a26a353
remove internal function in facet doc
maxnorm Dec 22, 2025
5a95f56
normalize source path to always refer to Perfect-Abstractions/Compose…
maxnorm Dec 22, 2025
a365d4e
docs: auto-generate docs pages from NatSpec
maxnorm Dec 23, 2025
8f096bd
Merge pull request #26 from maxnorm/docs/auto-generated-22
maxnorm Dec 23, 2025
b36fdb4
update parse to extract storage location value
maxnorm Dec 23, 2025
dac1d44
remove library section
maxnorm Dec 23, 2025
e3c2c76
add check
maxnorm Dec 23, 2025
de03fd0
docs: auto-generate docs pages from NatSpec
maxnorm Dec 23, 2025
35f096e
Merge pull request #27 from maxnorm/docs/auto-generated-24
maxnorm Dec 23, 2025
637b026
clean up
maxnorm Dec 28, 2025
7431ad6
docs: auto-generate docs pages from NatSpec
maxnorm Dec 28, 2025
cf0a31e
Merge pull request #28 from maxnorm/docs/auto-generated-25
maxnorm Dec 28, 2025
732d26d
add relationship and improve navigation
maxnorm Dec 28, 2025
ae9fdc8
docs: auto-generate docs pages from NatSpec
maxnorm Dec 28, 2025
3533708
Merge pull request #29 from maxnorm/docs/auto-generated-26
maxnorm Dec 28, 2025
5dfdcff
improve related docs, separate contractRegistry
maxnorm Dec 30, 2025
d6012a5
docs: auto-generate docs pages from NatSpec
maxnorm Dec 30, 2025
406bc43
Merge pull request #31 from maxnorm/docs/auto-generated-28
maxnorm Dec 30, 2025
8571a30
hide library index in sidebar
maxnorm Dec 30, 2025
043f28b
docs: auto-generate docs pages from NatSpec
maxnorm Dec 30, 2025
607d51f
Merge pull request #32 from maxnorm/docs/auto-generated-29
maxnorm Dec 30, 2025
e6e8d4a
hide library index in sidebar
maxnorm Dec 30, 2025
8d7d20d
improve AI context
maxnorm Dec 30, 2025
2abc434
docs: auto-generate docs pages from NatSpec
maxnorm Dec 30, 2025
360728e
Merge pull request #33 from maxnorm/docs/auto-generated-30
maxnorm Dec 30, 2025
20918ed
make sure library index is hidden in sidebar
maxnorm Dec 30, 2025
7e106b7
docs: auto-generate docs pages from NatSpec
maxnorm Dec 30, 2025
c053dd4
Merge pull request #34 from maxnorm/docs/auto-generated-31
maxnorm Dec 30, 2025
c7a7d70
comment out code example, improve prompt
maxnorm Dec 30, 2025
dc61776
comment usage example
maxnorm Dec 30, 2025
02f755a
docs: auto-generate docs pages from NatSpec
maxnorm Dec 30, 2025
cd8dfae
Merge pull request #37 from maxnorm/docs/auto-generated-34
maxnorm Dec 30, 2025
83c1876
remove logs
maxnorm Dec 30, 2025
b2147a0
add wasHelpful feedback hook, improve component design
maxnorm Dec 30, 2025
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
404 changes: 404 additions & 0 deletions .github/docs-gen-prompts.md

Large diffs are not rendered by default.

179 changes: 179 additions & 0 deletions .github/scripts/ai-provider/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
# AI Provider Service

Simple, configurable AI service for CI workflows supporting multiple providers.

## Features

- **Simple API**: One function to call any AI model
- **Multiple Providers**: GitHub Models (GPT-4o) and Google Gemini
- **Auto-detection**: Automatically uses available provider
- **Rate Limiting**: Built-in request and token-based rate limiting
- **Configurable**: Override provider and model via environment variables

## Supported Providers

| Provider | Models | Rate Limits | API Key |
|----------|--------|-------------|---------|
| **GitHub Models** | gpt-4o, gpt-4o-mini | 10 req/min, 40k tokens/min | `GITHUB_TOKEN` |
| **Google Gemini** | gemini-1.5-flash, gemini-1.5-pro | 15 req/min, 1M tokens/min | `GOOGLE_AI_API_KEY` |

## Usage

### Basic Usage

```javascript
const ai = require('./ai-provider');

const response = await ai.call(
'You are a helpful assistant', // system prompt
'Explain quantum computing' // user prompt
);

console.log(response);
```

### With Options

```javascript
const response = await ai.call(
systemPrompt,
userPrompt,
{
maxTokens: 1000,
onSuccess: (text, tokens) => {
console.log(`Success! Used ${tokens} tokens`);
},
onError: (error) => {
console.error('Failed:', error);
}
}
);
```

## Environment Variables

### Provider Selection

```bash
# Auto-detect (default) - Try other provider with fallback to Github
AI_PROVIDER=auto

# Use specific provider
AI_PROVIDER=github # Use GitHub Models
AI_PROVIDER=gemini # Use Google Gemini
```

### Model Override

```bash
# Override default model for the provider
AI_MODEL=gpt-4o # For GitHub Models
AI_MODEL=gemini-1.5-pro # For Gemini
```

### API Keys

```bash
# Google Gemini
GOOGLE_AI_API_KEY=
```

## Examples

## GitHub Actions Integration

```yaml
- name: Run AI-powered task
env:
# Option 1: Auto-detect (recommended)
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GOOGLE_AI_API_KEY: ${{ secrets.GOOGLE_AI_API_KEY }}

# Option 2: Force specific provider
# AI_PROVIDER: 'gemini'
# AI_MODEL: 'gemini-1.5-pro'
run: node .github/scripts/your-script.js
```

## Architecture

```
ai-provider/
├── index.js # Main service (singleton)
├── base-provider.js # Base provider class
├── provider-factory.js # Provider creation logic
├── rate-limiter.js # Rate limiting logic
└── providers/
├── github-models.js # GitHub Models implementation
└── gemini.js # Gemini implementation
```

## Adding a New Provider

1. Create a new provider class in `providers/`:

```javascript
const BaseAIProvider = require('../base-provider');

class MyProvider extends BaseAIProvider {
constructor(config, apiKey) {
super('My Provider', config, apiKey);
}

buildRequestOptions() {
// Return HTTP request options
}

buildRequestBody(systemPrompt, userPrompt, maxTokens) {
// Return JSON.stringify(...) of request body
}

extractContent(response) {
// Return { content: string, tokens: number|null }
}
}

module.exports = MyProvider;
```

2. Register in `provider-factory.js`:

```javascript
const MyProvider = require('./providers/my-provider');

function createMyProvider(customModel) {
const apiKey = process.env.MY_PROVIDER_API_KEY;
if (!apiKey) return null;

return new MyProvider({ model: customModel || 'default-model' }, apiKey);
}
```

3. Add to auto-detection or switch statement.

## Rate Limiting

The service automatically handles rate limiting:

- **Request-based**: Ensures minimum delay between requests
- **Token-based**: Tracks token consumption in a 60-second rolling window
- **Smart waiting**: Calculates exact wait time needed

Rate limits are provider-specific and configured automatically.

## Error Handling

```javascript
try {
const response = await ai.call(systemPrompt, userPrompt);
// Use response
} catch (error) {
if (error.message.includes('429')) {
console.log('Rate limited - try again later');
} else if (error.message.includes('401')) {
console.log('Invalid API key');
} else {
console.log('Other error:', error.message);
}
}
```
132 changes: 132 additions & 0 deletions .github/scripts/ai-provider/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/**
* AI Provider Service
* Simple, configurable AI service supporting multiple providers
*
* Usage:
* const ai = require('./ai-provider');
* const response = await ai.call(systemPrompt, userPrompt);
*
* Environment Variables:
* AI_PROVIDER - 'github' | 'gemini' | 'auto' (default: auto)
* AI_MODEL - Override default model
* GITHUB_TOKEN - For GitHub Models
* GOOGLE_AI_API_KEY - For Gemini
*/

const { getProvider } = require('./provider-factory');
const RateLimiter = require('./rate-limiter');

class AIProvider {
constructor() {
this.provider = null;
this.rateLimiter = new RateLimiter();
this.initialized = false;
}

/**
* Initialize the provider (lazy loading)
*/
_init() {
if (this.initialized) {
return;
}

this.provider = getProvider();
if (!this.provider) {
throw new Error(
'No AI provider available. Set AI_PROVIDER or corresponding API key.'
);
}

this.rateLimiter.setProvider(this.provider);
this.initialized = true;
}

/**
* Make an AI call
*
* @param {string} systemPrompt - System prompt
* @param {string} userPrompt - User prompt
* @param {object} options - Optional settings
* @param {number} options.maxTokens - Override max tokens
* @param {function} options.onSuccess - Success callback
* @param {function} options.onError - Error callback
* @returns {Promise<string>} Response text
*/
async call(systemPrompt, userPrompt, options = {}) {
this._init();

const {
maxTokens = null,
onSuccess = null,
onError = null,
} = options;

if (!systemPrompt || !userPrompt) {
throw new Error('systemPrompt and userPrompt are required');
}

try {
// Estimate tokens and wait for rate limits
const tokensToUse = maxTokens || this.provider.getMaxTokens();
const estimatedTokens = this.rateLimiter.estimateTokenUsage(
systemPrompt,
userPrompt,
tokensToUse
);

await this.rateLimiter.waitForRateLimit(estimatedTokens);

// Build and send request
const requestBody = this.provider.buildRequestBody(systemPrompt, userPrompt, tokensToUse);
const requestOptions = this.provider.buildRequestOptions();

const response = await this._makeRequest(requestOptions, requestBody);

// Extract content
const extracted = this.provider.extractContent(response);
if (!extracted) {
throw new Error('Invalid response format from API');
}

// Record actual token usage
const actualTokens = extracted.tokens || estimatedTokens;
this.rateLimiter.recordTokenConsumption(actualTokens);

if (onSuccess) {
onSuccess(extracted.content, actualTokens);
}

return extracted.content;

} catch (error) {
if (onError) {
onError(error);
}

throw error;
}
}

/**
* Make HTTPS request
*/
async _makeRequest(options, body) {
const { makeHttpsRequest } = require('../workflow-utils');
return await makeHttpsRequest(options, body);
}

/**
* Get provider info
*/
getProviderInfo() {
this._init();
return {
name: this.provider.name,
limits: this.provider.getRateLimits(),
maxTokens: this.provider.getMaxTokens(),
};
}
}

module.exports = new AIProvider();
65 changes: 65 additions & 0 deletions .github/scripts/ai-provider/provider-factory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* Provider Factory
* Creates the appropriate AI provider based on environment variables
*/

const { createGitHubProvider } = require('./providers/github-models');
const { createGeminiProvider } = require('./providers/gemini');

/**
* Get the active AI provider based on environment configuration
*
* Environment variables:
* - AI_PROVIDER: 'github' | 'gemini' | 'auto' (default: 'auto')
* - AI_MODEL: Override default model for the provider
* - GITHUB_TOKEN: API key for GitHub Models
* - GOOGLE_AI_API_KEY: API key for Gemini
*
* @returns {BaseAIProvider|null} Provider instance or null if none available
*/
function getProvider() {
const providerName = (process.env.AI_PROVIDER || 'auto').toLowerCase();
const customModel = process.env.AI_MODEL;

if (providerName === 'auto') {
return autoDetectProvider(customModel);
}

switch (providerName) {
case 'github':
case 'github-models':
return createGitHubProvider(customModel);

case 'gemini':
case 'google':
return createGeminiProvider(customModel);

default:
console.warn(`⚠️ Unknown provider: ${providerName}. Falling back to auto-detect.`);
return autoDetectProvider(customModel);
}
}

/**
* Auto-detect provider based on available API keys
*/
function autoDetectProvider(customModel) {
// Try Gemini
const geminiProvider = createGeminiProvider(customModel);
if (geminiProvider) {
return geminiProvider;
}

// Fallback to GitHub Models (free in GitHub Actions)
const githubProvider = createGitHubProvider(customModel);
if (githubProvider) {
return githubProvider;
}

return null;
}

module.exports = {
getProvider,
};

Loading
Loading