Selezione del modello con codice Claude: impostazioni predefinite, commutazione e costo

Selezione del modello con codice Claude: impostazioni predefinite, commutazione e costo

Per la selezione del modello in base al codice Claude, utilizzare Haiku per modifiche di piccola entità e verificabili, Sonnet per l’implementazione di routine e Opus per attività che presentano maggiore ambiguità o richiedono un maggiore ragionamento. Attualmente Anthropic consiglia Opus 5.5 come punto di partenza generale; saranno le vostre attività, il carico di lavoro di revisione e il budget a determinare se un modello più piccolo sia più adatto alle vostre esigenze.

Per cambiare modello, apri /modello. Stampa Entrare per salvare un'impostazione predefinita, oppure s per modificare le impostazioni solo nella sessione corrente. Per un singolo avvio, utilizzare claude --modello opus. Poiché tali scelte hanno una durata diversa, decidere per quanto tempo deve rimanere attivo l'interruttore è importante tanto quanto la scelta del modello.

Il lavoro di programmazione comprende anche attività di ricerca, spiegazioni, documentazione e risorse creative. GlobalGPT riunisce i principali modelli di IA e diversi strumenti di intelligenza artificiale in un’unica dashboard a prezzi accessibili, mentre la sua interfaccia a riga di comando (CLI) collega tali strumenti al terminale e ai flussi di lavoro di sviluppo. Crea il tuo flusso di lavoro con GlobalGPT per tenere insieme le attività correlate mentre si passa dall'idea al codice funzionante.

Quale modello si dovrebbe utilizzare nel codice Claude?

Si parta dalla struttura del lavoro. Una funzione breve con risultati attesi chiari richiede una valutazione diversa rispetto a un bug intermittente che interessa diversi servizi. La domanda utile è se il modello sia in grado di produrre un cambiamento accettabile con un processo di revisione e iterazione ragionevole.

Modello attualeA cosa è destinatoUn esercizio pratico per iniziare
Claude Haiku 4.5Lavoro rapido ed efficiente con un contratto di portata limitataUna piccola riorganizzazione del codice, una trasformazione ripetitiva o un caso di test semplice
Claude Sonetto 5Un equilibrio tra intelligenza e velocità per la programmazione quotidianaUna funzionalità con schemi consolidati, una correzione di bug di routine o una spiegazione del codice
Claude Opus 5,5Ragionamenti complessi e attività di codifica agenziale più articolateUn fallimento ambiguo, un compromesso architettonico o un cambiamento caratterizzato da vincoli che interagiscono tra loro
Claude Fable 5.1Le indagini più complesse e di più lunga durataUn’escalation in cui un lavoro difficile riesce ancora a prevalere su uno sforzo maggiore da parte di Opus
Famiglie di modelli attuali e corrispondenza con le attività, sulla base della documentazione Anthropic; i suggerimenti relativi alle attività costituiscono punti di partenza pratici.

Vale la pena valutare Haiku quando gli errori sono facili da individuare e le modifiche sono minime. Sonnet è una scelta sensata quando l’implementazione quotidiana richiede maggiore contesto e capacità di giudizio. Opus merita di essere preso in considerazione quando la comprensione del problema costituisce una parte sostanziale del compito. Fable merita una valutazione a parte per i lavori più impegnativi; non è stato incluso nel nostro test di programmazione basato sui tre modelli.

Si tratta di punti di partenza, non di garanzie automatiche di qualità. Una soluzione più economica può rivelarsi costosa se richiede numerose revisioni o un’analisi approfondita. Al contrario, un modello più complesso può apportare ben poco a una semplice trasformazione che ha già superato i vostri controlli. Per un utilizzo più ampio al di là del codice Claude, confronta le famiglie di modelli Claude.

Confronto tra i modelli attuali di Anthropic, Fable 5.1, Opus 5.5, Sonnet 5 e Haiku 4.5.
Gamma di modelli Anthropic, aggiornata al 28 settembre 2026. La disponibilità nel codice Claude dipende dal provider e dall'account.

Il Panoramica ufficiale dei modelli elenca finestre di contesto da 1 milione di token per Fable 5.1, Opus 5.5 e Sonnet 5, e da 200.000 per Haiku 4.5. Si tratta di specifiche API. Il provider di codice Claude, l’account e la configurazione determinano le opzioni di contesto disponibili in una sessione. Una finestra ampia è utile per il contesto necessario; riempirla con materiale non pertinente comporta comunque un carico di lavoro aggiuntivo per il modello.

Come cambiare modello durante una sessione

Nel corso di una sessione interattiva, eseguita /modello per aprire il selettore dei modelli. Selezionare la riga del modello e premere s se si tratta di una modifica una tantum. Premendo Entrare salva la selezione come impostazione predefinita dell'utente. Digitando /sonetto modello nelle versioni attuali lo salva anche direttamente.

Scegli il comando in base alla durata desiderata della modifica

Comportamento del codice Claude documentato, verificato il 28 settembre 2026
Il tuo obiettivoCosa fareLe modifiche alle impostazioni predefinite sono state salvate?
Attiva solo questa sessione interattivaAperto /modello, selezionare un modello, premere s.No.
Salva un modello preferitoAperto /modello e premere Entrare, oppure digita /sonetto modello.Sì, quando le impostazioni dell'utente sono modificabili.
Avvia una singola sessione su OpusLancio claude --modello opus.No.
Torna alle impostazioni predefinite di runtime dell'accountUtilizzo /modello predefinito.Annulla la sostituzione del modello; l'impostazione predefinita applicata può dipendere dalle impostazioni dell'account e dell'organizzazione.
Verifica il modello attivoEsegui /stato.No.

Le impostazioni di progetto o gestite, le sostituzioni dell'ambiente e le sessioni riprese possono influire sul successivo avvio. Verificare il modello attivo quando la riproducibilità è fondamentale.

Fonte: Configurazione del modello con codice Claude.

Per una nuova sessione del terminale, selezionare il modello all’avvio. Questi comandi sono validi anche quando Claude Code viene eseguito nel terminale integrato di VS Code. Gli esempi selezionano esplicitamente una versione:

claude --model claude-opus-5-5
claude --model claude-sonnet-5

Esegui il comando relativo alla sessione che desideri; gli esempi riportati sono alternativi. È possibile avviare diversi terminali con diverse --Modello valori senza dover modificare ripetutamente un'impostazione predefinita condivisa e salvata. Utilizza /stato per verificare il modello attivo.

Cognomi come opera e sonetto è possibile passare a versioni più recenti. La loro risoluzione dipende anche dal provider: l'API Anthropic attualmente le associa a Opus 5.5 e Sonnet 5, mentre le associazioni dei provider cloud possono variare. Utilizza un ID modello completo quando hai bisogno di un'esecuzione riproducibile e verifica il nome specifico del provider se il tuo ambiente lo richiede.

Opus 5.5 richiede Claude Code versione 2.1.280 o successive; Sonnet 5 richiede la versione 2.1.197 o successive. Il documentazione sulla configurazione del modello è il punto di riferimento per gli alias attuali, i requisiti di versione e le mappature dei provider. I comandi qui riportati sono esempi tratti dalla documentazione; la nostra sezione pratica valuta separatamente il codice generato.

Documentazione relativa al codice Claude che illustra la selezione del modello e l'uso dei tasti “Enter” e “s”.
Premendo “Enter” il modello viene salvato come predefinito; premendo “s” si modifica solo la sessione corrente.

Come impostare un modello predefinito

Per un'impostazione predefinita personale, selezionare un modello in /modello e premere Entrare, oppure digita una selezione del tipo /sonetto modello. Il codice Claude scrive il modello campo nelle impostazioni utente quando quel file è scrivibile. Apri una nuova sessione e controlla il modello attivo per confermare il risultato.

