Compare commits
1 commit
dev
...
kit/ns-ses
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a83e989ffa |
54 changed files with 4838 additions and 4852 deletions
|
|
@ -42,9 +42,9 @@ import { ModelID, ProviderID } from "../provider/schema"
|
|||
import { Agent as AgentModule } from "../agent/agent"
|
||||
import { AppRuntime } from "@/effect/app-runtime"
|
||||
import { Installation } from "@/installation"
|
||||
import { MessageV2 } from "@/session/message-v2"
|
||||
import { MessageV2 } from "@/session"
|
||||
import { Config } from "@/config"
|
||||
import { Todo } from "@/session/todo"
|
||||
import { Todo } from "@/session"
|
||||
import { z } from "zod"
|
||||
import { LoadAPIKeyError } from "ai"
|
||||
import type { AssistantMessage, Event, OpencodeClient, SessionMessageResponse, ToolPart } from "@opencode-ai/sdk/v2"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Effect } from "effect"
|
|||
import { Agent } from "../../../agent/agent"
|
||||
import { Provider } from "../../../provider"
|
||||
import { Session } from "../../../session"
|
||||
import type { MessageV2 } from "../../../session/message-v2"
|
||||
import type { MessageV2 } from "../../../session"
|
||||
import { MessageID, PartID } from "../../../session/schema"
|
||||
import { ToolRegistry } from "../../../tool/registry"
|
||||
import { Instance } from "../../../project/instance"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { Argv } from "yargs"
|
||||
import { Session } from "../../session"
|
||||
import { MessageV2 } from "../../session/message-v2"
|
||||
import { MessageV2 } from "../../session"
|
||||
import { SessionID } from "../../session/schema"
|
||||
import { cmd } from "./cmd"
|
||||
import { bootstrap } from "../bootstrap"
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ import type { SessionID } from "../../session/schema"
|
|||
import { MessageID, PartID } from "../../session/schema"
|
||||
import { Provider } from "../../provider"
|
||||
import { Bus } from "../../bus"
|
||||
import { MessageV2 } from "../../session/message-v2"
|
||||
import { SessionPrompt } from "@/session/prompt"
|
||||
import { MessageV2 } from "../../session"
|
||||
import { SessionPrompt } from "@/session"
|
||||
import { AppRuntime } from "@/effect/app-runtime"
|
||||
import { Git } from "@/git"
|
||||
import { setTimeout as sleep } from "node:timers/promises"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { Argv } from "yargs"
|
||||
import type { Session as SDKSession, Message, Part } from "@opencode-ai/sdk/v2"
|
||||
import { Session } from "../../session"
|
||||
import { MessageV2 } from "../../session/message-v2"
|
||||
import { MessageV2 } from "../../session"
|
||||
import { cmd } from "./cmd"
|
||||
import { bootstrap } from "../bootstrap"
|
||||
import { Database } from "../../storage/db"
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ import { useTuiConfig } from "../../context/tui-config"
|
|||
import { getScrollAcceleration } from "../../util/scroll"
|
||||
import { TuiPluginRuntime } from "../../plugin"
|
||||
import { DialogGoUpsell } from "../../component/dialog-go-upsell"
|
||||
import { SessionRetry } from "@/session/retry"
|
||||
import { SessionRetry } from "@/session"
|
||||
|
||||
addDefaultParsers(parsers.parsers)
|
||||
|
||||
|
|
|
|||
|
|
@ -22,17 +22,17 @@ import { Skill } from "@/skill"
|
|||
import { Discovery } from "@/skill/discovery"
|
||||
import { Question } from "@/question"
|
||||
import { Permission } from "@/permission"
|
||||
import { Todo } from "@/session/todo"
|
||||
import { Todo } from "@/session"
|
||||
import { Session } from "@/session"
|
||||
import { SessionStatus } from "@/session/status"
|
||||
import { SessionRunState } from "@/session/run-state"
|
||||
import { SessionProcessor } from "@/session/processor"
|
||||
import { SessionCompaction } from "@/session/compaction"
|
||||
import { SessionRevert } from "@/session/revert"
|
||||
import { SessionSummary } from "@/session/summary"
|
||||
import { SessionPrompt } from "@/session/prompt"
|
||||
import { Instruction } from "@/session/instruction"
|
||||
import { LLM } from "@/session/llm"
|
||||
import { SessionStatus } from "@/session"
|
||||
import { SessionRunState } from "@/session"
|
||||
import { SessionProcessor } from "@/session"
|
||||
import { SessionCompaction } from "@/session"
|
||||
import { SessionRevert } from "@/session"
|
||||
import { SessionSummary } from "@/session"
|
||||
import { SessionPrompt } from "@/session"
|
||||
import { Instruction } from "@/session"
|
||||
import { LLM } from "@/session"
|
||||
import { LSP } from "@/lsp"
|
||||
import { MCP } from "@/mcp"
|
||||
import { McpAuth } from "@/mcp/auth"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { iife } from "@/util/iife"
|
|||
import { Log } from "../../util/log"
|
||||
import { setTimeout as sleep } from "node:timers/promises"
|
||||
import { CopilotModels } from "./models"
|
||||
import { MessageV2 } from "@/session/message-v2"
|
||||
import { MessageV2 } from "@/session"
|
||||
|
||||
const log = Log.create({ service: "plugin.copilot" })
|
||||
|
||||
|
|
|
|||
|
|
@ -4,15 +4,15 @@ import { describeRoute, validator, resolver } from "hono-openapi"
|
|||
import { SessionID, MessageID, PartID } from "@/session/schema"
|
||||
import z from "zod"
|
||||
import { Session } from "../../session"
|
||||
import { MessageV2 } from "../../session/message-v2"
|
||||
import { SessionPrompt } from "../../session/prompt"
|
||||
import { SessionRunState } from "@/session/run-state"
|
||||
import { SessionCompaction } from "../../session/compaction"
|
||||
import { SessionRevert } from "../../session/revert"
|
||||
import { MessageV2 } from "../../session"
|
||||
import { SessionPrompt } from "../../session"
|
||||
import { SessionRunState } from "@/session"
|
||||
import { SessionCompaction } from "../../session"
|
||||
import { SessionRevert } from "../../session"
|
||||
import { SessionShare } from "@/share/session"
|
||||
import { SessionStatus } from "@/session/status"
|
||||
import { SessionSummary } from "@/session/summary"
|
||||
import { Todo } from "../../session/todo"
|
||||
import { SessionStatus } from "@/session"
|
||||
import { SessionSummary } from "@/session"
|
||||
import { Todo } from "../../session"
|
||||
import { Effect } from "effect"
|
||||
import { AppRuntime } from "../../effect/app-runtime"
|
||||
import { Agent } from "../../agent/agent"
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ import { Bus } from "@/bus"
|
|||
import { Session } from "."
|
||||
import { SessionID, MessageID, PartID } from "./schema"
|
||||
import { Provider } from "../provider"
|
||||
import { MessageV2 } from "./message-v2"
|
||||
import { MessageV2 } from "."
|
||||
import z from "zod"
|
||||
import { Token } from "../util/token"
|
||||
import { Log } from "../util/log"
|
||||
import { SessionProcessor } from "./processor"
|
||||
import { SessionProcessor } from "."
|
||||
import { Agent } from "@/agent/agent"
|
||||
import { Plugin } from "@/plugin"
|
||||
import { Config } from "@/config"
|
||||
|
|
@ -17,23 +17,22 @@ import { Effect, Layer, Context } from "effect"
|
|||
import { InstanceState } from "@/effect"
|
||||
import { isOverflow as overflow } from "./overflow"
|
||||
|
||||
export namespace SessionCompaction {
|
||||
const log = Log.create({ service: "session.compaction" })
|
||||
const log = Log.create({ service: "session.compaction" })
|
||||
|
||||
export const Event = {
|
||||
export const Event = {
|
||||
Compacted: BusEvent.define(
|
||||
"session.compacted",
|
||||
z.object({
|
||||
sessionID: SessionID.zod,
|
||||
}),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
export const PRUNE_MINIMUM = 20_000
|
||||
export const PRUNE_PROTECT = 40_000
|
||||
const PRUNE_PROTECTED_TOOLS = ["skill"]
|
||||
export const PRUNE_MINIMUM = 20_000
|
||||
export const PRUNE_PROTECT = 40_000
|
||||
const PRUNE_PROTECTED_TOOLS = ["skill"]
|
||||
|
||||
export interface Interface {
|
||||
export interface Interface {
|
||||
readonly isOverflow: (input: {
|
||||
tokens: MessageV2.Assistant["tokens"]
|
||||
model: Provider.Model
|
||||
|
|
@ -53,11 +52,11 @@ export namespace SessionCompaction {
|
|||
auto: boolean
|
||||
overflow?: boolean
|
||||
}) => Effect.Effect<void>
|
||||
}
|
||||
}
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionCompaction") {}
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionCompaction") {}
|
||||
|
||||
export const layer: Layer.Layer<
|
||||
export const layer: Layer.Layer<
|
||||
Service,
|
||||
never,
|
||||
| Bus.Service
|
||||
|
|
@ -67,7 +66,7 @@ export namespace SessionCompaction {
|
|||
| Plugin.Service
|
||||
| SessionProcessor.Service
|
||||
| Provider.Service
|
||||
> = Layer.effect(
|
||||
> = Layer.effect(
|
||||
Service,
|
||||
Effect.gen(function* () {
|
||||
const bus = yield* Bus.Service
|
||||
|
|
@ -396,9 +395,9 @@ When constructing the summary, try to stick to this template:
|
|||
create,
|
||||
})
|
||||
}),
|
||||
)
|
||||
)
|
||||
|
||||
export const defaultLayer = Layer.suspend(() =>
|
||||
export const defaultLayer = Layer.suspend(() =>
|
||||
layer.pipe(
|
||||
Layer.provide(Provider.defaultLayer),
|
||||
Layer.provide(Session.defaultLayer),
|
||||
|
|
@ -408,5 +407,4 @@ When constructing the summary, try to stick to this template:
|
|||
Layer.provide(Bus.layer),
|
||||
Layer.provide(Config.defaultLayer),
|
||||
),
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1 +1,15 @@
|
|||
export * as Session from "./session"
|
||||
export * as SessionRunState from "./run-state"
|
||||
export * as SystemPrompt from "./system"
|
||||
export * as Message from "./message"
|
||||
export * as SessionRetry from "./retry"
|
||||
export * as SessionProcessor from "./processor"
|
||||
export * as SessionRevert from "./revert"
|
||||
export * as Instruction from "./instruction"
|
||||
export * as SessionSummary from "./summary"
|
||||
export * as Todo from "./todo"
|
||||
export * as LLM from "./llm"
|
||||
export * as SessionStatus from "./status"
|
||||
export * as SessionCompaction from "./compaction"
|
||||
export * as SessionPrompt from "./prompt"
|
||||
export * as MessageV2 from "./message-v2"
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { withTransientReadRetry } from "@/util/effect-http-client"
|
|||
import { Global } from "../global"
|
||||
import { Instance } from "../project/instance"
|
||||
import { Log } from "../util/log"
|
||||
import type { MessageV2 } from "./message-v2"
|
||||
import type { MessageV2 } from "."
|
||||
import type { MessageID } from "./schema"
|
||||
|
||||
const log = Log.create({ service: "instruction" })
|
||||
|
|
@ -50,8 +50,7 @@ function extract(messages: MessageV2.WithParts[]) {
|
|||
return paths
|
||||
}
|
||||
|
||||
export namespace Instruction {
|
||||
export interface Interface {
|
||||
export interface Interface {
|
||||
readonly clear: (messageID: MessageID) => Effect.Effect<void>
|
||||
readonly systemPaths: () => Effect.Effect<Set<string>, AppFileSystem.Error>
|
||||
readonly system: () => Effect.Effect<string[], AppFileSystem.Error>
|
||||
|
|
@ -61,11 +60,11 @@ export namespace Instruction {
|
|||
filepath: string,
|
||||
messageID: MessageID,
|
||||
) => Effect.Effect<{ filepath: string; content: string }[], AppFileSystem.Error>
|
||||
}
|
||||
}
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/Instruction") {}
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/Instruction") {}
|
||||
|
||||
export const layer: Layer.Layer<Service, never, AppFileSystem.Service | Config.Service | HttpClient.HttpClient> =
|
||||
export const layer: Layer.Layer<Service, never, AppFileSystem.Service | Config.Service | HttpClient.HttpClient> =
|
||||
Layer.effect(
|
||||
Service,
|
||||
Effect.gen(function* () {
|
||||
|
|
@ -231,13 +230,12 @@ export namespace Instruction {
|
|||
}),
|
||||
)
|
||||
|
||||
export const defaultLayer = layer.pipe(
|
||||
export const defaultLayer = layer.pipe(
|
||||
Layer.provide(Config.defaultLayer),
|
||||
Layer.provide(AppFileSystem.defaultLayer),
|
||||
Layer.provide(FetchHttpClient.layer),
|
||||
)
|
||||
)
|
||||
|
||||
export function loaded(messages: MessageV2.WithParts[]) {
|
||||
export function loaded(messages: MessageV2.WithParts[]) {
|
||||
return extract(messages)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ import { ProviderTransform } from "@/provider/transform"
|
|||
import { Config } from "@/config"
|
||||
import { Instance } from "@/project/instance"
|
||||
import type { Agent } from "@/agent/agent"
|
||||
import type { MessageV2 } from "./message-v2"
|
||||
import type { MessageV2 } from "."
|
||||
import { Plugin } from "@/plugin"
|
||||
import { SystemPrompt } from "./system"
|
||||
import { SystemPrompt } from "."
|
||||
import { Flag } from "@/flag/flag"
|
||||
import { Permission } from "@/permission"
|
||||
import { PermissionID } from "@/permission/schema"
|
||||
|
|
@ -24,12 +24,11 @@ import { EffectBridge } from "@/effect"
|
|||
import * as Option from "effect/Option"
|
||||
import * as OtelTracer from "@effect/opentelemetry/Tracer"
|
||||
|
||||
export namespace LLM {
|
||||
const log = Log.create({ service: "llm" })
|
||||
export const OUTPUT_TOKEN_MAX = ProviderTransform.OUTPUT_TOKEN_MAX
|
||||
type Result = Awaited<ReturnType<typeof streamText>>
|
||||
const log = Log.create({ service: "llm" })
|
||||
export const OUTPUT_TOKEN_MAX = ProviderTransform.OUTPUT_TOKEN_MAX
|
||||
type Result = Awaited<ReturnType<typeof streamText>>
|
||||
|
||||
export type StreamInput = {
|
||||
export type StreamInput = {
|
||||
user: MessageV2.User
|
||||
sessionID: string
|
||||
parentSessionID?: string
|
||||
|
|
@ -42,25 +41,25 @@ export namespace LLM {
|
|||
tools: Record<string, Tool>
|
||||
retries?: number
|
||||
toolChoice?: "auto" | "required" | "none"
|
||||
}
|
||||
}
|
||||
|
||||
export type StreamRequest = StreamInput & {
|
||||
export type StreamRequest = StreamInput & {
|
||||
abort: AbortSignal
|
||||
}
|
||||
}
|
||||
|
||||
export type Event = Result["fullStream"] extends AsyncIterable<infer T> ? T : never
|
||||
export type Event = Result["fullStream"] extends AsyncIterable<infer T> ? T : never
|
||||
|
||||
export interface Interface {
|
||||
export interface Interface {
|
||||
readonly stream: (input: StreamInput) => Stream.Stream<Event, unknown>
|
||||
}
|
||||
}
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/LLM") {}
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/LLM") {}
|
||||
|
||||
const live: Layer.Layer<
|
||||
const live: Layer.Layer<
|
||||
Service,
|
||||
never,
|
||||
Auth.Service | Config.Service | Provider.Service | Plugin.Service | Permission.Service
|
||||
> = Layer.effect(
|
||||
> = Layer.effect(
|
||||
Service,
|
||||
Effect.gen(function* () {
|
||||
const auth = yield* Auth.Service
|
||||
|
|
@ -418,30 +417,30 @@ export namespace LLM {
|
|||
|
||||
return Service.of({ stream })
|
||||
}),
|
||||
)
|
||||
)
|
||||
|
||||
export const layer = live.pipe(Layer.provide(Permission.defaultLayer))
|
||||
export const layer = live.pipe(Layer.provide(Permission.defaultLayer))
|
||||
|
||||
export const defaultLayer = Layer.suspend(() =>
|
||||
export const defaultLayer = Layer.suspend(() =>
|
||||
layer.pipe(
|
||||
Layer.provide(Auth.defaultLayer),
|
||||
Layer.provide(Config.defaultLayer),
|
||||
Layer.provide(Provider.defaultLayer),
|
||||
Layer.provide(Plugin.defaultLayer),
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
function resolveTools(input: Pick<StreamInput, "tools" | "agent" | "permission" | "user">) {
|
||||
function resolveTools(input: Pick<StreamInput, "tools" | "agent" | "permission" | "user">) {
|
||||
const disabled = Permission.disabled(
|
||||
Object.keys(input.tools),
|
||||
Permission.merge(input.agent.permission, input.permission ?? []),
|
||||
)
|
||||
return Record.filter(input.tools, (_, k) => input.user.tools?.[k] !== false && !disabled.has(k))
|
||||
}
|
||||
}
|
||||
|
||||
// Check if messages contain any tool-call content
|
||||
// Used to determine if a dummy tool should be added for LiteLLM proxy compatibility
|
||||
export function hasToolCalls(messages: ModelMessage[]): boolean {
|
||||
// Check if messages contain any tool-call content
|
||||
// Used to determine if a dummy tool should be added for LiteLLM proxy compatibility
|
||||
export function hasToolCalls(messages: ModelMessage[]): boolean {
|
||||
for (const msg of messages) {
|
||||
if (!Array.isArray(msg.content)) continue
|
||||
for (const part of msg.content) {
|
||||
|
|
@ -449,5 +448,4 @@ export namespace LLM {
|
|||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,30 +24,29 @@ interface FetchDecompressionError extends Error {
|
|||
path: string
|
||||
}
|
||||
|
||||
export namespace MessageV2 {
|
||||
export const SYNTHETIC_ATTACHMENT_PROMPT = "Attached image(s) from tool result:"
|
||||
export const SYNTHETIC_ATTACHMENT_PROMPT = "Attached image(s) from tool result:"
|
||||
|
||||
export function isMedia(mime: string) {
|
||||
export function isMedia(mime: string) {
|
||||
return mime.startsWith("image/") || mime === "application/pdf"
|
||||
}
|
||||
}
|
||||
|
||||
export const OutputLengthError = NamedError.create("MessageOutputLengthError", z.object({}))
|
||||
export const AbortedError = NamedError.create("MessageAbortedError", z.object({ message: z.string() }))
|
||||
export const StructuredOutputError = NamedError.create(
|
||||
export const OutputLengthError = NamedError.create("MessageOutputLengthError", z.object({}))
|
||||
export const AbortedError = NamedError.create("MessageAbortedError", z.object({ message: z.string() }))
|
||||
export const StructuredOutputError = NamedError.create(
|
||||
"StructuredOutputError",
|
||||
z.object({
|
||||
message: z.string(),
|
||||
retries: z.number(),
|
||||
}),
|
||||
)
|
||||
export const AuthError = NamedError.create(
|
||||
)
|
||||
export const AuthError = NamedError.create(
|
||||
"ProviderAuthError",
|
||||
z.object({
|
||||
providerID: z.string(),
|
||||
message: z.string(),
|
||||
}),
|
||||
)
|
||||
export const APIError = NamedError.create(
|
||||
)
|
||||
export const APIError = NamedError.create(
|
||||
"APIError",
|
||||
z.object({
|
||||
message: z.string(),
|
||||
|
|
@ -57,14 +56,14 @@ export namespace MessageV2 {
|
|||
responseBody: z.string().optional(),
|
||||
metadata: z.record(z.string(), z.string()).optional(),
|
||||
}),
|
||||
)
|
||||
export type APIError = z.infer<typeof APIError.Schema>
|
||||
export const ContextOverflowError = NamedError.create(
|
||||
)
|
||||
export type APIError = z.infer<typeof APIError.Schema>
|
||||
export const ContextOverflowError = NamedError.create(
|
||||
"ContextOverflowError",
|
||||
z.object({ message: z.string(), responseBody: z.string().optional() }),
|
||||
)
|
||||
)
|
||||
|
||||
export const OutputFormatText = z
|
||||
export const OutputFormatText = z
|
||||
.object({
|
||||
type: z.literal("text"),
|
||||
})
|
||||
|
|
@ -72,7 +71,7 @@ export namespace MessageV2 {
|
|||
ref: "OutputFormatText",
|
||||
})
|
||||
|
||||
export const OutputFormatJsonSchema = z
|
||||
export const OutputFormatJsonSchema = z
|
||||
.object({
|
||||
type: z.literal("json_schema"),
|
||||
schema: z.record(z.string(), z.any()).meta({ ref: "JSONSchema" }),
|
||||
|
|
@ -82,35 +81,35 @@ export namespace MessageV2 {
|
|||
ref: "OutputFormatJsonSchema",
|
||||
})
|
||||
|
||||
export const Format = z.discriminatedUnion("type", [OutputFormatText, OutputFormatJsonSchema]).meta({
|
||||
export const Format = z.discriminatedUnion("type", [OutputFormatText, OutputFormatJsonSchema]).meta({
|
||||
ref: "OutputFormat",
|
||||
})
|
||||
export type OutputFormat = z.infer<typeof Format>
|
||||
})
|
||||
export type OutputFormat = z.infer<typeof Format>
|
||||
|
||||
const PartBase = z.object({
|
||||
const PartBase = z.object({
|
||||
id: PartID.zod,
|
||||
sessionID: SessionID.zod,
|
||||
messageID: MessageID.zod,
|
||||
})
|
||||
})
|
||||
|
||||
export const SnapshotPart = PartBase.extend({
|
||||
export const SnapshotPart = PartBase.extend({
|
||||
type: z.literal("snapshot"),
|
||||
snapshot: z.string(),
|
||||
}).meta({
|
||||
}).meta({
|
||||
ref: "SnapshotPart",
|
||||
})
|
||||
export type SnapshotPart = z.infer<typeof SnapshotPart>
|
||||
})
|
||||
export type SnapshotPart = z.infer<typeof SnapshotPart>
|
||||
|
||||
export const PatchPart = PartBase.extend({
|
||||
export const PatchPart = PartBase.extend({
|
||||
type: z.literal("patch"),
|
||||
hash: z.string(),
|
||||
files: z.string().array(),
|
||||
}).meta({
|
||||
}).meta({
|
||||
ref: "PatchPart",
|
||||
})
|
||||
export type PatchPart = z.infer<typeof PatchPart>
|
||||
})
|
||||
export type PatchPart = z.infer<typeof PatchPart>
|
||||
|
||||
export const TextPart = PartBase.extend({
|
||||
export const TextPart = PartBase.extend({
|
||||
type: z.literal("text"),
|
||||
text: z.string(),
|
||||
synthetic: z.boolean().optional(),
|
||||
|
|
@ -122,12 +121,12 @@ export namespace MessageV2 {
|
|||
})
|
||||
.optional(),
|
||||
metadata: z.record(z.string(), z.any()).optional(),
|
||||
}).meta({
|
||||
}).meta({
|
||||
ref: "TextPart",
|
||||
})
|
||||
export type TextPart = z.infer<typeof TextPart>
|
||||
})
|
||||
export type TextPart = z.infer<typeof TextPart>
|
||||
|
||||
export const ReasoningPart = PartBase.extend({
|
||||
export const ReasoningPart = PartBase.extend({
|
||||
type: z.literal("reasoning"),
|
||||
text: z.string(),
|
||||
metadata: z.record(z.string(), z.any()).optional(),
|
||||
|
|
@ -135,12 +134,12 @@ export namespace MessageV2 {
|
|||
start: z.number(),
|
||||
end: z.number().optional(),
|
||||
}),
|
||||
}).meta({
|
||||
}).meta({
|
||||
ref: "ReasoningPart",
|
||||
})
|
||||
export type ReasoningPart = z.infer<typeof ReasoningPart>
|
||||
})
|
||||
export type ReasoningPart = z.infer<typeof ReasoningPart>
|
||||
|
||||
const FilePartSourceBase = z.object({
|
||||
const FilePartSourceBase = z.object({
|
||||
text: z
|
||||
.object({
|
||||
value: z.string(),
|
||||
|
|
@ -150,49 +149,49 @@ export namespace MessageV2 {
|
|||
.meta({
|
||||
ref: "FilePartSourceText",
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
export const FileSource = FilePartSourceBase.extend({
|
||||
export const FileSource = FilePartSourceBase.extend({
|
||||
type: z.literal("file"),
|
||||
path: z.string(),
|
||||
}).meta({
|
||||
}).meta({
|
||||
ref: "FileSource",
|
||||
})
|
||||
})
|
||||
|
||||
export const SymbolSource = FilePartSourceBase.extend({
|
||||
export const SymbolSource = FilePartSourceBase.extend({
|
||||
type: z.literal("symbol"),
|
||||
path: z.string(),
|
||||
range: LSP.Range,
|
||||
name: z.string(),
|
||||
kind: z.number().int(),
|
||||
}).meta({
|
||||
}).meta({
|
||||
ref: "SymbolSource",
|
||||
})
|
||||
})
|
||||
|
||||
export const ResourceSource = FilePartSourceBase.extend({
|
||||
export const ResourceSource = FilePartSourceBase.extend({
|
||||
type: z.literal("resource"),
|
||||
clientName: z.string(),
|
||||
uri: z.string(),
|
||||
}).meta({
|
||||
}).meta({
|
||||
ref: "ResourceSource",
|
||||
})
|
||||
})
|
||||
|
||||
export const FilePartSource = z.discriminatedUnion("type", [FileSource, SymbolSource, ResourceSource]).meta({
|
||||
export const FilePartSource = z.discriminatedUnion("type", [FileSource, SymbolSource, ResourceSource]).meta({
|
||||
ref: "FilePartSource",
|
||||
})
|
||||
})
|
||||
|
||||
export const FilePart = PartBase.extend({
|
||||
export const FilePart = PartBase.extend({
|
||||
type: z.literal("file"),
|
||||
mime: z.string(),
|
||||
filename: z.string().optional(),
|
||||
url: z.string(),
|
||||
source: FilePartSource.optional(),
|
||||
}).meta({
|
||||
}).meta({
|
||||
ref: "FilePart",
|
||||
})
|
||||
export type FilePart = z.infer<typeof FilePart>
|
||||
})
|
||||
export type FilePart = z.infer<typeof FilePart>
|
||||
|
||||
export const AgentPart = PartBase.extend({
|
||||
export const AgentPart = PartBase.extend({
|
||||
type: z.literal("agent"),
|
||||
name: z.string(),
|
||||
source: z
|
||||
|
|
@ -202,21 +201,21 @@ export namespace MessageV2 {
|
|||
end: z.number().int(),
|
||||
})
|
||||
.optional(),
|
||||
}).meta({
|
||||
}).meta({
|
||||
ref: "AgentPart",
|
||||
})
|
||||
export type AgentPart = z.infer<typeof AgentPart>
|
||||
})
|
||||
export type AgentPart = z.infer<typeof AgentPart>
|
||||
|
||||
export const CompactionPart = PartBase.extend({
|
||||
export const CompactionPart = PartBase.extend({
|
||||
type: z.literal("compaction"),
|
||||
auto: z.boolean(),
|
||||
overflow: z.boolean().optional(),
|
||||
}).meta({
|
||||
}).meta({
|
||||
ref: "CompactionPart",
|
||||
})
|
||||
export type CompactionPart = z.infer<typeof CompactionPart>
|
||||
})
|
||||
export type CompactionPart = z.infer<typeof CompactionPart>
|
||||
|
||||
export const SubtaskPart = PartBase.extend({
|
||||
export const SubtaskPart = PartBase.extend({
|
||||
type: z.literal("subtask"),
|
||||
prompt: z.string(),
|
||||
description: z.string(),
|
||||
|
|
@ -228,32 +227,32 @@ export namespace MessageV2 {
|
|||
})
|
||||
.optional(),
|
||||
command: z.string().optional(),
|
||||
}).meta({
|
||||
}).meta({
|
||||
ref: "SubtaskPart",
|
||||
})
|
||||
export type SubtaskPart = z.infer<typeof SubtaskPart>
|
||||
})
|
||||
export type SubtaskPart = z.infer<typeof SubtaskPart>
|
||||
|
||||
export const RetryPart = PartBase.extend({
|
||||
export const RetryPart = PartBase.extend({
|
||||
type: z.literal("retry"),
|
||||
attempt: z.number(),
|
||||
error: APIError.Schema,
|
||||
time: z.object({
|
||||
created: z.number(),
|
||||
}),
|
||||
}).meta({
|
||||
}).meta({
|
||||
ref: "RetryPart",
|
||||
})
|
||||
export type RetryPart = z.infer<typeof RetryPart>
|
||||
})
|
||||
export type RetryPart = z.infer<typeof RetryPart>
|
||||
|
||||
export const StepStartPart = PartBase.extend({
|
||||
export const StepStartPart = PartBase.extend({
|
||||
type: z.literal("step-start"),
|
||||
snapshot: z.string().optional(),
|
||||
}).meta({
|
||||
}).meta({
|
||||
ref: "StepStartPart",
|
||||
})
|
||||
export type StepStartPart = z.infer<typeof StepStartPart>
|
||||
})
|
||||
export type StepStartPart = z.infer<typeof StepStartPart>
|
||||
|
||||
export const StepFinishPart = PartBase.extend({
|
||||
export const StepFinishPart = PartBase.extend({
|
||||
type: z.literal("step-finish"),
|
||||
reason: z.string(),
|
||||
snapshot: z.string().optional(),
|
||||
|
|
@ -268,12 +267,12 @@ export namespace MessageV2 {
|
|||
write: z.number(),
|
||||
}),
|
||||
}),
|
||||
}).meta({
|
||||
}).meta({
|
||||
ref: "StepFinishPart",
|
||||
})
|
||||
export type StepFinishPart = z.infer<typeof StepFinishPart>
|
||||
})
|
||||
export type StepFinishPart = z.infer<typeof StepFinishPart>
|
||||
|
||||
export const ToolStatePending = z
|
||||
export const ToolStatePending = z
|
||||
.object({
|
||||
status: z.literal("pending"),
|
||||
input: z.record(z.string(), z.any()),
|
||||
|
|
@ -283,9 +282,9 @@ export namespace MessageV2 {
|
|||
ref: "ToolStatePending",
|
||||
})
|
||||
|
||||
export type ToolStatePending = z.infer<typeof ToolStatePending>
|
||||
export type ToolStatePending = z.infer<typeof ToolStatePending>
|
||||
|
||||
export const ToolStateRunning = z
|
||||
export const ToolStateRunning = z
|
||||
.object({
|
||||
status: z.literal("running"),
|
||||
input: z.record(z.string(), z.any()),
|
||||
|
|
@ -298,9 +297,9 @@ export namespace MessageV2 {
|
|||
.meta({
|
||||
ref: "ToolStateRunning",
|
||||
})
|
||||
export type ToolStateRunning = z.infer<typeof ToolStateRunning>
|
||||
export type ToolStateRunning = z.infer<typeof ToolStateRunning>
|
||||
|
||||
export const ToolStateCompleted = z
|
||||
export const ToolStateCompleted = z
|
||||
.object({
|
||||
status: z.literal("completed"),
|
||||
input: z.record(z.string(), z.any()),
|
||||
|
|
@ -317,9 +316,9 @@ export namespace MessageV2 {
|
|||
.meta({
|
||||
ref: "ToolStateCompleted",
|
||||
})
|
||||
export type ToolStateCompleted = z.infer<typeof ToolStateCompleted>
|
||||
export type ToolStateCompleted = z.infer<typeof ToolStateCompleted>
|
||||
|
||||
export const ToolStateError = z
|
||||
export const ToolStateError = z
|
||||
.object({
|
||||
status: z.literal("error"),
|
||||
input: z.record(z.string(), z.any()),
|
||||
|
|
@ -333,31 +332,31 @@ export namespace MessageV2 {
|
|||
.meta({
|
||||
ref: "ToolStateError",
|
||||
})
|
||||
export type ToolStateError = z.infer<typeof ToolStateError>
|
||||
export type ToolStateError = z.infer<typeof ToolStateError>
|
||||
|
||||
export const ToolState = z
|
||||
export const ToolState = z
|
||||
.discriminatedUnion("status", [ToolStatePending, ToolStateRunning, ToolStateCompleted, ToolStateError])
|
||||
.meta({
|
||||
ref: "ToolState",
|
||||
})
|
||||
|
||||
export const ToolPart = PartBase.extend({
|
||||
export const ToolPart = PartBase.extend({
|
||||
type: z.literal("tool"),
|
||||
callID: z.string(),
|
||||
tool: z.string(),
|
||||
state: ToolState,
|
||||
metadata: z.record(z.string(), z.any()).optional(),
|
||||
}).meta({
|
||||
}).meta({
|
||||
ref: "ToolPart",
|
||||
})
|
||||
export type ToolPart = z.infer<typeof ToolPart>
|
||||
})
|
||||
export type ToolPart = z.infer<typeof ToolPart>
|
||||
|
||||
const Base = z.object({
|
||||
const Base = z.object({
|
||||
id: MessageID.zod,
|
||||
sessionID: SessionID.zod,
|
||||
})
|
||||
})
|
||||
|
||||
export const User = Base.extend({
|
||||
export const User = Base.extend({
|
||||
role: z.literal("user"),
|
||||
time: z.object({
|
||||
created: z.number(),
|
||||
|
|
@ -378,12 +377,12 @@ export namespace MessageV2 {
|
|||
}),
|
||||
system: z.string().optional(),
|
||||
tools: z.record(z.string(), z.boolean()).optional(),
|
||||
}).meta({
|
||||
}).meta({
|
||||
ref: "UserMessage",
|
||||
})
|
||||
export type User = z.infer<typeof User>
|
||||
})
|
||||
export type User = z.infer<typeof User>
|
||||
|
||||
export const Part = z
|
||||
export const Part = z
|
||||
.discriminatedUnion("type", [
|
||||
TextPart,
|
||||
SubtaskPart,
|
||||
|
|
@ -401,9 +400,9 @@ export namespace MessageV2 {
|
|||
.meta({
|
||||
ref: "Part",
|
||||
})
|
||||
export type Part = z.infer<typeof Part>
|
||||
export type Part = z.infer<typeof Part>
|
||||
|
||||
export const Assistant = Base.extend({
|
||||
export const Assistant = Base.extend({
|
||||
role: z.literal("assistant"),
|
||||
time: z.object({
|
||||
created: z.number(),
|
||||
|
|
@ -447,17 +446,17 @@ export namespace MessageV2 {
|
|||
structured: z.any().optional(),
|
||||
variant: z.string().optional(),
|
||||
finish: z.string().optional(),
|
||||
}).meta({
|
||||
}).meta({
|
||||
ref: "AssistantMessage",
|
||||
})
|
||||
export type Assistant = z.infer<typeof Assistant>
|
||||
})
|
||||
export type Assistant = z.infer<typeof Assistant>
|
||||
|
||||
export const Info = z.discriminatedUnion("role", [User, Assistant]).meta({
|
||||
export const Info = z.discriminatedUnion("role", [User, Assistant]).meta({
|
||||
ref: "Message",
|
||||
})
|
||||
export type Info = z.infer<typeof Info>
|
||||
})
|
||||
export type Info = z.infer<typeof Info>
|
||||
|
||||
export const Event = {
|
||||
export const Event = {
|
||||
Updated: SyncEvent.define({
|
||||
type: "message.updated",
|
||||
version: 1,
|
||||
|
|
@ -506,53 +505,53 @@ export namespace MessageV2 {
|
|||
partID: PartID.zod,
|
||||
}),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
export const WithParts = z.object({
|
||||
export const WithParts = z.object({
|
||||
info: Info,
|
||||
parts: z.array(Part),
|
||||
})
|
||||
export type WithParts = z.infer<typeof WithParts>
|
||||
})
|
||||
export type WithParts = z.infer<typeof WithParts>
|
||||
|
||||
const Cursor = z.object({
|
||||
const Cursor = z.object({
|
||||
id: MessageID.zod,
|
||||
time: z.number(),
|
||||
})
|
||||
type Cursor = z.infer<typeof Cursor>
|
||||
})
|
||||
type Cursor = z.infer<typeof Cursor>
|
||||
|
||||
export const cursor = {
|
||||
export const cursor = {
|
||||
encode(input: Cursor) {
|
||||
return Buffer.from(JSON.stringify(input)).toString("base64url")
|
||||
},
|
||||
decode(input: string) {
|
||||
return Cursor.parse(JSON.parse(Buffer.from(input, "base64url").toString("utf8")))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const info = (row: typeof MessageTable.$inferSelect) =>
|
||||
const info = (row: typeof MessageTable.$inferSelect) =>
|
||||
({
|
||||
...row.data,
|
||||
id: row.id,
|
||||
sessionID: row.session_id,
|
||||
}) as MessageV2.Info
|
||||
}) as Info
|
||||
|
||||
const part = (row: typeof PartTable.$inferSelect) =>
|
||||
const part = (row: typeof PartTable.$inferSelect) =>
|
||||
({
|
||||
...row.data,
|
||||
id: row.id,
|
||||
sessionID: row.session_id,
|
||||
messageID: row.message_id,
|
||||
}) as MessageV2.Part
|
||||
}) as Part
|
||||
|
||||
const older = (row: Cursor) =>
|
||||
const older = (row: Cursor) =>
|
||||
or(
|
||||
lt(MessageTable.time_created, row.time),
|
||||
and(eq(MessageTable.time_created, row.time), lt(MessageTable.id, row.id)),
|
||||
)
|
||||
|
||||
function hydrate(rows: (typeof MessageTable.$inferSelect)[]) {
|
||||
function hydrate(rows: (typeof MessageTable.$inferSelect)[]) {
|
||||
const ids = rows.map((row) => row.id)
|
||||
const partByMessage = new Map<string, MessageV2.Part[]>()
|
||||
const partByMessage = new Map<string, Part[]>()
|
||||
if (ids.length > 0) {
|
||||
const partRows = Database.use((db) =>
|
||||
db
|
||||
|
|
@ -574,19 +573,19 @@ export namespace MessageV2 {
|
|||
info: info(row),
|
||||
parts: partByMessage.get(row.id) ?? [],
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
function providerMeta(metadata: Record<string, any> | undefined) {
|
||||
function providerMeta(metadata: Record<string, any> | undefined) {
|
||||
if (!metadata) return undefined
|
||||
const { providerExecuted: _, ...rest } = metadata
|
||||
return Object.keys(rest).length > 0 ? rest : undefined
|
||||
}
|
||||
}
|
||||
|
||||
export const toModelMessagesEffect = Effect.fnUntraced(function* (
|
||||
export const toModelMessagesEffect = Effect.fnUntraced(function* (
|
||||
input: WithParts[],
|
||||
model: Provider.Model,
|
||||
options?: { stripMedia?: boolean },
|
||||
) {
|
||||
) {
|
||||
const result: UIMessage[] = []
|
||||
const toolNames = new Set<string>()
|
||||
// Track media from tool results that need to be injected as user messages
|
||||
|
|
@ -699,7 +698,7 @@ export namespace MessageV2 {
|
|||
if (
|
||||
msg.info.error &&
|
||||
!(
|
||||
MessageV2.AbortedError.isInstance(msg.info.error) &&
|
||||
AbortedError.isInstance(msg.info.error) &&
|
||||
msg.parts.some((part) => part.type !== "step-start" && part.type !== "reasoning")
|
||||
)
|
||||
) {
|
||||
|
|
@ -835,17 +834,17 @@ export namespace MessageV2 {
|
|||
},
|
||||
),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
export function toModelMessages(
|
||||
export function toModelMessages(
|
||||
input: WithParts[],
|
||||
model: Provider.Model,
|
||||
options?: { stripMedia?: boolean },
|
||||
): Promise<ModelMessage[]> {
|
||||
): Promise<ModelMessage[]> {
|
||||
return Effect.runPromise(toModelMessagesEffect(input, model, options).pipe(Effect.provide(EffectLogger.layer)))
|
||||
}
|
||||
}
|
||||
|
||||
export function page(input: { sessionID: SessionID; limit: number; before?: string }) {
|
||||
export function page(input: { sessionID: SessionID; limit: number; before?: string }) {
|
||||
const before = input.before ? cursor.decode(input.before) : undefined
|
||||
const where = before
|
||||
? and(eq(MessageTable.session_id, input.sessionID), older(before))
|
||||
|
|
@ -865,7 +864,7 @@ export namespace MessageV2 {
|
|||
)
|
||||
if (!row) throw new NotFoundError({ message: `Session not found: ${input.sessionID}` })
|
||||
return {
|
||||
items: [] as MessageV2.WithParts[],
|
||||
items: [] as WithParts[],
|
||||
more: false,
|
||||
}
|
||||
}
|
||||
|
|
@ -880,9 +879,9 @@ export namespace MessageV2 {
|
|||
more,
|
||||
cursor: more && tail ? cursor.encode({ id: tail.id, time: tail.time_created }) : undefined,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function* stream(sessionID: SessionID) {
|
||||
export function* stream(sessionID: SessionID) {
|
||||
const size = 50
|
||||
let before: string | undefined
|
||||
while (true) {
|
||||
|
|
@ -894,9 +893,9 @@ export namespace MessageV2 {
|
|||
if (!next.more || !next.cursor) break
|
||||
before = next.cursor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function parts(message_id: MessageID) {
|
||||
export function parts(message_id: MessageID) {
|
||||
const rows = Database.use((db) =>
|
||||
db.select().from(PartTable).where(eq(PartTable.message_id, message_id)).orderBy(PartTable.id).all(),
|
||||
)
|
||||
|
|
@ -907,11 +906,11 @@ export namespace MessageV2 {
|
|||
id: row.id,
|
||||
sessionID: row.session_id,
|
||||
messageID: row.message_id,
|
||||
}) as MessageV2.Part,
|
||||
}) as Part,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export function get(input: { sessionID: SessionID; messageID: MessageID }): WithParts {
|
||||
export function get(input: { sessionID: SessionID; messageID: MessageID }): WithParts {
|
||||
const row = Database.use((db) =>
|
||||
db
|
||||
.select()
|
||||
|
|
@ -924,10 +923,10 @@ export namespace MessageV2 {
|
|||
info: info(row),
|
||||
parts: parts(input.messageID),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function filterCompacted(msgs: Iterable<MessageV2.WithParts>) {
|
||||
const result = [] as MessageV2.WithParts[]
|
||||
export function filterCompacted(msgs: Iterable<WithParts>) {
|
||||
const result = [] as WithParts[]
|
||||
const completed = new Set<string>()
|
||||
for (const msg of msgs) {
|
||||
result.push(msg)
|
||||
|
|
@ -942,28 +941,28 @@ export namespace MessageV2 {
|
|||
}
|
||||
result.reverse()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
export const filterCompactedEffect = Effect.fnUntraced(function* (sessionID: SessionID) {
|
||||
export const filterCompactedEffect = Effect.fnUntraced(function* (sessionID: SessionID) {
|
||||
return filterCompacted(stream(sessionID))
|
||||
})
|
||||
})
|
||||
|
||||
export function fromError(
|
||||
export function fromError(
|
||||
e: unknown,
|
||||
ctx: { providerID: ProviderID; aborted?: boolean },
|
||||
): NonNullable<Assistant["error"]> {
|
||||
): NonNullable<Assistant["error"]> {
|
||||
switch (true) {
|
||||
case e instanceof DOMException && e.name === "AbortError":
|
||||
return new MessageV2.AbortedError(
|
||||
return new AbortedError(
|
||||
{ message: e.message },
|
||||
{
|
||||
cause: e,
|
||||
},
|
||||
).toObject()
|
||||
case MessageV2.OutputLengthError.isInstance(e):
|
||||
case OutputLengthError.isInstance(e):
|
||||
return e
|
||||
case LoadAPIKeyError.isInstance(e):
|
||||
return new MessageV2.AuthError(
|
||||
return new AuthError(
|
||||
{
|
||||
providerID: ctx.providerID,
|
||||
message: e.message,
|
||||
|
|
@ -971,7 +970,7 @@ export namespace MessageV2 {
|
|||
{ cause: e },
|
||||
).toObject()
|
||||
case (e as SystemError)?.code === "ECONNRESET":
|
||||
return new MessageV2.APIError(
|
||||
return new APIError(
|
||||
{
|
||||
message: "Connection reset by server",
|
||||
isRetryable: true,
|
||||
|
|
@ -985,9 +984,9 @@ export namespace MessageV2 {
|
|||
).toObject()
|
||||
case e instanceof Error && (e as FetchDecompressionError).code === "ZlibError":
|
||||
if (ctx.aborted) {
|
||||
return new MessageV2.AbortedError({ message: e.message }, { cause: e }).toObject()
|
||||
return new AbortedError({ message: e.message }, { cause: e }).toObject()
|
||||
}
|
||||
return new MessageV2.APIError(
|
||||
return new APIError(
|
||||
{
|
||||
message: "Response decompression failed",
|
||||
isRetryable: true,
|
||||
|
|
@ -1004,7 +1003,7 @@ export namespace MessageV2 {
|
|||
error: e,
|
||||
})
|
||||
if (parsed.type === "context_overflow") {
|
||||
return new MessageV2.ContextOverflowError(
|
||||
return new ContextOverflowError(
|
||||
{
|
||||
message: parsed.message,
|
||||
responseBody: parsed.responseBody,
|
||||
|
|
@ -1013,7 +1012,7 @@ export namespace MessageV2 {
|
|||
).toObject()
|
||||
}
|
||||
|
||||
return new MessageV2.APIError(
|
||||
return new APIError(
|
||||
{
|
||||
message: parsed.message,
|
||||
statusCode: parsed.statusCode,
|
||||
|
|
@ -1031,7 +1030,7 @@ export namespace MessageV2 {
|
|||
const parsed = ProviderError.parseStreamError(e)
|
||||
if (parsed) {
|
||||
if (parsed.type === "context_overflow") {
|
||||
return new MessageV2.ContextOverflowError(
|
||||
return new ContextOverflowError(
|
||||
{
|
||||
message: parsed.message,
|
||||
responseBody: parsed.responseBody,
|
||||
|
|
@ -1039,7 +1038,7 @@ export namespace MessageV2 {
|
|||
{ cause: e },
|
||||
).toObject()
|
||||
}
|
||||
return new MessageV2.APIError(
|
||||
return new APIError(
|
||||
{
|
||||
message: parsed.message,
|
||||
isRetryable: parsed.isRetryable,
|
||||
|
|
@ -1053,5 +1052,4 @@ export namespace MessageV2 {
|
|||
} catch {}
|
||||
return new NamedError.Unknown({ message: JSON.stringify(e) }, { cause: e }).toObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,17 +3,16 @@ import { SessionID } from "./schema"
|
|||
import { ModelID, ProviderID } from "../provider/schema"
|
||||
import { NamedError } from "@opencode-ai/shared/util/error"
|
||||
|
||||
export namespace Message {
|
||||
export const OutputLengthError = NamedError.create("MessageOutputLengthError", z.object({}))
|
||||
export const AuthError = NamedError.create(
|
||||
export const OutputLengthError = NamedError.create("MessageOutputLengthError", z.object({}))
|
||||
export const AuthError = NamedError.create(
|
||||
"ProviderAuthError",
|
||||
z.object({
|
||||
providerID: z.string(),
|
||||
message: z.string(),
|
||||
}),
|
||||
)
|
||||
)
|
||||
|
||||
export const ToolCall = z
|
||||
export const ToolCall = z
|
||||
.object({
|
||||
state: z.literal("call"),
|
||||
step: z.number().optional(),
|
||||
|
|
@ -24,9 +23,9 @@ export namespace Message {
|
|||
.meta({
|
||||
ref: "ToolCall",
|
||||
})
|
||||
export type ToolCall = z.infer<typeof ToolCall>
|
||||
export type ToolCall = z.infer<typeof ToolCall>
|
||||
|
||||
export const ToolPartialCall = z
|
||||
export const ToolPartialCall = z
|
||||
.object({
|
||||
state: z.literal("partial-call"),
|
||||
step: z.number().optional(),
|
||||
|
|
@ -37,9 +36,9 @@ export namespace Message {
|
|||
.meta({
|
||||
ref: "ToolPartialCall",
|
||||
})
|
||||
export type ToolPartialCall = z.infer<typeof ToolPartialCall>
|
||||
export type ToolPartialCall = z.infer<typeof ToolPartialCall>
|
||||
|
||||
export const ToolResult = z
|
||||
export const ToolResult = z
|
||||
.object({
|
||||
state: z.literal("result"),
|
||||
step: z.number().optional(),
|
||||
|
|
@ -51,14 +50,14 @@ export namespace Message {
|
|||
.meta({
|
||||
ref: "ToolResult",
|
||||
})
|
||||
export type ToolResult = z.infer<typeof ToolResult>
|
||||
export type ToolResult = z.infer<typeof ToolResult>
|
||||
|
||||
export const ToolInvocation = z.discriminatedUnion("state", [ToolCall, ToolPartialCall, ToolResult]).meta({
|
||||
export const ToolInvocation = z.discriminatedUnion("state", [ToolCall, ToolPartialCall, ToolResult]).meta({
|
||||
ref: "ToolInvocation",
|
||||
})
|
||||
export type ToolInvocation = z.infer<typeof ToolInvocation>
|
||||
})
|
||||
export type ToolInvocation = z.infer<typeof ToolInvocation>
|
||||
|
||||
export const TextPart = z
|
||||
export const TextPart = z
|
||||
.object({
|
||||
type: z.literal("text"),
|
||||
text: z.string(),
|
||||
|
|
@ -66,9 +65,9 @@ export namespace Message {
|
|||
.meta({
|
||||
ref: "TextPart",
|
||||
})
|
||||
export type TextPart = z.infer<typeof TextPart>
|
||||
export type TextPart = z.infer<typeof TextPart>
|
||||
|
||||
export const ReasoningPart = z
|
||||
export const ReasoningPart = z
|
||||
.object({
|
||||
type: z.literal("reasoning"),
|
||||
text: z.string(),
|
||||
|
|
@ -77,9 +76,9 @@ export namespace Message {
|
|||
.meta({
|
||||
ref: "ReasoningPart",
|
||||
})
|
||||
export type ReasoningPart = z.infer<typeof ReasoningPart>
|
||||
export type ReasoningPart = z.infer<typeof ReasoningPart>
|
||||
|
||||
export const ToolInvocationPart = z
|
||||
export const ToolInvocationPart = z
|
||||
.object({
|
||||
type: z.literal("tool-invocation"),
|
||||
toolInvocation: ToolInvocation,
|
||||
|
|
@ -87,9 +86,9 @@ export namespace Message {
|
|||
.meta({
|
||||
ref: "ToolInvocationPart",
|
||||
})
|
||||
export type ToolInvocationPart = z.infer<typeof ToolInvocationPart>
|
||||
export type ToolInvocationPart = z.infer<typeof ToolInvocationPart>
|
||||
|
||||
export const SourceUrlPart = z
|
||||
export const SourceUrlPart = z
|
||||
.object({
|
||||
type: z.literal("source-url"),
|
||||
sourceId: z.string(),
|
||||
|
|
@ -100,9 +99,9 @@ export namespace Message {
|
|||
.meta({
|
||||
ref: "SourceUrlPart",
|
||||
})
|
||||
export type SourceUrlPart = z.infer<typeof SourceUrlPart>
|
||||
export type SourceUrlPart = z.infer<typeof SourceUrlPart>
|
||||
|
||||
export const FilePart = z
|
||||
export const FilePart = z
|
||||
.object({
|
||||
type: z.literal("file"),
|
||||
mediaType: z.string(),
|
||||
|
|
@ -112,25 +111,25 @@ export namespace Message {
|
|||
.meta({
|
||||
ref: "FilePart",
|
||||
})
|
||||
export type FilePart = z.infer<typeof FilePart>
|
||||
export type FilePart = z.infer<typeof FilePart>
|
||||
|
||||
export const StepStartPart = z
|
||||
export const StepStartPart = z
|
||||
.object({
|
||||
type: z.literal("step-start"),
|
||||
})
|
||||
.meta({
|
||||
ref: "StepStartPart",
|
||||
})
|
||||
export type StepStartPart = z.infer<typeof StepStartPart>
|
||||
export type StepStartPart = z.infer<typeof StepStartPart>
|
||||
|
||||
export const MessagePart = z
|
||||
export const MessagePart = z
|
||||
.discriminatedUnion("type", [TextPart, ReasoningPart, ToolInvocationPart, SourceUrlPart, FilePart, StepStartPart])
|
||||
.meta({
|
||||
ref: "MessagePart",
|
||||
})
|
||||
export type MessagePart = z.infer<typeof MessagePart>
|
||||
export type MessagePart = z.infer<typeof MessagePart>
|
||||
|
||||
export const Info = z
|
||||
export const Info = z
|
||||
.object({
|
||||
id: z.string(),
|
||||
role: z.enum(["user", "assistant"]),
|
||||
|
|
@ -187,5 +186,4 @@ export namespace Message {
|
|||
.meta({
|
||||
ref: "Message",
|
||||
})
|
||||
export type Info = z.infer<typeof Info>
|
||||
}
|
||||
export type Info = z.infer<typeof Info>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { Config } from "@/config"
|
||||
import type { Provider } from "@/provider"
|
||||
import { ProviderTransform } from "@/provider/transform"
|
||||
import type { MessageV2 } from "./message-v2"
|
||||
import type { MessageV2 } from "."
|
||||
|
||||
const COMPACTION_BUFFER = 20_000
|
||||
|
||||
|
|
|
|||
|
|
@ -7,29 +7,28 @@ import { Permission } from "@/permission"
|
|||
import { Plugin } from "@/plugin"
|
||||
import { Snapshot } from "@/snapshot"
|
||||
import { Session } from "."
|
||||
import { LLM } from "./llm"
|
||||
import { MessageV2 } from "./message-v2"
|
||||
import { LLM } from "."
|
||||
import { MessageV2 } from "."
|
||||
import { isOverflow } from "./overflow"
|
||||
import { PartID } from "./schema"
|
||||
import type { SessionID } from "./schema"
|
||||
import { SessionRetry } from "./retry"
|
||||
import { SessionStatus } from "./status"
|
||||
import { SessionSummary } from "./summary"
|
||||
import { SessionRetry } from "."
|
||||
import { SessionStatus } from "."
|
||||
import { SessionSummary } from "."
|
||||
import type { Provider } from "@/provider"
|
||||
import { Question } from "@/question"
|
||||
import { errorMessage } from "@/util/error"
|
||||
import { Log } from "@/util/log"
|
||||
import { isRecord } from "@/util/record"
|
||||
|
||||
export namespace SessionProcessor {
|
||||
const DOOM_LOOP_THRESHOLD = 3
|
||||
const log = Log.create({ service: "session.processor" })
|
||||
const DOOM_LOOP_THRESHOLD = 3
|
||||
const log = Log.create({ service: "session.processor" })
|
||||
|
||||
export type Result = "compact" | "stop" | "continue"
|
||||
export type Result = "compact" | "stop" | "continue"
|
||||
|
||||
export type Event = LLM.Event
|
||||
export type Event = LLM.Event
|
||||
|
||||
export interface Handle {
|
||||
export interface Handle {
|
||||
readonly message: MessageV2.Assistant
|
||||
readonly updateToolCall: (
|
||||
toolCallID: string,
|
||||
|
|
@ -45,26 +44,26 @@ export namespace SessionProcessor {
|
|||
},
|
||||
) => Effect.Effect<void>
|
||||
readonly process: (streamInput: LLM.StreamInput) => Effect.Effect<Result>
|
||||
}
|
||||
}
|
||||
|
||||
type Input = {
|
||||
type Input = {
|
||||
assistantMessage: MessageV2.Assistant
|
||||
sessionID: SessionID
|
||||
model: Provider.Model
|
||||
}
|
||||
}
|
||||
|
||||
export interface Interface {
|
||||
export interface Interface {
|
||||
readonly create: (input: Input) => Effect.Effect<Handle>
|
||||
}
|
||||
}
|
||||
|
||||
type ToolCall = {
|
||||
type ToolCall = {
|
||||
partID: MessageV2.ToolPart["id"]
|
||||
messageID: MessageV2.ToolPart["messageID"]
|
||||
sessionID: MessageV2.ToolPart["sessionID"]
|
||||
done: Deferred.Deferred<void>
|
||||
}
|
||||
}
|
||||
|
||||
interface ProcessorContext extends Input {
|
||||
interface ProcessorContext extends Input {
|
||||
toolcalls: Record<string, ToolCall>
|
||||
shouldBreak: boolean
|
||||
snapshot: string | undefined
|
||||
|
|
@ -72,13 +71,13 @@ export namespace SessionProcessor {
|
|||
needsCompaction: boolean
|
||||
currentText: MessageV2.TextPart | undefined
|
||||
reasoningMap: Record<string, MessageV2.ReasoningPart>
|
||||
}
|
||||
}
|
||||
|
||||
type StreamEvent = Event
|
||||
type StreamEvent = Event
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionProcessor") {}
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionProcessor") {}
|
||||
|
||||
export const layer: Layer.Layer<
|
||||
export const layer: Layer.Layer<
|
||||
Service,
|
||||
never,
|
||||
| Session.Service
|
||||
|
|
@ -91,7 +90,7 @@ export namespace SessionProcessor {
|
|||
| Plugin.Service
|
||||
| SessionSummary.Service
|
||||
| SessionStatus.Service
|
||||
> = Layer.effect(
|
||||
> = Layer.effect(
|
||||
Service,
|
||||
Effect.gen(function* () {
|
||||
const session = yield* Session.Service
|
||||
|
|
@ -600,9 +599,9 @@ export namespace SessionProcessor {
|
|||
|
||||
return Service.of({ create })
|
||||
}),
|
||||
)
|
||||
)
|
||||
|
||||
export const defaultLayer = Layer.suspend(() =>
|
||||
export const defaultLayer = Layer.suspend(() =>
|
||||
layer.pipe(
|
||||
Layer.provide(Session.defaultLayer),
|
||||
Layer.provide(Snapshot.defaultLayer),
|
||||
|
|
@ -615,5 +614,4 @@ export namespace SessionProcessor {
|
|||
Layer.provide(Bus.layer),
|
||||
Layer.provide(Config.defaultLayer),
|
||||
),
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { NotFoundError, eq, and } from "../storage/db"
|
||||
import { SyncEvent } from "@/sync"
|
||||
import { Session } from "."
|
||||
import { MessageV2 } from "./message-v2"
|
||||
import { MessageV2 } from "."
|
||||
import { SessionTable, MessageTable, PartTable } from "./session.sql"
|
||||
import { Log } from "../util/log"
|
||||
|
||||
|
|
|
|||
|
|
@ -2,19 +2,19 @@ import path from "path"
|
|||
import os from "os"
|
||||
import z from "zod"
|
||||
import { SessionID, MessageID, PartID } from "./schema"
|
||||
import { MessageV2 } from "./message-v2"
|
||||
import { MessageV2 } from "."
|
||||
import { Log } from "../util/log"
|
||||
import { SessionRevert } from "./revert"
|
||||
import { SessionRevert } from "."
|
||||
import { Session } from "."
|
||||
import { Agent } from "../agent/agent"
|
||||
import { Provider } from "../provider"
|
||||
import { ModelID, ProviderID } from "../provider/schema"
|
||||
import { type Tool as AITool, tool, jsonSchema, type ToolExecutionOptions, asSchema } from "ai"
|
||||
import { SessionCompaction } from "./compaction"
|
||||
import { SessionCompaction } from "."
|
||||
import { Bus } from "../bus"
|
||||
import { ProviderTransform } from "../provider/transform"
|
||||
import { SystemPrompt } from "./system"
|
||||
import { Instruction } from "./instruction"
|
||||
import { SystemPrompt } from "."
|
||||
import { Instruction } from "."
|
||||
import { Plugin } from "../plugin"
|
||||
import PROMPT_PLAN from "../session/prompt/plan.txt"
|
||||
import BUILD_SWITCH from "../session/prompt/build-switch.txt"
|
||||
|
|
@ -31,13 +31,13 @@ import * as Stream from "effect/Stream"
|
|||
import { Command } from "../command"
|
||||
import { pathToFileURL, fileURLToPath } from "url"
|
||||
import { ConfigMarkdown } from "../config/markdown"
|
||||
import { SessionSummary } from "./summary"
|
||||
import { SessionSummary } from "."
|
||||
import { NamedError } from "@opencode-ai/shared/util/error"
|
||||
import { SessionProcessor } from "./processor"
|
||||
import { SessionProcessor } from "."
|
||||
import { Tool } from "@/tool/tool"
|
||||
import { Permission } from "@/permission"
|
||||
import { SessionStatus } from "./status"
|
||||
import { LLM } from "./llm"
|
||||
import { SessionStatus } from "."
|
||||
import { LLM } from "."
|
||||
import { Shell } from "@/shell/shell"
|
||||
import { AppFileSystem } from "@opencode-ai/shared/filesystem"
|
||||
import { Truncate } from "@/tool/truncate"
|
||||
|
|
@ -47,7 +47,7 @@ import { Cause, Effect, Exit, Layer, Option, Scope, Context } from "effect"
|
|||
import { EffectLogger } from "@/effect/logger"
|
||||
import { InstanceState } from "@/effect"
|
||||
import { TaskTool, type TaskPromptOps } from "@/tool/task"
|
||||
import { SessionRunState } from "./run-state"
|
||||
import { SessionRunState } from "."
|
||||
import { EffectBridge } from "@/effect"
|
||||
|
||||
// @ts-ignore
|
||||
|
|
@ -63,22 +63,21 @@ IMPORTANT:
|
|||
|
||||
const STRUCTURED_OUTPUT_SYSTEM_PROMPT = `IMPORTANT: The user has requested structured output. You MUST use the StructuredOutput tool to provide your final response. Do NOT respond with plain text - you MUST call the StructuredOutput tool with your answer formatted according to the schema.`
|
||||
|
||||
export namespace SessionPrompt {
|
||||
const log = Log.create({ service: "session.prompt" })
|
||||
const elog = EffectLogger.create({ service: "session.prompt" })
|
||||
const log = Log.create({ service: "session.prompt" })
|
||||
const elog = EffectLogger.create({ service: "session.prompt" })
|
||||
|
||||
export interface Interface {
|
||||
export interface Interface {
|
||||
readonly cancel: (sessionID: SessionID) => Effect.Effect<void>
|
||||
readonly prompt: (input: PromptInput) => Effect.Effect<MessageV2.WithParts>
|
||||
readonly loop: (input: z.infer<typeof LoopInput>) => Effect.Effect<MessageV2.WithParts>
|
||||
readonly shell: (input: ShellInput) => Effect.Effect<MessageV2.WithParts>
|
||||
readonly command: (input: CommandInput) => Effect.Effect<MessageV2.WithParts>
|
||||
readonly resolvePromptParts: (template: string) => Effect.Effect<PromptInput["parts"]>
|
||||
}
|
||||
}
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionPrompt") {}
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionPrompt") {}
|
||||
|
||||
export const layer = Layer.effect(
|
||||
export const layer = Layer.effect(
|
||||
Service,
|
||||
Effect.gen(function* () {
|
||||
const bus = yield* Bus.Service
|
||||
|
|
@ -1677,9 +1676,9 @@ NOTE: At any point in time through this workflow you should feel free to ask the
|
|||
resolvePromptParts,
|
||||
})
|
||||
}),
|
||||
)
|
||||
)
|
||||
|
||||
export const defaultLayer = Layer.suspend(() =>
|
||||
export const defaultLayer = Layer.suspend(() =>
|
||||
layer.pipe(
|
||||
Layer.provide(SessionRunState.defaultLayer),
|
||||
Layer.provide(SessionStatus.defaultLayer),
|
||||
|
|
@ -1709,8 +1708,8 @@ NOTE: At any point in time through this workflow you should feel free to ask the
|
|||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
export const PromptInput = z.object({
|
||||
)
|
||||
export const PromptInput = z.object({
|
||||
sessionID: SessionID.zod,
|
||||
messageID: MessageID.zod.optional(),
|
||||
model: z
|
||||
|
|
@ -1774,14 +1773,14 @@ NOTE: At any point in time through this workflow you should feel free to ask the
|
|||
}),
|
||||
]),
|
||||
),
|
||||
})
|
||||
export type PromptInput = z.infer<typeof PromptInput>
|
||||
})
|
||||
export type PromptInput = z.infer<typeof PromptInput>
|
||||
|
||||
export const LoopInput = z.object({
|
||||
export const LoopInput = z.object({
|
||||
sessionID: SessionID.zod,
|
||||
})
|
||||
})
|
||||
|
||||
export const ShellInput = z.object({
|
||||
export const ShellInput = z.object({
|
||||
sessionID: SessionID.zod,
|
||||
messageID: MessageID.zod.optional(),
|
||||
agent: z.string(),
|
||||
|
|
@ -1792,10 +1791,10 @@ NOTE: At any point in time through this workflow you should feel free to ask the
|
|||
})
|
||||
.optional(),
|
||||
command: z.string(),
|
||||
})
|
||||
export type ShellInput = z.infer<typeof ShellInput>
|
||||
})
|
||||
export type ShellInput = z.infer<typeof ShellInput>
|
||||
|
||||
export const CommandInput = z.object({
|
||||
export const CommandInput = z.object({
|
||||
messageID: MessageID.zod.optional(),
|
||||
sessionID: SessionID.zod,
|
||||
agent: z.string().optional(),
|
||||
|
|
@ -1815,14 +1814,14 @@ NOTE: At any point in time through this workflow you should feel free to ask the
|
|||
]),
|
||||
)
|
||||
.optional(),
|
||||
})
|
||||
export type CommandInput = z.infer<typeof CommandInput>
|
||||
})
|
||||
export type CommandInput = z.infer<typeof CommandInput>
|
||||
|
||||
/** @internal Exported for testing */
|
||||
export function createStructuredOutputTool(input: {
|
||||
/** @internal Exported for testing */
|
||||
export function createStructuredOutputTool(input: {
|
||||
schema: Record<string, any>
|
||||
onSuccess: (output: unknown) => void
|
||||
}): AITool {
|
||||
}): AITool {
|
||||
// Remove $schema property if present (not needed for tool input)
|
||||
const { $schema: _, ...toolSchema } = input.schema
|
||||
|
||||
|
|
@ -1846,10 +1845,9 @@ NOTE: At any point in time through this workflow you should feel free to ask the
|
|||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
const bashRegex = /!`([^`]+)`/g
|
||||
// Match [Image N] as single token, quoted strings, or non-space sequences
|
||||
const argsRegex = /(?:\[Image\s+\d+\]|"[^"]*"|'[^']*'|[^\s"']+)/gi
|
||||
const placeholderRegex = /\$(\d+)/g
|
||||
const quoteTrimRegex = /^["']|["']$/g
|
||||
}
|
||||
const bashRegex = /!`([^`]+)`/g
|
||||
// Match [Image N] as single token, quoted strings, or non-space sequences
|
||||
const argsRegex = /(?:\[Image\s+\d+\]|"[^"]*"|'[^']*'|[^\s"']+)/gi
|
||||
const placeholderRegex = /\$(\d+)/g
|
||||
const quoteTrimRegex = /^["']|["']$/g
|
||||
|
|
|
|||
|
|
@ -1,25 +1,24 @@
|
|||
import type { NamedError } from "@opencode-ai/shared/util/error"
|
||||
import { Cause, Clock, Duration, Effect, Schedule } from "effect"
|
||||
import { MessageV2 } from "./message-v2"
|
||||
import { MessageV2 } from "."
|
||||
import { iife } from "@/util/iife"
|
||||
|
||||
export namespace SessionRetry {
|
||||
export type Err = ReturnType<NamedError["toObject"]>
|
||||
export type Err = ReturnType<NamedError["toObject"]>
|
||||
|
||||
// This exported message is shared with the TUI upsell detector. Matching on a
|
||||
// literal error string kind of sucks, but it is the simplest for now.
|
||||
export const GO_UPSELL_MESSAGE = "Free usage exceeded, subscribe to Go https://opencode.ai/go"
|
||||
// This exported message is shared with the TUI upsell detector. Matching on a
|
||||
// literal error string kind of sucks, but it is the simplest for now.
|
||||
export const GO_UPSELL_MESSAGE = "Free usage exceeded, subscribe to Go https://opencode.ai/go"
|
||||
|
||||
export const RETRY_INITIAL_DELAY = 2000
|
||||
export const RETRY_BACKOFF_FACTOR = 2
|
||||
export const RETRY_MAX_DELAY_NO_HEADERS = 30_000 // 30 seconds
|
||||
export const RETRY_MAX_DELAY = 2_147_483_647 // max 32-bit signed integer for setTimeout
|
||||
export const RETRY_INITIAL_DELAY = 2000
|
||||
export const RETRY_BACKOFF_FACTOR = 2
|
||||
export const RETRY_MAX_DELAY_NO_HEADERS = 30_000 // 30 seconds
|
||||
export const RETRY_MAX_DELAY = 2_147_483_647 // max 32-bit signed integer for setTimeout
|
||||
|
||||
function cap(ms: number) {
|
||||
function cap(ms: number) {
|
||||
return Math.min(ms, RETRY_MAX_DELAY)
|
||||
}
|
||||
}
|
||||
|
||||
export function delay(attempt: number, error?: MessageV2.APIError) {
|
||||
export function delay(attempt: number, error?: MessageV2.APIError) {
|
||||
if (error) {
|
||||
const headers = error.data.responseHeaders
|
||||
if (headers) {
|
||||
|
|
@ -50,9 +49,9 @@ export namespace SessionRetry {
|
|||
}
|
||||
|
||||
return cap(Math.min(RETRY_INITIAL_DELAY * Math.pow(RETRY_BACKOFF_FACTOR, attempt - 1), RETRY_MAX_DELAY_NO_HEADERS))
|
||||
}
|
||||
}
|
||||
|
||||
export function retryable(error: Err) {
|
||||
export function retryable(error: Err) {
|
||||
// context overflow errors should not be retried
|
||||
if (MessageV2.ContextOverflowError.isInstance(error)) return undefined
|
||||
if (MessageV2.APIError.isInstance(error)) {
|
||||
|
|
@ -102,12 +101,12 @@ export namespace SessionRetry {
|
|||
return "Rate Limited"
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
export function policy(opts: {
|
||||
export function policy(opts: {
|
||||
parse: (error: unknown) => Err
|
||||
set: (input: { attempt: number; message: string; next: number }) => Effect.Effect<void>
|
||||
}) {
|
||||
}) {
|
||||
return Schedule.fromStepWithMetadata(
|
||||
Effect.succeed((meta: Schedule.InputMetadata<unknown>) => {
|
||||
const error = opts.parse(meta.input)
|
||||
|
|
@ -121,5 +120,4 @@ export namespace SessionRetry {
|
|||
})
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,30 +6,29 @@ import { Storage } from "@/storage/storage"
|
|||
import { SyncEvent } from "../sync"
|
||||
import { Log } from "../util/log"
|
||||
import { Session } from "."
|
||||
import { MessageV2 } from "./message-v2"
|
||||
import { MessageV2 } from "."
|
||||
import { SessionID, MessageID, PartID } from "./schema"
|
||||
import { SessionRunState } from "./run-state"
|
||||
import { SessionSummary } from "./summary"
|
||||
import { SessionRunState } from "."
|
||||
import { SessionSummary } from "."
|
||||
|
||||
export namespace SessionRevert {
|
||||
const log = Log.create({ service: "session.revert" })
|
||||
const log = Log.create({ service: "session.revert" })
|
||||
|
||||
export const RevertInput = z.object({
|
||||
export const RevertInput = z.object({
|
||||
sessionID: SessionID.zod,
|
||||
messageID: MessageID.zod,
|
||||
partID: PartID.zod.optional(),
|
||||
})
|
||||
export type RevertInput = z.infer<typeof RevertInput>
|
||||
})
|
||||
export type RevertInput = z.infer<typeof RevertInput>
|
||||
|
||||
export interface Interface {
|
||||
export interface Interface {
|
||||
readonly revert: (input: RevertInput) => Effect.Effect<Session.Info>
|
||||
readonly unrevert: (input: { sessionID: SessionID }) => Effect.Effect<Session.Info>
|
||||
readonly cleanup: (session: Session.Info) => Effect.Effect<void>
|
||||
}
|
||||
}
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionRevert") {}
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionRevert") {}
|
||||
|
||||
export const layer = Layer.effect(
|
||||
export const layer = Layer.effect(
|
||||
Service,
|
||||
Effect.gen(function* () {
|
||||
const sessions = yield* Session.Service
|
||||
|
|
@ -146,9 +145,9 @@ export namespace SessionRevert {
|
|||
|
||||
return Service.of({ revert, unrevert, cleanup })
|
||||
}),
|
||||
)
|
||||
)
|
||||
|
||||
export const defaultLayer = Layer.suspend(() =>
|
||||
export const defaultLayer = Layer.suspend(() =>
|
||||
layer.pipe(
|
||||
Layer.provide(SessionRunState.defaultLayer),
|
||||
Layer.provide(Session.defaultLayer),
|
||||
|
|
@ -157,5 +156,4 @@ export namespace SessionRevert {
|
|||
Layer.provide(Bus.layer),
|
||||
Layer.provide(SessionSummary.defaultLayer),
|
||||
),
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@ import { InstanceState } from "@/effect"
|
|||
import { Runner } from "@/effect/runner"
|
||||
import { Effect, Layer, Scope, Context } from "effect"
|
||||
import { Session } from "."
|
||||
import { MessageV2 } from "./message-v2"
|
||||
import { MessageV2 } from "."
|
||||
import { SessionID } from "./schema"
|
||||
import { SessionStatus } from "./status"
|
||||
import { SessionStatus } from "."
|
||||
|
||||
export namespace SessionRunState {
|
||||
export interface Interface {
|
||||
export interface Interface {
|
||||
readonly assertNotBusy: (sessionID: SessionID) => Effect.Effect<void>
|
||||
readonly cancel: (sessionID: SessionID) => Effect.Effect<void>
|
||||
readonly ensureRunning: (
|
||||
|
|
@ -20,11 +19,11 @@ export namespace SessionRunState {
|
|||
onInterrupt: Effect.Effect<MessageV2.WithParts>,
|
||||
work: Effect.Effect<MessageV2.WithParts>,
|
||||
) => Effect.Effect<MessageV2.WithParts>
|
||||
}
|
||||
}
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionRunState") {}
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionRunState") {}
|
||||
|
||||
export const layer = Layer.effect(
|
||||
export const layer = Layer.effect(
|
||||
Service,
|
||||
Effect.gen(function* () {
|
||||
const status = yield* SessionStatus.Service
|
||||
|
|
@ -102,7 +101,6 @@ export namespace SessionRunState {
|
|||
|
||||
return Service.of({ assertNotBusy, cancel, ensureRunning, startShell })
|
||||
}),
|
||||
)
|
||||
)
|
||||
|
||||
export const defaultLayer = layer.pipe(Layer.provide(SessionStatus.defaultLayer))
|
||||
}
|
||||
export const defaultLayer = layer.pipe(Layer.provide(SessionStatus.defaultLayer))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { sqliteTable, text, integer, index, primaryKey } from "drizzle-orm/sqlite-core"
|
||||
import { ProjectTable } from "../project/project.sql"
|
||||
import type { MessageV2 } from "./message-v2"
|
||||
import type { MessageV2 } from "."
|
||||
import type { SessionEntry } from "../v2/session-entry"
|
||||
import type { Snapshot } from "../snapshot"
|
||||
import type { Permission } from "../permission"
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import { ProjectTable } from "../project/project.sql"
|
|||
import { Storage } from "@/storage/storage"
|
||||
import { Log } from "../util/log"
|
||||
import { updateSchema } from "../util/update-schema"
|
||||
import { MessageV2 } from "./message-v2"
|
||||
import { MessageV2 } from "."
|
||||
import { Instance } from "../project/instance"
|
||||
import { InstanceState } from "@/effect"
|
||||
import { Snapshot } from "@/snapshot"
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ import { SessionID } from "./schema"
|
|||
import { Effect, Layer, Context } from "effect"
|
||||
import z from "zod"
|
||||
|
||||
export namespace SessionStatus {
|
||||
export const Info = z
|
||||
export const Info = z
|
||||
.union([
|
||||
z.object({
|
||||
type: z.literal("idle"),
|
||||
|
|
@ -24,9 +23,9 @@ export namespace SessionStatus {
|
|||
.meta({
|
||||
ref: "SessionStatus",
|
||||
})
|
||||
export type Info = z.infer<typeof Info>
|
||||
export type Info = z.infer<typeof Info>
|
||||
|
||||
export const Event = {
|
||||
export const Event = {
|
||||
Status: BusEvent.define(
|
||||
"session.status",
|
||||
z.object({
|
||||
|
|
@ -41,17 +40,17 @@ export namespace SessionStatus {
|
|||
sessionID: SessionID.zod,
|
||||
}),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
export interface Interface {
|
||||
export interface Interface {
|
||||
readonly get: (sessionID: SessionID) => Effect.Effect<Info>
|
||||
readonly list: () => Effect.Effect<Map<SessionID, Info>>
|
||||
readonly set: (sessionID: SessionID, status: Info) => Effect.Effect<void>
|
||||
}
|
||||
}
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionStatus") {}
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionStatus") {}
|
||||
|
||||
export const layer = Layer.effect(
|
||||
export const layer = Layer.effect(
|
||||
Service,
|
||||
Effect.gen(function* () {
|
||||
const bus = yield* Bus.Service
|
||||
|
|
@ -82,7 +81,6 @@ export namespace SessionStatus {
|
|||
|
||||
return Service.of({ get, list, set })
|
||||
}),
|
||||
)
|
||||
)
|
||||
|
||||
export const defaultLayer = layer.pipe(Layer.provide(Bus.layer))
|
||||
}
|
||||
export const defaultLayer = layer.pipe(Layer.provide(Bus.layer))
|
||||
|
|
|
|||
|
|
@ -4,11 +4,10 @@ import { Bus } from "@/bus"
|
|||
import { Snapshot } from "@/snapshot"
|
||||
import { Storage } from "@/storage/storage"
|
||||
import { Session } from "."
|
||||
import { MessageV2 } from "./message-v2"
|
||||
import { MessageV2 } from "."
|
||||
import { SessionID, MessageID } from "./schema"
|
||||
|
||||
export namespace SessionSummary {
|
||||
function unquoteGitPath(input: string) {
|
||||
function unquoteGitPath(input: string) {
|
||||
if (!input.startsWith('"')) return input
|
||||
if (!input.endsWith('"')) return input
|
||||
const body = input.slice(1, -1)
|
||||
|
|
@ -62,17 +61,17 @@ export namespace SessionSummary {
|
|||
}
|
||||
|
||||
return Buffer.from(bytes).toString()
|
||||
}
|
||||
}
|
||||
|
||||
export interface Interface {
|
||||
export interface Interface {
|
||||
readonly summarize: (input: { sessionID: SessionID; messageID: MessageID }) => Effect.Effect<void>
|
||||
readonly diff: (input: { sessionID: SessionID; messageID?: MessageID }) => Effect.Effect<Snapshot.FileDiff[]>
|
||||
readonly computeDiff: (input: { messages: MessageV2.WithParts[] }) => Effect.Effect<Snapshot.FileDiff[]>
|
||||
}
|
||||
}
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionSummary") {}
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionSummary") {}
|
||||
|
||||
export const layer = Layer.effect(
|
||||
export const layer = Layer.effect(
|
||||
Service,
|
||||
Effect.gen(function* () {
|
||||
const sessions = yield* Session.Service
|
||||
|
|
@ -147,19 +146,18 @@ export namespace SessionSummary {
|
|||
|
||||
return Service.of({ summarize, diff, computeDiff })
|
||||
}),
|
||||
)
|
||||
)
|
||||
|
||||
export const defaultLayer = Layer.suspend(() =>
|
||||
export const defaultLayer = Layer.suspend(() =>
|
||||
layer.pipe(
|
||||
Layer.provide(Session.defaultLayer),
|
||||
Layer.provide(Snapshot.defaultLayer),
|
||||
Layer.provide(Storage.defaultLayer),
|
||||
Layer.provide(Bus.layer),
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
export const DiffInput = z.object({
|
||||
export const DiffInput = z.object({
|
||||
sessionID: SessionID.zod,
|
||||
messageID: MessageID.zod.optional(),
|
||||
})
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@ import type { Agent } from "@/agent/agent"
|
|||
import { Permission } from "@/permission"
|
||||
import { Skill } from "@/skill"
|
||||
|
||||
export namespace SystemPrompt {
|
||||
export function provider(model: Provider.Model) {
|
||||
export function provider(model: Provider.Model) {
|
||||
if (model.api.id.includes("gpt-4") || model.api.id.includes("o1") || model.api.id.includes("o3"))
|
||||
return [PROMPT_BEAST]
|
||||
if (model.api.id.includes("gpt")) {
|
||||
|
|
@ -31,16 +30,16 @@ export namespace SystemPrompt {
|
|||
if (model.api.id.toLowerCase().includes("trinity")) return [PROMPT_TRINITY]
|
||||
if (model.api.id.toLowerCase().includes("kimi")) return [PROMPT_KIMI]
|
||||
return [PROMPT_DEFAULT]
|
||||
}
|
||||
}
|
||||
|
||||
export interface Interface {
|
||||
export interface Interface {
|
||||
readonly environment: (model: Provider.Model) => string[]
|
||||
readonly skills: (agent: Agent.Info) => Effect.Effect<string | undefined>
|
||||
}
|
||||
}
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SystemPrompt") {}
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SystemPrompt") {}
|
||||
|
||||
export const layer = Layer.effect(
|
||||
export const layer = Layer.effect(
|
||||
Service,
|
||||
Effect.gen(function* () {
|
||||
const skill = yield* Skill.Service
|
||||
|
|
@ -78,7 +77,6 @@ export namespace SystemPrompt {
|
|||
}),
|
||||
})
|
||||
}),
|
||||
)
|
||||
)
|
||||
|
||||
export const defaultLayer = layer.pipe(Layer.provide(Skill.defaultLayer))
|
||||
}
|
||||
export const defaultLayer = layer.pipe(Layer.provide(Skill.defaultLayer))
|
||||
|
|
|
|||
|
|
@ -6,17 +6,16 @@ import z from "zod"
|
|||
import { Database, eq, asc } from "../storage/db"
|
||||
import { TodoTable } from "./session.sql"
|
||||
|
||||
export namespace Todo {
|
||||
export const Info = z
|
||||
export const Info = z
|
||||
.object({
|
||||
content: z.string().describe("Brief description of the task"),
|
||||
status: z.string().describe("Current status of the task: pending, in_progress, completed, cancelled"),
|
||||
priority: z.string().describe("Priority level of the task: high, medium, low"),
|
||||
})
|
||||
.meta({ ref: "Todo" })
|
||||
export type Info = z.infer<typeof Info>
|
||||
export type Info = z.infer<typeof Info>
|
||||
|
||||
export const Event = {
|
||||
export const Event = {
|
||||
Updated: BusEvent.define(
|
||||
"todo.updated",
|
||||
z.object({
|
||||
|
|
@ -24,16 +23,16 @@ export namespace Todo {
|
|||
todos: z.array(Info),
|
||||
}),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
export interface Interface {
|
||||
export interface Interface {
|
||||
readonly update: (input: { sessionID: SessionID; todos: Info[] }) => Effect.Effect<void>
|
||||
readonly get: (sessionID: SessionID) => Effect.Effect<Info[]>
|
||||
}
|
||||
}
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionTodo") {}
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionTodo") {}
|
||||
|
||||
export const layer = Layer.effect(
|
||||
export const layer = Layer.effect(
|
||||
Service,
|
||||
Effect.gen(function* () {
|
||||
const bus = yield* Bus.Service
|
||||
|
|
@ -79,7 +78,6 @@ export namespace Todo {
|
|||
|
||||
return Service.of({ update, get })
|
||||
}),
|
||||
)
|
||||
)
|
||||
|
||||
export const defaultLayer = layer.pipe(Layer.provide(Bus.layer))
|
||||
}
|
||||
export const defaultLayer = layer.pipe(Layer.provide(Bus.layer))
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { InstanceState } from "@/effect"
|
|||
import { Provider } from "@/provider"
|
||||
import { ModelID, ProviderID } from "@/provider/schema"
|
||||
import { Session } from "@/session"
|
||||
import { MessageV2 } from "@/session/message-v2"
|
||||
import { MessageV2 } from "@/session"
|
||||
import type { SessionID } from "@/session/schema"
|
||||
import { Database, eq } from "@/storage/db"
|
||||
import { Config } from "@/config"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Effect } from "effect"
|
|||
import { Tool } from "./tool"
|
||||
import { Question } from "../question"
|
||||
import { Session } from "../session"
|
||||
import { MessageV2 } from "../session/message-v2"
|
||||
import { MessageV2 } from "../session"
|
||||
import { Provider } from "../provider"
|
||||
import { Instance } from "../project/instance"
|
||||
import { type SessionID, MessageID, PartID } from "../session/schema"
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { FileTime } from "../file/time"
|
|||
import DESCRIPTION from "./read.txt"
|
||||
import { Instance } from "../project/instance"
|
||||
import { assertExternalDirectoryEffect } from "./external-directory"
|
||||
import { Instruction } from "../session/instruction"
|
||||
import { Instruction } from "../session"
|
||||
|
||||
const DEFAULT_READ_LIMIT = 2000
|
||||
const MAX_LINE_LENGTH = 2000
|
||||
|
|
|
|||
|
|
@ -37,10 +37,10 @@ import { Ripgrep } from "../file/ripgrep"
|
|||
import { Format } from "../format"
|
||||
import { InstanceState } from "@/effect"
|
||||
import { Question } from "../question"
|
||||
import { Todo } from "../session/todo"
|
||||
import { Todo } from "../session"
|
||||
import { LSP } from "../lsp"
|
||||
import { FileTime } from "../file/time"
|
||||
import { Instruction } from "../session/instruction"
|
||||
import { Instruction } from "../session"
|
||||
import { AppFileSystem } from "@opencode-ai/shared/filesystem"
|
||||
import { Bus } from "../bus"
|
||||
import { Agent } from "../agent/agent"
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ import DESCRIPTION from "./task.txt"
|
|||
import z from "zod"
|
||||
import { Session } from "../session"
|
||||
import { SessionID, MessageID } from "../session/schema"
|
||||
import { MessageV2 } from "../session/message-v2"
|
||||
import { MessageV2 } from "../session"
|
||||
import { Agent } from "../agent/agent"
|
||||
import type { SessionPrompt } from "../session/prompt"
|
||||
import type { SessionPrompt } from "../session"
|
||||
import { Config } from "../config"
|
||||
import { Effect } from "effect"
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import z from "zod"
|
|||
import { Effect } from "effect"
|
||||
import { Tool } from "./tool"
|
||||
import DESCRIPTION_WRITE from "./todowrite.txt"
|
||||
import { Todo } from "../session/todo"
|
||||
import { Todo } from "../session"
|
||||
|
||||
const parameters = z.object({
|
||||
todos: z.array(z.object(Todo.Info.shape)).describe("The updated todo list"),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import z from "zod"
|
||||
import { Effect } from "effect"
|
||||
import type { MessageV2 } from "../session/message-v2"
|
||||
import type { MessageV2 } from "../session"
|
||||
import type { Permission } from "../permission"
|
||||
import type { SessionID, MessageID } from "../session/schema"
|
||||
import { Truncate } from "./truncate"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { test, expect, describe } from "bun:test"
|
||||
import { extractResponseText, formatPromptTooLargeError } from "../../src/cli/cmd/github"
|
||||
import type { MessageV2 } from "../../src/session/message-v2"
|
||||
import type { MessageV2 } from "../../src/session"
|
||||
import { SessionID, MessageID, PartID } from "../../src/session/schema"
|
||||
|
||||
// Helper to create minimal valid parts
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { Effect } from "effect"
|
|||
import { Instance } from "../../src/project/instance"
|
||||
import { Server } from "../../src/server/server"
|
||||
import { Session as SessionNs } from "../../src/session"
|
||||
import { MessageV2 } from "../../src/session/message-v2"
|
||||
import { MessageV2 } from "../../src/session"
|
||||
import { MessageID, PartID, type SessionID } from "../../src/session/schema"
|
||||
import { Log } from "../../src/util/log"
|
||||
import { tmpdir } from "../fixture/fixture"
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import z from "zod"
|
|||
import { Bus } from "../../src/bus"
|
||||
import { Config } from "../../src/config"
|
||||
import { Agent } from "../../src/agent/agent"
|
||||
import { LLM } from "../../src/session/llm"
|
||||
import { SessionCompaction } from "../../src/session/compaction"
|
||||
import { LLM } from "../../src/session"
|
||||
import { SessionCompaction } from "../../src/session"
|
||||
import { Token } from "../../src/util/token"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { Log } from "../../src/util/log"
|
||||
|
|
@ -15,13 +15,13 @@ import { Permission } from "../../src/permission"
|
|||
import { Plugin } from "../../src/plugin"
|
||||
import { provideTmpdirInstance, tmpdir } from "../fixture/fixture"
|
||||
import { Session as SessionNs } from "../../src/session"
|
||||
import { MessageV2 } from "../../src/session/message-v2"
|
||||
import { MessageV2 } from "../../src/session"
|
||||
import { MessageID, PartID, SessionID } from "../../src/session/schema"
|
||||
import { SessionStatus } from "../../src/session/status"
|
||||
import { SessionSummary } from "../../src/session/summary"
|
||||
import { SessionStatus } from "../../src/session"
|
||||
import { SessionSummary } from "../../src/session"
|
||||
import { ModelID, ProviderID } from "../../src/provider/schema"
|
||||
import type { Provider } from "../../src/provider"
|
||||
import * as SessionProcessorModule from "../../src/session/processor"
|
||||
import * as SessionProcessorModule from "../../src/session"
|
||||
import { Snapshot } from "../../src/snapshot"
|
||||
import { ProviderTest } from "../fake/provider"
|
||||
import { testEffect } from "../lib/effect"
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"
|
|||
import path from "path"
|
||||
import { Effect } from "effect"
|
||||
import { ModelID, ProviderID } from "../../src/provider/schema"
|
||||
import { Instruction } from "../../src/session/instruction"
|
||||
import type { MessageV2 } from "../../src/session/message-v2"
|
||||
import { Instruction } from "../../src/session"
|
||||
import type { MessageV2 } from "../../src/session"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { MessageID, PartID, SessionID } from "../../src/session/schema"
|
||||
import { Global } from "../../src/global"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { tool, type ModelMessage } from "ai"
|
|||
import { Cause, Effect, Exit, Stream } from "effect"
|
||||
import z from "zod"
|
||||
import { makeRuntime } from "../../src/effect/run-service"
|
||||
import { LLM } from "../../src/session/llm"
|
||||
import { LLM } from "../../src/session"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { Provider } from "../../src/provider"
|
||||
import { ProviderTransform } from "../../src/provider/transform"
|
||||
|
|
@ -13,7 +13,7 @@ import { ProviderID, ModelID } from "../../src/provider/schema"
|
|||
import { Filesystem } from "../../src/util/filesystem"
|
||||
import { tmpdir } from "../fixture/fixture"
|
||||
import type { Agent } from "../../src/agent/agent"
|
||||
import { MessageV2 } from "../../src/session/message-v2"
|
||||
import { MessageV2 } from "../../src/session"
|
||||
import { SessionID, MessageID } from "../../src/session/schema"
|
||||
import { AppRuntime } from "../../src/effect/app-runtime"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { describe, expect, test } from "bun:test"
|
||||
import { APICallError } from "ai"
|
||||
import { MessageV2 } from "../../src/session/message-v2"
|
||||
import { MessageV2 } from "../../src/session"
|
||||
import type { Provider } from "../../src/provider"
|
||||
import { ModelID, ProviderID } from "../../src/provider/schema"
|
||||
import { SessionID, MessageID, PartID } from "../../src/session/schema"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { Effect } from "effect"
|
|||
import path from "path"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { Session as SessionNs } from "../../src/session"
|
||||
import { MessageV2 } from "../../src/session/message-v2"
|
||||
import { MessageV2 } from "../../src/session"
|
||||
import { MessageID, PartID, type SessionID } from "../../src/session/schema"
|
||||
import { ModelID, ProviderID } from "../../src/provider/schema"
|
||||
import { Log } from "../../src/util/log"
|
||||
|
|
|
|||
|
|
@ -11,12 +11,12 @@ import { Plugin } from "../../src/plugin"
|
|||
import { Provider } from "../../src/provider"
|
||||
import { ModelID, ProviderID } from "../../src/provider/schema"
|
||||
import { Session } from "../../src/session"
|
||||
import { LLM } from "../../src/session/llm"
|
||||
import { MessageV2 } from "../../src/session/message-v2"
|
||||
import { SessionProcessor } from "../../src/session/processor"
|
||||
import { LLM } from "../../src/session"
|
||||
import { MessageV2 } from "../../src/session"
|
||||
import { SessionProcessor } from "../../src/session"
|
||||
import { MessageID, PartID, SessionID } from "../../src/session/schema"
|
||||
import { SessionStatus } from "../../src/session/status"
|
||||
import { SessionSummary } from "../../src/session/summary"
|
||||
import { SessionStatus } from "../../src/session"
|
||||
import { SessionSummary } from "../../src/session"
|
||||
import { Snapshot } from "../../src/snapshot"
|
||||
import { Log } from "../../src/util/log"
|
||||
import * as CrossSpawnSpawner from "../../src/effect/cross-spawn-spawner"
|
||||
|
|
|
|||
|
|
@ -16,22 +16,22 @@ import { Provider as ProviderSvc } from "../../src/provider"
|
|||
import { Env } from "../../src/env"
|
||||
import { ModelID, ProviderID } from "../../src/provider/schema"
|
||||
import { Question } from "../../src/question"
|
||||
import { Todo } from "../../src/session/todo"
|
||||
import { Todo } from "../../src/session"
|
||||
import { Session } from "../../src/session"
|
||||
import { LLM } from "../../src/session/llm"
|
||||
import { MessageV2 } from "../../src/session/message-v2"
|
||||
import { LLM } from "../../src/session"
|
||||
import { MessageV2 } from "../../src/session"
|
||||
import { AppFileSystem } from "@opencode-ai/shared/filesystem"
|
||||
import { SessionCompaction } from "../../src/session/compaction"
|
||||
import { SessionSummary } from "../../src/session/summary"
|
||||
import { Instruction } from "../../src/session/instruction"
|
||||
import { SessionProcessor } from "../../src/session/processor"
|
||||
import { SessionPrompt } from "../../src/session/prompt"
|
||||
import { SessionRevert } from "../../src/session/revert"
|
||||
import { SessionRunState } from "../../src/session/run-state"
|
||||
import { SessionCompaction } from "../../src/session"
|
||||
import { SessionSummary } from "../../src/session"
|
||||
import { Instruction } from "../../src/session"
|
||||
import { SessionProcessor } from "../../src/session"
|
||||
import { SessionPrompt } from "../../src/session"
|
||||
import { SessionRevert } from "../../src/session"
|
||||
import { SessionRunState } from "../../src/session"
|
||||
import { MessageID, PartID, SessionID } from "../../src/session/schema"
|
||||
import { SessionStatus } from "../../src/session/status"
|
||||
import { SessionStatus } from "../../src/session"
|
||||
import { Skill } from "../../src/skill"
|
||||
import { SystemPrompt } from "../../src/session/system"
|
||||
import { SystemPrompt } from "../../src/session"
|
||||
import { Shell } from "../../src/shell/shell"
|
||||
import { Snapshot } from "../../src/snapshot"
|
||||
import { ToolRegistry } from "../../src/tool/registry"
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import { Effect, Layer } from "effect"
|
|||
import { Instance } from "../../src/project/instance"
|
||||
import { ModelID, ProviderID } from "../../src/provider/schema"
|
||||
import { Session } from "../../src/session"
|
||||
import { MessageV2 } from "../../src/session/message-v2"
|
||||
import { SessionPrompt } from "../../src/session/prompt"
|
||||
import { MessageV2 } from "../../src/session"
|
||||
import { SessionPrompt } from "../../src/session"
|
||||
import { Log } from "../../src/util/log"
|
||||
import { tmpdir } from "../fixture/fixture"
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ import type { NamedError } from "@opencode-ai/shared/util/error"
|
|||
import { APICallError } from "ai"
|
||||
import { setTimeout as sleep } from "node:timers/promises"
|
||||
import { Effect, Schedule } from "effect"
|
||||
import { SessionRetry } from "../../src/session/retry"
|
||||
import { MessageV2 } from "../../src/session/message-v2"
|
||||
import { SessionRetry } from "../../src/session"
|
||||
import { MessageV2 } from "../../src/session"
|
||||
import { ProviderID } from "../../src/provider/schema"
|
||||
import { AppRuntime } from "../../src/effect/app-runtime"
|
||||
import { SessionID } from "../../src/session/schema"
|
||||
import { SessionStatus } from "../../src/session/status"
|
||||
import { SessionStatus } from "../../src/session"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { tmpdir } from "../fixture/fixture"
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import path from "path"
|
|||
import { Effect, Layer } from "effect"
|
||||
import { Session } from "../../src/session"
|
||||
import { ModelID, ProviderID } from "../../src/provider/schema"
|
||||
import { SessionRevert } from "../../src/session/revert"
|
||||
import { MessageV2 } from "../../src/session/message-v2"
|
||||
import { SessionRevert } from "../../src/session"
|
||||
import { MessageV2 } from "../../src/session"
|
||||
import { Snapshot } from "../../src/snapshot"
|
||||
import { Log } from "../../src/util/log"
|
||||
import { MessageID, PartID, SessionID } from "../../src/session/schema"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Session as SessionNs } from "../../src/session"
|
|||
import { Bus } from "../../src/bus"
|
||||
import { Log } from "../../src/util/log"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { MessageV2 } from "../../src/session/message-v2"
|
||||
import { MessageV2 } from "../../src/session"
|
||||
import { MessageID, PartID, type SessionID } from "../../src/session/schema"
|
||||
import { AppRuntime } from "../../src/effect/app-runtime"
|
||||
import { tmpdir } from "../fixture/fixture"
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ import { FetchHttpClient } from "effect/unstable/http"
|
|||
import fs from "fs/promises"
|
||||
import path from "path"
|
||||
import { Session } from "../../src/session"
|
||||
import { LLM } from "../../src/session/llm"
|
||||
import { SessionPrompt } from "../../src/session/prompt"
|
||||
import { SessionRevert } from "../../src/session/revert"
|
||||
import { SessionSummary } from "../../src/session/summary"
|
||||
import { MessageV2 } from "../../src/session/message-v2"
|
||||
import { LLM } from "../../src/session"
|
||||
import { SessionPrompt } from "../../src/session"
|
||||
import { SessionRevert } from "../../src/session"
|
||||
import { SessionSummary } from "../../src/session"
|
||||
import { MessageV2 } from "../../src/session"
|
||||
import { Log } from "../../src/util/log"
|
||||
import { provideTmpdirServer } from "../fixture/fixture"
|
||||
import { testEffect } from "../lib/effect"
|
||||
|
|
@ -42,13 +42,13 @@ import { Provider as ProviderSvc } from "../../src/provider"
|
|||
import { Env } from "../../src/env"
|
||||
import { Question } from "../../src/question"
|
||||
import { Skill } from "../../src/skill"
|
||||
import { SystemPrompt } from "../../src/session/system"
|
||||
import { Todo } from "../../src/session/todo"
|
||||
import { SessionCompaction } from "../../src/session/compaction"
|
||||
import { Instruction } from "../../src/session/instruction"
|
||||
import { SessionProcessor } from "../../src/session/processor"
|
||||
import { SessionRunState } from "../../src/session/run-state"
|
||||
import { SessionStatus } from "../../src/session/status"
|
||||
import { SystemPrompt } from "../../src/session"
|
||||
import { Todo } from "../../src/session"
|
||||
import { SessionCompaction } from "../../src/session"
|
||||
import { Instruction } from "../../src/session"
|
||||
import { SessionProcessor } from "../../src/session"
|
||||
import { SessionRunState } from "../../src/session"
|
||||
import { SessionStatus } from "../../src/session"
|
||||
import { Snapshot } from "../../src/snapshot"
|
||||
import { ToolRegistry } from "../../src/tool/registry"
|
||||
import { Truncate } from "../../src/tool/truncate"
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ import { describe, expect, test } from "bun:test"
|
|||
import path from "path"
|
||||
import { Effect, Layer } from "effect"
|
||||
import { Session } from "../../src/session"
|
||||
import { SessionPrompt } from "../../src/session/prompt"
|
||||
import { SessionPrompt } from "../../src/session"
|
||||
import { Log } from "../../src/util/log"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { MessageV2 } from "../../src/session/message-v2"
|
||||
import { MessageV2 } from "../../src/session"
|
||||
|
||||
const projectRoot = path.join(__dirname, "../..")
|
||||
Log.init({ print: false })
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { describe, expect, test } from "bun:test"
|
||||
import { MessageV2 } from "../../src/session/message-v2"
|
||||
import { SessionPrompt } from "../../src/session/prompt"
|
||||
import { MessageV2 } from "../../src/session"
|
||||
import { SessionPrompt } from "../../src/session"
|
||||
import { SessionID, MessageID } from "../../src/session/schema"
|
||||
|
||||
describe("structured-output.OutputFormat", () => {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import path from "path"
|
|||
import { Effect } from "effect"
|
||||
import { Agent } from "../../src/agent/agent"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { SystemPrompt } from "../../src/session/system"
|
||||
import { SystemPrompt } from "../../src/session"
|
||||
import { provideInstance, tmpdir } from "../fixture/fixture"
|
||||
|
||||
function load<A>(dir: string, fn: (svc: Agent.Interface) => Effect.Effect<A>) {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { LSP } from "../../src/lsp"
|
|||
import { Permission } from "../../src/permission"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { SessionID, MessageID } from "../../src/session/schema"
|
||||
import { Instruction } from "../../src/session/instruction"
|
||||
import { Instruction } from "../../src/session"
|
||||
import { ReadTool } from "../../src/tool/read"
|
||||
import { Truncate } from "../../src/tool/truncate"
|
||||
import { Tool } from "../../src/tool/tool"
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import { Config } from "../../src/config"
|
|||
import * as CrossSpawnSpawner from "../../src/effect/cross-spawn-spawner"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { Session } from "../../src/session"
|
||||
import { MessageV2 } from "../../src/session/message-v2"
|
||||
import type { SessionPrompt } from "../../src/session/prompt"
|
||||
import { MessageV2 } from "../../src/session"
|
||||
import type { SessionPrompt } from "../../src/session"
|
||||
import { MessageID, PartID } from "../../src/session/schema"
|
||||
import { ModelID, ProviderID } from "../../src/provider/schema"
|
||||
import { TaskTool, type TaskPromptOps } from "../../src/tool/task"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue