chore: generate
This commit is contained in:
parent
83452558f7
commit
6003217eaa
@ -29,7 +29,9 @@ export function make<
|
||||
return {
|
||||
name,
|
||||
spec,
|
||||
commands: Object.fromEntries((options.commands ?? []).map((command) => [command.name, command])) as ChildrenOf<Commands>,
|
||||
commands: Object.fromEntries(
|
||||
(options.commands ?? []).map((command) => [command.name, command]),
|
||||
) as ChildrenOf<Commands>,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,11 +2,12 @@ import * as Effect from "effect/Effect"
|
||||
import * as Command from "effect/unstable/cli/Command"
|
||||
import { CliApi } from "./cli-api"
|
||||
|
||||
export type Input<Value> = Value extends CliApi.Node<infer _Name, infer Spec, infer _Commands>
|
||||
? Input<Spec>
|
||||
: Value extends Command.Command<infer _Name, infer Input, infer _Context, infer _Error, infer _Requirements>
|
||||
? Input
|
||||
: never
|
||||
export type Input<Value> =
|
||||
Value extends CliApi.Node<infer _Name, infer Spec, infer _Commands>
|
||||
? Input<Spec>
|
||||
: Value extends Command.Command<infer _Name, infer Input, infer _Context, infer _Error, infer _Requirements>
|
||||
? Input
|
||||
: never
|
||||
|
||||
type RuntimeHandler = (input: unknown) => Effect.Effect<void, unknown>
|
||||
type Loader<Node extends CliApi.Any> = () => Promise<{ default: (input: Input<Node>) => Effect.Effect<void, any> }>
|
||||
@ -21,7 +22,12 @@ interface LazyHandler {
|
||||
readonly load: () => Promise<{ default: RuntimeHandler }>
|
||||
}
|
||||
|
||||
type RuntimeHandlers = (() => Promise<{ default: RuntimeHandler }>) | { readonly $?: () => Promise<{ default: RuntimeHandler }>; readonly [key: string]: RuntimeHandlers | (() => Promise<{ default: RuntimeHandler }>) | undefined }
|
||||
type RuntimeHandlers =
|
||||
| (() => Promise<{ default: RuntimeHandler }>)
|
||||
| {
|
||||
readonly $?: () => Promise<{ default: RuntimeHandler }>
|
||||
readonly [key: string]: RuntimeHandlers | (() => Promise<{ default: RuntimeHandler }>) | undefined
|
||||
}
|
||||
|
||||
export function handler<const Node extends CliApi.Any, Error>(
|
||||
_node: Node,
|
||||
|
||||
@ -7,11 +7,24 @@ import * as Effect from "effect/Effect"
|
||||
import { Api } from "../../api"
|
||||
import { CliBuilder } from "../../cli-builder"
|
||||
|
||||
export default CliBuilder.handler(Api.commands.debug.commands.agents, Effect.fn("cli.debug.agents")(function* () {
|
||||
const svc = {
|
||||
plugin: yield* PluginBoot.Service,
|
||||
agent: yield* AgentV2.Service,
|
||||
}
|
||||
yield* svc.plugin.wait()
|
||||
process.stdout.write(JSON.stringify((yield* svc.agent.all()).sort((a, b) => a.id.localeCompare(b.id)), null, 2) + EOL)
|
||||
}, Effect.provide(LocationServiceMap.get({ directory: AbsolutePath.make(process.cwd()) })), Effect.provide(LocationServiceMap.layer)))
|
||||
export default CliBuilder.handler(
|
||||
Api.commands.debug.commands.agents,
|
||||
Effect.fn("cli.debug.agents")(
|
||||
function* () {
|
||||
const svc = {
|
||||
plugin: yield* PluginBoot.Service,
|
||||
agent: yield* AgentV2.Service,
|
||||
}
|
||||
yield* svc.plugin.wait()
|
||||
process.stdout.write(
|
||||
JSON.stringify(
|
||||
(yield* svc.agent.all()).sort((a, b) => a.id.localeCompare(b.id)),
|
||||
null,
|
||||
2,
|
||||
) + EOL,
|
||||
)
|
||||
},
|
||||
Effect.provide(LocationServiceMap.get({ directory: AbsolutePath.make(process.cwd()) })),
|
||||
Effect.provide(LocationServiceMap.layer),
|
||||
),
|
||||
)
|
||||
|
||||
@ -76,9 +76,7 @@ function messageData(
|
||||
return rest as DeepMutable<typeof rest>
|
||||
}
|
||||
|
||||
function partData(
|
||||
part: (typeof SessionV1.Event.PartUpdated.Type)["data"]["part"],
|
||||
): typeof PartTable.$inferInsert.data {
|
||||
function partData(part: (typeof SessionV1.Event.PartUpdated.Type)["data"]["part"]): typeof PartTable.$inferInsert.data {
|
||||
const { id: _, messageID: __, sessionID: ___, ...rest } = part
|
||||
return rest as DeepMutable<typeof rest>
|
||||
}
|
||||
|
||||
@ -30,40 +30,157 @@ const LogLevelRef = Schema.Literals(["DEBUG", "INFO", "WARN", "ERROR"]).annotate
|
||||
})
|
||||
|
||||
export const Info = Schema.Struct({
|
||||
$schema: Schema.optional(Schema.String).annotate({ description: "JSON schema reference for configuration validation" }),
|
||||
$schema: Schema.optional(Schema.String).annotate({
|
||||
description: "JSON schema reference for configuration validation",
|
||||
}),
|
||||
shell: Schema.optional(Schema.String).annotate({ description: "Default shell to use for terminal and bash tool" }),
|
||||
logLevel: Schema.optional(LogLevelRef).annotate({ description: "Log level" }),
|
||||
server: Schema.optional(ConfigServerV1.Server).annotate({ description: "Server configuration for opencode serve and web commands" }),
|
||||
command: Schema.optional(Schema.Record(Schema.String, ConfigCommandV1.Info)).annotate({ description: "Command configuration, see https://opencode.ai/docs/commands" }),
|
||||
server: Schema.optional(ConfigServerV1.Server).annotate({
|
||||
description: "Server configuration for opencode serve and web commands",
|
||||
}),
|
||||
command: Schema.optional(Schema.Record(Schema.String, ConfigCommandV1.Info)).annotate({
|
||||
description: "Command configuration, see https://opencode.ai/docs/commands",
|
||||
}),
|
||||
skills: Schema.optional(ConfigSkillsV1.Info).annotate({ description: "Additional skill folder paths" }),
|
||||
reference: Schema.optional(ConfigReferenceV1.Info).annotate({ description: "Named git or local directory references that can be mentioned as @alias or @alias/path" }),
|
||||
reference: Schema.optional(ConfigReferenceV1.Info).annotate({
|
||||
description: "Named git or local directory references that can be mentioned as @alias or @alias/path",
|
||||
}),
|
||||
watcher: Schema.optional(Schema.Struct({ ignore: Schema.optional(Schema.mutable(Schema.Array(Schema.String))) })),
|
||||
snapshot: Schema.optional(Schema.Boolean).annotate({ description: "Enable or disable snapshot tracking. When false, filesystem snapshots are not recorded and undoing or reverting will not undo/redo file changes. Defaults to true." }),
|
||||
snapshot: Schema.optional(Schema.Boolean).annotate({
|
||||
description:
|
||||
"Enable or disable snapshot tracking. When false, filesystem snapshots are not recorded and undoing or reverting will not undo/redo file changes. Defaults to true.",
|
||||
}),
|
||||
plugin: Schema.optional(Schema.mutable(Schema.Array(ConfigPluginV1.Spec))),
|
||||
share: Schema.optional(Schema.Literals(["manual", "auto", "disabled"])).annotate({ description: "Control sharing behavior:'manual' allows manual sharing via commands, 'auto' enables automatic sharing, 'disabled' disables all sharing" }),
|
||||
autoshare: Schema.optional(Schema.Boolean).annotate({ description: "@deprecated Use 'share' field instead. Share newly created sessions automatically" }),
|
||||
autoupdate: Schema.optional(Schema.Union([Schema.Boolean, Schema.Literal("notify")])).annotate({ description: "Automatically update to the latest version. Set to true to auto-update, false to disable, or 'notify' to show update notifications" }),
|
||||
disabled_providers: Schema.optional(Schema.mutable(Schema.Array(Schema.String))).annotate({ description: "Disable providers that are loaded automatically" }),
|
||||
enabled_providers: Schema.optional(Schema.mutable(Schema.Array(Schema.String))).annotate({ description: "When set, ONLY these providers will be enabled. All other providers will be ignored" }),
|
||||
model: Schema.optional(Schema.String).annotate({ description: "Model to use in the format of provider/model, eg anthropic/claude-2" }),
|
||||
small_model: Schema.optional(Schema.String).annotate({ description: "Small model to use for tasks like title generation in the format of provider/model" }),
|
||||
default_agent: Schema.optional(Schema.String).annotate({ description: "Default agent to use when none is specified. Must be a primary agent. Falls back to 'build' if not set or if the specified agent is invalid." }),
|
||||
username: Schema.optional(Schema.String).annotate({ description: "Custom username to display in conversations instead of system username" }),
|
||||
mode: Schema.optional(Schema.StructWithRest(Schema.Struct({ build: Schema.optional(ConfigAgentV1.Info), plan: Schema.optional(ConfigAgentV1.Info) }), [Schema.Record(Schema.String, ConfigAgentV1.Info)])).annotate({ description: "@deprecated Use `agent` field instead." }),
|
||||
agent: Schema.optional(Schema.StructWithRest(Schema.Struct({ plan: Schema.optional(ConfigAgentV1.Info), build: Schema.optional(ConfigAgentV1.Info), general: Schema.optional(ConfigAgentV1.Info), explore: Schema.optional(ConfigAgentV1.Info), title: Schema.optional(ConfigAgentV1.Info), summary: Schema.optional(ConfigAgentV1.Info), compaction: Schema.optional(ConfigAgentV1.Info) }), [Schema.Record(Schema.String, ConfigAgentV1.Info)])).annotate({ description: "Agent configuration, see https://opencode.ai/docs/agents" }),
|
||||
provider: Schema.optional(Schema.Record(Schema.String, ConfigProviderV1.Info)).annotate({ description: "Custom provider configurations and model overrides" }),
|
||||
mcp: Schema.optional(Schema.Record(Schema.String, Schema.Union([ConfigMCPV1.Info, Schema.Struct({ enabled: Schema.Boolean })]))).annotate({ description: "MCP (Model Context Protocol) server configurations" }),
|
||||
formatter: Schema.optional(ConfigFormatterV1.Info).annotate({ description: "Enable or configure formatters. Omit or set to false to disable, true to enable built-ins, or an object to enable built-ins with overrides." }),
|
||||
lsp: Schema.optional(ConfigLSPV1.Info).annotate({ description: "Enable or configure LSP servers. Omit or set to false to disable, true to enable built-ins, or an object to enable built-ins with overrides." }),
|
||||
instructions: Schema.optional(Schema.mutable(Schema.Array(Schema.String))).annotate({ description: "Additional instruction files or patterns to include" }),
|
||||
share: Schema.optional(Schema.Literals(["manual", "auto", "disabled"])).annotate({
|
||||
description:
|
||||
"Control sharing behavior:'manual' allows manual sharing via commands, 'auto' enables automatic sharing, 'disabled' disables all sharing",
|
||||
}),
|
||||
autoshare: Schema.optional(Schema.Boolean).annotate({
|
||||
description: "@deprecated Use 'share' field instead. Share newly created sessions automatically",
|
||||
}),
|
||||
autoupdate: Schema.optional(Schema.Union([Schema.Boolean, Schema.Literal("notify")])).annotate({
|
||||
description:
|
||||
"Automatically update to the latest version. Set to true to auto-update, false to disable, or 'notify' to show update notifications",
|
||||
}),
|
||||
disabled_providers: Schema.optional(Schema.mutable(Schema.Array(Schema.String))).annotate({
|
||||
description: "Disable providers that are loaded automatically",
|
||||
}),
|
||||
enabled_providers: Schema.optional(Schema.mutable(Schema.Array(Schema.String))).annotate({
|
||||
description: "When set, ONLY these providers will be enabled. All other providers will be ignored",
|
||||
}),
|
||||
model: Schema.optional(Schema.String).annotate({
|
||||
description: "Model to use in the format of provider/model, eg anthropic/claude-2",
|
||||
}),
|
||||
small_model: Schema.optional(Schema.String).annotate({
|
||||
description: "Small model to use for tasks like title generation in the format of provider/model",
|
||||
}),
|
||||
default_agent: Schema.optional(Schema.String).annotate({
|
||||
description:
|
||||
"Default agent to use when none is specified. Must be a primary agent. Falls back to 'build' if not set or if the specified agent is invalid.",
|
||||
}),
|
||||
username: Schema.optional(Schema.String).annotate({
|
||||
description: "Custom username to display in conversations instead of system username",
|
||||
}),
|
||||
mode: Schema.optional(
|
||||
Schema.StructWithRest(
|
||||
Schema.Struct({ build: Schema.optional(ConfigAgentV1.Info), plan: Schema.optional(ConfigAgentV1.Info) }),
|
||||
[Schema.Record(Schema.String, ConfigAgentV1.Info)],
|
||||
),
|
||||
).annotate({ description: "@deprecated Use `agent` field instead." }),
|
||||
agent: Schema.optional(
|
||||
Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
plan: Schema.optional(ConfigAgentV1.Info),
|
||||
build: Schema.optional(ConfigAgentV1.Info),
|
||||
general: Schema.optional(ConfigAgentV1.Info),
|
||||
explore: Schema.optional(ConfigAgentV1.Info),
|
||||
title: Schema.optional(ConfigAgentV1.Info),
|
||||
summary: Schema.optional(ConfigAgentV1.Info),
|
||||
compaction: Schema.optional(ConfigAgentV1.Info),
|
||||
}),
|
||||
[Schema.Record(Schema.String, ConfigAgentV1.Info)],
|
||||
),
|
||||
).annotate({ description: "Agent configuration, see https://opencode.ai/docs/agents" }),
|
||||
provider: Schema.optional(Schema.Record(Schema.String, ConfigProviderV1.Info)).annotate({
|
||||
description: "Custom provider configurations and model overrides",
|
||||
}),
|
||||
mcp: Schema.optional(
|
||||
Schema.Record(Schema.String, Schema.Union([ConfigMCPV1.Info, Schema.Struct({ enabled: Schema.Boolean })])),
|
||||
).annotate({ description: "MCP (Model Context Protocol) server configurations" }),
|
||||
formatter: Schema.optional(ConfigFormatterV1.Info).annotate({
|
||||
description:
|
||||
"Enable or configure formatters. Omit or set to false to disable, true to enable built-ins, or an object to enable built-ins with overrides.",
|
||||
}),
|
||||
lsp: Schema.optional(ConfigLSPV1.Info).annotate({
|
||||
description:
|
||||
"Enable or configure LSP servers. Omit or set to false to disable, true to enable built-ins, or an object to enable built-ins with overrides.",
|
||||
}),
|
||||
instructions: Schema.optional(Schema.mutable(Schema.Array(Schema.String))).annotate({
|
||||
description: "Additional instruction files or patterns to include",
|
||||
}),
|
||||
layout: Schema.optional(ConfigLayoutV1.Layout).annotate({ description: "@deprecated Always uses stretch layout." }),
|
||||
permission: Schema.optional(ConfigPermissionV1.Info),
|
||||
tools: Schema.optional(Schema.Record(Schema.String, Schema.Boolean)),
|
||||
attachment: Schema.optional(ConfigAttachmentV1.Info).annotate({ description: "Attachment processing configuration, including image size limits and resizing behavior" }),
|
||||
enterprise: Schema.optional(Schema.Struct({ url: Schema.optional(Schema.String).annotate({ description: "Enterprise URL" }) })),
|
||||
tool_output: Schema.optional(Schema.Struct({ max_lines: Schema.optional(PositiveInt).annotate({ description: "Maximum lines of tool output before it is truncated and saved to disk (default: 2000)" }), max_bytes: Schema.optional(PositiveInt).annotate({ description: "Maximum bytes of tool output before it is truncated and saved to disk (default: 51200)" }) })).annotate({ description: "Thresholds for truncating tool output. When output exceeds either limit, the full text is written to the truncation directory and a preview is returned." }),
|
||||
compaction: Schema.optional(Schema.Struct({ auto: Schema.optional(Schema.Boolean).annotate({ description: "Enable automatic compaction when context is full (default: true)" }), prune: Schema.optional(Schema.Boolean).annotate({ description: "Enable pruning of old tool outputs (default: true)" }), tail_turns: Schema.optional(NonNegativeInt).annotate({ description: "Number of recent user turns, including their following assistant/tool responses, to keep verbatim during compaction (default: 2)" }), preserve_recent_tokens: Schema.optional(NonNegativeInt).annotate({ description: "Maximum number of tokens from recent turns to preserve verbatim after compaction" }), reserved: Schema.optional(NonNegativeInt).annotate({ description: "Token buffer for compaction. Leaves enough window to avoid overflow during compaction." }) })),
|
||||
experimental: Schema.optional(Schema.Struct({ disable_paste_summary: Schema.optional(Schema.Boolean), batch_tool: Schema.optional(Schema.Boolean).annotate({ description: "Enable the batch tool" }), openTelemetry: Schema.optional(Schema.Boolean).annotate({ description: "Enable OpenTelemetry spans for AI SDK calls (using the 'experimental_telemetry' flag)" }), primary_tools: Schema.optional(Schema.mutable(Schema.Array(Schema.String))).annotate({ description: "Tools that should only be available to primary agents." }), continue_loop_on_deny: Schema.optional(Schema.Boolean).annotate({ description: "Continue the agent loop when a tool call is denied" }), mcp_timeout: Schema.optional(PositiveInt).annotate({ description: "Timeout in milliseconds for model context protocol (MCP) requests" }), policies: Schema.optional(Schema.mutable(Schema.Array(ConfigExperimental.Policy))).annotate({ description: "Policy statements applied to supported resources, such as provider access" }) })),
|
||||
attachment: Schema.optional(ConfigAttachmentV1.Info).annotate({
|
||||
description: "Attachment processing configuration, including image size limits and resizing behavior",
|
||||
}),
|
||||
enterprise: Schema.optional(
|
||||
Schema.Struct({ url: Schema.optional(Schema.String).annotate({ description: "Enterprise URL" }) }),
|
||||
),
|
||||
tool_output: Schema.optional(
|
||||
Schema.Struct({
|
||||
max_lines: Schema.optional(PositiveInt).annotate({
|
||||
description: "Maximum lines of tool output before it is truncated and saved to disk (default: 2000)",
|
||||
}),
|
||||
max_bytes: Schema.optional(PositiveInt).annotate({
|
||||
description: "Maximum bytes of tool output before it is truncated and saved to disk (default: 51200)",
|
||||
}),
|
||||
}),
|
||||
).annotate({
|
||||
description:
|
||||
"Thresholds for truncating tool output. When output exceeds either limit, the full text is written to the truncation directory and a preview is returned.",
|
||||
}),
|
||||
compaction: Schema.optional(
|
||||
Schema.Struct({
|
||||
auto: Schema.optional(Schema.Boolean).annotate({
|
||||
description: "Enable automatic compaction when context is full (default: true)",
|
||||
}),
|
||||
prune: Schema.optional(Schema.Boolean).annotate({
|
||||
description: "Enable pruning of old tool outputs (default: true)",
|
||||
}),
|
||||
tail_turns: Schema.optional(NonNegativeInt).annotate({
|
||||
description:
|
||||
"Number of recent user turns, including their following assistant/tool responses, to keep verbatim during compaction (default: 2)",
|
||||
}),
|
||||
preserve_recent_tokens: Schema.optional(NonNegativeInt).annotate({
|
||||
description: "Maximum number of tokens from recent turns to preserve verbatim after compaction",
|
||||
}),
|
||||
reserved: Schema.optional(NonNegativeInt).annotate({
|
||||
description: "Token buffer for compaction. Leaves enough window to avoid overflow during compaction.",
|
||||
}),
|
||||
}),
|
||||
),
|
||||
experimental: Schema.optional(
|
||||
Schema.Struct({
|
||||
disable_paste_summary: Schema.optional(Schema.Boolean),
|
||||
batch_tool: Schema.optional(Schema.Boolean).annotate({ description: "Enable the batch tool" }),
|
||||
openTelemetry: Schema.optional(Schema.Boolean).annotate({
|
||||
description: "Enable OpenTelemetry spans for AI SDK calls (using the 'experimental_telemetry' flag)",
|
||||
}),
|
||||
primary_tools: Schema.optional(Schema.mutable(Schema.Array(Schema.String))).annotate({
|
||||
description: "Tools that should only be available to primary agents.",
|
||||
}),
|
||||
continue_loop_on_deny: Schema.optional(Schema.Boolean).annotate({
|
||||
description: "Continue the agent loop when a tool call is denied",
|
||||
}),
|
||||
mcp_timeout: Schema.optional(PositiveInt).annotate({
|
||||
description: "Timeout in milliseconds for model context protocol (MCP) requests",
|
||||
}),
|
||||
policies: Schema.optional(Schema.mutable(Schema.Array(ConfigExperimental.Policy))).annotate({
|
||||
description: "Policy statements applied to supported resources, such as provider access",
|
||||
}),
|
||||
}),
|
||||
),
|
||||
}).annotate({ identifier: "Config" })
|
||||
|
||||
export type Info = DeepMutable<Schema.Schema.Type<typeof Info>>
|
||||
|
||||
@ -136,19 +136,19 @@ function mcp(info: typeof ConfigV1.Info.Type) {
|
||||
|
||||
function migrateMcp(info: ConfigMCPV1.Info) {
|
||||
const disabled = info.enabled === undefined ? undefined : !info.enabled
|
||||
if (info.type === "local") return { type: info.type, command: info.command, environment: info.environment, disabled, timeout: info.timeout }
|
||||
if (info.type === "local")
|
||||
return { type: info.type, command: info.command, environment: info.environment, disabled, timeout: info.timeout }
|
||||
return {
|
||||
type: info.type,
|
||||
url: info.url,
|
||||
headers: info.headers,
|
||||
oauth:
|
||||
info.oauth && {
|
||||
client_id: info.oauth.clientId,
|
||||
client_secret: info.oauth.clientSecret,
|
||||
scope: info.oauth.scope,
|
||||
callback_port: info.oauth.callbackPort,
|
||||
redirect_uri: info.oauth.redirectUri,
|
||||
},
|
||||
oauth: info.oauth && {
|
||||
client_id: info.oauth.clientId,
|
||||
client_secret: info.oauth.clientSecret,
|
||||
scope: info.oauth.scope,
|
||||
callback_port: info.oauth.callbackPort,
|
||||
redirect_uri: info.oauth.redirectUri,
|
||||
},
|
||||
disabled,
|
||||
timeout: info.timeout,
|
||||
}
|
||||
@ -169,7 +169,9 @@ function migrateProvider(info: ConfigProviderV1.Info) {
|
||||
url: info.api ?? (typeof info.options?.baseURL === "string" ? info.options.baseURL : undefined),
|
||||
},
|
||||
options: info.options && { body: info.options },
|
||||
models: info.models && Object.fromEntries(Object.entries(info.models).map(([name, model]) => [name, migrateModel(model)])),
|
||||
models:
|
||||
info.models &&
|
||||
Object.fromEntries(Object.entries(info.models).map(([name, model]) => [name, migrateModel(model)])),
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,9 +204,7 @@ function migrateModel(info: typeof ConfigProviderV1.Model.Type) {
|
||||
endpoint: info.provider?.npm && { type: "aisdk" as const, package: info.provider.npm, url: info.provider.api },
|
||||
capabilities,
|
||||
options: (info.headers || info.options) && { headers: info.headers, body: info.options },
|
||||
variants:
|
||||
info.variants &&
|
||||
Object.entries(info.variants).map(([id, options]) => ({ id, body: options })),
|
||||
variants: info.variants && Object.entries(info.variants).map(([id, options]) => ({ id, body: options })),
|
||||
cost: costs,
|
||||
disabled: info.status === "deprecated" ? true : undefined,
|
||||
limit: info.limit,
|
||||
|
||||
@ -55,7 +55,9 @@ export const Model = Schema.Struct({
|
||||
),
|
||||
experimental: Schema.optional(Schema.Boolean),
|
||||
status: Schema.optional(ModelStatus),
|
||||
provider: Schema.optional(Schema.Struct({ npm: Schema.optional(Schema.String), api: Schema.optional(Schema.String) })),
|
||||
provider: Schema.optional(
|
||||
Schema.Struct({ npm: Schema.optional(Schema.String), api: Schema.optional(Schema.String) }),
|
||||
),
|
||||
options: Schema.optional(Schema.Record(Schema.String, Schema.Any)),
|
||||
headers: Schema.optional(Schema.Record(Schema.String, Schema.String)),
|
||||
variants: Schema.optional(
|
||||
|
||||
@ -372,7 +372,10 @@ describe("Config", () => {
|
||||
permission: { read: "allow" },
|
||||
},
|
||||
},
|
||||
plugin: ["opencode-helicone-session", ["@my-org/audit-plugin", { endpoint: "https://audit.example.com" }]],
|
||||
plugin: [
|
||||
"opencode-helicone-session",
|
||||
["@my-org/audit-plugin", { endpoint: "https://audit.example.com" }],
|
||||
],
|
||||
skills: { paths: ["./skills"], urls: ["https://example.com/.well-known/skills/"] },
|
||||
reference: { docs: { path: "../docs" } },
|
||||
attachment: { image: { auto_resize: false, max_width: 1200 } },
|
||||
|
||||
@ -39,7 +39,10 @@ export function pluginOptions(plugin: ConfigPluginV1.Spec): ConfigPluginV1.Optio
|
||||
|
||||
// Path-like specs are resolved relative to the config file that declared them so merges later on do not
|
||||
// accidentally reinterpret `./plugin.ts` relative to some other directory.
|
||||
export async function resolvePluginSpec(plugin: ConfigPluginV1.Spec, configFilepath: string): Promise<ConfigPluginV1.Spec> {
|
||||
export async function resolvePluginSpec(
|
||||
plugin: ConfigPluginV1.Spec,
|
||||
configFilepath: string,
|
||||
): Promise<ConfigPluginV1.Spec> {
|
||||
const spec = pluginSpecifier(plugin)
|
||||
if (!isPathPluginSpec(spec)) return plugin
|
||||
|
||||
|
||||
@ -38,11 +38,7 @@ interface State {
|
||||
approved: PermissionV1.Rule[]
|
||||
}
|
||||
|
||||
export function evaluate(
|
||||
permission: string,
|
||||
pattern: string,
|
||||
...rulesets: PermissionV1.Ruleset[]
|
||||
): PermissionV1.Rule {
|
||||
export function evaluate(permission: string, pattern: string, ...rulesets: PermissionV1.Ruleset[]): PermissionV1.Rule {
|
||||
return (
|
||||
rulesets
|
||||
.flat()
|
||||
|
||||
@ -354,9 +354,7 @@ export const layer = Layer.effect(
|
||||
throw new Error(`Compaction parent must be a user message: ${input.parentID}`)
|
||||
}
|
||||
const userMessage = parent.info
|
||||
const compactionPart = parent.parts.find(
|
||||
(part): part is SessionV1.CompactionPart => part.type === "compaction",
|
||||
)
|
||||
const compactionPart = parent.parts.find((part): part is SessionV1.CompactionPart => part.type === "compaction")
|
||||
|
||||
let messages = input.messages
|
||||
let replay:
|
||||
|
||||
@ -1500,11 +1500,11 @@ export const layer = Layer.effect(
|
||||
},
|
||||
)
|
||||
|
||||
const loop: (input: LoopInput) => Effect.Effect<SessionV1.WithParts> = Effect.fn("SessionPrompt.loop")(
|
||||
function* (input: LoopInput) {
|
||||
return yield* state.ensureRunning(input.sessionID, lastAssistant(input.sessionID), runLoop(input.sessionID))
|
||||
},
|
||||
)
|
||||
const loop: (input: LoopInput) => Effect.Effect<SessionV1.WithParts> = Effect.fn("SessionPrompt.loop")(function* (
|
||||
input: LoopInput,
|
||||
) {
|
||||
return yield* state.ensureRunning(input.sessionID, lastAssistant(input.sessionID), runLoop(input.sessionID))
|
||||
})
|
||||
|
||||
const shell: (input: ShellInput) => Effect.Effect<SessionV1.WithParts, Session.BusyError> = Effect.fn(
|
||||
"SessionPrompt.shell",
|
||||
|
||||
@ -493,10 +493,7 @@ export interface Interface {
|
||||
readonly setShare: (input: { sessionID: SessionID; share: Info["share"] }) => Effect.Effect<void>
|
||||
readonly setWorkspace: (input: { sessionID: SessionID; workspaceID: Info["workspaceID"] }) => Effect.Effect<void>
|
||||
readonly diff: (sessionID: SessionID) => Effect.Effect<Snapshot.FileDiff[]>
|
||||
readonly messages: (input: {
|
||||
sessionID: SessionID
|
||||
limit?: number
|
||||
}) => Effect.Effect<SessionV1.WithParts[], NotFound>
|
||||
readonly messages: (input: { sessionID: SessionID; limit?: number }) => Effect.Effect<SessionV1.WithParts[], NotFound>
|
||||
readonly children: (parentID: SessionID) => Effect.Effect<Info[]>
|
||||
readonly remove: (sessionID: SessionID) => Effect.Effect<void, NotFound>
|
||||
readonly updateMessage: <T extends SessionV1.Info>(msg: T) => Effect.Effect<T>
|
||||
|
||||
@ -78,9 +78,7 @@ export const layer = Layer.effect(
|
||||
const events = yield* EventV2Bridge.Service
|
||||
const config = yield* Config.Service
|
||||
|
||||
const computeDiff = Effect.fn("SessionSummary.computeDiff")(function* (input: {
|
||||
messages: SessionV1.WithParts[]
|
||||
}) {
|
||||
const computeDiff = Effect.fn("SessionSummary.computeDiff")(function* (input: { messages: SessionV1.WithParts[] }) {
|
||||
let from: string | undefined
|
||||
let to: string | undefined
|
||||
for (const item of input.messages) {
|
||||
|
||||
@ -109,9 +109,7 @@ const add = Effect.fnUntraced(function* (state: State, match: string, events: Ev
|
||||
}).pipe(
|
||||
Effect.catch(
|
||||
Effect.fnUntraced(function* (err) {
|
||||
const message = FrontmatterError.isInstance(err)
|
||||
? err.data.message
|
||||
: `Failed to parse skill ${match}`
|
||||
const message = FrontmatterError.isInstance(err) ? err.data.message : `Failed to parse skill ${match}`
|
||||
const { Session } = yield* Effect.promise(() => import("@/session/session"))
|
||||
yield* events.publish(Session.Event.Error, { error: new NamedError.Unknown({ message }).toObject() })
|
||||
log.error("failed to load skill", { skill: match, err })
|
||||
|
||||
@ -26,11 +26,7 @@ function createReasoningPart(text: string): SessionV1.Part {
|
||||
}
|
||||
}
|
||||
|
||||
function createToolPart(
|
||||
tool: string,
|
||||
title: string,
|
||||
status: "completed" | "running" = "completed",
|
||||
): SessionV1.Part {
|
||||
function createToolPart(tool: string, title: string, status: "completed" | "running" = "completed"): SessionV1.Part {
|
||||
if (status === "completed") {
|
||||
return {
|
||||
id: PartID.ascending(),
|
||||
|
||||
@ -330,9 +330,7 @@ it.live("session.processor effect tests preserve text start time", () =>
|
||||
gate.resolve()
|
||||
|
||||
const exit = yield* Fiber.await(run)
|
||||
const text = (yield* MessageV2.parts(msg.id)).find(
|
||||
(part): part is SessionV1.TextPart => part.type === "text",
|
||||
)
|
||||
const text = (yield* MessageV2.parts(msg.id)).find((part): part is SessionV1.TextPart => part.type === "text")
|
||||
|
||||
expect(Exit.isSuccess(exit)).toBe(true)
|
||||
expect(text?.text).toBe("hello")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user