fix sdk generation for date time schemas
This commit is contained in:
parent
459af775e8
commit
81d81e6334
3 changed files with 606 additions and 34 deletions
|
|
@ -1,6 +1,8 @@
|
|||
export * as ConfigPermission from "./permission"
|
||||
import { Schema, SchemaGetter } from "effect"
|
||||
import z from "zod"
|
||||
import { zod } from "@/util/effect-zod"
|
||||
import { ZodOverride } from "@/util/effect-zod"
|
||||
import { withStatics } from "@/util/schema"
|
||||
|
||||
export const Action = Schema.Literals(["ask", "allow", "deny"])
|
||||
|
|
@ -18,17 +20,9 @@ export const Rule = Schema.Union([Action, Object])
|
|||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export type Rule = Schema.Schema.Type<typeof Rule>
|
||||
|
||||
// Known permission keys get explicit types — most are full Rule (either a
|
||||
// single Action or a per-pattern object), but a handful of tools take no
|
||||
// sub-target patterns and are Action-only. Unknown keys fall through the
|
||||
// Record rest signature as Rule.
|
||||
//
|
||||
// StructWithRest canonicalises key order on decode (known first, then rest),
|
||||
// which used to require the `__originalKeys` preprocess hack because
|
||||
// `Permission.fromConfig` depended on the user's insertion order. That
|
||||
// dependency is gone — `fromConfig` now sorts top-level keys so wildcard
|
||||
// permissions come before specifics, making the final precedence
|
||||
// order-independent.
|
||||
// Known permission keys get explicit types in the Effect schema for generated
|
||||
// docs/types. Runtime config parsing uses `InfoZod` below so user key order is
|
||||
// preserved for permission precedence.
|
||||
const InputObject = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
read: Schema.optional(Rule),
|
||||
|
|
@ -60,6 +54,18 @@ const InputSchema = Schema.Union([Action, InputObject])
|
|||
const normalizeInput = (input: Schema.Schema.Type<typeof InputSchema>): Schema.Schema.Type<typeof InputObject> =>
|
||||
typeof input === "string" ? { "*": input } : input
|
||||
|
||||
const ACTION_ONLY = new Set(["todowrite", "question", "webfetch", "websearch", "codesearch", "doom_loop"])
|
||||
|
||||
const InfoZod = z
|
||||
.union([zod(Action), z.record(z.string(), z.union([zod(Action), z.record(z.string(), zod(Action))]))])
|
||||
.transform(normalizeInput)
|
||||
.superRefine((input, ctx) => {
|
||||
for (const [key, value] of globalThis.Object.entries(input)) {
|
||||
if (!ACTION_ONLY.has(key) || typeof value === "string") continue
|
||||
ctx.addIssue({ code: "custom", message: `${key} must be a permission action`, path: [key] })
|
||||
}
|
||||
})
|
||||
|
||||
export const Info = InputSchema.pipe(
|
||||
Schema.decodeTo(InputObject, {
|
||||
decode: SchemaGetter.transform(normalizeInput),
|
||||
|
|
@ -70,6 +76,7 @@ export const Info = InputSchema.pipe(
|
|||
}),
|
||||
)
|
||||
.annotate({ identifier: "PermissionConfig" })
|
||||
.annotate({ [ZodOverride]: InfoZod })
|
||||
.pipe(
|
||||
// Walker already emits the decodeTo transform into the derived zod (see
|
||||
// `encoded()` in effect-zod.ts), so just expose that directly.
|
||||
|
|
|
|||
|
|
@ -360,6 +360,8 @@ function array(ast: SchemaAST.Arrays): z.ZodTypeAny {
|
|||
}
|
||||
|
||||
function decl(ast: SchemaAST.Declaration): z.ZodTypeAny {
|
||||
const typeConstructor = (ast.annotations as { typeConstructor?: { _tag?: string } }).typeConstructor
|
||||
if (typeConstructor?._tag === "effect/DateTime.Utc") return z.string().datetime()
|
||||
if (ast.typeParameters.length !== 1) return fail(ast)
|
||||
return walk(ast.typeParameters[0])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -987,6 +987,371 @@ export type EventSessionDeleted = {
|
|||
}
|
||||
}
|
||||
|
||||
export type SessionEventSource = {
|
||||
start: number
|
||||
end: number
|
||||
text: string
|
||||
}
|
||||
|
||||
export type SessionEventFileAttachment = {
|
||||
uri: string
|
||||
mime: string
|
||||
name?: string
|
||||
description?: string
|
||||
source?: SessionEventSource
|
||||
}
|
||||
|
||||
export type SessionEventAgentAttachment = {
|
||||
name: string
|
||||
source?: SessionEventSource
|
||||
}
|
||||
|
||||
export type SessionEventPrompt = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "prompt"
|
||||
text: string
|
||||
files?: Array<SessionEventFileAttachment>
|
||||
agents?: Array<SessionEventAgentAttachment>
|
||||
}
|
||||
|
||||
export type EventPrompt = {
|
||||
type: "prompt"
|
||||
properties: SessionEventPrompt
|
||||
}
|
||||
|
||||
export type SessionEventSynthetic = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "synthetic"
|
||||
text: string
|
||||
}
|
||||
|
||||
export type EventSynthetic = {
|
||||
type: "synthetic"
|
||||
properties: SessionEventSynthetic
|
||||
}
|
||||
|
||||
export type SessionEventStepStarted = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "step.started"
|
||||
model: {
|
||||
id: string
|
||||
providerID: string
|
||||
variant?: string
|
||||
}
|
||||
}
|
||||
|
||||
export type EventStepStarted = {
|
||||
type: "step.started"
|
||||
properties: SessionEventStepStarted
|
||||
}
|
||||
|
||||
export type SessionEventStepEnded = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "step.ended"
|
||||
reason: string
|
||||
cost: number
|
||||
tokens: {
|
||||
input: number
|
||||
output: number
|
||||
reasoning: number
|
||||
cache: {
|
||||
read: number
|
||||
write: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type EventStepEnded = {
|
||||
type: "step.ended"
|
||||
properties: SessionEventStepEnded
|
||||
}
|
||||
|
||||
export type SessionEventTextStarted = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "text.started"
|
||||
}
|
||||
|
||||
export type EventTextStarted = {
|
||||
type: "text.started"
|
||||
properties: SessionEventTextStarted
|
||||
}
|
||||
|
||||
export type SessionEventTextDelta = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "text.delta"
|
||||
delta: string
|
||||
}
|
||||
|
||||
export type EventTextDelta = {
|
||||
type: "text.delta"
|
||||
properties: SessionEventTextDelta
|
||||
}
|
||||
|
||||
export type SessionEventTextEnded = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "text.ended"
|
||||
text: string
|
||||
}
|
||||
|
||||
export type EventTextEnded = {
|
||||
type: "text.ended"
|
||||
properties: SessionEventTextEnded
|
||||
}
|
||||
|
||||
export type SessionEventReasoningStarted = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "reasoning.started"
|
||||
}
|
||||
|
||||
export type EventReasoningStarted = {
|
||||
type: "reasoning.started"
|
||||
properties: SessionEventReasoningStarted
|
||||
}
|
||||
|
||||
export type SessionEventReasoningDelta = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "reasoning.delta"
|
||||
delta: string
|
||||
}
|
||||
|
||||
export type EventReasoningDelta = {
|
||||
type: "reasoning.delta"
|
||||
properties: SessionEventReasoningDelta
|
||||
}
|
||||
|
||||
export type SessionEventReasoningEnded = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "reasoning.ended"
|
||||
text: string
|
||||
}
|
||||
|
||||
export type EventReasoningEnded = {
|
||||
type: "reasoning.ended"
|
||||
properties: SessionEventReasoningEnded
|
||||
}
|
||||
|
||||
export type SessionEventToolInputStarted = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "tool.input.started"
|
||||
callID: string
|
||||
name: string
|
||||
}
|
||||
|
||||
export type EventToolInputStarted = {
|
||||
type: "tool.input.started"
|
||||
properties: SessionEventToolInputStarted
|
||||
}
|
||||
|
||||
export type SessionEventToolInputDelta = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "tool.input.delta"
|
||||
callID: string
|
||||
delta: string
|
||||
}
|
||||
|
||||
export type EventToolInputDelta = {
|
||||
type: "tool.input.delta"
|
||||
properties: SessionEventToolInputDelta
|
||||
}
|
||||
|
||||
export type SessionEventToolInputEnded = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "tool.input.ended"
|
||||
callID: string
|
||||
text: string
|
||||
}
|
||||
|
||||
export type EventToolInputEnded = {
|
||||
type: "tool.input.ended"
|
||||
properties: SessionEventToolInputEnded
|
||||
}
|
||||
|
||||
export type SessionEventToolCalled = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "tool.called"
|
||||
callID: string
|
||||
tool: string
|
||||
input: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
provider: {
|
||||
executed: boolean
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type EventToolCalled = {
|
||||
type: "tool.called"
|
||||
properties: SessionEventToolCalled
|
||||
}
|
||||
|
||||
export type SessionEventToolSuccess = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "tool.success"
|
||||
callID: string
|
||||
title: string
|
||||
output?: string
|
||||
attachments?: Array<SessionEventFileAttachment>
|
||||
provider: {
|
||||
executed: boolean
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type EventToolSuccess = {
|
||||
type: "tool.success"
|
||||
properties: SessionEventToolSuccess
|
||||
}
|
||||
|
||||
export type SessionEventToolError = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "tool.error"
|
||||
callID: string
|
||||
error: string
|
||||
provider: {
|
||||
executed: boolean
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type EventToolError = {
|
||||
type: "tool.error"
|
||||
properties: SessionEventToolError
|
||||
}
|
||||
|
||||
export type SessionEventRetryError = {
|
||||
message: string
|
||||
statusCode?: number
|
||||
isRetryable: boolean
|
||||
responseHeaders?: {
|
||||
[key: string]: string
|
||||
}
|
||||
responseBody?: string
|
||||
metadata?: {
|
||||
[key: string]: string
|
||||
}
|
||||
}
|
||||
|
||||
export type SessionEventRetried = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "retried"
|
||||
attempt: number
|
||||
error: SessionEventRetryError
|
||||
}
|
||||
|
||||
export type EventRetried = {
|
||||
type: "retried"
|
||||
properties: SessionEventRetried
|
||||
}
|
||||
|
||||
export type SessionEventCompacted = {
|
||||
id: string
|
||||
sessionID: string
|
||||
metadata?: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
timestamp: string
|
||||
type: "compacted"
|
||||
auto: boolean
|
||||
overflow?: boolean
|
||||
}
|
||||
|
||||
export type EventCompacted = {
|
||||
type: "compacted"
|
||||
properties: SessionEventCompacted
|
||||
}
|
||||
|
||||
export type SyncEventMessageUpdated = {
|
||||
type: "sync"
|
||||
name: "message.updated.1"
|
||||
|
|
@ -1104,6 +1469,168 @@ export type SyncEventSessionDeleted = {
|
|||
}
|
||||
}
|
||||
|
||||
export type SyncEventPrompt = {
|
||||
type: "sync"
|
||||
name: "prompt.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventPrompt
|
||||
}
|
||||
|
||||
export type SyncEventSynthetic = {
|
||||
type: "sync"
|
||||
name: "synthetic.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventSynthetic
|
||||
}
|
||||
|
||||
export type SyncEventStepStarted = {
|
||||
type: "sync"
|
||||
name: "step.started.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventStepStarted
|
||||
}
|
||||
|
||||
export type SyncEventStepEnded = {
|
||||
type: "sync"
|
||||
name: "step.ended.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventStepEnded
|
||||
}
|
||||
|
||||
export type SyncEventTextStarted = {
|
||||
type: "sync"
|
||||
name: "text.started.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventTextStarted
|
||||
}
|
||||
|
||||
export type SyncEventTextDelta = {
|
||||
type: "sync"
|
||||
name: "text.delta.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventTextDelta
|
||||
}
|
||||
|
||||
export type SyncEventTextEnded = {
|
||||
type: "sync"
|
||||
name: "text.ended.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventTextEnded
|
||||
}
|
||||
|
||||
export type SyncEventReasoningStarted = {
|
||||
type: "sync"
|
||||
name: "reasoning.started.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventReasoningStarted
|
||||
}
|
||||
|
||||
export type SyncEventReasoningDelta = {
|
||||
type: "sync"
|
||||
name: "reasoning.delta.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventReasoningDelta
|
||||
}
|
||||
|
||||
export type SyncEventReasoningEnded = {
|
||||
type: "sync"
|
||||
name: "reasoning.ended.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventReasoningEnded
|
||||
}
|
||||
|
||||
export type SyncEventToolInputStarted = {
|
||||
type: "sync"
|
||||
name: "tool.input.started.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventToolInputStarted
|
||||
}
|
||||
|
||||
export type SyncEventToolInputDelta = {
|
||||
type: "sync"
|
||||
name: "tool.input.delta.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventToolInputDelta
|
||||
}
|
||||
|
||||
export type SyncEventToolInputEnded = {
|
||||
type: "sync"
|
||||
name: "tool.input.ended.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventToolInputEnded
|
||||
}
|
||||
|
||||
export type SyncEventToolCalled = {
|
||||
type: "sync"
|
||||
name: "tool.called.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventToolCalled
|
||||
}
|
||||
|
||||
export type SyncEventToolSuccess = {
|
||||
type: "sync"
|
||||
name: "tool.success.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventToolSuccess
|
||||
}
|
||||
|
||||
export type SyncEventToolError = {
|
||||
type: "sync"
|
||||
name: "tool.error.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventToolError
|
||||
}
|
||||
|
||||
export type SyncEventRetried = {
|
||||
type: "sync"
|
||||
name: "retried.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventRetried
|
||||
}
|
||||
|
||||
export type SyncEventCompacted = {
|
||||
type: "sync"
|
||||
name: "compacted.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: SessionEventCompacted
|
||||
}
|
||||
|
||||
export type GlobalEvent = {
|
||||
directory: string
|
||||
project?: string
|
||||
|
|
@ -1156,6 +1683,24 @@ export type GlobalEvent = {
|
|||
| EventSessionCreated
|
||||
| EventSessionUpdated
|
||||
| EventSessionDeleted
|
||||
| EventPrompt
|
||||
| EventSynthetic
|
||||
| EventStepStarted
|
||||
| EventStepEnded
|
||||
| EventTextStarted
|
||||
| EventTextDelta
|
||||
| EventTextEnded
|
||||
| EventReasoningStarted
|
||||
| EventReasoningDelta
|
||||
| EventReasoningEnded
|
||||
| EventToolInputStarted
|
||||
| EventToolInputDelta
|
||||
| EventToolInputEnded
|
||||
| EventToolCalled
|
||||
| EventToolSuccess
|
||||
| EventToolError
|
||||
| EventRetried
|
||||
| EventCompacted
|
||||
| SyncEventMessageUpdated
|
||||
| SyncEventMessageRemoved
|
||||
| SyncEventMessagePartUpdated
|
||||
|
|
@ -1163,6 +1708,24 @@ export type GlobalEvent = {
|
|||
| SyncEventSessionCreated
|
||||
| SyncEventSessionUpdated
|
||||
| SyncEventSessionDeleted
|
||||
| SyncEventPrompt
|
||||
| SyncEventSynthetic
|
||||
| SyncEventStepStarted
|
||||
| SyncEventStepEnded
|
||||
| SyncEventTextStarted
|
||||
| SyncEventTextDelta
|
||||
| SyncEventTextEnded
|
||||
| SyncEventReasoningStarted
|
||||
| SyncEventReasoningDelta
|
||||
| SyncEventReasoningEnded
|
||||
| SyncEventToolInputStarted
|
||||
| SyncEventToolInputDelta
|
||||
| SyncEventToolInputEnded
|
||||
| SyncEventToolCalled
|
||||
| SyncEventToolSuccess
|
||||
| SyncEventToolError
|
||||
| SyncEventRetried
|
||||
| SyncEventCompacted
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1198,32 +1761,14 @@ export type ServerConfig = {
|
|||
|
||||
export type PermissionActionConfig = "ask" | "allow" | "deny"
|
||||
|
||||
export type PermissionObjectConfig = {
|
||||
[key: string]: PermissionActionConfig
|
||||
}
|
||||
|
||||
export type PermissionRuleConfig = PermissionActionConfig | PermissionObjectConfig
|
||||
|
||||
export type PermissionConfig =
|
||||
| PermissionActionConfig
|
||||
| {
|
||||
read?: PermissionRuleConfig
|
||||
edit?: PermissionRuleConfig
|
||||
glob?: PermissionRuleConfig
|
||||
grep?: PermissionRuleConfig
|
||||
list?: PermissionRuleConfig
|
||||
bash?: PermissionRuleConfig
|
||||
task?: PermissionRuleConfig
|
||||
external_directory?: PermissionRuleConfig
|
||||
todowrite?: PermissionActionConfig
|
||||
question?: PermissionActionConfig
|
||||
webfetch?: PermissionActionConfig
|
||||
websearch?: PermissionActionConfig
|
||||
codesearch?: PermissionActionConfig
|
||||
lsp?: PermissionRuleConfig
|
||||
doom_loop?: PermissionActionConfig
|
||||
skill?: PermissionRuleConfig
|
||||
[key: string]: PermissionRuleConfig | PermissionActionConfig | undefined
|
||||
[key: string]:
|
||||
| PermissionActionConfig
|
||||
| {
|
||||
[key: string]: PermissionActionConfig
|
||||
}
|
||||
}
|
||||
|
||||
export type AgentConfig = {
|
||||
|
|
@ -2082,6 +2627,24 @@ export type Event =
|
|||
| EventSessionCreated
|
||||
| EventSessionUpdated
|
||||
| EventSessionDeleted
|
||||
| EventPrompt
|
||||
| EventSynthetic
|
||||
| EventStepStarted
|
||||
| EventStepEnded
|
||||
| EventTextStarted
|
||||
| EventTextDelta
|
||||
| EventTextEnded
|
||||
| EventReasoningStarted
|
||||
| EventReasoningDelta
|
||||
| EventReasoningEnded
|
||||
| EventToolInputStarted
|
||||
| EventToolInputDelta
|
||||
| EventToolInputEnded
|
||||
| EventToolCalled
|
||||
| EventToolSuccess
|
||||
| EventToolError
|
||||
| EventRetried
|
||||
| EventCompacted
|
||||
|
||||
export type McpStatusConnected = {
|
||||
status: "connected"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue