← Public packages
@kody/integrations-sh
Client for the public integrations.sh registry: search, detect, cached surface, and live discover.
src/detect.ts
83 lines · 2.6 KB · TypeScriptimport { fetchRegistryJson } from './client.ts'
import { normalizeProviderDomain } from './domain.ts'
import { isRecord } from './is-record.ts'
import { stringOrUndefined } from './types.ts'
import { buildDetectUrl } from './urls.ts'
const DETECT_FETCH_TIMEOUT_MS = 20_000
export type DetectInput = {
/** Bare provider hostname (for example stripe.com). */
domain: string
}
export type DetectOutput = {
domain: string
found: Array<string>
probed: Array<string> | null
errors: Array<string>
mcpCount: number
hasIntegrationsJson: boolean
hasApiCatalog: boolean
hasApiSchema: boolean
hasAuth: boolean
hasAgentCard: boolean
hasAgentSkills: boolean
llmsTxtUrl: string | null
source: string
}
function stringList(value: unknown): Array<string> {
if (!Array.isArray(value)) {
return []
}
return value.filter((item): item is string => typeof item === 'string')
}
/**
* Probe a domain's well-known agent manifests and live capability signals.
* Use when you need current readiness, not the cached surface document.
*
* @param input - Bare provider hostname
* @returns Compact detect summary (found keys, errors, pointer flags)
*
* @example
* import detect from 'kody:@<username>/integrations-sh/detect'
* const readiness = await detect({ domain: 'stripe.com' })
*/
export default async function detect(
input: DetectInput,
): Promise<DetectOutput> {
const domain = normalizeProviderDomain(input.domain)
const source = buildDetectUrl(domain)
const fetched = await fetchRegistryJson(source, DETECT_FETCH_TIMEOUT_MS)
if (fetched.outcome !== 'success') {
const detail =
fetched.outcome === 'not-found'
? `HTTP 404 for ${source}`
: fetched.message
throw new Error(`integrations.sh detect failed: ${detail}`)
}
if (!isRecord(fetched.json) || typeof fetched.json.domain !== 'string') {
throw new Error('integrations.sh detect failed: unexpected response shape')
}
const llmsTxt = isRecord(fetched.json.llmsTxt) ? fetched.json.llmsTxt : null
return {
domain: fetched.json.domain,
found: stringList(fetched.json.found),
probed: Array.isArray(fetched.json.probed)
? stringList(fetched.json.probed)
: null,
errors: stringList(fetched.json.errors),
mcpCount: Array.isArray(fetched.json.mcp) ? fetched.json.mcp.length : 0,
hasIntegrationsJson: fetched.json.integrationsJson != null,
hasApiCatalog: fetched.json.apiCatalog != null,
hasApiSchema: fetched.json.apiSchema != null,
hasAuth: fetched.json.auth != null,
hasAgentCard: fetched.json.agentCard != null,
hasAgentSkills: fetched.json.agentSkills != null,
llmsTxtUrl: stringOrUndefined(llmsTxt?.url) ?? null,
source,
}
}