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
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ All notable changes to this project will be documented in this file.
- auth preflight helper for provider-backed commands
- lookup-resolution helpers for id-or-query flows, not-found outcomes, and ambiguous matches
- adapter contract helpers for capability checks and normalized adapter failures
- config convention helpers for env/profile loading and structured config diagnostics
- richer testing helpers for auth, lookup, adapter, config, and dry-run assertions

### Changed
- command and tool metadata now support descriptions, aliases, usage, and examples
- human failure output can now render structured auth guidance details, adapter failure metadata, and lookup candidate summaries
- README examples now show help-oriented command metadata, auth preflight usage, adapter contract patterns, and lookup resolution patterns
- human failure output can now render structured auth guidance details, adapter failure metadata, config diagnostics, and lookup candidate summaries
- README examples now show help-oriented command metadata, auth preflight usage, adapter contract patterns, config conventions, testing helpers, and lookup resolution patterns

## [0.1.3] - 2026-04-11

Expand Down
70 changes: 70 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ Helpers:
- `requireCapability`
- `adapterFailure`
- `unsupportedCapability`
- `defineProfile`
- `loadConfig`
- `validateConfig`
- `missingConfig`
- `malformedConfig`
- `selectProfile`
- `notFound`
- `ambiguousMatch`
- `resolveById`
Expand All @@ -146,6 +152,13 @@ Testing:
- `runTool`
- `expectOk`
- `expectFailure`
- `expectDryRun`
- `expectAuthFailure`
- `expectLookupFailure`
- `expectAdapterFailure`
- `expectConfigFailure`
- `authFailureFixture`
- `lookupCandidatesFixture`
- `fakeAdapter`

