Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions content/docs/changelog/changelog-028.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,21 @@ import Image from 'next/image';
/>
Hey everyone. This was a session-and-CLI week.

The big one: sessions can now release themselves after sitting idle for however long you set, so you stop paying for tabs nobody's using. The CLI also grew up a bit — you can manage sessions and browse or install agent skills straight from it now. The rest is docs and API cleanup.
The big one: a browser session can now release itself when your agent goes quiet, so you stop paying for tabs nobody's using. The CLI also grew up a bit, with commands to manage sessions and browse or install agent skills straight from the terminal. The rest is docs and API cleanup.

### ⭐ New

#### Inactivity-based session timeouts

Set an inactivity timeout and idle sessions get released automatically. No more orphaned sessions running until the hard limit.
Set an inactivity timeout and the browser session releases itself once your agent goes quiet, instead of running until the hard limit.

#### CLI commands for sessions and agent skills

The Steel CLI now manages sessions and agent skills directly, including an interactive skills catalog and an `--all` install option.

### 🔧 Improvements

* The docs have a dedicated agent skills section now installation, authoring, and troubleshootingand the quickstart covers skills as part of setup.
* The docs have a dedicated agent skills section now, covering installation, authoring, and troubleshooting, and the quickstart walks through skills as part of setup.

* Docs pages support markdown content negotiation, so you can pull raw markdown straight from the site.

Expand All @@ -42,14 +42,8 @@ The Steel CLI now manages sessions and agent skills directly, including an inter

### 🐛 Bug Fixes

* Fixed docs pages that intermittently returned 500s when rendering raw markdown outside the prerender cache.

* Fixed `/changelog` so it redirects to the latest entry instead of leaning on a stale index source.

* Corrected billing credit grants and usage display so they match each plan's configured credits.

* Fixed Steel Browser fingerprint injection so launch configs that skip injection are respected.

### 🏡 Housekeeping

* Docs analytics moved to a shared GTM container, replacing the standalone Reo script setup.
* Fixed docs pages that intermittently returned 500s when rendering raw markdown outside the prerender cache.
51 changes: 49 additions & 2 deletions lib/source.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { execSync } from 'node:child_process';
import { existsSync, readFileSync } from 'node:fs';
import { existsSync, readdirSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
import { loader } from 'fumadocs-core/source';
import { attachFile, createOpenAPI } from 'fumadocs-openapi/server';
Expand All @@ -18,7 +18,7 @@ const customIcons = {

const icons = { ...lucideIcons, ...customIcons } as any;

const NEW_BADGE_DURATION = 10 * 24 * 60 * 60 * 1000;
const NEW_BADGE_DURATION = 7 * 24 * 60 * 60 * 1000;

// FIXME: feature flag to enable/disable git-based "new" badge detection
const ENABLE_GIT_NEW_DETECTION = false; // Set to true when ready to use
Expand Down Expand Up @@ -116,7 +116,54 @@ function getFileGitDate(filePath: string): Date | null {
return gitDate;
}

// Returns the `changelog-NNN` slug for a changelog entry, or null otherwise.
function getChangelogSlug(filePath: string): string | null {
return filePath.match(/changelog\/(changelog-\d+)\.mdx$/)?.[1] ?? null;
}

let latestChangelogSlugCache: string | null | undefined;

// The highest-numbered changelog entry on disk. Cached for the process since
// the set of changelog files is fixed at build time.
function getLatestChangelogSlug(): string | null {
if (latestChangelogSlugCache !== undefined) return latestChangelogSlugCache;

let latest: string | null = null;
let highest = -1;
try {
for (const entry of readdirSync(join(process.cwd(), 'content/docs/changelog'))) {
const match = entry.match(/^(changelog-(\d+))\.mdx$/);
if (!match) continue;
const num = Number(match[2]);
if (num > highest) {
highest = num;
latest = match[1];
}
}
} catch {
latest = null;
}

latestChangelogSlugCache = latest;
return latest;
}

function isPageNew(filePath: string, frontmatter?: any): boolean {
// Changelog entries get the NEW badge only on the most recent entry, and
// only while it's within the publish window. Publishing a newer changelog
// moves the badge forward; the previous entry loses it immediately.
const changelogSlug = getChangelogSlug(filePath);
if (changelogSlug) {
if (changelogSlug !== getLatestChangelogSlug()) return false;
if (frontmatter?.publishedAt) {
const publishDate = new Date(frontmatter.publishedAt);
if (isValidDate(publishDate)) {
return Date.now() - publishDate.getTime() < NEW_BADGE_DURATION;
}
}
return false;
}

if (frontmatter?.publishedAt) {
try {
const publishDate = new Date(frontmatter.publishedAt);
Expand Down
Loading