chore: add docs
This commit is contained in:
151
docs/Discoveries.md
Normal file
151
docs/Discoveries.md
Normal file
@@ -0,0 +1,151 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user