## Auth preflight
Expand Down Expand Up @@ -219,6 +232,34 @@ const tool = createTool({

Provider-specific SDK calls and object models should stay in the downstream repo. AgentTK only owns the contract boundary, capability checks, and normalized failure shapes.

## Config conventions

```ts
import { createTool, defineCommand, isFailure, loadConfig, ok } from 'agenttk'
import { z } from 'zod'

const schema = z.object({
account: z.string().min(1),
apiBaseUrl: z.string().url()
})

const config = loadConfig(schema, {
env: { apiBaseUrl: process.env.API_BASE_URL },
profiles: {
work: { account: 'team@example.com', apiBaseUrl: 'https://api.example.com' }
},
profile: 'work'
}, {
expected: '{"account":"team@example.com","apiBaseUrl":"https://api.example.com"}',
nextStep: 'Set API_BASE_URL or choose a valid profile'
})

if (isFailure(config)) return config
return ok({ type: 'config', record: config })
```

Load order is predictable: base config, then selected profile, then env overrides. AgentTK stays out of secrets management and provider-specific config policy.

## Lookup resolution

```ts
Expand Down Expand Up @@ -247,18 +288,47 @@ const tool = createTool({
})
```

## Testing helpers

Use the richer assertions when you want cheap confidence around framework primitives, not shell-heavy rechecks of every field by hand.

```ts
import test from 'node:test'
import { authFailureFixture, expectAuthFailure, requireAuth } from 'agenttk'

test('auth failure stays structured', async () => {
const auth = await requireAuth(authFailureFixture({
code: 'ACCOUNT_MISMATCH',
currentAccount: 'personal@example.com',
expectedAccount: 'team@example.com'
}))

expectAuthFailure(auth, {
code: 'ACCOUNT_MISMATCH',
provider: 'google',
currentAccount: 'personal@example.com',
expectedAccount: 'team@example.com'
})
})
```

Keep using plain `runTool(...)` tests for command wiring and output mode checks. Use the richer helpers when you want fast, data-first checks around auth, lookup, dry-run, adapter, and config behavior.

## Examples

- `examples/minimal-cli/`
- `examples/tasks-cli/`
- `examples/adapter-cli/`
- `examples/config-cli/`
- `examples/testing-fixtures/`

```bash
node examples/minimal-cli/index.mjs hello --json
node examples/minimal-cli/index.mjs help
node examples/tasks-cli/index.mjs add --title "Send estimate" --dry-run --json
node examples/tasks-cli/index.mjs add
node examples/adapter-cli/index.mjs status --json
node examples/config-cli/index.mjs show --profile work
```

## Development
Expand Down
8 changes: 8 additions & 0 deletions examples/config-cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# config-cli

Minimal example showing environment-backed config loading, named profiles, and structured config diagnostics.

```bash
node examples/config-cli/index.mjs show --json
node examples/config-cli/index.mjs show --profile work
```
67 changes: 67 additions & 0 deletions examples/config-cli/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { z } from 'zod'
import { createTool, defineCommand, isFailure, loadConfig, ok } from 'agenttk'

const schema = z.object({
account: z.string().min(1),
region: z.string().min(1),
apiBaseUrl: z.string().url()
})

function parseFlags(rawArgs) {
const input = { profile: undefined }

for (let i = 0; i < rawArgs.length; i += 1) {
const arg = rawArgs[i]
if (arg === '--profile') {
input.profile = rawArgs[i + 1]
i += 1
}
}

return input
}

const profiles = {
work: {
account: 'team@example.com',
region: 'us',
apiBaseUrl: 'https://api.example.com'
},
personal: {
account: 'me@example.com',
region: 'us',
apiBaseUrl: 'https://personal.example.com'
}
}

const envConfig = {
account: process.env.CONFIG_DEMO_ACCOUNT,
region: process.env.CONFIG_DEMO_REGION,
apiBaseUrl: process.env.CONFIG_DEMO_API_BASE_URL
}

const tool = createTool({
name: 'config-demo',
commands: [
defineCommand({
name: 'show',
description: 'Load config from env and optional named profiles',
handler: async ({ rawArgs }) => {
const flags = parseFlags(rawArgs)
const config = loadConfig(schema, {
env: envConfig,
profiles,
profile: flags.profile
}, {
expected: '{"account":"team@example.com","region":"us","apiBaseUrl":"https://api.example.com"}',
nextStep: 'Set CONFIG_DEMO_* env vars or run config-demo show --profile work'
})

if (isFailure(config)) return config
return ok({ type: 'config', record: config })
}
})
]
})

await tool.run(process.argv.slice(2))
23 changes: 23 additions & 0 deletions examples/testing-fixtures/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# testing-fixtures

Minimal downstream-style example of using AgentTK's richer testing helpers.

```ts
import test from 'node:test'
import { accountMismatch, authFailureFixture, expectAuthFailure, requireAuth } from 'agenttk'

test('auth preflight stays cheap to test', async () => {
const auth = await requireAuth(authFailureFixture({
code: 'ACCOUNT_MISMATCH',
currentAccount: 'personal@example.com',
expectedAccount: 'team@example.com'
}))

expectAuthFailure(auth, {
code: 'ACCOUNT_MISMATCH',
provider: 'google',
currentAccount: 'personal@example.com',
expectedAccount: 'team@example.com'
})
})
```
16 changes: 0 additions & 16 deletions openspec/changes/add-config-conventions/tasks.md

This file was deleted.

15 changes: 0 additions & 15 deletions openspec/changes/add-testing-fixtures/tasks.md

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## 1. Config primitives

- [x] 1.1 Define config loading helper patterns.
- [x] 1.2 Add validation helpers for missing or malformed config.
- [x] 1.3 Add profile/account naming conventions that stay provider-agnostic.

## 2. Docs and output

- [x] 2.1 Ensure config diagnostics are actionable in human mode.
- [x] 2.2 Preserve config diagnostic detail in JSON mode.
- [x] 2.3 Add examples for environment-backed and profile-backed config.

## 3. Verification

- [x] 3.1 Add tests for missing-config and malformed-config flows.
- [x] 3.2 Validate the OpenSpec change.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## MODIFIED Requirements
## ADDED Requirements

### Requirement: Lightweight testing kit
### Requirement: Rich primitive-aware testing helpers
The system SHALL provide lightweight testing helpers for AgentTK-based CLIs.

#### Scenario: Framework primitives have matching test helpers
Expand Down
15 changes: 15 additions & 0 deletions openspec/changes/archive/2026-04-12-add-testing-fixtures/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## 1. Fixture coverage

- [x] 1.1 Add reusable fixtures or assertions for auth failure scenarios.
- [x] 1.2 Add reusable fixtures or assertions for lookup ambiguity and not-found flows.
- [x] 1.3 Add richer helpers for dry-run and adapter-backed command verification.

## 2. Examples and docs

- [x] 2.1 Document when to use the richer test helpers versus plain command tests.
- [x] 2.2 Add at least one downstream-style example using the richer fixtures.

## 3. Verification

- [x] 3.1 Ensure the testing-kit spec reflects the new helper surface.
- [x] 3.2 Validate the OpenSpec change.
11 changes: 3 additions & 8 deletions openspec/specs/command-blocks/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,9 @@ TBD - created by archiving change add-agenttk-v0. Update Purpose after archive.
### Requirement: Validation helpers
The system SHALL provide reusable validation helpers for command inputs.

#### Scenario: Valid input passes through
- **WHEN** a command validates input against a declared schema and the input is valid
- **THEN** the helper returns the typed parsed value

#### Scenario: Invalid input returns a structured validation failure
- **WHEN** a command validates input against a declared schema and the input is invalid
- **THEN** the helper returns a structured failure with code `VALIDATION_ERROR`
- **AND** the failure message describes the validation problem without throwing an uncaught exception into the caller
#### Scenario: Config diagnostics reuse structured validation style
- **WHEN** a downstream tool validates environment or config inputs before command execution
- **THEN** AgentTK can return a structured failure with actionable guidance using the same predictable envelope style as other validation helpers

### Requirement: Corrective guidance in validation failures
The system SHALL support validation failures that include corrective guidance.
Expand Down
31 changes: 31 additions & 0 deletions openspec/specs/config-conventions/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# config-conventions Specification

## Purpose
TBD - created by archiving change add-config-conventions. Update Purpose after archive.
## Requirements
### Requirement: Config loading conventions
The system SHALL provide reusable conventions for loading config in AgentTK-based tools.

#### Scenario: Load config from declared inputs
- **WHEN** a downstream CLI loads configuration from environment variables, local config objects, or profile selection
- **THEN** AgentTK provides a narrow helper pattern that keeps the loading path predictable

### Requirement: Config diagnostics
The system SHALL support structured diagnostics for missing or malformed config.

#### Scenario: Required config is missing
- **WHEN** a downstream tool cannot find a required config value
- **THEN** AgentTK returns a structured failure that identifies the missing config input
- **AND** the payload can include corrective guidance for how to provide it

#### Scenario: Config value is malformed
- **WHEN** a downstream tool finds a config value but it fails validation
- **THEN** AgentTK returns a structured diagnostic failure rather than an uncaught exception

### Requirement: Provider-agnostic profile conventions
The system SHALL support generic profile or account naming conventions.

#### Scenario: Tool selects a named profile
- **WHEN** a downstream CLI chooses among named profiles or accounts
- **THEN** AgentTK provides a reusable convention that does not depend on any single provider domain

13 changes: 13 additions & 0 deletions openspec/specs/testing-kit/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,16 @@ The system SHALL keep the testing helpers lightweight in v0.
- **WHEN** AgentTK v0 is implemented
- **THEN** the testing kit does not require live UAT runners, network recording, snapshot orchestration, or process-level CLI spawning to satisfy the v0 contract

### Requirement: Rich primitive-aware testing helpers
The system SHALL provide lightweight testing helpers for AgentTK-based CLIs.

#### Scenario: Framework primitives have matching test helpers
- **WHEN** AgentTK introduces reusable primitives such as auth blocks, lookup resolution, dry-run helpers, or adapter contracts
- **THEN** the testing kit can expose matching lightweight fixtures or assertions
- **AND** downstream tools do not need to rebuild the same harness patterns repeatedly

#### Scenario: Data-first testing remains possible
- **WHEN** a downstream developer uses the richer testing kit helpers
- **THEN** they can still test command behavior through explicit inputs and outputs
- **AND** the testing kit does not require a heavyweight integration framework or snapshot system

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"build": "tsc -p tsconfig.json",
"check": "tsc -p tsconfig.json --noEmit",
"test": "node --import tsx --test test/*.test.ts",
"examples:smoke": "node examples/minimal-cli/index.mjs hello --json && node examples/tasks-cli/index.mjs add --title \"Send estimate\" --dry-run --json && node examples/tasks-cli/index.mjs add --title \"Send estimate\"",
"examples:smoke": "node examples/minimal-cli/index.mjs hello --json && node examples/tasks-cli/index.mjs add --title \"Send estimate\" --dry-run --json && node examples/tasks-cli/index.mjs add --title \"Send estimate\" && node examples/config-cli/index.mjs show --profile work --json && node examples/config-cli/index.mjs show --profile work",
"verify": "npm run build && npm test && npm run examples:smoke",
"prepublishOnly": "npm run verify"
},
Expand Down
Loading
Loading