Add Agent SDK migration plan documentation
Documents the migration from @anthropic-ai/sdk to @anthropic-ai/claude-agent-sdk with phases, code examples, and progress tracking. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
636
docs/PLAN_MIGRATION_AGENT_SDK.md
Normal file
636
docs/PLAN_MIGRATION_AGENT_SDK.md
Normal file
@@ -0,0 +1,636 @@
|
|||||||
|
# Plan de Migration : API Anthropic → Claude Agent SDK TypeScript
|
||||||
|
|
||||||
|
> Version 1.1 - Janvier 2026
|
||||||
|
> Migration du backend Ikario vers le Claude Agent SDK
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Statut de Migration (mise à jour: 31 janvier 2026)
|
||||||
|
|
||||||
|
| Phase | Statut | Notes |
|
||||||
|
|-------|--------|-------|
|
||||||
|
| Phase 0 | ✅ TERMINÉ | Token OAuth configuré, SDK installé, backups créés |
|
||||||
|
| Phase 1 | ✅ TERMINÉ | `agentSdkService.js` créé avec toutes les fonctions |
|
||||||
|
| Phase 2 | ✅ TERMINÉ | `messages.js` et `claude.js` migrés vers SDK |
|
||||||
|
| Phase 3 | ✅ TERMINÉ | `@anthropic-ai/sdk` supprimé de package.json |
|
||||||
|
| Phase 4 | ⏳ À FAIRE | Tests et validation |
|
||||||
|
| Phase 5 | ⏳ À FAIRE | Mode AGENT auto-poïétique |
|
||||||
|
|
||||||
|
**Fichiers backupés** (`backups/pre-agent-sdk/`):
|
||||||
|
- `messages.js`, `claude.js`, `unifiedRagClient.js`, `tavilyMcpClient.js`, `toolExecutor.js`
|
||||||
|
|
||||||
|
**Note**: Les clients MCP (`unifiedRagClient.js`, etc.) sont conservés car utilisés par les routes directes (`/api/rag`, `/api/memory`, `/api/tavily`) pour l'accès hors-contexte chat.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contexte
|
||||||
|
|
||||||
|
### Objectif
|
||||||
|
|
||||||
|
Remplacer l'utilisation de l'API Anthropic (`@anthropic-ai/sdk` avec `ANTHROPIC_API_KEY`) par le Claude Agent SDK (`@anthropic-ai/claude-agent-sdk` avec `CLAUDE_CODE_OAUTH_TOKEN`).
|
||||||
|
|
||||||
|
### Pourquoi ?
|
||||||
|
|
||||||
|
1. **Unification** : Un seul SDK pour le chat ET les capacités agent
|
||||||
|
2. **Simplification** : Le SDK gère automatiquement la boucle tool-use
|
||||||
|
3. **MCP intégré** : Les serveurs MCP sont déclarés dans les options, plus besoin de clients séparés
|
||||||
|
4. **Auto-poïétique** : Permet à Ikario de se modifier lui-même (Phase 5)
|
||||||
|
|
||||||
|
### Décision architecturale
|
||||||
|
|
||||||
|
- **SDK choisi** : TypeScript (`@anthropic-ai/claude-agent-sdk`) - intégration directe dans le backend Node.js
|
||||||
|
- **Extended Thinking** : Le contenu "thinking" ne sera plus affiché au frontend (limitation du SDK)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Avant (actuel)
|
||||||
|
|
||||||
|
```
|
||||||
|
Frontend (React)
|
||||||
|
↓
|
||||||
|
Backend (Express)
|
||||||
|
↓
|
||||||
|
@anthropic-ai/sdk (ANTHROPIC_API_KEY)
|
||||||
|
↓
|
||||||
|
anthropic.messages.stream()
|
||||||
|
↓
|
||||||
|
Boucle while pour tool_use
|
||||||
|
↓
|
||||||
|
toolExecutor.js
|
||||||
|
↓
|
||||||
|
4 MCP Clients séparés:
|
||||||
|
├── unifiedRagClient.js (Weaviate)
|
||||||
|
├── tavilyMcpClient.js (Internet)
|
||||||
|
├── libraryRagMcpClient.js (Documents)
|
||||||
|
└── mcpClient.js (base)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Après (cible)
|
||||||
|
|
||||||
|
```
|
||||||
|
Frontend (React)
|
||||||
|
↓
|
||||||
|
Backend (Express)
|
||||||
|
↓
|
||||||
|
@anthropic-ai/claude-agent-sdk (CLAUDE_CODE_OAUTH_TOKEN)
|
||||||
|
↓
|
||||||
|
query() avec for await (streaming)
|
||||||
|
↓
|
||||||
|
Gestion automatique des tools par le SDK
|
||||||
|
↓
|
||||||
|
MCP servers dans options.mcpServers:
|
||||||
|
├── unified_rag (stdio → Python)
|
||||||
|
└── tavily (stdio → npx)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## SDK TypeScript - Référence
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @anthropic-ai/claude-agent-sdk
|
||||||
|
```
|
||||||
|
|
||||||
|
### API principale
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
||||||
|
|
||||||
|
for await (const message of query({
|
||||||
|
prompt: "Your prompt",
|
||||||
|
options: {
|
||||||
|
model: "claude-opus-4-5-20251101",
|
||||||
|
systemPrompt: "Tu es Ikario...",
|
||||||
|
maxThinkingTokens: 5000,
|
||||||
|
mcpServers: {
|
||||||
|
unified_rag: {
|
||||||
|
command: "python",
|
||||||
|
args: ["/path/to/mcp_server.py"],
|
||||||
|
env: { WEAVIATE_URL: "http://localhost:8080" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
allowedTools: ["mcp__unified_rag__*"],
|
||||||
|
permissionMode: "bypassPermissions"
|
||||||
|
}
|
||||||
|
})) {
|
||||||
|
if (message.type === 'result' && message.subtype === 'success') {
|
||||||
|
console.log(message.result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Types de messages
|
||||||
|
|
||||||
|
| Type | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| `system` (subtype: `init`) | Initialisation, liste des MCP servers |
|
||||||
|
| `assistant` | Réponse avec content blocks (text, tool_use) |
|
||||||
|
| `result` | Résultat final avec usage, cost, duration |
|
||||||
|
|
||||||
|
### Options disponibles
|
||||||
|
|
||||||
|
| Option | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `model` | string | Modèle Claude à utiliser |
|
||||||
|
| `systemPrompt` | string | Prompt système |
|
||||||
|
| `maxThinkingTokens` | number | Budget Extended Thinking (1024-32000) |
|
||||||
|
| `mcpServers` | object | Configuration des serveurs MCP |
|
||||||
|
| `allowedTools` | string[] | Outils autorisés (wildcards supportés) |
|
||||||
|
| `permissionMode` | string | `default`, `acceptEdits`, `bypassPermissions` |
|
||||||
|
| `cwd` | string | Répertoire de travail |
|
||||||
|
| `hooks` | object | Hooks PreToolUse, PostToolUse, etc. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phases de Migration
|
||||||
|
|
||||||
|
### Phase 0 : Préparation (1 jour)
|
||||||
|
|
||||||
|
| Tâche | Description | Commande/Action |
|
||||||
|
|-------|-------------|-----------------|
|
||||||
|
| 0.1 | Générer le token OAuth | `claude setup-token` |
|
||||||
|
| 0.2 | Ajouter au `.env` d'Ikario | `CLAUDE_CODE_OAUTH_TOKEN='...'` |
|
||||||
|
| 0.3 | Installer le SDK | `cd server && npm install @anthropic-ai/claude-agent-sdk` |
|
||||||
|
| 0.4 | Créer branche Git | `git checkout -b feature/agent-sdk-migration` |
|
||||||
|
| 0.5 | Backup fichiers actuels | Copier `messages.js`, `claude.js`, etc. |
|
||||||
|
|
||||||
|
**Validation Phase 0 :**
|
||||||
|
```bash
|
||||||
|
# Vérifier le token
|
||||||
|
echo $CLAUDE_CODE_OAUTH_TOKEN
|
||||||
|
|
||||||
|
# Vérifier le package
|
||||||
|
cd generations/ikario/server && npm ls @anthropic-ai/claude-agent-sdk
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 1 : Service Agent SDK (2-3 jours)
|
||||||
|
|
||||||
|
**Objectif** : Créer `server/services/agentSdkService.js`
|
||||||
|
|
||||||
|
#### 1.1 Structure du service
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// server/services/agentSdkService.js
|
||||||
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée une query Agent SDK avec la configuration Ikario
|
||||||
|
*/
|
||||||
|
export function createAgentQuery(prompt, ikarioOptions = {}) {
|
||||||
|
const {
|
||||||
|
model = "claude-sonnet-4-5-20250929",
|
||||||
|
systemPrompt = "",
|
||||||
|
thinkingBudget = 5000,
|
||||||
|
enableMemory = true,
|
||||||
|
enableTavily = false,
|
||||||
|
cwd = null,
|
||||||
|
additionalTools = []
|
||||||
|
} = ikarioOptions;
|
||||||
|
|
||||||
|
// Construire les MCP servers
|
||||||
|
const mcpServers = {};
|
||||||
|
const allowedTools = [];
|
||||||
|
|
||||||
|
if (enableMemory) {
|
||||||
|
mcpServers.unified_rag = {
|
||||||
|
command: "python",
|
||||||
|
args: [process.env.UNIFIED_RAG_SERVER_PATH],
|
||||||
|
env: {
|
||||||
|
WEAVIATE_URL: process.env.WEAVIATE_URL,
|
||||||
|
WEAVIATE_API_KEY: process.env.WEAVIATE_API_KEY || ""
|
||||||
|
}
|
||||||
|
};
|
||||||
|
allowedTools.push("mcp__unified_rag__*");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enableTavily && process.env.TAVILY_API_KEY) {
|
||||||
|
mcpServers.tavily = {
|
||||||
|
command: "npx",
|
||||||
|
args: ["-y", "@anthropic-ai/mcp-tavily"],
|
||||||
|
env: {
|
||||||
|
TAVILY_API_KEY: process.env.TAVILY_API_KEY
|
||||||
|
}
|
||||||
|
};
|
||||||
|
allowedTools.push("mcp__tavily__*");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ajouter les outils supplémentaires
|
||||||
|
allowedTools.push(...additionalTools);
|
||||||
|
|
||||||
|
return query({
|
||||||
|
prompt,
|
||||||
|
options: {
|
||||||
|
model,
|
||||||
|
systemPrompt,
|
||||||
|
maxThinkingTokens: thinkingBudget,
|
||||||
|
mcpServers,
|
||||||
|
allowedTools,
|
||||||
|
permissionMode: "bypassPermissions",
|
||||||
|
...(cwd && { cwd })
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construit le system prompt complet pour Ikario
|
||||||
|
*/
|
||||||
|
export function buildIkarioSystemPrompt(options = {}) {
|
||||||
|
const {
|
||||||
|
globalInstructions = "",
|
||||||
|
projectInstructions = "",
|
||||||
|
enableMemory = true,
|
||||||
|
enableTavily = false
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
const parts = [];
|
||||||
|
|
||||||
|
// Date/Heure
|
||||||
|
const now = new Date();
|
||||||
|
parts.push(`## Date et Heure Actuelles
|
||||||
|
Date: ${now.toLocaleDateString('fr-FR', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}
|
||||||
|
Heure: ${now.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' })}
|
||||||
|
Fuseau: ${Intl.DateTimeFormat().resolvedOptions().timeZone}`);
|
||||||
|
|
||||||
|
// Instructions globales
|
||||||
|
if (globalInstructions.trim()) {
|
||||||
|
parts.push(`## Instructions Globales\n${globalInstructions.trim()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instructions projet
|
||||||
|
if (projectInstructions.trim()) {
|
||||||
|
parts.push(`## Instructions Projet\n${projectInstructions.trim()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mémoire
|
||||||
|
if (enableMemory) {
|
||||||
|
parts.push(`## Mémoire
|
||||||
|
Tu as une mémoire persistante. Les conversations sont sauvegardées AUTOMATIQUEMENT.
|
||||||
|
Utilise add_thought pour tes réflexions internes, search_memories pour chercher.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internet
|
||||||
|
if (enableTavily) {
|
||||||
|
parts.push(`## Internet
|
||||||
|
Tu as accès à internet via Tavily: tavily_search (web), tavily_search_news (actualités).
|
||||||
|
Cite tes sources.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts.join('\n\n');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 1.2 Tests du service
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// server/services/__tests__/agentSdkService.test.js
|
||||||
|
import { createAgentQuery, buildIkarioSystemPrompt } from '../agentSdkService.js';
|
||||||
|
|
||||||
|
// Test basique
|
||||||
|
async function testBasicQuery() {
|
||||||
|
const q = createAgentQuery("Dis bonjour", {
|
||||||
|
model: "claude-sonnet-4-5-20250929",
|
||||||
|
systemPrompt: "Tu es Ikario.",
|
||||||
|
enableMemory: false,
|
||||||
|
enableTavily: false
|
||||||
|
});
|
||||||
|
|
||||||
|
for await (const message of q) {
|
||||||
|
console.log(message.type, message);
|
||||||
|
if (message.type === 'result') {
|
||||||
|
console.log("Résultat:", message.result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Validation Phase 1 :**
|
||||||
|
```bash
|
||||||
|
# Test manuel du service
|
||||||
|
node -e "
|
||||||
|
import('./services/agentSdkService.js').then(async ({ createAgentQuery }) => {
|
||||||
|
const q = createAgentQuery('Dis bonjour', { enableMemory: false });
|
||||||
|
for await (const m of q) {
|
||||||
|
if (m.type === 'result') console.log(m.result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 2 : Migration Route Messages (2-3 jours)
|
||||||
|
|
||||||
|
**Objectif** : Modifier `server/routes/messages.js` pour utiliser le SDK
|
||||||
|
|
||||||
|
#### 2.1 Changements principaux
|
||||||
|
|
||||||
|
| Avant | Après |
|
||||||
|
|-------|-------|
|
||||||
|
| `import Anthropic from '@anthropic-ai/sdk'` | `import { createAgentQuery, buildIkarioSystemPrompt } from '../services/agentSdkService.js'` |
|
||||||
|
| `const anthropic = new Anthropic({ apiKey })` | Supprimé (le SDK utilise CLAUDE_CODE_OAUTH_TOKEN) |
|
||||||
|
| `anthropic.messages.stream({...})` | `createAgentQuery(prompt, options)` |
|
||||||
|
| `stream.on('text', ...)` | `for await (const message of query)` |
|
||||||
|
| Boucle while tool_use | Supprimée (automatique) |
|
||||||
|
|
||||||
|
#### 2.2 Mapping SSE
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Nouveau code streaming
|
||||||
|
const q = createAgentQuery(content, {
|
||||||
|
model: conversation.model,
|
||||||
|
systemPrompt: buildIkarioSystemPrompt({
|
||||||
|
globalInstructions,
|
||||||
|
projectInstructions,
|
||||||
|
enableMemory: true,
|
||||||
|
enableTavily: conversation.enable_internet
|
||||||
|
}),
|
||||||
|
thinkingBudget: conversation.thinking_budget_tokens,
|
||||||
|
enableMemory: true,
|
||||||
|
enableTavily: conversation.enable_internet
|
||||||
|
});
|
||||||
|
|
||||||
|
for await (const message of q) {
|
||||||
|
// Messages assistant avec contenu
|
||||||
|
if (message.type === 'assistant') {
|
||||||
|
for (const block of message.message.content) {
|
||||||
|
if (block.type === 'text') {
|
||||||
|
res.write(`data: ${JSON.stringify({ type: 'content', text: block.text })}\n\n`);
|
||||||
|
}
|
||||||
|
if (block.type === 'tool_use') {
|
||||||
|
res.write(`data: ${JSON.stringify({ type: 'tool_use', name: block.name })}\n\n`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Résultat final
|
||||||
|
if (message.type === 'result') {
|
||||||
|
if (message.subtype === 'success') {
|
||||||
|
res.write(`data: ${JSON.stringify({
|
||||||
|
type: 'done',
|
||||||
|
id: assistantMessageId,
|
||||||
|
usage: {
|
||||||
|
inputTokens: message.usage?.input_tokens || 0,
|
||||||
|
outputTokens: message.usage?.output_tokens || 0
|
||||||
|
}
|
||||||
|
})}\n\n`);
|
||||||
|
} else {
|
||||||
|
res.write(`data: ${JSON.stringify({
|
||||||
|
type: 'error',
|
||||||
|
message: message.result || 'Erreur inconnue'
|
||||||
|
})}\n\n`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.3 Fichiers à modifier
|
||||||
|
|
||||||
|
| Fichier | Modifications |
|
||||||
|
|---------|---------------|
|
||||||
|
| `server/routes/messages.js` | Route principale streaming |
|
||||||
|
| `server/routes/claude.js` | Route API Claude (si utilisée) |
|
||||||
|
| `server/index.js` | Supprimer init des anciens clients MCP |
|
||||||
|
|
||||||
|
**Validation Phase 2 :**
|
||||||
|
```bash
|
||||||
|
# Test streaming
|
||||||
|
curl -X POST http://localhost:3001/api/conversations/test-conv-id/messages/stream \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"content": "Bonjour Ikario"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 3 : Nettoyage (1-2 jours)
|
||||||
|
|
||||||
|
**Objectif** : Supprimer le code obsolète
|
||||||
|
|
||||||
|
#### 3.1 Fichiers à supprimer
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Services MCP obsolètes
|
||||||
|
rm server/services/unifiedRagClient.js
|
||||||
|
rm server/services/tavilyMcpClient.js
|
||||||
|
rm server/services/libraryRagMcpClient.js
|
||||||
|
rm server/services/mcpClient.js
|
||||||
|
rm server/services/toolExecutor.js
|
||||||
|
|
||||||
|
# Configs tools obsolètes (optionnel - peuvent être gardées comme référence)
|
||||||
|
# rm server/config/memoryTools.js
|
||||||
|
# rm server/config/tavilyTools.js
|
||||||
|
# rm server/config/libraryRagTools.js
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.2 Dépendances à supprimer
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd server
|
||||||
|
npm uninstall @anthropic-ai/sdk
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.3 Nettoyage des imports
|
||||||
|
|
||||||
|
Rechercher et supprimer dans tous les fichiers :
|
||||||
|
- `import Anthropic from '@anthropic-ai/sdk'`
|
||||||
|
- `import { ... } from '../services/unifiedRagClient.js'`
|
||||||
|
- `import { ... } from '../services/tavilyMcpClient.js'`
|
||||||
|
- `import { ... } from '../services/toolExecutor.js'`
|
||||||
|
|
||||||
|
**Validation Phase 3 :**
|
||||||
|
```bash
|
||||||
|
# Vérifier qu'il n'y a plus de références aux anciens fichiers
|
||||||
|
grep -r "unifiedRagClient" server/
|
||||||
|
grep -r "tavilyMcpClient" server/
|
||||||
|
grep -r "toolExecutor" server/
|
||||||
|
grep -r "@anthropic-ai/sdk" server/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 4 : Tests et Validation (2 jours)
|
||||||
|
|
||||||
|
| Test | Description | Commande |
|
||||||
|
|------|-------------|----------|
|
||||||
|
| 4.1 | Streaming SSE | Envoyer message, vérifier réponse temps réel |
|
||||||
|
| 4.2 | Outils mémoire | `add_thought`, `search_thoughts`, `search_memories` |
|
||||||
|
| 4.3 | Tavily | Recherche internet (si activé) |
|
||||||
|
| 4.4 | Images | Upload et analyse d'images |
|
||||||
|
| 4.5 | Tokens | Vérifier compteur tokens correct |
|
||||||
|
| 4.6 | Conversations | Multi-tours, contexte préservé |
|
||||||
|
| 4.7 | Projets | Instructions projet appliquées |
|
||||||
|
|
||||||
|
**Script de test complet :**
|
||||||
|
```bash
|
||||||
|
# Test conversation complète
|
||||||
|
./tests/test_agent_sdk_integration.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 5 : Mode AGENT Auto-poïétique (3-4 jours)
|
||||||
|
|
||||||
|
**Objectif** : Permettre à Ikario de modifier son propre code
|
||||||
|
|
||||||
|
#### 5.1 Nouvelle route
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// server/routes/agent.js
|
||||||
|
import express from 'express';
|
||||||
|
import { query } from '@anthropic-ai/claude-agent-sdk';
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
// POST /api/agent/evolve
|
||||||
|
router.post('/evolve', async (req, res) => {
|
||||||
|
const { task, context } = req.body;
|
||||||
|
|
||||||
|
res.setHeader('Content-Type', 'text/event-stream');
|
||||||
|
res.setHeader('Cache-Control', 'no-cache');
|
||||||
|
res.setHeader('Connection', 'keep-alive');
|
||||||
|
|
||||||
|
const q = query({
|
||||||
|
prompt: `
|
||||||
|
Contexte: ${context}
|
||||||
|
Tâche: ${task}
|
||||||
|
|
||||||
|
Instructions:
|
||||||
|
1. Analyse le code actuel avec Read/Grep
|
||||||
|
2. Planifie les modifications
|
||||||
|
3. Implémente avec Edit/Write
|
||||||
|
4. Documente dans la mémoire (add_thought)
|
||||||
|
`,
|
||||||
|
options: {
|
||||||
|
model: "claude-opus-4-5-20251101",
|
||||||
|
systemPrompt: "Tu es Ikario en mode auto-modification...",
|
||||||
|
allowedTools: [
|
||||||
|
"Read", "Write", "Edit", "Glob", "Grep", "Bash",
|
||||||
|
"mcp__unified_rag__add_thought",
|
||||||
|
"mcp__unified_rag__search_thoughts"
|
||||||
|
],
|
||||||
|
mcpServers: {
|
||||||
|
unified_rag: {
|
||||||
|
command: "python",
|
||||||
|
args: [process.env.UNIFIED_RAG_SERVER_PATH],
|
||||||
|
env: { WEAVIATE_URL: process.env.WEAVIATE_URL }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cwd: process.env.IKARIO_PROJECT_DIR,
|
||||||
|
hooks: {
|
||||||
|
PreToolUse: [{
|
||||||
|
matcher: 'Write|Edit',
|
||||||
|
hooks: [protectSensitiveFiles]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
permissionMode: "acceptEdits"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for await (const message of q) {
|
||||||
|
res.write(`data: ${JSON.stringify(message)}\n\n`);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Hook de sécurité
|
||||||
|
async function protectSensitiveFiles(input, toolUseID, { signal }) {
|
||||||
|
const filePath = input.tool_input?.file_path || '';
|
||||||
|
const fileName = filePath.split('/').pop();
|
||||||
|
|
||||||
|
const protected = ['.env', 'api-key', 'credentials', 'secret'];
|
||||||
|
if (protected.some(p => fileName.includes(p))) {
|
||||||
|
return {
|
||||||
|
hookSpecificOutput: {
|
||||||
|
hookEventName: input.hook_event_name,
|
||||||
|
decision: 'deny',
|
||||||
|
reason: `Fichier protégé: ${fileName}`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default router;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5.2 Variables d'environnement
|
||||||
|
|
||||||
|
Ajouter dans `.env` :
|
||||||
|
```bash
|
||||||
|
IKARIO_PROJECT_DIR=/path/to/generations/ikario
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5.3 UI (optionnel)
|
||||||
|
|
||||||
|
Créer un composant React pour déclencher l'auto-modification depuis l'interface.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Variables d'Environnement Finales
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# === CLAUDE AGENT SDK (nouveau) ===
|
||||||
|
CLAUDE_CODE_OAUTH_TOKEN='your-oauth-token' # De: claude setup-token
|
||||||
|
|
||||||
|
# === WEAVIATE (inchangé) ===
|
||||||
|
WEAVIATE_URL=http://localhost:8080
|
||||||
|
WEAVIATE_API_KEY= # Optionnel pour cloud
|
||||||
|
|
||||||
|
# === UNIFIED RAG MCP (inchangé) ===
|
||||||
|
UNIFIED_RAG_SERVER_PATH=/path/to/library_rag/mcp_server.py
|
||||||
|
|
||||||
|
# === TAVILY (inchangé) ===
|
||||||
|
TAVILY_API_KEY=tvly-xxxxx
|
||||||
|
|
||||||
|
# === MODE AGENT (nouveau) ===
|
||||||
|
IKARIO_PROJECT_DIR=/path/to/generations/ikario
|
||||||
|
|
||||||
|
# === OBSOLÈTES (à supprimer) ===
|
||||||
|
# ANTHROPIC_API_KEY=sk-ant-xxxxx # Plus nécessaire
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Récapitulatif
|
||||||
|
|
||||||
|
| Phase | Durée | Objectif | Livrable |
|
||||||
|
|-------|-------|----------|----------|
|
||||||
|
| 0 | 1 jour | Préparation | Token, package, branche |
|
||||||
|
| 1 | 2-3 jours | Service SDK | `agentSdkService.js` |
|
||||||
|
| 2 | 2-3 jours | Migration routes | `messages.js` modifié |
|
||||||
|
| 3 | 1-2 jours | Nettoyage | Anciens fichiers supprimés |
|
||||||
|
| 4 | 2 jours | Tests | Validation complète |
|
||||||
|
| 5 | 3-4 jours | Mode AGENT | `/api/agent/evolve` |
|
||||||
|
|
||||||
|
**Total : 11-15 jours**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Breaking Changes
|
||||||
|
|
||||||
|
1. **Extended Thinking** : Le contenu "thinking" n'est plus affiché au frontend
|
||||||
|
2. **API Key** : `ANTHROPIC_API_KEY` remplacé par `CLAUDE_CODE_OAUTH_TOKEN`
|
||||||
|
3. **MCP Clients** : Les 4 clients séparés sont supprimés
|
||||||
|
4. **toolExecutor** : Supprimé, géré automatiquement par le SDK
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rollback
|
||||||
|
|
||||||
|
En cas de problème, restaurer depuis la branche `main` :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git checkout main
|
||||||
|
git branch -D feature/agent-sdk-migration
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Document créé le 31 janvier 2026*
|
||||||
|
*Migration vers Claude Agent SDK TypeScript*
|
||||||
Reference in New Issue
Block a user