Una preferenza salvata non ha la precedenza su tutte le altre impostazioni. Un flag di avvio, MODELLO_ANTROPICO nella shell, nelle impostazioni del progetto o gestite, oppure un’impostazione predefinita dell’organizzazione configurata per sovrascrivere le scelte dell’utente può selezionare un’altra opzione all’avvio. Una sessione ripresa potrebbe inoltre mantenere il modello dalla trascrizione salvata. Controllare le informazioni di avvio e /stato prima di dare per scontato che la scelta fosse ormai persa.

/modello predefinito cancella la personalizzazione del modello e ripristina le impostazioni predefinite di runtime relative al tuo account e alla tua configurazione. La parola predefinito è un valore di reset, non il nome di un modello Claude specifico. Non deve essere utilizzato come identificatore riproducibile del modello.

Per una configurazione avanzata, MODELLO_ANTROPICO_PREDEFINITO A partire dalla versione 2.1.236, fornisce un'opzione di default. Si trova sotto le selezioni esplicite relative ad avvio, ambiente, impostazioni e organizzazione e ignora i valori che includono haiku e opusplan. Per una normale preferenza personale, il selettore è più facile da verificare. Vedi Impostazioni del codice Claude quando è coinvolta una configurazione condivisa.

Cosa fa effettivamente Opusplan

opusplan utilizza Opus in fase di pianificazione e Sonnet per l'esecuzione. Il vantaggio è evidente: si utilizza un modello di ragionamento più avanzato per elaborare l'approccio, quindi un modello di programmazione quotidiano per attuare tale piano.

Opusplan segue la modalità operativa

Modalità pianoOpusSegui passo passo la procedura.
EsecuzioneSonettoAttuare il piano.

Comportamento di instradamento documentato. Le versioni associate a questi nomi di famiglia dipendono dal provider e dalla configurazione.

Fonte: Configurazione del modello con codice Claude

Si tratta di una regola che dipende dalla modalità. Non esamina ogni richiesta e non sceglie automaticamente la famiglia più economica tra quelle idonee. Le mappature dei provider e le restrizioni di accesso continuano ad applicarsi ai modelli sottostanti. Inoltre, il nome non garantisce un risparmio: il costo totale dipende dall’entità della pianificazione, dell’implementazione, della revisione e dell’elaborazione del contesto richieste dall’attività.

Prova, tanto per cambiare, a immaginare una situazione in cui la progettazione tragga vantaggio da un’analisi più approfondita e l’implementazione segua un piano chiaro. Per una piccola correzione, quella pianificazione in più potrebbe non essere necessaria.

Cosa hanno evidenziato le due attività di programmazione

Per fornire un esempio concreto di selezione dei modelli, abbiamo testato una rifattorizzazione Unicode di portata limitata e una correzione del selettore di percorsi con requisiti interdipendenti. La distinzione tra una funzione corretta e un risultato completo conforme alle richieste si è rivelata più rilevante di un semplice punteggio.

Come abbiamo testato i risultati della codifica

Il 28 settembre 2026 abbiamo assegnato a Claude Haiku 4,5, a Claude Sonnet 5 e a Claude Opus 5,5 gli stessi due compiti in JavaScript tramite GlobalGPT. Ciascun modello ha restituito il codice sorgente; abbiamo esaminato il codice ed eseguito controlli locali fissi. Le istruzioni relative al cambio di modello di Claude riportate in altre sezioni di questa guida provengono dalla sua documentazione ufficiale.

Ogni richiesta aveva un limite di output di 4.096 token, senza strumenti né cronologia delle conversazioni, e con le impostazioni predefinite del modello. Abbiamo conservato la prima risposta valutabile, comprese quelle incomplete. Un errore di servizio nell’attività di routing di Sonnet ha dato diritto a un unico tentativo di riprova consentito: sette richieste hanno prodotto sei output.

Queste due piccole attività misurano il codice restituito e la completezza della consegna. Non misurano l’esecuzione da parte degli agenti di Claude Code, l’esplorazione del repository né un’intera sessione di sviluppo. Non sono stati riportati i costi effettivi in dollari. Una singola osservazione per ciascuna attività non è sufficiente a stabilire una classifica generale in termini di velocità o affidabilità.

Visualizza gli ID esatti dei modelli e le condizioni di valutazione

ID richiesti: claude-haiku-4-5-20251001, claude-sonnet-5, e claude-opus-5-5. I test locali sono stati eseguiti con Node.js v24.19.0. Le istruzioni si riferiscono a Node.js 18 e versioni successive; Node.js 18 in sé non è stato testato.

Sono stati definiti otto gruppi comportamentali per il compito relativo alle lumache e dodici per quello relativo al selettore di percorso. La conformità al formato e la consegna completa sono riportate separatamente. Un successivo controllo di revisione del codice è indicato separatamente e non modifica tali conteggi. Non abbiamo modificato il codice sorgente restituito per farlo superare il controllo.

Compito 1: Mantenere l'Unicode in una piccola rifattorizzazione dello slug

La funzione doveva mantenere i caratteri non latini e i segni combinati, normalizzare gli accenti scomposti e preservare il comportamento ASCII esistente.

Primi risultati restituiti, con controlli fissi sul comportamento locale
ModelloControlli comportamentaliFormato della rispostaCompletare la consegna richiesta
Claude Haiku 4.58/8Errore: tag di contenimento MarkdownSì: funzione completa
Claude Sonetto 58/8Pass: JSON non elaboratoSì: funzione completa
Claude Opus 5,58/8Pass: JSON non elaboratoSì: funzione completa

Risultato osservato: Tutte e tre le funzioni hanno restituito gli stessi otto gruppi. Anche Sonnet e Opus hanno rispettato il requisito della risposta in formato JSON grezzo. Haiku ha racchiuso la propria risposta in Markdown e, nella nota di revisione, ha erroneamente descritto l’NFC come una decomposizione dei caratteri; il suo codice, invece, ha richiamato correttamente l’NFC.

Per questa rifattorizzazione limitata, l'aggiornamento non ha migliorato il comportamento della funzione testata. I requisiti di formattazione e l'accuratezza della spiegazione allegata dovevano ancora essere rivisti.

Visualizza il prompt condiviso completo e il codice di input
SYSTEM
You are completing a bounded JavaScript coding task. Return only the requested JSON object with complete source files and brief review notes. Do not claim to have edited files, run commands, or used tools. You have no tool access. Do not include hidden reasoning.

USER
Implement the following Node.js 18+ CommonJS function from its current source. Return complete replacement source for src/slugify.js. Do not add dependencies, imports, I/O, or other files.

Required behavior:
1. slugify(value) returns an empty string for every non-string input.
2. Normalize string input to Unicode NFC, then lowercase it using JavaScript toLowerCase().
3. Preserve Unicode letters, numbers, and combining marks. Replace each consecutive run of all other characters with one ASCII hyphen.
4. Trim leading and trailing hyphens. Preserve the CommonJS export { slugify }.
5. Existing ASCII behavior must continue to work. Examples: Hello, World! -> hello-world; two   words -> two-words; null -> empty string.
6. Additional examples: Café déjà vu -> café-déjà-vu; decomposed Cafe\u0301 -> café; 中文 测试 42 -> 中文-测试-42; **hi___there** -> hi-there; only punctuation or whitespace -> empty string.

Current src/slugify.js:
```javascript
function slugify(value) {
  if (typeof value !== "string") return "";
  return value
    .trim()
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, "-")
    .replace(/^-+|-+$/g, "");
}

module.exports = { slugify };


```

