Rename v2 auth service to account (#28260)
This commit is contained in:
@@ -1,18 +1,16 @@
|
||||
import { EOL } from "os"
|
||||
import { Effect, Layer, Option } from "effect"
|
||||
import { Effect, Option } from "effect"
|
||||
import { Catalog } from "@opencode-ai/core/catalog"
|
||||
import { LocationServiceMap } from "@opencode-ai/core/location-layer"
|
||||
import { PluginBoot } from "@opencode-ai/core/plugin/boot"
|
||||
import { effectCmd } from "../../effect-cmd"
|
||||
|
||||
const Runtime = Layer.mergeAll(LocationServiceMap.layer)
|
||||
|
||||
export const V2Command = effectCmd({
|
||||
command: "v2",
|
||||
describe: "debug v2 catalog and built-in plugins",
|
||||
instance: false,
|
||||
handler: Effect.fn("Cli.debug.v2")(
|
||||
function* () {
|
||||
handler: () =>
|
||||
Effect.gen(function* () {
|
||||
yield* PluginBoot.Service.use((service) => service.wait())
|
||||
const catalog = yield* Catalog.Service
|
||||
const providers = (yield* catalog.provider.available()).sort((a, b) => a.id.localeCompare(b.id))
|
||||
@@ -35,12 +33,13 @@ export const V2Command = effectCmd({
|
||||
),
|
||||
}
|
||||
process.stdout.write(JSON.stringify(result, null, 2) + EOL)
|
||||
},
|
||||
Effect.provide(
|
||||
LocationServiceMap.get({
|
||||
directory: process.cwd(),
|
||||
}),
|
||||
}).pipe(
|
||||
Effect.withSpan("Cli.debug.v2"),
|
||||
Effect.provide(
|
||||
LocationServiceMap.get({
|
||||
directory: process.cwd(),
|
||||
}),
|
||||
),
|
||||
Effect.provide(LocationServiceMap.layer),
|
||||
),
|
||||
Effect.provide(Runtime),
|
||||
),
|
||||
})
|
||||
|
||||
@@ -458,7 +458,7 @@ export const RunCommand = effectCmd({
|
||||
const name = title()
|
||||
const result = await sdk.session.create({
|
||||
title: name,
|
||||
permission: rules,
|
||||
permission: [...rules],
|
||||
})
|
||||
const id = result.data?.id
|
||||
if (!id) {
|
||||
@@ -501,7 +501,7 @@ export const RunCommand = effectCmd({
|
||||
variant: input.variant,
|
||||
}
|
||||
: undefined,
|
||||
permission: rules,
|
||||
permission: [...rules],
|
||||
})
|
||||
const id = result.data?.id
|
||||
if (!id) {
|
||||
|
||||
@@ -81,7 +81,7 @@ export const layer = Layer.effect(
|
||||
)
|
||||
|
||||
export const defaultLayer = layer.pipe(
|
||||
Layer.provideMerge(EventV2.defaultLayer),
|
||||
Layer.provide(EventV2.defaultLayer),
|
||||
Layer.provide(SyncEvent.defaultLayer),
|
||||
Layer.provide(ProjectBus.defaultLayer),
|
||||
)
|
||||
|
||||
@@ -1,15 +1 @@
|
||||
import { Wildcard } from "@/util/wildcard"
|
||||
|
||||
type Rule = {
|
||||
permission: string
|
||||
pattern: string
|
||||
action: "allow" | "deny" | "ask"
|
||||
}
|
||||
|
||||
export function evaluate(permission: string, pattern: string, ...rulesets: Rule[][]): Rule {
|
||||
const rules = rulesets.flat()
|
||||
const match = rules.findLast(
|
||||
(rule) => Wildcard.match(permission, rule.permission) && Wildcard.match(pattern, rule.pattern),
|
||||
)
|
||||
return match ?? { action: "ask", permission, pattern: "*" }
|
||||
}
|
||||
export { evaluate } from "@opencode-ai/core/permission"
|
||||
|
||||
@@ -8,15 +8,15 @@ import { PermissionTable } from "@/session/session.sql"
|
||||
import { Database } from "@/storage/db"
|
||||
import { eq } from "drizzle-orm"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import { Wildcard } from "@/util/wildcard"
|
||||
import { Wildcard } from "@opencode-ai/core/util/wildcard"
|
||||
import { Deferred, Effect, Layer, Schema, Context } from "effect"
|
||||
import os from "os"
|
||||
import { evaluate as evalRule } from "./evaluate"
|
||||
import { PermissionV2 } from "@opencode-ai/core/permission"
|
||||
import { PermissionID } from "./schema"
|
||||
|
||||
const log = Log.create({ service: "permission" })
|
||||
|
||||
export const Action = Schema.Literals(["allow", "deny", "ask"]).annotate({ identifier: "PermissionAction" })
|
||||
export const Action = PermissionV2.Action.annotate({ identifier: "PermissionAction" })
|
||||
export type Action = Schema.Schema.Type<typeof Action>
|
||||
|
||||
export const Rule = Schema.Struct({
|
||||
@@ -26,7 +26,7 @@ export const Rule = Schema.Struct({
|
||||
}).annotate({ identifier: "PermissionRule" })
|
||||
export type Rule = Schema.Schema.Type<typeof Rule>
|
||||
|
||||
export const Ruleset = Schema.mutable(Schema.Array(Rule)).annotate({ identifier: "PermissionRuleset" })
|
||||
export const Ruleset = Schema.Array(Rule).annotate({ identifier: "PermissionRuleset" })
|
||||
export type Ruleset = Schema.Schema.Type<typeof Ruleset>
|
||||
|
||||
export class Request extends Schema.Class<Request>("PermissionRequest")({
|
||||
@@ -122,11 +122,11 @@ interface PendingEntry {
|
||||
|
||||
interface State {
|
||||
pending: Map<PermissionID, PendingEntry>
|
||||
approved: Ruleset
|
||||
approved: Rule[]
|
||||
}
|
||||
|
||||
export function evaluate(permission: string, pattern: string, ...rulesets: Ruleset[]): Rule {
|
||||
return evalRule(permission, pattern, ...rulesets)
|
||||
return PermissionV2.evaluate(permission, pattern, ...rulesets)
|
||||
}
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/Permission") {}
|
||||
@@ -142,7 +142,7 @@ export const layer = Layer.effect(
|
||||
)
|
||||
const state = {
|
||||
pending: new Map<PermissionID, PendingEntry>(),
|
||||
approved: row?.data ?? [],
|
||||
approved: [...(row?.data ?? [])],
|
||||
}
|
||||
|
||||
yield* Effect.addFinalizer(() =>
|
||||
@@ -271,7 +271,7 @@ function expand(pattern: string): string {
|
||||
}
|
||||
|
||||
export function fromConfig(permission: ConfigPermission.Info) {
|
||||
const ruleset: Ruleset = []
|
||||
const ruleset: Rule[] = []
|
||||
for (const [key, value] of Object.entries(permission)) {
|
||||
if (typeof value === "string") {
|
||||
ruleset.push({ permission: key, action: value, pattern: "*" })
|
||||
@@ -284,21 +284,12 @@ export function fromConfig(permission: ConfigPermission.Info) {
|
||||
return ruleset
|
||||
}
|
||||
|
||||
export function merge(...rulesets: Ruleset[]): Ruleset {
|
||||
return rulesets.flat()
|
||||
export function merge(...rulesets: Ruleset[]): Rule[] {
|
||||
return [...PermissionV2.merge(...rulesets)]
|
||||
}
|
||||
|
||||
const EDIT_TOOLS = ["edit", "write", "apply_patch"]
|
||||
|
||||
export function disabled(tools: string[], ruleset: Ruleset): Set<string> {
|
||||
const result = new Set<string>()
|
||||
for (const tool of tools) {
|
||||
const permission = EDIT_TOOLS.includes(tool) ? "edit" : tool
|
||||
const rule = ruleset.findLast((rule) => Wildcard.match(permission, rule.permission))
|
||||
if (!rule) continue
|
||||
if (rule.pattern === "*" && rule.action === "deny") result.add(tool)
|
||||
}
|
||||
return result
|
||||
return PermissionV2.disabled(tools, ruleset)
|
||||
}
|
||||
|
||||
export const defaultLayer = layer.pipe(Layer.provide(Bus.layer))
|
||||
|
||||
@@ -159,9 +159,15 @@ export const sessionHandlers = HttpApiBuilder.group(InstanceHttpApi, "session",
|
||||
if (body.trim().length === 0) return yield* create({})
|
||||
|
||||
const json = yield* tryParseJson(body)
|
||||
const payload = yield* Schema.decodeUnknownEffect(Session.CreateInput)(json).pipe(
|
||||
const decoded = yield* Schema.decodeUnknownEffect(Session.CreateInput)(json).pipe(
|
||||
Effect.mapError(() => new HttpApiError.BadRequest({})),
|
||||
)
|
||||
const payload = decoded
|
||||
? {
|
||||
...decoded,
|
||||
permission: decoded.permission ? [...decoded.permission] : undefined,
|
||||
}
|
||||
: decoded
|
||||
return yield* create({ payload })
|
||||
})
|
||||
|
||||
|
||||
@@ -1216,7 +1216,7 @@ export const layer = Layer.effect(
|
||||
const message = yield* createUserMessage(input)
|
||||
yield* sessions.touch(input.sessionID)
|
||||
|
||||
const permissions: Permission.Ruleset = []
|
||||
const permissions: Permission.Rule[] = []
|
||||
for (const [t, enabled] of Object.entries(input.tools ?? {})) {
|
||||
permissions.push({ permission: t, action: enabled ? "allow" : "deny", pattern: "*" })
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ export function fromRow(row: SessionRow): Info {
|
||||
},
|
||||
share,
|
||||
revert,
|
||||
permission: row.permission ?? undefined,
|
||||
permission: row.permission ? [...row.permission] : undefined,
|
||||
time: {
|
||||
created: row.time_created,
|
||||
updated: row.time_updated,
|
||||
@@ -542,7 +542,7 @@ export const layer: Layer.Layer<
|
||||
title: input.title ?? createDefaultTitle(!!input.parentID),
|
||||
agent: input.agent,
|
||||
model: input.model,
|
||||
permission: input.permission,
|
||||
permission: input.permission ? [...input.permission] : undefined,
|
||||
cost: 0,
|
||||
tokens: EmptyTokens,
|
||||
time: {
|
||||
@@ -734,7 +734,7 @@ export const layer: Layer.Layer<
|
||||
sessionID: SessionID
|
||||
permission: Permission.Ruleset
|
||||
}) {
|
||||
yield* patch(input.sessionID, { permission: input.permission, time: { updated: Date.now() } })
|
||||
yield* patch(input.sessionID, { permission: [...input.permission], time: { updated: Date.now() } })
|
||||
})
|
||||
|
||||
const setRevert = Effect.fn("Session.setRevert")(function* (input: {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { SyncEvent } from "@/sync"
|
||||
import { Effect, Layer, Scope, Context } from "effect"
|
||||
import { Config } from "@/config/config"
|
||||
import { RuntimeFlags } from "@/effect/runtime-flags"
|
||||
import * as ShareNext from "./share-next"
|
||||
import { ShareNext } from "./share-next"
|
||||
|
||||
export interface Interface {
|
||||
readonly create: (input?: Session.CreateInput) => Effect.Effect<Session.Info>
|
||||
|
||||
Reference in New Issue
Block a user