Files
zeekay 1b367e2b62 chore: rebase the tree onto upstream master
The tree was a debranded snapshot of upstream taken around 2026-02-20, and
upstream has moved about five months since. This replaces it with upstream
master, mechanically re-derived: bin/debrand does the rename, and the
pipeline and squashed migrations are restored from the shipped tree.

Not a merge. The previous import replaced the tree wholesale in a single
commit, so there is no shared content history to merge against. Reproducing
the rename on the new tree is what actually converges.

What survives: .hanzo/workflows, the Dockerfiles and bin/docker* entrypoints,
compose files, LLM.md, and insights/migrations. The squashed initial
migration is load-bearing — the live database records it by name, so
upstream's ~918 individual migrations cannot come back.

Nine products are dropped as unreferenced. Twenty-one more that we do not run
are kept anyway because the core app still imports them; unpicking those is a
refactor and does not belong in a rebase.

This base does not build yet, and the reasons are not in the rename:
upstream now wants Python 3.13.13 against our 3.12.12 and Django 5.2 against
our 4.2, and the dependency manifests still name upstream packages that we
republish under our own names. Those are decisions, not renames.
2026-08-01 15:44:40 -07:00

542 lines
20 KiB
TypeScript

import { MakeLogicType, actions, connect, kea, listeners, path, reducers } from 'kea'
import { loaders } from 'kea-loaders'
import { router } from 'kea-router'
import api from 'lib/api'
import { SetupTaskId, globalSetupLogic } from 'lib/components/ProductSetup'
import { Dialog } from 'lib/elements/Dialog'
import { toast } from 'lib/elements/Toast/Toast'
import { debounce } from 'lib/utils/async'
import { permanentlyMount } from 'lib/utils/kea-logic-builders'
import { slugify } from 'lib/utils/strings'
import { teamLogic } from 'scenes/teamLogic'
import { urls } from 'scenes/urls'
import { sceneLayoutLogic } from '~/layout/scenes/sceneLayoutLogic'
import { EndpointRequest, ProductIntentContext, ProductKey } from '~/queries/schema/schema-general'
import { EndpointType, EndpointVersionType } from '~/types'
import type { ProductIntentProperties } from '../../../frontend/src/lib/utils/product-intents'
import type { EndpointVersionMaterializationType } from '../../../frontend/src/types'
import { endpointsLogic } from './endpointsLogic'
import { insightPickerEndpointModalLogic } from './insightPickerEndpointModalLogic'
export type CodeExampleTab = 'terminal' | 'python' | 'nodejs'
// Generated by kea-typegen. Update if you're an agent, ignore if you're human.
export interface endpointLogicValues {
activeCodeExampleTab: CodeExampleTab
createFromInsightModalOpen: boolean
duplicateEndpoint: EndpointType | null
endpoint: EndpointVersionType | null
endpointDescription: string | null
endpointLoading: boolean
endpointName: string | null
isUpdateMode: boolean
materializationStatus: EndpointType['materialization'] | null
materializationStatusLoading: boolean
selectedCodeExampleVersion: number | null
selectedEndpointName: string | null
updatingEndpoint: boolean
versions: EndpointVersionType[]
versionsLoading: boolean
}
// Generated by kea-typegen. Update if you're an agent, ignore if you're human.
export interface endpointLogicActions {
loadEndpoints: () => any // endpointsLogic
setScenePanelOpen: (open: boolean) => {
open: boolean
} // sceneLayoutLogic
addProductIntent: (properties: ProductIntentProperties) => ProductIntentProperties // teamLogic
clearMaterializationStatus: () => {
value: true
}
closeCreateFromInsightModal: () => {
value: true
}
confirmToggleActive: (endpoint: EndpointType) => {
endpoint: EndpointType
}
createEndpoint: (request: EndpointRequest) => {
request: EndpointRequest
}
createEndpointFailure: (queryError?: string | null) => {
queryError: string | null | undefined
}
createEndpointSuccess: (response: any) => {
response: any
}
deleteEndpoint: (name: string) => {
name: string
}
deleteEndpointFailure: () => {}
deleteEndpointSuccess: (response: any) => {
response: any
}
loadEndpoint: (name: string) => string
loadEndpointFailure: (
error: string,
errorObject?: any
) => {
error: string
errorObject?: any
}
loadEndpointSuccess: (
endpoint: EndpointVersionType | null,
payload?: string
) => {
endpoint: EndpointVersionType | null
payload?: string
}
loadMaterializationStatus: ({ name, version }: { name: string; version?: number }) => {
name: string
version?: number
}
loadMaterializationStatusFailure: (
error: string,
errorObject?: any
) => {
error: string
errorObject?: any
}
loadMaterializationStatusSuccess: (
materializationStatus: EndpointVersionMaterializationType | null | undefined,
payload?: {
name: string
version?: number
}
) => {
materializationStatus: EndpointVersionMaterializationType | null | undefined
payload?: {
name: string
version?: number
}
}
loadVersions: (name: string) => string
loadVersionsFailure: (
error: string,
errorObject?: any
) => {
error: string
errorObject?: any
}
loadVersionsSuccess: (
versions: EndpointVersionType[],
payload?: string
) => {
versions: EndpointVersionType[]
payload?: string
}
openCreateFromInsightModal: () => {
value: true
}
saveTagsInline: (tags: string[]) => {
tags: string[]
}
setActiveCodeExampleTab: (tab: CodeExampleTab) => {
tab: CodeExampleTab
}
setDuplicateEndpoint: (endpoint: EndpointType | null) => {
endpoint: EndpointType | null
}
setEndpointDescription: (endpointDescription: string | null) => {
endpointDescription: string | null
}
setEndpointName: (endpointName: string) => {
endpointName: string
}
setIsUpdateMode: (isUpdateMode: boolean) => {
isUpdateMode: boolean
}
setSelectedCodeExampleVersion: (version: number | null) => {
version: number | null
}
setSelectedEndpointName: (selectedEndpointName: string | null) => {
selectedEndpointName: string | null
}
updateEndpoint: (
name: string,
request: Partial<EndpointRequest>,
options?: {
showViewButton?: boolean
version?: number
}
) => {
name: string
options:
| {
showViewButton?: boolean | undefined
version?: number | undefined
}
| undefined
request: Partial<EndpointRequest>
}
updateEndpointFailure: (queryError?: string | null) => {
queryError: string | null | undefined
}
updateEndpointSuccess: (
response: any,
endpointName: string,
options?: {
showViewButton?: boolean
version?: number
}
) => {
endpointName: string
options:
| {
showViewButton?: boolean | undefined
version?: number | undefined
}
| undefined
response: any
}
}
export type endpointLogicType = MakeLogicType<endpointLogicValues, endpointLogicActions>
export const endpointLogic = kea<endpointLogicType>([
path(['products', 'endpoints', 'frontend', 'endpointLogic']),
connect(() => ({
actions: [
endpointsLogic,
['loadEndpoints'],
sceneLayoutLogic,
['setScenePanelOpen'],
teamLogic,
['addProductIntent'],
],
})),
actions({
setEndpointName: (endpointName: string) => ({ endpointName }),
setEndpointDescription: (endpointDescription: string | null) => ({ endpointDescription }),
setActiveCodeExampleTab: (tab: CodeExampleTab) => ({ tab }),
setSelectedCodeExampleVersion: (version: number | null) => ({ version }),
setIsUpdateMode: (isUpdateMode: boolean) => ({ isUpdateMode }),
setSelectedEndpointName: (selectedEndpointName: string | null) => ({ selectedEndpointName }),
openCreateFromInsightModal: true,
closeCreateFromInsightModal: true,
setDuplicateEndpoint: (endpoint: EndpointType | null) => ({ endpoint }),
createEndpoint: (request: EndpointRequest) => ({ request }),
createEndpointSuccess: (response: any) => ({ response }),
createEndpointFailure: (queryError?: string | null) => ({ queryError }),
updateEndpoint: (
name: string,
request: Partial<EndpointRequest>,
options?: { showViewButton?: boolean; version?: number }
) => ({
name,
request,
options,
}),
updateEndpointSuccess: (
response: any,
endpointName: string,
options?: { showViewButton?: boolean; version?: number }
) => ({
response,
endpointName,
options,
}),
updateEndpointFailure: (queryError?: string | null) => ({ queryError }),
deleteEndpoint: (name: string) => ({ name }),
deleteEndpointSuccess: (response: any) => ({ response }),
clearMaterializationStatus: true,
deleteEndpointFailure: () => ({}),
confirmToggleActive: (endpoint: EndpointType) => ({ endpoint }),
saveTagsInline: (tags: string[]) => ({ tags }),
}),
reducers({
endpointName: [null as string | null, { setEndpointName: (_, { endpointName }) => endpointName }],
endpointDescription: [
null as string | null,
{ setEndpointDescription: (_, { endpointDescription }) => endpointDescription },
],
activeCodeExampleTab: ['terminal' as CodeExampleTab, { setActiveCodeExampleTab: (_, { tab }) => tab }],
selectedCodeExampleVersion: [
null as number | null,
{ setSelectedCodeExampleVersion: (_, { version }) => version },
],
isUpdateMode: [
false,
{
setIsUpdateMode: (_, { isUpdateMode }) => isUpdateMode,
},
],
selectedEndpointName: [
null as string | null,
{
setSelectedEndpointName: (_, { selectedEndpointName }) => selectedEndpointName,
},
],
createFromInsightModalOpen: [
false,
{
openCreateFromInsightModal: () => true,
setDuplicateEndpoint: (_, { endpoint }) => !!endpoint,
closeCreateFromInsightModal: () => false,
createEndpointSuccess: () => false,
},
],
duplicateEndpoint: [
null as EndpointType | null,
{
setDuplicateEndpoint: (_, { endpoint }) => endpoint,
createEndpointSuccess: () => null,
},
],
updatingEndpoint: [
false,
{
updateEndpoint: () => true,
updateEndpointSuccess: () => false,
updateEndpointFailure: () => false,
},
],
// Clear stale endpoint data immediately when loading a new endpoint
endpoint: [
null as EndpointVersionType | null,
{
loadEndpoint: () => null,
},
],
versions: [
[] as EndpointVersionType[],
{
loadEndpoint: () => [],
},
],
// Extend the loader reducer to clear on action
materializationStatus: [
null as EndpointType['materialization'] | null,
{
clearMaterializationStatus: () => null,
},
],
}),
loaders(({ actions, values }) => ({
endpoint: [
null as EndpointVersionType | null,
{
loadEndpoint: async (name: string) => {
if (!name) {
return null
}
return await api.endpoint.get(name)
},
},
],
materializationStatus: [
null as EndpointType['materialization'] | null,
{
loadMaterializationStatus: async ({ name, version }: { name: string; version?: number }) => {
if (!name) {
return null
}
const materializationStatus = await api.endpoint.getMaterializationStatus(name, version)
// Update the endpoint object with the new materialization status (only for current version)
if (values.endpoint && version === undefined) {
const updatedEndpoint = {
...values.endpoint,
materialization: materializationStatus,
is_materialized: materializationStatus?.can_materialize
? !!materializationStatus.status
: false,
}
actions.loadEndpointSuccess(updatedEndpoint)
}
return materializationStatus
},
},
],
versions: [
[] as EndpointVersionType[],
{
loadVersions: async (name: string) => {
if (!name) {
return []
}
const response = await api.endpoint.listVersions(name)
return response.results
},
},
],
})),
listeners(({ actions, values }) => {
const reloadMaterializationStatus = debounce((name: string, version?: number): void => {
actions.loadMaterializationStatus({ name, version })
}, 2000)
return {
openCreateFromInsightModal: () => {
actions.loadEndpoints()
},
closeCreateFromInsightModal: () => {
actions.setDuplicateEndpoint(null)
insightPickerEndpointModalLogic.findMounted()?.actions.clearSelectedInsight()
},
createEndpoint: async ({ request }) => {
try {
if (request.name) {
request.name = slugify(request.name)
}
const response = await api.endpoint.create(request)
actions.createEndpointSuccess(response)
} catch (error: any) {
console.error('Failed to create endpoint:', error)
actions.createEndpointFailure(error.detail || null)
}
},
createEndpointSuccess: ({ response }) => {
actions.setEndpointName('')
actions.setEndpointDescription('')
actions.loadEndpoints()
insightPickerEndpointModalLogic.findMounted()?.actions.closeModal()
toast.success(<>Endpoint created</>, {
button: {
label: 'View',
action: () => {
// Close the scene panel (info & actions panel) if endpoint was created from insight
if (response.derived_from_insight) {
actions.setScenePanelOpen(false)
}
router.actions.push(urls.endpoint(response.name))
},
},
})
// Mark endpoint creation task as completed
globalSetupLogic.findMounted()?.actions.markTaskAsCompleted(SetupTaskId.CreateFirstEndpoint)
// Track product intent for sidebar visibility
const intentContext = response.derived_from_insight
? ProductIntentContext.ENDPOINT_CREATED_FROM_INSIGHT
: ProductIntentContext.ENDPOINT_CREATED_FROM_SQL_EDITOR
actions.addProductIntent({
product_type: ProductKey.ENDPOINTS,
intent_context: intentContext,
})
},
createEndpointFailure: ({ queryError }) => {
if (queryError) {
toast.error(`Failed to create endpoint: ${queryError}`)
} else {
toast.error('Failed to create endpoint')
}
},
updateEndpoint: async ({ name, request, options }) => {
try {
const response = await api.endpoint.update(name, request, options?.version)
actions.updateEndpointSuccess(response, name, options)
} catch (error: any) {
console.error('Failed to update endpoint:', error)
const queryError = error.attr === 'query' ? error.detail : null
actions.updateEndpointFailure(queryError)
}
},
updateEndpointSuccess: ({ response, endpointName, options }) => {
actions.setEndpointDescription(null)
actions.loadEndpoints()
// Reload versions if we updated a specific version
if (options?.version) {
actions.loadVersions(endpointName)
}
if (options?.showViewButton) {
toast.success(<>Endpoint updated</>, {
button: {
label: 'View',
action: () => router.actions.push(urls.endpoint(endpointName)),
},
})
} else {
toast.success('Endpoint updated')
actions.loadEndpoint(endpointName)
}
reloadMaterializationStatus(endpointName, options?.version)
// Mark activation task as completed when endpoint is activated
if (response.is_active) {
globalSetupLogic.findMounted()?.actions.markTaskAsCompleted(SetupTaskId.ConfigureEndpoint)
}
},
updateEndpointFailure: ({ queryError }) => {
if (queryError) {
toast.error(`Failed to update endpoint: ${queryError}`)
} else {
toast.error('Failed to update endpoint')
}
},
saveTagsInline: async ({ tags }, breakpoint) => {
const endpoint = values.endpoint
if (!endpoint) {
return
}
actions.loadEndpointSuccess({ ...endpoint, tags } as EndpointVersionType)
await breakpoint(250)
try {
const saved = await api.endpoint.update(endpoint.name, { tags } as Partial<EndpointRequest>)
breakpoint()
actions.loadEndpointSuccess(saved as EndpointVersionType)
actions.loadEndpoints()
} catch (error: any) {
if (error.isBreakpoint) {
throw error
}
actions.loadEndpointSuccess(endpoint)
toast.error('Failed to save tags')
}
},
deleteEndpoint: async ({ name }) => {
try {
await api.endpoint.delete(name)
actions.deleteEndpointSuccess(name)
} catch (error) {
console.error('Failed to delete endpoint:', error)
actions.deleteEndpointFailure()
}
},
deleteEndpointSuccess: () => {
toast.success('Endpoint deleted')
actions.loadEndpoints()
},
deleteEndpointFailure: () => {
toast.error('Failed to delete endpoint')
},
confirmToggleActive: ({ endpoint }) => {
const isActivating = !endpoint.is_active
Dialog.open({
title: isActivating ? 'Activate endpoint?' : 'Deactivate endpoint?',
content: (
<div className="text-sm text-secondary">
{isActivating
? 'Are you sure you want to activate this endpoint? It will be accessible via the API.'
: 'Are you sure you want to deactivate this endpoint? It will no longer be accessible via the API.'}
</div>
),
primaryButton: {
children: isActivating ? 'Activate' : 'Deactivate',
type: 'primary',
status: isActivating ? undefined : 'danger',
onClick: () => {
actions.updateEndpoint(endpoint.name, { is_active: isActivating })
},
size: 'small',
},
secondaryButton: {
children: 'Cancel',
type: 'tertiary',
size: 'small',
},
})
},
}
}),
permanentlyMount(),
])