zephyr-agent
Version:
Zephyr plugin agent
295 lines (206 loc) • 10.2 kB
Markdown
# Zephyr Agent (Internal)
<div align="center">
[Zephyr Cloud](https://zephyr-cloud.io) | [Zephyr Docs](https://docs.zephyr-cloud.io) | [Discord](https://zephyr-cloud.io/discord) | [Twitter](https://x.com/ZephyrCloudIO) | [LinkedIn](https://www.linkedin.com/company/zephyr-cloud/)
<hr/>
<img src="https://cdn.prod.website-files.com/669061ee3adb95b628c3acda/66981c766e352fe1f57191e2_Opengraph-zephyr.png" alt="Zephyr Logo" />
</div>
**Internal Package** - The main internal package that provides the Zephyr agent for bundler plugins. This package contains the core functionality for deployment, asset management, and communication with Zephyr Cloud.
> **Note**: This is an internal package used by other Zephyr plugins. It is not intended for direct use by end users.
## Overview
The Zephyr Agent is the core engine that powers all Zephyr bundler plugins. It provides:
- **Deployment Pipeline**: Handles the complete deployment workflow to Zephyr Cloud
- **Asset Management**: Optimizes and manages build assets for edge distribution
- **Authentication**: Manages secure communication with Zephyr Cloud services
- **Build Context**: Provides build-time context and metadata for plugins
- **Edge Communication**: Handles communication with Zephyr's edge network
## Architecture
The agent is structured into several key modules:
### Authentication (`lib/auth/`)
- Handles user authentication and authorization
- Manages API tokens and session management
- Provides WebSocket connections for real-time updates
- Reads `ZE_SECRET_TOKEN` directly without persisting the environment secret
- Exchanges `ZE_CI_TOKEN` once per CI identity using a persistent, inter-process locked access-token cache
- Keeps credential cleanup scoped so concurrent deployment and application records remain intact
See [CI Token Identity](../../docs/ci-token-identity.md) for token precedence,
identity attribution, persistence, and concurrency invariants.
### Build Context (`lib/build-context/`)
- Extracts build metadata and package information
- Provides Git integration and repository context
- Manages dependency resolution and parsing
### Deployment (`lib/deployment/`)
- Implements deployment strategies for different CDN providers
- Supports Cloudflare, Fastly, and Netlify deployment targets
- Handles asset uploads and build stats publication
### Edge Actions (`lib/edge-actions/`)
- Manages deployment operations on edge infrastructure
- Handles snapshot creation and environment enabling
- Coordinates asset uploads and build statistics
### HTTP Layer (`lib/http/`)
- Provides HTTP client functionality with retries
- Handles file uploads and API communication
- Manages request/response lifecycle
## Usage by Plugins
Public Zephyr plugins interact with the agent through well-defined APIs:
```typescript
import { ZephyrAgent } from 'zephyr-agent';
// Initialize the agent
const agent = new ZephyrAgent({
buildContext: buildInfo,
assets: assetMap,
});
// Deploy to Zephyr Cloud
await agent.deploy();
```
## Dependencies
The agent has minimal external dependencies:
- **Core Dependencies**: Node.js built-ins and essential utilities
- **Network**: HTTP client libraries for API communication
- **File System**: Asset management and build context extraction
- **Crypto**: Secure token management and validation
## Configuration
Bundler plugins can infer application identity from Git and `package.json`, or load a
strict project config from the bundler context:
```typescript
import { defineConfig } from 'zephyr-agent';
export default defineConfig({
org: 'my-org',
project: 'my-project',
appName: 'my-app',
remoteDependencies: {
remote: 'zephyr:remote.remote-project.remote-org@latest',
},
dependencyUrlMode: 'version',
});
```
Name the file `zephyr.config.ts`, `.mts`, `.cts`, `.js`, `.mjs`, or `.cjs`. Only
`org`, `project`, `appName`, `remoteDependencies`, and `dependencyUrlMode` are valid.
Config identity wins over Git inference, `appName` wins over the package name, and
config remotes win by key over `package.json` `zephyr:dependencies`.
`dependencyUrlMode: 'version'` keeps tag, environment, and workspace selection while
embedding the resolved immutable version URLs in Module Federation configuration. The
default `selector` mode preserves mutable tag and environment URLs. Environment identity
overrides are not supported, and config loading never mutates `process.env`.
The config is resolved once when a `ZephyrEngine` is created and is shared by every
compiler participating in that application build. Restart the bundler after changing
the file so an active `ApplicationContext` never changes identity between watch
generations.
### Git Repository Requirements
Git remains the richest source of version metadata. An explicit Zephyr config can
replace remote-origin identity inference while retaining Git author, branch, commit, and
tag metadata.
#### Git Information Handling
When Zephyr cannot find a Git repository with remote origin, it will:
1. **Automatic Package.json-Based Naming**:
- Extract organization, project, and app names from your `package.json`
- Use authenticated user's username as the organization for personal Zephyr org
- Follow intelligent naming conventions based on package structure
- No user prompts or environment variables required
2. **Enhanced Naming Logic**:
- **Scoped packages** (`@scope/name`): project = scope, app = name
- **With root package.json**:
- If root is scoped (`@scope/name`): project = scope, app = current package name
- Otherwise: project = root package name, app = current package name
- **Fallback to directory name**: If no root package.json found, uses directory name as project
- **Single package**: project = app = package name
- **Organization**: Uses authenticated user's username (sanitized for URL safety)
#### Example Scenarios
```bash
# Recommended: Proper Git setup (required for CI)
git init
git remote add origin git@github.com:YOUR_ORG/YOUR_REPO.git
git add . && git commit -m "Initial commit"
npm run build # Works perfectly with full Git context
# Local-only metadata mode (no commit yet)
git init
git remote add origin git@github.com:YOUR_ORG/YOUR_REPO.git
npm run build # Works for local builds; CI still requires commit history
# Automatic fallback (works seamlessly)
# No git repository - uses package.json naming
npm run build # Automatically determines naming from package.json
# Examples of automatic naming:
# package.json: { "name": "@my-company/my-app" }
# → org: "jwt-username", project: "my-company", app: "my-app"
# package.json: { "name": "my-project" } (no root package.json)
# → org: "jwt-username", project: "my-project", app: "my-project"
# package.json: { "name": "my-app" } (root package.json: { "name": "my-workspace" })
# → org: "jwt-username", project: "my-workspace", app: "my-app"
# package.json: { "name": "my-app" } (root package.json: { "name": "@company/monorepo" })
# → org: "jwt-username", project: "company", app: "my-app"
# package.json: { "name": "my-app" } (no root package.json found)
# → org: "jwt-username", project: "current-directory-name", app: "my-app"
# Special characters in username get sanitized:
# Username: "Néstor López" → org: "n-stor-l-pez"
```
#### Why Git is Required
Zephyr uses Git information to:
- Determine organization and project structure
- Track deployment versions and commits
- Enable collaboration features
- Provide proper deployment metadata
Without Git, Zephyr cannot guarantee proper functionality, especially for:
- Production deployments
- Team collaboration
- Version tracking
- Rollback capabilities
#### Package.json-Based Naming (Non-Git Environments)
When Git is not available (e.g., AI coding tools, quick prototypes), Zephyr automatically extracts naming information from your `package.json` structure:
**Automatic Organization Detection:**
- Uses the authenticated user's name from your authentication token
- Requires valid authentication to determine organization
**Project and App Naming Logic:**
1. **Scoped Package** (`@company/app-name`):
- Project: `company` (scope without @)
- App: `app-name`
2. **Monorepo Structure** (root `package.json` exists):
- If root is scoped (`@company/monorepo`): Project = `company`, App = current package name
- Otherwise: Project = root package name, App = current package name
- If no root package.json found: Project = current directory name, App = current package name
3. **Single Package**:
- Project: Package name
- App: Package name
## Internal APIs
### Build Context API
```typescript
// Extract package.json information
const packageInfo = await readPackageJson(projectRoot);
// Get Git repository information
const gitInfo = await getGitInfo();
// Parse Zephyr dependencies
const deps = parseZephyrDependencies(packageJson);
```
### Deployment API
```typescript
// Upload assets to CDN
await uploadAssets(assets, uploadStrategy);
// Enable environment on edge
await enableSnapshotOnEdge(snapshotId);
// Upload build statistics
await uploadBuildStats(buildStats);
```
## Integration Points
The agent integrates with:
- **Bundler Plugins**: Receives build assets and metadata
- **Zephyr Cloud**: Deploys assets and manages deployments
- **CDN Providers**: Uploads assets to edge locations
- **Git Providers**: Extracts repository and commit information
## Development
For plugin developers working on Zephyr integrations:
```bash
# Build the agent
npm run build
# Run tests
npm run test
# Development mode
npm run dev
```
## Security
The agent implements several security measures:
- **Token Management**: Secure storage and rotation of API tokens
- **Encrypted Communication**: All API communication uses HTTPS/WSS
- **Input Validation**: Validates all build inputs and configurations
- **Access Control**: Role-based access to deployment operations
## Contributing
This is an internal package. Contributions should be made through the main Zephyr plugins repository. Please read our [contributing guidelines](../../CONTRIBUTING.md) for more information.
## License
Licensed under the Apache-2.0 License. See [LICENSE](LICENSE) for more information.