feat(id): brand WorkspaceID through Drizzle and Zod schemas (#16964)
This commit is contained in:
@@ -12,6 +12,7 @@ const seed = async () => {
|
|||||||
const { InstanceBootstrap } = await import("../src/project/bootstrap")
|
const { InstanceBootstrap } = await import("../src/project/bootstrap")
|
||||||
const { Session } = await import("../src/session")
|
const { Session } = await import("../src/session")
|
||||||
const { Identifier } = await import("../src/id/id")
|
const { Identifier } = await import("../src/id/id")
|
||||||
|
const { MessageID } = await import("../src/session/schema")
|
||||||
const { Project } = await import("../src/project/project")
|
const { Project } = await import("../src/project/project")
|
||||||
|
|
||||||
await Instance.provide({
|
await Instance.provide({
|
||||||
@@ -19,7 +20,7 @@ const seed = async () => {
|
|||||||
init: InstanceBootstrap,
|
init: InstanceBootstrap,
|
||||||
fn: async () => {
|
fn: async () => {
|
||||||
const session = await Session.create({ title })
|
const session = await Session.create({ title })
|
||||||
const messageID = Identifier.descending("message")
|
const messageID = MessageID.ascending()
|
||||||
const partID = Identifier.descending("part")
|
const partID = Identifier.descending("part")
|
||||||
const message = {
|
const message = {
|
||||||
id: messageID,
|
id: messageID,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { Provider } from "../../../provider/provider"
|
|||||||
import { Session } from "../../../session"
|
import { Session } from "../../../session"
|
||||||
import type { MessageV2 } from "../../../session/message-v2"
|
import type { MessageV2 } from "../../../session/message-v2"
|
||||||
import { Identifier } from "../../../id/id"
|
import { Identifier } from "../../../id/id"
|
||||||
|
import { MessageID } from "../../../session/schema"
|
||||||
import { ToolRegistry } from "../../../tool/registry"
|
import { ToolRegistry } from "../../../tool/registry"
|
||||||
import { Instance } from "../../../project/instance"
|
import { Instance } from "../../../project/instance"
|
||||||
import { PermissionNext } from "../../../permission/next"
|
import { PermissionNext } from "../../../permission/next"
|
||||||
@@ -113,7 +114,7 @@ function parseToolParams(input?: string) {
|
|||||||
|
|
||||||
async function createToolContext(agent: Agent.Info) {
|
async function createToolContext(agent: Agent.Info) {
|
||||||
const session = await Session.create({ title: `Debug tool run (${agent.name})` })
|
const session = await Session.create({ title: `Debug tool run (${agent.name})` })
|
||||||
const messageID = Identifier.ascending("message")
|
const messageID = MessageID.ascending()
|
||||||
const model = agent.model ?? (await Provider.defaultModel())
|
const model = agent.model ?? (await Provider.defaultModel())
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
const message: MessageV2.Assistant = {
|
const message: MessageV2.Assistant = {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { bootstrap } from "../bootstrap"
|
|||||||
import { Session } from "../../session"
|
import { Session } from "../../session"
|
||||||
import type { SessionID } from "../../session/schema"
|
import type { SessionID } from "../../session/schema"
|
||||||
import { Identifier } from "../../id/id"
|
import { Identifier } from "../../id/id"
|
||||||
|
import { MessageID } from "../../session/schema"
|
||||||
import { Provider } from "../../provider/provider"
|
import { Provider } from "../../provider/provider"
|
||||||
import { Bus } from "../../bus"
|
import { Bus } from "../../bus"
|
||||||
import { MessageV2 } from "../../session/message-v2"
|
import { MessageV2 } from "../../session/message-v2"
|
||||||
@@ -935,7 +936,7 @@ export const GithubRunCommand = cmd({
|
|||||||
|
|
||||||
const result = await SessionPrompt.prompt({
|
const result = await SessionPrompt.prompt({
|
||||||
sessionID: session.id,
|
sessionID: session.id,
|
||||||
messageID: Identifier.ascending("message"),
|
messageID: MessageID.ascending(),
|
||||||
variant,
|
variant,
|
||||||
model: {
|
model: {
|
||||||
providerID,
|
providerID,
|
||||||
@@ -989,7 +990,7 @@ export const GithubRunCommand = cmd({
|
|||||||
console.log("Requesting summary from agent...")
|
console.log("Requesting summary from agent...")
|
||||||
const summary = await SessionPrompt.prompt({
|
const summary = await SessionPrompt.prompt({
|
||||||
sessionID: session.id,
|
sessionID: session.id,
|
||||||
messageID: Identifier.ascending("message"),
|
messageID: MessageID.ascending(),
|
||||||
variant,
|
variant,
|
||||||
model: {
|
model: {
|
||||||
providerID,
|
providerID,
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import type { Argv } from "yargs"
|
import type { Argv } from "yargs"
|
||||||
import type { Session as SDKSession, Message, Part } from "@opencode-ai/sdk/v2"
|
import type { Session as SDKSession, Message, Part } from "@opencode-ai/sdk/v2"
|
||||||
import { Session } from "../../session"
|
import { Session } from "../../session"
|
||||||
import { SessionID } from "../../session/schema"
|
import { SessionID, MessageID } from "../../session/schema"
|
||||||
|
import { WorkspaceID } from "../../control-plane/schema"
|
||||||
import { cmd } from "./cmd"
|
import { cmd } from "./cmd"
|
||||||
import { bootstrap } from "../bootstrap"
|
import { bootstrap } from "../bootstrap"
|
||||||
import { Database } from "../../storage/db"
|
import { Database } from "../../storage/db"
|
||||||
@@ -157,7 +158,11 @@ export const ImportCommand = cmd({
|
|||||||
...exportData.info,
|
...exportData.info,
|
||||||
id: SessionID.make(exportData.info.id),
|
id: SessionID.make(exportData.info.id),
|
||||||
parentID: exportData.info.parentID ? SessionID.make(exportData.info.parentID) : undefined,
|
parentID: exportData.info.parentID ? SessionID.make(exportData.info.parentID) : undefined,
|
||||||
|
workspaceID: exportData.info.workspaceID ? WorkspaceID.make(exportData.info.workspaceID) : undefined,
|
||||||
projectID: Instance.project.id,
|
projectID: Instance.project.id,
|
||||||
|
revert: exportData.info.revert
|
||||||
|
? { ...exportData.info.revert, messageID: MessageID.make(exportData.info.revert.messageID) }
|
||||||
|
: undefined,
|
||||||
})
|
})
|
||||||
Database.use((db) =>
|
Database.use((db) =>
|
||||||
db
|
db
|
||||||
@@ -168,28 +173,30 @@ export const ImportCommand = cmd({
|
|||||||
)
|
)
|
||||||
|
|
||||||
for (const msg of exportData.messages) {
|
for (const msg of exportData.messages) {
|
||||||
|
const { id: _mid, sessionID: _msid, ...msgData } = msg.info
|
||||||
Database.use((db) =>
|
Database.use((db) =>
|
||||||
db
|
db
|
||||||
.insert(MessageTable)
|
.insert(MessageTable)
|
||||||
.values({
|
.values({
|
||||||
id: msg.info.id,
|
id: MessageID.make(msg.info.id),
|
||||||
session_id: row.id,
|
session_id: row.id,
|
||||||
time_created: msg.info.time?.created ?? Date.now(),
|
time_created: msg.info.time?.created ?? Date.now(),
|
||||||
data: msg.info,
|
data: msgData,
|
||||||
})
|
})
|
||||||
.onConflictDoNothing()
|
.onConflictDoNothing()
|
||||||
.run(),
|
.run(),
|
||||||
)
|
)
|
||||||
|
|
||||||
for (const part of msg.parts) {
|
for (const part of msg.parts) {
|
||||||
|
const { id: _pid, sessionID: _psid, messageID: _pmid, ...partData } = part
|
||||||
Database.use((db) =>
|
Database.use((db) =>
|
||||||
db
|
db
|
||||||
.insert(PartTable)
|
.insert(PartTable)
|
||||||
.values({
|
.values({
|
||||||
id: part.id,
|
id: part.id,
|
||||||
message_id: msg.info.id,
|
message_id: MessageID.make(msg.info.id),
|
||||||
session_id: row.id,
|
session_id: row.id,
|
||||||
data: part,
|
data: partData,
|
||||||
})
|
})
|
||||||
.onConflictDoNothing()
|
.onConflictDoNothing()
|
||||||
.run(),
|
.run(),
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { useSDK } from "@tui/context/sdk"
|
|||||||
import { useRoute } from "@tui/context/route"
|
import { useRoute } from "@tui/context/route"
|
||||||
import { useSync } from "@tui/context/sync"
|
import { useSync } from "@tui/context/sync"
|
||||||
import { Identifier } from "@/id/id"
|
import { Identifier } from "@/id/id"
|
||||||
|
import { MessageID } from "@/session/schema"
|
||||||
import { createStore, produce } from "solid-js/store"
|
import { createStore, produce } from "solid-js/store"
|
||||||
import { useKeybind } from "@tui/context/keybind"
|
import { useKeybind } from "@tui/context/keybind"
|
||||||
import { usePromptHistory, type PromptInfo } from "./history"
|
import { usePromptHistory, type PromptInfo } from "./history"
|
||||||
@@ -561,7 +562,7 @@ export function Prompt(props: PromptProps) {
|
|||||||
sessionID = res.data.id
|
sessionID = res.data.id
|
||||||
}
|
}
|
||||||
|
|
||||||
const messageID = Identifier.ascending("message")
|
const messageID = MessageID.ascending()
|
||||||
let inputText = store.prompt.input
|
let inputText = store.prompt.input
|
||||||
|
|
||||||
// Expand pasted text inline before submitting
|
// Expand pasted text inline before submitting
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { BusEvent } from "@/bus/bus-event"
|
import { BusEvent } from "@/bus/bus-event"
|
||||||
import { SessionID } from "@/session/schema"
|
import { SessionID, MessageID } from "@/session/schema"
|
||||||
import z from "zod"
|
import z from "zod"
|
||||||
import { Config } from "../config/config"
|
import { Config } from "../config/config"
|
||||||
import { Instance } from "../project/instance"
|
import { Instance } from "../project/instance"
|
||||||
@@ -17,7 +17,7 @@ export namespace Command {
|
|||||||
name: z.string(),
|
name: z.string(),
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
arguments: z.string(),
|
arguments: z.string(),
|
||||||
messageID: Identifier.schema("message"),
|
messageID: MessageID.zod,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { Schema } from "effect"
|
||||||
|
import z from "zod"
|
||||||
|
|
||||||
|
import { withStatics } from "@/util/schema"
|
||||||
|
import { Identifier } from "@/id/id"
|
||||||
|
|
||||||
|
const workspaceIdSchema = Schema.String.pipe(Schema.brand("WorkspaceId"))
|
||||||
|
|
||||||
|
export type WorkspaceID = typeof workspaceIdSchema.Type
|
||||||
|
|
||||||
|
export const WorkspaceID = workspaceIdSchema.pipe(
|
||||||
|
withStatics((schema: typeof workspaceIdSchema) => ({
|
||||||
|
make: (id: string) => schema.makeUnsafe(id),
|
||||||
|
ascending: (id?: string) => schema.makeUnsafe(Identifier.ascending("workspace", id)),
|
||||||
|
zod: z.string().startsWith("wrk").pipe(z.custom<WorkspaceID>()),
|
||||||
|
})),
|
||||||
|
)
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import z from "zod"
|
import z from "zod"
|
||||||
import { Identifier } from "@/id/id"
|
|
||||||
import { ProjectID } from "@/project/schema"
|
import { ProjectID } from "@/project/schema"
|
||||||
|
import { WorkspaceID } from "./schema"
|
||||||
|
|
||||||
export const WorkspaceInfo = z.object({
|
export const WorkspaceInfo = z.object({
|
||||||
id: Identifier.schema("workspace"),
|
id: WorkspaceID.zod,
|
||||||
type: z.string(),
|
type: z.string(),
|
||||||
branch: z.string().nullable(),
|
branch: z.string().nullable(),
|
||||||
name: z.string().nullable(),
|
name: z.string().nullable(),
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import { Context } from "../util/context"
|
import { Context } from "../util/context"
|
||||||
|
import type { WorkspaceID } from "./schema"
|
||||||
|
|
||||||
interface Context {
|
interface Context {
|
||||||
workspaceID?: string
|
workspaceID?: WorkspaceID
|
||||||
}
|
}
|
||||||
|
|
||||||
const context = Context.create<Context>("workspace")
|
const context = Context.create<Context>("workspace")
|
||||||
|
|
||||||
export const WorkspaceContext = {
|
export const WorkspaceContext = {
|
||||||
async provide<R>(input: { workspaceID?: string; fn: () => R }): Promise<R> {
|
async provide<R>(input: { workspaceID?: WorkspaceID; fn: () => R }): Promise<R> {
|
||||||
return context.provide({ workspaceID: input.workspaceID }, async () => {
|
return context.provide({ workspaceID: input.workspaceID }, async () => {
|
||||||
return input.fn()
|
return input.fn()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { InstanceBootstrap } from "../../project/bootstrap"
|
|||||||
import { SessionRoutes } from "../../server/routes/session"
|
import { SessionRoutes } from "../../server/routes/session"
|
||||||
import { WorkspaceServerRoutes } from "./routes"
|
import { WorkspaceServerRoutes } from "./routes"
|
||||||
import { WorkspaceContext } from "../workspace-context"
|
import { WorkspaceContext } from "../workspace-context"
|
||||||
|
import { WorkspaceID } from "../schema"
|
||||||
|
|
||||||
export namespace WorkspaceServer {
|
export namespace WorkspaceServer {
|
||||||
export function App() {
|
export function App() {
|
||||||
@@ -20,9 +21,9 @@ export namespace WorkspaceServer {
|
|||||||
|
|
||||||
return new Hono()
|
return new Hono()
|
||||||
.use(async (c, next) => {
|
.use(async (c, next) => {
|
||||||
const workspaceID = c.req.query("workspace") || c.req.header("x-opencode-workspace")
|
const rawWorkspaceID = c.req.query("workspace") || c.req.header("x-opencode-workspace")
|
||||||
const raw = c.req.query("directory") || c.req.header("x-opencode-directory")
|
const raw = c.req.query("directory") || c.req.header("x-opencode-directory")
|
||||||
if (workspaceID == null) {
|
if (rawWorkspaceID == null) {
|
||||||
throw new Error("workspaceID parameter is required")
|
throw new Error("workspaceID parameter is required")
|
||||||
}
|
}
|
||||||
if (raw == null) {
|
if (raw == null) {
|
||||||
@@ -38,7 +39,7 @@ export namespace WorkspaceServer {
|
|||||||
})()
|
})()
|
||||||
|
|
||||||
return WorkspaceContext.provide({
|
return WorkspaceContext.provide({
|
||||||
workspaceID,
|
workspaceID: WorkspaceID.make(rawWorkspaceID),
|
||||||
async fn() {
|
async fn() {
|
||||||
return Instance.provide({
|
return Instance.provide({
|
||||||
directory,
|
directory,
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { sqliteTable, text } from "drizzle-orm/sqlite-core"
|
import { sqliteTable, text } from "drizzle-orm/sqlite-core"
|
||||||
import { ProjectTable } from "../project/project.sql"
|
import { ProjectTable } from "../project/project.sql"
|
||||||
import type { ProjectID } from "../project/schema"
|
import type { ProjectID } from "../project/schema"
|
||||||
|
import type { WorkspaceID } from "./schema"
|
||||||
|
|
||||||
export const WorkspaceTable = sqliteTable("workspace", {
|
export const WorkspaceTable = sqliteTable("workspace", {
|
||||||
id: text().primaryKey(),
|
id: text().$type<WorkspaceID>().primaryKey(),
|
||||||
type: text().notNull(),
|
type: text().notNull(),
|
||||||
branch: text(),
|
branch: text(),
|
||||||
name: text(),
|
name: text(),
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import z from "zod"
|
import z from "zod"
|
||||||
import { Identifier } from "@/id/id"
|
|
||||||
import { fn } from "@/util/fn"
|
import { fn } from "@/util/fn"
|
||||||
import { Database, eq } from "@/storage/db"
|
import { Database, eq } from "@/storage/db"
|
||||||
import { Project } from "@/project/project"
|
import { Project } from "@/project/project"
|
||||||
@@ -10,6 +9,7 @@ import { ProjectID } from "@/project/schema"
|
|||||||
import { WorkspaceTable } from "./workspace.sql"
|
import { WorkspaceTable } from "./workspace.sql"
|
||||||
import { getAdaptor } from "./adaptors"
|
import { getAdaptor } from "./adaptors"
|
||||||
import { WorkspaceInfo } from "./types"
|
import { WorkspaceInfo } from "./types"
|
||||||
|
import { WorkspaceID } from "./schema"
|
||||||
import { parseSSE } from "./sse"
|
import { parseSSE } from "./sse"
|
||||||
|
|
||||||
export namespace Workspace {
|
export namespace Workspace {
|
||||||
@@ -46,7 +46,7 @@ export namespace Workspace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const CreateInput = z.object({
|
const CreateInput = z.object({
|
||||||
id: Identifier.schema("workspace").optional(),
|
id: WorkspaceID.zod.optional(),
|
||||||
type: Info.shape.type,
|
type: Info.shape.type,
|
||||||
branch: Info.shape.branch,
|
branch: Info.shape.branch,
|
||||||
projectID: ProjectID.zod,
|
projectID: ProjectID.zod,
|
||||||
@@ -54,7 +54,7 @@ export namespace Workspace {
|
|||||||
})
|
})
|
||||||
|
|
||||||
export const create = fn(CreateInput, async (input) => {
|
export const create = fn(CreateInput, async (input) => {
|
||||||
const id = Identifier.ascending("workspace", input.id)
|
const id = WorkspaceID.ascending(input.id)
|
||||||
const adaptor = await getAdaptor(input.type)
|
const adaptor = await getAdaptor(input.type)
|
||||||
|
|
||||||
const config = await adaptor.configure({ ...input, id, name: null, directory: null })
|
const config = await adaptor.configure({ ...input, id, name: null, directory: null })
|
||||||
@@ -94,13 +94,13 @@ export namespace Workspace {
|
|||||||
return rows.map(fromRow).sort((a, b) => a.id.localeCompare(b.id))
|
return rows.map(fromRow).sort((a, b) => a.id.localeCompare(b.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const get = fn(Identifier.schema("workspace"), async (id) => {
|
export const get = fn(WorkspaceID.zod, async (id) => {
|
||||||
const row = Database.use((db) => db.select().from(WorkspaceTable).where(eq(WorkspaceTable.id, id)).get())
|
const row = Database.use((db) => db.select().from(WorkspaceTable).where(eq(WorkspaceTable.id, id)).get())
|
||||||
if (!row) return
|
if (!row) return
|
||||||
return fromRow(row)
|
return fromRow(row)
|
||||||
})
|
})
|
||||||
|
|
||||||
export const remove = fn(Identifier.schema("workspace"), async (id) => {
|
export const remove = fn(WorkspaceID.zod, async (id) => {
|
||||||
const row = Database.use((db) => db.select().from(WorkspaceTable).where(eq(WorkspaceTable.id, id)).get())
|
const row = Database.use((db) => db.select().from(WorkspaceTable).where(eq(WorkspaceTable.id, id)).get())
|
||||||
if (row) {
|
if (row) {
|
||||||
const info = fromRow(row)
|
const info = fromRow(row)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { BusEvent } from "@/bus/bus-event"
|
import { BusEvent } from "@/bus/bus-event"
|
||||||
import { Bus } from "@/bus"
|
import { Bus } from "@/bus"
|
||||||
import { SessionID } from "@/session/schema"
|
import { SessionID, MessageID } from "@/session/schema"
|
||||||
import z from "zod"
|
import z from "zod"
|
||||||
import { Log } from "../util/log"
|
import { Log } from "../util/log"
|
||||||
import { Identifier } from "../id/id"
|
import { Identifier } from "../id/id"
|
||||||
@@ -26,7 +26,7 @@ export namespace Permission {
|
|||||||
type: z.string(),
|
type: z.string(),
|
||||||
pattern: z.union([z.string(), z.array(z.string())]).optional(),
|
pattern: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: z.string(),
|
messageID: MessageID.zod,
|
||||||
callID: z.string().optional(),
|
callID: z.string().optional(),
|
||||||
message: z.string(),
|
message: z.string(),
|
||||||
metadata: z.record(z.string(), z.any()),
|
metadata: z.record(z.string(), z.any()),
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Bus } from "@/bus"
|
|||||||
import { BusEvent } from "@/bus/bus-event"
|
import { BusEvent } from "@/bus/bus-event"
|
||||||
import { Config } from "@/config/config"
|
import { Config } from "@/config/config"
|
||||||
import { Identifier } from "@/id/id"
|
import { Identifier } from "@/id/id"
|
||||||
import { SessionID } from "@/session/schema"
|
import { SessionID, MessageID } from "@/session/schema"
|
||||||
import { Instance } from "@/project/instance"
|
import { Instance } from "@/project/instance"
|
||||||
import { Database, eq } from "@/storage/db"
|
import { Database, eq } from "@/storage/db"
|
||||||
import { PermissionTable } from "@/session/session.sql"
|
import { PermissionTable } from "@/session/session.sql"
|
||||||
@@ -77,7 +77,7 @@ export namespace PermissionNext {
|
|||||||
always: z.string().array(),
|
always: z.string().array(),
|
||||||
tool: z
|
tool: z
|
||||||
.object({
|
.object({
|
||||||
messageID: z.string(),
|
messageID: MessageID.zod,
|
||||||
callID: z.string(),
|
callID: z.string(),
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Bus } from "@/bus"
|
import { Bus } from "@/bus"
|
||||||
import { BusEvent } from "@/bus/bus-event"
|
import { BusEvent } from "@/bus/bus-event"
|
||||||
import { Identifier } from "@/id/id"
|
import { Identifier } from "@/id/id"
|
||||||
import { SessionID } from "@/session/schema"
|
import { SessionID, MessageID } from "@/session/schema"
|
||||||
import { Instance } from "@/project/instance"
|
import { Instance } from "@/project/instance"
|
||||||
import { Log } from "@/util/log"
|
import { Log } from "@/util/log"
|
||||||
import z from "zod"
|
import z from "zod"
|
||||||
@@ -39,7 +39,7 @@ export namespace Question {
|
|||||||
questions: z.array(Info).describe("Questions to ask"),
|
questions: z.array(Info).describe("Questions to ask"),
|
||||||
tool: z
|
tool: z
|
||||||
.object({
|
.object({
|
||||||
messageID: z.string(),
|
messageID: MessageID.zod,
|
||||||
callID: z.string(),
|
callID: z.string(),
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
@@ -98,7 +98,7 @@ export namespace Question {
|
|||||||
export async function ask(input: {
|
export async function ask(input: {
|
||||||
sessionID: SessionID
|
sessionID: SessionID
|
||||||
questions: Info[]
|
questions: Info[]
|
||||||
tool?: { messageID: string; callID: string }
|
tool?: { messageID: MessageID; callID: string }
|
||||||
}): Promise<Answer[]> {
|
}): Promise<Answer[]> {
|
||||||
const s = await state()
|
const s = await state()
|
||||||
const id = Identifier.ascending("question")
|
const id = Identifier.ascending("question")
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Hono } from "hono"
|
import { Hono } from "hono"
|
||||||
import { stream } from "hono/streaming"
|
import { stream } from "hono/streaming"
|
||||||
import { describeRoute, validator, resolver } from "hono-openapi"
|
import { describeRoute, validator, resolver } from "hono-openapi"
|
||||||
import { SessionID } from "@/session/schema"
|
import { SessionID, MessageID } from "@/session/schema"
|
||||||
import z from "zod"
|
import z from "zod"
|
||||||
import { Session } from "../../session"
|
import { Session } from "../../session"
|
||||||
import { MessageV2 } from "../../session/message-v2"
|
import { MessageV2 } from "../../session/message-v2"
|
||||||
@@ -607,7 +607,7 @@ export const SessionRoutes = lazy(() =>
|
|||||||
"param",
|
"param",
|
||||||
z.object({
|
z.object({
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: z.string().meta({ description: "Message ID" }),
|
messageID: MessageID.zod,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
@@ -642,7 +642,7 @@ export const SessionRoutes = lazy(() =>
|
|||||||
"param",
|
"param",
|
||||||
z.object({
|
z.object({
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: z.string().meta({ description: "Message ID" }),
|
messageID: MessageID.zod,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
@@ -676,8 +676,8 @@ export const SessionRoutes = lazy(() =>
|
|||||||
"param",
|
"param",
|
||||||
z.object({
|
z.object({
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: z.string().meta({ description: "Message ID" }),
|
messageID: MessageID.zod,
|
||||||
partID: z.string().meta({ description: "Part ID" }),
|
partID: z.string(),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
@@ -711,8 +711,8 @@ export const SessionRoutes = lazy(() =>
|
|||||||
"param",
|
"param",
|
||||||
z.object({
|
z.object({
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: z.string().meta({ description: "Message ID" }),
|
messageID: MessageID.zod,
|
||||||
partID: z.string().meta({ description: "Part ID" }),
|
partID: z.string(),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
validator("json", MessageV2.Part),
|
validator("json", MessageV2.Part),
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { Flag } from "../flag/flag"
|
|||||||
import { Command } from "../command"
|
import { Command } from "../command"
|
||||||
import { Global } from "../global"
|
import { Global } from "../global"
|
||||||
import { WorkspaceContext } from "../control-plane/workspace-context"
|
import { WorkspaceContext } from "../control-plane/workspace-context"
|
||||||
|
import { WorkspaceID } from "../control-plane/schema"
|
||||||
import { WorkspaceRouterMiddleware } from "../control-plane/workspace-router-middleware"
|
import { WorkspaceRouterMiddleware } from "../control-plane/workspace-router-middleware"
|
||||||
import { ProjectRoutes } from "./routes/project"
|
import { ProjectRoutes } from "./routes/project"
|
||||||
import { SessionRoutes } from "./routes/session"
|
import { SessionRoutes } from "./routes/session"
|
||||||
@@ -190,7 +191,7 @@ export namespace Server {
|
|||||||
)
|
)
|
||||||
.use(async (c, next) => {
|
.use(async (c, next) => {
|
||||||
if (c.req.path === "/log") return next()
|
if (c.req.path === "/log") return next()
|
||||||
const workspaceID = c.req.query("workspace") || c.req.header("x-opencode-workspace")
|
const rawWorkspaceID = c.req.query("workspace") || c.req.header("x-opencode-workspace")
|
||||||
const raw = c.req.query("directory") || c.req.header("x-opencode-directory") || process.cwd()
|
const raw = c.req.query("directory") || c.req.header("x-opencode-directory") || process.cwd()
|
||||||
const directory = Filesystem.resolve(
|
const directory = Filesystem.resolve(
|
||||||
(() => {
|
(() => {
|
||||||
@@ -203,7 +204,7 @@ export namespace Server {
|
|||||||
)
|
)
|
||||||
|
|
||||||
return WorkspaceContext.provide({
|
return WorkspaceContext.provide({
|
||||||
workspaceID,
|
workspaceID: rawWorkspaceID ? WorkspaceID.make(rawWorkspaceID) : undefined,
|
||||||
async fn() {
|
async fn() {
|
||||||
return Instance.provide({
|
return Instance.provide({
|
||||||
directory,
|
directory,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { BusEvent } from "@/bus/bus-event"
|
|||||||
import { Bus } from "@/bus"
|
import { Bus } from "@/bus"
|
||||||
import { Session } from "."
|
import { Session } from "."
|
||||||
import { Identifier } from "../id/id"
|
import { Identifier } from "../id/id"
|
||||||
import { SessionID } from "./schema"
|
import { SessionID, MessageID } from "./schema"
|
||||||
import { Instance } from "../project/instance"
|
import { Instance } from "../project/instance"
|
||||||
import { Provider } from "../provider/provider"
|
import { Provider } from "../provider/provider"
|
||||||
import { MessageV2 } from "./message-v2"
|
import { MessageV2 } from "./message-v2"
|
||||||
@@ -100,7 +100,7 @@ export namespace SessionCompaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function process(input: {
|
export async function process(input: {
|
||||||
parentID: string
|
parentID: MessageID
|
||||||
messages: MessageV2.WithParts[]
|
messages: MessageV2.WithParts[]
|
||||||
sessionID: SessionID
|
sessionID: SessionID
|
||||||
abort: AbortSignal
|
abort: AbortSignal
|
||||||
@@ -134,7 +134,7 @@ export namespace SessionCompaction {
|
|||||||
? await Provider.getModel(agent.model.providerID, agent.model.modelID)
|
? await Provider.getModel(agent.model.providerID, agent.model.modelID)
|
||||||
: await Provider.getModel(userMessage.model.providerID, userMessage.model.modelID)
|
: await Provider.getModel(userMessage.model.providerID, userMessage.model.modelID)
|
||||||
const msg = (await Session.updateMessage({
|
const msg = (await Session.updateMessage({
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
role: "assistant",
|
role: "assistant",
|
||||||
parentID: input.parentID,
|
parentID: input.parentID,
|
||||||
sessionID: input.sessionID,
|
sessionID: input.sessionID,
|
||||||
@@ -237,7 +237,7 @@ When constructing the summary, try to stick to this template:
|
|||||||
if (replay) {
|
if (replay) {
|
||||||
const original = replay.info as MessageV2.User
|
const original = replay.info as MessageV2.User
|
||||||
const replayMsg = await Session.updateMessage({
|
const replayMsg = await Session.updateMessage({
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
role: "user",
|
role: "user",
|
||||||
sessionID: input.sessionID,
|
sessionID: input.sessionID,
|
||||||
time: { created: Date.now() },
|
time: { created: Date.now() },
|
||||||
@@ -263,7 +263,7 @@ When constructing the summary, try to stick to this template:
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const continueMsg = await Session.updateMessage({
|
const continueMsg = await Session.updateMessage({
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
role: "user",
|
role: "user",
|
||||||
sessionID: input.sessionID,
|
sessionID: input.sessionID,
|
||||||
time: { created: Date.now() },
|
time: { created: Date.now() },
|
||||||
@@ -307,7 +307,7 @@ When constructing the summary, try to stick to this template:
|
|||||||
}),
|
}),
|
||||||
async (input) => {
|
async (input) => {
|
||||||
const msg = await Session.updateMessage({
|
const msg = await Session.updateMessage({
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
role: "user",
|
role: "user",
|
||||||
model: input.model,
|
model: input.model,
|
||||||
sessionID: input.sessionID,
|
sessionID: input.sessionID,
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ import { Command } from "../command"
|
|||||||
import { Snapshot } from "@/snapshot"
|
import { Snapshot } from "@/snapshot"
|
||||||
import { WorkspaceContext } from "../control-plane/workspace-context"
|
import { WorkspaceContext } from "../control-plane/workspace-context"
|
||||||
import { ProjectID } from "../project/schema"
|
import { ProjectID } from "../project/schema"
|
||||||
import { SessionID } from "./schema"
|
import { WorkspaceID } from "../control-plane/schema"
|
||||||
|
import { SessionID, MessageID } from "./schema"
|
||||||
|
|
||||||
import type { Provider } from "@/provider/provider"
|
import type { Provider } from "@/provider/provider"
|
||||||
import { PermissionNext } from "@/permission/next"
|
import { PermissionNext } from "@/permission/next"
|
||||||
@@ -123,7 +124,7 @@ export namespace Session {
|
|||||||
id: SessionID.zod,
|
id: SessionID.zod,
|
||||||
slug: z.string(),
|
slug: z.string(),
|
||||||
projectID: ProjectID.zod,
|
projectID: ProjectID.zod,
|
||||||
workspaceID: z.string().optional(),
|
workspaceID: WorkspaceID.zod.optional(),
|
||||||
directory: z.string(),
|
directory: z.string(),
|
||||||
parentID: SessionID.zod.optional(),
|
parentID: SessionID.zod.optional(),
|
||||||
summary: z
|
summary: z
|
||||||
@@ -150,7 +151,7 @@ export namespace Session {
|
|||||||
permission: PermissionNext.Ruleset.optional(),
|
permission: PermissionNext.Ruleset.optional(),
|
||||||
revert: z
|
revert: z
|
||||||
.object({
|
.object({
|
||||||
messageID: z.string(),
|
messageID: MessageID.zod,
|
||||||
partID: z.string().optional(),
|
partID: z.string().optional(),
|
||||||
snapshot: z.string().optional(),
|
snapshot: z.string().optional(),
|
||||||
diff: z.string().optional(),
|
diff: z.string().optional(),
|
||||||
@@ -221,7 +222,7 @@ export namespace Session {
|
|||||||
parentID: SessionID.zod.optional(),
|
parentID: SessionID.zod.optional(),
|
||||||
title: z.string().optional(),
|
title: z.string().optional(),
|
||||||
permission: Info.shape.permission,
|
permission: Info.shape.permission,
|
||||||
workspaceID: Identifier.schema("workspace").optional(),
|
workspaceID: WorkspaceID.zod.optional(),
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
async (input) => {
|
async (input) => {
|
||||||
@@ -238,7 +239,7 @@ export namespace Session {
|
|||||||
export const fork = fn(
|
export const fork = fn(
|
||||||
z.object({
|
z.object({
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: Identifier.schema("message").optional(),
|
messageID: MessageID.zod.optional(),
|
||||||
}),
|
}),
|
||||||
async (input) => {
|
async (input) => {
|
||||||
const original = await get(input.sessionID)
|
const original = await get(input.sessionID)
|
||||||
@@ -250,11 +251,11 @@ export namespace Session {
|
|||||||
title,
|
title,
|
||||||
})
|
})
|
||||||
const msgs = await messages({ sessionID: input.sessionID })
|
const msgs = await messages({ sessionID: input.sessionID })
|
||||||
const idMap = new Map<string, string>()
|
const idMap = new Map<string, MessageID>()
|
||||||
|
|
||||||
for (const msg of msgs) {
|
for (const msg of msgs) {
|
||||||
if (input.messageID && msg.info.id >= input.messageID) break
|
if (input.messageID && msg.info.id >= input.messageID) break
|
||||||
const newID = Identifier.ascending("message")
|
const newID = MessageID.ascending()
|
||||||
idMap.set(msg.info.id, newID)
|
idMap.set(msg.info.id, newID)
|
||||||
|
|
||||||
const parentID = msg.info.role === "assistant" && msg.info.parentID ? idMap.get(msg.info.parentID) : undefined
|
const parentID = msg.info.role === "assistant" && msg.info.parentID ? idMap.get(msg.info.parentID) : undefined
|
||||||
@@ -297,7 +298,7 @@ export namespace Session {
|
|||||||
id?: SessionID
|
id?: SessionID
|
||||||
title?: string
|
title?: string
|
||||||
parentID?: SessionID
|
parentID?: SessionID
|
||||||
workspaceID?: string
|
workspaceID?: WorkspaceID
|
||||||
directory: string
|
directory: string
|
||||||
permission?: PermissionNext.Ruleset
|
permission?: PermissionNext.Ruleset
|
||||||
}) {
|
}) {
|
||||||
@@ -538,7 +539,7 @@ export namespace Session {
|
|||||||
|
|
||||||
export function* list(input?: {
|
export function* list(input?: {
|
||||||
directory?: string
|
directory?: string
|
||||||
workspaceID?: string
|
workspaceID?: WorkspaceID
|
||||||
roots?: boolean
|
roots?: boolean
|
||||||
start?: number
|
start?: number
|
||||||
search?: string
|
search?: string
|
||||||
@@ -707,7 +708,7 @@ export namespace Session {
|
|||||||
export const removeMessage = fn(
|
export const removeMessage = fn(
|
||||||
z.object({
|
z.object({
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: Identifier.schema("message"),
|
messageID: MessageID.zod,
|
||||||
}),
|
}),
|
||||||
async (input) => {
|
async (input) => {
|
||||||
// CASCADE delete handles parts automatically
|
// CASCADE delete handles parts automatically
|
||||||
@@ -729,7 +730,7 @@ export namespace Session {
|
|||||||
export const removePart = fn(
|
export const removePart = fn(
|
||||||
z.object({
|
z.object({
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: Identifier.schema("message"),
|
messageID: MessageID.zod,
|
||||||
partID: Identifier.schema("part"),
|
partID: Identifier.schema("part"),
|
||||||
}),
|
}),
|
||||||
async (input) => {
|
async (input) => {
|
||||||
@@ -777,7 +778,7 @@ export namespace Session {
|
|||||||
export const updatePartDelta = fn(
|
export const updatePartDelta = fn(
|
||||||
z.object({
|
z.object({
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: z.string(),
|
messageID: MessageID.zod,
|
||||||
partID: z.string(),
|
partID: z.string(),
|
||||||
field: z.string(),
|
field: z.string(),
|
||||||
delta: z.string(),
|
delta: z.string(),
|
||||||
@@ -877,7 +878,7 @@ export namespace Session {
|
|||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
modelID: z.string(),
|
modelID: z.string(),
|
||||||
providerID: z.string(),
|
providerID: z.string(),
|
||||||
messageID: Identifier.schema("message"),
|
messageID: MessageID.zod,
|
||||||
}),
|
}),
|
||||||
async (input) => {
|
async (input) => {
|
||||||
await SessionPrompt.command({
|
await SessionPrompt.command({
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { BusEvent } from "@/bus/bus-event"
|
import { BusEvent } from "@/bus/bus-event"
|
||||||
import { SessionID } from "./schema"
|
import { SessionID, MessageID } from "./schema"
|
||||||
import z from "zod"
|
import z from "zod"
|
||||||
import { NamedError } from "@opencode-ai/util/error"
|
import { NamedError } from "@opencode-ai/util/error"
|
||||||
import { APICallError, convertToModelMessages, LoadAPIKeyError, type ModelMessage, type UIMessage } from "ai"
|
import { APICallError, convertToModelMessages, LoadAPIKeyError, type ModelMessage, type UIMessage } from "ai"
|
||||||
import { Identifier } from "../id/id"
|
|
||||||
import { LSP } from "../lsp"
|
import { LSP } from "../lsp"
|
||||||
import { Snapshot } from "@/snapshot"
|
import { Snapshot } from "@/snapshot"
|
||||||
import { fn } from "@/util/fn"
|
import { fn } from "@/util/fn"
|
||||||
@@ -81,7 +80,7 @@ export namespace MessageV2 {
|
|||||||
const PartBase = z.object({
|
const PartBase = z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: z.string(),
|
messageID: MessageID.zod,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const SnapshotPart = PartBase.extend({
|
export const SnapshotPart = PartBase.extend({
|
||||||
@@ -344,7 +343,7 @@ export namespace MessageV2 {
|
|||||||
export type ToolPart = z.infer<typeof ToolPart>
|
export type ToolPart = z.infer<typeof ToolPart>
|
||||||
|
|
||||||
const Base = z.object({
|
const Base = z.object({
|
||||||
id: z.string(),
|
id: MessageID.zod,
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -411,7 +410,7 @@ export namespace MessageV2 {
|
|||||||
APIError.Schema,
|
APIError.Schema,
|
||||||
])
|
])
|
||||||
.optional(),
|
.optional(),
|
||||||
parentID: z.string(),
|
parentID: MessageID.zod,
|
||||||
modelID: z.string(),
|
modelID: z.string(),
|
||||||
providerID: z.string(),
|
providerID: z.string(),
|
||||||
/**
|
/**
|
||||||
@@ -459,7 +458,7 @@ export namespace MessageV2 {
|
|||||||
"message.removed",
|
"message.removed",
|
||||||
z.object({
|
z.object({
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: z.string(),
|
messageID: MessageID.zod,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
PartUpdated: BusEvent.define(
|
PartUpdated: BusEvent.define(
|
||||||
@@ -472,7 +471,7 @@ export namespace MessageV2 {
|
|||||||
"message.part.delta",
|
"message.part.delta",
|
||||||
z.object({
|
z.object({
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: z.string(),
|
messageID: MessageID.zod,
|
||||||
partID: z.string(),
|
partID: z.string(),
|
||||||
field: z.string(),
|
field: z.string(),
|
||||||
delta: z.string(),
|
delta: z.string(),
|
||||||
@@ -482,7 +481,7 @@ export namespace MessageV2 {
|
|||||||
"message.part.removed",
|
"message.part.removed",
|
||||||
z.object({
|
z.object({
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: z.string(),
|
messageID: MessageID.zod,
|
||||||
partID: z.string(),
|
partID: z.string(),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
@@ -699,7 +698,7 @@ export namespace MessageV2 {
|
|||||||
// media (images, PDFs) in tool results
|
// media (images, PDFs) in tool results
|
||||||
if (media.length > 0) {
|
if (media.length > 0) {
|
||||||
result.push({
|
result.push({
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
role: "user",
|
role: "user",
|
||||||
parts: [
|
parts: [
|
||||||
{
|
{
|
||||||
@@ -782,7 +781,7 @@ export namespace MessageV2 {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export const parts = fn(Identifier.schema("message"), async (message_id) => {
|
export const parts = fn(MessageID.zod, async (message_id) => {
|
||||||
const rows = Database.use((db) =>
|
const rows = Database.use((db) =>
|
||||||
db.select().from(PartTable).where(eq(PartTable.message_id, message_id)).orderBy(PartTable.id).all(),
|
db.select().from(PartTable).where(eq(PartTable.message_id, message_id)).orderBy(PartTable.id).all(),
|
||||||
)
|
)
|
||||||
@@ -794,7 +793,7 @@ export namespace MessageV2 {
|
|||||||
export const get = fn(
|
export const get = fn(
|
||||||
z.object({
|
z.object({
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: Identifier.schema("message"),
|
messageID: MessageID.zod,
|
||||||
}),
|
}),
|
||||||
async (input): Promise<WithParts> => {
|
async (input): Promise<WithParts> => {
|
||||||
const row = Database.use((db) => db.select().from(MessageTable).where(eq(MessageTable.id, input.messageID)).get())
|
const row = Database.use((db) => db.select().from(MessageTable).where(eq(MessageTable.id, input.messageID)).get())
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { Config } from "@/config/config"
|
|||||||
import { SessionCompaction } from "./compaction"
|
import { SessionCompaction } from "./compaction"
|
||||||
import { PermissionNext } from "@/permission/next"
|
import { PermissionNext } from "@/permission/next"
|
||||||
import { Question } from "@/question"
|
import { Question } from "@/question"
|
||||||
import type { SessionID } from "./schema"
|
import type { SessionID, MessageID } from "./schema"
|
||||||
|
|
||||||
export namespace SessionProcessor {
|
export namespace SessionProcessor {
|
||||||
const DOOM_LOOP_THRESHOLD = 3
|
const DOOM_LOOP_THRESHOLD = 3
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import fs from "fs/promises"
|
|||||||
import z from "zod"
|
import z from "zod"
|
||||||
import { Filesystem } from "../util/filesystem"
|
import { Filesystem } from "../util/filesystem"
|
||||||
import { Identifier } from "../id/id"
|
import { Identifier } from "../id/id"
|
||||||
import { SessionID } from "./schema"
|
import { SessionID, MessageID } from "./schema"
|
||||||
import { MessageV2 } from "./message-v2"
|
import { MessageV2 } from "./message-v2"
|
||||||
import { Log } from "../util/log"
|
import { Log } from "../util/log"
|
||||||
import { SessionRevert } from "./revert"
|
import { SessionRevert } from "./revert"
|
||||||
@@ -92,7 +92,7 @@ export namespace SessionPrompt {
|
|||||||
|
|
||||||
export const PromptInput = z.object({
|
export const PromptInput = z.object({
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: Identifier.schema("message").optional(),
|
messageID: MessageID.zod.optional(),
|
||||||
model: z
|
model: z
|
||||||
.object({
|
.object({
|
||||||
providerID: z.string(),
|
providerID: z.string(),
|
||||||
@@ -355,7 +355,7 @@ export namespace SessionPrompt {
|
|||||||
const taskTool = await TaskTool.init()
|
const taskTool = await TaskTool.init()
|
||||||
const taskModel = task.model ? await Provider.getModel(task.model.providerID, task.model.modelID) : model
|
const taskModel = task.model ? await Provider.getModel(task.model.providerID, task.model.modelID) : model
|
||||||
const assistantMessage = (await Session.updateMessage({
|
const assistantMessage = (await Session.updateMessage({
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
role: "assistant",
|
role: "assistant",
|
||||||
parentID: lastUser.id,
|
parentID: lastUser.id,
|
||||||
sessionID,
|
sessionID,
|
||||||
@@ -504,7 +504,7 @@ export namespace SessionPrompt {
|
|||||||
// If we create assistant messages w/ out user ones following mid loop thinking signatures
|
// If we create assistant messages w/ out user ones following mid loop thinking signatures
|
||||||
// will be missing and it can cause errors for models like gemini for example
|
// will be missing and it can cause errors for models like gemini for example
|
||||||
const summaryUserMsg: MessageV2.User = {
|
const summaryUserMsg: MessageV2.User = {
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
sessionID,
|
sessionID,
|
||||||
role: "user",
|
role: "user",
|
||||||
time: {
|
time: {
|
||||||
@@ -568,7 +568,7 @@ export namespace SessionPrompt {
|
|||||||
|
|
||||||
const processor = SessionProcessor.create({
|
const processor = SessionProcessor.create({
|
||||||
assistantMessage: (await Session.updateMessage({
|
assistantMessage: (await Session.updateMessage({
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
parentID: lastUser.id,
|
parentID: lastUser.id,
|
||||||
role: "assistant",
|
role: "assistant",
|
||||||
mode: agent.name,
|
mode: agent.name,
|
||||||
@@ -971,7 +971,7 @@ export namespace SessionPrompt {
|
|||||||
const variant = input.variant ?? (agent.variant && full?.variants?.[agent.variant] ? agent.variant : undefined)
|
const variant = input.variant ?? (agent.variant && full?.variants?.[agent.variant] ? agent.variant : undefined)
|
||||||
|
|
||||||
const info: MessageV2.Info = {
|
const info: MessageV2.Info = {
|
||||||
id: input.messageID ?? Identifier.ascending("message"),
|
id: input.messageID ?? MessageID.ascending(),
|
||||||
role: "user",
|
role: "user",
|
||||||
sessionID: input.sessionID,
|
sessionID: input.sessionID,
|
||||||
time: {
|
time: {
|
||||||
@@ -1505,7 +1505,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
|
|||||||
const agent = await Agent.get(input.agent)
|
const agent = await Agent.get(input.agent)
|
||||||
const model = input.model ?? agent.model ?? (await lastModel(input.sessionID))
|
const model = input.model ?? agent.model ?? (await lastModel(input.sessionID))
|
||||||
const userMsg: MessageV2.User = {
|
const userMsg: MessageV2.User = {
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
sessionID: input.sessionID,
|
sessionID: input.sessionID,
|
||||||
time: {
|
time: {
|
||||||
created: Date.now(),
|
created: Date.now(),
|
||||||
@@ -1529,7 +1529,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
|
|||||||
await Session.updatePart(userPart)
|
await Session.updatePart(userPart)
|
||||||
|
|
||||||
const msg: MessageV2.Assistant = {
|
const msg: MessageV2.Assistant = {
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
sessionID: input.sessionID,
|
sessionID: input.sessionID,
|
||||||
parentID: userMsg.id,
|
parentID: userMsg.id,
|
||||||
mode: input.agent,
|
mode: input.agent,
|
||||||
@@ -1719,7 +1719,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const CommandInput = z.object({
|
export const CommandInput = z.object({
|
||||||
messageID: Identifier.schema("message").optional(),
|
messageID: MessageID.zod.optional(),
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
agent: z.string().optional(),
|
agent: z.string().optional(),
|
||||||
model: z.string().optional(),
|
model: z.string().optional(),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import z from "zod"
|
import z from "zod"
|
||||||
import { Identifier } from "../id/id"
|
import { Identifier } from "../id/id"
|
||||||
import { SessionID } from "./schema"
|
import { SessionID, MessageID } from "./schema"
|
||||||
import { Snapshot } from "../snapshot"
|
import { Snapshot } from "../snapshot"
|
||||||
import { MessageV2 } from "./message-v2"
|
import { MessageV2 } from "./message-v2"
|
||||||
import { Session } from "."
|
import { Session } from "."
|
||||||
@@ -17,7 +17,7 @@ export namespace SessionRevert {
|
|||||||
|
|
||||||
export const RevertInput = z.object({
|
export const RevertInput = z.object({
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: Identifier.schema("message"),
|
messageID: MessageID.zod,
|
||||||
partID: Identifier.schema("part").optional(),
|
partID: Identifier.schema("part").optional(),
|
||||||
})
|
})
|
||||||
export type RevertInput = z.infer<typeof RevertInput>
|
export type RevertInput = z.infer<typeof RevertInput>
|
||||||
|
|||||||
@@ -15,3 +15,15 @@ export const SessionID = sessionIdSchema.pipe(
|
|||||||
zod: z.string().startsWith("ses").pipe(z.custom<SessionID>()),
|
zod: z.string().startsWith("ses").pipe(z.custom<SessionID>()),
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const messageIdSchema = Schema.String.pipe(Schema.brand("MessageId"))
|
||||||
|
|
||||||
|
export type MessageID = typeof messageIdSchema.Type
|
||||||
|
|
||||||
|
export const MessageID = messageIdSchema.pipe(
|
||||||
|
withStatics((schema: typeof messageIdSchema) => ({
|
||||||
|
make: (id: string) => schema.makeUnsafe(id),
|
||||||
|
ascending: (id?: string) => schema.makeUnsafe(Identifier.ascending("message", id)),
|
||||||
|
zod: z.string().startsWith("msg").pipe(z.custom<MessageID>()),
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import type { MessageV2 } from "./message-v2"
|
|||||||
import type { Snapshot } from "../snapshot"
|
import type { Snapshot } from "../snapshot"
|
||||||
import type { PermissionNext } from "../permission/next"
|
import type { PermissionNext } from "../permission/next"
|
||||||
import type { ProjectID } from "../project/schema"
|
import type { ProjectID } from "../project/schema"
|
||||||
import type { SessionID } from "./schema"
|
import type { SessionID, MessageID } from "./schema"
|
||||||
|
import type { WorkspaceID } from "../control-plane/schema"
|
||||||
import { Timestamps } from "../storage/schema.sql"
|
import { Timestamps } from "../storage/schema.sql"
|
||||||
|
|
||||||
type PartData = Omit<MessageV2.Part, "id" | "sessionID" | "messageID">
|
type PartData = Omit<MessageV2.Part, "id" | "sessionID" | "messageID">
|
||||||
@@ -18,7 +19,7 @@ export const SessionTable = sqliteTable(
|
|||||||
.$type<ProjectID>()
|
.$type<ProjectID>()
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => ProjectTable.id, { onDelete: "cascade" }),
|
.references(() => ProjectTable.id, { onDelete: "cascade" }),
|
||||||
workspace_id: text(),
|
workspace_id: text().$type<WorkspaceID>(),
|
||||||
parent_id: text().$type<SessionID>(),
|
parent_id: text().$type<SessionID>(),
|
||||||
slug: text().notNull(),
|
slug: text().notNull(),
|
||||||
directory: text().notNull(),
|
directory: text().notNull(),
|
||||||
@@ -29,7 +30,7 @@ export const SessionTable = sqliteTable(
|
|||||||
summary_deletions: integer(),
|
summary_deletions: integer(),
|
||||||
summary_files: integer(),
|
summary_files: integer(),
|
||||||
summary_diffs: text({ mode: "json" }).$type<Snapshot.FileDiff[]>(),
|
summary_diffs: text({ mode: "json" }).$type<Snapshot.FileDiff[]>(),
|
||||||
revert: text({ mode: "json" }).$type<{ messageID: string; partID?: string; snapshot?: string; diff?: string }>(),
|
revert: text({ mode: "json" }).$type<{ messageID: MessageID; partID?: string; snapshot?: string; diff?: string }>(),
|
||||||
permission: text({ mode: "json" }).$type<PermissionNext.Ruleset>(),
|
permission: text({ mode: "json" }).$type<PermissionNext.Ruleset>(),
|
||||||
...Timestamps,
|
...Timestamps,
|
||||||
time_compacting: integer(),
|
time_compacting: integer(),
|
||||||
@@ -45,7 +46,7 @@ export const SessionTable = sqliteTable(
|
|||||||
export const MessageTable = sqliteTable(
|
export const MessageTable = sqliteTable(
|
||||||
"message",
|
"message",
|
||||||
{
|
{
|
||||||
id: text().primaryKey(),
|
id: text().$type<MessageID>().primaryKey(),
|
||||||
session_id: text()
|
session_id: text()
|
||||||
.$type<SessionID>()
|
.$type<SessionID>()
|
||||||
.notNull()
|
.notNull()
|
||||||
@@ -61,6 +62,7 @@ export const PartTable = sqliteTable(
|
|||||||
{
|
{
|
||||||
id: text().primaryKey(),
|
id: text().primaryKey(),
|
||||||
message_id: text()
|
message_id: text()
|
||||||
|
.$type<MessageID>()
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => MessageTable.id, { onDelete: "cascade" }),
|
.references(() => MessageTable.id, { onDelete: "cascade" }),
|
||||||
session_id: text().$type<SessionID>().notNull(),
|
session_id: text().$type<SessionID>().notNull(),
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Session } from "."
|
|||||||
|
|
||||||
import { MessageV2 } from "./message-v2"
|
import { MessageV2 } from "./message-v2"
|
||||||
import { Identifier } from "@/id/id"
|
import { Identifier } from "@/id/id"
|
||||||
import { SessionID } from "./schema"
|
import { SessionID, MessageID } from "./schema"
|
||||||
import { Snapshot } from "@/snapshot"
|
import { Snapshot } from "@/snapshot"
|
||||||
|
|
||||||
import { Storage } from "@/storage/storage"
|
import { Storage } from "@/storage/storage"
|
||||||
@@ -70,7 +70,7 @@ export namespace SessionSummary {
|
|||||||
export const summarize = fn(
|
export const summarize = fn(
|
||||||
z.object({
|
z.object({
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: z.string(),
|
messageID: MessageID.zod,
|
||||||
}),
|
}),
|
||||||
async (input) => {
|
async (input) => {
|
||||||
const all = await Session.messages({ sessionID: input.sessionID })
|
const all = await Session.messages({ sessionID: input.sessionID })
|
||||||
@@ -115,7 +115,7 @@ export namespace SessionSummary {
|
|||||||
export const diff = fn(
|
export const diff = fn(
|
||||||
z.object({
|
z.object({
|
||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
messageID: Identifier.schema("message").optional(),
|
messageID: MessageID.zod.optional(),
|
||||||
}),
|
}),
|
||||||
async (input) => {
|
async (input) => {
|
||||||
const diffs = await Storage.read<Snapshot.FileDiff[]>(["session_diff", input.sessionID]).catch(() => [])
|
const diffs = await Storage.read<Snapshot.FileDiff[]>(["session_diff", input.sessionID]).catch(() => [])
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { MessageV2 } from "../session/message-v2"
|
|||||||
import { Identifier } from "../id/id"
|
import { Identifier } from "../id/id"
|
||||||
import { Provider } from "../provider/provider"
|
import { Provider } from "../provider/provider"
|
||||||
import { Instance } from "../project/instance"
|
import { Instance } from "../project/instance"
|
||||||
import type { SessionID } from "../session/schema"
|
import { type SessionID, MessageID } from "../session/schema"
|
||||||
import EXIT_DESCRIPTION from "./plan-exit.txt"
|
import EXIT_DESCRIPTION from "./plan-exit.txt"
|
||||||
|
|
||||||
async function getLastModel(sessionID: SessionID) {
|
async function getLastModel(sessionID: SessionID) {
|
||||||
@@ -45,7 +45,7 @@ export const PlanExitTool = Tool.define("plan_exit", {
|
|||||||
const model = await getLastModel(ctx.sessionID)
|
const model = await getLastModel(ctx.sessionID)
|
||||||
|
|
||||||
const userMsg: MessageV2.User = {
|
const userMsg: MessageV2.User = {
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
sessionID: ctx.sessionID,
|
sessionID: ctx.sessionID,
|
||||||
role: "user",
|
role: "user",
|
||||||
time: {
|
time: {
|
||||||
@@ -103,7 +103,7 @@ export const PlanEnterTool = Tool.define("plan_enter", {
|
|||||||
const model = await getLastModel(ctx.sessionID)
|
const model = await getLastModel(ctx.sessionID)
|
||||||
|
|
||||||
const userMsg: MessageV2.User = {
|
const userMsg: MessageV2.User = {
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
sessionID: ctx.sessionID,
|
sessionID: ctx.sessionID,
|
||||||
role: "user",
|
role: "user",
|
||||||
time: {
|
time: {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Tool } from "./tool"
|
|||||||
import DESCRIPTION from "./task.txt"
|
import DESCRIPTION from "./task.txt"
|
||||||
import z from "zod"
|
import z from "zod"
|
||||||
import { Session } from "../session"
|
import { Session } from "../session"
|
||||||
import { SessionID } from "../session/schema"
|
import { SessionID, MessageID } from "../session/schema"
|
||||||
import { MessageV2 } from "../session/message-v2"
|
import { MessageV2 } from "../session/message-v2"
|
||||||
import { Identifier } from "../id/id"
|
import { Identifier } from "../id/id"
|
||||||
import { Agent } from "../agent/agent"
|
import { Agent } from "../agent/agent"
|
||||||
@@ -117,7 +117,7 @@ export const TaskTool = Tool.define("task", async (ctx) => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const messageID = Identifier.ascending("message")
|
const messageID = MessageID.ascending()
|
||||||
|
|
||||||
function cancel() {
|
function cancel() {
|
||||||
SessionPrompt.cancel(session.id)
|
SessionPrompt.cancel(session.id)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import z from "zod"
|
|||||||
import type { MessageV2 } from "../session/message-v2"
|
import type { MessageV2 } from "../session/message-v2"
|
||||||
import type { Agent } from "../agent/agent"
|
import type { Agent } from "../agent/agent"
|
||||||
import type { PermissionNext } from "../permission/next"
|
import type { PermissionNext } from "../permission/next"
|
||||||
import type { SessionID } from "../session/schema"
|
import type { SessionID, MessageID } from "../session/schema"
|
||||||
import { Truncate } from "./truncation"
|
import { Truncate } from "./truncation"
|
||||||
|
|
||||||
export namespace Tool {
|
export namespace Tool {
|
||||||
@@ -16,7 +16,7 @@ export namespace Tool {
|
|||||||
|
|
||||||
export type Context<M extends Metadata = Metadata> = {
|
export type Context<M extends Metadata = Metadata> = {
|
||||||
sessionID: SessionID
|
sessionID: SessionID
|
||||||
messageID: string
|
messageID: MessageID
|
||||||
agent: string
|
agent: string
|
||||||
abort: AbortSignal
|
abort: AbortSignal
|
||||||
callID?: string
|
callID?: string
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { test, expect, describe } from "bun:test"
|
import { test, expect, describe } from "bun:test"
|
||||||
import { extractResponseText, formatPromptTooLargeError } from "../../src/cli/cmd/github"
|
import { extractResponseText, formatPromptTooLargeError } from "../../src/cli/cmd/github"
|
||||||
import type { MessageV2 } from "../../src/session/message-v2"
|
import type { MessageV2 } from "../../src/session/message-v2"
|
||||||
import { SessionID } from "../../src/session/schema"
|
import { SessionID, MessageID } from "../../src/session/schema"
|
||||||
|
|
||||||
// Helper to create minimal valid parts
|
// Helper to create minimal valid parts
|
||||||
function createTextPart(text: string): MessageV2.Part {
|
function createTextPart(text: string): MessageV2.Part {
|
||||||
return {
|
return {
|
||||||
id: "1",
|
id: "1",
|
||||||
sessionID: SessionID.make("s"),
|
sessionID: SessionID.make("s"),
|
||||||
messageID: "m",
|
messageID: MessageID.make("m"),
|
||||||
type: "text" as const,
|
type: "text" as const,
|
||||||
text,
|
text,
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,7 @@ function createReasoningPart(text: string): MessageV2.Part {
|
|||||||
return {
|
return {
|
||||||
id: "1",
|
id: "1",
|
||||||
sessionID: SessionID.make("s"),
|
sessionID: SessionID.make("s"),
|
||||||
messageID: "m",
|
messageID: MessageID.make("m"),
|
||||||
type: "reasoning" as const,
|
type: "reasoning" as const,
|
||||||
text,
|
text,
|
||||||
time: { start: 0 },
|
time: { start: 0 },
|
||||||
@@ -30,7 +30,7 @@ function createToolPart(tool: string, title: string, status: "completed" | "runn
|
|||||||
return {
|
return {
|
||||||
id: "1",
|
id: "1",
|
||||||
sessionID: SessionID.make("s"),
|
sessionID: SessionID.make("s"),
|
||||||
messageID: "m",
|
messageID: MessageID.make("m"),
|
||||||
type: "tool" as const,
|
type: "tool" as const,
|
||||||
callID: "c1",
|
callID: "c1",
|
||||||
tool,
|
tool,
|
||||||
@@ -47,7 +47,7 @@ function createToolPart(tool: string, title: string, status: "completed" | "runn
|
|||||||
return {
|
return {
|
||||||
id: "1",
|
id: "1",
|
||||||
sessionID: SessionID.make("s"),
|
sessionID: SessionID.make("s"),
|
||||||
messageID: "m",
|
messageID: MessageID.make("m"),
|
||||||
type: "tool" as const,
|
type: "tool" as const,
|
||||||
callID: "c1",
|
callID: "c1",
|
||||||
tool,
|
tool,
|
||||||
@@ -63,7 +63,7 @@ function createStepStartPart(): MessageV2.Part {
|
|||||||
return {
|
return {
|
||||||
id: "1",
|
id: "1",
|
||||||
sessionID: SessionID.make("s"),
|
sessionID: SessionID.make("s"),
|
||||||
messageID: "m",
|
messageID: MessageID.make("m"),
|
||||||
type: "step-start" as const,
|
type: "step-start" as const,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,7 @@ function createStepFinishPart(): MessageV2.Part {
|
|||||||
return {
|
return {
|
||||||
id: "1",
|
id: "1",
|
||||||
sessionID: SessionID.make("s"),
|
sessionID: SessionID.make("s"),
|
||||||
messageID: "m",
|
messageID: MessageID.make("m"),
|
||||||
type: "step-finish" as const,
|
type: "step-finish" as const,
|
||||||
reason: "done",
|
reason: "done",
|
||||||
cost: 0,
|
cost: 0,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { afterEach, describe, expect, mock, test } from "bun:test"
|
import { afterEach, describe, expect, mock, test } from "bun:test"
|
||||||
import { Identifier } from "../../src/id/id"
|
import { WorkspaceID } from "../../src/control-plane/schema"
|
||||||
import { Hono } from "hono"
|
import { Hono } from "hono"
|
||||||
import { tmpdir } from "../fixture/fixture"
|
import { tmpdir } from "../fixture/fixture"
|
||||||
import { Project } from "../../src/project/project"
|
import { Project } from "../../src/project/project"
|
||||||
@@ -64,8 +64,8 @@ async function setup(state: State) {
|
|||||||
await using tmp = await tmpdir({ git: true })
|
await using tmp = await tmpdir({ git: true })
|
||||||
const { project } = await Project.fromDirectory(tmp.path)
|
const { project } = await Project.fromDirectory(tmp.path)
|
||||||
|
|
||||||
const id1 = Identifier.descending("workspace")
|
const id1 = WorkspaceID.ascending()
|
||||||
const id2 = Identifier.descending("workspace")
|
const id2 = WorkspaceID.ascending()
|
||||||
|
|
||||||
Database.use((db) =>
|
Database.use((db) =>
|
||||||
db
|
db
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { afterEach, describe, expect, mock, test } from "bun:test"
|
import { afterEach, describe, expect, mock, test } from "bun:test"
|
||||||
import { Identifier } from "../../src/id/id"
|
import { WorkspaceID } from "../../src/control-plane/schema"
|
||||||
import { Log } from "../../src/util/log"
|
import { Log } from "../../src/util/log"
|
||||||
import { tmpdir } from "../fixture/fixture"
|
import { tmpdir } from "../fixture/fixture"
|
||||||
import { Project } from "../../src/project/project"
|
import { Project } from "../../src/project/project"
|
||||||
@@ -52,8 +52,8 @@ describe("control-plane/workspace.startSyncing", () => {
|
|||||||
await using tmp = await tmpdir({ git: true })
|
await using tmp = await tmpdir({ git: true })
|
||||||
const { project } = await Project.fromDirectory(tmp.path)
|
const { project } = await Project.fromDirectory(tmp.path)
|
||||||
|
|
||||||
const id1 = Identifier.descending("workspace")
|
const id1 = WorkspaceID.ascending()
|
||||||
const id2 = Identifier.descending("workspace")
|
const id2 = WorkspaceID.ascending()
|
||||||
|
|
||||||
Database.use((db) =>
|
Database.use((db) =>
|
||||||
db
|
db
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ import { describe, test, expect } from "bun:test"
|
|||||||
import path from "path"
|
import path from "path"
|
||||||
import { Instance } from "../../src/project/instance"
|
import { Instance } from "../../src/project/instance"
|
||||||
import { WebFetchTool } from "../../src/tool/webfetch"
|
import { WebFetchTool } from "../../src/tool/webfetch"
|
||||||
import { SessionID } from "../../src/session/schema"
|
import { SessionID, MessageID } from "../../src/session/schema"
|
||||||
|
|
||||||
const projectRoot = path.join(__dirname, "../..")
|
const projectRoot = path.join(__dirname, "../..")
|
||||||
|
|
||||||
const ctx = {
|
const ctx = {
|
||||||
sessionID: SessionID.make("ses_test"),
|
sessionID: SessionID.make("ses_test"),
|
||||||
messageID: "",
|
messageID: MessageID.make(""),
|
||||||
callID: "",
|
callID: "",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
abort: new AbortController().signal,
|
abort: new AbortController().signal,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { Filesystem } from "../../src/util/filesystem"
|
|||||||
import { tmpdir } from "../fixture/fixture"
|
import { tmpdir } from "../fixture/fixture"
|
||||||
import type { Agent } from "../../src/agent/agent"
|
import type { Agent } from "../../src/agent/agent"
|
||||||
import type { MessageV2 } from "../../src/session/message-v2"
|
import type { MessageV2 } from "../../src/session/message-v2"
|
||||||
import { SessionID } from "../../src/session/schema"
|
import { SessionID, MessageID } from "../../src/session/schema"
|
||||||
|
|
||||||
describe("session.llm.hasToolCalls", () => {
|
describe("session.llm.hasToolCalls", () => {
|
||||||
test("returns false for empty messages array", () => {
|
test("returns false for empty messages array", () => {
|
||||||
@@ -277,7 +277,7 @@ describe("session.llm.stream", () => {
|
|||||||
} satisfies Agent.Info
|
} satisfies Agent.Info
|
||||||
|
|
||||||
const user = {
|
const user = {
|
||||||
id: "user-1",
|
id: MessageID.make("user-1"),
|
||||||
sessionID,
|
sessionID,
|
||||||
role: "user",
|
role: "user",
|
||||||
time: { created: Date.now() },
|
time: { created: Date.now() },
|
||||||
@@ -406,7 +406,7 @@ describe("session.llm.stream", () => {
|
|||||||
} satisfies Agent.Info
|
} satisfies Agent.Info
|
||||||
|
|
||||||
const user = {
|
const user = {
|
||||||
id: "user-2",
|
id: MessageID.make("user-2"),
|
||||||
sessionID,
|
sessionID,
|
||||||
role: "user",
|
role: "user",
|
||||||
time: { created: Date.now() },
|
time: { created: Date.now() },
|
||||||
@@ -529,7 +529,7 @@ describe("session.llm.stream", () => {
|
|||||||
} satisfies Agent.Info
|
} satisfies Agent.Info
|
||||||
|
|
||||||
const user = {
|
const user = {
|
||||||
id: "user-3",
|
id: MessageID.make("user-3"),
|
||||||
sessionID,
|
sessionID,
|
||||||
role: "user",
|
role: "user",
|
||||||
time: { created: Date.now() },
|
time: { created: Date.now() },
|
||||||
@@ -630,7 +630,7 @@ describe("session.llm.stream", () => {
|
|||||||
} satisfies Agent.Info
|
} satisfies Agent.Info
|
||||||
|
|
||||||
const user = {
|
const user = {
|
||||||
id: "user-4",
|
id: MessageID.make("user-4"),
|
||||||
sessionID,
|
sessionID,
|
||||||
role: "user",
|
role: "user",
|
||||||
time: { created: Date.now() },
|
time: { created: Date.now() },
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test"
|
|||||||
import { APICallError } from "ai"
|
import { APICallError } from "ai"
|
||||||
import { MessageV2 } from "../../src/session/message-v2"
|
import { MessageV2 } from "../../src/session/message-v2"
|
||||||
import type { Provider } from "../../src/provider/provider"
|
import type { Provider } from "../../src/provider/provider"
|
||||||
import { SessionID } from "../../src/session/schema"
|
import { SessionID, MessageID } from "../../src/session/schema"
|
||||||
|
|
||||||
const sessionID = SessionID.make("session")
|
const sessionID = SessionID.make("session")
|
||||||
const model: Provider.Model = {
|
const model: Provider.Model = {
|
||||||
@@ -100,7 +100,7 @@ function basePart(messageID: string, id: string) {
|
|||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
sessionID,
|
sessionID,
|
||||||
messageID,
|
messageID: MessageID.make(messageID),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { MessageV2 } from "../../src/session/message-v2"
|
|||||||
import { Log } from "../../src/util/log"
|
import { Log } from "../../src/util/log"
|
||||||
import { Instance } from "../../src/project/instance"
|
import { Instance } from "../../src/project/instance"
|
||||||
import { Identifier } from "../../src/id/id"
|
import { Identifier } from "../../src/id/id"
|
||||||
|
import { MessageID } from "../../src/session/schema"
|
||||||
import { tmpdir } from "../fixture/fixture"
|
import { tmpdir } from "../fixture/fixture"
|
||||||
|
|
||||||
const projectRoot = path.join(__dirname, "../..")
|
const projectRoot = path.join(__dirname, "../..")
|
||||||
@@ -24,7 +25,7 @@ describe("revert + compact workflow", () => {
|
|||||||
|
|
||||||
// Create a user message
|
// Create a user message
|
||||||
const userMsg1 = await Session.updateMessage({
|
const userMsg1 = await Session.updateMessage({
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
role: "user",
|
role: "user",
|
||||||
sessionID,
|
sessionID,
|
||||||
agent: "default",
|
agent: "default",
|
||||||
@@ -48,7 +49,7 @@ describe("revert + compact workflow", () => {
|
|||||||
|
|
||||||
// Create an assistant response message
|
// Create an assistant response message
|
||||||
const assistantMsg1: MessageV2.Assistant = {
|
const assistantMsg1: MessageV2.Assistant = {
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
role: "assistant",
|
role: "assistant",
|
||||||
sessionID,
|
sessionID,
|
||||||
mode: "default",
|
mode: "default",
|
||||||
@@ -85,7 +86,7 @@ describe("revert + compact workflow", () => {
|
|||||||
|
|
||||||
// Create another user message
|
// Create another user message
|
||||||
const userMsg2 = await Session.updateMessage({
|
const userMsg2 = await Session.updateMessage({
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
role: "user",
|
role: "user",
|
||||||
sessionID,
|
sessionID,
|
||||||
agent: "default",
|
agent: "default",
|
||||||
@@ -108,7 +109,7 @@ describe("revert + compact workflow", () => {
|
|||||||
|
|
||||||
// Create another assistant response
|
// Create another assistant response
|
||||||
const assistantMsg2: MessageV2.Assistant = {
|
const assistantMsg2: MessageV2.Assistant = {
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
role: "assistant",
|
role: "assistant",
|
||||||
sessionID,
|
sessionID,
|
||||||
mode: "default",
|
mode: "default",
|
||||||
@@ -200,7 +201,7 @@ describe("revert + compact workflow", () => {
|
|||||||
|
|
||||||
// Create initial messages
|
// Create initial messages
|
||||||
const userMsg = await Session.updateMessage({
|
const userMsg = await Session.updateMessage({
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
role: "user",
|
role: "user",
|
||||||
sessionID,
|
sessionID,
|
||||||
agent: "default",
|
agent: "default",
|
||||||
@@ -222,7 +223,7 @@ describe("revert + compact workflow", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const assistantMsg: MessageV2.Assistant = {
|
const assistantMsg: MessageV2.Assistant = {
|
||||||
id: Identifier.ascending("message"),
|
id: MessageID.ascending(),
|
||||||
role: "assistant",
|
role: "assistant",
|
||||||
sessionID,
|
sessionID,
|
||||||
mode: "default",
|
mode: "default",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Log } from "../../src/util/log"
|
|||||||
import { Instance } from "../../src/project/instance"
|
import { Instance } from "../../src/project/instance"
|
||||||
import { MessageV2 } from "../../src/session/message-v2"
|
import { MessageV2 } from "../../src/session/message-v2"
|
||||||
import { Identifier } from "../../src/id/id"
|
import { Identifier } from "../../src/id/id"
|
||||||
|
import { MessageID } from "../../src/session/schema"
|
||||||
|
|
||||||
const projectRoot = path.join(__dirname, "../..")
|
const projectRoot = path.join(__dirname, "../..")
|
||||||
Log.init({ print: false })
|
Log.init({ print: false })
|
||||||
@@ -81,7 +82,7 @@ describe("step-finish token propagation via Bus event", () => {
|
|||||||
fn: async () => {
|
fn: async () => {
|
||||||
const session = await Session.create({})
|
const session = await Session.create({})
|
||||||
|
|
||||||
const messageID = Identifier.ascending("message")
|
const messageID = MessageID.ascending()
|
||||||
await Session.updateMessage({
|
await Session.updateMessage({
|
||||||
id: messageID,
|
id: messageID,
|
||||||
sessionID: session.id,
|
sessionID: session.id,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { describe, expect, test } from "bun:test"
|
import { describe, expect, test } from "bun:test"
|
||||||
import { MessageV2 } from "../../src/session/message-v2"
|
import { MessageV2 } from "../../src/session/message-v2"
|
||||||
import { SessionPrompt } from "../../src/session/prompt"
|
import { SessionPrompt } from "../../src/session/prompt"
|
||||||
import { SessionID } from "../../src/session/schema"
|
import { SessionID, MessageID } from "../../src/session/schema"
|
||||||
|
|
||||||
describe("structured-output.OutputFormat", () => {
|
describe("structured-output.OutputFormat", () => {
|
||||||
test("parses text format", () => {
|
test("parses text format", () => {
|
||||||
@@ -96,7 +96,7 @@ describe("structured-output.StructuredOutputError", () => {
|
|||||||
describe("structured-output.UserMessage", () => {
|
describe("structured-output.UserMessage", () => {
|
||||||
test("user message accepts outputFormat", () => {
|
test("user message accepts outputFormat", () => {
|
||||||
const result = MessageV2.User.safeParse({
|
const result = MessageV2.User.safeParse({
|
||||||
id: "test-id",
|
id: MessageID.ascending(),
|
||||||
sessionID: SessionID.descending(),
|
sessionID: SessionID.descending(),
|
||||||
role: "user",
|
role: "user",
|
||||||
time: { created: Date.now() },
|
time: { created: Date.now() },
|
||||||
@@ -112,7 +112,7 @@ describe("structured-output.UserMessage", () => {
|
|||||||
|
|
||||||
test("user message works without outputFormat (optional)", () => {
|
test("user message works without outputFormat (optional)", () => {
|
||||||
const result = MessageV2.User.safeParse({
|
const result = MessageV2.User.safeParse({
|
||||||
id: "test-id",
|
id: MessageID.ascending(),
|
||||||
sessionID: SessionID.descending(),
|
sessionID: SessionID.descending(),
|
||||||
role: "user",
|
role: "user",
|
||||||
time: { created: Date.now() },
|
time: { created: Date.now() },
|
||||||
@@ -125,10 +125,10 @@ describe("structured-output.UserMessage", () => {
|
|||||||
|
|
||||||
describe("structured-output.AssistantMessage", () => {
|
describe("structured-output.AssistantMessage", () => {
|
||||||
const baseAssistantMessage = {
|
const baseAssistantMessage = {
|
||||||
id: "test-id",
|
id: MessageID.ascending(),
|
||||||
sessionID: SessionID.descending(),
|
sessionID: SessionID.descending(),
|
||||||
role: "assistant" as const,
|
role: "assistant" as const,
|
||||||
parentID: "parent-id",
|
parentID: MessageID.ascending(),
|
||||||
modelID: "claude-3",
|
modelID: "claude-3",
|
||||||
providerID: "anthropic",
|
providerID: "anthropic",
|
||||||
mode: "default",
|
mode: "default",
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { ProjectTable } from "../../src/project/project.sql"
|
|||||||
import { ProjectID } from "../../src/project/schema"
|
import { ProjectID } from "../../src/project/schema"
|
||||||
import { SessionTable, MessageTable, PartTable, TodoTable, PermissionTable } from "../../src/session/session.sql"
|
import { SessionTable, MessageTable, PartTable, TodoTable, PermissionTable } from "../../src/session/session.sql"
|
||||||
import { SessionShareTable } from "../../src/share/share.sql"
|
import { SessionShareTable } from "../../src/share/share.sql"
|
||||||
import { SessionID } from "../../src/session/schema"
|
import { SessionID, MessageID } from "../../src/session/schema"
|
||||||
|
|
||||||
// Test fixtures
|
// Test fixtures
|
||||||
const fixtures = {
|
const fixtures = {
|
||||||
@@ -255,7 +255,7 @@ describe("JSON to SQLite migration", () => {
|
|||||||
const db = drizzle({ client: sqlite })
|
const db = drizzle({ client: sqlite })
|
||||||
const messages = db.select().from(MessageTable).all()
|
const messages = db.select().from(MessageTable).all()
|
||||||
expect(messages.length).toBe(1)
|
expect(messages.length).toBe(1)
|
||||||
expect(messages[0].id).toBe("msg_test789ghi")
|
expect(messages[0].id).toBe(MessageID.make("msg_test789ghi"))
|
||||||
|
|
||||||
const parts = db.select().from(PartTable).all()
|
const parts = db.select().from(PartTable).all()
|
||||||
expect(parts.length).toBe(1)
|
expect(parts.length).toBe(1)
|
||||||
@@ -295,7 +295,7 @@ describe("JSON to SQLite migration", () => {
|
|||||||
const db = drizzle({ client: sqlite })
|
const db = drizzle({ client: sqlite })
|
||||||
const messages = db.select().from(MessageTable).all()
|
const messages = db.select().from(MessageTable).all()
|
||||||
expect(messages.length).toBe(1)
|
expect(messages.length).toBe(1)
|
||||||
expect(messages[0].id).toBe("msg_test789ghi")
|
expect(messages[0].id).toBe(MessageID.make("msg_test789ghi"))
|
||||||
expect(messages[0].session_id).toBe(SessionID.make("ses_test456def"))
|
expect(messages[0].session_id).toBe(SessionID.make("ses_test456def"))
|
||||||
expect(messages[0].data).not.toHaveProperty("id")
|
expect(messages[0].data).not.toHaveProperty("id")
|
||||||
expect(messages[0].data).not.toHaveProperty("sessionID")
|
expect(messages[0].data).not.toHaveProperty("sessionID")
|
||||||
@@ -303,7 +303,7 @@ describe("JSON to SQLite migration", () => {
|
|||||||
const parts = db.select().from(PartTable).all()
|
const parts = db.select().from(PartTable).all()
|
||||||
expect(parts.length).toBe(1)
|
expect(parts.length).toBe(1)
|
||||||
expect(parts[0].id).toBe("prt_testabc123")
|
expect(parts[0].id).toBe("prt_testabc123")
|
||||||
expect(parts[0].message_id).toBe("msg_test789ghi")
|
expect(parts[0].message_id).toBe(MessageID.make("msg_test789ghi"))
|
||||||
expect(parts[0].session_id).toBe(SessionID.make("ses_test456def"))
|
expect(parts[0].session_id).toBe(SessionID.make("ses_test456def"))
|
||||||
expect(parts[0].data).not.toHaveProperty("id")
|
expect(parts[0].data).not.toHaveProperty("id")
|
||||||
expect(parts[0].data).not.toHaveProperty("messageID")
|
expect(parts[0].data).not.toHaveProperty("messageID")
|
||||||
@@ -336,7 +336,7 @@ describe("JSON to SQLite migration", () => {
|
|||||||
const db = drizzle({ client: sqlite })
|
const db = drizzle({ client: sqlite })
|
||||||
const messages = db.select().from(MessageTable).all()
|
const messages = db.select().from(MessageTable).all()
|
||||||
expect(messages.length).toBe(1)
|
expect(messages.length).toBe(1)
|
||||||
expect(messages[0].id).toBe("msg_from_filename") // Uses filename, not JSON id
|
expect(messages[0].id).toBe(MessageID.make("msg_from_filename")) // Uses filename, not JSON id
|
||||||
expect(messages[0].session_id).toBe(SessionID.make("ses_test456def"))
|
expect(messages[0].session_id).toBe(SessionID.make("ses_test456def"))
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -375,7 +375,7 @@ describe("JSON to SQLite migration", () => {
|
|||||||
const parts = db.select().from(PartTable).all()
|
const parts = db.select().from(PartTable).all()
|
||||||
expect(parts.length).toBe(1)
|
expect(parts.length).toBe(1)
|
||||||
expect(parts[0].id).toBe("prt_from_filename") // Uses filename, not JSON id
|
expect(parts[0].id).toBe("prt_from_filename") // Uses filename, not JSON id
|
||||||
expect(parts[0].message_id).toBe("msg_realmsgid") // Uses parent dir, not JSON messageID
|
expect(parts[0].message_id).toBe(MessageID.make("msg_realmsgid")) // Uses parent dir, not JSON messageID
|
||||||
})
|
})
|
||||||
|
|
||||||
test("skips orphaned sessions (no parent project)", async () => {
|
test("skips orphaned sessions (no parent project)", async () => {
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import * as fs from "fs/promises"
|
|||||||
import { ApplyPatchTool } from "../../src/tool/apply_patch"
|
import { ApplyPatchTool } from "../../src/tool/apply_patch"
|
||||||
import { Instance } from "../../src/project/instance"
|
import { Instance } from "../../src/project/instance"
|
||||||
import { tmpdir } from "../fixture/fixture"
|
import { tmpdir } from "../fixture/fixture"
|
||||||
import { SessionID } from "../../src/session/schema"
|
import { SessionID, MessageID } from "../../src/session/schema"
|
||||||
|
|
||||||
const baseCtx = {
|
const baseCtx = {
|
||||||
sessionID: SessionID.make("ses_test"),
|
sessionID: SessionID.make("ses_test"),
|
||||||
messageID: "",
|
messageID: MessageID.make(""),
|
||||||
callID: "",
|
callID: "",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
abort: AbortSignal.any([]),
|
abort: AbortSignal.any([]),
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import { Filesystem } from "../../src/util/filesystem"
|
|||||||
import { tmpdir } from "../fixture/fixture"
|
import { tmpdir } from "../fixture/fixture"
|
||||||
import type { PermissionNext } from "../../src/permission/next"
|
import type { PermissionNext } from "../../src/permission/next"
|
||||||
import { Truncate } from "../../src/tool/truncation"
|
import { Truncate } from "../../src/tool/truncation"
|
||||||
import { SessionID } from "../../src/session/schema"
|
import { SessionID, MessageID } from "../../src/session/schema"
|
||||||
|
|
||||||
const ctx = {
|
const ctx = {
|
||||||
sessionID: SessionID.make("ses_test"),
|
sessionID: SessionID.make("ses_test"),
|
||||||
messageID: "",
|
messageID: MessageID.make(""),
|
||||||
callID: "",
|
callID: "",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
abort: AbortSignal.any([]),
|
abort: AbortSignal.any([]),
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import { EditTool } from "../../src/tool/edit"
|
|||||||
import { Instance } from "../../src/project/instance"
|
import { Instance } from "../../src/project/instance"
|
||||||
import { tmpdir } from "../fixture/fixture"
|
import { tmpdir } from "../fixture/fixture"
|
||||||
import { FileTime } from "../../src/file/time"
|
import { FileTime } from "../../src/file/time"
|
||||||
import { SessionID } from "../../src/session/schema"
|
import { SessionID, MessageID } from "../../src/session/schema"
|
||||||
|
|
||||||
const ctx = {
|
const ctx = {
|
||||||
sessionID: SessionID.make("ses_test-edit-session"),
|
sessionID: SessionID.make("ses_test-edit-session"),
|
||||||
messageID: "",
|
messageID: MessageID.make(""),
|
||||||
callID: "",
|
callID: "",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
abort: AbortSignal.any([]),
|
abort: AbortSignal.any([]),
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import type { Tool } from "../../src/tool/tool"
|
|||||||
import { Instance } from "../../src/project/instance"
|
import { Instance } from "../../src/project/instance"
|
||||||
import { assertExternalDirectory } from "../../src/tool/external-directory"
|
import { assertExternalDirectory } from "../../src/tool/external-directory"
|
||||||
import type { PermissionNext } from "../../src/permission/next"
|
import type { PermissionNext } from "../../src/permission/next"
|
||||||
import { SessionID } from "../../src/session/schema"
|
import { SessionID, MessageID } from "../../src/session/schema"
|
||||||
|
|
||||||
const baseCtx: Omit<Tool.Context, "ask"> = {
|
const baseCtx: Omit<Tool.Context, "ask"> = {
|
||||||
sessionID: SessionID.make("ses_test"),
|
sessionID: SessionID.make("ses_test"),
|
||||||
messageID: "",
|
messageID: MessageID.make(""),
|
||||||
callID: "",
|
callID: "",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
abort: AbortSignal.any([]),
|
abort: AbortSignal.any([]),
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import path from "path"
|
|||||||
import { GrepTool } from "../../src/tool/grep"
|
import { GrepTool } from "../../src/tool/grep"
|
||||||
import { Instance } from "../../src/project/instance"
|
import { Instance } from "../../src/project/instance"
|
||||||
import { tmpdir } from "../fixture/fixture"
|
import { tmpdir } from "../fixture/fixture"
|
||||||
import { SessionID } from "../../src/session/schema"
|
import { SessionID, MessageID } from "../../src/session/schema"
|
||||||
|
|
||||||
const ctx = {
|
const ctx = {
|
||||||
sessionID: SessionID.make("ses_test"),
|
sessionID: SessionID.make("ses_test"),
|
||||||
messageID: "",
|
messageID: MessageID.make(""),
|
||||||
callID: "",
|
callID: "",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
abort: AbortSignal.any([]),
|
abort: AbortSignal.any([]),
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import { describe, expect, test, spyOn, beforeEach, afterEach } from "bun:test"
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
import { QuestionTool } from "../../src/tool/question"
|
import { QuestionTool } from "../../src/tool/question"
|
||||||
import * as QuestionModule from "../../src/question"
|
import * as QuestionModule from "../../src/question"
|
||||||
import { SessionID } from "../../src/session/schema"
|
import { SessionID, MessageID } from "../../src/session/schema"
|
||||||
|
|
||||||
const ctx = {
|
const ctx = {
|
||||||
sessionID: SessionID.make("ses_test-session"),
|
sessionID: SessionID.make("ses_test-session"),
|
||||||
messageID: "test-message",
|
messageID: MessageID.make("test-message"),
|
||||||
callID: "test-call",
|
callID: "test-call",
|
||||||
agent: "test-agent",
|
agent: "test-agent",
|
||||||
abort: AbortSignal.any([]),
|
abort: AbortSignal.any([]),
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import { Filesystem } from "../../src/util/filesystem"
|
|||||||
import { tmpdir } from "../fixture/fixture"
|
import { tmpdir } from "../fixture/fixture"
|
||||||
import { PermissionNext } from "../../src/permission/next"
|
import { PermissionNext } from "../../src/permission/next"
|
||||||
import { Agent } from "../../src/agent/agent"
|
import { Agent } from "../../src/agent/agent"
|
||||||
import { SessionID } from "../../src/session/schema"
|
import { SessionID, MessageID } from "../../src/session/schema"
|
||||||
|
|
||||||
const FIXTURES_DIR = path.join(import.meta.dir, "fixtures")
|
const FIXTURES_DIR = path.join(import.meta.dir, "fixtures")
|
||||||
|
|
||||||
const ctx = {
|
const ctx = {
|
||||||
sessionID: SessionID.make("ses_test"),
|
sessionID: SessionID.make("ses_test"),
|
||||||
messageID: "",
|
messageID: MessageID.make(""),
|
||||||
callID: "",
|
callID: "",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
abort: AbortSignal.any([]),
|
abort: AbortSignal.any([]),
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import type { Tool } from "../../src/tool/tool"
|
|||||||
import { Instance } from "../../src/project/instance"
|
import { Instance } from "../../src/project/instance"
|
||||||
import { SkillTool } from "../../src/tool/skill"
|
import { SkillTool } from "../../src/tool/skill"
|
||||||
import { tmpdir } from "../fixture/fixture"
|
import { tmpdir } from "../fixture/fixture"
|
||||||
import { SessionID } from "../../src/session/schema"
|
import { SessionID, MessageID } from "../../src/session/schema"
|
||||||
|
|
||||||
const baseCtx: Omit<Tool.Context, "ask"> = {
|
const baseCtx: Omit<Tool.Context, "ask"> = {
|
||||||
sessionID: SessionID.make("ses_test"),
|
sessionID: SessionID.make("ses_test"),
|
||||||
messageID: "",
|
messageID: MessageID.make(""),
|
||||||
callID: "",
|
callID: "",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
abort: AbortSignal.any([]),
|
abort: AbortSignal.any([]),
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ import { describe, expect, test } from "bun:test"
|
|||||||
import path from "path"
|
import path from "path"
|
||||||
import { Instance } from "../../src/project/instance"
|
import { Instance } from "../../src/project/instance"
|
||||||
import { WebFetchTool } from "../../src/tool/webfetch"
|
import { WebFetchTool } from "../../src/tool/webfetch"
|
||||||
import { SessionID } from "../../src/session/schema"
|
import { SessionID, MessageID } from "../../src/session/schema"
|
||||||
|
|
||||||
const projectRoot = path.join(import.meta.dir, "../..")
|
const projectRoot = path.join(import.meta.dir, "../..")
|
||||||
|
|
||||||
const ctx = {
|
const ctx = {
|
||||||
sessionID: SessionID.make("ses_test"),
|
sessionID: SessionID.make("ses_test"),
|
||||||
messageID: "message",
|
messageID: MessageID.make("message"),
|
||||||
callID: "",
|
callID: "",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
abort: AbortSignal.any([]),
|
abort: AbortSignal.any([]),
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import fs from "fs/promises"
|
|||||||
import { WriteTool } from "../../src/tool/write"
|
import { WriteTool } from "../../src/tool/write"
|
||||||
import { Instance } from "../../src/project/instance"
|
import { Instance } from "../../src/project/instance"
|
||||||
import { tmpdir } from "../fixture/fixture"
|
import { tmpdir } from "../fixture/fixture"
|
||||||
import { SessionID } from "../../src/session/schema"
|
import { SessionID, MessageID } from "../../src/session/schema"
|
||||||
|
|
||||||
const ctx = {
|
const ctx = {
|
||||||
sessionID: SessionID.make("ses_test-write-session"),
|
sessionID: SessionID.make("ses_test-write-session"),
|
||||||
messageID: "",
|
messageID: MessageID.make(""),
|
||||||
callID: "",
|
callID: "",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
abort: AbortSignal.any([]),
|
abort: AbortSignal.any([]),
|
||||||
|
|||||||
Reference in New Issue
Block a user