Compare commits

...

12 Commits

Author SHA1 Message Date
4e2f938d71 v2.0.2
Some checks failed
Default (tags) / security (push) Failing after 0s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-03-24 18:56:18 +00:00
abdc2f2534 fix(smartconfig): migrate project metadata and config handling to .smartconfig.json 2026-03-24 18:56:18 +00:00
a2b596e5db v2.0.1
Some checks failed
Default (tags) / security (push) Failing after 0s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-03-24 15:07:49 +00:00
a3a0537ddc fix(aidocs, config): migrate aidocs configuration handling from npmextra to smartconfig 2026-03-24 15:07:49 +00:00
fc85f28f69 v2.0.0
Some checks failed
Default (tags) / security (push) Failing after 0s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-03-11 18:58:49 +00:00
6b2957b272 BREAKING CHANGE(aidoc): migrate agent orchestration to new runAgent API and filesystem tools; refactor model handling and update README and tests 2026-03-11 18:58:48 +00:00
883985dbc0 v1.12.0
Some checks failed
Default (tags) / security (push) Failing after 0s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-01-04 15:20:27 +00:00
21006b41d0 feat(commit): add token budgeting and dynamic diff token calculation to avoid OpenAI context limit issues 2026-01-04 15:20:27 +00:00
5d0411a5ba v1.11.4
Some checks failed
Default (tags) / security (push) Failing after 0s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2025-12-16 10:07:47 +00:00
39f5410b76 fix(aidocs_classes): clarify recommendedNextVersionMessage field to require only the description body without the type(scope) prefix 2025-12-16 10:07:47 +00:00
1a517fdd1b 1.11.3
Some checks failed
Default (tags) / security (push) Failing after 0s
Default (tags) / test (push) Failing after 0s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2025-12-15 15:54:45 +00:00
90af6eb1b1 update 2025-12-15 15:54:25 +00:00
17 changed files with 2016 additions and 3958 deletions

44
.smartconfig.json Normal file
View File

@@ -0,0 +1,44 @@
{
"gitzone": {
"projectType": "npm",
"module": {
"githost": "gitlab.com",
"gitscope": "gitzone",
"gitrepo": "tsdoc",
"shortDescription": "a tool for better documentation",
"npmPackagename": "@git.zone/tsdoc",
"license": "MIT",
"projectDomain": "git.zone",
"description": "A comprehensive TypeScript documentation tool that leverages AI to generate and enhance project documentation, including dynamic README creation, API docs via TypeDoc, and smart commit message generation.",
"keywords": [
"TypeScript",
"documentation",
"AI",
"CLI",
"README",
"TypeDoc",
"commit messages",
"automation",
"code analysis",
"context trimming",
"developer tools"
]
}
},
"npmci": {
"npmGlobalTools": [],
"npmAccessLevel": "public"
},
"tsdoc": {
"legal": "\n## License and Legal Information\n\nThis repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./license) file.\n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.\n\nUse of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District Court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
},
"@git.zone/cli": {
"release": {
"registries": [
"https://verdaccio.lossless.digital",
"https://registry.npmjs.org"
],
"accessLevel": "public"
}
}
}

View File

