152 lines
3.5 KiB
Markdown
152 lines
3.5 KiB
Markdown
# Discoveries
|
|
|
|
Empirical learnings from implementation that future sessions should know.
|
|
|
|
## Zod v4 Specifics
|
|
|
|
### `.default()` on Nested Objects
|
|
|
|
Zod v4 requires factory functions for nested object defaults, and the factory must return the **full output type** (not just `{}`):
|
|
|
|
```typescript
|
|
// ❌ Wrong - empty object won't match the schema
|
|
const Config = z.object({
|
|
nested: NestedSchema.default({}),
|
|
});
|
|
|
|
// ✅ Correct - factory returning full type
|
|
const Config = z.object({
|
|
nested: NestedSchema.default(() => ({ field: value, ... })),
|
|
});
|
|
```
|
|
|
|
### `z.record()` Requires Two Arguments
|
|
|
|
```typescript
|
|
// ❌ Wrong
|
|
z.record(z.string())
|
|
|
|
// ✅ Correct
|
|
z.record(z.string(), z.unknown())
|
|
```
|
|
|
|
## AI SDK v6 Changes
|
|
|
|
| v4/v5 | v6 |
|
|
|-------|-----|
|
|
| `LanguageModelV2` | `LanguageModel` |
|
|
| `maxTokens` | `maxOutputTokens` |
|
|
| `maxSteps` | `stopWhen: stepCountIs(n)` |
|
|
| `usage.promptTokens` | `usage.inputTokens` |
|
|
| `usage.completionTokens` | `usage.outputTokens` |
|
|
|
|
## ollama-ai-provider Compatibility
|
|
|
|
`ollama-ai-provider` v1.2.0 returns `LanguageModelV1`, not the expected `LanguageModel` (v2/v3). Cast at call site:
|
|
|
|
```typescript
|
|
import { ollama } from 'ollama-ai-provider';
|
|
import type { LanguageModel } from 'ai';
|
|
|
|
const model = ollama('llama3.2') as unknown as LanguageModel;
|
|
```
|
|
|
|
## js-tiktoken API
|
|
|
|
```typescript
|
|
// ❌ Wrong (Python-style)
|
|
import { get_encoding } from 'js-tiktoken';
|
|
|
|
// ✅ Correct
|
|
import { getEncoding } from 'js-tiktoken';
|
|
```
|
|
|
|
## Bun/Node Globals
|
|
|
|
`Document` is not available as a global in Bun/Node. For DOM-like operations:
|
|
|
|
```typescript
|
|
// ❌ Wrong
|
|
function makeDocument(): Document { ... }
|
|
|
|
// ✅ Correct
|
|
function makePseudoDocument(): Record<string, unknown> { ... }
|
|
// Cast at call site if needed
|
|
```
|
|
|
|
## WebSocket Error Types
|
|
|
|
WebSocket `onerror` handler receives an `Event`, not an `Error`:
|
|
|
|
```typescript
|
|
socket.onerror = (err: Event) => {
|
|
console.error(`WebSocket error: ${err.type}`);
|
|
};
|
|
```
|
|
|
|
## Template Literals with Unknown Types
|
|
|
|
When interpolating `unknown` types in template literals, explicitly convert to string:
|
|
|
|
```typescript
|
|
// ❌ Risky - may throw
|
|
console.log(`Error: ${err}`);
|
|
|
|
// ✅ Safe
|
|
console.log(`Error: ${String(err)}`);
|
|
```
|
|
|
|
## Helper: strArg
|
|
|
|
For safely extracting string arguments from `Record<string, unknown>`:
|
|
|
|
```typescript
|
|
// src/agent/tools/base.ts
|
|
export function strArg(args: Record<string, unknown>, key: string, fallback = ''): string {
|
|
const val = args[key];
|
|
return typeof val === 'string' ? val : fallback;
|
|
}
|
|
```
|
|
|
|
Usage:
|
|
|
|
```typescript
|
|
// ❌ Verbose
|
|
const path = String(args['path'] ?? '');
|
|
|
|
// ✅ Cleaner
|
|
const path = strArg(args, 'path');
|
|
const timeout = parseInt(strArg(args, 'timeout', '30'), 10);
|
|
```
|
|
|
|
## Mattermost WebSocket
|
|
|
|
- Uses raw `WebSocket` + `fetch` (no mattermostdriver library)
|
|
- Auth via hello message with token
|
|
- Event types: `posted`, `post_edited`, `reaction_added`, etc.
|
|
- Group channel policy: `mention` (default), `open`, `allowlist`
|
|
|
|
## Session Persistence
|
|
|
|
- Format: JSONL (one JSON object per line)
|
|
- Location: `~/.nanobot/sessions/{sessionKey}.jsonl`
|
|
- Tool results truncated at 16,000 characters
|
|
- Memory consolidation triggered when approaching context window limit
|
|
|
|
## Retry Logic
|
|
|
|
`LLMProvider.chatWithRetry()` retries on:
|
|
- HTTP 429 (rate limit)
|
|
- HTTP 5xx (server errors)
|
|
- Timeouts
|
|
- Network errors
|
|
|
|
Max 3 attempts with exponential backoff.
|
|
|
|
## Config Precedence
|
|
|
|
1. CLI flags (`-c`, `-m`, `-w`, `-M`)
|
|
2. Environment variables (`NANOBOT_CONFIG`, `NANOBOT_MODEL`, `NANOBOT_WORKSPACE`)
|
|
3. Config file (`~/.nanobot/config.json`)
|
|
4. Zod schema defaults
|