import { kody, packageStorage } from 'kody:runtime'
import {
asRecord,
assertOk,
isRecord,
originFetch,
stringField,
} from './http.ts'
import {
type OriginAccountInput,
type OriginAuthLaneInfo,
type OriginInstallation,
type OriginResolvedAccount,
} from './types.ts'
export const DEFAULT_ORIGIN_ACCOUNT = 'origin'
export const DEFAULT_ORIGIN_SECRET_NAME = 'originAppPrivateKey'
export const APP_ID_VALUE = 'originAppId'
export const INSTALLATION_ID_VALUE = 'originInstallationId'
export const ORIGIN_API_HOST = 'api.cursor.com'
export const APP_JWT_AUDIENCE = 'origin-apps'
export const APP_JWT_LIFETIME_SECONDS = 300
export const ORIGIN_SECRET_SETUP_URL =
'https://kody.codes/account/secrets/new?name=originAppPrivateKey&description=Origin%20App%20Ed25519%20PKCS%238%20private%20key&allowedHosts=api.cursor.com&allowedCapabilities=secret_jwt_sign&scope=user'
export const ORIGIN_APPS_DASHBOARD_URL =
'https://cursor.com/codebase/settings/apps'
export const ORIGIN_PUBLIC_URL = 'https://kody.codes/@kody/origin'
export function resolveOriginAccount(
input: OriginAccountInput = {},
): OriginResolvedAccount {
const secretName = trimToUndefined(input.secretName)
const account =
trimToUndefined(input.integrationName) ??
trimToUndefined(input.account) ??
DEFAULT_ORIGIN_ACCOUNT
if (secretName) {
return {
account,
secretName,
appIdKey: storageKey(APP_ID_VALUE, account),
installationIdKey: storageKey(INSTALLATION_ID_VALUE, account),
}
}
return {
account,
secretName: secretNameForAccount(account),
appIdKey: storageKey(APP_ID_VALUE, account),
installationIdKey: storageKey(INSTALLATION_ID_VALUE, account),
}
}
export function secretSetupUrlForAccount(account: string): string {
const secretName = secretNameForAccount(account)
const params = new URLSearchParams({
name: secretName,
description: 'Origin App Ed25519 PKCS#8 private key',
allowedHosts: ORIGIN_API_HOST,
allowedCapabilities: 'secret_jwt_sign',
scope: 'user',
})
return `https://kody.codes/account/secrets/new?${params.toString()}`
}
export function accounts(): readonly OriginAuthLaneInfo[] {
return [
{
lane: 'origin-app',
default: true,
account: DEFAULT_ORIGIN_ACCOUNT,
secretName: DEFAULT_ORIGIN_SECRET_NAME,
secretSetupUrl: ORIGIN_SECRET_SETUP_URL,
useWhen:
'Default Origin App. Extra apps use a distinct account/integrationName (for example origin-work) and matching secret/storage keys.',
avoidWhen:
'You only have a Cloud Agents API key. Origin rejects crsr_ / cursorApiKey credentials.',
mutationGuidance:
'Mutating helpers and non-GET originRequest calls require dryRun: true to preview, then confirm: true to apply. Jobs are not enabled.',
},
]
}
export async function readNamedSetting(name: string): Promise<string> {
const storage = packageStorage()
const stored = await storage.get(name)
if (typeof stored === 'string' && stored.trim()) return stored.trim()
try {
const entry = await kody.value_get({ name, scope: 'user' })
const value = typeof entry?.value === 'string' ? entry.value.trim() : ''
if (value) {
await storage.set(name, value)
return value
}
} catch {
// Leftover user values may already be gone.
}
return ''
}
export async function writeNamedSetting(name: string, value: string) {
const trimmed = value.trim()
if (!trimmed) throw new Error(`${name} is required.`)
await packageStorage().set(name, trimmed)
return trimmed
}
export async function migrateOriginIdsFromValues(
input: OriginAccountInput = {},
) {
const resolved = resolveOriginAccount(input)
const copied: Array<string> = []
const appId = await readNamedSetting(resolved.appIdKey)
if (appId) copied.push(resolved.appIdKey)
const installationId = await readNamedSetting(resolved.installationIdKey)
if (installationId) copied.push(resolved.installationIdKey)
return {
account: resolved.account,
copied,
hasAppId: Boolean(appId),
hasInstallationId: Boolean(installationId),
}
}
export async function resolveOriginAppId(
input: OriginAccountInput = {},
): Promise<string> {
const explicit = trimToUndefined(input.appId)
if (explicit) return explicit
const resolved = resolveOriginAccount(input)
const appId = await readNamedSetting(resolved.appIdKey)
if (!appId) {
throw new Error(
`Save ${resolved.appIdKey} in this package's storage (the Origin App id, app_01…) or pass appId. See ${ORIGIN_PUBLIC_URL} and coding_guide_get({ guide: "provider_origin" }).`,
)
}
return appId
}
export async function signOriginAppJwt(
input: OriginAccountInput = {},
): Promise<string> {
const resolved = resolveOriginAccount(input)
const appId = await resolveOriginAppId(input)
const now = Math.floor(Date.now() / 1000)
const signed = await signOriginAppJwtWithHost({
private_key_secret_name: resolved.secretName,
algorithm: 'EdDSA',
header: { kid: appId },
claims: {
iss: appId,
aud: APP_JWT_AUDIENCE,
iat: now,
exp: now + APP_JWT_LIFETIME_SECONDS,
},
})
return signed.jwt
}
export async function resolveOriginInstallationId(
input: OriginAccountInput = {},
): Promise<string> {
const requested = trimToUndefined(input.installationId)
if (requested) return requested
const resolved = resolveOriginAccount(input)
const saved = await readNamedSetting(resolved.installationIdKey)
if (saved) return saved
const { items } = await listOriginInstallations(input)
if (items.length === 1 && items[0]) return items[0].id
if (items.length === 0) {
throw new Error(
`No Origin App installations found. Install the app at ${ORIGIN_APPS_DASHBOARD_URL} and save ${resolved.installationIdKey} (or pass installationId). See ${ORIGIN_PUBLIC_URL}.`,
)
}
const ids = items.map((item) => item.id).filter(Boolean).join(', ')
throw new Error(
`Multiple Origin installations found (${ids}). Pass installationId or save ${resolved.installationIdKey} in this package's storage. Do not pick one implicitly.`,
)
}
export async function listOriginInstallations(
input: OriginAccountInput = {},
): Promise<{ items: Array<OriginInstallation> }> {
const result = await originFetch({
path: '/app/installations',
bearerToken: await signOriginAppJwt(input),
})
assertOk(result.status, result.body, 'list Origin installations')
const payload = asRecord(result.body)
const raw = Array.isArray(payload.installations) ? payload.installations : []
return {
items: raw.map((item) => slimInstallation(asRecord(item))),
}
}
export async function mintInstallationAccessTokenInternal(
input: OriginAccountInput & { scopes?: Array<string> } = {},
): Promise<{
token: string
installationId: string
expiresAt: string | null
}> {
const installationId = await resolveOriginInstallationId(input)
const result = await originFetch({
path: `/app/installations/${encodeURIComponent(installationId)}/access_tokens`,
method: 'POST',
bearerToken: await signOriginAppJwt(input),
body: input.scopes && input.scopes.length > 0 ? { scopes: input.scopes } : {},
})
assertOk(result.status, result.body, 'mint Origin installation token')
const payload = asRecord(result.body)
const token = typeof payload.token === 'string' ? payload.token : ''
if (!token) {
throw new Error('Origin installation token response did not include token.')
}
return {
token,
installationId,
expiresAt: typeof payload.expiresAt === 'string' ? payload.expiresAt : null,
}
}
async function signOriginAppJwtWithHost(input: {
private_key_secret_name: string
algorithm: 'EdDSA'
header: Record<string, unknown>
claims: Record<string, unknown>
}): Promise<{ jwt: string }> {
const sign = kody.secret_jwt_sign as (args: {
private_key_secret_name: string
algorithm: 'RS256' | 'EdDSA'
header?: Record<string, unknown>
claims: Record<string, unknown>
}) => Promise<{ jwt: string }>
return sign(input)
}
function slimInstallation(item: Record<string, unknown>): OriginInstallation {
const target = isRecord(item.target) ? item.target : null
const scopes = Array.isArray(item.scopes)
? item.scopes.filter((scope): scope is string => typeof scope === 'string')
: []
return {
id: stringField(item.id) ?? '',
appId: stringField(item.appId),
target: target ? slimOwner(target) : null,
repoSelectionMode: stringField(item.repoSelectionMode),
scopes,
}
}
export function slimOwner(item: Record<string, unknown>) {
return {
slug: stringField(item.slug) ?? '',
id: stringField(item.id) ?? '',
type: stringField(item.type),
}
}
function secretNameForAccount(account: string): string {
if (account === DEFAULT_ORIGIN_ACCOUNT) return DEFAULT_ORIGIN_SECRET_NAME
return `${DEFAULT_ORIGIN_SECRET_NAME}-${account}`
}
function storageKey(base: string, account: string): string {
if (account === DEFAULT_ORIGIN_ACCOUNT) return base
return `${base}-${account}`
}
function trimToUndefined(value: string | undefined): string | undefined {
const trimmed = value?.trim()
return trimmed ? trimmed : undefined
}