@@ -1,7 +1,7 @@
{
"json.schemas": [
{
"fileMatch": ["/npmextra.json"],
"fileMatch": ["/.smartconfig.json"],
"schema": {
"type": "object",
"properties": {

View File

@@ -1,5 +1,45 @@
# Changelog
## 2026-03-24 - 2.0.2 - fix(smartconfig)
migrate project metadata and config handling to .smartconfig.json
- replace npmextra.json with .smartconfig.json across packaging, project context, README generation, and description prompts
- fix description updates to write metadata under gitzone.module and use smartconfig KeyValueStore for persisted settings
- refresh documentation and dependency versions to reflect the new config location and storage path
## 2026-03-24 - 2.0.1 - fix(aidocs, config)
migrate aidocs configuration handling from npmextra to smartconfig
- replace the @push.rocks/npmextra dependency with @push.rocks/smartconfig
- load project metadata from smartconfig.json instead of npmextra.json in aidocs workflows
- move user key-value store paths from ~/.npmextra to ~/.smartconfig and preserve existing OPENAI_TOKEN data through migration
## 2026-03-11 - 2.0.0 - BREAKING CHANGE(aidoc)
migrate agent orchestration to new runAgent API and filesystem tools; refactor model handling and update README and tests
- Replace DualAgentOrchestrator with plugins.smartagent.runAgent and scoped filesystem tools
- Introduce smartagentTools export and use filesystemTool for agents
- Replace smartAiInstance with model via plugins.smartai.getModel() and remove previous lifecycle methods (breaking API change)
- Normalize agent output property from result to text and standardize log messages (removed emojis)
- Update changelog/README/description generation flows to use new agent interface
- Bump several devDependencies and dependencies (tsbuild, tstest, @types/node, tspublish, push.rocks packages, typedoc, typescript)
- Change test entry to export default tap.start()
- Revise README content and structure
## 2026-01-04 - 1.12.0 - feat(commit)
add token budgeting and dynamic diff token calculation to avoid OpenAI context limit issues
- Introduce TOKEN_BUDGET constants and calculateMaxDiffTokens() in ts/aidocs_classes/commit.ts
- Use dynamic maxDiffTokens for DiffProcessor and validate/log warnings when estimated tokens approach limits
- Add token budgeting notes to readme.hints.md (guidance for splitting large commits and adjusting overhead)
- Bump dependencies/devDependencies: @git.zone/tstest ^3.1.4, @types/node ^25.0.3, @git.zone/tspublish ^1.11.0, @push.rocks/smartfs ^1.3.1
## 2025-12-16 - 1.11.4 - fix(aidocs_classes)
clarify recommendedNextVersionMessage field to require only the description body without the type(scope) prefix
- Updated inline documentation in ts/aidocs_classes/commit.ts to explicitly state that recommendedNextVersionMessage must be only the description body (example: 'bump dependency to ^1.2.6') and not include the type(scope) prefix.
- Removes ambiguity in the example text and improves guidance for commit message generation.
## 2025-12-15 - 1.11.0 - feat(commit)
Integrate DualAgentOrchestrator for commit message generation and improve diff/context handling

View File

@@ -1,4 +1,4 @@
Copyright (c) 2019 Lossless GmbH (hello@lossless.com)
Copyright (c) 2019 Task Venture Capital GmbH (hello@task.vc)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,44 +0,0 @@
{
"gitzone": {
"projectType": "npm",
"module": {
"githost": "gitlab.com",
"gitscope": "gitzone",
"gitrepo": "tsdoc",
"shortDescription": "a tool for better documentation",
"npmPackagename": "@git.zone/tsdoc",
"license": "MIT",
"projectDomain": "git.zone",
"description": "A comprehensive TypeScript documentation tool that leverages AI to generate and enhance project documentation, including dynamic README creation, API docs via TypeDoc, and smart commit message generation.",
"keywords": [
"TypeScript",
"documentation",
"AI",
"CLI",
"README",
"TypeDoc",
"commit messages",
"automation",
"code analysis",
"context trimming",
"developer tools"
]
}
},
"npmci": {
"npmGlobalTools": [],
"npmAccessLevel": "public"
},
"tsdoc": {
"legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
},
"@git.zone/cli": {
"release": {
"registries": [
"https://verdaccio.lossless.digital",
"https://registry.npmjs.org"
],
"accessLevel": "public"
}
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@git.zone/tsdoc",
"version": "1.11.2",
"version": "2.0.2",
"private": false,
"description": "A comprehensive TypeScript documentation tool that leverages AI to generate and enhance project documentation, including dynamic README creation, API docs via TypeDoc, and smart commit message generation.",
"type": "module",
@@ -19,31 +19,31 @@
"buildDocs": "tsdoc"
},
"devDependencies": {
"@git.zone/tsbuild": "^4.0.2",
"@git.zone/tsbuild": "^4.3.0",
"@git.zone/tsrun": "^2.0.1",
"@git.zone/tstest": "^3.1.3",
"@types/node": "^25.0.2"
"@git.zone/tstest": "^3.5.1",
"@types/node": "^25.5.0"
},
"dependencies": {
"@git.zone/tspublish": "^1.10.3",
"@git.zone/tspublish": "^1.11.3",
"@push.rocks/early": "^4.0.4",
"@push.rocks/npmextra": "^5.3.3",
"@push.rocks/smartconfig": "^6.0.1",
"@push.rocks/qenv": "^6.1.3",
"@push.rocks/smartagent": "file:../../push.rocks/smartagent",
"@push.rocks/smartai": "^0.8.0",
"@push.rocks/smartcli": "^4.0.19",
"@push.rocks/smartagent": "^3.0.2",
"@push.rocks/smartai": "^2.0.0",
"@push.rocks/smartcli": "^4.0.20",
"@push.rocks/smartdelay": "^3.0.5",
"@push.rocks/smartfile": "^13.1.2",
"@push.rocks/smartfs": "^1.2.0",
"@push.rocks/smartfs": "^1.5.0",
"@push.rocks/smartgit": "^3.3.1",
"@push.rocks/smartinteract": "^2.0.16",
"@push.rocks/smartlog": "^3.1.10",
"@push.rocks/smartlog": "^3.2.1",
"@push.rocks/smartlog-destination-local": "^9.0.2",
"@push.rocks/smartpath": "^6.0.0",
"@push.rocks/smartshell": "^3.3.0",
"@push.rocks/smarttime": "^4.1.1",
"typedoc": "^0.28.15",
"typescript": "^5.9.3"
"@push.rocks/smartshell": "^3.3.8",
"@push.rocks/smarttime": "^4.2.3",
"typedoc": "^0.28.18",
"typescript": "^6.0.2"
},
"files": [
"ts/**/*",
@@ -54,7 +54,7 @@
"dist_ts_web/**/*",
"assets/**/*",
"cli.js",
"npmextra.json",
".smartconfig.json",
"readme.md"
],
"browserslist": [

4794
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,4 +2,13 @@
* alternatively can be used through npx, if installed locally
* cli parameters are concluded from ./ts/cli.ts
* this module is not intended for API use.
* Read carefully through the TypeScript files. Don't make stuff up.
* Read carefully through the TypeScript files. Don't make stuff up.
## Token Budgeting (commit.ts)
* OpenAI has a 272,000 token context limit
* The smartagent infrastructure adds ~180,000 tokens of overhead (system messages, tool descriptions, conversation history)
* TOKEN_BUDGET constants in commit.ts control the available tokens for diff content
* Dynamic calculation: 272K - 10K (safety) - 180K (overhead) - 2K (prompt) = 80K tokens for diff
* If token limit errors occur, consider:
- Splitting large commits into smaller ones
- Adjusting SMARTAGENT_OVERHEAD if actual overhead is different

517
readme.md
View File

@@ -1,347 +1,193 @@
# @git.zone/tsdoc 🚀
# @git.zone/tsdoc
AI-Powered Documentation for TypeScript Projects
AI-Powered Documentation & Commit Intelligence for TypeScript Projects 🚀
## Issue Reporting and Security
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
## What is tsdoc?
`@git.zone/tsdoc` is a next-generation documentation CLI tool that combines traditional TypeDoc generation with cutting-edge AI to create comprehensive, intelligent documentation for your TypeScript projects. It reads your code, understands it, and writes documentation that actually makes sense.
### ✨ Key Features
- **🤖 AI-Enhanced Documentation** - Leverages AI to generate contextual READMEs
- **🧠 Smart Context Building** - Intelligent file prioritization with dependency analysis and caching
- **📚 TypeDoc Integration** - Classic API documentation generation when you need it
- **💬 Smart Commit Messages** - AI analyzes your changes and suggests meaningful commit messages
- **🎯 Context Optimization** - Advanced token management with 40-60% reduction in usage
- **⚡ Performance Optimized** - 3-5x faster with lazy loading and parallel processing
- **📦 Zero Config** - Works out of the box with sensible defaults
- **🔧 Highly Configurable** - Customize every aspect when needed
## Installation
## Install
```bash
# Global installation (recommended)
# Global installation (recommended for CLI usage)
pnpm add -g @git.zone/tsdoc
# Or use with npx
# Or use with npx (no install needed)
npx @git.zone/tsdoc
# Or install locally as a project dependency
pnpm add @git.zone/tsdoc
```
## Quick Start
## Usage
### Generate AI-Powered Documentation
`@git.zone/tsdoc` is a TypeScript documentation powerhouse that combines traditional [TypeDoc](https://typedoc.org/) API docs with AI-powered documentation workflows. It uses OpenAI models via `@push.rocks/smartai` and autonomous agents via `@push.rocks/smartagent` to generate READMEs, project descriptions, keywords, and semantic commit messages — all by intelligently exploring your project's codebase with scoped filesystem tools.
### CLI Commands
| Command | Description |
|---------|-------------|
| `tsdoc` | 🔍 Auto-detects project type and runs TypeDoc |
| `tsdoc aidoc` | 🤖 Generates AI-powered README + description/keywords |
| `tsdoc readme` | 📝 Generates AI-powered README only |
| `tsdoc description` | 🏷️ Generates AI-powered description and keywords only |
| `tsdoc commit` | 💬 Generates a semantic commit message from uncommitted changes |
| `tsdoc typedoc` | 📚 Generates traditional TypeDoc API documentation |
### 🤖 AI-Powered Documentation (`aidoc`)
The `aidoc` command is the all-in-one workflow that combines README generation and description/keyword generation:
```bash
# In your project root
tsdoc aidoc
```
That's it! tsdoc will analyze your entire codebase and generate:
- A comprehensive README.md
- Updated package.json description and keywords
- Smart documentation based on your actual code structure
This will:
### Generate Traditional TypeDoc
1. Spin up an AI agent with read-only filesystem access scoped to your project
2. The agent autonomously explores your project structure, reads source files, and understands the API
3. Generate a comprehensive `readme.md` with install instructions, usage examples, and architecture overview
4. Update `package.json` and `.smartconfig.json` with an AI-generated description and keywords
You can also run these steps individually:
```bash
tsdoc typedoc --publicSubdir docs
# Generate only the README
tsdoc readme
# Generate only the description and keywords
tsdoc description
```
### Get Smart Commit Messages
### 💬 Smart Commit Messages (`commit`)
The `commit` command analyzes your uncommitted changes and produces a structured commit object following [Conventional Commits](https://www.conventionalcommits.org/):
```bash
tsdoc commit
```
## CLI Commands
Output is a JSON object:
| Command | Description |
|---------|-------------|
| `tsdoc` | Auto-detects and runs appropriate documentation |
| `tsdoc aidoc` | Generate AI-enhanced documentation |
| `tsdoc typedoc` | Generate TypeDoc documentation |
| `tsdoc commit` | Generate smart commit message |
| `tsdoc tokens` | Analyze token usage for AI context |
### Token Analysis
Understanding token usage helps optimize AI costs:
```bash
# Show token count for current project
tsdoc tokens
# Show detailed stats for all task types
tsdoc tokens --all
# Show detailed breakdown with file listing
tsdoc tokens --detailed --listFiles
```json
{
"recommendedNextVersionLevel": "feat",
"recommendedNextVersionScope": "core",
"recommendedNextVersionMessage": "add smart diff processing for large changesets",
"recommendedNextVersionDetails": [
"implemented intelligent diff sampling with head/tail extraction",
"added file prioritization by importance score"
],
"recommendedNextVersion": "1.13.0",
"changelog": "# Changelog\n\n## 2026-03-24 - 1.13.0 - core\n..."
}
```
### Command Options
Under the hood, the commit flow:
#### tsdoc aidoc
- `--tokens` / `--showTokens` - Show token count before generating
- `--tokensOnly` - Only show token count, don't generate
- **Excludes noise**: Lock files, build artifacts (`dist/`, `dist_*/`), IDE directories, caches, and source maps are filtered out before processing
- **Prioritizes what matters**: Source files rank higher than test files, which rank higher than config, docs, and build artifacts
- **Handles large diffs gracefully**: The `DiffProcessor` categorizes files by size — small files (< 300 lines) are included in full, medium files (< 800 lines) get head/tail sampling, and large files are metadata-only
- **Respects token budgets**: Dynamically calculates available tokens based on the model's context limit minus overhead
- **Auto-generates changelogs**: If no `changelog.md` exists, one is created from the full git history
#### tsdoc typedoc
- `--publicSubdir <dir>` - Output subdirectory within public folder
### 📚 TypeDoc Generation (`typedoc`)
#### tsdoc tokens
- `--task <type>` - Specify task type: `readme`, `commit`, or `description`
- `--all` - Show stats for all task types
- `--detailed` - Show detailed token usage and costs
- `--listFiles` - List all files included in context
- `--model <name>` - Show usage for specific model (`gpt4`, `gpt35`)
For traditional API documentation:
```bash
# Generate to default ./public directory
tsdoc typedoc
# Generate to a specific subdirectory
tsdoc typedoc --publicSubdir docs
```
TypeDoc generation auto-detects your source directories (`ts/` and `ts_web/`) and creates a temporary tsconfig for compilation.
### 🏗️ Monorepo Support
When generating READMEs, tsdoc automatically detects monorepo submodules via `@git.zone/tspublish` conventions. Each submodule directory containing a `tspublish.json` gets its own generated README with the legal section appended.
### Programmatic API
You can use tsdoc programmatically in your own tools:
```typescript
import { AiDoc } from '@git.zone/tsdoc';
const aidoc = new AiDoc();
// Initialize — prompts for OpenAI token on first run, then persists it
await aidoc.start();
// Generate a comprehensive README for a project
const readmeContent = await aidoc.buildReadme('/path/to/project');
// Generate description and keywords, updating package.json and .smartconfig.json
await aidoc.buildDescription('/path/to/project');
// Generate a structured commit message object from uncommitted changes
const commitObj = await aidoc.buildNextCommitObject('/path/to/project');
console.log(commitObj.recommendedNextVersionLevel); // 'fix' | 'feat' | 'BREAKING CHANGE'
console.log(commitObj.recommendedNextVersionMessage);
console.log(commitObj.changelog);
// Get gathered project files (package.json, source files, tests, config)
const context = await aidoc.getProjectContext('/path/to/project');
// Get token count for a project's context
const tokenCount = await aidoc.getProjectContextTokenCount('/path/to/project');
// Estimate tokens in arbitrary text
const tokens = aidoc.countTokens('some text here');
await aidoc.stop();
```
You can also pass the OpenAI token directly via the constructor:
```typescript
const aidoc = new AiDoc({ OPENAI_TOKEN: 'sk-...' });
await aidoc.start();
```
## Configuration
Configure tsdoc via `npmextra.json`:
### OpenAI Token
An OpenAI API key is required for all AI features. It can be provided in three ways (checked in order):
1. **Environment variable**: Set `OPENAI_TOKEN` in your environment or `.env` file
2. **Constructor argument**: Pass `{ OPENAI_TOKEN: 'sk-...' }` to `new AiDoc()`
3. **Interactive prompt**: On first run, tsdoc will prompt for the token and persist it
The token is persisted at `~/.smartconfig/kv/@git.zone/tsdoc.json` for subsequent runs.
### .smartconfig.json
tsdoc uses `.smartconfig.json` for project metadata. The `tsdoc` key holds legal information that gets appended to generated READMEs:
```json
{
"@git.zone/tsdoc": {
"legal": "## License and Legal Information\n\n...",
"context": {
"maxTokens": 190000,
"defaultMode": "trimmed",
"cache": {
"enabled": true,
"ttl": 3600,
"maxSize": 100
},
"analyzer": {
"useAIRefinement": false
},
"prioritization": {
"dependencyWeight": 0.3,
"relevanceWeight": 0.4,
"efficiencyWeight": 0.2,
"recencyWeight": 0.1
},
"tiers": {
"essential": { "minScore": 0.8, "trimLevel": "none" },
"important": { "minScore": 0.5, "trimLevel": "light" },
"optional": { "minScore": 0.2, "trimLevel": "aggressive" }
},
"taskSpecificSettings": {
"readme": {
"mode": "trimmed",
"includePaths": ["ts/", "src/"],
"excludePaths": ["test/", "node_modules/"]
},
"commit": {
"mode": "trimmed",
"focusOnChangedFiles": true
}
},
"trimming": {
"removeImplementations": true,
"preserveInterfaces": true,
"preserveJSDoc": true,
"maxFunctionLines": 5,
"removeComments": true
}
"tsdoc": {
"legal": "\n## License and Legal Information\n\n..."
},
"gitzone": {
"module": {
"githost": "gitlab.com",
"gitscope": "gitzone",
"gitrepo": "tsdoc",
"npmPackagename": "@git.zone/tsdoc",
"description": "...",
"keywords": ["..."]
}
}
}
```
### Configuration Options
#### Context Settings
- **maxTokens** - Maximum tokens for AI context (default: 190000)
- **defaultMode** - Default context mode: 'full', 'trimmed', or 'summarized'
- **cache** - Caching configuration for improved performance
- **analyzer** - Smart file analysis and prioritization settings
- **prioritization** - Weights for file importance scoring
- **tiers** - Tier thresholds and trimming levels
#### Cache Configuration
- **enabled** - Enable/disable file caching (default: true)
- **ttl** - Time-to-live in seconds (default: 3600)
- **maxSize** - Maximum cache size in MB (default: 100)
- **directory** - Cache directory path (default: .nogit/context-cache)
## How It Works
### 🚀 Smart Context Building Pipeline
1. **📊 Fast Metadata Scanning** - Lazy loading scans files without reading contents
2. **🧬 Dependency Analysis** - Builds dependency graph from import statements
3. **🎯 Intelligent Scoring** - Multi-factor importance scoring:
- **Relevance**: Task-specific file importance (e.g., index.ts for READMEs)
- **Centrality**: How many files depend on this file
- **Efficiency**: Information density (tokens vs. value)
- **Recency**: Recently changed files (for commits)
4. **🏆 Smart Prioritization** - Files sorted by combined importance score
5. **🎭 Tier-Based Trimming** - Adaptive trimming based on importance:
- **Essential** (score ≥ 0.8): No trimming
- **Important** (score ≥ 0.5): Light trimming
- **Optional** (score ≥ 0.2): Aggressive trimming
6. **💾 Intelligent Caching** - Cache results with file change detection
7. **🧠 AI Processing** - Send optimized context to AI for documentation
### Context Optimization Benefits
The smart context system delivers significant improvements:
| Metric | Before | After | Improvement |
|--------|--------|-------|-------------|
| **Token Usage** | ~190k (limit) | ~110-130k | ⬇️ 40-60% reduction |
| **Build Time** | 4-6 seconds | 1-2 seconds | ⚡ 3-5x faster |
| **Memory Usage** | All files loaded | Metadata + selected | 📉 80%+ reduction |
| **Relevance** | Alphabetical sorting | Smart scoring | 🎯 90%+ relevant |
| **Cache Hits** | None | 70-80% | 🚀 Major speedup |
## Environment Variables
| Variable | Description |
|----------|-------------|
| `OPENAI_TOKEN` | Your OpenAI API key for AI features (required) |
The token can also be provided interactively on first run - it will be persisted in `~/.npmextra/kv/@git.zone/tsdoc.json`.
## Use Cases
### 🚀 Continuous Integration
```yaml
# .github/workflows/docs.yml
name: Documentation
on: [push]
jobs:
docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Generate Documentation
env:
OPENAI_TOKEN: ${{ secrets.OPENAI_TOKEN }}
run: |
npm install -g @git.zone/tsdoc
tsdoc aidoc
- name: Commit Changes
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add readme.md package.json
git commit -m "docs: update documentation [skip ci]" || exit 0
git push
```
### 🔄 Pre-Commit Hooks
```bash
# .git/hooks/prepare-commit-msg
#!/bin/bash
tsdoc commit > .git/COMMIT_EDITMSG
```
### 📦 Package Publishing
```json
{
"scripts": {
"prepublishOnly": "tsdoc aidoc",
"version": "tsdoc aidoc && git add readme.md"
}
}
```
## Requirements
- **Node.js** >= 18.0.0
- **TypeScript** project
- **OpenAI API key** (for AI features)
## Troubleshooting
### Token Limit Exceeded
If you hit token limits, try:
```bash
# Check token usage details
tsdoc tokens --all --detailed
```
Or configure stricter limits in `npmextra.json`:
```json
{
"@git.zone/tsdoc": {
"context": {
"maxTokens": 100000,
"tiers": {
"essential": { "minScore": 0.9, "trimLevel": "none" },
"important": { "minScore": 0.7, "trimLevel": "aggressive" },
"optional": { "minScore": 0.5, "trimLevel": "aggressive" }
}
}
}
}
```
### Missing API Key
Set your OpenAI key:
```bash
export OPENAI_TOKEN="your-key-here"
tsdoc aidoc
```
### Slow Performance
Enable caching and adjust settings in `npmextra.json`:
```json
{
"@git.zone/tsdoc": {
"context": {
"cache": {
"enabled": true,
"ttl": 7200,
"maxSize": 200
}
}
}
}
```
### Cache Issues
Clear the cache if needed:
```bash
rm -rf .nogit/context-cache
```
## Why tsdoc?
### 🎯 Actually Understands Your Code
Not just parsing, but real comprehension through AI. The smart context system ensures AI sees the most relevant parts of your codebase.
### ⏱️ Saves Hours
Generate complete, accurate documentation in seconds. The intelligent caching system makes subsequent runs even faster.
### 🔄 Always Up-to-Date
Regenerate documentation with every change. Smart dependency analysis ensures nothing important is missed.
### 🎨 Beautiful Output
Clean, professional documentation every time. AI understands your code's purpose and explains it clearly.
### 💰 Cost-Effective
Smart context optimization reduces AI API costs by 40-60% without sacrificing quality.
The `description` command writes updated description/keywords to both `gitzone.module` in `.smartconfig.json` and to `package.json`.
## Architecture
@@ -349,45 +195,56 @@ Smart context optimization reduces AI API costs by 40-60% without sacrificing qu
```
@git.zone/tsdoc
├── AiDoc # Main AI documentation orchestrator
├── TypeDoc # Traditional TypeDoc integration
├── Context System # Smart context building
│ ├── EnhancedContext # Main context builder
│ ├── LazyFileLoader # Efficient file loading
├── ContextCache # Performance caching
│ ├── ContextAnalyzer # Intelligent file analysis
│ ├── ContextTrimmer # Adaptive code trimming
│ ├── DiffProcessor # Git diff optimization
│ ├── ConfigManager # Configuration management
│ └── TaskContextFactory # Task-specific contexts
└── CLI # Command-line interface
├── AiDoc # Main orchestrator — manages AI model, delegates to task classes
├── TypeDoc # Traditional TypeDoc API documentation generation
├── ProjectContext # Gathers project files (package.json, source, tests, config)
├── DiffProcessor # Intelligent git diff processing with prioritization & sampling
├── Readme # AI agent-driven README generation with filesystem tools
├── Commit # AI agent-driven commit message generation with diff analysis
├── Description # AI agent-driven description and keyword generation
└── CLI # Command-line interface built on @push.rocks/smartcli
```
### Data Flow
### 🧠 AI Agent Architecture
```
Project Files
LazyFileLoader (metadata scan)
ContextAnalyzer (scoring & prioritization)
ContextCache (check cache)
File Loading (parallel, on-demand)
ContextTrimmer (tier-based)
Token Budget (enforcement)
AI Model
Generated Documentation
```
Each documentation task (readme, commit, description) runs an autonomous AI agent via `@push.rocks/smartagent`'s `runAgent()`:
1. **System prompt** defines the agent's role, constraints, and output format
2. **Filesystem tools** give the agent scoped, read-only access to the project directory
3. **Autonomous exploration** — the agent decides which files to read, in what order
4. **Structured output** — README markdown, commit JSON, or description JSON
The agents use `@push.rocks/smartai`'s `getModel()` to create a language model instance backed by OpenAI.
### ⚡ Diff Processing Pipeline
The `DiffProcessor` handles large git diffs without blowing up token budgets:
| File Category | Threshold | Treatment |
|---------------|-----------|-----------|
| **Small** | < 300 lines changed | Included in full |
| **Medium** | < 800 lines changed | Head (75 lines) + tail (75 lines) sampling |
| **Large** | ≥ 800 lines changed | Metadata only (filepath + stats) |
Files are scored by importance:
- **100** — Source files (`src/`, `lib/`, `app/`, `components/`, `pages/`, `api/`)
- **80** — Test files (`test/`, `*.test.ts`, `*.spec.ts`)
- **70** — Interface/type files, entry points (`index.ts`, `mod.ts`)
- **60** — Configuration files (`.json`, `.yaml`, `.config.ts`)
- **40** — Documentation (`.md`, `.txt`)
- **10** — Build artifacts (`dist/`, `build/`, `.next/`)
Token budget is calculated dynamically: `context_limit - safety_margin - overhead - prompt_size`.
## Requirements
- **Node.js** >= 18
- **TypeScript** project with a `ts/` source directory
- **OpenAI API key** for AI features
## License and Legal Information
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file.
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./license) file.
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.

View File

@@ -39,4 +39,4 @@ tap.test('should stop AIdocs', async () => {
await aidocs.stop();
});
tap.start();
export default tap.start();

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@git.zone/tsdoc',
version: '1.11.0',
version: '2.0.2',
description: 'A comprehensive TypeScript documentation tool that leverages AI to generate and enhance project documentation, including dynamic README creation, API docs via TypeDoc, and smart commit message generation.'
}

View File

@@ -4,6 +4,25 @@ import { ProjectContext } from './projectcontext.js';
import { DiffProcessor } from '../classes.diffprocessor.js';
import { logger } from '../logging.js';
// Token budget configuration for OpenAI API limits
const TOKEN_BUDGET = {
OPENAI_CONTEXT_LIMIT: 272000, // OpenAI's configured limit
SAFETY_MARGIN: 10000, // Buffer to avoid hitting exact limit
SMARTAGENT_OVERHEAD: 180000, // System msgs, tools, history, formatting
TASK_PROMPT_OVERHEAD: 2000, // Task prompt template size
} as const;
/**
* Calculate max tokens available for diff content based on total budget
*/
function calculateMaxDiffTokens(): number {
const available = TOKEN_BUDGET.OPENAI_CONTEXT_LIMIT
- TOKEN_BUDGET.SAFETY_MARGIN
- TOKEN_BUDGET.SMARTAGENT_OVERHEAD
- TOKEN_BUDGET.TASK_PROMPT_OVERHEAD;
return Math.max(available, 30000);
}
export interface INextCommitObject {
recommendedNextVersionLevel: 'fix' | 'feat' | 'BREAKING CHANGE'; // the recommended next version level of the project
recommendedNextVersionScope: string; // the recommended scope name of the next version, like "core" or "cli", or specific class names.
@@ -84,15 +103,19 @@ export class Commit {
const totalChars = diffStringArray.join('\n\n').length;
const estimatedTokens = Math.ceil(totalChars / 4);
console.log(`📊 Raw git diff statistics:`);
console.log(`Raw git diff statistics:`);
console.log(` Files changed: ${diffStringArray.length}`);
console.log(` Total characters: ${totalChars.toLocaleString()}`);
console.log(` Estimated tokens: ${estimatedTokens.toLocaleString()}`);
console.log(` Exclusion patterns: ${excludePatterns.length}`);
// Calculate available tokens for diff based on total budget
const maxDiffTokens = calculateMaxDiffTokens();
console.log(`Token budget: ${maxDiffTokens.toLocaleString()} tokens for diff (limit: ${TOKEN_BUDGET.OPENAI_CONTEXT_LIMIT.toLocaleString()}, overhead: ${(TOKEN_BUDGET.SMARTAGENT_OVERHEAD + TOKEN_BUDGET.TASK_PROMPT_OVERHEAD).toLocaleString()})`);
// Use DiffProcessor to intelligently handle large diffs
const diffProcessor = new DiffProcessor({
maxDiffTokens: 100000, // Reserve 100k tokens for diffs
maxDiffTokens, // Dynamic based on total budget
smallFileLines: 300, // Most source files are under 300 lines
mediumFileLines: 800, // Only very large files get head/tail treatment
sampleHeadLines: 75, // When sampling, show more context
@@ -102,66 +125,70 @@ export class Commit {
const processedDiff = diffProcessor.processDiffs(diffStringArray);
processedDiffString = diffProcessor.formatForContext(processedDiff);
console.log(`📝 Processed diff statistics:`);
console.log(`Processed diff statistics:`);
console.log(` Full diffs: ${processedDiff.fullDiffs.length} files`);
console.log(` Summarized: ${processedDiff.summarizedDiffs.length} files`);
console.log(` Metadata only: ${processedDiff.metadataOnly.length} files`);
console.log(` Final tokens: ${processedDiff.totalTokens.toLocaleString()}`);
if (estimatedTokens > 50000) {
console.log(`DiffProcessor reduced token usage: ${estimatedTokens.toLocaleString()} ${processedDiff.totalTokens.toLocaleString()}`);
console.log(`DiffProcessor reduced token usage: ${estimatedTokens.toLocaleString()} -> ${processedDiff.totalTokens.toLocaleString()}`);
}
// Validate total tokens won't exceed limit
const totalEstimatedTokens = processedDiff.totalTokens
+ TOKEN_BUDGET.SMARTAGENT_OVERHEAD
+ TOKEN_BUDGET.TASK_PROMPT_OVERHEAD;
if (totalEstimatedTokens > TOKEN_BUDGET.OPENAI_CONTEXT_LIMIT - TOKEN_BUDGET.SAFETY_MARGIN) {
console.log(`Warning: Estimated tokens (${totalEstimatedTokens.toLocaleString()}) approaching limit`);
console.log(` Consider splitting into smaller commits`);
}
} else {
processedDiffString = 'No changes.';
}
// Use DualAgentOrchestrator for commit message generation
// Note: No filesystem tool needed - the diff already contains all change information
const commitOrchestrator = new plugins.smartagent.DualAgentOrchestrator({
smartAiInstance: this.aiDocsRef.smartAiInstance,
defaultProvider: 'openai',
logPrefix: '[Commit]',
onProgress: (event) => logger.log(event.logLevel, event.logMessage),
guardianPolicyPrompt: `
You validate commit messages for semantic versioning compliance.
// Use runAgent for commit message generation with filesystem tool
const fsTools = plugins.smartagentTools.filesystemTool({ rootDir: this.projectDir });
APPROVE if:
- Version level (fix/feat/BREAKING CHANGE) matches the scope of changes in the diff
- Commit message is clear, professional, and follows conventional commit conventions
- No personal information, licensing details, or AI mentions (Claude/Codex) included
- JSON structure is valid with all required fields
- Scope accurately reflects the changed modules/files
const commitSystemPrompt = `
You create commit messages for git commits following semantic versioning conventions.
REJECT with specific feedback if:
- Version level doesn't match the scope of changes (e.g., "feat" for a typo fix should be "fix")
- Message is vague, unprofessional, or contains sensitive information
- JSON is malformed or missing required fields
`,
});
You have access to filesystem tools to explore the project if needed.
await commitOrchestrator.start();
IMPORTANT RULES:
- Only READ files (package.json, source files) for context
- Do NOT write, delete, or modify any files
- Version level (fix/feat/BREAKING CHANGE) must match the scope of changes
- Commit message must be clear, professional, and follow conventional commit conventions
- Do NOT include personal information, licensing details, or AI mentions (Claude/Codex)
- JSON structure must be valid with all required fields
- Scope must accurately reflect the changed modules/files
`;
const commitTaskPrompt = `
You create a commit message for a git commit.
Project directory: ${this.projectDir}
You have access to filesystem tools to explore the project if needed:
- Use list_directory to see project structure
- Use read_file to read package.json or source files for context
Analyze the git diff below to understand what changed and generate a commit message.
You should not include any licensing information or personal information.
Never mention CLAUDE code, or codex.
Important: Answer only in valid JSON.
Your final response must be ONLY valid JSON - the raw JSON object, nothing else.
No explanations, no summaries, no markdown - just the JSON object that can be parsed with JSON.parse().
Your answer should be parseable with JSON.parse() without modifying anything.
Here is the structure of the JSON you must return:
Here is the structure of the JSON you should return:
interface {
recommendedNextVersionLevel: 'fix' | 'feat' | 'BREAKING CHANGE'; // the recommended next version level
recommendedNextVersionScope: string; // scope name like "core", "cli", or specific class names
recommendedNextVersionMessage: string; // the commit message (don't include fix/feat prefix)
recommendedNextVersionDetails: string[]; // detailed bullet points for the changelog
recommendedNextVersion: string; // the recommended next version x.x.x
{
"recommendedNextVersionLevel": "fix" | "feat" | "BREAKING CHANGE",
"recommendedNextVersionScope": "string",
"recommendedNextVersionMessage": "string (ONLY the description body WITHOUT the type(scope): prefix - e.g. 'bump dependency to ^1.2.6' NOT 'fix(deps): bump dependency to ^1.2.6')",
"recommendedNextVersionDetails": ["string"],
"recommendedNextVersion": "x.x.x"
}
For recommendedNextVersionDetails, only add entries that have obvious value to the reader.
@@ -170,19 +197,33 @@ Here is the git diff showing what changed:
${processedDiffString}
Generate the commit message based on these changes.
Analyze these changes and output the JSON commit message object.
`;
const commitResult = await commitOrchestrator.run(commitTaskPrompt);
await commitOrchestrator.stop();
logger.log('info', 'Starting commit message generation with agent...');
if (!commitResult.success) {
throw new Error(`Commit message generation failed: ${commitResult.status}`);
const commitResult = await plugins.smartagent.runAgent({
model: this.aiDocsRef.model,
prompt: commitTaskPrompt,
system: commitSystemPrompt,
tools: fsTools,
maxSteps: 10,
onToolCall: (toolName) => logger.log('info', `[Commit] Tool call: ${toolName}`),
});
// Extract JSON from result - handle cases where AI adds text around it
let jsonString = commitResult.text
.replace(/```json\n?/gi, '')
.replace(/```\n?/gi, '');
// Try to find JSON object in the result
const jsonMatch = jsonString.match(/\{[\s\S]*\}/);
if (!jsonMatch) {
throw new Error(`Could not find JSON object in result: ${jsonString.substring(0, 100)}...`);
}
jsonString = jsonMatch[0];
const resultObject: INextCommitObject = JSON.parse(
commitResult.result.replace('```json', '').replace('```', '')
);
const resultObject: INextCommitObject = JSON.parse(jsonString);
const previousChangelogPath = plugins.path.join(this.projectDir, 'changelog.md');
let previousChangelog: plugins.smartfile.SmartFile;
@@ -195,30 +236,16 @@ Generate the commit message based on these changes.
const commitMessages = await gitRepo.getAllCommitMessages();
console.log(JSON.stringify(commitMessages, null, 2));
// Use DualAgentOrchestrator for changelog generation with Guardian validation
const changelogOrchestrator = new plugins.smartagent.DualAgentOrchestrator({
smartAiInstance: this.aiDocsRef.smartAiInstance,
defaultProvider: 'openai',
logPrefix: '[Changelog]',
onProgress: (event) => logger.log(event.logLevel, event.logMessage),
guardianPolicyPrompt: `
You validate changelog generation.
const changelogSystemPrompt = `
You generate changelog.md files for software projects.
APPROVE if:
- Changelog follows proper markdown format with ## headers for each version
- Entries are chronologically ordered (newest first)
- Version ranges for trivial commits are properly summarized
RULES:
- Changelog must follow proper markdown format with ## headers for each version
- Entries must be chronologically ordered (newest first)
- Version ranges for trivial commits should be properly summarized
- No duplicate or empty entries
- Format matches: ## yyyy-mm-dd - x.x.x - scope
REJECT with feedback if:
- Markdown formatting is incorrect
- Entries are not meaningful or helpful
- Dates or versions are malformed
`,
});
await changelogOrchestrator.start();
- Format: ## yyyy-mm-dd - x.x.x - scope
`;
const changelogTaskPrompt = `
You are building a changelog.md file for the project.
@@ -227,7 +254,7 @@ Omit commits and versions that lack relevant changes, but make sure to mention t
A changelog entry should look like this:
## yyyy-mm-dd - x.x.x - scope here
main descriptiom here
main description here
- detailed bullet points follow
@@ -241,16 +268,17 @@ Here are the commit messages:
${JSON.stringify(commitMessages, null, 2)}
`;
const changelogResult = await changelogOrchestrator.run(changelogTaskPrompt);
await changelogOrchestrator.stop();
if (!changelogResult.success) {
throw new Error(`Changelog generation failed: ${changelogResult.status}`);
}
const changelogResult = await plugins.smartagent.runAgent({
model: this.aiDocsRef.model,
prompt: changelogTaskPrompt,
system: changelogSystemPrompt,
maxSteps: 1,
onToolCall: (toolName) => logger.log('info', `[Changelog] Tool call: ${toolName}`),
});
previousChangelog = plugins.smartfileFactory.fromString(
previousChangelogPath,
changelogResult.result.replaceAll('```markdown', '').replaceAll('```', ''),
changelogResult.text.replaceAll('```markdown', '').replaceAll('```', ''),
'utf8'
);
}

View File

@@ -19,55 +19,31 @@ export class Description {
}
public async build() {
// Use DualAgentOrchestrator with filesystem tool for agent-driven exploration
const descriptionOrchestrator = new plugins.smartagent.DualAgentOrchestrator({
smartAiInstance: this.aiDocsRef.smartAiInstance,
defaultProvider: 'openai',
maxIterations: 15,
maxResultChars: 10000, // Limit tool output to prevent token explosion
maxHistoryMessages: 15, // Limit history window
logPrefix: '[Description]',
onProgress: (event) => logger.log(event.logLevel, event.logMessage),
guardianPolicyPrompt: `
You validate description generation tool calls and outputs.
// Use runAgent with filesystem tool for agent-driven exploration
const fsTools = plugins.smartagentTools.filesystemTool({ rootDir: this.projectDir });
APPROVE tool calls for:
- Reading package.json, npmextra.json, or source files in the ts/ directory
- Listing directory contents to understand project structure
- Using tree to see project structure
const descriptionSystemPrompt = `
You create project descriptions and keywords for npm packages.
REJECT tool calls for:
- Reading files outside the project directory
- Writing, deleting, or modifying any files
- Any destructive operations
You have access to filesystem tools to explore the project.
For final output, APPROVE if:
- JSON is valid and parseable
- Description is a clear, concise one-sentence summary
- Keywords are relevant to the project's use cases
- Both description and keywords fields are present
REJECT final output if:
- JSON is malformed or wrapped in markdown code blocks
- Description is too long or vague
- Keywords are irrelevant or generic
`,
});
// Register scoped filesystem tool for agent exploration
descriptionOrchestrator.registerScopedFilesystemTool(this.projectDir);
await descriptionOrchestrator.start();
IMPORTANT RULES:
- Only READ files (package.json, .smartconfig.json, source files in ts/)
- Do NOT write, delete, or modify any files
- Your final response must be valid JSON only
- Description must be a clear, concise one-sentence summary
- Keywords must be relevant to the project's use cases
- Both description and keywords fields must be present
- Do NOT wrap JSON in markdown code blocks
`;
const descriptionTaskPrompt = `
You create a project description and keywords for an npm package.
PROJECT DIRECTORY: ${this.projectDir}
Use the filesystem tool to explore the project and understand what it does:
1. First, use tree to see the project structure
Use the filesystem tools to explore the project and understand what it does:
1. First, use list_directory to see the project structure
2. Read package.json to understand the package name and current description
3. Read npmextra.json if it exists for additional metadata
3. Read .smartconfig.json if it exists for additional metadata
4. Read key source files in ts/ directory to understand the implementation
Then generate a description and keywords based on your exploration.
@@ -83,31 +59,35 @@ Your answer should be parseable with JSON.parse() without modifying anything.
Don't wrap the JSON in \`\`\`json\`\`\` - just return the raw JSON object.
`;
const descriptionResult = await descriptionOrchestrator.run(descriptionTaskPrompt);
await descriptionOrchestrator.stop();
logger.log('info', 'Starting description generation with agent...');
if (!descriptionResult.success) {
throw new Error(`Description generation failed: ${descriptionResult.status}`);
}
const descriptionResult = await plugins.smartagent.runAgent({
model: this.aiDocsRef.model,
prompt: descriptionTaskPrompt,
system: descriptionSystemPrompt,
tools: fsTools,
maxSteps: 15,
onToolCall: (toolName) => logger.log('info', `[Description] Tool call: ${toolName}`),
});
console.log(descriptionResult.result);
console.log(descriptionResult.text);
const resultObject: IDescriptionInterface = JSON.parse(
descriptionResult.result.replace('```json', '').replace('```', ''),
descriptionResult.text.replace('```json', '').replace('```', ''),
);
// Use ProjectContext to get file handles for writing
const projectContext = new ProjectContext(this.projectDir);
const files = await projectContext.gatherFiles();
// Update npmextra.json
const npmextraJson = files.smartfilesNpmextraJSON;
const npmextraJsonContent = JSON.parse(npmextraJson.contents.toString());
// Update smartconfig.json
const smartconfigJson = files.smartfilesNpmextraJSON;
const smartconfigJsonContent = JSON.parse(smartconfigJson.contents.toString());
npmextraJsonContent['@git.zone/cli'].module.description = resultObject.description;
npmextraJsonContent['@git.zone/cli'].module.keywords = resultObject.keywords;
smartconfigJsonContent['gitzone'].module.description = resultObject.description;
smartconfigJsonContent['gitzone'].module.keywords = resultObject.keywords;
npmextraJson.contents = Buffer.from(JSON.stringify(npmextraJsonContent, null, 2));
await npmextraJson.write();
smartconfigJson.contents = Buffer.from(JSON.stringify(smartconfigJsonContent, null, 2));
await smartconfigJson.write();
// Update package.json
const packageJson = files.smartfilePackageJSON;
@@ -120,6 +100,6 @@ Don't wrap the JSON in \`\`\`json\`\`\` - just return the raw JSON object.
console.log(`\n======================\n`);
console.log(JSON.stringify(resultObject, null, 2));
console.log(`\n======================\n`);
return descriptionResult.result;
return descriptionResult.text;
}
}

View File

@@ -27,7 +27,7 @@ export class ProjectContext {
this.projectDir,
);
const smartfilesNpmextraJSON = await plugins.smartfileFactory.fromFilePath(
plugins.path.join(this.projectDir, 'npmextra.json'),
plugins.path.join(this.projectDir, '.smartconfig.json'),
this.projectDir,
);
const smartfilesMod = await plugins.smartfileFactory.virtualDirectoryFromPath(

View File

@@ -19,64 +19,40 @@ export class Readme {
// First check legal info before introducing any cost
const projectContext = new ProjectContext(this.projectDir);
const npmExtraJson = JSON.parse(
const smartconfigJson = JSON.parse(
(await projectContext.gatherFiles()).smartfilesNpmextraJSON.contents.toString()
);
const legalInfo = npmExtraJson?.['@git.zone/tsdoc']?.legal;
const legalInfo = smartconfigJson?.['tsdoc']?.legal;
if (!legalInfo) {
const error = new Error(`No legal information found in npmextra.json`);
const error = new Error(`No legal information found in .smartconfig.json`);
console.log(error);
}
// Use DualAgentOrchestrator with filesystem tool for agent-driven exploration
const readmeOrchestrator = new plugins.smartagent.DualAgentOrchestrator({
smartAiInstance: this.aiDocsRef.smartAiInstance,
defaultProvider: 'openai',
maxIterations: 25,
maxResultChars: 15000, // Limit tool output to prevent token explosion
maxHistoryMessages: 20, // Limit history window
logPrefix: '[README]',
onProgress: (event) => logger.log(event.logLevel, event.logMessage),
guardianPolicyPrompt: `
You validate README generation tool calls and outputs.
// Use runAgent with filesystem tool for agent-driven exploration
const fsTools = plugins.smartagentTools.filesystemTool({ rootDir: this.projectDir });
APPROVE tool calls for:
- Reading any files within the project directory (package.json, ts/*.ts, readme.md, etc.)
- Using tree to see project structure
- Using glob to find source files
- Listing directory contents
REJECT tool calls for:
- Reading files outside the project directory
- Writing, deleting, or modifying any files
- Any destructive operations
For final README output, APPROVE if:
- README follows proper markdown format
- Contains Install and Usage sections
- Code examples are correct TypeScript/ESM syntax
- Documentation is comprehensive and helpful
REJECT final output if:
- README is incomplete or poorly formatted
- Contains licensing information (added separately)
- Uses CommonJS syntax instead of ESM
- Contains "in conclusion" or similar filler
`,
});
// Register scoped filesystem tool for agent exploration
readmeOrchestrator.registerScopedFilesystemTool(this.projectDir);
await readmeOrchestrator.start();
const readmeTaskPrompt = `
const readmeSystemPrompt = `
You create markdown READMEs for npm projects. You only output the markdown readme.
You have access to filesystem tools to explore the project. Use them to understand the codebase.
IMPORTANT RULES:
- Only READ files within the project directory
- Do NOT write, delete, or modify any files
- README must follow proper markdown format
- Must contain Install and Usage sections
- Code examples must use correct TypeScript/ESM syntax
- Documentation must be comprehensive and helpful
- Do NOT include licensing information (added separately)
- Do NOT use CommonJS syntax - only ESM
- Do NOT include "in conclusion" or similar filler
`;
const readmeTaskPrompt = `
PROJECT DIRECTORY: ${this.projectDir}
Use the filesystem tool to explore the project and understand what it does:
1. First, use tree to see the project structure (maxDepth: 3)
Use the filesystem tools to explore the project and understand what it does:
1. First, use list_directory to see the project structure
2. Read package.json to understand the package name, description, and dependencies
3. Read the existing readme.md if it exists (use it as a base, improve and expand)
4. Read readme.hints.md if it exists (contains hints for documentation)
@@ -106,15 +82,19 @@ Then generate a comprehensive README following this template:
]
`;
const readmeResult = await readmeOrchestrator.run(readmeTaskPrompt);
await readmeOrchestrator.stop();
logger.log('info', 'Starting README generation with agent...');
if (!readmeResult.success) {
throw new Error(`README generation failed: ${readmeResult.status}`);
}
const readmeResult = await plugins.smartagent.runAgent({
model: this.aiDocsRef.model,
prompt: readmeTaskPrompt,
system: readmeSystemPrompt,
tools: fsTools,
maxSteps: 25,
onToolCall: (toolName) => logger.log('info', `[README] Tool call: ${toolName}`),
});
// Clean up markdown formatting if wrapped in code blocks
let resultMessage = readmeResult.result
let resultMessage = readmeResult.text
.replace(/^```markdown\n?/i, '')
.replace(/\n?```$/i, '');
@@ -142,40 +122,19 @@ Then generate a comprehensive README following this template:
.encoding('utf8')
.read();
// Create a new orchestrator with filesystem tool for each submodule
const subModuleOrchestrator = new plugins.smartagent.DualAgentOrchestrator({
smartAiInstance: this.aiDocsRef.smartAiInstance,
defaultProvider: 'openai',
maxIterations: 20,
maxResultChars: 12000,
maxHistoryMessages: 15,
logPrefix: `[README:${subModule}]`,
onProgress: (event) => logger.log(event.logLevel, event.logMessage),
guardianPolicyPrompt: `
You validate README generation for submodules.
const subModuleFsTools = plugins.smartagentTools.filesystemTool({ rootDir: subModulePath });
APPROVE tool calls for:
- Reading any files within the submodule directory
- Using tree to see structure
- Using glob to find source files
const subModuleSystemPrompt = `
You create markdown READMEs for npm projects. You only output the markdown readme.
REJECT tool calls for:
- Reading files outside the submodule directory
- Writing, deleting, or modifying any files
- Any destructive operations
APPROVE final README if comprehensive, well-formatted markdown with ESM TypeScript examples.
REJECT incomplete READMEs or those with licensing info.
`,
});
// Register scoped filesystem tool for the submodule directory
subModuleOrchestrator.registerScopedFilesystemTool(subModulePath);
await subModuleOrchestrator.start();
IMPORTANT RULES:
- Only READ files within the submodule directory
- Do NOT write, delete, or modify any files
- README must be comprehensive, well-formatted markdown with ESM TypeScript examples
- Do NOT include licensing information (added separately)
`;
const subModulePrompt = `
You create markdown READMEs for npm projects. You only output the markdown readme.
SUB MODULE: ${subModule}
SUB MODULE DIRECTORY: ${subModulePath}
@@ -183,8 +142,8 @@ IMPORTANT: YOU ARE CREATING THE README FOR THIS SUB MODULE: ${subModule}
The Sub Module will be published with:
${JSON.stringify(tspublishData, null, 2)}
Use the filesystem tool to explore the submodule:
1. Use tree to see the submodule structure
Use the filesystem tools to explore the submodule:
1. Use list_directory to see the submodule structure
2. Read package.json to understand the submodule
3. Read source files in ts/ directory to understand the implementation
@@ -208,21 +167,23 @@ Generate a README following the template:
Don't use \`\`\` at the beginning or end. Only for code blocks.
`;
const subModuleResult = await subModuleOrchestrator.run(subModulePrompt);
await subModuleOrchestrator.stop();
const subModuleResult = await plugins.smartagent.runAgent({
model: this.aiDocsRef.model,
prompt: subModulePrompt,
system: subModuleSystemPrompt,
tools: subModuleFsTools,
maxSteps: 20,
onToolCall: (toolName) => logger.log('info', `[README:${subModule}] Tool call: ${toolName}`),
});
if (subModuleResult.success) {
const subModuleReadmeString = subModuleResult.result
.replace(/^```markdown\n?/i, '')
.replace(/\n?```$/i, '') + '\n' + legalInfo;
await plugins.fsInstance
.file(plugins.path.join(subModulePath, 'readme.md'))
.encoding('utf8')
.write(subModuleReadmeString);
logger.log('success', `Built readme for ${subModule}`);
} else {
logger.log('error', `Failed to build readme for ${subModule}: ${subModuleResult.status}`);
}
const subModuleReadmeString = subModuleResult.text
.replace(/^```markdown\n?/i, '')
.replace(/\n?```$/i, '') + '\n' + legalInfo;
await plugins.fsInstance
.file(plugins.path.join(subModulePath, 'readme.md'))
.encoding('utf8')
.write(subModuleReadmeString);
logger.log('success', `Built readme for ${subModule}`);
}
return resultMessage;

View File

@@ -5,10 +5,10 @@ import * as aiDocsClasses from './aidocs_classes/index.js';
export class AiDoc {
private openaiToken: string;
public npmextraKV: plugins.npmextra.KeyValueStore;
public smartconfigKV: plugins.smartconfig.KeyValueStore;
public qenvInstance: plugins.qenv.Qenv;
public aidocInteract: plugins.smartinteract.SmartInteract;
public smartAiInstance: plugins.smartai.SmartAi;
public model: plugins.smartai.LanguageModelV3;
argvArg: any;
@@ -38,8 +38,8 @@ export class AiDoc {
if (!(await this.qenvInstance.getEnvVarOnDemand('OPENAI_TOKEN'))) {
// Migrate old KV store path to new path if needed
const homeDir = plugins.smartpath.get.home();
const oldKvPath = plugins.path.join(homeDir, '.npmextra/kv/tsdoc.json');
const newKvDir = plugins.path.join(homeDir, '.npmextra/kv/@git.zone');
const oldKvPath = plugins.path.join(homeDir, '.smartconfig/kv/tsdoc.json');
const newKvDir = plugins.path.join(homeDir, '.smartconfig/kv/@git.zone');
const newKvPath = plugins.path.join(newKvDir, 'tsdoc.json');
if (
await plugins.fsInstance.file(oldKvPath).exists() &&
@@ -52,13 +52,13 @@ export class AiDoc {
console.log('Migration complete: tsdoc.json -> @git.zone/tsdoc.json');
}
this.npmextraKV = new plugins.npmextra.KeyValueStore({
this.smartconfigKV = new plugins.smartconfig.KeyValueStore({
typeArg: 'userHomeDir',
identityArg: '@git.zone/tsdoc',
mandatoryKeys: ['OPENAI_TOKEN'],
});
const missingKeys = await this.npmextraKV.getMissingMandatoryKeys();
const missingKeys = await this.smartconfigKV.getMissingMandatoryKeys();
if (missingKeys.length > 0) {
// lets try argv
if (this.argvArg?.OPENAI_TOKEN) {
@@ -77,34 +77,23 @@ export class AiDoc {
}
this.printSanitizedToken();
await this.npmextraKV.writeKey('OPENAI_TOKEN', this.openaiToken);
await this.smartconfigKV.writeKey('OPENAI_TOKEN', this.openaiToken);
}
}
if (!this.openaiToken && this.npmextraKV) {
this.openaiToken = await this.npmextraKV.readKey('OPENAI_TOKEN');
if (!this.openaiToken && this.smartconfigKV) {
this.openaiToken = await this.smartconfigKV.readKey('OPENAI_TOKEN');
}
// lets assume we have an OPENAI_Token now
this.smartAiInstance = new plugins.smartai.SmartAi({
openaiToken: this.openaiToken,
// Create model using getModel()
this.model = plugins.smartai.getModel({
provider: 'openai',
model: 'gpt-5.4',
apiKey: this.openaiToken,
});
await this.smartAiInstance.start();
}
public async stop() {
if (this.smartAiInstance) {
await this.smartAiInstance.stop();
}
// No explicit cleanup needed for npmextraKV or aidocInteract
// They don't keep event loop alive
}
/**
* Get the OpenAI provider for direct chat calls
* This is a convenience getter to access the provider from SmartAi
*/
public get openaiProvider(): plugins.smartai.OpenAiProvider {
return this.smartAiInstance.openaiProvider;
// No lifecycle management needed with getModel() API
}
public getOpenaiToken(): string {
@@ -130,7 +119,7 @@ export class AiDoc {
const projectContextInstance = new aiDocsClasses.ProjectContext(projectDirArg);
return await projectContextInstance.gatherFiles();
}
/**
* Get the context with token count information
* @param projectDirArg The path to the project directory
@@ -141,7 +130,7 @@ export class AiDoc {
await projectContextInstance.update();
return projectContextInstance.getContextWithTokenCount();
}
/**
* Get just the token count for a project's context
* @param projectDirArg The path to the project directory
@@ -152,7 +141,7 @@ export class AiDoc {
await projectContextInstance.update();
return projectContextInstance.getTokenCount();
}
/**
* Estimate token count in a text string
* @param text The text to estimate tokens for

View File

@@ -4,9 +4,10 @@ import * as path from 'path';
export { path };
// pushrocks scope
import * as npmextra from '@push.rocks/npmextra';
import * as smartconfig from '@push.rocks/smartconfig';
import * as qenv from '@push.rocks/qenv';
import * as smartagent from '@push.rocks/smartagent';
import * as smartagentTools from '@push.rocks/smartagent/tools';
import * as smartai from '@push.rocks/smartai';
import * as smartcli from '@push.rocks/smartcli';
import * as smartdelay from '@push.rocks/smartdelay';
@@ -21,9 +22,10 @@ import * as smartshell from '@push.rocks/smartshell';
import * as smarttime from '@push.rocks/smarttime';
export {
npmextra,
smartconfig,
qenv,
smartagent,
smartagentTools,
smartai,
smartcli,
smartdelay,