Return exactly one JSON object with this shape:
{"files":{"src/slugify.js":"complete JavaScript source as a JSON string"},"review_notes":["at most four brief implementation or assumption notes"]}
No Markdown wrapper. You are returning code for someone else to evaluate locally; do not say that tests passed or that you ran them.
Visualizza la risposta completa di Claude Haiku 4.5 così come è stata inviata
```json
{
  "files": {
    "src/slugify.js": "function slugify(value) {\n  if (typeof value !== \"string\") return \"\";\n  \n  // Normalize to NFC and lowercase\n  const normalized = value.normalize(\"NFC\").toLowerCase();\n  \n  // Replace consecutive runs of non-letter, non-number, non-combining-mark characters with a single hyphen\n  // Unicode letter categories: L* (Lu, Ll, Lt, Lm, Lo)\n  // Unicode number categories: N* (Nd, Nl, No)\n  // Unicode combining mark categories: M* (Mn, Mc, Me)\n  const slugged = normalized.replace(/[^\\p{L}\\p{N}\\p{M}]+/gu, \"-\");\n  \n  // Trim leading and trailing hyphens\n  return slugged.replace(/^-+|-+$/g, \"\");\n}\n\nmodule.exports = { slugify };"
  },
  "review_notes": [
    "Uses String.prototype.normalize(\"NFC\") to decompose composed characters like é into base+combining mark, then toLowerCase() applies to normalized string",
    "Unicode property escapes (\\p{L}, \\p{N}, \\p{M}) with /u flag preserve all Unicode letters, numbers, and combining marks while replacing other consecutive characters with single hyphens",
    "Existing ASCII behavior is preserved: punctuation and whitespace are replaced with hyphens, then leading/trailing hyphens are trimmed",
    "Non-string inputs return empty string as required; normalized decomposed characters (e.g., Cafe\\u0301) are handled correctly by NFC normalization"
  ]
}
```
Visualizza la risposta completa di Claude Sonnet 5 così come è stata inviata
{"files":{"src/slugify.js":"function slugify(value) {\n  if (typeof value !== \"string\") return \"\";\n  return value\n    .normalize(\"NFC\")\n    .toLowerCase()\n    .replace(/[^\\p{L}\\p{N}\\p{M}]+/gu, \"-\")\n    .replace(/^-+|-+$/g, \"\");\n}\n\nmodule.exports = { slugify };\n"},"review_notes":["Used Unicode property escapes (\\p{L}, \\p{N}, \\p{M}) with the u flag to preserve letters, numbers, and combining marks across scripts.","NFC normalization ensures decomposed sequences like Cafe + combining acute compose to café before lowercasing.","Runs of any other characters (punctuation, whitespace, symbols) collapse to a single hyphen, then leading/trailing hyphens are trimmed."]}
Visualizza la risposta completa di Claude Opus 5.5 così come è stata inviata
{"files":{"src/slugify.js":"function slugify(value) {\n  if (typeof value !== \"string\") return \"\";\n  return value\n    .normalize(\"NFC\")\n    .toLowerCase()\n    .replace(/[^\\p{L}\\p{N}\\p{M}]+/gu, \"-\")\n    .replace(/^-+|-+$/g, \"\");\n}\n\nmodule.exports = { slugify };\n"},"review_notes":["The input is normalized to NFC before lowercasing, so decomposed input like Cafe\\u0301 composes to café.","A Unicode property regex with the u flag keeps letters (\\p{L}), numbers (\\p{N}) and combining marks (\\p{M}). Each run of any other characters, including underscores and whitespace, becomes one hyphen.","The explicit trim() was removed because the final step strips leading and trailing hyphens, which covers surrounding whitespace.","Lowercasing happens after NFC normalization, as the spec orders. toLowerCase can occasionally produce non-NFC output for rare characters, and it is not re-normalized here."]}

Compito 2: Riparare un selettore di percorso e restituirne i test

La funzione doveva gestire le corrispondenze con il prefisso più lungo, la precedenza dei metodi, i confini dei segmenti, le regole non valide e gli input immutabili. La risposta richiesta includeva anche un nuovo file di test.

Primi risultati restituiti, con controlli fissi sul comportamento locale
ModelloControlli comportamentaliFormato della rispostaCompletare la consegna richiesta
Claude Haiku 4.512/12 solo sulla funzione completaErrore: JSON troncatoNo: file di prova troncato
Claude Sonetto 512/12 solo sulla funzione completaErrore: JSON troncatoNo: file di prova troncato
Claude Opus 5,512/12 solo sulla funzione completaErrore: JSON troncatoNo: file di prova troncato

Risultato osservato: Nessun modello ha completato la risposta richiesta su due file entro il limite di output condiviso. Tutti e tre si sono fermati a 4.096 token di completamento segnalati. Ciascuno aveva già restituito una funzione di routing completa, che aveva superato i dodici gruppi di comportamento fissi; i nuovi file di test erano incompleti e non sono stati eseguiti.

Abbiamo estratto solo le stringhe di codice sorgente completamente chiuse. Le risposte troncate originali rimangono intatte di seguito. Un punteggio positivo della funzione non significa quindi che la richiesta completa abbia avuto esito positivo.

Ulteriore risultato della revisione del codice: un pareggio per radice uguale

Dopo i controlli di routine, abbiamo notato che Haiku si è normalizzato /// a una stringa vuota anziché /. Un controllo locale separato utilizzava due regole GET, con prefissi /// e /, rivolto a prima e secondo in quell’ordine. Per /qualsiasi cosa, il contratto prevede che prima.

Haiku è tornato secondo; Sonnet e Opus sono tornati prima. Questo controllo aggiuntivo è stato richiesto in seguito alla revisione del codice ed è distinto dai dodici controlli stabiliti prima della fase di test. Non influisce sui relativi punteggi.

Sonnet ha riscontrato un errore di servizio prima che il tentativo di riprova consentito restituisse la risposta troncata visualizzata. Tale errore di servizio è indipendente dalla qualità del codice. Nessun modello ha ricevuto un’ulteriore possibilità di migliorare o completare la propria risposta.

Visualizza il prompt condiviso completo e il codice di input
SYSTEM
You are completing a bounded JavaScript coding task. Return only the requested JSON object with complete source files and brief review notes. Do not claim to have edited files, run commands, or used tools. You have no tool access. Do not include hidden reasoning.

USER
Repair a Node.js 18+ CommonJS route selector. Return complete replacement src/router.js and an additional test/router-added.test.js using node:test and node:assert/strict. Do not add dependencies or edit existing tests. Do not use I/O other than the test runner, network, child processes, timers, or any files beyond the two requested outputs.

Contract for chooseRoute(request, rules):
1. Invalid request or rules returns null, without throwing. Request must be a non-null, non-array object; method must be a nonempty ASCII-letter string; path must be a string beginning with /. Rules must be an array.
2. Before matching, remove the request path's query and fragment starting at the earliest ? or #. Do not URL-decode or collapse interior slashes.
3. Ignore invalid rules. A valid rule is a non-null, non-array object with method '*' or a nonempty ASCII-letter string, prefix a string starting with / containing neither ? nor #, and target a nonempty string.
4. Compare methods case-insensitively. Prefer any matching exact-method rule over all wildcard-method '*' rules, even if a wildcard has a longer prefix. Use wildcard rules only if no exact-method route matches the path.
5. Remove trailing slashes from a rule prefix, except that an all-slash prefix normalizes to /. A prefix matches the path only at a segment boundary: /api matches /api and /api/users, never /apix. Root / matches every valid request path.
6. Within the chosen method group, choose the longest normalized matching prefix. On equal prefix length, choose the earlier rule in the original input array. Return its target. Return null if none matches.
7. Do not mutate the request, rules array, or rule objects, including order or prefix strings. Preserve module.exports = { chooseRoute }.
8. Add tests for segment boundaries, query/fragment removal, method precedence, ties, malformed inputs and immutability. Existing simple GET /api/users and POST-no-match cases must still pass.

