# SDK Examples

Programmatic usage of xcsh-coding-agent via `createAgentSession()`.

## Examples

| File                       | Description                                    |
| -------------------------- | ---------------------------------------------- |
| `01-minimal.ts`            | Simplest usage with all defaults               |
| `02-custom-model.ts`       | Select model and thinking level                |
| `03-custom-prompt.ts`      | Replace or modify system prompt                |
| `04-skills.ts`             | Discover, filter, or replace skills            |
| `05-tools.ts`              | Built-in tools, custom tools                   |
| `06-hooks.ts`              | Logging, blocking, result modification         |
| `07-context-files.ts`      | AGENTS.md context files                        |
| `08-slash-commands.ts`     | File-based slash commands                      |
| `09-api-keys-and-oauth.ts` | API key resolution, OAuth config               |
| `10-settings.ts`           | Override compaction, retry, terminal settings  |
| `11-sessions.ts`           | In-memory, persistent, continue, list sessions |
| `12-full-control.ts`       | Replace everything, no discovery               |

## Running

```bash
cd packages/coding-agent
npx tsx examples/sdk/01-minimal.ts
```

## Quick Reference

```typescript
import { getModel } from "@f5xc-salesdemos/pi-ai";
import {
	AuthStorage,
	createAgentSession,
	discoverAuthStorage,
	discoverModels,
	discoverSkills,
	discoverHooks,
	discoverCustomTools,
	discoverContextFiles,
	discoverSlashCommands,
	loadSettings,
	buildSystemPrompt,
	ModelRegistry,
	SessionManager,
	BUILTIN_TOOLS,
	HIDDEN_TOOLS,
	createTools,
	ResolveTool,
} from "@f5xc-salesdemos/xcsh";

// Auth and models setup
const authStorage = discoverAuthStorage();
const modelRegistry = discoverModels(authStorage);

// Minimal
const { session } = await createAgentSession({ authStorage, modelRegistry });

// Custom model
const model = getModel("anthropic", "claude-opus-4-5");
const { session } = await createAgentSession({ model, thinkingLevel: "high", authStorage, modelRegistry });

// Modify prompt
const { session } = await createAgentSession({
	systemPrompt: (defaultPrompt) => defaultPrompt + "\n\nBe concise.",
	authStorage,
	modelRegistry,
});

// Read-only tools
const { session } = await createAgentSession({ toolNames: ["read", "grep", "find", "ls"], authStorage, modelRegistry });

// In-memory
const { session } = await createAgentSession({
	sessionManager: SessionManager.inMemory(),
	authStorage,
	modelRegistry,
});

// Full control
const customAuth = await AuthStorage.create("/my/app/agent.db");
customAuth.setRuntimeApiKey("anthropic", Bun.env.MY_KEY!);
const customRegistry = new ModelRegistry(customAuth);

const { session } = await createAgentSession({
	model,
	authStorage: customAuth,
	modelRegistry: customRegistry,
	systemPrompt: "You are helpful.",
	toolNames: ["read", "bash"],
	customTools: [{ tool: myTool }],
	hooks: [{ factory: myHook }],
	skills: [],
	contextFiles: [],
	slashCommands: [],
	sessionManager: SessionManager.inMemory(),
});

// Run prompts
session.subscribe((event) => {
	if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
		process.stdout.write(event.assistantMessageEvent.delta);
	}
});
await session.prompt("Hello");
```

## Resolve preview workflow (AST edit apply/discard)

`ast_edit` now always returns a preview. To finalize, call hidden `resolve` with a required reason.

- `action: "apply"` → commit pending preview changes
- `action: "discard"` → drop pending preview changes
- `reason: string` is required for both paths

`createAgentSession()` / `createTools()` include `resolve` automatically, even when filtering `toolNames`.
If you are composing tools manually, use `HIDDEN_TOOLS.resolve` (or `ResolveTool`) and wire the same `pendingActionStore`.

```typescript
const tools = await createTools(toolSession, ["ast_edit"]); // resolve is auto-included
const resolveTool = tools.find(t => t.name === "resolve") as ResolveTool;

await resolveTool.execute("call-1", {
  action: "apply",
  reason: "Preview matches expected replacements",
});
```
## Options

| Option                      | Default                       | Description                       |
| --------------------------- | ----------------------------- | --------------------------------- |
| `authStorage`               | `discoverAuthStorage()`       | Credential storage                |
| `modelRegistry`             | `discoverModels(authStorage)` | Model registry                    |
| `cwd`                       | `process.cwd()`               | Working directory                 |
| `agentDir`                  | `~/.xcsh/agent`                | Config directory                  |
| `model`                     | From settings/first available | Model to use                      |
| `thinkingLevel`             | From settings/"off"           | off, low, medium, high            |
| `systemPrompt`              | Discovered                    | String or `(default) => modified` |
| `toolNames`                 | All built-in tools            | Filter which tools to include     |
| `customTools`               | Discovered                    | Replaces discovery                |
| `additionalCustomToolPaths` | `[]`                          | Merge with discovery              |
| `hooks`                     | Discovered                    | Replaces discovery                |
| `additionalHookPaths`       | `[]`                          | Merge with discovery              |
| `skills`                    | Discovered                    | Skills for prompt                 |
| `contextFiles`              | Discovered                    | AGENTS.md files                   |
| `slashCommands`             | Discovered                    | File commands                     |
| `sessionManager`            | `SessionManager.create(cwd)`  | Persistence                       |
| `settingsManager`           | From agentDir                 | Settings overrides                |

## Events

```typescript
session.subscribe((event) => {
	switch (event.type) {
		case "message_update":
			if (event.assistantMessageEvent.type === "text_delta") {
				process.stdout.write(event.assistantMessageEvent.delta);
			}
			break;
		case "tool_execution_start":
			console.log(`Tool: ${event.toolName}`);
			break;
		case "tool_execution_end":
			console.log(`Result: ${event.result}`);
			break;
		case "agent_end":
			console.log("Done");
			break;
	}
});
```
