Files
sigil/src/kv.ts
T
xiaoju fd210c0edd feat: schema + execute abstraction for Agent-friendly deploy
- Agent provides schema (JSON Schema) + execute (function body)
- Sigil auto-generates full Worker code via codegen.ts
- Input parsing: GET query params + POST JSON body, auto type conversion
- Required field validation, default values
- find mode returns schema so Agent knows how to call
- Backward compatible: raw code deploy still works
2026-04-03 08:34:49 +00:00

162 lines
4.6 KiB
TypeScript

// KV key prefixes and data types
import type { InputSchema } from './codegen.js'
export interface KvCodeValue {
code: string
}
export interface KvMetaValue {
type: 'persistent' | 'normal' | 'ephemeral'
ttl?: number
created_at: number
bindings?: string[]
description?: string
tags?: string[]
examples?: string[]
schema?: InputSchema // 新增:模式 B deploy 时存储,find 模式返回
}
export interface KvLruValue {
last_access: number
access_count: number
deployed: boolean
}
export interface KvRouteValue {
worker_name: string
subdomain: string
}
export interface KvAuthValue {
token: string
deploy_cooldown_until?: number
}
export interface KvPageRateValue {
count: number
window_start: number
}
export class KvStore {
private kv: KVNamespace
constructor(kv: KVNamespace) {
this.kv = kv
}
// code:{capability}
async getCode(capability: string): Promise<string | null> {
const v = await this.kv.get(`code:${capability}`, 'json') as KvCodeValue | null
return v?.code ?? null
}
async setCode(capability: string, code: string): Promise<void> {
await this.kv.put(`code:${capability}`, JSON.stringify({ code }))
}
async deleteCode(capability: string): Promise<void> {
await this.kv.delete(`code:${capability}`)
}
// meta:{capability}
async getMeta(capability: string): Promise<KvMetaValue | null> {
return await this.kv.get(`meta:${capability}`, 'json') as KvMetaValue | null
}
async setMeta(capability: string, meta: KvMetaValue): Promise<void> {
await this.kv.put(`meta:${capability}`, JSON.stringify(meta))
}
async deleteMeta(capability: string): Promise<void> {
await this.kv.delete(`meta:${capability}`)
}
// lru:{capability}
async getLru(capability: string): Promise<KvLruValue | null> {
return await this.kv.get(`lru:${capability}`, 'json') as KvLruValue | null
}
async setLru(capability: string, lru: KvLruValue): Promise<void> {
await this.kv.put(`lru:${capability}`, JSON.stringify(lru))
}
async deleteLru(capability: string): Promise<void> {
await this.kv.delete(`lru:${capability}`)
}
// route:{capability}
async getRoute(capability: string): Promise<KvRouteValue | null> {
return await this.kv.get(`route:${capability}`, 'json') as KvRouteValue | null
}
async setRoute(capability: string, route: KvRouteValue): Promise<void> {
await this.kv.put(`route:${capability}`, JSON.stringify(route))
}
async deleteRoute(capability: string): Promise<void> {
await this.kv.delete(`route:${capability}`)
}
// auth:deploy-token — single unified token
async getDeployToken(): Promise<KvAuthValue | null> {
return await this.kv.get('auth:deploy-token', 'json') as KvAuthValue | null
}
async setDeployToken(auth: KvAuthValue): Promise<void> {
await this.kv.put('auth:deploy-token', JSON.stringify(auth))
}
// stats:eviction_count
async getEvictionCount(): Promise<number> {
const v = await this.kv.get('stats:eviction_count', 'json') as { count: number } | null
return v?.count ?? 0
}
async incrementEvictionCount(): Promise<number> {
const current = await this.getEvictionCount()
const next = current + 1
await this.kv.put('stats:eviction_count', JSON.stringify({ count: next }))
return next
}
// stats:page_rate
async getPageRate(): Promise<KvPageRateValue> {
const v = await this.kv.get('stats:page_rate', 'json') as KvPageRateValue | null
return v ?? { count: 0, window_start: Date.now() }
}
async setPageRate(rate: KvPageRateValue): Promise<void> {
await this.kv.put('stats:page_rate', JSON.stringify(rate))
}
// stats:last_deploy_time — global deploy cooldown
async getLastDeployTime(): Promise<number> {
const v = await this.kv.get('stats:last_deploy_time', 'json') as { time: number } | null
return v?.time ?? 0
}
async setLastDeployTime(time: number): Promise<void> {
await this.kv.put('stats:last_deploy_time', JSON.stringify({ time }))
}
// embed:{capability} — capability embedding vector
async getEmbedding(capability: string): Promise<number[] | null> {
return await this.kv.get(`embed:${capability}`, 'json') as number[] | null
}
async setEmbedding(capability: string, vector: number[]): Promise<void> {
await this.kv.put(`embed:${capability}`, JSON.stringify(vector))
}
async deleteEmbedding(capability: string): Promise<void> {
await this.kv.delete(`embed:${capability}`)
}
// List all capabilities by prefix scanning
async listCapabilities(): Promise<string[]> {
const list = await this.kv.list({ prefix: 'lru:' })
return list.keys.map(k => k.name.slice('lru:'.length))
}
}