chore: remove packages/cli/docs
This commit is contained in:
@@ -1,544 +0,0 @@
|
|||||||
# Output Architecture Design
|
|
||||||
|
|
||||||
This document describes the output abstraction layer for the Paseo CLI, enabling structured data output with multiple format options.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
Commands should return **structured data objects**, not formatted strings. A separate rendering layer transforms this data into the requested output format. This separation enables:
|
|
||||||
|
|
||||||
1. **Testability** - Tests verify structured data without parsing strings
|
|
||||||
2. **Flexibility** - Easy to add new output formats
|
|
||||||
3. **Consistency** - Uniform formatting across all commands
|
|
||||||
|
|
||||||
### Inspiration from Existing CLIs
|
|
||||||
|
|
||||||
This design draws from patterns in established CLIs:
|
|
||||||
|
|
||||||
- **Docker CLI** - Uses Go templates with `--format` flag, provides `table` and `json` directives
|
|
||||||
- **kubectl** - Supports `-o json`, `-o yaml`, `-o wide`, and custom columns
|
|
||||||
- **GitHub CLI** - Uses `--json` with field selection, plus `--jq` and `--template` post-processors
|
|
||||||
|
|
||||||
Sources:
|
|
||||||
- [Docker CLI Formatting](https://docs.docker.com/engine/cli/formatting/)
|
|
||||||
- [kubectl Output Formatting](https://www.baeldung.com/ops/kubectl-output-format)
|
|
||||||
- [GitHub CLI Formatting](https://cli.github.com/manual/gh_help_formatting)
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ Command Execution │
|
|
||||||
│ │
|
|
||||||
│ parseArgs() → executeCommand() → CommandResult<T> │
|
|
||||||
└─────────────────────────────────┬───────────────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ Output Renderer │
|
|
||||||
│ │
|
|
||||||
│ CommandResult<T> + OutputOptions → formatted string │
|
|
||||||
│ │
|
|
||||||
│ Renderers: │
|
|
||||||
│ - TableRenderer (default, human-readable) │
|
|
||||||
│ - JsonRenderer (machine-readable) │
|
|
||||||
│ - YamlRenderer (machine-readable) │
|
|
||||||
│ - QuietRenderer (minimal, IDs only) │
|
|
||||||
└─────────────────────────────────┬───────────────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ stdout/stderr │
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
## Type Definitions
|
|
||||||
|
|
||||||
### Output Options
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
type OutputFormat = 'table' | 'json' | 'yaml'
|
|
||||||
|
|
||||||
interface OutputOptions {
|
|
||||||
format: OutputFormat
|
|
||||||
quiet: boolean // Minimal output (IDs only)
|
|
||||||
noHeaders: boolean // Omit table headers
|
|
||||||
noColor: boolean // Disable color output
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Command Result
|
|
||||||
|
|
||||||
Commands return a `CommandResult<T>` that contains structured data plus metadata for formatting:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
interface CommandResult<T> {
|
|
||||||
/** The structured data to render */
|
|
||||||
data: T
|
|
||||||
|
|
||||||
/** Schema describing how to render this data */
|
|
||||||
schema: OutputSchema<T>
|
|
||||||
}
|
|
||||||
|
|
||||||
interface OutputSchema<T> {
|
|
||||||
/** Field to use for quiet mode (--quiet outputs just this) */
|
|
||||||
idField: keyof T | ((item: T) => string)
|
|
||||||
|
|
||||||
/** Column definitions for table output */
|
|
||||||
columns: ColumnDef<T>[]
|
|
||||||
|
|
||||||
/** Optional: transform data before JSON/YAML output */
|
|
||||||
serialize?: (data: T) => unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ColumnDef<T> {
|
|
||||||
/** Header text for the column */
|
|
||||||
header: string
|
|
||||||
|
|
||||||
/** Field key or accessor function */
|
|
||||||
field: keyof T | ((item: T) => unknown)
|
|
||||||
|
|
||||||
/** Optional width hint (characters) */
|
|
||||||
width?: number
|
|
||||||
|
|
||||||
/** Optional alignment */
|
|
||||||
align?: 'left' | 'right' | 'center'
|
|
||||||
|
|
||||||
/** Optional color function */
|
|
||||||
color?: (value: unknown, item: T) => string | undefined
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Single vs List Results
|
|
||||||
|
|
||||||
Commands may return either a single item or a list:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// For commands returning a single item (e.g., `agent show <id>`)
|
|
||||||
interface SingleResult<T> extends CommandResult<T> {
|
|
||||||
type: 'single'
|
|
||||||
data: T
|
|
||||||
}
|
|
||||||
|
|
||||||
// For commands returning a list (e.g., `agent list`)
|
|
||||||
interface ListResult<T> extends CommandResult<T[]> {
|
|
||||||
type: 'list'
|
|
||||||
data: T[]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Union type for command handlers
|
|
||||||
type AnyCommandResult<T> = SingleResult<T> | ListResult<T>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example: Agent List Command
|
|
||||||
|
|
||||||
### Data Type
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
interface AgentListItem {
|
|
||||||
id: string
|
|
||||||
title: string
|
|
||||||
status: 'running' | 'idle' | 'error'
|
|
||||||
provider: string
|
|
||||||
cwd: string
|
|
||||||
createdAt: string
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Schema Definition
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const agentListSchema: OutputSchema<AgentListItem> = {
|
|
||||||
idField: 'id',
|
|
||||||
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
header: 'ID',
|
|
||||||
field: 'id',
|
|
||||||
width: 8,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'TITLE',
|
|
||||||
field: 'title',
|
|
||||||
width: 30,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'STATUS',
|
|
||||||
field: 'status',
|
|
||||||
color: (value) => {
|
|
||||||
switch (value) {
|
|
||||||
case 'running': return 'green'
|
|
||||||
case 'idle': return 'dim'
|
|
||||||
case 'error': return 'red'
|
|
||||||
default: return undefined
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'PROVIDER',
|
|
||||||
field: 'provider',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'CWD',
|
|
||||||
field: 'cwd',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Command Implementation
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
async function agentListCommand(options: CommandOptions): Promise<ListResult<AgentListItem>> {
|
|
||||||
const client = await connectToDaemon(options)
|
|
||||||
const agents = client.listAgents()
|
|
||||||
|
|
||||||
const data = agents.map(agent => ({
|
|
||||||
id: agent.agentId,
|
|
||||||
title: agent.title ?? '(untitled)',
|
|
||||||
status: mapLifecycleStatus(agent.lifecycle),
|
|
||||||
provider: agent.agentType,
|
|
||||||
cwd: agent.cwd,
|
|
||||||
createdAt: agent.createdAt,
|
|
||||||
}))
|
|
||||||
|
|
||||||
return {
|
|
||||||
type: 'list',
|
|
||||||
data,
|
|
||||||
schema: agentListSchema,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Renderer Implementations
|
|
||||||
|
|
||||||
### Table Renderer
|
|
||||||
|
|
||||||
The default renderer for human-readable output:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
function renderTable<T>(result: ListResult<T>, options: OutputOptions): string {
|
|
||||||
const { data, schema } = result
|
|
||||||
|
|
||||||
if (data.length === 0) {
|
|
||||||
return '' // Or a "no items" message
|
|
||||||
}
|
|
||||||
|
|
||||||
const rows: string[][] = []
|
|
||||||
|
|
||||||
// Add header row (unless noHeaders)
|
|
||||||
if (!options.noHeaders) {
|
|
||||||
rows.push(schema.columns.map(col => col.header))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add data rows
|
|
||||||
for (const item of data) {
|
|
||||||
const row = schema.columns.map(col => {
|
|
||||||
const value = typeof col.field === 'function'
|
|
||||||
? col.field(item)
|
|
||||||
: item[col.field]
|
|
||||||
return String(value ?? '')
|
|
||||||
})
|
|
||||||
rows.push(row)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate column widths
|
|
||||||
const widths = schema.columns.map((col, i) => {
|
|
||||||
const maxContent = Math.max(...rows.map(row => stripAnsi(row[i]).length))
|
|
||||||
return col.width ? Math.max(col.width, maxContent) : maxContent
|
|
||||||
})
|
|
||||||
|
|
||||||
// Format and join
|
|
||||||
return rows.map((row, rowIndex) => {
|
|
||||||
return row.map((cell, colIndex) => {
|
|
||||||
const col = schema.columns[colIndex]
|
|
||||||
const width = widths[colIndex]
|
|
||||||
let formatted = padCell(cell, width, col.align ?? 'left')
|
|
||||||
|
|
||||||
// Apply color (skip header row)
|
|
||||||
if (rowIndex > 0 && col.color && !options.noColor) {
|
|
||||||
const colorName = col.color(cell, data[rowIndex - 1])
|
|
||||||
if (colorName) {
|
|
||||||
formatted = applyColor(formatted, colorName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return formatted
|
|
||||||
}).join(' ')
|
|
||||||
}).join('\n')
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### JSON Renderer
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
function renderJson<T>(result: AnyCommandResult<T>, options: OutputOptions): string {
|
|
||||||
const { data, schema } = result
|
|
||||||
const output = schema.serialize ? schema.serialize(data) : data
|
|
||||||
return JSON.stringify(output, null, 2)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### YAML Renderer
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import YAML from 'yaml'
|
|
||||||
|
|
||||||
function renderYaml<T>(result: AnyCommandResult<T>, options: OutputOptions): string {
|
|
||||||
const { data, schema } = result
|
|
||||||
const output = schema.serialize ? schema.serialize(data) : data
|
|
||||||
return YAML.stringify(output)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Quiet Renderer
|
|
||||||
|
|
||||||
Returns only the ID field(s):
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
function renderQuiet<T>(result: AnyCommandResult<T>, options: OutputOptions): string {
|
|
||||||
const { data, schema } = result
|
|
||||||
const getId = typeof schema.idField === 'function'
|
|
||||||
? schema.idField
|
|
||||||
: (item: T) => String(item[schema.idField as keyof T])
|
|
||||||
|
|
||||||
if (result.type === 'single') {
|
|
||||||
return getId(data as T)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (data as T[]).map(getId).join('\n')
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Error Output
|
|
||||||
|
|
||||||
Errors are handled separately from success output and always go to stderr:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
interface CommandError {
|
|
||||||
code: string // Machine-readable error code
|
|
||||||
message: string // Human-readable message
|
|
||||||
details?: unknown // Additional context
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderError(error: CommandError, options: OutputOptions): string {
|
|
||||||
if (options.format === 'json') {
|
|
||||||
return JSON.stringify({ error }, null, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.format === 'yaml') {
|
|
||||||
return YAML.stringify({ error })
|
|
||||||
}
|
|
||||||
|
|
||||||
// Table/default format
|
|
||||||
return chalk.red(`Error: ${error.message}`)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Streaming Output
|
|
||||||
|
|
||||||
For commands like `logs -f` and `attach`, streaming requires a different approach:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
interface StreamingResult<T> {
|
|
||||||
type: 'stream'
|
|
||||||
schema: OutputSchema<T>
|
|
||||||
|
|
||||||
/** Async iterator yielding items as they arrive */
|
|
||||||
stream: AsyncIterable<T>
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Streaming Renderer
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
async function renderStream<T>(
|
|
||||||
result: StreamingResult<T>,
|
|
||||||
options: OutputOptions,
|
|
||||||
write: (chunk: string) => void
|
|
||||||
): Promise<void> {
|
|
||||||
const { stream, schema } = result
|
|
||||||
|
|
||||||
// For JSON, output newline-delimited JSON (NDJSON)
|
|
||||||
if (options.format === 'json') {
|
|
||||||
for await (const item of stream) {
|
|
||||||
write(JSON.stringify(item) + '\n')
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// For table format, render each item as a row
|
|
||||||
let headerWritten = false
|
|
||||||
for await (const item of stream) {
|
|
||||||
if (!headerWritten && !options.noHeaders) {
|
|
||||||
write(renderTableHeader(schema) + '\n')
|
|
||||||
headerWritten = true
|
|
||||||
}
|
|
||||||
write(renderTableRow(item, schema, options) + '\n')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### NDJSON for Streaming
|
|
||||||
|
|
||||||
When `--json` (or `--format json`) is used with streaming commands, output is newline-delimited JSON (NDJSON) for easy parsing:
|
|
||||||
|
|
||||||
```
|
|
||||||
{"timestamp":"2024-01-15T10:30:00Z","type":"stdout","content":"Hello"}
|
|
||||||
{"timestamp":"2024-01-15T10:30:01Z","type":"stdout","content":"World"}
|
|
||||||
```
|
|
||||||
|
|
||||||
This allows consumers to process output line-by-line without buffering the entire stream.
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
### Testing Structured Data
|
|
||||||
|
|
||||||
Tests can directly verify the structured data without parsing formatted output:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
describe('agent list', () => {
|
|
||||||
it('returns agents with correct structure', async () => {
|
|
||||||
const result = await agentListCommand({ host: testHost })
|
|
||||||
|
|
||||||
expect(result.type).toBe('list')
|
|
||||||
expect(result.data).toHaveLength(2)
|
|
||||||
expect(result.data[0]).toMatchObject({
|
|
||||||
id: expect.any(String),
|
|
||||||
title: 'Test Agent',
|
|
||||||
status: 'running',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('uses correct schema for table output', async () => {
|
|
||||||
const result = await agentListCommand({ host: testHost })
|
|
||||||
|
|
||||||
expect(result.schema.idField).toBe('id')
|
|
||||||
expect(result.schema.columns.map(c => c.header)).toEqual([
|
|
||||||
'ID', 'TITLE', 'STATUS', 'PROVIDER', 'CWD'
|
|
||||||
])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
### Testing Renderers
|
|
||||||
|
|
||||||
Renderer tests verify formatting independently:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
describe('table renderer', () => {
|
|
||||||
it('formats data as aligned table', () => {
|
|
||||||
const result: ListResult<AgentListItem> = {
|
|
||||||
type: 'list',
|
|
||||||
data: [
|
|
||||||
{ id: 'abc123', title: 'Agent 1', status: 'running', ... },
|
|
||||||
{ id: 'def456', title: 'Agent 2', status: 'idle', ... },
|
|
||||||
],
|
|
||||||
schema: agentListSchema,
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = renderTable(result, { format: 'table', quiet: false, ... })
|
|
||||||
|
|
||||||
expect(output).toContain('ID')
|
|
||||||
expect(output).toContain('abc123')
|
|
||||||
expect(output).toContain('Agent 1')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
### E2E Tests
|
|
||||||
|
|
||||||
E2E tests can verify both structured data (for correctness) and formatted output (for UX):
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// Verify JSON output is valid and contains expected data
|
|
||||||
test('agent list --json', async () => {
|
|
||||||
const output = await ctx.paseo('agent list --json')
|
|
||||||
const data = JSON.parse(output.stdout)
|
|
||||||
|
|
||||||
expect(data).toBeInstanceOf(Array)
|
|
||||||
expect(data[0]).toHaveProperty('id')
|
|
||||||
})
|
|
||||||
|
|
||||||
// Verify table output looks correct
|
|
||||||
test('agent list shows table headers', async () => {
|
|
||||||
const output = await ctx.paseo('agent list')
|
|
||||||
|
|
||||||
expect(output.stdout).toMatch(/ID\s+TITLE\s+STATUS/)
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
## Integration with Command Framework
|
|
||||||
|
|
||||||
### Global Options
|
|
||||||
|
|
||||||
Add output options to the root command:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
program
|
|
||||||
.option('-o, --format <format>', 'Output format: table, json, yaml', 'table')
|
|
||||||
.option('--json', 'Output in JSON format (alias for --format json)')
|
|
||||||
.option('-q, --quiet', 'Minimal output (IDs only)')
|
|
||||||
.option('--no-headers', 'Omit table headers')
|
|
||||||
.option('--no-color', 'Disable colored output')
|
|
||||||
```
|
|
||||||
|
|
||||||
### Command Handler Wrapper
|
|
||||||
|
|
||||||
A wrapper function handles the rendering:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
function withOutput<T>(
|
|
||||||
handler: (options: CommandOptions) => Promise<AnyCommandResult<T>>
|
|
||||||
) {
|
|
||||||
return async (options: CommandOptions) => {
|
|
||||||
try {
|
|
||||||
const result = await handler(options)
|
|
||||||
const output = render(result, options)
|
|
||||||
process.stdout.write(output + '\n')
|
|
||||||
} catch (error) {
|
|
||||||
const errorOutput = renderError(toCommandError(error), options)
|
|
||||||
process.stderr.write(errorOutput + '\n')
|
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Usage
|
|
||||||
program
|
|
||||||
.command('list')
|
|
||||||
.description('List agents')
|
|
||||||
.action(withOutput(agentListCommand))
|
|
||||||
```
|
|
||||||
|
|
||||||
## Implementation Plan
|
|
||||||
|
|
||||||
1. **Phase 1: Core Types**
|
|
||||||
- Define `CommandResult`, `OutputSchema`, `ColumnDef` types
|
|
||||||
- Implement basic table renderer
|
|
||||||
- Implement JSON renderer
|
|
||||||
|
|
||||||
2. **Phase 2: Integration**
|
|
||||||
- Add global output options to CLI
|
|
||||||
- Create `withOutput` wrapper
|
|
||||||
- Migrate `daemon status` command as proof of concept
|
|
||||||
|
|
||||||
3. **Phase 3: Full Coverage**
|
|
||||||
- Add YAML renderer
|
|
||||||
- Add quiet renderer
|
|
||||||
- Migrate all existing commands
|
|
||||||
|
|
||||||
4. **Phase 4: Streaming**
|
|
||||||
- Implement `StreamingResult` type
|
|
||||||
- Add streaming renderers
|
|
||||||
- Apply to `logs` and `attach` commands
|
|
||||||
|
|
||||||
## Open Questions
|
|
||||||
|
|
||||||
1. **Should we support Go templates like Docker/gh?** This adds flexibility but also complexity. For v1, predefined formats are likely sufficient.
|
|
||||||
|
|
||||||
2. **How to handle nested data in tables?** Options:
|
|
||||||
- Flatten (e.g., `config.timeout` becomes `TIMEOUT` column)
|
|
||||||
- Skip in table, include in JSON/YAML
|
|
||||||
- Use nested tables for detail views
|
|
||||||
|
|
||||||
3. **Should quiet mode support custom fields?** e.g., `--quiet=title` to output titles instead of IDs.
|
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
# CLI Type Audit (commands)
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
- Audited `packages/cli/src/commands/**` for inline type/interface definitions.
|
|
||||||
- Checked `@getpaseo/server` exports from `packages/server/src/server/exports.ts`.
|
|
||||||
- Note: `packages/server/src/index.ts` does **not** exist in this repo; the package export entrypoint is `./src/server/exports.ts` per `packages/server/package.json`.
|
|
||||||
|
|
||||||
## Server Exports (current)
|
|
||||||
`packages/server/src/server/exports.ts` exports:
|
|
||||||
- `createPaseoDaemon`, `PaseoDaemon`, `PaseoDaemonConfig`
|
|
||||||
- `loadConfig`, `resolvePaseoHome`
|
|
||||||
- `createRootLogger`, `LogLevel`, `LogFormat`
|
|
||||||
- `loadPersistedConfig`, `PersistedConfig`
|
|
||||||
- `DaemonClient`, `DaemonClientConfig`, `ConnectionState`, `DaemonEvent`
|
|
||||||
|
|
||||||
No agent snapshot/timeline/permission/message types are exported.
|
|
||||||
|
|
||||||
## Findings by File
|
|
||||||
|
|
||||||
### `packages/cli/src/commands/agent/run.ts`
|
|
||||||
Inline types:
|
|
||||||
- `AgentSnapshot` (id/provider/cwd/createdAt/status/title)
|
|
||||||
|
|
||||||
Recommended server type:
|
|
||||||
- `AgentSnapshotPayload` from `packages/server/src/shared/messages.ts` (daemon client returns this shape). **Not exported** from `@getpaseo/server` today.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
- `AgentRunResult` is CLI output; no server type expected.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### `packages/cli/src/commands/agent/ps.ts`
|
|
||||||
Inline types:
|
|
||||||
- `AgentSnapshot` (id/provider/cwd/createdAt/status/title/archivedAt?)
|
|
||||||
|
|
||||||
Recommended server type:
|
|
||||||
- `AgentSnapshotPayload` (includes `archivedAt` and full snapshot fields). **Not exported**.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
- `AgentListItem` is CLI output; no server type expected.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### `packages/cli/src/commands/agent/send.ts`
|
|
||||||
Inline types:
|
|
||||||
- `AgentSnapshot` (id/provider/cwd/createdAt/status/title)
|
|
||||||
|
|
||||||
Recommended server type:
|
|
||||||
- `AgentSnapshotPayload`. **Not exported**.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
- `AgentSendResult` is CLI output; no server type expected.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### `packages/cli/src/commands/agent/inspect.ts`
|
|
||||||
Inline types:
|
|
||||||
- `AgentSnapshotLike` (snapshot fields + `lastUsage`, `capabilities`, `availableModes`, `pendingPermissions`)
|
|
||||||
|
|
||||||
Recommended server types:
|
|
||||||
- `AgentSnapshotPayload` (overall snapshot shape). **Not exported**.
|
|
||||||
- `AgentUsage` for `lastUsage`. **Not exported** (in `packages/server/src/server/agent/agent-sdk-types.ts`).
|
|
||||||
- `AgentCapabilityFlags` for `capabilities`. **Not exported**.
|
|
||||||
- `AgentMode` for `availableModes`. **Not exported**.
|
|
||||||
- `AgentPermissionRequest` for `pendingPermissions`. **Not exported**.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
- `pendingPermissions` uses `{ id, tool?: string }` but server type is `AgentPermissionRequest` with `{ name, kind, ... }`; current CLI projection is lossy and field names don’t match (`tool` vs `name`).
|
|
||||||
- `AgentInspect` and `InspectRow` are CLI output types.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### `packages/cli/src/commands/agent/logs.ts`
|
|
||||||
Inline types:
|
|
||||||
- `AgentStreamSnapshotMessage`
|
|
||||||
- `AgentStreamMessage`
|
|
||||||
- Timeline item shape in `formatTimelineItem` and `extractTimelineFrom*` helpers (`{ type: string; ... }`)
|
|
||||||
|
|
||||||
Recommended server types:
|
|
||||||
- `AgentStreamSnapshotMessage` from `packages/server/src/shared/messages.ts`. **Not exported**.
|
|
||||||
- `AgentStreamMessage` from `packages/server/src/shared/messages.ts`. **Not exported**.
|
|
||||||
- `AgentStreamEventPayload` from `packages/server/src/shared/messages.ts` (for `event` typing). **Not exported**.
|
|
||||||
- `AgentTimelineItem` from `packages/server/src/server/agent/agent-sdk-types.ts` (for timeline item shape). **Not exported**.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
- These are WebSocket message types; they should come from shared message definitions to avoid drift.
|
|
||||||
- `LogEntry` is CLI output.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### `packages/cli/src/commands/agent/mode.ts`
|
|
||||||
Inline types:
|
|
||||||
- `ModeListItem` (id/label/description)
|
|
||||||
- `SetModeResult` (agentId/mode)
|
|
||||||
|
|
||||||
Recommended server type:
|
|
||||||
- `ModeListItem` duplicates the shape of `AgentMode` (id/label/description) from `packages/server/src/server/agent/agent-sdk-types.ts`. **Not exported**.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
- `SetModeResult` is CLI output.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### `packages/cli/src/commands/daemon/start.ts`
|
|
||||||
Inline types:
|
|
||||||
- `StartOptions` (CLI flags)
|
|
||||||
|
|
||||||
Server type usage:
|
|
||||||
- CLI-only; no server type expected.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### `packages/cli/src/commands/daemon/status.ts`
|
|
||||||
Inline types:
|
|
||||||
- `DaemonStatus`
|
|
||||||
- `StatusRow`
|
|
||||||
|
|
||||||
Server type usage:
|
|
||||||
- CLI-only; no server type expected.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### `packages/cli/src/commands/daemon/restart.ts`
|
|
||||||
Inline types:
|
|
||||||
- `RestartResult`
|
|
||||||
|
|
||||||
Server type usage:
|
|
||||||
- CLI-only; no server type expected.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### `packages/cli/src/commands/daemon/stop.ts`
|
|
||||||
Inline types:
|
|
||||||
- `StopResult`
|
|
||||||
|
|
||||||
Server type usage:
|
|
||||||
- CLI-only; no server type expected.
|
|
||||||
|
|
||||||
## Gaps in `@getpaseo/server` Exports (needed for CLI cleanup)
|
|
||||||
To replace inline types in CLI commands, `@getpaseo/server` would need to export (directly or re-export):
|
|
||||||
- From `packages/server/src/shared/messages.ts`:
|
|
||||||
- `AgentSnapshotPayload`
|
|
||||||
- `AgentStreamEventPayload`
|
|
||||||
- `AgentStreamMessage`
|
|
||||||
- `AgentStreamSnapshotMessage`
|
|
||||||
- (optionally) `AgentStateMessage`, `SessionStateMessage`, `SessionOutboundMessage` if CLI starts typing daemon event queues more strictly
|
|
||||||
- From `packages/server/src/server/agent/agent-sdk-types.ts`:
|
|
||||||
- `AgentMode`
|
|
||||||
- `AgentUsage`
|
|
||||||
- `AgentCapabilityFlags`
|
|
||||||
- `AgentPermissionRequest`
|
|
||||||
- `AgentTimelineItem`
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
Primary inline types that should become server imports are the agent snapshot/timeline/message/permission/mode shapes in `agent/*` commands. All are defined in server shared or agent SDK types today but are not exported through `@getpaseo/server`.
|
|
||||||
Reference in New Issue
Block a user