Przeglądaj źródła

fix sdk generation for date time schemas

Dax Raad 3 miesięcy temu
rodzic
commit
81d81e6334

+ 18 - 11
packages/opencode/src/config/permission.ts

@@ -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.

+ 2 - 0
packages/opencode/src/util/effect-zod.ts

@@ -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])
 }

+ 586 - 23
packages/sdk/js/src/v2/gen/types.gen.ts

@@ -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"