Changelog
Cosa c'è di nuovo.
Ogni miglioramento alla piattaforma, come si spedisce.
· kamo-internal
Bulk-reassign selezionato porta a un membro del team
La griglia aveva già caselle di controllo multi-seletto ma niente a che fare con una selezione. Controllare le righe ora rivela un'azione di Riassegna accanto alle altre azioni di piombo, gated su REASSIGN LEADS MANUALL (il server lo ricontrolla; questa è solo convenienza). Utilizza il checkRight piuttosto che controllareRole in modo che la modalità dio corrisponda all'hashtad del backend bypass — checkRole non bypassa e si diverte per gli utenti di dio. La finestra di dialogo sceglie un membro di destinazione per ricerca, prende una nota facoltativa, e dice davanti che il membro sarà inviato via e-mail, dal momento che è il punto del caratteristica. Indigo/blu piuttosto che Hot Reassign's arancione/rosa: questo è un deliberata azione amministratore di massa, non un trasferimento di chiamata urgente. La casella di controllo dell'intestazione seleziona ogni riga nella griglia lato client — migliaia per una grande org — così il berretto 250 è applicato anche qui. Altrimenti il titolo "seleziona tutto e riassegna" il flusso fallirebbe lato server solo dopo che l'utente aveva riempito nell'intera finestra di dialogo, con un errore non tradotto. La selezione viene cancellata tramite selezionatoIdsRef prima di ricaricare: loadLeads ri-seleziona qualsiasi cosa detiene, così lasciandolo popolato ricontrollare Le file si sono appena spostate. Il messaggio di risultato è composto piuttosto che un'altra catena, perché un lotto può essere sia parziale che unnotificata e la catena riportata solo il primo.
· SecurityService
Punto finale del marchio Bulk-reassign, gated su REASSIGN LEADS MANUALLY
# POST # # Mossa un lotto di contatti in una squadra # membro e-mail che membro una volta per l'intero lotto. L'autorizzazione utilizza REASSIGN LEADS MANUALLY (149) — il diritto denominato per esattamente Questo. Questo è più rigoroso del percorso a singolo percorso su PUT /leads/{id}, che controlli ASSIGN LEADS; riassegnare un centinaio di cavi è un raggio di esplosione diverso da riassegnare uno, e i due diritti esistono in modo che possano essere concessi a parte. Anche il livello di visibilità non assegnato viene applicato qui. Assegnazione È una visibilità sovvenzione: una volta che un piombo è assegnato al chiamante legge come "assegnato a me", che solleva il 403 non firmato e salta la maschera contact-info. Senza questo controllare un chiamante che tiene 149 ma non VIEW UNASSIGNED LEADS potrebbe autoassegnare i lead la griglia si nasconde da loro e li ricicla in quelli completamente leggibili. Scivolo porta la relazione NOT FOUND — corrispondente a ciò che la propria griglia mostra — così la risposta non può enumerare indizi nascosti o stranieri. Il lotto non è deliberatamente all-or-nothing: ogni assegnaLead corre in proprio transazione e un cattivo id diventa un salto, perché scartando nove buoni le riassegnazioni sul decimo sono peggiori di quelle che non hanno preso. Catturato a 250 per chiamata per legare sia le serrature di riga e il fan-out in tempo reale. Il notificante risolve i suoi dati in una breve transazione attraverso un fagiolo separato e invia dopo, quindi una chiamata in uscita con un timeout di lettura di 30s mai pins un Collegamento CRDB. Attraversare il confine del fagiolo è anche ciò che rende @Transactional applicare a tutti — l'autoinvocazione sarebbe silenziosamente eseguito senza transazione e LAZY associazione utente avrebbe gettato.
· EmailService
Variabili del campione per il modello LEADS ASSIGNED
Senza un caso qui l'Anteprima dell'editor del modello di amministratore rende il nuovo modello con ogni segnaposto vuoto, che legge come modello rotto piuttosto che un non riempito. noteBlock è pre-rendered HTML perché il renderer non ha condizionali — il mittente lo collassa a "" quando non c'è nota.
· kamo-shared-library
LEADS ASSIGNED modello di e-mail; indurire assegnarePer uso di massa
assegnareLead aveva zero chiamanti e non aveva mai eseguito in produzione. Prima del cablaggio percorso di riassegnamento di massa ad esso, dare le garanzie che il percorso ha bisogno: - prendere orgId e verificare BOTH il piombo e il nuovo cessionario appartengono ad esso, quindi un il riassegnamento non può raggiungere attraverso gli inquilini (riportato come "non trovato" piuttosto che "proibito" in modo che l'errore non possa essere utilizzato per sondare id di piombo stranieri) - bloccare la riga con findByUidForUpdate: un riassegnamento manuale e un concorrente accettazione della piscina bersaglio lo stesso piombo e altrimenti si interpellerebbe in un perso aggiornamento - liberare le bandiere della piscina, specchiando CreditLeadAssignmentService. Una pista segnata per auto-assegnamento altrimenti rimane in piscina dopo essere stato rivendicato a mano e viene preso da sotto il suo nuovo proprietario - pubblicare chat routing, come updateLead già fa, quindi il mutuatario aperto dal vivo chat segue il piombo invece di rimanere con il precedente ufficiale Aggiungi anche il modello canonico LEADS ASSIGNED. La chiave deve essere in CANONICAL KEYs o non può mai essere seme e non può mai self-heal, e ogni invio restituisce un permanente 404.
· kamo-shared-library
Aggiungi MANAGE ORG BRANDING (174)
Org branding endpoints (logos, colori, sfondi, tema provisioning) erano proprietario-o-god solo, senza lasciare il modo di delegare il branding senza cedere proprietà dell'org. Aggiunge il diritto delegable; i controlli del proprietario rimangono come un sovvenzione implicita così i proprietari esistenti continuano a lavorare senza essere assegnati.
· kamo-internal
Autore matrici di ammissibilità dal pannello di catalogo
Senza una matrice che copre l'occupazione e lo scopo di uno scenario, i prezzi restituisce NO COVERAGE — così prima di questo, solo un acquisto di una residenza primaria potrebbe essere valutato. La forma autori un matrice e le sue celle per un tipo di limite prescelto, occupazione e scopo, con cella add/remove righe, accanto al modulo lock-policy nello stesso pannello. Lasciando il prodotto unset autori una matrice per prodotto ACTIVE dell'investitore, perché la portata del prodotto della matrice NON è NULL e non può esprimere "tutti i prodotti" come una singola riga.
· SecurityService
Relay eligibility-matrix che autorizza; ricostruire raccoglie il curriculum SUSPENDED
Relè POST ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** aiutante, così un steward autori matrices solo per il loro inquilino. Questa spinta si ricostruisce anche contro il cambiamento condiviso-lib che consente un curriculum di prestito SUSPENDED. kamo-shared-library non ha CI del proprio — ogni cloni di servizio e lo costruisce dalla fonte — in modo che la correzione raggiunge questo servizio solo quando questo servizio ricostruisce.
· kamo-internal
Ricostruire lo studio agente come uno spazio di lavoro a tutta la larghezza
Rimuovere il tappo di larghezza non era la correzione; il layout stesso doveva essere progettato per lo spazio piuttosto che tollerato in esso. Lo studio è ora tre zone laterali: - ** Ferrovia esterna** — le sezioni, con quella corrente evidenziata mentre si scorre (IntersezioneObserver, sovrappeso in modo che una sezione diventi corrente quando la sua intestazione raggiunge dove l'attenzione è realmente). Sezioni scritte a mano sono marcate, quindi un parte scritta a mano è rilevabile in seguito senza aprire ciascuno. - **Editor** — le sezioni stesse, che si inseriscono in altrettante colonne come viewport detiene invece di un nastro stretto. - **Live talking** — una colonna reale su un ampio display, non una striscia che collassa il contenuto quando aperto. Questo è il loop edit-and-watch dello studio esiste per: cambiare un'istruzione, vedere il cambiamento di risposta, senza navigare. Un'istanza TestDrivePanel, riposizionata piuttosto che duplicata — montandola due volte inizierebbe due sessioni di lancio. Sotto xl scende sotto l'editor come una riga di larghezza piena piuttosto che schiacciare una terza colonna su un display senza stanza per uno, e la ferrovia si nasconde interamente su piccoli schermi.
· kamo-internal
Autorizzare politiche — senza uno, nessun tasso può essere bloccato a tutti
RateCommitmentService rifiuta una serratura ogni volta che il risultato prezzo non porta lockPolicyVersionId ("la versione lock-policy è richiesta"), e un risultato porta solo se l'investitore ha una versione pubblica di lock-policy. Nessun UI potrebbe pubblicarne uno, quindi il blocco della tariffa era irraggiungibile per ogni inquilino, mentre il punto finale era già costruito, e sovrascrivendo correttamente. Mancava solo il metodo del cliente e questo modulo. Il modulo prende i periodi di blocco offerti come elenco ordinato perché il PRIMO diventa il default, quindi deliberatamente non li ordina; voci che non sono un tutto positivo il numero di giorni sono calati piuttosto che inviati come termine di blocco cattivo.
· kamo-internal
Mostra come ogni agente sta facendo
Aggiunge una sezione delle prestazioni alla parte superiore dello studio agente: conversazioni, come spesso una persona ha preso il sopravvento e ciò che ha innescato, risultati di outreach, e il costo. Scritto in modo che nessuna figura può ingannare: - Zero rende come la parola 'None', mai 0. - Una quota rende solo quando c'è un denominatore; altrimenti 'No conversazioni ma per comparare». Non ci sono percentuali zero-denominatore. - Quando nulla nel periodo ha portato un prezzo, nessuna cifra di costo è mostrata affatto - solo una spiegazione che il prezzo è stato istituito dopo il traffico è accaduto. Parziale la copertura mostra l'importo più quante risposte mancano da esso. - L'eccessiva intolleranza è presentata come la caratteristica che è: 'Questi sono mantenuti su scopo - sono il tuo record di perché qualcuno non è stato contattato. ' - I codici enum sconosciuti si degradano al testo leggibile piuttosto che ad un percorso chiave grezzo. Il messaggio di perversione e le colonne di handoff sono state rimosse: l'API non aggrega loro per versione, quindi quelle celle avrebbero reso un 0 fabbricato come se era stato misurato. Conversazioni da sole rispondere a quello che la tabella è per - che salvato copia gestito quale traffico. Piegato nel documento dello studio di scorrimento esistente piuttosto che una nuova scheda, e tenuto fuori dalla lista agente, dove un nudo 0 contro ogni agente sarebbe l'esatto errato essere evitato.
· AIService
Scheda di punteggio per età
Ciò che ogni agente effettivamente ha fatto: conversazioni, quanto spesso una persona ha dovuto prendere il sopravvento e perché, supera i risultati tra cui quelli tenuti indietro, e che cosa costa. Ogni numero è uno che i dati possono effettivamente supportare. Tre cose sono deliberatamente Non qui: - Niente token totals. Sono reali sul percorso di sincronizzazione e fabbricati sul streaming uno (content.length()/4), quindi ogni totale è parte inventato. Le risposte ai costi la stessa domanda onestamente, perché è nullo piuttosto che indovinare dove il il prezzo è sconosciuto. - ** Nessuna risoluzione o flessione. Niente osserva se una conversazione finito bene, e 'nessun handoff si è verificato' non è prova di successo. ** Nessun messaggio di perversione o conteggi di consegna.** Questi non sono aggregati per versione, emettendo 0 per loro sarebbe una fabbricazione reso come una misura - il guasto preciso che questa schermata esiste per evitare. Il costo porta una bandiera esplicita e un importo nullo piuttosto che 0 quando niente nella finestra è stato prezzo, quindi un org il cui traffico anticipa i prezzi vede 'non registrato' invece di un fiducioso $0,00. prezzodCalls è l'autorità piuttosto che la somma, così uno zero genuino dalle chiamate free-tier a prezzi ancora legge come rintracciato. La prosa transcript è gated su VIEW SALES AGENT TRANSCRIPTS separatamente dal conteggi - il riassunto del modello di un visitatore specifico è contenuto di conversazione, non un metrico. Agenti senza traffico riportano una scheda di punteggio vuota strutturalmente completa: un agente scomparso dalla lista legge come un bug, un agente presente con zeros legge come la verità. parseHandoffArguments è ora condiviso con il percorso di chat piuttosto che implementato, così la coercizione di motivi inventati a ALTRE non può derivare tra i due. Suite è 150 test, verde.
· kamo-shared-library
Domande aggregate raggruppate per l'agente scorecard
Dodici aggregati @Query attraverso sessioni, messaggi, record di utilizzo e in uscita tatti, quindi una scheda di punteggio è una manciata di domande raggruppate piuttosto che caricare righe in memoria. Due proprietà sono applicate nei predicati piuttosto che lasciate ai chiamanti: - Si'. Le sessioni di test sono escluse nella query stessa.** Su un giovane agente i propri test drive dell'autore altrimenti sarebbero la maggior parte dei dati, e un chiamante che dimentica di filtrare produce numeri che sembrano reali e non lo sono. - **conto(costEstimate) conta solo costi NON NULL.** Questo è ciò che lascia scorecard distinguere 'nothing was priced' da 'it cost zero' - collapsing quelli avrebbero messo un fiducioso $0,00 di fronte a un org il cui traffico semplicemente preda i prezzi. I tocchi in uscita sono raggruppati per decisione piuttosto che filtrati per inviare. The i rifiuti sono la metà più interessante: un agente i cui tocchi sono quasi tutti SUPPRESSED QUIET HOURS è configurato male, e questo è invisibile se i decodificatori sono scartato.
· kamo-internal
Modificare i costi di ogni modello
Aggiunge la modifica dei prezzi per modello alla schermata di configurazione del fornitore. I prezzi sono seminati ogni venditore ha pubblicato il prezzo di listino dove lo conosciamo, e vuoto dove non lo facciamo - un mezzo vuoto costo semplicemente non è tracciato per quel modello, che è meglio di un numero che è sicuro di sbagliato. Copia dice alle persone di controllare le cifre semenzate contro il proprio disegno di legge piuttosto che presentarle come autorevoli. Risolve un bug di visualizzazione catturato in recensione: il taglio trailing-zero avrebbe reso un prezzo di 10 come 1. Ora spoglia zeros solo dopo il punto decimale.
· AIService
Catalogo prezzi modello, percorso di scrittura e backfill
La contabilità dei costi non potrebbe mai funzionare: AiModel ha colonne di prezzo, AiModelController li legge e Chat OrchestrationService li legge per calcolare il costoEstimate - ma NONHING li ha scritti ovunque. I modelli sono creati solo dalla scoperta del fornitore, e nessun provider API restituisce i prezzi. 140 modelli, 0 prezzo, nessun percorso da cui quello potrebbe cambiare. Le colonne erano strutturalmente irraggiungibili. Tre parti: - ModelPricingCatalog semi fornitore LIST prezzi alla scoperta, abbinati a un identificatore normalizzato con una regola di prefisso di trattino in modo che gpt-4 non possa mai rivendicare gpt-4o. I modelli non-chat (TTS, embeddings, realtime) sono respinti da riutilizzando il controllo di modalità esistente - si fatturano un foglio diverso. - PATCH endpoint + UI in modo che un org possa correggere o cancellare un prezzo. Org-scopio esattamente come il DELETE esistente. - Riempire solo colonne NULL, per colonna in modo indipendente, e mai sovrascrive ciò che un org ha impostato - altrimenti rendere i prezzi modificabili sarebbe un bugia. Idempotent, e avvolto in modo che la contabilità dei costi non può mai bloccare il boot. **Un modello che non siamo sicuri di ottenere NO prezzo piuttosto che uno indovinato.** GPT-5, o3, la maggior parte Mistral, DeepSeek, xAI, Cohere e Meta sono volutamente vuoti; OpenRouter e HuggingFace non si abbinano mai al design, dal momento che fatturano le proprie tariffe e ereditare i prezzi a monte sarebbe un'ipotesi. Un prezzo sbagliato produce figura a forma di fattura che è fiduciosamente sbagliato - lo stesso motivo costo è ancora non calcolato sul percorso di streaming, dove i conteggi di token sono fabbricati. La conversione alla colonna per-1k utilizza RoundingMode. UNNECESSARIO di proposito: un prezzo bisogno di più di 6 decimali lancia a class-init piuttosto che silenziosamente memorizzare un ragione ed è lasciato vuoto. Suite è 145 test, verde.
· kamo-internal
Mostra il contesto di consegna AI all'agente che prende il sopravvento
Renders un evento di sistema AI HANDOFF come una carta con il motivo, il riassunto dell'IA, e una trascrizione pieghevole della conversazione finora - così il mutuatario fa non devono rispiegarsi alla persona che prende. I tre stati degradati sono espliciti e visibili piuttosto che silenziosi: trascrizione non disponibile, trascrizione troncata, e carico di pagamento spogliato in transito. Un agente deve mai essere lasciato credere di avere il contesto completo quando non lo fanno. Visitatore e agente condividono un argomento STOMP, in modo che il telaio in tensione arriva a rosso (il Il riassunto di AI è la sua valutazione privata del visitatore e non può andare al loro browser). Piuttosto che dire all'agente di ricarica, la scheda rilegge la riga completa una volta dal suo punto di vista autenticato. Il riletto viene convalidato prima che sia adottato - una risposta che è tornato fermo è respinto piuttosto che usato, così l'avvertimento può sempre chiaro quando il contesto è stato effettivamente guadagnato. Qualsiasi fallimento ritorna al messaggio di ricarica.
· APIService
Proxy il percorso pubblico AI->human handoff
Aggiunta di POST. proxied a MediaService accanto alla sua creazioneSupportSession fratello. Senza questo la funzione di consegna era morta all'arrivo: il punto finale di MediaService X-Internal-Auth, X-Public-Chat-Org-Id e X-Public-Chat-Key-Hash, che solo questo gateway inietta, quindi il widget's POST 404'd qui e mai l'ho raggiunto. Porta la stessa guardia condizionale**** come creareSupportSession. Passeggino l'intero percorso di creazione della sessione, in modo da procurarlo nudo avrebbe lasciato un percorso di creazione di biglietti che bypassa la prova-di-lavoro le sue forze di fratelli.
· MediaService
Portare la conversazione AI nel filo umano sul handoff
Crea o riutilizza la sessione di supporto, copia la trascrizione AI in un unico sistema evento, lo tratta, e dice al visitatore onestamente cosa succede dopo. La confidenzialità è divisa dal pubblico, che il primo passo ha avuto all'indietro. The Riepilogo e ragione di AI Dettagli sono la sua valutazione privata del visitatore, e pieno carico di pagamento stava raggiungendo il proprio browser del visitatore attraverso due porte REST e il telaio STOMP mentre l'agente non ha visto nulla. La Redazione si applica ora ad ogni percorso rivolto ai visitatori; la riga perseverata mantiene il carico di pagamento completo per l'agente. chat.session.{guid} è un unico argomento a cui entrambi i pubblici abbonano, quindi il live frame è tagliato a ciò che il visitatore può vedere e l'agente UI rilegge la riga completa dal suo punto di vista autenticato. Idempotency è fondamentale su aiSessionGuid, org-scoped, e controlla BEFORE creazione Qualsiasi cosa. Registrarlo sulla sessione e controllare dopo la creazione - l'ovvio forma - è inutile proprio quando conta: una riprovazione che ha perso la sessione token passa sempre il controllo e produce un biglietto duplicato e un secondo agente pagina. transcriptAttached now riferisce che cosa realmente è successo. In precedenza è tornato vero anche quando la scrittura aveva fallito silenziosamente, che è il peggio possibile combinazione: il visitatore viene detto che il loro contesto è venuto attraverso, il filo dell'agente è vuoto, e nessuna festa lo sa. Copy-on-handoff, non migrazione: l'intelligenza artificiale rimane dove l'analisi le legge.
· AIService
Spegnimento avviato da agente a un umano, con contesto
L'IA non poteva prima chiedere una persona: regole di escalation raggiunto il modello tramite il prompt compilato, ma non c'era un segnale leggibile dalla macchina, quindi il il modello poteva solo dire che avrebbe preso qualcuno e non è successo nulla. - Strumento sintetico kamo request human, descritto dalla propria abilitazione dell'agente titoli di regola di escalation in modo che il modello vede condizioni di trigger identiche nella prompt e lo strumento. Intercettato prima della spedizione MCP - è un segnale, non un vera chiamata strumento - e la riga TOOL persiste è ciò che rende la ragione durevole e analitico-pronto con zero nuove colonne. - Collegato SOLO quando il canale ha effettivamente il supporto live abilitato. Consegnare un AI-solo org uno strumento che promette un umano che non può mai arrivare è peggio di senza strumento: il widget non ha scheda di supporto, quindi il segnale è caduto e il il visitatore è lasciato in attesa di qualcuno che non è mai venuto. - Il nuovo endpoint interno restituisce la ragione di consegna, il riassunto dell'IA per chiunque prende il controllo, e la trascrizione USER/ASSISTANT. Le righe TOOL e SISTEMA sono escluso - l'uomo ha bisogno della conversazione, non del macchinario. - ragioneDettagli e riepilogo sono deliberatamente trattenuti dal browser del visitatore: sono la valutazione privata del modello del visitatore. Solo {richiesta, ragione} passa al client; MediaService recupera il lato server di riposo. - I giri dell'IA non vengono mai spostati o cancellati. AiChatMessage rimane il sistema di analisi di record; il lato umano ottiene una copia. Corregge anche un bug latente trovato sulla strada: gli strumenti bloccati ignorato il per-model supporta la bandiera ToolUse, quindi un modello esplicitamente contrassegnato come non strumenti di supporto è stato Li ha ancora mandati. 31 di 140 modelli sono falsi contrassegnati; ai mcp server configs è Il raggio d'esplosione di oggi è zero. Suite è 124 test, verde.
· MediaService
Accettare l'accesso autorizzato dall'agente in un thread del mutuatario aperto
La controparte AIService sta contattando il mittente. Senza tutto questo percorso di uscita terminato in un registrato 404 - il cancello ha autorizzato un tocco, il messaggio era composto, e non c'era posto per metterlo. I soggiorni di proprietà si dividono deliberatamente: AIService decide WHETHER un tocco può uscire e scrive il testo, questo servizio lo colloca. Scrivere queste righe da AIService forcherebbe la proprietà della trascrizione al servizio che possiede né la chat tavoli e la presa. Due cose che non farà. Non crea mai una conversazione - outreach può riprendere un thread il visitatore già aperto, mai evoca una finestra di chat a qualcuno che no. E non attraversa mai org: un piombo uid che risuona al biglietto di un altro org avrebbe messo l'agente di un org dentro la conversazione di un altro org, quindi l'org è controllato contro il biglietto piuttosto che fidato dal chiamante. Il messaggio è attribuito al membro della sessione, esattamente come un messaggio visitatore è - NON all'ufficiale umano assegnato. Rendere un messaggio AI-composto come anche se una persona chiamata, licenziata ha scritto che è quello che una regola di divulgazione AI esiste prevenire. assicurareSubscription precede il NATS pubblicare perché il consumatore utilizza Consegnare Policy. Nuovo: la pubblicazione per primo persiste il messaggio, ma lascialo cadere ogni client connesso. Restituisce sia id che messageId in modo che il registro di controllo di outreach fa riferimento al messaggio piuttosto che al thread. 404 quando non esiste un thread aperto, così il chiamante registra un fallimento pulito invece di assumere la consegna.
· AIService
Attivatori, programmatore e web-chat di spedizione
Fa fuoco alla spina dorsale. Il cancello, lo stato di contatto, il consenso e l'audit già esisteva; nulla ha causato un tocco da valutare. - NATS abilitato per AIService tramite il proprio k8s/configmap.yaml (ogni servizio Java trasporta il proprio k8s dir; KlusterServices detiene solo cluster infra). JetStream è volutamente lasciato OFF: NatsConfig afferma il proprio replica-fattore contro stream pianificati centralmente all'avvio, e AIService si iscrive solo al core NATS e non pubblica nulla, così permettendo che non avrebbe guadagnato nulla e rischiare un secondo servizio che afferma la replica conta. - AgentOutboundConsumer sottoscrive security.leads.rt.> e consuma SOLO LEAD CREATED/LEAD UPDATED. L'editore emette anche eventi di blocco e statistiche - raggiungere una persona perché un collega ha preso una serratura di modifica sul loro record non è degni di essere. Ids arrivano come stringhe dall'editore, quindi sono parsed come testo piuttosto che asLong(). - AgentOutboundScheduler valuta i trigger di programma sotto quattro limiti: org set derivato da agenti che in realtà hanno outreach su (capped), un sottile scorrevole fetta di tempo così costo tracce nuovo tasso di carico piuttosto che totale conduce, una fila per-tick cap, e un ammortizzatore di rivalutazione in modo da un passaggio di piombo durante le ore tranquille è retried una volta piuttosto che ogni zecca per un giorno. - Composizione semi testoCompleto con il prompt compilato della versione PUBLISHED, mai la bozza, piu' l'intento del grilletto. Composizione record di fallimento FAILED; non c'è nessun messaggio di fallback in scatola. - L'invio WEB CHAT continua un solo thread esistente. L'adesione può riprendere conversazione il visitatore ha aperto; non può coniugare una finestra di chat a qualcuno che non ne ha mai aperto uno. - percorso SMS/EMAIL/SOCIAL DM a un FAILED registrato che nomina la conformità mancante idraulico, quindi un org che indica un trigger a SMS vede perché nel registro di outreach immediatamente invece che non succede nulla. 23 nuovi test; suite è 68 e verde.
· kamo-internal
Required-text editor; dedupe Impostazioni generali AI; fix model toggle
Aggiunge un editor per org-wide richiesto apertura / chiusura del testo - il compilatore e le colonne esistevano ma niente poteva impostarle, quindi la capacità era morta. Copia afferma chiaramente che gli agenti non possono rimuoverlo e che il risparmio lo applica ad ogni agente immediatamente, e il brindisi riporta quanti agenti sono stati ripubblicati piuttosto che un nudo 'Saved', perché gli agenti dal vivo hanno appena cambiato quello che dicono. Due bug preesistenti trovati lungo il percorso: - L'interruttore 'Auto-Select miglior modello disponibile' non ha mai funzionato. Il frontend leggi i dati.autoSelectModel e invia autoSelectModel, ma il backend ritorna e si aspetta autoModelEnabled - così il gioco sempre reso vero e il suo valore era scartato su ogni salvataggio. Risolto frontend-side; nessuna modifica del server necessaria. - AiGeneralSettings.tsx era codice morto, mai importato, mentre un verbatim inline duplicato vissuto in fondo a SecurityModelsTab.tsx. Piuttosto che implementare testo richiesto due volte, il duplicato viene cancellato e SecurityModelsTab importa il componente condiviso. Inoltre sostituisce la punta di aiuto di vendite-agents, che ha ancora detto agli utenti la caratteristica era Presto.
· AIService
Persist org-wide richiesto testo e applicarlo immediatamente
AiOrgSettings guadagnato forzataPreamble / forzatoFoooter e SalesAgentCompiler già li ripiega in ogni agente, ma il controller delle impostazioni non legge né scrive loro - così la capacità era morta: un salvataggio sembrava avere successo e tornò vuoto su ricarica. GET ora restituisce entrambi i campi (comprese le impostazioni predefinite) e PUT li persiste, normalizzando vuoto a null così sgomberare un campo effettivamente lo sgombera piuttosto che lasciare una stringa vuota da piegare come separatore randagi. Il testo richiesto ora ha effetto IMMEDIATELY, ricompilando e ripubblicando ogni agente pubblicato nell'org. Lasciarlo applicare sulla prossima pubblicazione di ogni agente era più economico ed è una trappola: un amministratore che aggiunge 'sempre dire che sei un automatizzato l'assistente crederà che sia vivo, e un agente che nessuno si ripubblica Continuerebbe a parlare senza di essa indefinitamente. Una linea richiesta che fa silenziosamente non applicare è peggio di non offrire uno. Ogni agente interessato ottiene un nuovo salvato copia etichettata con il perché, e la risposta riporta quanti sono stati ripubblicati così l'UI può dire quello che è successo in realtà invece di solo 'Saved'.
· kamo-internal
Studio AI Sales Agent, in sostituzione dei modals
L'editor di agente era un ~800px MUI Dialog la cui superficie era di 10 fila textarea, su una scheda AI che ha usato una finestra di dialogo a tutti. È ora un dedicato route, e il modello di editing dietro è strutturato piuttosto che un blob. - /settings/ai/sales-agents/new — una colonna 720px, non lo studio. Carte modello (la carta è l'industria, quindi nessuna riduzione del settore), poi due campi: nome e una frase sul business. Un agente in meno di un minuto. - /settings/ai/sales-agents/[id] — larghezza piena, un documento di scorrimento con appiccicoso intestazioni di sezione, contenuto incassato a 880px in modo da ingressi a singola linea non sono allungati attraverso un display 4K. No 240px nav rail: nove sezioni è un lavoro a scorrimento-spy, non un Lavoro nav. - Try-it-out è un'intestazione di gioco piuttosto che una colonna permanentemente riservata. An vuoto finestra di chat accanto a un nuovo agente è sprecato spazio che legge come il l'utente non riesce a riempirlo. - La prontezza è un elenco ordinato e irricevibile di ciò che aiuterebbe - mai una frazione. Una frazione dice a qualcuno che stanno fallendo; una lista dice loro cosa fare dopo. - Le regole bloccate rendono bloccate e inaffidabili, e prendendo una sezione a mano avverte quando ne contiene uno (il compilatore ora li riapplica indipendentemente). - L'intestazione afferma chiaramente che le modifiche riguardano solo NUOVE conversazioni, perché il prompt istantanee alla creazione di sessione e gli utenti potrebbero altrimenti concludere il loro cambiamento non ha funzionato. - outboundEnabled viene inviato solo quando effettivamente cambiato: il server 403s l'intero MA se quel campo è presente senza MANAGE SALES AGENT OUTREACH, così incluso in ogni autosave avrebbe rotto lo studio per chiunque non abbia quel diritto. Rimuove anche il duplicato crudo " prompt del sistema AI" scatola dal canale di chat editore. Era un secondo posto più debole per autore la stessa cosa, senza versione, senza regole bloccate e nessuna storia — qualsiasi editor che è successo open ha deciso quello che i clienti hanno sentito. I suggerimenti esistenti ancora risolvono; canali usando uno ora ottenere un avviso che indica agli agenti. Copia non porta alcun gergo AI per design, e l'array di industria inglese hardcoded è sostituito con etichette tradotte.
· AIService
Compilatore di vendite-agent, versione, cancello di outreach; correzione riplay strumento
Agente strutturato config compila al prompt del sistema, congela per pubblicato versione, e ottiene il cancello un agente deve passare prima di iniziare il contatto. Compiler - AgentConfig + SalesAgentCompiler: compilazione pura e deterministica della struttura configurare in un prompt di sezione. Le sezioni vuote sono omesse in modo da tre rubriche agente non compila a un documento che è per lo più voci. - Override a livello di sezione ("scrivi questa parte tu stesso") piuttosto che un livello di documento grezzo-edit switch: un autore ottiene pieno potere espressivo su una sezione mentre ogni altra sezione continua a compilare, mantiene le regole bloccate e mantiene la versione. - Lo stesso meccanismo rende la migrazione byte-identica - prosa di un agente pre-config viene memorizzato come un override del documento intero e si compila indietro invariato, quindi la migrazione giorno è un no-op per gli agenti che già parlano con i clienti. Provato per prova. - PhraseBank è volutamente due dimensioni, con la buona prosa sul TEMPLATE. Una banca globale chiave su ogni combinazione di enum ha bisogno di ~90 paragrafi scritti a mano, degenera in clausole impilate, e renderebbe ogni org aperto con lo stesso frase - che distrugge l'unica cosa che un org sta comprando. - Sei modelli (front-desk e inbound-lead prima: sono orizzontali e coprire qualsiasi org il cui verticale non è elencato). Ogni nave ha bloccato le regole di conformità modello non può mai rimuovere, verificato da test. Durata + autorizzazione - Pubblica congela {config, compilatoPrompt, hash, model, provider}; rollback repoints e ripristina il progetto in modo che lo studio non possa mai mostrare una cosa mentre l'agente ne serve un altro. - Il controllore è per la prima volta con diritti. Precedentemente membro di qualsiasi org potrebbe riscrivere ciò che org dice ai suoi clienti. Cadute indietro a MANAGE AI SETTINGS in modo che nessun amministratore esistente è bloccato su distribuzione. - La chat pubblica preferisce il prompt congelato della versione pubblicata sul live formazioneContesto e francobolli venditeAgentId/versioneId sulla sessione - l'agente era già stato risolto lì e fu scartato. - Progetto assistita dall'IA: una frase in, configurabile. Le regole bloccate sono portato in codice, mai mostrato al modello, quindi una linea di conformità non può mai essere cancellato da istruzioni-seguenti. Cancello di accesso (tutte le 14 regole testate) - Opt-out batte ogni altro assegno E viene segnalato come il motivo, perché il la ragione registrata contro un rifiuto è di per sé la prova. - SMS senza registrazione di consenso è rifiutato: in TCPA l'onere della prova è sul mittente, quindi l'assenza di record è assenza di consenso. - Le ore tranquille sono giudicate dove il CONTATTO è, non dove è l'attività. - Gli invii non spendono il budget touch; gli invii soppressi non lo fanno né, né un blocco sarebbe cascata nel bloccare tutto dopo di esso. - Il cancello fallisce CLOSED - un cancello di accesso che gli errori si aprono invia messaggi nessuno autorizzato, l'unico fallimento qui che non può essere annullato. Fissi trovati lungo la strada - La ripetizione della storia della barra degli strumenti è stata spezzata: la riga TOOL non ha persistito alcun contenuto e assistente tool use turno non è mai stato persistito, quindi girare 2 ha inviato un null-content blocchi. Abilitare gli strumenti avrebbe fallito ogni conversazione multi-turn. - textComplete non ha avuto timeout (bloccare .get(), pinning un thread su un lento provider) e non ha registrato alcun utilizzo, rendendo ogni chiamata helper invisibile alla fatturazione. - La partizione di sistema nel montaggio di contesto è stata sbloccata, quindi un agente verbose più un RAG blocco potrebbe affollare tutta la storia. - costEstimate è ora popolato solo sul percorso di sincronizzazione, dai token dei fornitori reali. Streaming rimane null: fabbrica i token come contenuto.lunghezza()/4 e moltiplicazione che da un prezzo reale produce un numero a forma di fattura che è sbagliato.
· kamo-shared-library
Structured sales-agent config, version spine and outreach state
Replaces the single training-context blob with a structured, versionable agent model, and adds the per-contact spine an agent needs before it may initiate contact rather than only reply. - SalesAgent gains configJson (jsonb-as-String, matching WebChatIntegration .designConfig), hasConfig, publishedVersionId, audience and outboundEnabled. trainingContext is retained as the COMPILED OUTPUT so every existing consumer keeps working untouched. hasConfig is explicit rather than inferred from trainingContext being blank, because once it is compiled output it is never blank and any blankness test would be unreachable. - SalesAgentVersion freezes {configJson, compiledPrompt, compiledHash, modelId, providerId} per publish. The model is pinned alongside the prompt: freezing instructions while the model auto-routes would make the artifact a half-truth. - AiChatSession/AiUsageRecord gain salesAgentId + salesAgentVersionId. Previously "which agent handled this?" could only be answered by walking the mutable, nullable, non-FK WebChatIntegration.salesAgentId hop, so reassigning a channel silently re-attributed all history. - AiOrgSettings gains forcedPreamble/forcedFooter as NEW nullable columns rather than reusing defaultSystemPrompt, so concatenation is a no-op until an admin fills one in. Reusing the existing field would have changed behaviour for every org that already had one populated, on deploy day. - AgentContactState + AgentOutboundTouch: per-contact cross-channel suppression, explicit per-channel opt-out columns and timestamped consent. Opt-out is stored as real columns rather than JSON because "prove this number was suppressed on that date" must not depend on JSON path extraction. The touch log records REFUSALS as well as sends - a log of sends proves what you did, a log of decisions proves what you would not do. - Rights 168-173 split **************** off MANAGE_AI_SETTINGS(53), which previously gated none of this.
· kamo-internal
AI Sales Agents tab + incarico agente per canale
Costruisce /settings/ai?tab=sales-agents (era una stub): org crea agenti per i loro industria di vendita, sia da un modello integrato o scrivendo il contesto di formazione loro stessi, quindi modifica/attiva/eliminarli. I canali di chat (/impostazioni/caratteristiche/chat) ora possono scegliere quale agente guida che canale's AI, indipendentemente — l'agente sovrascrive il prompt del sistema grezzo.
· SecurityService
Arricchire mutuante chat routing + cattura soggetto-property stato
chat-routing ora restituisce il NMLS ufficiale assegnato, titolo, foto, telefono, e-mail e se hanno una licenza valida per lo stato soggetto-proprietà, più il e se dobbiamo ancora chiederlo. Riutilizza la carta SAFE-Act i dati risolti in modo che la chat non possa mai mostrare un'identità fabbricata. Aggiunge POST /portal/subject-state: quando il piombo non ha ancora stato di proprietà, il mutuatario può impostare da chat; scorre attraverso patchEstimate (e il suo incarico pool re-entry) come qualsiasi altro fatto rivendicato, che sblocca la linea di licenza.
· MediaService
Assegnare un agente di vendita per canale + rapporto LO disponibilità
- WebChatIntegration CRUD threads salesAgentId (null cancella l'assegnazione) - lo-presenza ora restituisce la disponibilità del membroStato accanto a on-line, così il widget può mostrare uno stato reale invece di un punto nudo. Sonde Cross-org ancora ritorna solo {online:false}.
· AIService
Vendite-agente CRUD, modello di ipoteca, e l'agente-driven chat prompt
- AiSalesAgentController (/api/ai/sales-agents): org-scoped CRUD + GET /templates - SalesAgentTemplateRegistry: modelli di starter integrati, a partire da un mutuo-borrower assistente (consapevolezza-consapevole: nessun vincolo cita, nessun le promesse di approvazione, sfidare il funzionario di prestito autorizzato, chiede lo stato soggetto) - PublicAiChatService: l'addestramento assegnato di SalesAgentContext diventa il top tier della cascata del prompt (agent -> integration prompt -> org -> generico)
· kamo-shared-library
SalesAgent entità + incarico agente per canale
Org-configurable AI agenti di vendita: un denominato agente per un settore di vendita, programmato con un contesto di formazione gli autori org (da un modello o a mano), assegnabili per guidare l'IA di quel canale. Kamo serve tutte le industrie — mutuo è solo un modello. - SalesAgent entità (dao/beans/ai) + SalesAgentRepository + SalesAgentDTO - WebChatIntegration.salesAgentId (collegamento morbido variabile) + campo DTO

Il tuo universo ti sta aspettando.
Aggiungi i prodotti quando sei pronto: nessuna migrazione, nessun nuovo login, nessuna richiesta di pagamento.
Gratis per sempre — nessuna carta di credito richiesta