Skip to content
Open
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
340 changes: 331 additions & 9 deletions docs/commands/agents.md

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,19 @@ Manage Netlify AI agent tasks

| Subcommand | description |
|:--------------------------- |:-----|
| [`agents:archive`](/commands/agents#agentsarchive) | Archive an agent task |
| [`agents:commit`](/commands/agents#agentscommit) | Commit an agent task’s changes directly to a branch |
| [`agents:create`](/commands/agents#agentscreate) | Create and run a new agent task on your site |
| [`agents:diff`](/commands/agents#agentsdiff) | Print the unified diff produced by an agent task |
| [`agents:follow-up`](/commands/agents#agentsfollow-up) | Send a follow-up prompt to an existing agent task |
| [`agents:list`](/commands/agents#agentslist) | List agent tasks for the current site |
| [`agents:open`](/commands/agents#agentsopen) | Open the agent task preview, dashboard, or pull request in a browser |
| [`agents:pr`](/commands/agents#agentspr) | Open a pull request for an agent task |
| [`agents:publish`](/commands/agents#agentspublish) | Publish an agent task’s changes to production |
| [`agents:redeploy`](/commands/agents#agentsredeploy) | Create a redeploy session that reapplies an existing diff (no AI inference) |
| [`agents:revert`](/commands/agents#agentsrevert) | Revert an agent task to a specific session (sessions after it are discarded) |
| [`agents:show`](/commands/agents#agentsshow) | Show details of a specific agent task |
| [`agents:stop`](/commands/agents#agentsstop) | Stop a running agent task |
| [`agents:stop`](/commands/agents#agentsstop) | Stop a running agent task or session |


### [api](/commands/api)
Expand Down
53 changes: 53 additions & 0 deletions src/commands/agents/agents-archive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { OptionValues } from 'commander'
import inquirer from 'inquirer'

import { chalk, exit, log, logAndThrowError, logJson } from '../../utils/command-helpers.js'
import { startSpinner, stopSpinner } from '../../lib/spinner.js'
import type BaseCommand from '../base-command.js'
import { createAgentsApi } from './api.js'

interface AgentArchiveOptions extends OptionValues {
json?: boolean
yes?: boolean
}

export const agentsArchive = async (id: string, options: AgentArchiveOptions, command: BaseCommand) => {
if (!id) return logAndThrowError('Agent task ID is required')
await command.authenticate()
const api = createAgentsApi(command.netlify)

if (!options.yes && !options.json) {
if (!process.stdin.isTTY) {
return logAndThrowError('Refusing to archive without --yes when stdin is not a TTY')
}
const { confirmed } = await inquirer.prompt<{ confirmed: boolean }>([
{
type: 'confirm',
name: 'confirmed',
message: `Archive agent task ${id}?`,
default: false,
},
])
if (!confirmed) return exit()
}

const spinner = startSpinner({ text: 'Archiving agent task...' })
try {
await api.archiveAgentRunner(id)
stopSpinner({ spinner })

const result = { success: true, id }
if (options.json) {
logJson(result)
return result
}

log(`${chalk.green('✓')} Agent task archived.`)
log(` Task ID: ${chalk.cyan(id)}`)
return result
} catch (error_) {
stopSpinner({ spinner, error: true })
const error = error_ as Error
return logAndThrowError(`Failed to archive: ${error.message}`)
}
}
59 changes: 59 additions & 0 deletions src/commands/agents/agents-commit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import type { OptionValues } from 'commander'
import inquirer from 'inquirer'

import { chalk, log, logAndThrowError, logJson } from '../../utils/command-helpers.js'
import { startSpinner, stopSpinner } from '../../lib/spinner.js'
import type BaseCommand from '../base-command.js'
import { createAgentsApi } from './api.js'

interface AgentCommitOptions extends OptionValues {
branch?: string
json?: boolean
}

export const agentsCommit = async (id: string, options: AgentCommitOptions, command: BaseCommand) => {
if (!id) return logAndThrowError('Agent task ID is required')
await command.authenticate()
const api = createAgentsApi(command.netlify)

let targetBranch = options.branch?.trim()
if (!targetBranch) {
if (!process.stdin.isTTY) {
return logAndThrowError('--branch is required when stdin is not a TTY')
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
const { branchInput } = await inquirer.prompt<{ branchInput: string }>([
{
type: 'input',
name: 'branchInput',
message: 'Which branch should the agent commit to?',
validate: (input: string) => (input.trim().length > 0 ? true : 'Branch name is required'),
},
])
targetBranch = branchInput.trim()
}

const spinner = startSpinner({ text: `Committing to ${targetBranch}...` })
try {
const runner = await api.agentRunnerCommitToBranch(id, targetBranch)
stopSpinner({ spinner })

if (options.json) {
logJson(runner)
return runner
}

if (runner.merge_commit_error) {
log(`${chalk.red('✗')} Commit failed: ${runner.merge_commit_error}`)
return runner
}

log(`${chalk.green('✓')} Committed to ${chalk.cyan(targetBranch)}`)
log()
if (runner.merge_commit_sha) log(` SHA: ${chalk.cyan(runner.merge_commit_sha)}`)
return runner
} catch (error_) {
stopSpinner({ spinner, error: true })
const error = error_ as Error
return logAndThrowError(`Failed to commit: ${error.message}`)
}
}
Loading
Loading