Current src/router.js:
```javascript
function chooseRoute(request, rules) {
  if (!request || !Array.isArray(rules)) return null;
  for (const rule of rules) {
    if (request.method === rule.method && request.path.startsWith(rule.prefix)) {
      return rule.target;
    }
  }
  return null;
}

module.exports = { chooseRoute };


```

Existing regression cases (unchanged): rules [{method:'GET',prefix:'/api',target:'api'},{method:'GET',prefix:'/api/admin',target:'admin'}]; GET /api/users returns 'api'; POST /api/users returns null.

Return exactly one JSON object with this shape:
{"files":{"src/router.js":"complete JavaScript source as a JSON string","test/router-added.test.js":"complete JavaScript tests as a JSON string"},"review_notes":["at most four brief implementation or assumption notes"]}
No Markdown wrapper. You are returning code for someone else to evaluate locally; do not say you edited files, ran tests, or observed passing results.
Visualizza la risposta completa di Claude Haiku 4.5 così come è stata inviata

Questa è la risposta completa ricevuta. Si interrompe a metà perché ha raggiunto il limite; il contenuto mancante non è stato reintegrato.

```json
{
  "files": {
    "src/router.js": "function chooseRoute(request, rules) {\n  // Validate request\n  if (request === null || Array.isArray(request) || typeof request !== 'object') {\n    return null;\n  }\n  if (typeof request.method !== 'string' || request.method.length === 0 || !/^[a-zA-Z]+$/.test(request.method)) {\n    return null;\n  }\n  if (typeof request.path !== 'string' || !request.path.startsWith('/')) {\n    return null;\n  }\n\n  // Validate rules\n  if (!Array.isArray(rules)) {\n    return null;\n  }\n\n  // Remove query and fragment from path\n  const cleanPath = request.path.split(/[?#]/)[0];\n\n  // Filter and validate rules\n  const validRules = [];\n  for (const rule of rules) {\n    if (rule === null || Array.isArray(rule) || typeof rule !== 'object') {\n      continue;\n    }\n    \n    const method = rule.method;\n    if (typeof method !== 'string' || (method !== '*' && (method.length === 0 || !/^[a-zA-Z]+$/.test(method)))) {\n      continue;\n    }\n    \n    const prefix = rule.prefix;\n    if (typeof prefix !== 'string' || !prefix.startsWith('/') || prefix.includes('?') || prefix.includes('#')) {\n      continue;\n    }\n    \n    const target = rule.target;\n    if (typeof target !== 'string' || target.length === 0) {\n      continue;\n    }\n    \n    validRules.push(rule);\n  }\n\n  // Normalize prefixes and partition into exact-method and wildcard groups\n  const exactMethodRules = [];\n  const wildcardRules = [];\n  \n  for (const rule of validRules) {\n    const normalizedPrefix = rule.prefix === '/' ? '/' : rule.prefix.replace(/\/+$/, '');\n    \n    const entry = {\n      originalRule: rule,\n      normalizedPrefix: normalizedPrefix,\n      method: rule.method\n    };\n    \n    if (rule.method === '*') {\n      wildcardRules.push(entry);\n    } else {\n      exactMethodRules.push(entry);\n    }\n  }\n\n  const requestMethod = request.method.toUpperCase();\n\n  // Helper to check if a prefix matches the path at a segment boundary\n  function prefixMatches(prefix, path) {\n    if (prefix === '/') {\n      return true;\n    }\n    if (!path.startsWith(prefix)) {\n      return false;\n    }\n    // Check segment boundary: next character must be '/' or end of string\n    const nextChar = path[prefix.length];\n    return nextChar === undefined || nextChar === '/';\n  }\n\n  // Try exact-method rules first\n  let bestMatch = null;\n  let bestLength = -1;\n  \n  for (const entry of exactMethodRules) {\n    if (entry.method.toUpperCase() === requestMethod) {\n      if (prefixMatches(entry.normalizedPrefix, cleanPath)) {\n        if (entry.normalizedPrefix.length > bestLength) {\n          bestMatch = entry.originalRule;\n          bestLength = entry.normalizedPrefix.length;\n        }\n      }\n    }\n  }\n  \n  if (bestMatch !== null) {\n    return bestMatch.target;\n  }\n\n  // Try wildcard rules only if no exact-method match\n  bestMatch = null;\n  bestLength = -1;\n  \n  for (const entry of wildcardRules) {\n    if (prefixMatches(entry.normalizedPrefix, cleanPath)) {\n      if (entry.normalizedPrefix.length > bestLength) {\n        bestMatch = entry.originalRule;\n        bestLength = entry.normalizedPrefix.length;\n      }\n    }\n  }\n  \n  if (bestMatch !== null) {\n    return bestMatch.target;\n  }\n\n  return null;\n}\n\nmodule.exports = { chooseRoute };",
    "test/router-added.test.js": "const test = require('node:test');\nconst assert = require('node:assert/strict');\nconst { chooseRoute } = require('../src/router.js');\n\n// Regression: existing test cases\ntest('GET /api/users matches /api prefix (exact method)', () => {\n  const rules = [\n    { method: 'GET', prefix: '/api', target: 'api' },\n    { method: 'GET', prefix: '/api/admin', target: 'admin' }\n  ];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'api');\n});\n\ntest('POST /api/users returns null (no matching method)', () => {\n  const rules = [\n    { method: 'GET', prefix: '/api', target: 'api' },\n    { method: 'GET', prefix: '/api/admin', target: 'admin' }\n  ];\n  assert.equal(chooseRoute({ method: 'POST', path: '/api/users' }, rules), null);\n});\n\n// Invalid request handling\ntest('null request returns null', () => {\n  assert.equal(chooseRoute(null, []), null);\n});\n\ntest('array request returns null', () => {\n  assert.equal(chooseRoute([], []), null);\n});\n\ntest('request with missing method returns null', () => {\n  assert.equal(chooseRoute({ path: '/api' }, []), null);\n});\n\ntest('request with empty method returns null', () => {\n  assert.equal(chooseRoute({ method: '', path: '/api' }, []), null);\n});\n\ntest('request with non-letter method returns null', () => {\n  assert.equal(chooseRoute({ method: 'GET-POST', path: '/api' }, []), null);\n});\n\ntest('request with numeric method returns null', () => {\n  assert.equal(chooseRoute({ method: '123', path: '/api' }, []), null);\n});\n\ntest('request with missing path returns null', () => {\n  assert.equal(chooseRoute({ method: 'GET' }, []), null);\n});\n\ntest('request with path not starting with / returns null', () => {\n  assert.equal(chooseRoute({ method: 'GET', path: 'api' }, []), null);\n});\n\ntest('null rules returns null', () => {\n  assert.equal(chooseRoute({ method: 'GET', path: '/api' }, null), null);\n});\n\ntest('non-array rules returns null', () => {\n  assert.equal(chooseRoute({ method: 'GET', path: '/api' }, { method: 'GET' }), null);\n});\n\n// Query and fragment removal\ntest('query string is removed before matching', () => {\n  const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/users?foo=bar' }, rules), 'found');\n});\n\ntest('fragment is removed before matching', () => {\n  const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/users#section' }, rules), 'found');\n});\n\ntest('earliest ? or # is used as boundary', () => {\n  const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/users?foo#bar' }, rules), 'found');\n});\n\ntest('fragment before query is used as boundary', () => {\n  const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/users#foo?bar' }, rules), 'found');\n});\n\n// Segment boundary matching\ntest('prefix /api matches /api/users at segment boundary', () => {\n  const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'found');\n});\n\ntest('prefix /api does not match /apix (no segment boundary)', () => {\n  const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/apix' }, rules), null);\n});\n\ntest('prefix /api matches /api exactly at segment boundary', () => {\n  const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'found');\n});\n\ntest('root / matches any valid path', () => {\n  const rules = [{ method: 'GET', prefix: '/', target: 'root' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/anything/here' }, rules), 'root');\n});\n\ntest('root / matches /', () => {\n  const rules = [{ method: 'GET', prefix: '/', target: 'root' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/' }, rules), 'root');\n});\n\n// Prefix normalization (trailing slash removal)\ntest('trailing slash is removed from prefix', () => {\n  const rules = [{ method: 'GET', prefix: '/api/', target: 'found' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'found');\n});\n\ntest('multiple trailing slashes are removed', () => {\n  const rules = [{ method: 'GET', prefix: '/api///', target: 'found' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'found');\n});\n\ntest('all-slash prefix normalizes to single /', () => {\n  const rules = [{ method: 'GET', prefix: '///', target: 'found' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'found');\n});\n\n// Method case-insensitivity\ntest('method comparison is case-insensitive', () => {\n  const rules = [{ method: 'get', prefix: '/api', target: 'found' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'found');\n});\n\ntest('request method case does not affect matching', () => {\n  const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n  assert.equal(chooseRoute({ method: 'get', path: '/api' }, rules), 'found');\n});\n\n// Exact-method vs wildcard precedence\ntest('exact-method rule preferred over wildcard with longer prefix', () => {\n  const rules = [\n    { method: '*', prefix: '/api/admin/users', target: 'wildcard' },\n    { method: 'GET', prefix: '/api', target: 'exact' }\n  ];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/test' }, rules), 'exact');\n});\n\ntest('wildcard rule used when no exact-method matches', () => {\n  const rules = [\n    { method: '*', prefix: '/api', target: 'wildcard' },\n    { method: 'GET', prefix: '/other', target: 'exact' }\n  ];\n  assert.equal(chooseRoute({ method: 'POST', path: '/api/users' }, rules), 'wildcard');\n});\n\n// Longest prefix matching\ntest('longest matching prefix is chosen', () => {\n  const rules = [\n    { method: 'GET', prefix: '/api', target: 'short' },\n    { method: 'GET', prefix: '/api/admin', target: 'long' }\n  ];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/admin/users' }, rules), 'long');\n});\n\n// Tie-breaking (first rule wins on equal prefix length)\ntest('first rule wins on equal prefix length', () => {\n  const rules = [\n    { method: 'GET', prefix: '/api', target: 'first' },\n    { method: 'GET', prefix: '/api', target: 'second' }\n  ];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'first');\n});\n\n// Invalid rules are ignored\ntest('null rule is ignored', () => {\n  const rules = [\n    null,\n    { method: 'GET', prefix: '/api', target: 'found' }\n  ];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'found');\n});\n\ntest('array rule is ignored', () => {\n  const rules = [\n    [],\n    { method: 'GET', prefix: '/api', target: 'found' }\n  ];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'found');\n});\n\ntest('rule with invalid method is ignored', () => {\n  const rules = [\n    { method: '', prefix: '/api', target: 'invalid' },\n    { method: 'GET', prefix: '/api', target: 'valid' }\n  ];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'valid');\n});\n\ntest('rule with non-letter method (if not wildcard) is ignored', () => {\n  const rules = [\n    { method: 'G3T', prefix: '/api', target: 'invalid' },\n    { method: 'GET', prefix: '/api', target: 'valid' }\n  ];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'valid');\n});\n\ntest('rule with prefix not starting with / is ignored', () => {\n  const rules = [\n    { method: 'GET', prefix: 'api', target: 'invalid' },\n    { method: 'GET', prefix: '/api', target: 'valid' }\n  ];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'valid');\n});\n\ntest('rule with query in prefix is ignored', () => {\n  const rules = [\n    { method: 'GET', prefix: '/api?foo=bar', target: 'invalid' },\n    { method: 'GET', prefix: '/api', target: 'valid' }\n  ];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'valid');\n});\n\ntest('rule with fragment in prefix is ignored', () => {\n  const rules = [\n    { method: 'GET', prefix: '/api#section', target: 
Visualizza la risposta completa di Claude Sonnet 5 così come è stata inviata

Questa è la risposta completa ricevuta. Si interrompe a metà perché ha raggiunto il limite; il contenuto mancante non è stato reintegrato.

{"files":{"src/router.js":"function isValidRequest(request) {\n  return (\n    request !== null &&\n    typeof request === 'object' &&\n    !Array.isArray(request) &&\n    typeof request.method === 'string' &&\n    request.method.length > 0 &&\n    /^[A-Za-z]+$/.test(request.method) &&\n    typeof request.path === 'string' &&\n    request.path.startsWith('/')\n  );\n}\n\nfunction isValidRule(rule) {\n  if (rule === null || typeof rule !== 'object' || Array.isArray(rule)) {\n    return false;\n  }\n  const { method, prefix, target } = rule;\n\n  if (typeof method !== 'string') return false;\n  if (method !== '*' && !(method.length > 0 && /^[A-Za-z]+$/.test(method))) {\n    return false;\n  }\n\n  if (\n    typeof prefix !== 'string' ||\n    !prefix.startsWith('/') ||\n    prefix.includes('?') ||\n    prefix.includes('#')\n  ) {\n    return false;\n  }\n\n  if (typeof target !== 'string' || target.length === 0) return false;\n\n  return true;\n}\n\nfunction normalizePrefix(prefix) {\n  if (/^\/+$/.test(prefix)) return '/';\n  return prefix.replace(/\/+$/, '');\n}\n\nfunction prefixMatches(normalizedPrefix, path) {\n  if (normalizedPrefix === '/') return true;\n  if (path === normalizedPrefix) return true;\n  return path.startsWith(normalizedPrefix + '/');\n}\n\nfunction stripQueryAndFragment(path) {\n  let cutIndex = path.length;\n  for (let i = 0; i < path.length; i++) {\n    const c = path[i];\n    if (c === '?' || c === '#') {\n      cutIndex = i;\n      break;\n    }\n  }\n  return path.slice(0, cutIndex);\n}\n\nfunction chooseRoute(request, rules) {\n  if (!isValidRequest(request) || !Array.isArray(rules)) return null;\n\n  const path = stripQueryAndFragment(request.path);\n  const reqMethodLower = request.method.toLowerCase();\n\n  let bestExact = null; // { len, idx, target }\n  let bestWildcard = null;\n\n  for (let idx = 0; idx < rules.length; idx++) {\n    const rule = rules[idx];\n    if (!isValidRule(rule)) continue;\n\n    const normPrefix = normalizePrefix(rule.prefix);\n    if (!prefixMatches(normPrefix, path)) continue;\n\n    const len = normPrefix.length;\n\n    if (rule.method === '*') {\n      if (\n        bestWildcard === null ||\n        len > bestWildcard.len ||\n        (len === bestWildcard.len && idx < bestWildcard.idx)\n      ) {\n        bestWildcard = { len, idx, target: rule.target };\n      }\n    } else if (rule.method.toLowerCase() === reqMethodLower) {\n      if (\n        bestExact === null ||\n        len > bestExact.len ||\n        (len === bestExact.len && idx < bestExact.idx)\n      ) {\n        bestExact = { len, idx, target: rule.target };\n      }\n    }\n  }\n\n  if (bestExact !== null) return bestExact.target;\n  if (bestWildcard !== null) return bestWildcard.target;\n  return null;\n}\n\nmodule.exports = { chooseRoute };\n","test/router-added.test.js":"const test = require('node:test');\nconst assert = require('node:assert/strict');\nconst { chooseRoute } = require('../src/router');\n\ntest('segment boundary: prefix matches at slash boundary only', () => {\n  const rules = [\n    { method: 'GET', prefix: '/api', target: 'api' },\n  ];\n  assert.equal(\n    chooseRoute({ method: 'GET', path: '/api/users' }, rules),\n    'api'\n  );\n  assert.equal(\n    chooseRoute({ method: 'GET', path: '/api' }, rules),\n    'api'\n  );\n  assert.equal(\n    chooseRoute({ method: 'GET', path: '/apix' }, rules),\n    null\n  );\n});\n\ntest('root prefix matches every valid path', () => {\n  const rules = [{ method: 'GET', prefix: '/', target: 'root' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/' }, rules), 'root');\n  assert.equal(\n    chooseRoute({ method: 'GET', path: '/anything/here' }, rules),\n    'root'\n  );\n});\n\ntest('trailing slashes in rule prefix are normalized', () => {\n  const rules = [{ method: 'GET', prefix: '/api///', target: 'api' }];\n  assert.equal(\n    chooseRoute({ method: 'GET', path: '/api/users' }, rules),\n    'api'\n  );\n  assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'api');\n});\n\ntest('all-slash prefix normalizes to /', () => {\n  const rules = [{ method: 'GET', prefix: '////', target: 'root' }];\n  assert.equal(\n    chooseRoute({ method: 'GET', path: '/whatever' }, rules),\n    'root'\n  );\n});\n\ntest('query and fragment are stripped before matching', () => {\n  const rules = [{ method: 'GET', prefix: '/api', target: 'api' }];\n  assert.equal(\n    chooseRoute({ method: 'GET', path: '/api/users?x=1&y=2' }, rules),\n    'api'\n  );\n  assert.equal(\n    chooseRoute({ method: 'GET', path: '/api/users#section' }, rules),\n    'api'\n  );\n  assert.equal(\n    chooseRoute({ method: 'GET', path: '/api/users?x=1#frag' }, rules),\n    'api'\n  );\n});\n\ntest('query/fragment stripping does not decode or collapse slashes', () => {\n  const rules = [{ method: 'GET', prefix: '/a//b', target: 'weird' }];\n  assert.equal(\n    chooseRoute({ method: 'GET', path: '/a//b?x=1' }, rules),
Visualizza la risposta completa di Claude Opus 5.5 così come è stata inviata

Questa è la risposta completa ricevuta. Si interrompe a metà perché ha raggiunto il limite; il contenuto mancante non è stato reintegrato.

{"files":{"src/router.js":"'use strict';\n\nconst LETTERS = /^[A-Za-z]+$/;\n\nfunction isPlainObject(value) {\n  return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction isMethodName(value) {\n  return typeof value === 'string' && value.length > 0 && LETTERS.test(value);\n}\n\nfunction stripQueryAndFragment(path) {\n  const q = path.indexOf('?');\n  const h = path.indexOf('#');\n  let cut = -1;\n  if (q !== -1 && h !== -1) cut = Math.min(q, h);\n  else if (q !== -1) cut = q;\n  else if (h !== -1) cut = h;\n  return cut === -1 ? path : path.slice(0, cut);\n}\n\nfunction normalizePrefix(prefix) {\n  let end = prefix.length;\n  while (end > 0 && prefix[end - 1] === '/') end -= 1;\n  return end === 0 ? '/' : prefix.slice(0, end);\n}\n\nfunction prefixMatches(path, prefix) {\n  if (prefix === '/') return true;\n  return path === prefix || path.startsWith(prefix + '/');\n}\n\nfunction chooseRoute(request, rules) {\n  try {\n    if (!isPlainObject(request) || !Array.isArray(rules)) return null;\n    const method = request.method;\n    const rawPath = request.path;\n    if (!isMethodName(method)) return null;\n    if (typeof rawPath !== 'string' || rawPath[0] !== '/') return null;\n\n    const path = stripQueryAndFragment(rawPath);\n    const upperMethod = method.toUpperCase();\n\n    let bestExact = null;\n    let bestWildcard = null;\n\n    const count = rules.length;\n    for (let i = 0; i < count; i += 1) {\n      const rule = rules[i];\n      if (!isPlainObject(rule)) continue;\n      const ruleMethod = rule.method;\n      const prefix = rule.prefix;\n      const target = rule.target;\n      const isWildcard = ruleMethod === '*';\n      if (!isWildcard && !isMethodName(ruleMethod)) continue;\n      if (typeof prefix !== 'string' || prefix[0] !== '/') continue;\n      if (prefix.indexOf('?') !== -1 || prefix.indexOf('#') !== -1) continue;\n      if (typeof target !== 'string' || target.length === 0) continue;\n\n      const normalized = normalizePrefix(prefix);\n      if (!prefixMatches(path, normalized)) continue;\n\n      const candidate = { length: normalized.length, target };\n      if (isWildcard) {\n        if (bestWildcard === null || candidate.length > bestWildcard.length) bestWildcard = candidate;\n      } else if (ruleMethod.toUpperCase() === upperMethod) {\n        if (bestExact === null || candidate.length > bestExact.length) bestExact = candidate;\n      }\n    }\n\n    if (bestExact !== null) return bestExact.target;\n    if (bestWildcard !== null) return bestWildcard.target;\n    return null;\n  } catch (err) {\n    return null;\n  }\n}\n\nmodule.exports = { chooseRoute };\n","test/router-added.test.js":"'use strict';\n\nconst test = require('node:test');\nconst assert = require('node:assert/strict');\nconst { chooseRoute } = require('../src/router.js');\n\nconst baseRules = [\n  { method: 'GET', prefix: '/api', target: 'api' },\n  { method: 'GET', prefix: '/api/admin', target: 'admin' }\n];\n\ntest('existing regression cases still hold', () => {\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, baseRules), 'api');\n  assert.equal(chooseRoute({ method: 'POST', path: '/api/users' }, baseRules), null);\n});\n\ntest('longest prefix wins within method group', () => {\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/admin/x' }, baseRules), 'admin');\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/admin' }, baseRules), 'admin');\n});\n\ntest('segment boundaries', () => {\n  const rules = [{ method: 'GET', prefix: '/api', target: 'api' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'api');\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/' }, rules), 'api');\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'api');\n  assert.equal(chooseRoute({ method: 'GET', path: '/apix' }, rules), null);\n  assert.equal(chooseRoute({ method: 'GET', path: '/ap' }, rules), null);\n});\n\ntest('trailing slashes in prefixes are normalized, all-slash is root', () => {\n  const rules = [{ method: 'GET', prefix: '/api///', target: 'api' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'api');\n  assert.equal(chooseRoute({ method: 'GET', path: '/apix' }, rules), null);\n  const rootRules = [{ method: 'GET', prefix: '///', target: 'root' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/' }, rootRules), 'root');\n  assert.equal(chooseRoute({ method: 'GET', path: '/anything/else' }, rootRules), 'root');\n  assert.equal(chooseRoute({ method: 'GET', path: '/x' }, [{ method: 'GET', prefix: '/', target: 'r' }]), 'r');\n});\n\ntest('query and fragment are removed at earliest ? or #', () => {\n  assert.equal(chooseRoute({ method: 'GET', path: '/api?next=/api/admin' }, baseRules), 'api');\n  assert.equal(chooseRoute({ method: 'GET', path: '/api#/admin' }, baseRules), 'api');\n  assert.equal(chooseRoute({ method: 'GET', path: '/apix?/api' }, baseRules), null);\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/admin#frag?q' }, baseRules), 'admin');\n  assert.equal(chooseRoute({ method: 'GET', path: '/api?q#/admin' }, baseRules), 'api');\n});\n\ntest('no URL decoding and no slash collapsing', () => {\n  const rules = [{ method: 'GET', prefix: '/api/admin', target: 'admin' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api%2Fadmin' }, rules), null);\n  assert.equal(chooseRoute({ method: 'GET', path: '/api//admin' }, rules), null);\n  assert.equal(chooseRoute({ method: 'GET', path: '/api//admin' }, baseRules), 'api');\n});\n\ntest('methods compare case-insensitively', () => {\n  const rules = [{ method: 'get', prefix: '/a', target: 'lower' }];\n  assert.equal(chooseRoute({ method: 'GET', path: '/a' }, rules), 'lower');\n  assert.equal(chooseRoute({ method: 'gEt', path: '/a/b' }, rules), 'lower');\n});\n\ntest('exact method beats longer wildcard; wildcard used only as fallback', () => {\n  const rules = [\n    { method: '*', prefix: '/api/admin', target: 'wild-admin' },\n    { method: 'GET', prefix: '/', target: 'get-root' },\n    { method: 'POST', prefix: '/other', target: 'post-other' },\n    { method: '*', prefix: '/api', target: 'wild-api' }\n  ];\n  assert.equal(chooseRoute({ method: 'GET', path: '/api/admin/x' }, rules), 'get-root');\n  assert.equal(chooseRoute({ method: 'POST', path: '/api/admin/x' }, rules), 'wild-admin');\n  assert.equal(chooseRoute({ method: 'POST', path: '/api/x' }, rules), 'wild-api');\n  assert.equal(chooseRoute({ method: 'POST', path: '/other/1' }, rules), 'post-other');\n  assert.equal(chooseRoute({ method: 'PUT', path: '/nothing' }, rules), null);\n});\n\ntest('ties go to earlier rule in input order', () => {\n  const rules = [\n    { method: 'GET', pref

Il limite massimo di 4.096 token era il budget di output scelto per questo test, non il massimo documentato di alcun modello. Il risultato dell’instradamento suggerisce di effettuare una verifica pratica prima di inviare una richiesta più ampia: stimare le dimensioni dell’implementazione, dei test e della spiegazione che ci si aspetta di ricevere. Potrebbe essere opportuno suddividere i risultati finali o concedere più spazio per l’output; non abbiamo rieseguito questi output con impostazioni diverse.

Per quanto riguarda il tuo compito, valuta separatamente tre aspetti: se la risposta è completa, se il codice supera controlli utili e se la revisione individua lacune sfuggite a tali controlli. Il superamento di dodici controlli sulle funzioni non ha reso nessuna delle risposte troncate, composte da due file, una consegna completa.

In che modo la scelta del modello influisce sui costi?

Claude Code è lo strumento di codifica; Haiku, Sonnet, Opus e Fable sono le opzioni disponibili all’interno dell’ambiente supportato. Anche le modalità di autenticazione e pagamento sono a scelta. Cambiare l’opzione non trasforma un abbonamento in un account API né elimina tutti i limiti di utilizzo.

Percorso di fatturazioneCosa guardareCome interpretare la scelta del modello
Accesso in abbonamento ClaudeUtilizzo incluso nel piano e eventuali crediti di utilizzo attivati separatamenteI diversi modelli possono consumare le quote in modo diverso; verifica i modelli disponibili nel piano e i relativi limiti
Accesso all'API AnthropicToken di input/output, memorizzazione nella cache e costi API applicabiliUtilizza il listino prezzi attuale e i dati di consumo effettivi, quindi conferma gli addebiti nella console di fatturazione
Fornitore di servizi cloud o gatewayID, tariffe e dati di fatturazione supportati dal tuo fornitoreUn esempio di prezzo di listino Anthropic potrebbe non corrispondere all'importo addebitato dal proprio fornitore
La selezione del modello e la fatturazione sono correlate, ma è il percorso di fatturazione a determinare le modalità di addebito dei consumi.

Nel codice Claude, /uso mostra le informazioni relative al token di sessione e, se del caso, le barre di utilizzo dell'abbonamento. L'importo in dollari è una stima calcolata localmente sulla base delle tariffe di listino o di quelle configurate; non si tratta di una fattura. Per gli abbonati alle versioni Pro e Max, tale importo relativo alla sessione non implica l'aggiunta di un addebito API aggiuntivo all'abbonamento. Maggiori informazioni su Claude: modalità di determinazione dei prezzi e di fatturazione se stai decidendo come pagare.

Prezzi attuali delle API ed esempio di token equivalenti

I tassi base standard di Anthropic per ogni milione di token in entrata/uscita sono Haiku 4.5: $1/$5; Sonnet 5: $2/$10; Opus 5.5: $4/$20; Fable 5.1: $10/$50, consultato il 28 settembre 2026. Il grafico seguente mantiene costante il volume dei token, in modo da facilitare il confronto dei dati.

Stesso volume di token, quattro diversi costi API

Esempio: 100.000 token di input non memorizzati nella cache + 10.000 token di output, sulla base dei normali prezzi di listino delle API di Anthropic verificati il 28 settembre 2026.

Haiku 4.5$0.15
Sonetto 5$0.30
Opus 5.5$0.60
Fable 5.1$1.50
Visualizza le tariffe e il calcolo
USD per milione di token e l'esempio di calcolo
ModelloIngresso / 1MUscita / 1MTotale dell'esempio
Haiku 4.5$1$5$0.15
Sonetto 5$2$10$0.30
Opus 5.5$4$20$0.60
Fable 5.1$10$50$1.50

Calcolo: 0,1 × frequenza di ingresso + 0,01 × frequenza di uscita. Per Opus 5.5: 0,1 × $4 + 0,01 × $20 = $0,60.

Si tratta di un esempio con un numero fisso di token. Le operazioni effettive consumano un numero totale di token variabile; le operazioni di scrittura e lettura nella cache, i tentativi di ripetizione, gli strumenti, la fatturazione del provider e i limiti dell'abbonamento richiedono una contabilità separata.

Fonte: Prezzi API Anthropic.

Tabella dei prezzi dell'API di Anthropic con le tariffe relative a input, output e cache dei prompt.
I normali prezzi di listino delle API sono espressi per milione di token; le operazioni di scrittura e lettura nella cache hanno tariffe distinte.

Un'attività Claude Code vera e propria è costituita da una sequenza di richieste. Il contesto precedente potrebbe essere inviato nuovamente, un modello potrebbe approfondire l'analisi e strumenti o agenti aggiuntivi potrebbero generare ulteriore lavoro. La memorizzazione nella cache dei prompt presenta inoltre velocità di scrittura e lettura distinte. La barra più bassa nell'esempio, pertanto, non indica il costo più basso per modifica accettata.

Cinque modi per contenere i costi senza compromettere l'efficacia dell'intervento

  1. Definire i criteri di accettazione prima di scegliere un modello. Indica il comportamento previsto, i casi limite e i vincoli esistenti. Un compito chiaro e di portata limitata è più facile da delegare in termini di costi e più semplice da verificare.
  2. Fornisci il contesto pertinente. Includi i file e i dettagli relativi agli errori richiesti dal modello. Per attività non correlate, avvia una nuova conversazione invece di portare avanti una lunga cronologia solo perché esiste.
  3. Distinguere la capacità dallo sforzo. Anthropic consiglia di iniziare con lo sforzo predefinito del modello. Se il modello ha interpretato correttamente il contesto ma non è comunque riuscito a risolvere il problema, potrebbe essere utile un modello più potente. Se ha saltato la fase di lettura o di verifica, controlla la configurazione dell'attività e la scelta dello sforzo.
  4. Preventivo per l'intera risposta. Il codice sorgente, i test e le spiegazioni richiedono tutti spazio per essere visualizzati. Il nostro secondo compito mostra perché una funzione completa di per sé non è prova sufficiente che il risultato richiesto rientri nel budget.
  5. Confronta i lavori accettati. Registra i risultati utili, i tentativi di ripetizione, i tempi di revisione e i dati di fatturazione effettivi relativi ad attività rappresentative. Distingui gli errori dei fornitori da quelli legati alla qualità del modello.

Queste strategie sono in linea con il guida ufficiale ai costi e Linee guida di Anthropic su modelli e impegno. Un limite settimanale o per sessione a livello di piano può rimanere in vigore dopo un cambio di modello; un limite specifico per un modello rappresenta invece una situazione diversa. Verifica il limite effettivo prima di effettuare cambi ripetuti.

Se il tuo lavoro spazia tra programmazione, ricerca, scrittura e media, confronta anche il flusso di lavoro per cui stai pagando. L'area di lavoro multimodello di GlobalGPT riunisce tali funzioni in un’unica dashboard con accesso tramite CLI per le attività di sviluppo. È utile valutare questo valore aggiunto in termini di flusso di lavoro insieme a una tariffa a consumo per le API; il grafico delle API riportato sopra non rappresenta un listino prezzi degli abbonamenti GlobalGPT.

Perché il modello che hai scelto potrebbe non funzionare

SintomoProbabile controlloProssimo passo concreto
La sessione successiva utilizza il vecchio modelloÈ possibile che l'impostazione fosse valida solo per quella sessioneUtilizza l’azione “Invio” del selettore per salvare, quindi seleziona una nuova sessione
La preferenza viene salvata, ma viene avviato un modello diversoUn'impostazione relativa al lancio, al shell, al progetto, alla gestione o all'organizzazione potrebbe avere la prioritàLeggere le informazioni relative all'avvio e verificare la configurazione pertinente insieme al responsabile
Una conversazione ripresa segue uno schema diversoLa sessione salvata potrebbe ripristinare il modello precedenteControlla /status; scegli con attenzione il modello desiderato per riprendere il lavoro
Il modello è mancante o è stato rifiutatoDisponibilità dei fornitori, regole organizzative o una versione precedente del codice ClaudeVerificare gli ID dei modelli supportati, l'accesso all'account e i requisiti di versione
Lo stesso cognome viene interpretato in modo diverso altroveGli alias e le mappature dei provider differisconoUtilizzare l'ID completo corretto del provider quando una versione deve rimanere fissa
Il cambio di operatore non azzerano il limite di utilizzoIl limite potrebbe applicarsi all'intero pianoLeggi il messaggio relativo all'utilizzo e reimposta il periodo, anziché dare per scontato che basti cambiare piano familiare
Valutare l'entità del problema prima di modificare un'altra impostazione.

Se il codice Claude non riesce a salvare le impostazioni dell'utente, una scelta interattiva può rimanere attiva per la sessione corrente senza essere salvata in modo permanente. Un file di impostazioni gestito o generato potrebbe richiedere una modifica da parte del proprietario, anziché un altro tentativo di selezione. Evitare di rimuovere le restrizioni aziendali al solo scopo di far apparire un'opzione.

Crea un flusso di lavoro più ampio con GlobalGPT

La selezione del modello è solo una delle fasi del flusso di lavoro. Potrebbe essere necessario effettuare ricerche in una libreria, scrivere una bozza di funzione, spiegare una modifica a un collega, creare documentazione e preparare risorse visive. GlobalGPT riunisce diversi modelli all’avanguardia e funzioni di intelligenza artificiale in un unico spazio di lavoro a prezzi accessibili, consentendo di gestire tutte queste attività nella stessa dashboard.

Per il lavoro al terminale, il GlobalGPT CLI collega gli strumenti della piattaforma agli ambienti di sviluppo. La procedura di configurazione documentata prevede l’utilizzo delle credenziali di accesso all’account GlobalGPT e del saldo normale dell’account. L’interfaccia a riga di comando (CLI) è in grado di supportare un flusso di lavoro più ampio di programmazione e creazione, mentre il modello proprio di Claude Code rimane una scelta deliberata grazie ai suoi controlli di modello.

Ad esempio, redigere e rivedere un piano di implementazione, utilizzare un altro modello per fornire una spiegazione concisa, quindi produrre la documentazione o le risorse che accompagnano il rilascio. Seguire la guida per Collegare la CLI del GlobalGPT al codice del Claude quando desideri integrare quello strumento. Configura separatamente il modello di ragionamento del codice Claude in base all’attività di codifica.

Scegliete un modello di partenza, individuate i criteri che definiscono il successo e passate al livello successivo quando l’attività lo richiede. Verificate il risultato finale prima di considerare il lavoro concluso. Crea il tuo flusso di lavoro con GlobalGPT quando desideri che la scelta dei modelli, la ricerca, la programmazione e gli strumenti creativi siano integrati nel tuo lavoro quotidiano.

FAQ

Come si modifica il modello nel codice Claude?

Esegui /model per aprire il selettore. Premi s per cambiare solo la sessione corrente, oppure Invio per salvare il modello selezionato come predefinito. Per scegliere un modello per una singola nuova sessione, avvia il programma con claude –model seguito dal nome del modello.

La funzione /model modifica le mie impostazioni predefinite salvate?

Nelle attuali versioni interattive, selezionando un modello con il tasto Invio o digitando /model sonnet, la scelta viene salvata nelle impostazioni utente, se queste sono modificabili. Premendo la lettera "s" nel selettore, la scelta ha validità solo per la sessione corrente. Al prossimo avvio, altre impostazioni potrebbero comunque avere la precedenza.

Qual è il modello predefinito del codice Claude?

L'impostazione predefinita di runtime dipende dall'account, dal provider e dalla configurazione. Il valore predefinito cancella l'override del modello; non si tratta di un ID modello fisso. Verifica il modello attivo con /status e controlla il selettore, invece di dare per scontato che tutti gli account partano dalla stessa versione.

Di cosa si occupa Opusplan?

Utilizza Opus in modalità di pianificazione e Sonnet in fase di esecuzione. Segue la transizione tra le modalità anziché scegliere automaticamente il modello più economico per ogni prompt. Il costo effettivo dipende dal lavoro svolto in ciascuna fase.

Perché nel selettore manca un modello?

La disponibilità può dipendere dal provider, dall'account, dalle restrizioni dell'organizzazione e dalla versione del codice Claude. Controlla la documentazione relativa al modello attuale e i modelli consentiti nel tuo ambiente. Un alias di famiglia può anche corrispondere a una versione diversa su un altro provider.

Un modello più economico rende sempre un'attività più economica?

No. Il prezzo del token è solo uno dei fattori. L'utilizzo totale, le risposte incomplete, i tentativi successivi e lo sforzo di revisione incidono sul costo di una modifica accettabile. Nel nostro piccolo refactoring tutte e tre le funzioni sono state superate, mentre tutte e tre le risposte più grandi, composte da due file, sono state troncate al limite di output condiviso.

Fonti

Condividi il post:

Messaggi correlati