refactor(schema): extract shared public schemas (#33571)
This commit is contained in:
@@ -277,6 +277,7 @@
|
|||||||
"@opencode-ai/effect-sqlite-node": "workspace:*",
|
"@opencode-ai/effect-sqlite-node": "workspace:*",
|
||||||
"@opencode-ai/llm": "workspace:*",
|
"@opencode-ai/llm": "workspace:*",
|
||||||
"@opencode-ai/plugin": "workspace:*",
|
"@opencode-ai/plugin": "workspace:*",
|
||||||
|
"@opencode-ai/schema": "workspace:*",
|
||||||
"@openrouter/ai-sdk-provider": "2.9.0",
|
"@openrouter/ai-sdk-provider": "2.9.0",
|
||||||
"@opentelemetry/api": "1.9.0",
|
"@opentelemetry/api": "1.9.0",
|
||||||
"@opentelemetry/context-async-hooks": "2.6.1",
|
"@opentelemetry/context-async-hooks": "2.6.1",
|
||||||
@@ -480,6 +481,7 @@
|
|||||||
"name": "@opencode-ai/llm",
|
"name": "@opencode-ai/llm",
|
||||||
"version": "1.17.9",
|
"version": "1.17.9",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@opencode-ai/schema": "workspace:*",
|
||||||
"@smithy/eventstream-codec": "4.2.14",
|
"@smithy/eventstream-codec": "4.2.14",
|
||||||
"@smithy/util-utf8": "4.2.2",
|
"@smithy/util-utf8": "4.2.2",
|
||||||
"aws4fetch": "1.0.20",
|
"aws4fetch": "1.0.20",
|
||||||
@@ -651,6 +653,17 @@
|
|||||||
"@opentui/solid",
|
"@opentui/solid",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
"packages/schema": {
|
||||||
|
"name": "@opencode-ai/schema",
|
||||||
|
"dependencies": {
|
||||||
|
"effect": "catalog:",
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tsconfig/bun": "catalog:",
|
||||||
|
"@types/bun": "catalog:",
|
||||||
|
"@typescript/native-preview": "catalog:",
|
||||||
|
},
|
||||||
|
},
|
||||||
"packages/script": {
|
"packages/script": {
|
||||||
"name": "@opencode-ai/script",
|
"name": "@opencode-ai/script",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1804,6 +1817,8 @@
|
|||||||
|
|
||||||
"@opencode-ai/plugin": ["@opencode-ai/plugin@workspace:packages/plugin"],
|
"@opencode-ai/plugin": ["@opencode-ai/plugin@workspace:packages/plugin"],
|
||||||
|
|
||||||
|
"@opencode-ai/schema": ["@opencode-ai/schema@workspace:packages/schema"],
|
||||||
|
|
||||||
"@opencode-ai/script": ["@opencode-ai/script@workspace:packages/script"],
|
"@opencode-ai/script": ["@opencode-ai/script@workspace:packages/script"],
|
||||||
|
|
||||||
"@opencode-ai/sdk": ["@opencode-ai/sdk@workspace:packages/sdk/js"],
|
"@opencode-ai/sdk": ["@opencode-ai/sdk@workspace:packages/sdk/js"],
|
||||||
|
|||||||
@@ -91,6 +91,7 @@
|
|||||||
"@opencode-ai/effect-drizzle-sqlite": "workspace:*",
|
"@opencode-ai/effect-drizzle-sqlite": "workspace:*",
|
||||||
"@opencode-ai/effect-sqlite-node": "workspace:*",
|
"@opencode-ai/effect-sqlite-node": "workspace:*",
|
||||||
"@opencode-ai/llm": "workspace:*",
|
"@opencode-ai/llm": "workspace:*",
|
||||||
|
"@opencode-ai/schema": "workspace:*",
|
||||||
"@opencode-ai/plugin": "workspace:*",
|
"@opencode-ai/plugin": "workspace:*",
|
||||||
"@opentelemetry/api": "1.9.0",
|
"@opentelemetry/api": "1.9.0",
|
||||||
"@opentelemetry/context-async-hooks": "2.6.1",
|
"@opentelemetry/context-async-hooks": "2.6.1",
|
||||||
|
|||||||
@@ -1,46 +1,17 @@
|
|||||||
export * as AgentV2 from "./agent"
|
export * as AgentV2 from "./agent"
|
||||||
|
|
||||||
import { Array, Context, Effect, Layer, Schema, Scope, Types } from "effect"
|
import { Array, Context, Effect, Layer, Types } from "effect"
|
||||||
import { ModelV2 } from "./model"
|
import { Agent } from "@opencode-ai/schema/agent"
|
||||||
import { PermissionSchema } from "./permission/schema"
|
|
||||||
import { ProviderV2 } from "./provider"
|
|
||||||
import { PositiveInt } from "./schema"
|
|
||||||
import { State } from "./state"
|
import { State } from "./state"
|
||||||
|
|
||||||
export const ID = Schema.String.pipe(Schema.brand("AgentV2.ID"))
|
export const ID = Agent.ID
|
||||||
export type ID = typeof ID.Type
|
export type ID = typeof ID.Type
|
||||||
export const defaultID = ID.make("build")
|
export const defaultID = ID.make("build")
|
||||||
|
|
||||||
export const Color = Schema.Union([
|
export const Color = Agent.Color
|
||||||
Schema.String.check(Schema.isPattern(/^#[0-9a-fA-F]{6}$/)),
|
|
||||||
Schema.Literals(["primary", "secondary", "accent", "success", "warning", "error", "info"]),
|
|
||||||
])
|
|
||||||
|
|
||||||
export class Info extends Schema.Class<Info>("AgentV2.Info")({
|
export const Info = Agent.Info
|
||||||
id: ID,
|
export type Info = Agent.Info
|
||||||
model: ModelV2.Ref.pipe(Schema.optional),
|
|
||||||
request: ProviderV2.Request,
|
|
||||||
system: Schema.String.pipe(Schema.optional),
|
|
||||||
description: Schema.String.pipe(Schema.optional),
|
|
||||||
mode: Schema.Literals(["subagent", "primary", "all"]),
|
|
||||||
hidden: Schema.Boolean,
|
|
||||||
color: Color.pipe(Schema.optional),
|
|
||||||
steps: PositiveInt.pipe(Schema.optional),
|
|
||||||
permissions: PermissionSchema.Ruleset,
|
|
||||||
}) {
|
|
||||||
static empty(id: ID) {
|
|
||||||
return new Info({
|
|
||||||
id,
|
|
||||||
request: {
|
|
||||||
headers: {},
|
|
||||||
body: {},
|
|
||||||
},
|
|
||||||
mode: "all",
|
|
||||||
hidden: false,
|
|
||||||
permissions: [],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Selection {
|
export interface Selection {
|
||||||
readonly id: ID
|
readonly id: ID
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ export const layer = Layer.effect(
|
|||||||
...ModelRequest.merge({ ...provider.request, generation: {}, options: {} }, model.request),
|
...ModelRequest.merge({ ...provider.request, generation: {}, options: {} }, model.request),
|
||||||
variant: model.request.variant,
|
variant: model.request.variant,
|
||||||
}
|
}
|
||||||
return new ModelV2.Info({
|
return ModelV2.Info.make({
|
||||||
...model,
|
...model,
|
||||||
api,
|
api,
|
||||||
request,
|
request,
|
||||||
|
|||||||
@@ -1,17 +1,11 @@
|
|||||||
export * as CommandV2 from "./command"
|
export * as CommandV2 from "./command"
|
||||||
|
|
||||||
import { Context, Effect, Layer, Schema, Types } from "effect"
|
import { Context, Effect, Layer, Types } from "effect"
|
||||||
import { ModelV2 } from "./model"
|
import { Command } from "@opencode-ai/schema/command"
|
||||||
import { State } from "./state"
|
import { State } from "./state"
|
||||||
|
|
||||||
export class Info extends Schema.Class<Info>("CommandV2.Info")({
|
export const Info = Command.Info
|
||||||
name: Schema.String,
|
export type Info = Command.Info
|
||||||
template: Schema.String,
|
|
||||||
description: Schema.String.pipe(Schema.optional),
|
|
||||||
agent: Schema.String.pipe(Schema.optional),
|
|
||||||
model: ModelV2.Ref.pipe(Schema.optional),
|
|
||||||
subtask: Schema.Boolean.pipe(Schema.optional),
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export type Data = {
|
export type Data = {
|
||||||
commands: Map<string, Types.DeepMutable<Info>>
|
commands: Map<string, Types.DeepMutable<Info>>
|
||||||
@@ -40,7 +34,7 @@ export const layer = Layer.effect(
|
|||||||
list: () => Array.from(draft.commands.values()) as Info[],
|
list: () => Array.from(draft.commands.values()) as Info[],
|
||||||
get: (name) => draft.commands.get(name),
|
get: (name) => draft.commands.get(name),
|
||||||
update: (name, update) => {
|
update: (name, update) => {
|
||||||
const current = draft.commands.get(name) ?? (new Info({ name, template: "" }) as Types.DeepMutable<Info>)
|
const current = draft.commands.get(name) ?? ({ name, template: "" } as Types.DeepMutable<Info>)
|
||||||
if (!draft.commands.has(name)) draft.commands.set(name, current)
|
if (!draft.commands.has(name)) draft.commands.set(name, current)
|
||||||
update(current)
|
update(current)
|
||||||
current.name = name
|
current.name = name
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export const Plugin = define({
|
|||||||
entries.set(
|
entries.set(
|
||||||
name,
|
name,
|
||||||
local(entry)
|
local(entry)
|
||||||
? new Reference.LocalSource({
|
? Reference.LocalSource.make({
|
||||||
type: "local",
|
type: "local",
|
||||||
path: AbsolutePath.make(
|
path: AbsolutePath.make(
|
||||||
localPath(directory, global.home, typeof entry === "string" ? entry : entry.path),
|
localPath(directory, global.home, typeof entry === "string" ? entry : entry.path),
|
||||||
@@ -36,7 +36,7 @@ export const Plugin = define({
|
|||||||
description: typeof entry === "string" ? undefined : entry.description,
|
description: typeof entry === "string" ? undefined : entry.description,
|
||||||
hidden: typeof entry === "string" ? undefined : entry.hidden,
|
hidden: typeof entry === "string" ? undefined : entry.hidden,
|
||||||
})
|
})
|
||||||
: new Reference.GitSource({
|
: Reference.GitSource.make({
|
||||||
type: "git",
|
type: "git",
|
||||||
repository: typeof entry === "string" ? entry : entry.repository,
|
repository: typeof entry === "string" ? entry : entry.repository,
|
||||||
branch: typeof entry === "string" ? undefined : entry.branch,
|
branch: typeof entry === "string" ? undefined : entry.branch,
|
||||||
|
|||||||
@@ -22,20 +22,23 @@ export const Plugin = define({
|
|||||||
const items = entries.flatMap((entry) => (entry.type === "document" ? (entry.info.skills ?? []) : []))
|
const items = entries.flatMap((entry) => (entry.type === "document" ? (entry.info.skills ?? []) : []))
|
||||||
for (const directory of directories) {
|
for (const directory of directories) {
|
||||||
draft.source(
|
draft.source(
|
||||||
new SkillV2.DirectorySource({ type: "directory", path: AbsolutePath.make(path.join(directory, "skill")) }),
|
SkillV2.DirectorySource.make({ type: "directory", path: AbsolutePath.make(path.join(directory, "skill")) }),
|
||||||
)
|
)
|
||||||
draft.source(
|
draft.source(
|
||||||
new SkillV2.DirectorySource({ type: "directory", path: AbsolutePath.make(path.join(directory, "skills")) }),
|
SkillV2.DirectorySource.make({
|
||||||
|
type: "directory",
|
||||||
|
path: AbsolutePath.make(path.join(directory, "skills")),
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
if (URL.canParse(item) && /^(https?:)$/.test(new URL(item).protocol)) {
|
if (URL.canParse(item) && /^(https?:)$/.test(new URL(item).protocol)) {
|
||||||
draft.source(new SkillV2.UrlSource({ type: "url", url: item }))
|
draft.source(SkillV2.UrlSource.make({ type: "url", url: item }))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const expanded = item.startsWith("~/") ? path.join(global.home, item.slice(2)) : item
|
const expanded = item.startsWith("~/") ? path.join(global.home, item.slice(2)) : item
|
||||||
draft.source(
|
draft.source(
|
||||||
new SkillV2.DirectorySource({
|
SkillV2.DirectorySource.make({
|
||||||
type: "directory",
|
type: "directory",
|
||||||
path: AbsolutePath.make(path.isAbsolute(expanded) ? expanded : path.join(location.directory, expanded)),
|
path: AbsolutePath.make(path.isAbsolute(expanded) ? expanded : path.join(location.directory, expanded)),
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -2,37 +2,22 @@ export * as Credential from "./credential"
|
|||||||
|
|
||||||
import { asc, eq } from "drizzle-orm"
|
import { asc, eq } from "drizzle-orm"
|
||||||
import { Context, Effect, Layer, Schema } from "effect"
|
import { Context, Effect, Layer, Schema } from "effect"
|
||||||
|
import { Credential } from "@opencode-ai/schema/credential"
|
||||||
import { Database } from "./database/database"
|
import { Database } from "./database/database"
|
||||||
import { IntegrationSchema } from "./integration/schema"
|
import { IntegrationSchema } from "./integration/schema"
|
||||||
import { NonNegativeInt, withStatics } from "./schema"
|
|
||||||
import { Identifier } from "./util/identifier"
|
|
||||||
import { CredentialTable } from "./credential/sql"
|
import { CredentialTable } from "./credential/sql"
|
||||||
|
|
||||||
export const ID = Schema.String.pipe(
|
export const ID = Credential.ID
|
||||||
Schema.brand("Credential.ID"),
|
export type ID = Credential.ID
|
||||||
withStatics((schema) => ({ create: () => schema.make("cred_" + Identifier.ascending()) })),
|
|
||||||
)
|
|
||||||
export type ID = typeof ID.Type
|
|
||||||
|
|
||||||
export class OAuth extends Schema.Class<OAuth>("Credential.OAuth")({
|
export const OAuth = Credential.OAuth
|
||||||
type: Schema.Literal("oauth"),
|
export type OAuth = Credential.OAuth
|
||||||
methodID: IntegrationSchema.MethodID,
|
|
||||||
refresh: Schema.String,
|
|
||||||
access: Schema.String,
|
|
||||||
expires: NonNegativeInt,
|
|
||||||
metadata: Schema.optional(Schema.Record(Schema.String, Schema.Any)),
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class Key extends Schema.Class<Key>("Credential.Key")({
|
export const Key = Credential.Key
|
||||||
type: Schema.Literal("key"),
|
export type Key = Credential.Key
|
||||||
key: Schema.String,
|
|
||||||
metadata: Schema.optional(Schema.Record(Schema.String, Schema.Any)),
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export const Value = Schema.Union([OAuth, Key])
|
export const Value = Credential.Value
|
||||||
.pipe(Schema.toTaggedUnion("type"))
|
export type Value = Credential.Value
|
||||||
.annotate({ identifier: "Credential.Value" })
|
|
||||||
export type Value = Schema.Schema.Type<typeof Value>
|
|
||||||
|
|
||||||
export class Info extends Schema.Class<Info>("Credential.Info")({
|
export class Info extends Schema.Class<Info>("Credential.Info")({
|
||||||
id: ID,
|
id: ID,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { and, asc, eq, gt } from "drizzle-orm"
|
|||||||
import { Database } from "./database/database"
|
import { Database } from "./database/database"
|
||||||
import { EventSequenceTable, EventTable } from "./event/sql"
|
import { EventSequenceTable, EventTable } from "./event/sql"
|
||||||
import { Location } from "./location"
|
import { Location } from "./location"
|
||||||
import { externalID, type ExternalID, withStatics } from "./schema"
|
import { withStatics } from "./schema"
|
||||||
import { Identifier } from "./util/identifier"
|
import { Identifier } from "./util/identifier"
|
||||||
import { LayerNode } from "./effect/layer-node"
|
import { LayerNode } from "./effect/layer-node"
|
||||||
import { isDeepStrictEqual } from "node:util"
|
import { isDeepStrictEqual } from "node:util"
|
||||||
@@ -14,7 +14,6 @@ export const ID = Schema.String.check(Schema.isStartsWith("evt_")).pipe(
|
|||||||
Schema.brand("Event.ID"),
|
Schema.brand("Event.ID"),
|
||||||
withStatics((schema) => ({
|
withStatics((schema) => ({
|
||||||
create: () => schema.make("evt_" + Identifier.ascending()),
|
create: () => schema.make("evt_" + Identifier.ascending()),
|
||||||
fromExternal: (input: ExternalID) => schema.make(externalID("evt", input)),
|
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
export type ID = typeof ID.Type
|
export type ID = typeof ID.Type
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ const baseLayer = Layer.effect(
|
|||||||
const absolute = path.join(target.absolute, item.name)
|
const absolute = path.join(target.absolute, item.name)
|
||||||
const relative = path.relative(target.directory, absolute)
|
const relative = path.relative(target.directory, absolute)
|
||||||
return [
|
return [
|
||||||
new Entry({
|
Entry.make({
|
||||||
path: RelativePath.make(relative + (item.type === "directory" ? path.sep : "")),
|
path: RelativePath.make(relative + (item.type === "directory" ? path.sep : "")),
|
||||||
type: item.type,
|
type: item.type,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,22 +1,10 @@
|
|||||||
import { Schema } from "effect"
|
import { FileSystem } from "@opencode-ai/schema/filesystem"
|
||||||
import { NonNegativeInt, PositiveInt, RelativePath } from "../schema"
|
|
||||||
|
|
||||||
export class Entry extends Schema.Class<Entry>("FileSystem.Entry")({
|
export const Entry = FileSystem.Entry
|
||||||
path: RelativePath,
|
export type Entry = FileSystem.Entry
|
||||||
type: Schema.Literals(["file", "directory"]),
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export const Submatch = Schema.Struct({
|
export const Submatch = FileSystem.Submatch
|
||||||
text: Schema.String,
|
export type Submatch = FileSystem.Submatch
|
||||||
start: NonNegativeInt,
|
|
||||||
end: NonNegativeInt,
|
|
||||||
})
|
|
||||||
export type Submatch = typeof Submatch.Type
|
|
||||||
|
|
||||||
export class Match extends Schema.Class<Match>("FileSystem.Match")({
|
export const Match = FileSystem.Match
|
||||||
entry: Entry,
|
export type Match = FileSystem.Match
|
||||||
line: PositiveInt,
|
|
||||||
offset: NonNegativeInt,
|
|
||||||
text: Schema.String,
|
|
||||||
submatches: Schema.Array(Submatch),
|
|
||||||
}) {}
|
|
||||||
|
|||||||
@@ -59,12 +59,11 @@ export const ripgrepLayer = Layer.effect(
|
|||||||
})
|
})
|
||||||
.pipe(
|
.pipe(
|
||||||
Effect.map((result) =>
|
Effect.map((result) =>
|
||||||
result.map(
|
result.map((entry) =>
|
||||||
(entry) =>
|
FileSystem.Entry.make({
|
||||||
new FileSystem.Entry({
|
...entry,
|
||||||
...entry,
|
path: RelativePath.make(path.relative(location.directory, path.resolve(cwd, entry.path))),
|
||||||
path: RelativePath.make(path.relative(location.directory, path.resolve(cwd, entry.path))),
|
}),
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Effect.orDie,
|
Effect.orDie,
|
||||||
@@ -85,15 +84,14 @@ export const ripgrepLayer = Layer.effect(
|
|||||||
})
|
})
|
||||||
.pipe(
|
.pipe(
|
||||||
Effect.map((result) =>
|
Effect.map((result) =>
|
||||||
result.map(
|
result.map((match) =>
|
||||||
(match) =>
|
FileSystem.Match.make({
|
||||||
new FileSystem.Match({
|
...match,
|
||||||
...match,
|
entry: FileSystem.Entry.make({
|
||||||
entry: new FileSystem.Entry({
|
...match.entry,
|
||||||
...match.entry,
|
path: RelativePath.make(path.relative(location.directory, path.resolve(cwd, match.entry.path))),
|
||||||
path: RelativePath.make(path.relative(location.directory, path.resolve(cwd, match.entry.path))),
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Effect.orDie,
|
Effect.orDie,
|
||||||
@@ -110,7 +108,7 @@ export const ripgrepLayer = Layer.effect(
|
|||||||
return fuzzysort.go(input.query, items, { limit: input.limit ?? 50 }).map((item) => {
|
return fuzzysort.go(input.query, items, { limit: input.limit ?? 50 }).map((item) => {
|
||||||
const relative = item.target
|
const relative = item.target
|
||||||
const type = relative.endsWith(path.sep) ? ("directory" as const) : ("file" as const)
|
const type = relative.endsWith(path.sep) ? ("directory" as const) : ("file" as const)
|
||||||
return new FileSystem.Entry({
|
return FileSystem.Entry.make({
|
||||||
path: RelativePath.make(relative),
|
path: RelativePath.make(relative),
|
||||||
type,
|
type,
|
||||||
})
|
})
|
||||||
@@ -145,12 +143,11 @@ export const fffLayer = Layer.effect(
|
|||||||
pageSize: input.limit,
|
pageSize: input.limit,
|
||||||
})
|
})
|
||||||
if (!found.ok) throw found.error
|
if (!found.ok) throw found.error
|
||||||
return found.value.items.map(
|
return found.value.items.map((item) =>
|
||||||
(item) =>
|
FileSystem.Entry.make({
|
||||||
new FileSystem.Entry({
|
path: RelativePath.make(item.relativePath.replaceAll("\\", "/")),
|
||||||
path: RelativePath.make(item.relativePath.replaceAll("\\", "/")),
|
type: "file",
|
||||||
type: "file",
|
}),
|
||||||
}),
|
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
grep: (input) =>
|
grep: (input) =>
|
||||||
@@ -165,8 +162,8 @@ export const fffLayer = Layer.effect(
|
|||||||
if (!found.ok) throw found.error
|
if (!found.ok) throw found.error
|
||||||
return found.value.items.map((match) => {
|
return found.value.items.map((match) => {
|
||||||
const bytes = Buffer.from(match.lineContent)
|
const bytes = Buffer.from(match.lineContent)
|
||||||
return new FileSystem.Match({
|
return FileSystem.Match.make({
|
||||||
entry: new FileSystem.Entry({
|
entry: FileSystem.Entry.make({
|
||||||
path: RelativePath.make(match.relativePath.replaceAll("\\", "/")),
|
path: RelativePath.make(match.relativePath.replaceAll("\\", "/")),
|
||||||
type: "file",
|
type: "file",
|
||||||
}),
|
}),
|
||||||
@@ -215,7 +212,7 @@ export const fffLayer = Layer.effect(
|
|||||||
.sort((a, b) => b.score - a.score || a.path.length - b.path.length)
|
.sort((a, b) => b.score - a.score || a.path.length - b.path.length)
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
const relative = item.path.replaceAll("\\", "/").replace(/\/$/, "")
|
const relative = item.path.replaceAll("\\", "/").replace(/\/$/, "")
|
||||||
return new FileSystem.Entry({
|
return FileSystem.Entry.make({
|
||||||
path: RelativePath.make(relative + (item.type === "directory" ? path.sep : "")),
|
path: RelativePath.make(relative + (item.type === "directory" ? path.sep : "")),
|
||||||
type: item.type,
|
type: item.type,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { randomBytes } from "crypto"
|
import { create as createIdentifier } from "@opencode-ai/schema/identifier"
|
||||||
|
|
||||||
const prefixes = {
|
const prefixes = {
|
||||||
job: "job",
|
job: "job",
|
||||||
@@ -13,12 +13,6 @@ const prefixes = {
|
|||||||
workspace: "wrk",
|
workspace: "wrk",
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
const LENGTH = 26
|
|
||||||
|
|
||||||
// State for monotonic ID generation
|
|
||||||
let lastTimestamp = 0
|
|
||||||
let counter = 0
|
|
||||||
|
|
||||||
export function ascending(prefix: keyof typeof prefixes, given?: string) {
|
export function ascending(prefix: keyof typeof prefixes, given?: string) {
|
||||||
return generateID(prefix, "ascending", given)
|
return generateID(prefix, "ascending", given)
|
||||||
}
|
}
|
||||||
@@ -38,35 +32,8 @@ function generateID(prefix: keyof typeof prefixes, direction: "descending" | "as
|
|||||||
return given
|
return given
|
||||||
}
|
}
|
||||||
|
|
||||||
function randomBase62(length: number): string {
|
|
||||||
const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
||||||
let result = ""
|
|
||||||
const bytes = randomBytes(length)
|
|
||||||
for (let i = 0; i < length; i++) {
|
|
||||||
result += chars[bytes[i] % 62]
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
export function create(prefix: string, direction: "descending" | "ascending", timestamp?: number): string {
|
export function create(prefix: string, direction: "descending" | "ascending", timestamp?: number): string {
|
||||||
const currentTimestamp = timestamp ?? Date.now()
|
return prefix + "_" + createIdentifier(direction === "descending", timestamp)
|
||||||
|
|
||||||
if (currentTimestamp !== lastTimestamp) {
|
|
||||||
lastTimestamp = currentTimestamp
|
|
||||||
counter = 0
|
|
||||||
}
|
|
||||||
counter++
|
|
||||||
|
|
||||||
let now = BigInt(currentTimestamp) * BigInt(0x1000) + BigInt(counter)
|
|
||||||
|
|
||||||
now = direction === "descending" ? ~now : now
|
|
||||||
|
|
||||||
const timeBytes = Buffer.alloc(6)
|
|
||||||
for (let i = 0; i < 6; i++) {
|
|
||||||
timeBytes[i] = Number((now >> BigInt(40 - 8 * i)) & BigInt(0xff))
|
|
||||||
}
|
|
||||||
|
|
||||||
return prefix + "_" + timeBytes.toString("hex") + randomBase62(LENGTH - 12)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Extract timestamp from an ascending ID. Does not work with descending IDs. */
|
/** Extract timestamp from an ascending ID. Does not work with descending IDs. */
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
SynchronizedRef,
|
SynchronizedRef,
|
||||||
Types,
|
Types,
|
||||||
} from "effect"
|
} from "effect"
|
||||||
|
import { Integration } from "@opencode-ai/schema/integration"
|
||||||
import { Credential } from "./credential"
|
import { Credential } from "./credential"
|
||||||
import { IntegrationSchema } from "./integration/schema"
|
import { IntegrationSchema } from "./integration/schema"
|
||||||
import { withStatics } from "./schema"
|
import { withStatics } from "./schema"
|
||||||
@@ -34,66 +35,29 @@ export const AttemptID = Schema.String.pipe(
|
|||||||
)
|
)
|
||||||
export type AttemptID = typeof AttemptID.Type
|
export type AttemptID = typeof AttemptID.Type
|
||||||
|
|
||||||
export const When = Schema.Struct({
|
export const When = Integration.When
|
||||||
key: Schema.String,
|
export type When = Integration.When
|
||||||
op: Schema.Literals(["eq", "neq"]),
|
|
||||||
value: Schema.String,
|
|
||||||
}).annotate({ identifier: "Integration.When" })
|
|
||||||
export type When = typeof When.Type
|
|
||||||
|
|
||||||
export const TextPrompt = Schema.Struct({
|
export const TextPrompt = Integration.TextPrompt
|
||||||
type: Schema.Literal("text"),
|
export type TextPrompt = Integration.TextPrompt
|
||||||
key: Schema.String,
|
|
||||||
message: Schema.String,
|
|
||||||
placeholder: Schema.optional(Schema.String),
|
|
||||||
when: Schema.optional(When),
|
|
||||||
}).annotate({ identifier: "Integration.TextPrompt" })
|
|
||||||
export type TextPrompt = typeof TextPrompt.Type
|
|
||||||
|
|
||||||
export const SelectPrompt = Schema.Struct({
|
export const SelectPrompt = Integration.SelectPrompt
|
||||||
type: Schema.Literal("select"),
|
export type SelectPrompt = Integration.SelectPrompt
|
||||||
key: Schema.String,
|
|
||||||
message: Schema.String,
|
|
||||||
options: Schema.mutable(
|
|
||||||
Schema.Array(
|
|
||||||
Schema.Struct({
|
|
||||||
label: Schema.String,
|
|
||||||
value: Schema.String,
|
|
||||||
hint: Schema.optional(Schema.String),
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
when: Schema.optional(When),
|
|
||||||
}).annotate({ identifier: "Integration.SelectPrompt" })
|
|
||||||
export type SelectPrompt = typeof SelectPrompt.Type
|
|
||||||
|
|
||||||
export const Prompt = Schema.Union([TextPrompt, SelectPrompt]).pipe(Schema.toTaggedUnion("type"))
|
export const Prompt = Integration.Prompt
|
||||||
export type Prompt = typeof Prompt.Type
|
export type Prompt = Integration.Prompt
|
||||||
|
|
||||||
export const OAuthMethod = Schema.Struct({
|
export const OAuthMethod = Integration.OAuthMethod
|
||||||
id: MethodID,
|
export type OAuthMethod = Integration.OAuthMethod
|
||||||
type: Schema.Literal("oauth"),
|
|
||||||
label: Schema.String,
|
|
||||||
prompts: Schema.optional(Schema.mutable(Schema.Array(Prompt))),
|
|
||||||
}).annotate({ identifier: "Integration.OAuthMethod" })
|
|
||||||
export type OAuthMethod = typeof OAuthMethod.Type
|
|
||||||
|
|
||||||
export const KeyMethod = Schema.Struct({
|
export const KeyMethod = Integration.KeyMethod
|
||||||
type: Schema.Literal("key"),
|
export type KeyMethod = Integration.KeyMethod
|
||||||
label: Schema.optional(Schema.String),
|
|
||||||
}).annotate({ identifier: "Integration.KeyMethod" })
|
|
||||||
export type KeyMethod = typeof KeyMethod.Type
|
|
||||||
|
|
||||||
export const EnvMethod = Schema.Struct({
|
export const EnvMethod = Integration.EnvMethod
|
||||||
type: Schema.Literal("env"),
|
export type EnvMethod = Integration.EnvMethod
|
||||||
names: Schema.mutable(Schema.Array(Schema.String)),
|
|
||||||
}).annotate({ identifier: "Integration.EnvMethod" })
|
|
||||||
export type EnvMethod = typeof EnvMethod.Type
|
|
||||||
|
|
||||||
export const Method = Schema.Union([OAuthMethod, KeyMethod, EnvMethod])
|
export const Method = Integration.Method
|
||||||
.pipe(Schema.toTaggedUnion("type"))
|
export type Method = Integration.Method
|
||||||
.annotate({ identifier: "Integration.Method" })
|
|
||||||
export type Method = typeof Method.Type
|
|
||||||
|
|
||||||
export class Info extends Schema.Class<Info>("Integration.Info")({
|
export class Info extends Schema.Class<Info>("Integration.Info")({
|
||||||
id: ID,
|
id: ID,
|
||||||
@@ -102,8 +66,8 @@ export class Info extends Schema.Class<Info>("Integration.Info")({
|
|||||||
connections: Schema.mutable(Schema.Array(IntegrationConnection.Info)),
|
connections: Schema.mutable(Schema.Array(IntegrationConnection.Info)),
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
export const Inputs = Schema.Record(Schema.String, Schema.String).annotate({ identifier: "Integration.Inputs" })
|
export const Inputs = Integration.Inputs
|
||||||
export type Inputs = typeof Inputs.Type
|
export type Inputs = Integration.Inputs
|
||||||
|
|
||||||
export type OAuthAuthorization = {
|
export type OAuthAuthorization = {
|
||||||
readonly url: string
|
readonly url: string
|
||||||
@@ -188,11 +152,8 @@ export const Event = {
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Ref = Schema.Struct({
|
export const Ref = Integration.Ref
|
||||||
id: ID,
|
export type Ref = Integration.Ref
|
||||||
name: Schema.String,
|
|
||||||
}).annotate({ identifier: "Integration.Ref" })
|
|
||||||
export type Ref = typeof Ref.Type
|
|
||||||
|
|
||||||
type Entry = {
|
type Entry = {
|
||||||
ref: Types.DeepMutable<Ref>
|
ref: Types.DeepMutable<Ref>
|
||||||
@@ -464,7 +425,7 @@ export const locationLayer = Layer.effect(
|
|||||||
resolve: Effect.fn("Integration.connection.resolve")(function* (connection) {
|
resolve: Effect.fn("Integration.connection.resolve")(function* (connection) {
|
||||||
if (connection.type === "env") {
|
if (connection.type === "env") {
|
||||||
const key = process.env[connection.name]
|
const key = process.env[connection.name]
|
||||||
return key ? new Credential.Key({ type: "key", key }) : undefined
|
return key ? Credential.Key.make({ type: "key", key }) : undefined
|
||||||
}
|
}
|
||||||
const credential = yield* credentials.get(connection.id)
|
const credential = yield* credentials.get(connection.id)
|
||||||
if (!credential) return undefined
|
if (!credential) return undefined
|
||||||
@@ -489,7 +450,7 @@ export const locationLayer = Layer.effect(
|
|||||||
yield* credentials.create({
|
yield* credentials.create({
|
||||||
integrationID: input.integrationID,
|
integrationID: input.integrationID,
|
||||||
label: input.label,
|
label: input.label,
|
||||||
value: new Credential.Key({ type: "key", key: input.key }),
|
value: Credential.Key.make({ type: "key", key: input.key }),
|
||||||
})
|
})
|
||||||
yield* events.publish(Event.ConnectionUpdated, { integrationID: input.integrationID })
|
yield* events.publish(Event.ConnectionUpdated, { integrationID: input.integrationID })
|
||||||
yield* events.publish(Event.Updated, {})
|
yield* events.publish(Event.Updated, {})
|
||||||
|
|||||||
@@ -1,22 +1,12 @@
|
|||||||
export * as IntegrationConnection from "./connection"
|
export * as IntegrationConnection from "./connection"
|
||||||
|
|
||||||
import { Schema } from "effect"
|
import { Connection } from "@opencode-ai/schema/connection"
|
||||||
import { Credential } from "../credential"
|
|
||||||
|
|
||||||
export const CredentialInfo = Schema.Struct({
|
export const CredentialInfo = Connection.CredentialInfo
|
||||||
type: Schema.Literal("credential"),
|
export type CredentialInfo = Connection.CredentialInfo
|
||||||
id: Credential.ID,
|
|
||||||
label: Schema.String,
|
|
||||||
}).annotate({ identifier: "Connection.CredentialInfo" })
|
|
||||||
export type CredentialInfo = typeof CredentialInfo.Type
|
|
||||||
|
|
||||||
export const EnvInfo = Schema.Struct({
|
export const EnvInfo = Connection.EnvInfo
|
||||||
type: Schema.Literal("env"),
|
export type EnvInfo = Connection.EnvInfo
|
||||||
name: Schema.String,
|
|
||||||
}).annotate({ identifier: "Connection.EnvInfo" })
|
|
||||||
export type EnvInfo = typeof EnvInfo.Type
|
|
||||||
|
|
||||||
export const Info = Schema.Union([CredentialInfo, EnvInfo])
|
export const Info = Connection.Info
|
||||||
.pipe(Schema.toTaggedUnion("type"))
|
export type Info = Connection.Info
|
||||||
.annotate({ identifier: "Connection.Info" })
|
|
||||||
export type Info = typeof Info.Type
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
export * as IntegrationSchema from "./schema"
|
export * as IntegrationSchema from "./schema"
|
||||||
|
|
||||||
import { Schema } from "effect"
|
import { Integration } from "@opencode-ai/schema/integration"
|
||||||
|
|
||||||
export const ID = Schema.String.pipe(Schema.brand("Integration.ID"))
|
export const ID = Integration.ID
|
||||||
export type ID = typeof ID.Type
|
export type ID = Integration.ID
|
||||||
|
|
||||||
export const MethodID = Schema.String.pipe(Schema.brand("Integration.MethodID"))
|
export const MethodID = Integration.MethodID
|
||||||
export type MethodID = typeof MethodID.Type
|
export type MethodID = Integration.MethodID
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
import { Context, Effect, Layer, Schema } from "effect"
|
import { Context, Effect, Layer, Schema } from "effect"
|
||||||
|
import { Ref } from "@opencode-ai/schema/location"
|
||||||
import { Project } from "./project"
|
import { Project } from "./project"
|
||||||
import { AbsolutePath, optionalOmitUndefined } from "./schema"
|
import { AbsolutePath, optionalOmitUndefined } from "./schema"
|
||||||
import { WorkspaceV2 } from "./workspace"
|
import { WorkspaceV2 } from "./workspace"
|
||||||
|
|
||||||
export * as Location from "./location"
|
export * as Location from "./location"
|
||||||
|
|
||||||
export class Ref extends Schema.Class<Ref>("Location.Ref")({
|
export { Ref }
|
||||||
directory: AbsolutePath,
|
|
||||||
workspaceID: Schema.optional(WorkspaceV2.ID).pipe(Schema.withConstructorDefault(Effect.succeed(undefined))),
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class Info extends Schema.Class<Info>("Location.Info")({
|
export class Info extends Schema.Class<Info>("Location.Info")({
|
||||||
directory: AbsolutePath,
|
directory: AbsolutePath,
|
||||||
|
|||||||
@@ -1,34 +1,12 @@
|
|||||||
export * as ModelRequest from "./model-request"
|
export * as ModelRequest from "./model-request"
|
||||||
|
|
||||||
import { Effect, Schema } from "effect"
|
import { ModelRequest } from "@opencode-ai/schema/model-request"
|
||||||
|
|
||||||
export const Generation = Schema.Struct({
|
export const Generation = ModelRequest.Generation
|
||||||
maxTokens: Schema.Number.pipe(Schema.optional),
|
export type Generation = ModelRequest.Generation
|
||||||
temperature: Schema.Number.pipe(Schema.optional),
|
|
||||||
topP: Schema.Number.pipe(Schema.optional),
|
|
||||||
topK: Schema.Number.pipe(Schema.optional),
|
|
||||||
frequencyPenalty: Schema.Number.pipe(Schema.optional),
|
|
||||||
presencePenalty: Schema.Number.pipe(Schema.optional),
|
|
||||||
seed: Schema.Number.pipe(Schema.optional),
|
|
||||||
stop: Schema.String.pipe(Schema.Array, Schema.mutable, Schema.optional),
|
|
||||||
})
|
|
||||||
export type Generation = typeof Generation.Type
|
|
||||||
|
|
||||||
export const Request = Schema.Struct({
|
export const Request = ModelRequest.Request
|
||||||
headers: Schema.Record(Schema.String, Schema.String),
|
export type Request = ModelRequest.Request
|
||||||
body: Schema.Record(Schema.String, Schema.Any),
|
|
||||||
generation: Generation.pipe(
|
|
||||||
Schema.optionalKey,
|
|
||||||
Schema.withConstructorDefault(Effect.succeed({})),
|
|
||||||
Schema.withDecodingDefaultKey(Effect.succeed({})),
|
|
||||||
),
|
|
||||||
options: Schema.Record(Schema.String, Schema.Any).pipe(
|
|
||||||
Schema.optionalKey,
|
|
||||||
Schema.withConstructorDefault(Effect.succeed({})),
|
|
||||||
Schema.withDecodingDefaultKey(Effect.succeed({})),
|
|
||||||
),
|
|
||||||
})
|
|
||||||
export type Request = typeof Request.Type
|
|
||||||
|
|
||||||
interface MutableRequest {
|
interface MutableRequest {
|
||||||
headers: Record<string, string>
|
headers: Record<string, string>
|
||||||
|
|||||||
+14
-103
@@ -1,119 +1,30 @@
|
|||||||
import { Schema, Types } from "effect"
|
import { Types } from "effect"
|
||||||
|
import { Model } from "@opencode-ai/schema/model"
|
||||||
import { ProviderV2 } from "./provider"
|
import { ProviderV2 } from "./provider"
|
||||||
import { ModelRequest } from "./model-request"
|
|
||||||
|
|
||||||
export const ID = Schema.String.pipe(Schema.brand("ModelV2.ID"))
|
export const ID = Model.ID
|
||||||
export type ID = typeof ID.Type
|
export type ID = typeof ID.Type
|
||||||
|
|
||||||
export const VariantID = Schema.String.pipe(Schema.brand("VariantID"))
|
export const VariantID = Model.VariantID
|
||||||
export type VariantID = typeof VariantID.Type
|
export type VariantID = typeof VariantID.Type
|
||||||
|
|
||||||
// Grouping of models, eg claude opus, claude sonnet
|
// Grouping of models, eg claude opus, claude sonnet
|
||||||
export const Family = Schema.String.pipe(Schema.brand("Family"))
|
export const Family = Model.Family
|
||||||
export type Family = typeof Family.Type
|
export type Family = Model.Family
|
||||||
|
|
||||||
export const Capabilities = Schema.Struct({
|
export const Capabilities = Model.Capabilities
|
||||||
tools: Schema.Boolean,
|
export type Capabilities = Model.Capabilities
|
||||||
// mime patterns, image, audio, video/*, text/*
|
|
||||||
input: Schema.String.pipe(Schema.Array, Schema.mutable),
|
|
||||||
output: Schema.String.pipe(Schema.Array, Schema.mutable),
|
|
||||||
})
|
|
||||||
export type Capabilities = typeof Capabilities.Type
|
|
||||||
|
|
||||||
export const Cost = Schema.Struct({
|
export const Cost = Model.Cost
|
||||||
tier: Schema.Struct({
|
|
||||||
type: Schema.Literal("context"),
|
|
||||||
size: Schema.Int,
|
|
||||||
}).pipe(Schema.optional),
|
|
||||||
input: Schema.Finite,
|
|
||||||
output: Schema.Finite,
|
|
||||||
cache: Schema.Struct({
|
|
||||||
read: Schema.Finite,
|
|
||||||
write: Schema.Finite,
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const Ref = Schema.Struct({
|
export const Ref = Model.Ref
|
||||||
id: ID,
|
|
||||||
providerID: ProviderV2.ID,
|
|
||||||
variant: VariantID.pipe(Schema.optional),
|
|
||||||
})
|
|
||||||
export type Ref = typeof Ref.Type
|
export type Ref = typeof Ref.Type
|
||||||
|
|
||||||
export const Api = Schema.Union([
|
export const Api = Model.Api
|
||||||
Schema.Struct({
|
export type Api = Model.Api
|
||||||
id: ID,
|
|
||||||
...ProviderV2.AISDK.fields,
|
|
||||||
}),
|
|
||||||
Schema.Struct({
|
|
||||||
id: ID,
|
|
||||||
...ProviderV2.Native.fields,
|
|
||||||
}),
|
|
||||||
]).pipe(Schema.toTaggedUnion("type"))
|
|
||||||
export type Api = typeof Api.Type
|
|
||||||
|
|
||||||
export class Info extends Schema.Class<Info>("ModelV2.Info")({
|
export const Info = Model.Info
|
||||||
id: ID,
|
export type Info = Model.Info
|
||||||
providerID: ProviderV2.ID,
|
|
||||||
family: Family.pipe(Schema.optional),
|
|
||||||
name: Schema.String,
|
|
||||||
api: Api,
|
|
||||||
capabilities: Capabilities,
|
|
||||||
request: Schema.Struct({
|
|
||||||
...ModelRequest.Request.fields,
|
|
||||||
variant: Schema.String.pipe(Schema.optional),
|
|
||||||
}),
|
|
||||||
variants: Schema.Struct({
|
|
||||||
id: VariantID,
|
|
||||||
...ModelRequest.Request.fields,
|
|
||||||
}).pipe(Schema.Array, Schema.mutable),
|
|
||||||
time: Schema.Struct({
|
|
||||||
released: Schema.Finite,
|
|
||||||
}),
|
|
||||||
cost: Cost.pipe(Schema.Array, Schema.mutable),
|
|
||||||
status: Schema.Literals(["alpha", "beta", "deprecated", "active"]),
|
|
||||||
enabled: Schema.Boolean,
|
|
||||||
limit: Schema.Struct({
|
|
||||||
context: Schema.Int,
|
|
||||||
input: Schema.Int.pipe(Schema.optional),
|
|
||||||
output: Schema.Int,
|
|
||||||
}),
|
|
||||||
}) {
|
|
||||||
static empty(providerID: ProviderV2.ID, modelID: ID): Info {
|
|
||||||
return new Info({
|
|
||||||
id: modelID,
|
|
||||||
providerID,
|
|
||||||
name: modelID,
|
|
||||||
api: {
|
|
||||||
id: modelID,
|
|
||||||
type: "native",
|
|
||||||
settings: {},
|
|
||||||
},
|
|
||||||
capabilities: {
|
|
||||||
tools: false,
|
|
||||||
input: [],
|
|
||||||
output: [],
|
|
||||||
},
|
|
||||||
request: {
|
|
||||||
headers: {},
|
|
||||||
body: {},
|
|
||||||
generation: {},
|
|
||||||
options: {},
|
|
||||||
},
|
|
||||||
variants: [],
|
|
||||||
time: {
|
|
||||||
released: 0,
|
|
||||||
},
|
|
||||||
cost: [],
|
|
||||||
status: "active",
|
|
||||||
enabled: true,
|
|
||||||
limit: {
|
|
||||||
context: 0,
|
|
||||||
output: 0,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type MutableInfo = Omit<Types.DeepMutable<Info>, "api"> & {
|
export type MutableInfo = Omit<Types.DeepMutable<Info>, "api"> & {
|
||||||
api: ProviderV2.MutableApi<Api>
|
api: ProviderV2.MutableApi<Api>
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
export * as PermissionSchema from "./schema"
|
export * as PermissionSchema from "./schema"
|
||||||
|
|
||||||
import { Schema } from "effect"
|
import { Permission } from "@opencode-ai/schema/permission"
|
||||||
|
|
||||||
export const Effect = Schema.Literals(["allow", "deny", "ask"]).annotate({ identifier: "PermissionV2.Effect" })
|
export const Effect = Permission.Effect
|
||||||
export type Effect = typeof Effect.Type
|
export type Effect = Permission.Effect
|
||||||
|
|
||||||
export const Rule = Schema.Struct({
|
export const Rule = Permission.Rule
|
||||||
action: Schema.String,
|
export type Rule = Permission.Rule
|
||||||
resource: Schema.String,
|
|
||||||
effect: Effect,
|
|
||||||
}).annotate({ identifier: "PermissionV2.Rule" })
|
|
||||||
export type Rule = typeof Rule.Type
|
|
||||||
|
|
||||||
export const Ruleset = Schema.mutable(Schema.Array(Rule)).annotate({ identifier: "PermissionV2.Ruleset" })
|
export const Ruleset = Permission.Ruleset
|
||||||
export type Ruleset = typeof Ruleset.Type
|
export type Ruleset = Permission.Ruleset
|
||||||
|
|||||||
@@ -128,12 +128,11 @@ export const make = Effect.fn("PluginHost.make")(function* (plugin: PluginV2.Int
|
|||||||
return {
|
return {
|
||||||
...authorization,
|
...authorization,
|
||||||
callback: authorization.callback.pipe(
|
callback: authorization.callback.pipe(
|
||||||
Effect.map(
|
Effect.map((credential) =>
|
||||||
(credential) =>
|
Credential.OAuth.make({
|
||||||
new Credential.OAuth({
|
...credential,
|
||||||
...credential,
|
methodID: Integration.MethodID.make(credential.methodID),
|
||||||
methodID: Integration.MethodID.make(credential.methodID),
|
}),
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@@ -142,12 +141,11 @@ export const make = Effect.fn("PluginHost.make")(function* (plugin: PluginV2.Int
|
|||||||
...authorization,
|
...authorization,
|
||||||
callback: (code: string) =>
|
callback: (code: string) =>
|
||||||
authorization.callback(code).pipe(
|
authorization.callback(code).pipe(
|
||||||
Effect.map(
|
Effect.map((credential) =>
|
||||||
(credential) =>
|
Credential.OAuth.make({
|
||||||
new Credential.OAuth({
|
...credential,
|
||||||
...credential,
|
methodID: Integration.MethodID.make(credential.methodID),
|
||||||
methodID: Integration.MethodID.make(credential.methodID),
|
}),
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@@ -157,12 +155,11 @@ export const make = Effect.fn("PluginHost.make")(function* (plugin: PluginV2.Int
|
|||||||
? {
|
? {
|
||||||
refresh: (value: Credential.OAuth) =>
|
refresh: (value: Credential.OAuth) =>
|
||||||
refresh(value).pipe(
|
refresh(value).pipe(
|
||||||
Effect.map(
|
Effect.map((next) =>
|
||||||
(next) =>
|
Credential.OAuth.make({
|
||||||
new Credential.OAuth({
|
...next,
|
||||||
...next,
|
methodID: Integration.MethodID.make(next.methodID),
|
||||||
methodID: Integration.MethodID.make(next.methodID),
|
}),
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ function refresh(methodID: Integration.MethodID, value: Pick<Credential.OAuth, "
|
|||||||
}).pipe(
|
}).pipe(
|
||||||
Effect.map((tokens) => {
|
Effect.map((tokens) => {
|
||||||
const next = credential(methodID, tokens)
|
const next = credential(methodID, tokens)
|
||||||
return new Credential.OAuth({ ...next, metadata: next.metadata ?? value.metadata })
|
return Credential.OAuth.make({ ...next, metadata: next.metadata ?? value.metadata })
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -231,7 +231,7 @@ function request<A>(url: string, init: RequestInit) {
|
|||||||
|
|
||||||
function credential(methodID: Integration.MethodID, tokens: TokenResponse) {
|
function credential(methodID: Integration.MethodID, tokens: TokenResponse) {
|
||||||
const accountID = extractAccountID(tokens)
|
const accountID = extractAccountID(tokens)
|
||||||
return new Credential.OAuth({
|
return Credential.OAuth.make({
|
||||||
type: "oauth",
|
type: "oauth",
|
||||||
methodID,
|
methodID,
|
||||||
refresh: tokens.refresh_token,
|
refresh: tokens.refresh_token,
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ function credential(http: HttpClient.HttpClient, server: string, token: typeof T
|
|||||||
{ concurrency: 2 },
|
{ concurrency: 2 },
|
||||||
)
|
)
|
||||||
const org = orgs.toSorted((a, b) => a.name.localeCompare(b.name) || a.id.localeCompare(b.id))[0]
|
const org = orgs.toSorted((a, b) => a.name.localeCompare(b.name) || a.id.localeCompare(b.id))[0]
|
||||||
return new Credential.OAuth({
|
return Credential.OAuth.make({
|
||||||
type: "oauth" as const,
|
type: "oauth" as const,
|
||||||
methodID,
|
methodID,
|
||||||
access: token.access_token,
|
access: token.access_token,
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ export const Plugin = define({
|
|||||||
effect: Effect.fn(function* (ctx) {
|
effect: Effect.fn(function* (ctx) {
|
||||||
yield* ctx.skill.transform((draft) => {
|
yield* ctx.skill.transform((draft) => {
|
||||||
draft.source(
|
draft.source(
|
||||||
new SkillV2.EmbeddedSource({
|
SkillV2.EmbeddedSource.make({
|
||||||
type: "embedded",
|
type: "embedded",
|
||||||
skill: new SkillV2.Info({
|
skill: SkillV2.Info.make({
|
||||||
name: "customize-opencode",
|
name: "customize-opencode",
|
||||||
description:
|
description:
|
||||||
"Use ONLY when the user is editing or creating opencode's own configuration: opencode.json, opencode.jsonc, files under .opencode/, or files under ~/.config/opencode/. Also use when creating or fixing opencode agents, subagents, commands, skills, plugins, MCP servers, or permission rules. Do not use for the user's own application code, or for any project that is not configuring opencode itself.",
|
"Use ONLY when the user is editing or creating opencode's own configuration: opencode.json, opencode.jsonc, files under .opencode/, or files under ~/.config/opencode/. Also use when creating or fixing opencode agents, subagents, commands, skills, plugins, MCP servers, or permission rules. Do not use for the user's own application code, or for any project that is not configuring opencode itself.",
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
export * as ProjectSchema from "./schema"
|
export * as ProjectSchema from "./schema"
|
||||||
|
|
||||||
import { Schema } from "effect"
|
import { Schema } from "effect"
|
||||||
import { AbsolutePath, withStatics } from "../schema"
|
import { Project } from "@opencode-ai/schema/project"
|
||||||
|
import { AbsolutePath } from "../schema"
|
||||||
|
|
||||||
export const ID = Schema.String.pipe(
|
export const ID = Project.ID
|
||||||
Schema.brand("Project.ID"),
|
|
||||||
withStatics((schema) => ({
|
|
||||||
global: schema.make("global"),
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
export type ID = typeof ID.Type
|
export type ID = typeof ID.Type
|
||||||
|
|
||||||
export const Vcs = Schema.Union([
|
export const Vcs = Schema.Union([
|
||||||
|
|||||||
@@ -1,75 +1,25 @@
|
|||||||
export * as ProviderV2 from "./provider"
|
export * as ProviderV2 from "./provider"
|
||||||
|
|
||||||
import { withStatics } from "./schema"
|
import { Types } from "effect"
|
||||||
import { IntegrationSchema } from "./integration/schema"
|
import { Provider } from "@opencode-ai/schema/provider"
|
||||||
import { Schema, Types } from "effect"
|
|
||||||
|
|
||||||
export const ID = Schema.String.pipe(
|
export const ID = Provider.ID
|
||||||
Schema.brand("ProviderV2.ID"),
|
|
||||||
withStatics((schema) => ({
|
|
||||||
// Well-known providers
|
|
||||||
opencode: schema.make("opencode"),
|
|
||||||
anthropic: schema.make("anthropic"),
|
|
||||||
openai: schema.make("openai"),
|
|
||||||
google: schema.make("google"),
|
|
||||||
googleVertex: schema.make("google-vertex"),
|
|
||||||
githubCopilot: schema.make("github-copilot"),
|
|
||||||
amazonBedrock: schema.make("amazon-bedrock"),
|
|
||||||
azure: schema.make("azure"),
|
|
||||||
openrouter: schema.make("openrouter"),
|
|
||||||
mistral: schema.make("mistral"),
|
|
||||||
gitlab: schema.make("gitlab"),
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
export type ID = typeof ID.Type
|
export type ID = typeof ID.Type
|
||||||
|
|
||||||
export const AISDK = Schema.Struct({
|
export const AISDK = Provider.AISDK
|
||||||
type: Schema.Literal("aisdk"),
|
|
||||||
package: Schema.String,
|
|
||||||
url: Schema.String.pipe(Schema.optional),
|
|
||||||
settings: Schema.Record(Schema.String, Schema.Unknown).pipe(Schema.optional),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const Native = Schema.Struct({
|
export const Native = Provider.Native
|
||||||
type: Schema.Literal("native"),
|
|
||||||
url: Schema.String.pipe(Schema.optional),
|
|
||||||
settings: Schema.Record(Schema.String, Schema.Unknown),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const Api = Schema.Union([AISDK, Native]).pipe(Schema.toTaggedUnion("type"))
|
export const Api = Provider.Api
|
||||||
export type Api = typeof Api.Type
|
export type Api = Provider.Api
|
||||||
export type MutableApi<T extends Api = Api> = T extends Api
|
export type MutableApi<T extends Api = Api> = T extends Api
|
||||||
? Omit<Types.DeepMutable<T>, "settings"> & (undefined extends T["settings"] ? { settings?: any } : { settings: any })
|
? Omit<Types.DeepMutable<T>, "settings"> & (undefined extends T["settings"] ? { settings?: any } : { settings: any })
|
||||||
: never
|
: never
|
||||||
|
|
||||||
export const Request = Schema.Struct({
|
export const Request = Provider.Request
|
||||||
headers: Schema.Record(Schema.String, Schema.String),
|
export type Request = Provider.Request
|
||||||
body: Schema.Record(Schema.String, Schema.Any),
|
|
||||||
})
|
|
||||||
export type Request = typeof Request.Type
|
|
||||||
|
|
||||||
export class Info extends Schema.Class<Info>("ProviderV2.Info")({
|
export const Info = Provider.Info
|
||||||
id: ID,
|
export type Info = Provider.Info
|
||||||
integrationID: IntegrationSchema.ID.pipe(Schema.optional),
|
|
||||||
name: Schema.String,
|
|
||||||
disabled: Schema.Boolean.pipe(Schema.optional),
|
|
||||||
api: Api,
|
|
||||||
request: Request,
|
|
||||||
}) {
|
|
||||||
static empty(providerID: ID): Info {
|
|
||||||
return new Info({
|
|
||||||
id: providerID,
|
|
||||||
name: providerID,
|
|
||||||
api: {
|
|
||||||
type: "native",
|
|
||||||
settings: {},
|
|
||||||
},
|
|
||||||
request: {
|
|
||||||
headers: {},
|
|
||||||
body: {},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type MutableInfo = Omit<Types.DeepMutable<Info>, "api"> & { api: MutableApi }
|
export type MutableInfo = Omit<Types.DeepMutable<Info>, "api"> & { api: MutableApi }
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
export * as Reference from "./reference"
|
export * as Reference from "./reference"
|
||||||
|
|
||||||
import { Context, Effect, Layer, Schema, Scope, Types } from "effect"
|
import { Context, Effect, Layer, Schema, Scope, Types } from "effect"
|
||||||
|
import { Reference } from "@opencode-ai/schema/reference"
|
||||||
import { Global } from "./global"
|
import { Global } from "./global"
|
||||||
import { EventV2 } from "./event"
|
import { EventV2 } from "./event"
|
||||||
import { Repository } from "./repository"
|
import { Repository } from "./repository"
|
||||||
@@ -8,23 +9,14 @@ import { RepositoryCache } from "./repository-cache"
|
|||||||
import { AbsolutePath } from "./schema"
|
import { AbsolutePath } from "./schema"
|
||||||
import { State } from "./state"
|
import { State } from "./state"
|
||||||
|
|
||||||
export class LocalSource extends Schema.Class<LocalSource>("Reference.LocalSource")({
|
export const LocalSource = Reference.LocalSource
|
||||||
type: Schema.Literal("local"),
|
export type LocalSource = Reference.LocalSource
|
||||||
path: AbsolutePath,
|
|
||||||
description: Schema.String.pipe(Schema.optional),
|
|
||||||
hidden: Schema.Boolean.pipe(Schema.optional),
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class GitSource extends Schema.Class<GitSource>("Reference.GitSource")({
|
export const GitSource = Reference.GitSource
|
||||||
type: Schema.Literal("git"),
|
export type GitSource = Reference.GitSource
|
||||||
repository: Schema.String,
|
|
||||||
branch: Schema.String.pipe(Schema.optional),
|
|
||||||
description: Schema.String.pipe(Schema.optional),
|
|
||||||
hidden: Schema.Boolean.pipe(Schema.optional),
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export const Source = Schema.Union([LocalSource, GitSource]).pipe(Schema.toTaggedUnion("type"))
|
export const Source = Reference.Source
|
||||||
export type Source = typeof Source.Type
|
export type Source = Reference.Source
|
||||||
|
|
||||||
export const Event = {
|
export const Event = {
|
||||||
Updated: EventV2.define({ type: "reference.updated", schema: {} }),
|
Updated: EventV2.define({ type: "reference.updated", schema: {} }),
|
||||||
|
|||||||
@@ -176,12 +176,11 @@ export const layer = Layer.effect(
|
|||||||
),
|
),
|
||||||
}).pipe(
|
}).pipe(
|
||||||
Effect.map((result) =>
|
Effect.map((result) =>
|
||||||
result.items.map(
|
result.items.map((relative) =>
|
||||||
(relative) =>
|
Entry.make({
|
||||||
new Entry({
|
path: RelativePath.make(relative),
|
||||||
path: RelativePath.make(relative),
|
type: "file",
|
||||||
type: "file",
|
}),
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Effect.catchTag("Ripgrep.InvalidPatternError", (cause) => Effect.fail(failure(cause.message, cause))),
|
Effect.catchTag("Ripgrep.InvalidPatternError", (cause) => Effect.fail(failure(cause.message, cause))),
|
||||||
@@ -206,7 +205,7 @@ export const layer = Layer.effect(
|
|||||||
.replace(/^[\\/]+/u, "")
|
.replace(/^[\\/]+/u, "")
|
||||||
.replaceAll("\\", "/")
|
.replaceAll("\\", "/")
|
||||||
return Effect.succeed(
|
return Effect.succeed(
|
||||||
new Entry({
|
Entry.make({
|
||||||
path: RelativePath.make(relative),
|
path: RelativePath.make(relative),
|
||||||
type: "file",
|
type: "file",
|
||||||
}),
|
}),
|
||||||
@@ -259,8 +258,8 @@ export const layer = Layer.effect(
|
|||||||
.replace(/^(?:\.[\\/])+/u, "")
|
.replace(/^(?:\.[\\/])+/u, "")
|
||||||
.replace(/^[\\/]+/u, "")
|
.replace(/^[\\/]+/u, "")
|
||||||
.replaceAll("\\", "/")
|
.replaceAll("\\", "/")
|
||||||
return new Match({
|
return Match.make({
|
||||||
entry: new Entry({
|
entry: Entry.make({
|
||||||
path: RelativePath.make(relative),
|
path: RelativePath.make(relative),
|
||||||
type: "file",
|
type: "file",
|
||||||
}),
|
}),
|
||||||
|
|||||||
+18
-58
@@ -1,48 +1,24 @@
|
|||||||
import { Option, Schema, SchemaGetter } from "effect"
|
import { Schema } from "effect"
|
||||||
import { Hash } from "./util/hash"
|
import {
|
||||||
|
AbsolutePath,
|
||||||
|
DateTimeUtcFromMillis,
|
||||||
|
NonNegativeInt,
|
||||||
|
optionalOmitUndefined,
|
||||||
|
PositiveInt,
|
||||||
|
RelativePath,
|
||||||
|
withStatics,
|
||||||
|
} from "@opencode-ai/schema/schema"
|
||||||
|
|
||||||
export type ExternalID = {
|
export {
|
||||||
readonly namespace: string
|
AbsolutePath,
|
||||||
readonly key: string
|
DateTimeUtcFromMillis,
|
||||||
|
NonNegativeInt,
|
||||||
|
optionalOmitUndefined,
|
||||||
|
PositiveInt,
|
||||||
|
RelativePath,
|
||||||
|
withStatics,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const externalID = (prefix: string, input: ExternalID) =>
|
|
||||||
`${prefix}_${Hash.sha256(JSON.stringify([input.namespace, input.key]))}`
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Integer greater than zero.
|
|
||||||
*/
|
|
||||||
export const PositiveInt = Schema.Int.check(Schema.isGreaterThan(0))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Integer greater than or equal to zero.
|
|
||||||
*/
|
|
||||||
export const NonNegativeInt = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Relative file path (e.g., `src/components/Button.tsx`).
|
|
||||||
*/
|
|
||||||
export const RelativePath = Schema.String.pipe(Schema.brand("RelativePath"))
|
|
||||||
export type RelativePath = Schema.Schema.Type<typeof RelativePath>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Absolute file path (e.g., `/home/user/projects/myapp/src/main.ts`).
|
|
||||||
*/
|
|
||||||
export const AbsolutePath = Schema.String.pipe(Schema.brand("AbsolutePath"))
|
|
||||||
export type AbsolutePath = Schema.Schema.Type<typeof AbsolutePath>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optional public JSON field that can hold explicit `undefined` on the type
|
|
||||||
* side but encodes it as an omitted key, matching legacy `JSON.stringify`.
|
|
||||||
*/
|
|
||||||
export const optionalOmitUndefined = <S extends Schema.Top>(schema: S) =>
|
|
||||||
Schema.optionalKey(schema).pipe(
|
|
||||||
Schema.decodeTo(Schema.optional(schema), {
|
|
||||||
decode: SchemaGetter.passthrough({ strict: false }),
|
|
||||||
encode: SchemaGetter.transformOptional(Option.filter((value) => value !== undefined)),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Strip `readonly` from a nested type. Stand-in for `effect`'s `Types.DeepMutable`
|
* Strip `readonly` from a nested type. Stand-in for `effect`'s `Types.DeepMutable`
|
||||||
* until `effect:core/x228my` ("Types.DeepMutable widens unknown to `{}`") lands.
|
* until `effect:core/x228my` ("Types.DeepMutable widens unknown to `{}`") lands.
|
||||||
@@ -71,22 +47,6 @@ export type DeepMutable<T> = T extends string | number | boolean | bigint | symb
|
|||||||
? { -readonly [K in keyof T]: DeepMutable<T[K]> }
|
? { -readonly [K in keyof T]: DeepMutable<T[K]> }
|
||||||
: T
|
: T
|
||||||
|
|
||||||
/**
|
|
||||||
* Attach static methods to a schema object. Designed to be used with `.pipe()`:
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* export const Foo = fooSchema.pipe(
|
|
||||||
* withStatics((schema) => ({
|
|
||||||
* zero: schema.make(0),
|
|
||||||
* from: Schema.decodeUnknownOption(schema),
|
|
||||||
* }))
|
|
||||||
* )
|
|
||||||
*/
|
|
||||||
export const withStatics =
|
|
||||||
<S extends object, M extends Record<string, unknown>>(methods: (schema: S) => M) =>
|
|
||||||
(schema: S): S & M =>
|
|
||||||
Object.assign(schema, methods(schema))
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Nominal wrapper for scalar types. The class itself is a valid schema —
|
* Nominal wrapper for scalar types. The class itself is a valid schema —
|
||||||
* pass it directly to `Schema.decode`, `Schema.decodeEffect`, etc.
|
* pass it directly to `Schema.decode`, `Schema.decodeEffect`, etc.
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ export * as SessionV2 from "./session"
|
|||||||
export * from "./session/schema"
|
export * from "./session/schema"
|
||||||
|
|
||||||
import { DateTime, Effect, Layer, Schema, Context, Stream } from "effect"
|
import { DateTime, Effect, Layer, Schema, Context, Stream } from "effect"
|
||||||
|
import { ListAnchor } from "@opencode-ai/schema/session"
|
||||||
import { and, asc, desc, eq, gt, like, lt, or, type SQL } from "drizzle-orm"
|
import { and, asc, desc, eq, gt, like, lt, or, type SQL } from "drizzle-orm"
|
||||||
import { ProjectV2 } from "./project"
|
import { ProjectV2 } from "./project"
|
||||||
import { WorkspaceV2 } from "./workspace"
|
import { WorkspaceV2 } from "./workspace"
|
||||||
@@ -38,12 +39,7 @@ import { SessionInput } from "./session/input"
|
|||||||
// - by subpath
|
// - by subpath
|
||||||
// - by workspace (home is special)
|
// - by workspace (home is special)
|
||||||
|
|
||||||
export const ListAnchor = Schema.Struct({
|
export { ListAnchor }
|
||||||
id: SessionSchema.ID,
|
|
||||||
time: Schema.Finite,
|
|
||||||
direction: Schema.Literals(["previous", "next"]),
|
|
||||||
})
|
|
||||||
export type ListAnchor = typeof ListAnchor.Type
|
|
||||||
|
|
||||||
const ListInputBase = {
|
const ListInputBase = {
|
||||||
workspaceID: WorkspaceV2.ID.pipe(Schema.optional),
|
workspaceID: WorkspaceV2.ID.pipe(Schema.optional),
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { Schema } from "effect"
|
import { Schema } from "effect"
|
||||||
import { ProviderMetadata, ToolContent } from "@opencode-ai/llm"
|
import { ProviderMetadata, ToolContent } from "@opencode-ai/schema/llm"
|
||||||
|
import { Delivery } from "@opencode-ai/schema/session-delivery"
|
||||||
import { EventV2 } from "../event"
|
import { EventV2 } from "../event"
|
||||||
import { ModelV2 } from "../model"
|
import { ModelV2 } from "../model"
|
||||||
import { NonNegativeInt } from "../schema"
|
import { DateTimeUtcFromMillis, NonNegativeInt, RelativePath } from "../schema"
|
||||||
import { V2Schema } from "../v2-schema"
|
|
||||||
import { FileAttachment, Prompt } from "./prompt"
|
import { FileAttachment, Prompt } from "./prompt"
|
||||||
import { SessionSchema } from "./schema"
|
import { SessionSchema } from "./schema"
|
||||||
import { Location } from "../location"
|
import { Location } from "../location"
|
||||||
import { RelativePath } from "../schema"
|
|
||||||
import { SessionMessageID } from "./message-id"
|
import { SessionMessageID } from "./message-id"
|
||||||
|
import { SessionMessage } from "./message"
|
||||||
|
|
||||||
export { FileAttachment }
|
export { FileAttachment }
|
||||||
|
|
||||||
@@ -22,14 +22,14 @@ export const Source = Schema.Struct({
|
|||||||
export type Source = typeof Source.Type
|
export type Source = typeof Source.Type
|
||||||
|
|
||||||
const Base = {
|
const Base = {
|
||||||
timestamp: V2Schema.DateTimeUtcFromMillis,
|
timestamp: DateTimeUtcFromMillis,
|
||||||
sessionID: SessionSchema.ID,
|
sessionID: SessionSchema.ID,
|
||||||
}
|
}
|
||||||
const PromptFields = {
|
const PromptFields = {
|
||||||
...Base,
|
...Base,
|
||||||
messageID: SessionMessageID.ID,
|
messageID: SessionMessageID.ID,
|
||||||
prompt: Prompt,
|
prompt: Prompt,
|
||||||
delivery: Schema.Literals(["steer", "queue"]),
|
delivery: Delivery,
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
@@ -45,13 +45,8 @@ const stepSettlementOptions = {
|
|||||||
},
|
},
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export const UnknownError = Schema.Struct({
|
export const UnknownError = SessionMessage.UnknownError
|
||||||
type: Schema.Literal("unknown"),
|
export type UnknownError = SessionMessage.UnknownError
|
||||||
message: Schema.String,
|
|
||||||
}).annotate({
|
|
||||||
identifier: "Session.Error.Unknown",
|
|
||||||
})
|
|
||||||
export type UnknownError = typeof UnknownError.Type
|
|
||||||
|
|
||||||
export const AgentSwitched = EventV2.define({
|
export const AgentSwitched = EventV2.define({
|
||||||
type: "session.next.agent.switched",
|
type: "session.next.agent.switched",
|
||||||
|
|||||||
@@ -2,10 +2,9 @@ export * as SessionInput from "./input"
|
|||||||
|
|
||||||
import { and, asc, eq, isNull, lte } from "drizzle-orm"
|
import { and, asc, eq, isNull, lte } from "drizzle-orm"
|
||||||
import { DateTime, Effect, Schema } from "effect"
|
import { DateTime, Effect, Schema } from "effect"
|
||||||
|
import { Admitted, Delivery } from "@opencode-ai/schema/session-input"
|
||||||
import type { Database } from "../database/database"
|
import type { Database } from "../database/database"
|
||||||
import type { EventV2 } from "../event"
|
import type { EventV2 } from "../event"
|
||||||
import { NonNegativeInt } from "../schema"
|
|
||||||
import { V2Schema } from "../v2-schema"
|
|
||||||
import { SessionEvent } from "./event"
|
import { SessionEvent } from "./event"
|
||||||
import { SessionMessage } from "./message"
|
import { SessionMessage } from "./message"
|
||||||
import { Prompt } from "./prompt"
|
import { Prompt } from "./prompt"
|
||||||
@@ -14,24 +13,13 @@ import { SessionInputTable, SessionMessageTable } from "./sql"
|
|||||||
|
|
||||||
type DatabaseService = Database.Interface["db"]
|
type DatabaseService = Database.Interface["db"]
|
||||||
|
|
||||||
export const Delivery = Schema.Literals(["steer", "queue"])
|
export { Admitted, Delivery }
|
||||||
export type Delivery = typeof Delivery.Type
|
|
||||||
|
|
||||||
export class Admitted extends Schema.Class<Admitted>("SessionInput.Admitted")({
|
|
||||||
admittedSeq: NonNegativeInt,
|
|
||||||
id: SessionMessage.ID,
|
|
||||||
sessionID: SessionSchema.ID,
|
|
||||||
prompt: Prompt,
|
|
||||||
delivery: Delivery,
|
|
||||||
timeCreated: V2Schema.DateTimeUtcFromMillis,
|
|
||||||
promotedSeq: NonNegativeInt.pipe(Schema.optional),
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
const decodePrompt = Schema.decodeUnknownSync(Prompt)
|
const decodePrompt = Schema.decodeUnknownSync(Prompt)
|
||||||
const encodePrompt = Schema.encodeSync(Prompt)
|
const encodePrompt = Schema.encodeSync(Prompt)
|
||||||
|
|
||||||
const fromRow = (row: typeof SessionInputTable.$inferSelect): Admitted =>
|
const fromRow = (row: typeof SessionInputTable.$inferSelect): Admitted =>
|
||||||
new Admitted({
|
Admitted.make({
|
||||||
admittedSeq: row.admitted_seq,
|
admittedSeq: row.admitted_seq,
|
||||||
id: SessionMessage.ID.make(row.id),
|
id: SessionMessage.ID.make(row.id),
|
||||||
sessionID: SessionSchema.ID.make(row.session_id),
|
sessionID: SessionSchema.ID.make(row.session_id),
|
||||||
@@ -76,7 +64,7 @@ export const admit = Effect.fn("SessionInput.admit")(function* (
|
|||||||
event.durable === undefined
|
event.durable === undefined
|
||||||
? Effect.die("Prompt admission event is missing aggregate sequence")
|
? Effect.die("Prompt admission event is missing aggregate sequence")
|
||||||
: Effect.succeed(
|
: Effect.succeed(
|
||||||
new Admitted({
|
Admitted.make({
|
||||||
admittedSeq: event.durable.seq,
|
admittedSeq: event.durable.seq,
|
||||||
id: input.id,
|
id: input.id,
|
||||||
sessionID: input.sessionID,
|
sessionID: input.sessionID,
|
||||||
|
|||||||
@@ -1,13 +1,2 @@
|
|||||||
export * as SessionMessageID from "./message-id"
|
export * as SessionMessageID from "./message-id"
|
||||||
|
export { ID } from "@opencode-ai/schema/session-message-id"
|
||||||
import { Schema } from "effect"
|
|
||||||
import { withStatics } from "../schema"
|
|
||||||
import { Identifier } from "../util/identifier"
|
|
||||||
|
|
||||||
export const ID = Schema.String.check(Schema.isStartsWith("msg_")).pipe(
|
|
||||||
Schema.brand("Session.Message.ID"),
|
|
||||||
withStatics((schema) => ({
|
|
||||||
create: () => schema.make("msg_" + Identifier.ascending()),
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
export type ID = typeof ID.Type
|
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) {
|
|||||||
yield* SessionEvent.All.match(event, {
|
yield* SessionEvent.All.match(event, {
|
||||||
"session.next.agent.switched": (event) => {
|
"session.next.agent.switched": (event) => {
|
||||||
return adapter.appendMessage(
|
return adapter.appendMessage(
|
||||||
new SessionMessage.AgentSwitched({
|
SessionMessage.AgentSwitched.make({
|
||||||
id: event.data.messageID,
|
id: event.data.messageID,
|
||||||
type: "agent-switched",
|
type: "agent-switched",
|
||||||
metadata: event.metadata,
|
metadata: event.metadata,
|
||||||
@@ -113,7 +113,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) {
|
|||||||
},
|
},
|
||||||
"session.next.model.switched": (event) => {
|
"session.next.model.switched": (event) => {
|
||||||
return adapter.appendMessage(
|
return adapter.appendMessage(
|
||||||
new SessionMessage.ModelSwitched({
|
SessionMessage.ModelSwitched.make({
|
||||||
id: event.data.messageID,
|
id: event.data.messageID,
|
||||||
type: "model-switched",
|
type: "model-switched",
|
||||||
metadata: event.metadata,
|
metadata: event.metadata,
|
||||||
@@ -125,7 +125,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) {
|
|||||||
"session.next.moved": () => Effect.void,
|
"session.next.moved": () => Effect.void,
|
||||||
"session.next.prompted": (event) => {
|
"session.next.prompted": (event) => {
|
||||||
return adapter.appendMessage(
|
return adapter.appendMessage(
|
||||||
new SessionMessage.User({
|
SessionMessage.User.make({
|
||||||
id: event.data.messageID,
|
id: event.data.messageID,
|
||||||
type: "user",
|
type: "user",
|
||||||
metadata: event.metadata,
|
metadata: event.metadata,
|
||||||
@@ -139,7 +139,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) {
|
|||||||
"session.next.prompt.admitted": () => Effect.void,
|
"session.next.prompt.admitted": () => Effect.void,
|
||||||
"session.next.context.updated": (event) =>
|
"session.next.context.updated": (event) =>
|
||||||
adapter.appendMessage(
|
adapter.appendMessage(
|
||||||
new SessionMessage.System({
|
SessionMessage.System.make({
|
||||||
id: event.data.messageID,
|
id: event.data.messageID,
|
||||||
type: "system",
|
type: "system",
|
||||||
text: event.data.text,
|
text: event.data.text,
|
||||||
@@ -148,7 +148,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) {
|
|||||||
),
|
),
|
||||||
"session.next.synthetic": (event) => {
|
"session.next.synthetic": (event) => {
|
||||||
return adapter.appendMessage(
|
return adapter.appendMessage(
|
||||||
new SessionMessage.Synthetic({
|
SessionMessage.Synthetic.make({
|
||||||
sessionID: event.data.sessionID,
|
sessionID: event.data.sessionID,
|
||||||
text: event.data.text,
|
text: event.data.text,
|
||||||
id: event.data.messageID,
|
id: event.data.messageID,
|
||||||
@@ -159,7 +159,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) {
|
|||||||
},
|
},
|
||||||
"session.next.shell.started": (event) => {
|
"session.next.shell.started": (event) => {
|
||||||
return adapter.appendMessage(
|
return adapter.appendMessage(
|
||||||
new SessionMessage.Shell({
|
SessionMessage.Shell.make({
|
||||||
id: event.data.messageID,
|
id: event.data.messageID,
|
||||||
type: "shell",
|
type: "shell",
|
||||||
metadata: event.metadata,
|
metadata: event.metadata,
|
||||||
@@ -194,7 +194,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
yield* adapter.appendMessage(
|
yield* adapter.appendMessage(
|
||||||
new SessionMessage.Assistant({
|
SessionMessage.Assistant.make({
|
||||||
id: event.data.assistantMessageID,
|
id: event.data.assistantMessageID,
|
||||||
type: "assistant",
|
type: "assistant",
|
||||||
agent: event.data.agent,
|
agent: event.data.agent,
|
||||||
@@ -225,7 +225,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) {
|
|||||||
"session.next.text.started": (event) => {
|
"session.next.text.started": (event) => {
|
||||||
return updateOwnedAssistant(event.data.assistantMessageID, (draft) => {
|
return updateOwnedAssistant(event.data.assistantMessageID, (draft) => {
|
||||||
draft.content.push(
|
draft.content.push(
|
||||||
castDraft(new SessionMessage.AssistantText({ type: "text", id: event.data.textID, text: "" })),
|
castDraft(SessionMessage.AssistantText.make({ type: "text", id: event.data.textID, text: "" })),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -245,12 +245,12 @@ export function update(adapter: Adapter, event: SessionEvent.Event) {
|
|||||||
return updateOwnedAssistant(event.data.assistantMessageID, (draft) => {
|
return updateOwnedAssistant(event.data.assistantMessageID, (draft) => {
|
||||||
draft.content.push(
|
draft.content.push(
|
||||||
castDraft(
|
castDraft(
|
||||||
new SessionMessage.AssistantTool({
|
SessionMessage.AssistantTool.make({
|
||||||
type: "tool",
|
type: "tool",
|
||||||
id: event.data.callID,
|
id: event.data.callID,
|
||||||
name: event.data.name,
|
name: event.data.name,
|
||||||
time: { created: event.data.timestamp },
|
time: { created: event.data.timestamp },
|
||||||
state: new SessionMessage.ToolStatePending({ status: "pending", input: "" }),
|
state: SessionMessage.ToolStatePending.make({ status: "pending", input: "" }),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -270,7 +270,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) {
|
|||||||
match.provider = event.data.provider
|
match.provider = event.data.provider
|
||||||
match.time.ran = event.data.timestamp
|
match.time.ran = event.data.timestamp
|
||||||
match.state = castDraft(
|
match.state = castDraft(
|
||||||
new SessionMessage.ToolStateRunning({
|
SessionMessage.ToolStateRunning.make({
|
||||||
status: "running",
|
status: "running",
|
||||||
input: event.data.input,
|
input: event.data.input,
|
||||||
structured: {},
|
structured: {},
|
||||||
@@ -300,7 +300,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) {
|
|||||||
}
|
}
|
||||||
match.time.completed = event.data.timestamp
|
match.time.completed = event.data.timestamp
|
||||||
match.state = castDraft(
|
match.state = castDraft(
|
||||||
new SessionMessage.ToolStateCompleted({
|
SessionMessage.ToolStateCompleted.make({
|
||||||
status: "completed",
|
status: "completed",
|
||||||
input: match.state.input,
|
input: match.state.input,
|
||||||
structured: event.data.structured,
|
structured: event.data.structured,
|
||||||
@@ -323,7 +323,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) {
|
|||||||
}
|
}
|
||||||
match.time.completed = event.data.timestamp
|
match.time.completed = event.data.timestamp
|
||||||
match.state = castDraft(
|
match.state = castDraft(
|
||||||
new SessionMessage.ToolStateError({
|
SessionMessage.ToolStateError.make({
|
||||||
status: "error",
|
status: "error",
|
||||||
error: event.data.error,
|
error: event.data.error,
|
||||||
input: typeof match.state.input === "string" ? {} : match.state.input,
|
input: typeof match.state.input === "string" ? {} : match.state.input,
|
||||||
@@ -339,7 +339,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) {
|
|||||||
return updateOwnedAssistant(event.data.assistantMessageID, (draft) => {
|
return updateOwnedAssistant(event.data.assistantMessageID, (draft) => {
|
||||||
draft.content.push(
|
draft.content.push(
|
||||||
castDraft(
|
castDraft(
|
||||||
new SessionMessage.AssistantReasoning({
|
SessionMessage.AssistantReasoning.make({
|
||||||
type: "reasoning",
|
type: "reasoning",
|
||||||
id: event.data.reasoningID,
|
id: event.data.reasoningID,
|
||||||
text: "",
|
text: "",
|
||||||
@@ -369,7 +369,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) {
|
|||||||
"session.next.compaction.delta": () => Effect.void,
|
"session.next.compaction.delta": () => Effect.void,
|
||||||
"session.next.compaction.ended": (event) => {
|
"session.next.compaction.ended": (event) => {
|
||||||
return adapter.appendMessage(
|
return adapter.appendMessage(
|
||||||
new SessionMessage.Compaction({
|
SessionMessage.Compaction.make({
|
||||||
id: event.data.messageID,
|
id: event.data.messageID,
|
||||||
type: "compaction",
|
type: "compaction",
|
||||||
metadata: event.metadata,
|
metadata: event.metadata,
|
||||||
|
|||||||
@@ -1,193 +1,2 @@
|
|||||||
export * as SessionMessage from "./message"
|
export * as SessionMessage from "./message"
|
||||||
|
export * from "@opencode-ai/schema/session-message"
|
||||||
import { Schema } from "effect"
|
|
||||||
import { ProviderMetadata, ToolContent } from "@opencode-ai/llm"
|
|
||||||
import { ModelV2 } from "../model"
|
|
||||||
import { V2Schema } from "../v2-schema"
|
|
||||||
import { SessionEvent } from "./event"
|
|
||||||
import { Prompt } from "./prompt"
|
|
||||||
import { SessionMessageID } from "./message-id"
|
|
||||||
|
|
||||||
export const ID = SessionMessageID.ID
|
|
||||||
export type ID = typeof ID.Type
|
|
||||||
|
|
||||||
const Base = {
|
|
||||||
id: ID,
|
|
||||||
metadata: Schema.Record(Schema.String, Schema.Unknown).pipe(Schema.optional),
|
|
||||||
time: Schema.Struct({
|
|
||||||
created: V2Schema.DateTimeUtcFromMillis,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
|
|
||||||
export class AgentSwitched extends Schema.Class<AgentSwitched>("Session.Message.AgentSwitched")({
|
|
||||||
...Base,
|
|
||||||
type: Schema.Literal("agent-switched"),
|
|
||||||
agent: SessionEvent.AgentSwitched.data.fields.agent,
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class ModelSwitched extends Schema.Class<ModelSwitched>("Session.Message.ModelSwitched")({
|
|
||||||
...Base,
|
|
||||||
type: Schema.Literal("model-switched"),
|
|
||||||
model: ModelV2.Ref,
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class User extends Schema.Class<User>("Session.Message.User")({
|
|
||||||
...Base,
|
|
||||||
text: Prompt.fields.text,
|
|
||||||
files: Prompt.fields.files,
|
|
||||||
agents: Prompt.fields.agents,
|
|
||||||
type: Schema.Literal("user"),
|
|
||||||
time: Schema.Struct({
|
|
||||||
created: V2Schema.DateTimeUtcFromMillis,
|
|
||||||
}),
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class Synthetic extends Schema.Class<Synthetic>("Session.Message.Synthetic")({
|
|
||||||
...Base,
|
|
||||||
sessionID: SessionEvent.Synthetic.data.fields.sessionID,
|
|
||||||
text: SessionEvent.Synthetic.data.fields.text,
|
|
||||||
type: Schema.Literal("synthetic"),
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class System extends Schema.Class<System>("Session.Message.System")({
|
|
||||||
...Base,
|
|
||||||
type: Schema.Literal("system"),
|
|
||||||
text: SessionEvent.ContextUpdated.data.fields.text,
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class Shell extends Schema.Class<Shell>("Session.Message.Shell")({
|
|
||||||
...Base,
|
|
||||||
type: Schema.Literal("shell"),
|
|
||||||
callID: SessionEvent.Shell.Started.data.fields.callID,
|
|
||||||
command: SessionEvent.Shell.Started.data.fields.command,
|
|
||||||
output: Schema.String,
|
|
||||||
time: Schema.Struct({
|
|
||||||
created: V2Schema.DateTimeUtcFromMillis,
|
|
||||||
completed: V2Schema.DateTimeUtcFromMillis.pipe(Schema.optional),
|
|
||||||
}),
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class ToolStatePending extends Schema.Class<ToolStatePending>("Session.Message.ToolState.Pending")({
|
|
||||||
status: Schema.Literal("pending"),
|
|
||||||
input: Schema.String,
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class ToolStateRunning extends Schema.Class<ToolStateRunning>("Session.Message.ToolState.Running")({
|
|
||||||
status: Schema.Literal("running"),
|
|
||||||
input: Schema.Record(Schema.String, Schema.Unknown),
|
|
||||||
structured: Schema.Record(Schema.String, Schema.Any),
|
|
||||||
content: ToolContent.pipe(Schema.Array),
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class ToolStateCompleted extends Schema.Class<ToolStateCompleted>("Session.Message.ToolState.Completed")({
|
|
||||||
status: Schema.Literal("completed"),
|
|
||||||
input: Schema.Record(Schema.String, Schema.Unknown),
|
|
||||||
attachments: SessionEvent.FileAttachment.pipe(Schema.Array, Schema.optional),
|
|
||||||
content: ToolContent.pipe(Schema.Array),
|
|
||||||
outputPaths: SessionEvent.Tool.Success.data.fields.outputPaths,
|
|
||||||
structured: Schema.Record(Schema.String, Schema.Any),
|
|
||||||
result: SessionEvent.Tool.Success.data.fields.result,
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class ToolStateError extends Schema.Class<ToolStateError>("Session.Message.ToolState.Error")({
|
|
||||||
status: Schema.Literal("error"),
|
|
||||||
input: Schema.Record(Schema.String, Schema.Unknown),
|
|
||||||
content: ToolContent.pipe(Schema.Array),
|
|
||||||
structured: Schema.Record(Schema.String, Schema.Any),
|
|
||||||
error: SessionEvent.UnknownError,
|
|
||||||
result: SessionEvent.Tool.Failed.data.fields.result,
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export const ToolState = Schema.Union([ToolStatePending, ToolStateRunning, ToolStateCompleted, ToolStateError]).pipe(
|
|
||||||
Schema.toTaggedUnion("status"),
|
|
||||||
)
|
|
||||||
export type ToolState = Schema.Schema.Type<typeof ToolState>
|
|
||||||
|
|
||||||
export class AssistantTool extends Schema.Class<AssistantTool>("Session.Message.Assistant.Tool")({
|
|
||||||
type: Schema.Literal("tool"),
|
|
||||||
id: Schema.String,
|
|
||||||
name: Schema.String,
|
|
||||||
provider: Schema.Struct({
|
|
||||||
executed: Schema.Boolean,
|
|
||||||
metadata: ProviderMetadata.pipe(Schema.optional),
|
|
||||||
resultMetadata: ProviderMetadata.pipe(Schema.optional),
|
|
||||||
}).pipe(Schema.optional),
|
|
||||||
state: ToolState,
|
|
||||||
time: Schema.Struct({
|
|
||||||
created: V2Schema.DateTimeUtcFromMillis,
|
|
||||||
ran: V2Schema.DateTimeUtcFromMillis.pipe(Schema.optional),
|
|
||||||
completed: V2Schema.DateTimeUtcFromMillis.pipe(Schema.optional),
|
|
||||||
pruned: V2Schema.DateTimeUtcFromMillis.pipe(Schema.optional),
|
|
||||||
}),
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class AssistantText extends Schema.Class<AssistantText>("Session.Message.Assistant.Text")({
|
|
||||||
type: Schema.Literal("text"),
|
|
||||||
id: Schema.String,
|
|
||||||
text: Schema.String,
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class AssistantReasoning extends Schema.Class<AssistantReasoning>("Session.Message.Assistant.Reasoning")({
|
|
||||||
type: Schema.Literal("reasoning"),
|
|
||||||
id: Schema.String,
|
|
||||||
text: Schema.String,
|
|
||||||
providerMetadata: ProviderMetadata.pipe(Schema.optional),
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export const AssistantContent = Schema.Union([AssistantText, AssistantReasoning, AssistantTool]).pipe(
|
|
||||||
Schema.toTaggedUnion("type"),
|
|
||||||
)
|
|
||||||
export type AssistantContent = Schema.Schema.Type<typeof AssistantContent>
|
|
||||||
|
|
||||||
export class Assistant extends Schema.Class<Assistant>("Session.Message.Assistant")({
|
|
||||||
...Base,
|
|
||||||
type: Schema.Literal("assistant"),
|
|
||||||
agent: Schema.String,
|
|
||||||
model: SessionEvent.Step.Started.data.fields.model,
|
|
||||||
content: AssistantContent.pipe(Schema.Array),
|
|
||||||
snapshot: Schema.Struct({
|
|
||||||
start: Schema.String.pipe(Schema.optional),
|
|
||||||
end: Schema.String.pipe(Schema.optional),
|
|
||||||
}).pipe(Schema.optional),
|
|
||||||
finish: Schema.String.pipe(Schema.optional),
|
|
||||||
cost: Schema.Finite.pipe(Schema.optional),
|
|
||||||
tokens: Schema.Struct({
|
|
||||||
input: Schema.Finite,
|
|
||||||
output: Schema.Finite,
|
|
||||||
reasoning: Schema.Finite,
|
|
||||||
cache: Schema.Struct({
|
|
||||||
read: Schema.Finite,
|
|
||||||
write: Schema.Finite,
|
|
||||||
}),
|
|
||||||
}).pipe(Schema.optional),
|
|
||||||
error: SessionEvent.Step.Failed.data.fields.error.pipe(Schema.optional),
|
|
||||||
time: Schema.Struct({
|
|
||||||
created: V2Schema.DateTimeUtcFromMillis,
|
|
||||||
completed: V2Schema.DateTimeUtcFromMillis.pipe(Schema.optional),
|
|
||||||
}),
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class Compaction extends Schema.Class<Compaction>("Session.Message.Compaction")({
|
|
||||||
type: Schema.Literal("compaction"),
|
|
||||||
reason: SessionEvent.Compaction.Started.data.fields.reason,
|
|
||||||
summary: Schema.String,
|
|
||||||
recent: Schema.String,
|
|
||||||
...Base,
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export const Message = Schema.Union([
|
|
||||||
AgentSwitched,
|
|
||||||
ModelSwitched,
|
|
||||||
User,
|
|
||||||
Synthetic,
|
|
||||||
System,
|
|
||||||
Shell,
|
|
||||||
Assistant,
|
|
||||||
Compaction,
|
|
||||||
])
|
|
||||||
.pipe(Schema.toTaggedUnion("type"))
|
|
||||||
.annotate({ identifier: "Session.Message" })
|
|
||||||
|
|
||||||
export type Message = Schema.Schema.Type<typeof Message>
|
|
||||||
|
|
||||||
export type Type = Message["type"]
|
|
||||||
|
|||||||
@@ -1,46 +1 @@
|
|||||||
import * as Schema from "effect/Schema"
|
export { AgentAttachment, FileAttachment, Prompt, Source } from "@opencode-ai/schema/prompt"
|
||||||
|
|
||||||
export class Source extends Schema.Class<Source>("Prompt.Source")({
|
|
||||||
start: Schema.Finite,
|
|
||||||
end: Schema.Finite,
|
|
||||||
text: Schema.String,
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class FileAttachment extends Schema.Class<FileAttachment>("Prompt.FileAttachment")({
|
|
||||||
uri: Schema.String,
|
|
||||||
mime: Schema.String,
|
|
||||||
name: Schema.String.pipe(Schema.optional),
|
|
||||||
description: Schema.String.pipe(Schema.optional),
|
|
||||||
source: Source.pipe(Schema.optional),
|
|
||||||
}) {
|
|
||||||
static create(input: FileAttachment) {
|
|
||||||
return new FileAttachment({
|
|
||||||
uri: input.uri,
|
|
||||||
mime: input.mime,
|
|
||||||
name: input.name,
|
|
||||||
description: input.description,
|
|
||||||
source: input.source,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class AgentAttachment extends Schema.Class<AgentAttachment>("Prompt.AgentAttachment")({
|
|
||||||
name: Schema.String,
|
|
||||||
source: Source.pipe(Schema.optional),
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class Prompt extends Schema.Class<Prompt>("Prompt")({
|
|
||||||
text: Schema.String,
|
|
||||||
files: Schema.Array(FileAttachment).pipe(Schema.optional),
|
|
||||||
agents: Schema.Array(AgentAttachment).pipe(Schema.optional),
|
|
||||||
}) {
|
|
||||||
static readonly equivalence = Schema.toEquivalence(Prompt)
|
|
||||||
|
|
||||||
static fromUserMessage(input: Pick<Prompt, "text" | "files" | "agents">) {
|
|
||||||
return new Prompt({
|
|
||||||
text: input.text,
|
|
||||||
...(input.files === undefined ? {} : { files: input.files }),
|
|
||||||
...(input.agents === undefined ? {} : { agents: input.agents }),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,49 +1,9 @@
|
|||||||
export * as SessionSchema from "./schema"
|
export * as SessionSchema from "./schema"
|
||||||
|
|
||||||
import { Schema } from "effect"
|
import { Session } from "@opencode-ai/schema/session"
|
||||||
import { Location } from "../location"
|
|
||||||
import { ModelV2 } from "../model"
|
|
||||||
import { ProjectV2 } from "../project"
|
|
||||||
import { externalID, type ExternalID, RelativePath, optionalOmitUndefined, withStatics } from "../schema"
|
|
||||||
import { Identifier } from "../util/identifier"
|
|
||||||
import { V2Schema } from "../v2-schema"
|
|
||||||
import { AgentV2 } from "../agent"
|
|
||||||
|
|
||||||
export const ID = Schema.String.check(Schema.isStartsWith("ses")).pipe(
|
export const ID = Session.ID
|
||||||
Schema.brand("SessionID"),
|
|
||||||
withStatics((schema) => {
|
|
||||||
const create = () => schema.make("ses_" + Identifier.descending())
|
|
||||||
return {
|
|
||||||
create,
|
|
||||||
descending: (id?: string) => (id === undefined ? create() : schema.make(id)),
|
|
||||||
fromExternal: (input: ExternalID) => schema.make(externalID("ses", input)),
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
export type ID = typeof ID.Type
|
export type ID = typeof ID.Type
|
||||||
|
|
||||||
export class Info extends Schema.Class<Info>("SessionV2.Info")({
|
export const Info = Session.Info
|
||||||
id: ID,
|
export type Info = Session.Info
|
||||||
parentID: ID.pipe(optionalOmitUndefined),
|
|
||||||
projectID: ProjectV2.ID,
|
|
||||||
agent: AgentV2.ID.pipe(Schema.optional),
|
|
||||||
model: ModelV2.Ref.pipe(Schema.optional),
|
|
||||||
cost: Schema.Finite,
|
|
||||||
tokens: Schema.Struct({
|
|
||||||
input: Schema.Finite,
|
|
||||||
output: Schema.Finite,
|
|
||||||
reasoning: Schema.Finite,
|
|
||||||
cache: Schema.Struct({
|
|
||||||
read: Schema.Finite,
|
|
||||||
write: Schema.Finite,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
time: Schema.Struct({
|
|
||||||
created: V2Schema.DateTimeUtcFromMillis,
|
|
||||||
updated: V2Schema.DateTimeUtcFromMillis,
|
|
||||||
archived: V2Schema.DateTimeUtcFromMillis.pipe(Schema.optional),
|
|
||||||
}),
|
|
||||||
title: Schema.String,
|
|
||||||
location: Location.Ref,
|
|
||||||
subpath: RelativePath.pipe(Schema.optional),
|
|
||||||
}) {}
|
|
||||||
|
|||||||
+18
-48
@@ -2,57 +2,29 @@ export * as SkillV2 from "./skill"
|
|||||||
|
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import { Context, Effect, Layer, Schema, Types } from "effect"
|
import { Context, Effect, Layer, Schema, Types } from "effect"
|
||||||
|
import { Skill } from "@opencode-ai/schema/skill"
|
||||||
import { AgentV2 } from "./agent"
|
import { AgentV2 } from "./agent"
|
||||||
import { ConfigMarkdown } from "./config/markdown"
|
import { ConfigMarkdown } from "./config/markdown"
|
||||||
import { FSUtil } from "./fs-util"
|
import { FSUtil } from "./fs-util"
|
||||||
import { PermissionV2 } from "./permission"
|
import { PermissionV2 } from "./permission"
|
||||||
import { AbsolutePath, withStatics } from "./schema"
|
import { AbsolutePath } from "./schema"
|
||||||
import { SkillDiscovery } from "./skill/discovery"
|
import { SkillDiscovery } from "./skill/discovery"
|
||||||
import { State } from "./state"
|
import { State } from "./state"
|
||||||
|
|
||||||
export class DirectorySource extends Schema.Class<DirectorySource>("SkillV2.DirectorySource")({
|
export const DirectorySource = Skill.DirectorySource
|
||||||
type: Schema.Literal("directory"),
|
export type DirectorySource = Skill.DirectorySource
|
||||||
path: AbsolutePath,
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class UrlSource extends Schema.Class<UrlSource>("SkillV2.UrlSource")({
|
export const UrlSource = Skill.UrlSource
|
||||||
type: Schema.Literal("url"),
|
export type UrlSource = Skill.UrlSource
|
||||||
url: Schema.String,
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export class EmbeddedSource extends Schema.Class<EmbeddedSource>("SkillV2.EmbeddedSource")({
|
export const EmbeddedSource = Skill.EmbeddedSource
|
||||||
type: Schema.Literal("embedded"),
|
export type EmbeddedSource = Skill.EmbeddedSource
|
||||||
skill: Schema.suspend(() => Info),
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export const Source = Schema.Union([DirectorySource, UrlSource, EmbeddedSource]).pipe(
|
export const Source = Skill.Source
|
||||||
Schema.toTaggedUnion("type"),
|
|
||||||
Schema.annotate({ identifier: "SkillV2.Source" }),
|
|
||||||
withStatics(() => ({
|
|
||||||
equals: (a: DirectorySource | UrlSource | EmbeddedSource, b: DirectorySource | UrlSource | EmbeddedSource) => {
|
|
||||||
if (a.type !== b.type) return false
|
|
||||||
if (a.type === "directory" && b.type === "directory") return a.path === b.path
|
|
||||||
if (a.type === "url" && b.type === "url") return a.url === b.url
|
|
||||||
if (a.type === "embedded" && b.type === "embedded") return a.skill.name === b.skill.name
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
key: (source: DirectorySource | UrlSource | EmbeddedSource) =>
|
|
||||||
source.type === "directory"
|
|
||||||
? `directory:${source.path}`
|
|
||||||
: source.type === "url"
|
|
||||||
? `url:${source.url}`
|
|
||||||
: `embedded:${source.skill.name}`,
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
export type Source = typeof Source.Type
|
export type Source = typeof Source.Type
|
||||||
|
|
||||||
export class Info extends Schema.Class<Info>("SkillV2.Info")({
|
export const Info = Skill.Info
|
||||||
name: Schema.String,
|
export type Info = Skill.Info
|
||||||
description: Schema.String.pipe(Schema.optional),
|
|
||||||
slash: Schema.Boolean.pipe(Schema.optional),
|
|
||||||
location: AbsolutePath,
|
|
||||||
content: Schema.String,
|
|
||||||
}) {}
|
|
||||||
|
|
||||||
export const available = (skills: ReadonlyArray<Info>, agent: AgentV2.Info) =>
|
export const available = (skills: ReadonlyArray<Info>, agent: AgentV2.Info) =>
|
||||||
skills.filter((skill) => PermissionV2.evaluate("skill", skill.name, agent.permissions).effect !== "deny")
|
skills.filter((skill) => PermissionV2.evaluate("skill", skill.name, agent.permissions).effect !== "deny")
|
||||||
@@ -119,15 +91,13 @@ export const layer = Layer.effect(
|
|||||||
? path.basename(filepath, ".md")
|
? path.basename(filepath, ".md")
|
||||||
: undefined
|
: undefined
|
||||||
if (!name) continue
|
if (!name) continue
|
||||||
skills.push(
|
skills.push({
|
||||||
new Info({
|
name,
|
||||||
name,
|
description: frontmatter.description,
|
||||||
description: frontmatter.description,
|
slash: frontmatter.slash,
|
||||||
slash: frontmatter.slash,
|
location: AbsolutePath.make(filepath),
|
||||||
location: AbsolutePath.make(filepath),
|
content: markdown.content,
|
||||||
content: markdown.content,
|
})
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return skills
|
return skills
|
||||||
|
|||||||
@@ -79,12 +79,11 @@ export const layer = Layer.effectDiscard(
|
|||||||
})
|
})
|
||||||
.pipe(
|
.pipe(
|
||||||
Effect.map((result) =>
|
Effect.map((result) =>
|
||||||
result.map(
|
result.map((entry) =>
|
||||||
(entry) =>
|
FileSystem.Entry.make({
|
||||||
new FileSystem.Entry({
|
...entry,
|
||||||
...entry,
|
path: RelativePath.make(path.relative(location.directory, path.resolve(cwd, entry.path))),
|
||||||
path: RelativePath.make(path.relative(location.directory, path.resolve(cwd, entry.path))),
|
}),
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -102,23 +102,22 @@ export const layer = Layer.effectDiscard(
|
|||||||
})
|
})
|
||||||
.pipe(
|
.pipe(
|
||||||
Effect.map((result) =>
|
Effect.map((result) =>
|
||||||
result.map(
|
result.map((match) =>
|
||||||
(match) =>
|
FileSystem.Match.make({
|
||||||
new FileSystem.Match({
|
...match,
|
||||||
...match,
|
entry: FileSystem.Entry.make({
|
||||||
entry: new FileSystem.Entry({
|
...match.entry,
|
||||||
...match.entry,
|
path: RelativePath.make(
|
||||||
path: RelativePath.make(
|
path.relative(
|
||||||
path.relative(
|
location.directory,
|
||||||
location.directory,
|
path.resolve(
|
||||||
path.resolve(
|
info?.type === "Directory" ? target : path.dirname(target),
|
||||||
info?.type === "Directory" ? target : path.dirname(target),
|
match.entry.path,
|
||||||
match.entry.path,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}),
|
),
|
||||||
}),
|
}),
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ export const list = Effect.fn("ReadTool.list")(function* (fs: FSUtil.Interface,
|
|||||||
const info = yield* fs.stat(target).pipe(Effect.catch(() => Effect.void))
|
const info = yield* fs.stat(target).pipe(Effect.catch(() => Effect.void))
|
||||||
const type = info?.type === "Directory" ? "directory" : info?.type === "File" ? "file" : undefined
|
const type = info?.type === "Directory" ? "directory" : info?.type === "File" ? "file" : undefined
|
||||||
if (!type) return
|
if (!type) return
|
||||||
return new FileSystem.Entry({
|
return FileSystem.Entry.make({
|
||||||
path: RelativePath.make(item.name + (type === "directory" ? path.sep : "")),
|
path: RelativePath.make(item.name + (type === "directory" ? path.sep : "")),
|
||||||
type,
|
type,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,48 +1 @@
|
|||||||
import { randomBytes } from "crypto"
|
export * as Identifier from "@opencode-ai/schema/identifier"
|
||||||
|
|
||||||
export namespace Identifier {
|
|
||||||
const LENGTH = 26
|
|
||||||
|
|
||||||
// State for monotonic ID generation
|
|
||||||
let lastTimestamp = 0
|
|
||||||
let counter = 0
|
|
||||||
|
|
||||||
export function ascending() {
|
|
||||||
return create(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function descending() {
|
|
||||||
return create(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
function randomBase62(length: number): string {
|
|
||||||
const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
||||||
let result = ""
|
|
||||||
const bytes = randomBytes(length)
|
|
||||||
for (let i = 0; i < length; i++) {
|
|
||||||
result += chars[bytes[i] % 62]
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
export function create(descending: boolean, timestamp?: number): string {
|
|
||||||
const currentTimestamp = timestamp ?? Date.now()
|
|
||||||
|
|
||||||
if (currentTimestamp !== lastTimestamp) {
|
|
||||||
lastTimestamp = currentTimestamp
|
|
||||||
counter = 0
|
|
||||||
}
|
|
||||||
counter++
|
|
||||||
|
|
||||||
let now = BigInt(currentTimestamp) * BigInt(0x1000) + BigInt(counter)
|
|
||||||
|
|
||||||
now = descending ? ~now : now
|
|
||||||
|
|
||||||
const timeBytes = Buffer.alloc(6)
|
|
||||||
for (let i = 0; i < 6; i++) {
|
|
||||||
timeBytes[i] = Number((now >> BigInt(40 - 8 * i)) & BigInt(0xff))
|
|
||||||
}
|
|
||||||
|
|
||||||
return timeBytes.toString("hex") + randomBase62(LENGTH - 12)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,10 +1,3 @@
|
|||||||
import { DateTime, Schema, SchemaGetter } from "effect"
|
|
||||||
|
|
||||||
export const DateTimeUtcFromMillis = Schema.Finite.pipe(
|
|
||||||
Schema.decodeTo(Schema.DateTimeUtc, {
|
|
||||||
decode: SchemaGetter.transform((value) => DateTime.makeUnsafe(value)),
|
|
||||||
encode: SchemaGetter.transform((value) => DateTime.toEpochMillis(value)),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
export * as V2Schema from "./v2-schema"
|
export * as V2Schema from "./v2-schema"
|
||||||
|
|
||||||
|
export { DateTimeUtcFromMillis } from "@opencode-ai/schema/schema"
|
||||||
|
|||||||
@@ -1,18 +1,6 @@
|
|||||||
export * as WorkspaceV2 from "./workspace"
|
export * as WorkspaceV2 from "./workspace"
|
||||||
|
|
||||||
import { Schema } from "effect"
|
import { Workspace } from "@opencode-ai/schema/workspace"
|
||||||
import { withStatics } from "./schema"
|
|
||||||
import { Identifier } from "./util/identifier"
|
|
||||||
|
|
||||||
export const ID = Schema.String.check(Schema.isStartsWith("wrk")).pipe(
|
export const ID = Workspace.ID
|
||||||
Schema.brand("WorkspaceV2.ID"),
|
|
||||||
withStatics((schema) => ({
|
|
||||||
ascending: (id?: string) => {
|
|
||||||
if (!id) return schema.make("wrk_" + Identifier.ascending())
|
|
||||||
if (!id.startsWith("wrk")) throw new Error(`ID ${id} does not start with wrk`)
|
|
||||||
return schema.make(id)
|
|
||||||
},
|
|
||||||
create: () => schema.make("wrk_" + Identifier.ascending()),
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
export type ID = typeof ID.Type
|
export type ID = typeof ID.Type
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ describe("CatalogV2", () => {
|
|||||||
yield* credentials.create({
|
yield* credentials.create({
|
||||||
integrationID,
|
integrationID,
|
||||||
label: "First",
|
label: "First",
|
||||||
value: new Credential.Key({ type: "key", key: "first", metadata: { tenant: "one" } }),
|
value: Credential.Key.make({ type: "key", key: "first", metadata: { tenant: "one" } }),
|
||||||
})
|
})
|
||||||
|
|
||||||
expect((yield* catalog.provider.available()).map((provider) => provider.id)).toEqual([ProviderV2.ID.make("test")])
|
expect((yield* catalog.provider.available()).map((provider) => provider.id)).toEqual([ProviderV2.ID.make("test")])
|
||||||
@@ -69,7 +69,7 @@ describe("CatalogV2", () => {
|
|||||||
yield* credentials.create({
|
yield* credentials.create({
|
||||||
integrationID,
|
integrationID,
|
||||||
label: "Second",
|
label: "Second",
|
||||||
value: new Credential.Key({ type: "key", key: "second", metadata: { tenant: "two" } }),
|
value: Credential.Key.make({ type: "key", key: "second", metadata: { tenant: "two" } }),
|
||||||
})
|
})
|
||||||
expect((yield* catalog.provider.available()).map((provider) => provider.id)).toEqual([ProviderV2.ID.make("test")])
|
expect((yield* catalog.provider.available()).map((provider) => provider.id)).toEqual([ProviderV2.ID.make("test")])
|
||||||
expect(required(yield* catalog.provider.get(ProviderV2.ID.make("test"))).request.body).toEqual({})
|
expect(required(yield* catalog.provider.get(ProviderV2.ID.make("test"))).request.body).toEqual({})
|
||||||
@@ -98,7 +98,7 @@ describe("CatalogV2", () => {
|
|||||||
|
|
||||||
yield* (yield* Credential.Service).create({
|
yield* (yield* Credential.Service).create({
|
||||||
integrationID,
|
integrationID,
|
||||||
value: new Credential.Key({ type: "key", key: "secret" }),
|
value: Credential.Key.make({ type: "key", key: "secret" }),
|
||||||
})
|
})
|
||||||
|
|
||||||
expect((yield* catalog.provider.available()).map((provider) => provider.id)).toEqual([providerID])
|
expect((yield* catalog.provider.available()).map((provider) => provider.id)).toEqual([providerID])
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ describe("CommandV2", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
expect(yield* command.get("review")).toEqual(
|
expect(yield* command.get("review")).toEqual(
|
||||||
new CommandV2.Info({
|
CommandV2.Info.make({
|
||||||
name: "review",
|
name: "review",
|
||||||
template: "Second",
|
template: "Second",
|
||||||
description: "Review code",
|
description: "Review code",
|
||||||
@@ -39,7 +39,7 @@ describe("CommandV2", () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
expect(yield* command.list()).toEqual([
|
expect(yield* command.list()).toEqual([
|
||||||
new CommandV2.Info({
|
CommandV2.Info.make({
|
||||||
name: "review",
|
name: "review",
|
||||||
template: "Second",
|
template: "Second",
|
||||||
description: "Review code",
|
description: "Review code",
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ Review files`,
|
|||||||
)
|
)
|
||||||
|
|
||||||
expect(yield* command.list()).toEqual([
|
expect(yield* command.list()).toEqual([
|
||||||
new CommandV2.Info({
|
CommandV2.Info.make({
|
||||||
name: "review",
|
name: "review",
|
||||||
template: "Review files",
|
template: "Review files",
|
||||||
description: "File review",
|
description: "File review",
|
||||||
@@ -71,8 +71,8 @@ Review files`,
|
|||||||
},
|
},
|
||||||
subtask: true,
|
subtask: true,
|
||||||
}),
|
}),
|
||||||
new CommandV2.Info({ name: "empty", template: "" }),
|
CommandV2.Info.make({ name: "empty", template: "" }),
|
||||||
new CommandV2.Info({ name: "nested/docs", template: "Write docs" }),
|
CommandV2.Info.make({ name: "nested/docs", template: "Write docs" }),
|
||||||
])
|
])
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -59,21 +59,21 @@ describe("ConfigSkillPlugin.Plugin", () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
expect(sources).toEqual([
|
expect(sources).toEqual([
|
||||||
new SkillV2.DirectorySource({
|
SkillV2.DirectorySource.make({
|
||||||
type: "directory",
|
type: "directory",
|
||||||
path: AbsolutePath.make(path.join("/repo/.opencode", "skill")),
|
path: AbsolutePath.make(path.join("/repo/.opencode", "skill")),
|
||||||
}),
|
}),
|
||||||
new SkillV2.DirectorySource({
|
SkillV2.DirectorySource.make({
|
||||||
type: "directory",
|
type: "directory",
|
||||||
path: AbsolutePath.make(path.join("/repo/.opencode", "skills")),
|
path: AbsolutePath.make(path.join("/repo/.opencode", "skills")),
|
||||||
}),
|
}),
|
||||||
new SkillV2.DirectorySource({ type: "directory", path: AbsolutePath.make(path.join(directory, "skills")) }),
|
SkillV2.DirectorySource.make({ type: "directory", path: AbsolutePath.make(path.join(directory, "skills")) }),
|
||||||
new SkillV2.DirectorySource({
|
SkillV2.DirectorySource.make({
|
||||||
type: "directory",
|
type: "directory",
|
||||||
path: AbsolutePath.make(path.join("/home/test", "shared-skills")),
|
path: AbsolutePath.make(path.join("/home/test", "shared-skills")),
|
||||||
}),
|
}),
|
||||||
new SkillV2.DirectorySource({ type: "directory", path: AbsolutePath.make("/opt/skills") }),
|
SkillV2.DirectorySource.make({ type: "directory", path: AbsolutePath.make("/opt/skills") }),
|
||||||
new SkillV2.UrlSource({ type: "url", url: "https://example.test/skills/" }),
|
SkillV2.UrlSource.make({ type: "url", url: "https://example.test/skills/" }),
|
||||||
])
|
])
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ describe("Credential", () => {
|
|||||||
const created = yield* credentials.create({
|
const created = yield* credentials.create({
|
||||||
integrationID,
|
integrationID,
|
||||||
label: "Work",
|
label: "Work",
|
||||||
value: new Credential.Key({ type: "key", key: "secret" }),
|
value: Credential.Key.make({ type: "key", key: "secret" }),
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(yield* credentials.list(integrationID)).toEqual([created])
|
expect(yield* credentials.list(integrationID)).toEqual([created])
|
||||||
@@ -24,7 +24,7 @@ describe("Credential", () => {
|
|||||||
const replacement = yield* credentials.create({
|
const replacement = yield* credentials.create({
|
||||||
integrationID,
|
integrationID,
|
||||||
label: "Replacement",
|
label: "Replacement",
|
||||||
value: new Credential.Key({ type: "key", key: "replacement" }),
|
value: Credential.Key.make({ type: "key", key: "replacement" }),
|
||||||
})
|
})
|
||||||
expect(yield* credentials.list(integrationID)).toEqual([replacement])
|
expect(yield* credentials.list(integrationID)).toEqual([replacement])
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ import { EventV2 } from "@opencode-ai/core/event"
|
|||||||
import { Database } from "@opencode-ai/core/database/database"
|
import { Database } from "@opencode-ai/core/database/database"
|
||||||
import { EventSequenceTable, EventTable } from "@opencode-ai/core/event/sql"
|
import { EventSequenceTable, EventTable } from "@opencode-ai/core/event/sql"
|
||||||
import { Location } from "@opencode-ai/core/location"
|
import { Location } from "@opencode-ai/core/location"
|
||||||
import { AbsolutePath } from "@opencode-ai/core/schema"
|
import { AbsolutePath, DateTimeUtcFromMillis } from "@opencode-ai/core/schema"
|
||||||
import { WorkspaceV2 } from "@opencode-ai/core/workspace"
|
import { WorkspaceV2 } from "@opencode-ai/core/workspace"
|
||||||
import { V2Schema } from "@opencode-ai/core/v2-schema"
|
|
||||||
import { eq } from "drizzle-orm"
|
import { eq } from "drizzle-orm"
|
||||||
import { location } from "./fixture/location"
|
import { location } from "./fixture/location"
|
||||||
import { testEffect } from "./lib/effect"
|
import { testEffect } from "./lib/effect"
|
||||||
@@ -79,24 +78,11 @@ const SyncTimestamp = EventV2.define({
|
|||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
id: Schema.String,
|
id: Schema.String,
|
||||||
timestamp: V2Schema.DateTimeUtcFromMillis,
|
timestamp: DateTimeUtcFromMillis,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("EventV2", () => {
|
describe("EventV2", () => {
|
||||||
it.effect("derives stable namespaced external IDs", () =>
|
|
||||||
Effect.sync(() => {
|
|
||||||
const input = { namespace: "opencord.agent-input", key: "input-1" }
|
|
||||||
|
|
||||||
expect(EventV2.ID.fromExternal(input)).toBe(EventV2.ID.fromExternal(input))
|
|
||||||
expect(EventV2.ID.fromExternal(input)).toMatch(/^evt_[a-f0-9]{64}$/)
|
|
||||||
expect(EventV2.ID.fromExternal({ ...input, namespace: "another-app" })).not.toBe(EventV2.ID.fromExternal(input))
|
|
||||||
expect(EventV2.ID.fromExternal({ namespace: "a:b", key: "c" })).not.toBe(
|
|
||||||
EventV2.ID.fromExternal({ namespace: "a", key: "b:c" }),
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
it.effect("publishes events with the current location", () =>
|
it.effect("publishes events with the current location", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ describe("Integration", () => {
|
|||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
integrationID,
|
integrationID,
|
||||||
label: "Work",
|
label: "Work",
|
||||||
value: new Credential.Key({ type: "key", key: "secret" }),
|
value: Credential.Key.make({ type: "key", key: "secret" }),
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
expect((yield* Fiber.join(updated)).length).toBe(1)
|
expect((yield* Fiber.join(updated)).length).toBe(1)
|
||||||
@@ -149,7 +149,7 @@ describe("Integration", () => {
|
|||||||
instructions: "Paste the code",
|
instructions: "Paste the code",
|
||||||
callback: (code: string) =>
|
callback: (code: string) =>
|
||||||
Effect.succeed(
|
Effect.succeed(
|
||||||
new Credential.OAuth({
|
Credential.OAuth.make({
|
||||||
type: "oauth",
|
type: "oauth",
|
||||||
methodID,
|
methodID,
|
||||||
access: "access",
|
access: "access",
|
||||||
@@ -175,7 +175,7 @@ describe("Integration", () => {
|
|||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
integrationID,
|
integrationID,
|
||||||
label: "Personal",
|
label: "Personal",
|
||||||
value: new Credential.OAuth({
|
value: Credential.OAuth.make({
|
||||||
type: "oauth",
|
type: "oauth",
|
||||||
methodID,
|
methodID,
|
||||||
access: "access",
|
access: "access",
|
||||||
@@ -238,7 +238,7 @@ describe("Integration", () => {
|
|||||||
url: "https://example.com/authorize",
|
url: "https://example.com/authorize",
|
||||||
instructions: "Sign in",
|
instructions: "Sign in",
|
||||||
callback: Effect.succeed(
|
callback: Effect.succeed(
|
||||||
new Credential.OAuth({ type: "oauth", methodID, access: "access", refresh: "refresh", expires: 1 }),
|
Credential.OAuth.make({ type: "oauth", methodID, access: "access", refresh: "refresh", expires: 1 }),
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
@@ -315,12 +315,12 @@ describe("Integration", () => {
|
|||||||
const work = yield* credentials.create({
|
const work = yield* credentials.create({
|
||||||
integrationID,
|
integrationID,
|
||||||
label: "Work",
|
label: "Work",
|
||||||
value: new Credential.Key({ type: "key", key: "a" }),
|
value: Credential.Key.make({ type: "key", key: "a" }),
|
||||||
})
|
})
|
||||||
const personal = yield* credentials.create({
|
const personal = yield* credentials.create({
|
||||||
integrationID,
|
integrationID,
|
||||||
label: "Personal",
|
label: "Personal",
|
||||||
value: new Credential.Key({ type: "key", key: "b" }),
|
value: Credential.Key.make({ type: "key", key: "b" }),
|
||||||
})
|
})
|
||||||
|
|
||||||
// Stored credentials and detected env vars appear as connections.
|
// Stored credentials and detected env vars appear as connections.
|
||||||
|
|||||||
@@ -52,14 +52,28 @@ const it = testEffect(
|
|||||||
)
|
)
|
||||||
|
|
||||||
describe("LocationServiceMap", () => {
|
describe("LocationServiceMap", () => {
|
||||||
it.effect("compares equivalent location refs by value", () =>
|
it.live("reuses cached services for constructed and decoded location refs", () =>
|
||||||
Effect.sync(() => {
|
Effect.acquireRelease(
|
||||||
const directory = AbsolutePath.make("/project")
|
Effect.promise(() => tmpdir()),
|
||||||
expect(Equal.equals(Location.Ref.make({ directory }), Location.Ref.make({ directory }))).toBe(true)
|
(dir) => Effect.promise(() => dir[Symbol.asyncDispose]()),
|
||||||
expect(Hash.hash(Location.Ref.make({ directory }))).toBe(
|
).pipe(
|
||||||
Hash.hash(Location.Ref.make({ directory, workspaceID: undefined })),
|
Effect.flatMap((dir) =>
|
||||||
)
|
Effect.scoped(
|
||||||
}),
|
Effect.gen(function* () {
|
||||||
|
const locations = yield* LocationServiceMap
|
||||||
|
const directory = AbsolutePath.make(dir.path)
|
||||||
|
const constructed = Location.Ref.make({ directory })
|
||||||
|
const decoded = Schema.decodeUnknownSync(Location.Ref)({ directory })
|
||||||
|
|
||||||
|
expect(constructed).toEqual({ directory, workspaceID: undefined })
|
||||||
|
expect(decoded).toEqual(constructed)
|
||||||
|
expect(Equal.equals(constructed, decoded)).toBe(true)
|
||||||
|
expect(Hash.hash(constructed)).toBe(Hash.hash(decoded))
|
||||||
|
expect(yield* locations.contextEffect(constructed)).toBe(yield* locations.contextEffect(decoded))
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.live("isolates location state while sharing location policy with catalog", () =>
|
it.live("isolates location state while sharing location policy with catalog", () =>
|
||||||
|
|||||||
@@ -176,12 +176,11 @@ export function integrationHost(integration: Integration.Interface): PluginConte
|
|||||||
return {
|
return {
|
||||||
...authorization,
|
...authorization,
|
||||||
callback: authorization.callback.pipe(
|
callback: authorization.callback.pipe(
|
||||||
Effect.map(
|
Effect.map((credential) =>
|
||||||
(credential) =>
|
Credential.OAuth.make({
|
||||||
new Credential.OAuth({
|
...credential,
|
||||||
...credential,
|
methodID: Integration.MethodID.make(credential.methodID),
|
||||||
methodID: Integration.MethodID.make(credential.methodID),
|
}),
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@@ -190,12 +189,11 @@ export function integrationHost(integration: Integration.Interface): PluginConte
|
|||||||
...authorization,
|
...authorization,
|
||||||
callback: (code: string) =>
|
callback: (code: string) =>
|
||||||
authorization.callback(code).pipe(
|
authorization.callback(code).pipe(
|
||||||
Effect.map(
|
Effect.map((credential) =>
|
||||||
(credential) =>
|
Credential.OAuth.make({
|
||||||
new Credential.OAuth({
|
...credential,
|
||||||
...credential,
|
methodID: Integration.MethodID.make(credential.methodID),
|
||||||
methodID: Integration.MethodID.make(credential.methodID),
|
}),
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@@ -205,12 +203,11 @@ export function integrationHost(integration: Integration.Interface): PluginConte
|
|||||||
? {
|
? {
|
||||||
refresh: (value: Credential.OAuth) =>
|
refresh: (value: Credential.OAuth) =>
|
||||||
refresh(value).pipe(
|
refresh(value).pipe(
|
||||||
Effect.map(
|
Effect.map((next) =>
|
||||||
(next) =>
|
Credential.OAuth.make({
|
||||||
new Credential.OAuth({
|
...next,
|
||||||
...next,
|
methodID: Integration.MethodID.make(next.methodID),
|
||||||
methodID: Integration.MethodID.make(next.methodID),
|
}),
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ describe("AlibabaPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("alibaba"), ModelV2.ID.make("qwen")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("alibaba"), ModelV2.ID.make("qwen")),
|
||||||
api: { id: ModelV2.ID.make("qwen"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("qwen"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -43,7 +43,7 @@ describe("AlibabaPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("alibaba"), ModelV2.ID.make("qwen")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("alibaba"), ModelV2.ID.make("qwen")),
|
||||||
api: { id: ModelV2.ID.make("qwen"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("qwen"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -60,7 +60,7 @@ describe("AlibabaPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom-alibaba"), ModelV2.ID.make("qwen")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom-alibaba"), ModelV2.ID.make("qwen")),
|
||||||
api: { id: ModelV2.ID.make("qwen"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("qwen"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -79,7 +79,7 @@ describe("AlibabaPlugin", () => {
|
|||||||
const plugin = yield* PluginV2.Service
|
const plugin = yield* PluginV2.Service
|
||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const item = new ModelV2.Info({
|
const item = ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("alibaba"), ModelV2.ID.make("alias")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("alibaba"), ModelV2.ID.make("alias")),
|
||||||
api: { id: ModelV2.ID.make("qwen-plus"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("qwen-plus"), type: "aisdk", package: "test-provider" },
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const catalog = yield* Catalog.Service
|
const catalog = yield* Catalog.Service
|
||||||
yield* catalog.transform((catalog) => {
|
yield* catalog.transform((catalog) => {
|
||||||
const bedrock = new ProviderV2.Info({
|
const bedrock = ProviderV2.Info.make({
|
||||||
...ProviderV2.Info.empty(ProviderV2.ID.amazonBedrock),
|
...ProviderV2.Info.empty(ProviderV2.ID.amazonBedrock),
|
||||||
api: { type: "aisdk", package: "@ai-sdk/amazon-bedrock" },
|
api: { type: "aisdk", package: "@ai-sdk/amazon-bedrock" },
|
||||||
request: {
|
request: {
|
||||||
@@ -114,7 +114,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -139,7 +139,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -173,7 +173,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
||||||
api: {
|
api: {
|
||||||
id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"),
|
id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"),
|
||||||
@@ -197,7 +197,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -216,7 +216,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -235,7 +235,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -255,7 +255,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
const headers: Array<string | null> = []
|
const headers: Array<string | null> = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -284,7 +284,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
const headers: Array<string | null> = []
|
const headers: Array<string | null> = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -312,7 +312,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("openai.gpt-5.5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("openai.gpt-5.5")),
|
||||||
api: {
|
api: {
|
||||||
id: ModelV2.ID.make("openai.gpt-5.5"),
|
id: ModelV2.ID.make("openai.gpt-5.5"),
|
||||||
@@ -343,7 +343,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("openai.gpt-5.5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("openai.gpt-5.5")),
|
||||||
api: {
|
api: {
|
||||||
id: ModelV2.ID.make("openai.gpt-5.5"),
|
id: ModelV2.ID.make("openai.gpt-5.5"),
|
||||||
@@ -355,7 +355,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
options: { baseURL: "https://bedrock-mantle.us-east-2.api.aws/openai/v1", region: "us-east-2" },
|
options: { baseURL: "https://bedrock-mantle.us-east-2.api.aws/openai/v1", region: "us-east-2" },
|
||||||
})
|
})
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("openai.gpt-oss-safeguard-120b")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("openai.gpt-oss-safeguard-120b")),
|
||||||
api: {
|
api: {
|
||||||
id: ModelV2.ID.make("openai.gpt-oss-safeguard-120b"),
|
id: ModelV2.ID.make("openai.gpt-oss-safeguard-120b"),
|
||||||
@@ -376,7 +376,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
||||||
api: {
|
api: {
|
||||||
id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"),
|
id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"),
|
||||||
@@ -407,7 +407,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
const headers: Array<string | null> = []
|
const headers: Array<string | null> = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
||||||
api: {
|
api: {
|
||||||
id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"),
|
id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"),
|
||||||
@@ -442,7 +442,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -450,7 +450,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
options: {},
|
options: {},
|
||||||
})
|
})
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -458,7 +458,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
options: { region: "eu-west-1" },
|
options: { region: "eu-west-1" },
|
||||||
})
|
})
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("global.anthropic.claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("global.anthropic.claude-sonnet-4-5")),
|
||||||
api: {
|
api: {
|
||||||
id: ModelV2.ID.make("global.anthropic.claude-sonnet-4-5"),
|
id: ModelV2.ID.make("global.anthropic.claude-sonnet-4-5"),
|
||||||
@@ -470,7 +470,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
options: { region: "eu-west-1" },
|
options: { region: "eu-west-1" },
|
||||||
})
|
})
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -478,7 +478,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
options: { region: "ap-northeast-1" },
|
options: { region: "ap-northeast-1" },
|
||||||
})
|
})
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -503,7 +503,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -589,7 +589,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
for (const item of cases) {
|
for (const item of cases) {
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make(item.modelID)),
|
...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make(item.modelID)),
|
||||||
api: { id: ModelV2.ID.make(item.modelID), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make(item.modelID), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -608,7 +608,7 @@ describe("AmazonBedrockPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runLanguage({
|
const result = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("anthropic.claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ describe("AnthropicPlugin", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const catalog = yield* Catalog.Service
|
const catalog = yield* Catalog.Service
|
||||||
yield* catalog.transform((catalog) => {
|
yield* catalog.transform((catalog) => {
|
||||||
const item = new ProviderV2.Info({
|
const item = ProviderV2.Info.make({
|
||||||
...ProviderV2.Info.empty(ProviderV2.ID.anthropic),
|
...ProviderV2.Info.empty(ProviderV2.ID.anthropic),
|
||||||
api: { type: "aisdk", package: "@ai-sdk/anthropic" },
|
api: { type: "aisdk", package: "@ai-sdk/anthropic" },
|
||||||
request: { headers: { Existing: "1" }, body: {} },
|
request: { headers: { Existing: "1" }, body: {} },
|
||||||
@@ -64,7 +64,7 @@ describe("AnthropicPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom-anthropic"), ModelV2.ID.make("claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom-anthropic"), ModelV2.ID.make("claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "@ai-sdk/anthropic" },
|
api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "@ai-sdk/anthropic" },
|
||||||
}),
|
}),
|
||||||
@@ -81,7 +81,7 @@ describe("AnthropicPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.anthropic, ModelV2.ID.make("claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.anthropic, ModelV2.ID.make("claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "@ai-sdk/anthropic" },
|
api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "@ai-sdk/anthropic" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -87,11 +87,11 @@ describe("AzureCognitiveServicesPlugin", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const catalog = yield* Catalog.Service
|
const catalog = yield* Catalog.Service
|
||||||
yield* catalog.transform((catalog) => {
|
yield* catalog.transform((catalog) => {
|
||||||
const azure = new ProviderV2.Info({
|
const azure = ProviderV2.Info.make({
|
||||||
...ProviderV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services")),
|
...ProviderV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services")),
|
||||||
api: { type: "aisdk", package: "@ai-sdk/openai-compatible" },
|
api: { type: "aisdk", package: "@ai-sdk/openai-compatible" },
|
||||||
})
|
})
|
||||||
const openai = new ProviderV2.Info({
|
const openai = ProviderV2.Info.make({
|
||||||
...ProviderV2.Info.empty(ProviderV2.ID.openai),
|
...ProviderV2.Info.empty(ProviderV2.ID.openai),
|
||||||
api: { type: "aisdk", package: "test-provider" },
|
api: { type: "aisdk", package: "test-provider" },
|
||||||
})
|
})
|
||||||
@@ -120,7 +120,7 @@ describe("AzureCognitiveServicesPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services"), ModelV2.ID.make("deployment")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services"), ModelV2.ID.make("deployment")),
|
||||||
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -138,7 +138,7 @@ describe("AzureCognitiveServicesPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services"), ModelV2.ID.make("deployment")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services"), ModelV2.ID.make("deployment")),
|
||||||
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -146,7 +146,7 @@ describe("AzureCognitiveServicesPlugin", () => {
|
|||||||
options: {},
|
options: {},
|
||||||
})
|
})
|
||||||
const ignored = yield* aisdk.runLanguage({
|
const ignored = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("deployment")),
|
...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("deployment")),
|
||||||
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -166,7 +166,7 @@ describe("AzureCognitiveServicesPlugin", () => {
|
|||||||
const sdk = fakeSelectorSdk(calls)
|
const sdk = fakeSelectorSdk(calls)
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services"), ModelV2.ID.make("messages-deployment")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services"), ModelV2.ID.make("messages-deployment")),
|
||||||
api: { id: ModelV2.ID.make("messages-deployment"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("messages-deployment"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -174,7 +174,7 @@ describe("AzureCognitiveServicesPlugin", () => {
|
|||||||
options: {},
|
options: {},
|
||||||
})
|
})
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services"), ModelV2.ID.make("chat-deployment")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services"), ModelV2.ID.make("chat-deployment")),
|
||||||
api: { id: ModelV2.ID.make("chat-deployment"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("chat-deployment"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -182,7 +182,7 @@ describe("AzureCognitiveServicesPlugin", () => {
|
|||||||
options: {},
|
options: {},
|
||||||
})
|
})
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services"), ModelV2.ID.make("language-deployment")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services"), ModelV2.ID.make("language-deployment")),
|
||||||
api: { id: ModelV2.ID.make("language-deployment"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("language-deployment"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ describe("AzurePlugin", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const catalog = yield* Catalog.Service
|
const catalog = yield* Catalog.Service
|
||||||
yield* catalog.transform((catalog) => {
|
yield* catalog.transform((catalog) => {
|
||||||
const azure = new ProviderV2.Info({
|
const azure = ProviderV2.Info.make({
|
||||||
...ProviderV2.Info.empty(ProviderV2.ID.azure),
|
...ProviderV2.Info.empty(ProviderV2.ID.azure),
|
||||||
api: { type: "aisdk", package: "@ai-sdk/azure" },
|
api: { type: "aisdk", package: "@ai-sdk/azure" },
|
||||||
request: { headers: {}, body: { resourceName: "from-config" } },
|
request: { headers: {}, body: { resourceName: "from-config" } },
|
||||||
@@ -103,7 +103,7 @@ describe("AzurePlugin", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const catalog = yield* Catalog.Service
|
const catalog = yield* Catalog.Service
|
||||||
yield* catalog.transform((catalog) => {
|
yield* catalog.transform((catalog) => {
|
||||||
const azure = new ProviderV2.Info({
|
const azure = ProviderV2.Info.make({
|
||||||
...ProviderV2.Info.empty(ProviderV2.ID.azure),
|
...ProviderV2.Info.empty(ProviderV2.ID.azure),
|
||||||
api: { type: "aisdk", package: "@ai-sdk/azure" },
|
api: { type: "aisdk", package: "@ai-sdk/azure" },
|
||||||
request: { headers: {}, body: { resourceName: "" } },
|
request: { headers: {}, body: { resourceName: "" } },
|
||||||
@@ -124,7 +124,7 @@ describe("AzurePlugin", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const catalog = yield* Catalog.Service
|
const catalog = yield* Catalog.Service
|
||||||
yield* catalog.transform((catalog) => {
|
yield* catalog.transform((catalog) => {
|
||||||
const azure = new ProviderV2.Info({
|
const azure = ProviderV2.Info.make({
|
||||||
...ProviderV2.Info.empty(ProviderV2.ID.azure),
|
...ProviderV2.Info.empty(ProviderV2.ID.azure),
|
||||||
api: { type: "aisdk", package: "@ai-sdk/azure" },
|
api: { type: "aisdk", package: "@ai-sdk/azure" },
|
||||||
request: { headers: {}, body: { resourceName: " " } },
|
request: { headers: {}, body: { resourceName: " " } },
|
||||||
@@ -147,7 +147,7 @@ describe("AzurePlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")),
|
...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")),
|
||||||
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -166,7 +166,7 @@ describe("AzurePlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const exit = yield* aisdk
|
const exit = yield* aisdk
|
||||||
.runSDK({
|
.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")),
|
...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")),
|
||||||
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -186,7 +186,7 @@ describe("AzurePlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")),
|
...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")),
|
||||||
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -204,7 +204,7 @@ describe("AzurePlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")),
|
...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")),
|
||||||
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -222,7 +222,7 @@ describe("AzurePlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")),
|
...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")),
|
||||||
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
||||||
request: { headers: {}, body: { useCompletionUrls: true } },
|
request: { headers: {}, body: { useCompletionUrls: true } },
|
||||||
@@ -241,7 +241,7 @@ describe("AzurePlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")),
|
...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")),
|
||||||
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -249,7 +249,7 @@ describe("AzurePlugin", () => {
|
|||||||
options: {},
|
options: {},
|
||||||
})
|
})
|
||||||
const ignored = yield* aisdk.runLanguage({
|
const ignored = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("deployment")),
|
...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("deployment")),
|
||||||
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -272,7 +272,7 @@ describe("AzurePlugin", () => {
|
|||||||
}
|
}
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("messages-deployment")),
|
...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("messages-deployment")),
|
||||||
api: { id: ModelV2.ID.make("messages-deployment"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("messages-deployment"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -280,7 +280,7 @@ describe("AzurePlugin", () => {
|
|||||||
options: {},
|
options: {},
|
||||||
})
|
})
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("language-deployment")),
|
...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("language-deployment")),
|
||||||
api: { id: ModelV2.ID.make("language-deployment"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("language-deployment"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ describe("CerebrasPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(
|
...ModelV2.Info.empty(
|
||||||
ProviderV2.ID.make("custom-cerebras"),
|
ProviderV2.ID.make("custom-cerebras"),
|
||||||
ModelV2.ID.make("llama-4-scout-17b-16e-instruct"),
|
ModelV2.ID.make("llama-4-scout-17b-16e-instruct"),
|
||||||
@@ -90,7 +90,7 @@ describe("CerebrasPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runSDK({
|
yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(
|
...ModelV2.Info.empty(
|
||||||
ProviderV2.ID.make("custom-cerebras"),
|
ProviderV2.ID.make("custom-cerebras"),
|
||||||
ModelV2.ID.make("llama-4-scout-17b-16e-instruct"),
|
ModelV2.ID.make("llama-4-scout-17b-16e-instruct"),
|
||||||
@@ -115,7 +115,7 @@ describe("CerebrasPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(
|
...ModelV2.Info.empty(
|
||||||
ProviderV2.ID.make("custom-cerebras"),
|
ProviderV2.ID.make("custom-cerebras"),
|
||||||
ModelV2.ID.make("llama-4-scout-17b-16e-instruct"),
|
ModelV2.ID.make("llama-4-scout-17b-16e-instruct"),
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ describe("CloudflareAIGatewayPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -137,7 +137,7 @@ describe("CloudflareAIGatewayPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
yield* aisdk.runSDK({
|
yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -181,7 +181,7 @@ describe("CloudflareAIGatewayPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
yield* aisdk.runSDK({
|
yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -210,7 +210,7 @@ describe("CloudflareAIGatewayPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
yield* aisdk.runSDK({
|
yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -247,7 +247,7 @@ describe("CloudflareAIGatewayPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
yield* aisdk.runSDK({
|
yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -278,7 +278,7 @@ describe("CloudflareAIGatewayPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
yield* aisdk.runSDK({
|
yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -300,7 +300,7 @@ describe("CloudflareAIGatewayPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -323,7 +323,7 @@ describe("CloudflareAIGatewayPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -352,7 +352,7 @@ describe("CloudflareAIGatewayPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -375,7 +375,7 @@ describe("CloudflareAIGatewayPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(
|
...ModelV2.Info.empty(
|
||||||
ProviderV2.ID.make("cloudflare-ai-gateway"),
|
ProviderV2.ID.make("cloudflare-ai-gateway"),
|
||||||
ModelV2.ID.make("anthropic/claude-sonnet-4-5"),
|
ModelV2.ID.make("anthropic/claude-sonnet-4-5"),
|
||||||
@@ -410,7 +410,7 @@ describe("CloudflareAIGatewayPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ describe("CloudflareWorkersAIPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const provider = required(yield* catalog.provider.get(ProviderV2.ID.make("cloudflare-workers-ai")))
|
const provider = required(yield* catalog.provider.get(ProviderV2.ID.make("cloudflare-workers-ai")))
|
||||||
const sdk = yield* aisdk.runSDK({
|
const sdk = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("@cf/model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("@cf/model")),
|
||||||
api: { id: ModelV2.ID.make("@cf/model"), ...provider.api },
|
api: { id: ModelV2.ID.make("@cf/model"), ...provider.api },
|
||||||
}),
|
}),
|
||||||
@@ -136,7 +136,7 @@ describe("CloudflareWorkersAIPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("@cf/model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("@cf/model")),
|
||||||
api: {
|
api: {
|
||||||
id: ModelV2.ID.make("@cf/model"),
|
id: ModelV2.ID.make("@cf/model"),
|
||||||
@@ -180,7 +180,7 @@ describe("CloudflareWorkersAIPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("@cf/model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("@cf/model")),
|
||||||
api: {
|
api: {
|
||||||
id: ModelV2.ID.make("@cf/model"),
|
id: ModelV2.ID.make("@cf/model"),
|
||||||
@@ -212,7 +212,7 @@ describe("CloudflareWorkersAIPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("@cf/model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("@cf/model")),
|
||||||
api: {
|
api: {
|
||||||
id: ModelV2.ID.make("@cf/model"),
|
id: ModelV2.ID.make("@cf/model"),
|
||||||
@@ -241,7 +241,7 @@ describe("CloudflareWorkersAIPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runLanguage({
|
const result = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("alias")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("alias")),
|
||||||
api: { id: ModelV2.ID.make("@cf/api-model"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("@cf/api-model"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -260,7 +260,7 @@ describe("CloudflareWorkersAIPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("@cf/model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("@cf/model")),
|
||||||
api: {
|
api: {
|
||||||
id: ModelV2.ID.make("@cf/model"),
|
id: ModelV2.ID.make("@cf/model"),
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ describe("CoherePlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
const ignored = yield* aisdk.runSDK({
|
const ignored = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cohere"), ModelV2.ID.make("command")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cohere"), ModelV2.ID.make("command")),
|
||||||
api: { id: ModelV2.ID.make("command"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("command"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -64,7 +64,7 @@ describe("CoherePlugin", () => {
|
|||||||
expect(ignored.sdk).toBeUndefined()
|
expect(ignored.sdk).toBeUndefined()
|
||||||
|
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cohere"), ModelV2.ID.make("command")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cohere"), ModelV2.ID.make("command")),
|
||||||
api: { id: ModelV2.ID.make("command"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("command"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -81,7 +81,7 @@ describe("CoherePlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom-cohere"), ModelV2.ID.make("command-r-plus")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom-cohere"), ModelV2.ID.make("command-r-plus")),
|
||||||
api: { id: ModelV2.ID.make("command-r-plus"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("command-r-plus"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -106,7 +106,7 @@ describe("CoherePlugin", () => {
|
|||||||
const sdk = fakeSelectorSdk(calls)
|
const sdk = fakeSelectorSdk(calls)
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runLanguage({
|
const result = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cohere"), ModelV2.ID.make("alias")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cohere"), ModelV2.ID.make("alias")),
|
||||||
api: { id: ModelV2.ID.make("command-r-plus"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("command-r-plus"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ describe("DeepInfraPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
|
||||||
}),
|
}),
|
||||||
@@ -64,7 +64,7 @@ describe("DeepInfraPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom-deepinfra"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom-deepinfra"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
|
||||||
}),
|
}),
|
||||||
@@ -83,7 +83,7 @@ describe("DeepInfraPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
|
||||||
}),
|
}),
|
||||||
@@ -109,7 +109,7 @@ describe("DeepInfraPlugin", () => {
|
|||||||
yield* Effect.forEach(packages, (item) =>
|
yield* Effect.forEach(packages, (item) =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const ignored = yield* aisdk.runSDK({
|
const ignored = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
|
||||||
}),
|
}),
|
||||||
@@ -120,7 +120,7 @@ describe("DeepInfraPlugin", () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" },
|
||||||
}),
|
}),
|
||||||
@@ -139,7 +139,7 @@ describe("DeepInfraPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const sdkEvent = yield* aisdk.runSDK({
|
const sdkEvent = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("meta-llama/Llama-3.3-70B-Instruct")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("meta-llama/Llama-3.3-70B-Instruct")),
|
||||||
api: {
|
api: {
|
||||||
id: ModelV2.ID.make("meta-llama/Llama-3.3-70B-Instruct"),
|
id: ModelV2.ID.make("meta-llama/Llama-3.3-70B-Instruct"),
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ describe("DynamicProviderPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("test-model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("test-model")),
|
||||||
api: { id: ModelV2.ID.make("test-model"), type: "aisdk", package: fixtureProvider },
|
api: { id: ModelV2.ID.make("test-model"), type: "aisdk", package: fixtureProvider },
|
||||||
}),
|
}),
|
||||||
@@ -69,7 +69,7 @@ describe("DynamicProviderPlugin", () => {
|
|||||||
const sdk = { marker: "existing" }
|
const sdk = { marker: "existing" }
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("test-model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("test-model")),
|
||||||
api: { id: ModelV2.ID.make("test-model"), type: "aisdk", package: fixtureProvider },
|
api: { id: ModelV2.ID.make("test-model"), type: "aisdk", package: fixtureProvider },
|
||||||
}),
|
}),
|
||||||
@@ -86,7 +86,7 @@ describe("DynamicProviderPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom-provider"), ModelV2.ID.make("test-model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom-provider"), ModelV2.ID.make("test-model")),
|
||||||
api: { id: ModelV2.ID.make("test-model"), type: "aisdk", package: fixtureProvider },
|
api: { id: ModelV2.ID.make("test-model"), type: "aisdk", package: fixtureProvider },
|
||||||
}),
|
}),
|
||||||
@@ -102,7 +102,7 @@ describe("DynamicProviderPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin(npmEntrypoint(fixtureProviderPath))
|
yield* addPlugin(npmEntrypoint(fixtureProviderPath))
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("npm-provider"), ModelV2.ID.make("test-model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("npm-provider"), ModelV2.ID.make("test-model")),
|
||||||
api: { id: ModelV2.ID.make("test-model"), type: "aisdk", package: "fixture-provider" },
|
api: { id: ModelV2.ID.make("test-model"), type: "aisdk", package: "fixture-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -119,7 +119,7 @@ describe("DynamicProviderPlugin", () => {
|
|||||||
yield* addPlugin(npmEntrypoint())
|
yield* addPlugin(npmEntrypoint())
|
||||||
const exit = yield* aisdk
|
const exit = yield* aisdk
|
||||||
.language(
|
.language(
|
||||||
new ModelV2.Info({
|
ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("missing-entrypoint"), ModelV2.ID.make("alias")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("missing-entrypoint"), ModelV2.ID.make("alias")),
|
||||||
api: { id: ModelV2.ID.make("alias"), type: "aisdk", package: "fixture-provider" },
|
api: { id: ModelV2.ID.make("alias"), type: "aisdk", package: "fixture-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -136,7 +136,7 @@ describe("DynamicProviderPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const exit = yield* aisdk
|
const exit = yield* aisdk
|
||||||
.language(
|
.language(
|
||||||
new ModelV2.Info({
|
ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("bad-import"), ModelV2.ID.make("alias")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("bad-import"), ModelV2.ID.make("alias")),
|
||||||
api: { id: ModelV2.ID.make("alias"), type: "aisdk", package: "file:///missing/provider-factory.js" },
|
api: { id: ModelV2.ID.make("alias"), type: "aisdk", package: "file:///missing/provider-factory.js" },
|
||||||
}),
|
}),
|
||||||
@@ -155,7 +155,7 @@ describe("DynamicProviderPlugin", () => {
|
|||||||
yield* addPlugin(npmEntrypoint(tmp.entrypoint))
|
yield* addPlugin(npmEntrypoint(tmp.entrypoint))
|
||||||
const exit = yield* aisdk
|
const exit = yield* aisdk
|
||||||
.language(
|
.language(
|
||||||
new ModelV2.Info({
|
ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("missing-factory"), ModelV2.ID.make("alias")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("missing-factory"), ModelV2.ID.make("alias")),
|
||||||
api: { id: ModelV2.ID.make("alias"), type: "aisdk", package: "fixture-provider" },
|
api: { id: ModelV2.ID.make("alias"), type: "aisdk", package: "fixture-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -172,7 +172,7 @@ describe("DynamicProviderPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const language = yield* aisdk.language(
|
const language = yield* aisdk.language(
|
||||||
new ModelV2.Info({
|
ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("alias")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("alias")),
|
||||||
api: { id: ModelV2.ID.make("test-model-api"), type: "aisdk", package: fixtureProvider },
|
api: { id: ModelV2.ID.make("test-model-api"), type: "aisdk", package: fixtureProvider },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ describe("GatewayPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("gateway"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("gateway"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -63,7 +63,7 @@ describe("GatewayPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("vercel"), ModelV2.ID.make("anthropic/claude-sonnet-4")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("vercel"), ModelV2.ID.make("anthropic/claude-sonnet-4")),
|
||||||
api: {
|
api: {
|
||||||
id: ModelV2.ID.make("anthropic/claude-sonnet-4"),
|
id: ModelV2.ID.make("anthropic/claude-sonnet-4"),
|
||||||
@@ -89,7 +89,7 @@ describe("GatewayPlugin", () => {
|
|||||||
|
|
||||||
for (const modelID of vercelGatewayModels) {
|
for (const modelID of vercelGatewayModels) {
|
||||||
const ignored = yield* aisdk.runSDK({
|
const ignored = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("vercel"), ModelV2.ID.make(modelID)),
|
...ModelV2.Info.empty(ProviderV2.ID.make("vercel"), ModelV2.ID.make(modelID)),
|
||||||
api: { id: ModelV2.ID.make(modelID), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make(modelID), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -99,7 +99,7 @@ describe("GatewayPlugin", () => {
|
|||||||
expect(ignored.sdk).toBeUndefined()
|
expect(ignored.sdk).toBeUndefined()
|
||||||
|
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("vercel"), ModelV2.ID.make(modelID)),
|
...ModelV2.Info.empty(ProviderV2.ID.make("vercel"), ModelV2.ID.make(modelID)),
|
||||||
api: { id: ModelV2.ID.make(modelID), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make(modelID), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ describe("GithubCopilotPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const ignored = yield* aisdk.runSDK({
|
const ignored = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -53,7 +53,7 @@ describe("GithubCopilotPlugin", () => {
|
|||||||
options: { name: "github-copilot" },
|
options: { name: "github-copilot" },
|
||||||
})
|
})
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -72,7 +72,7 @@ describe("GithubCopilotPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("claude-sonnet-4")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("claude-sonnet-4")),
|
||||||
api: { id: ModelV2.ID.make("claude-sonnet-4"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("claude-sonnet-4"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -90,7 +90,7 @@ describe("GithubCopilotPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("alias")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("alias")),
|
||||||
api: { id: ModelV2.ID.make("claude-sonnet-4"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("claude-sonnet-4"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -108,7 +108,7 @@ describe("GithubCopilotPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -116,7 +116,7 @@ describe("GithubCopilotPlugin", () => {
|
|||||||
options: {},
|
options: {},
|
||||||
})
|
})
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5.1-codex")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5.1-codex")),
|
||||||
api: { id: ModelV2.ID.make("gpt-5.1-codex"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("gpt-5.1-codex"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -124,7 +124,7 @@ describe("GithubCopilotPlugin", () => {
|
|||||||
options: {},
|
options: {},
|
||||||
})
|
})
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-4o")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-4o")),
|
||||||
api: { id: ModelV2.ID.make("gpt-4o"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("gpt-4o"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -132,7 +132,7 @@ describe("GithubCopilotPlugin", () => {
|
|||||||
options: {},
|
options: {},
|
||||||
})
|
})
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5-mini")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5-mini")),
|
||||||
api: { id: ModelV2.ID.make("gpt-5-mini"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("gpt-5-mini"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -140,7 +140,7 @@ describe("GithubCopilotPlugin", () => {
|
|||||||
options: {},
|
options: {},
|
||||||
})
|
})
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5-mini-2025-08-07")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5-mini-2025-08-07")),
|
||||||
api: { id: ModelV2.ID.make("gpt-5-mini-2025-08-07"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("gpt-5-mini-2025-08-07"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -164,7 +164,7 @@ describe("GithubCopilotPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("default")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("default")),
|
||||||
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -172,7 +172,7 @@ describe("GithubCopilotPlugin", () => {
|
|||||||
options: {},
|
options: {},
|
||||||
})
|
})
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("small")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("small")),
|
||||||
api: { id: ModelV2.ID.make("gpt-5-mini"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("gpt-5-mini"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -180,7 +180,7 @@ describe("GithubCopilotPlugin", () => {
|
|||||||
options: {},
|
options: {},
|
||||||
})
|
})
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("sonnet")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("sonnet")),
|
||||||
api: { id: ModelV2.ID.make("claude-sonnet-4"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("claude-sonnet-4"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -228,7 +228,7 @@ describe("GithubCopilotPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runLanguage({
|
const result = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("openai"), ModelV2.ID.make("gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("openai"), ModelV2.ID.make("gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ describe("GitLabPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runSDK({
|
yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("claude")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("claude")),
|
||||||
api: { id: ModelV2.ID.make("claude"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("claude"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -105,7 +105,7 @@ describe("GitLabPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runSDK({
|
yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("claude")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("claude")),
|
||||||
api: { id: ModelV2.ID.make("claude"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("claude"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -130,7 +130,7 @@ describe("GitLabPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runSDK({
|
yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("claude")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("claude")),
|
||||||
api: { id: ModelV2.ID.make("claude"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("claude"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -171,7 +171,7 @@ describe("GitLabPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("claude")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("claude")),
|
||||||
api: { id: ModelV2.ID.make("claude"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("claude"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -190,7 +190,7 @@ describe("GitLabPlugin", () => {
|
|||||||
const calls: [string, unknown][] = []
|
const calls: [string, unknown][] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runLanguage({
|
const result = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("duo-workflow-custom")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("duo-workflow-custom")),
|
||||||
api: { id: ModelV2.ID.make("duo-workflow-custom"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("duo-workflow-custom"), type: "aisdk", package: "test-provider" },
|
||||||
request: {
|
request: {
|
||||||
@@ -225,7 +225,7 @@ describe("GitLabPlugin", () => {
|
|||||||
const calls: [string, unknown][] = []
|
const calls: [string, unknown][] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runLanguage({
|
const result = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("duo-workflow-exact")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("duo-workflow-exact")),
|
||||||
api: { id: ModelV2.ID.make("duo-workflow-exact"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("duo-workflow-exact"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -252,7 +252,7 @@ describe("GitLabPlugin", () => {
|
|||||||
const calls: [string, unknown][] = []
|
const calls: [string, unknown][] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("duo-workflow-custom")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("duo-workflow-custom")),
|
||||||
api: { id: ModelV2.ID.make("duo-workflow-custom"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("duo-workflow-custom"), type: "aisdk", package: "test-provider" },
|
||||||
request: {
|
request: {
|
||||||
@@ -280,7 +280,7 @@ describe("GitLabPlugin", () => {
|
|||||||
const calls: [string, unknown][] = []
|
const calls: [string, unknown][] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("claude")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("claude")),
|
||||||
api: { id: ModelV2.ID.make("claude"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("claude"), type: "aisdk", package: "test-provider" },
|
||||||
request: { headers: { h: "v" }, body: {} },
|
request: { headers: { h: "v" }, body: {} },
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ describe("GoogleVertexAnthropicPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin(GoogleVertexAnthropicPlugin)
|
yield* addPlugin(GoogleVertexAnthropicPlugin)
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(
|
...ModelV2.Info.empty(
|
||||||
ProviderV2.ID.make("google-vertex-anthropic"),
|
ProviderV2.ID.make("google-vertex-anthropic"),
|
||||||
ModelV2.ID.make("claude-sonnet-4-5"),
|
ModelV2.ID.make("claude-sonnet-4-5"),
|
||||||
@@ -142,7 +142,7 @@ describe("GoogleVertexAnthropicPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin(GoogleVertexAnthropicPlugin)
|
yield* addPlugin(GoogleVertexAnthropicPlugin)
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(
|
...ModelV2.Info.empty(
|
||||||
ProviderV2.ID.make("google-vertex-anthropic"),
|
ProviderV2.ID.make("google-vertex-anthropic"),
|
||||||
ModelV2.ID.make("claude-sonnet-4-5"),
|
ModelV2.ID.make("claude-sonnet-4-5"),
|
||||||
@@ -165,7 +165,7 @@ describe("GoogleVertexAnthropicPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin(GoogleVertexAnthropicPlugin)
|
yield* addPlugin(GoogleVertexAnthropicPlugin)
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -184,7 +184,7 @@ describe("GoogleVertexAnthropicPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin(GoogleVertexAnthropicPlugin)
|
yield* addPlugin(GoogleVertexAnthropicPlugin)
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -202,7 +202,7 @@ describe("GoogleVertexAnthropicPlugin", () => {
|
|||||||
yield* addPlugin(GoogleVertexPlugin)
|
yield* addPlugin(GoogleVertexPlugin)
|
||||||
yield* addPlugin(GoogleVertexAnthropicPlugin)
|
yield* addPlugin(GoogleVertexAnthropicPlugin)
|
||||||
const sdkResult = yield* aisdk.runSDK({
|
const sdkResult = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make(" claude-sonnet-4-5 ")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make(" claude-sonnet-4-5 ")),
|
||||||
api: { id: ModelV2.ID.make(" claude-sonnet-4-5 "), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make(" claude-sonnet-4-5 "), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -210,7 +210,7 @@ describe("GoogleVertexAnthropicPlugin", () => {
|
|||||||
options: { name: "google-vertex", project: "project", location: "us" },
|
options: { name: "google-vertex", project: "project", location: "us" },
|
||||||
})
|
})
|
||||||
const languageResult = yield* aisdk.runLanguage({
|
const languageResult = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make(" claude-sonnet-4-5 ")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make(" claude-sonnet-4-5 ")),
|
||||||
api: { id: ModelV2.ID.make(" claude-sonnet-4-5 "), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make(" claude-sonnet-4-5 "), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -232,7 +232,7 @@ describe("GoogleVertexAnthropicPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin(GoogleVertexAnthropicPlugin)
|
yield* addPlugin(GoogleVertexAnthropicPlugin)
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex-anthropic"), ModelV2.ID.make(" claude-sonnet-4-5 ")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex-anthropic"), ModelV2.ID.make(" claude-sonnet-4-5 ")),
|
||||||
api: { id: ModelV2.ID.make(" claude-sonnet-4-5 "), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make(" claude-sonnet-4-5 "), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -250,7 +250,7 @@ describe("GoogleVertexAnthropicPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin(GoogleVertexAnthropicPlugin)
|
yield* addPlugin(GoogleVertexAnthropicPlugin)
|
||||||
const result = yield* aisdk.runLanguage({
|
const result = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("claude-sonnet-4-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("claude-sonnet-4-5")),
|
||||||
api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ describe("GoogleVertexPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const provider = required(yield* catalog.provider.get(ProviderV2.ID.make("google-vertex")))
|
const provider = required(yield* catalog.provider.get(ProviderV2.ID.make("google-vertex")))
|
||||||
yield* aisdk.runSDK({
|
yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("gemini")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("gemini")),
|
||||||
api: {
|
api: {
|
||||||
id: ModelV2.ID.make("gemini"),
|
id: ModelV2.ID.make("gemini"),
|
||||||
@@ -295,7 +295,7 @@ describe("GoogleVertexPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runSDK({
|
yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("gemini")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("gemini")),
|
||||||
api: {
|
api: {
|
||||||
id: ModelV2.ID.make("gemini"),
|
id: ModelV2.ID.make("gemini"),
|
||||||
@@ -343,7 +343,7 @@ describe("GoogleVertexPlugin", () => {
|
|||||||
Effect.void,
|
Effect.void,
|
||||||
() =>
|
() =>
|
||||||
aisdk.runSDK({
|
aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("gemini")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("gemini")),
|
||||||
api: {
|
api: {
|
||||||
id: ModelV2.ID.make("gemini"),
|
id: ModelV2.ID.make("gemini"),
|
||||||
@@ -374,7 +374,7 @@ describe("GoogleVertexPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
yield* aisdk.runLanguage({
|
yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make(" gemini-2.5-pro ")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make(" gemini-2.5-pro ")),
|
||||||
api: { id: ModelV2.ID.make(" gemini-2.5-pro "), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make(" gemini-2.5-pro "), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ describe("GooglePlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom-google"), ModelV2.ID.make("gemini")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom-google"), ModelV2.ID.make("gemini")),
|
||||||
api: { id: ModelV2.ID.make("gemini"), type: "aisdk", package: "@ai-sdk/google" },
|
api: { id: ModelV2.ID.make("gemini"), type: "aisdk", package: "@ai-sdk/google" },
|
||||||
}),
|
}),
|
||||||
@@ -43,7 +43,7 @@ describe("GooglePlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("google"), ModelV2.ID.make("gemini")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("google"), ModelV2.ID.make("gemini")),
|
||||||
api: { id: ModelV2.ID.make("gemini"), type: "aisdk", package: "@ai-sdk/google" },
|
api: { id: ModelV2.ID.make("gemini"), type: "aisdk", package: "@ai-sdk/google" },
|
||||||
}),
|
}),
|
||||||
@@ -60,7 +60,7 @@ describe("GooglePlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const sdkEvent = yield* aisdk.runSDK({
|
const sdkEvent = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom-google"), ModelV2.ID.make("alias")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom-google"), ModelV2.ID.make("alias")),
|
||||||
api: { id: ModelV2.ID.make("gemini-api"), type: "aisdk", package: "@ai-sdk/google" },
|
api: { id: ModelV2.ID.make("gemini-api"), type: "aisdk", package: "@ai-sdk/google" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ describe("GroqPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("groq"), ModelV2.ID.make("llama")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("groq"), ModelV2.ID.make("llama")),
|
||||||
api: { id: ModelV2.ID.make("llama"), type: "aisdk", package: "@ai-sdk/groq" },
|
api: { id: ModelV2.ID.make("llama"), type: "aisdk", package: "@ai-sdk/groq" },
|
||||||
}),
|
}),
|
||||||
@@ -43,7 +43,7 @@ describe("GroqPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("groq"), ModelV2.ID.make("llama")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("groq"), ModelV2.ID.make("llama")),
|
||||||
api: { id: ModelV2.ID.make("llama"), type: "aisdk", package: "@ai-sdk/groq" },
|
api: { id: ModelV2.ID.make("llama"), type: "aisdk", package: "@ai-sdk/groq" },
|
||||||
}),
|
}),
|
||||||
@@ -60,7 +60,7 @@ describe("GroqPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("groq"), ModelV2.ID.make("llama")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("groq"), ModelV2.ID.make("llama")),
|
||||||
api: { id: ModelV2.ID.make("llama"), type: "aisdk", package: "@ai-sdk/groq" },
|
api: { id: ModelV2.ID.make("llama"), type: "aisdk", package: "@ai-sdk/groq" },
|
||||||
}),
|
}),
|
||||||
@@ -77,7 +77,7 @@ describe("GroqPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom-groq"), ModelV2.ID.make("llama")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom-groq"), ModelV2.ID.make("llama")),
|
||||||
api: { id: ModelV2.ID.make("llama"), type: "aisdk", package: "@ai-sdk/groq" },
|
api: { id: ModelV2.ID.make("llama"), type: "aisdk", package: "@ai-sdk/groq" },
|
||||||
}),
|
}),
|
||||||
@@ -102,7 +102,7 @@ describe("GroqPlugin", () => {
|
|||||||
name: string
|
name: string
|
||||||
})
|
})
|
||||||
const result = yield* aisdk.runLanguage({
|
const result = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("groq"), ModelV2.ID.make("alias")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("groq"), ModelV2.ID.make("alias")),
|
||||||
api: {
|
api: {
|
||||||
id: ModelV2.ID.make("llama-api"),
|
id: ModelV2.ID.make("llama-api"),
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ describe("MistralPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("mistral"), ModelV2.ID.make("mistral-large")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("mistral"), ModelV2.ID.make("mistral-large")),
|
||||||
api: { id: ModelV2.ID.make("mistral-large"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("mistral-large"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -43,7 +43,7 @@ describe("MistralPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("mistral"), ModelV2.ID.make("mistral-large")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("mistral"), ModelV2.ID.make("mistral-large")),
|
||||||
api: { id: ModelV2.ID.make("mistral-large"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("mistral-large"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -66,7 +66,7 @@ describe("MistralPlugin", () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("mistral"), ModelV2.ID.make("mistral-large")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("mistral"), ModelV2.ID.make("mistral-large")),
|
||||||
api: { id: ModelV2.ID.make("mistral-large"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("mistral-large"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -90,7 +90,7 @@ describe("MistralPlugin", () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
yield* aisdk.runSDK({
|
yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom-mistral"), ModelV2.ID.make("mistral-large")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom-mistral"), ModelV2.ID.make("mistral-large")),
|
||||||
api: { id: ModelV2.ID.make("mistral-large"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("mistral-large"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -114,7 +114,7 @@ describe("MistralPlugin", () => {
|
|||||||
}
|
}
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runLanguage({
|
const result = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("mistral"), ModelV2.ID.make("alias")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("mistral"), ModelV2.ID.make("alias")),
|
||||||
api: { id: ModelV2.ID.make("mistral-large"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("mistral-large"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ describe("OpenAICompatiblePlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const defaulted = yield* aisdk.runSDK({
|
const defaulted = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -33,7 +33,7 @@ describe("OpenAICompatiblePlugin", () => {
|
|||||||
options: { name: "custom" },
|
options: { name: "custom" },
|
||||||
})
|
})
|
||||||
const disabled = yield* aisdk.runSDK({
|
const disabled = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -51,7 +51,7 @@ describe("OpenAICompatiblePlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -74,7 +74,7 @@ describe("OpenAICompatiblePlugin", () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
yield* aisdk.runSDK({
|
yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom-provider"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom-provider"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -94,7 +94,7 @@ describe("OpenAICompatiblePlugin", () => {
|
|||||||
})
|
})
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ describe("OpenAIPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom-openai"), ModelV2.ID.make("gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom-openai"), ModelV2.ID.make("gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -82,7 +82,7 @@ describe("OpenAIPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -100,7 +100,7 @@ describe("OpenAIPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runLanguage({
|
const result = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("alias")),
|
...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("alias")),
|
||||||
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -119,7 +119,7 @@ describe("OpenAIPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runLanguage({
|
const result = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.anthropic, ModelV2.ID.make("gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.anthropic, ModelV2.ID.make("gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -135,7 +135,7 @@ describe("OpenAIPlugin", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const catalog = yield* Catalog.Service
|
const catalog = yield* Catalog.Service
|
||||||
yield* catalog.transform((catalog) => {
|
yield* catalog.transform((catalog) => {
|
||||||
const item = new ProviderV2.Info({
|
const item = ProviderV2.Info.make({
|
||||||
...ProviderV2.Info.empty(ProviderV2.ID.openai),
|
...ProviderV2.Info.empty(ProviderV2.ID.openai),
|
||||||
api: { type: "aisdk", package: "@ai-sdk/openai" },
|
api: { type: "aisdk", package: "@ai-sdk/openai" },
|
||||||
})
|
})
|
||||||
@@ -157,7 +157,7 @@ describe("OpenAIPlugin", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const catalog = yield* Catalog.Service
|
const catalog = yield* Catalog.Service
|
||||||
yield* catalog.transform((catalog) => {
|
yield* catalog.transform((catalog) => {
|
||||||
const item = new ProviderV2.Info({
|
const item = ProviderV2.Info.make({
|
||||||
...ProviderV2.Info.empty(ProviderV2.ID.make("custom-openai")),
|
...ProviderV2.Info.empty(ProviderV2.ID.make("custom-openai")),
|
||||||
api: { type: "aisdk", package: "test-provider" },
|
api: { type: "aisdk", package: "test-provider" },
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ describe("OpencodePlugin", () => {
|
|||||||
})
|
})
|
||||||
yield* credentials.create({
|
yield* credentials.create({
|
||||||
integrationID: Integration.ID.make("opencode"),
|
integrationID: Integration.ID.make("opencode"),
|
||||||
value: new Credential.Key({
|
value: Credential.Key.make({
|
||||||
type: "key",
|
type: "key",
|
||||||
key: "secret",
|
key: "secret",
|
||||||
metadata: { server: server.url.origin },
|
metadata: { server: server.url.origin },
|
||||||
@@ -176,11 +176,11 @@ describe("OpencodePlugin", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const catalog = yield* Catalog.Service
|
const catalog = yield* Catalog.Service
|
||||||
yield* catalog.transform((catalog) => {
|
yield* catalog.transform((catalog) => {
|
||||||
const provider = new ProviderV2.Info({
|
const provider = ProviderV2.Info.make({
|
||||||
...ProviderV2.Info.empty(ProviderV2.ID.opencode),
|
...ProviderV2.Info.empty(ProviderV2.ID.opencode),
|
||||||
api: { type: "aisdk", package: "test-provider" },
|
api: { type: "aisdk", package: "test-provider" },
|
||||||
})
|
})
|
||||||
const model = new ModelV2.Info({
|
const model = ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(provider.id, ModelV2.ID.make("paid")),
|
...ModelV2.Info.empty(provider.id, ModelV2.ID.make("paid")),
|
||||||
api: { id: ModelV2.ID.make("paid"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("paid"), type: "aisdk", package: "test-provider" },
|
||||||
cost: cost(1),
|
cost: cost(1),
|
||||||
@@ -202,11 +202,11 @@ describe("OpencodePlugin", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const catalog = yield* Catalog.Service
|
const catalog = yield* Catalog.Service
|
||||||
yield* catalog.transform((catalog) => {
|
yield* catalog.transform((catalog) => {
|
||||||
const provider = new ProviderV2.Info({
|
const provider = ProviderV2.Info.make({
|
||||||
...ProviderV2.Info.empty(ProviderV2.ID.opencode),
|
...ProviderV2.Info.empty(ProviderV2.ID.opencode),
|
||||||
api: { type: "aisdk", package: "test-provider" },
|
api: { type: "aisdk", package: "test-provider" },
|
||||||
})
|
})
|
||||||
const model = new ModelV2.Info({
|
const model = ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(provider.id, ModelV2.ID.make("free")),
|
...ModelV2.Info.empty(provider.id, ModelV2.ID.make("free")),
|
||||||
api: { id: ModelV2.ID.make("free"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("free"), type: "aisdk", package: "test-provider" },
|
||||||
cost: cost(0),
|
cost: cost(0),
|
||||||
@@ -228,11 +228,11 @@ describe("OpencodePlugin", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const catalog = yield* Catalog.Service
|
const catalog = yield* Catalog.Service
|
||||||
yield* catalog.transform((catalog) => {
|
yield* catalog.transform((catalog) => {
|
||||||
const provider = new ProviderV2.Info({
|
const provider = ProviderV2.Info.make({
|
||||||
...ProviderV2.Info.empty(ProviderV2.ID.opencode),
|
...ProviderV2.Info.empty(ProviderV2.ID.opencode),
|
||||||
api: { type: "aisdk", package: "test-provider" },
|
api: { type: "aisdk", package: "test-provider" },
|
||||||
})
|
})
|
||||||
const model = new ModelV2.Info({
|
const model = ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(provider.id, ModelV2.ID.make("output-only")),
|
...ModelV2.Info.empty(provider.id, ModelV2.ID.make("output-only")),
|
||||||
api: { id: ModelV2.ID.make("output-only"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("output-only"), type: "aisdk", package: "test-provider" },
|
||||||
cost: cost(0, 1),
|
cost: cost(0, 1),
|
||||||
@@ -256,11 +256,11 @@ describe("OpencodePlugin", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const catalog = yield* Catalog.Service
|
const catalog = yield* Catalog.Service
|
||||||
yield* catalog.transform((catalog) => {
|
yield* catalog.transform((catalog) => {
|
||||||
const provider = new ProviderV2.Info({
|
const provider = ProviderV2.Info.make({
|
||||||
...ProviderV2.Info.empty(ProviderV2.ID.opencode),
|
...ProviderV2.Info.empty(ProviderV2.ID.opencode),
|
||||||
api: { type: "aisdk", package: "test-provider" },
|
api: { type: "aisdk", package: "test-provider" },
|
||||||
})
|
})
|
||||||
const model = new ModelV2.Info({
|
const model = ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(provider.id, ModelV2.ID.make("paid")),
|
...ModelV2.Info.empty(provider.id, ModelV2.ID.make("paid")),
|
||||||
api: { id: ModelV2.ID.make("paid"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("paid"), type: "aisdk", package: "test-provider" },
|
||||||
cost: cost(1),
|
cost: cost(1),
|
||||||
@@ -289,11 +289,11 @@ describe("OpencodePlugin", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
yield* catalog.transform((catalog) => {
|
yield* catalog.transform((catalog) => {
|
||||||
const provider = new ProviderV2.Info({
|
const provider = ProviderV2.Info.make({
|
||||||
...ProviderV2.Info.empty(ProviderV2.ID.opencode),
|
...ProviderV2.Info.empty(ProviderV2.ID.opencode),
|
||||||
api: { type: "aisdk", package: "test-provider" },
|
api: { type: "aisdk", package: "test-provider" },
|
||||||
})
|
})
|
||||||
const model = new ModelV2.Info({
|
const model = ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(provider.id, ModelV2.ID.make("paid")),
|
...ModelV2.Info.empty(provider.id, ModelV2.ID.make("paid")),
|
||||||
api: { id: ModelV2.ID.make("paid"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("paid"), type: "aisdk", package: "test-provider" },
|
||||||
cost: cost(1),
|
cost: cost(1),
|
||||||
@@ -315,7 +315,7 @@ describe("OpencodePlugin", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const catalog = yield* Catalog.Service
|
const catalog = yield* Catalog.Service
|
||||||
yield* catalog.transform((catalog) => {
|
yield* catalog.transform((catalog) => {
|
||||||
const provider = new ProviderV2.Info({
|
const provider = ProviderV2.Info.make({
|
||||||
...ProviderV2.Info.empty(ProviderV2.ID.opencode),
|
...ProviderV2.Info.empty(ProviderV2.ID.opencode),
|
||||||
api: { type: "aisdk", package: "test-provider" },
|
api: { type: "aisdk", package: "test-provider" },
|
||||||
request: {
|
request: {
|
||||||
@@ -323,7 +323,7 @@ describe("OpencodePlugin", () => {
|
|||||||
body: { apiKey: "configured" },
|
body: { apiKey: "configured" },
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const model = new ModelV2.Info({
|
const model = ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(provider.id, ModelV2.ID.make("paid")),
|
...ModelV2.Info.empty(provider.id, ModelV2.ID.make("paid")),
|
||||||
api: { id: ModelV2.ID.make("paid"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("paid"), type: "aisdk", package: "test-provider" },
|
||||||
cost: cost(1),
|
cost: cost(1),
|
||||||
@@ -347,11 +347,11 @@ describe("OpencodePlugin", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const catalog = yield* Catalog.Service
|
const catalog = yield* Catalog.Service
|
||||||
yield* catalog.transform((catalog) => {
|
yield* catalog.transform((catalog) => {
|
||||||
const provider = new ProviderV2.Info({
|
const provider = ProviderV2.Info.make({
|
||||||
...ProviderV2.Info.empty(ProviderV2.ID.openai),
|
...ProviderV2.Info.empty(ProviderV2.ID.openai),
|
||||||
api: { type: "aisdk", package: "test-provider" },
|
api: { type: "aisdk", package: "test-provider" },
|
||||||
})
|
})
|
||||||
const model = new ModelV2.Info({
|
const model = ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(provider.id, ModelV2.ID.make("paid")),
|
...ModelV2.Info.empty(provider.id, ModelV2.ID.make("paid")),
|
||||||
api: { id: ModelV2.ID.make("paid"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("paid"), type: "aisdk", package: "test-provider" },
|
||||||
cost: cost(1),
|
cost: cost(1),
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ describe("OpenRouterPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
const ignored = yield* aisdk.runSDK({
|
const ignored = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.openrouter, ModelV2.ID.make("openai/gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.openrouter, ModelV2.ID.make("openai/gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -63,7 +63,7 @@ describe("OpenRouterPlugin", () => {
|
|||||||
expect(ignored.sdk).toBeUndefined()
|
expect(ignored.sdk).toBeUndefined()
|
||||||
|
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("openai/gpt-5")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("openai/gpt-5")),
|
||||||
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ describe("PerplexityPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("perplexity"), ModelV2.ID.make("sonar")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("perplexity"), ModelV2.ID.make("sonar")),
|
||||||
api: { id: ModelV2.ID.make("sonar"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("sonar"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -56,7 +56,7 @@ describe("PerplexityPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("perplexity"), ModelV2.ID.make("sonar")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("perplexity"), ModelV2.ID.make("sonar")),
|
||||||
api: { id: ModelV2.ID.make("sonar"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("sonar"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -73,7 +73,7 @@ describe("PerplexityPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("perplexity"), ModelV2.ID.make("sonar")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("perplexity"), ModelV2.ID.make("sonar")),
|
||||||
api: { id: ModelV2.ID.make("sonar"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("sonar"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -90,7 +90,7 @@ describe("PerplexityPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom-perplexity"), ModelV2.ID.make("sonar")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom-perplexity"), ModelV2.ID.make("sonar")),
|
||||||
api: { id: ModelV2.ID.make("sonar"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("sonar"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -108,7 +108,7 @@ describe("PerplexityPlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runLanguage({
|
const result = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("perplexity"), ModelV2.ID.make("alias")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("perplexity"), ModelV2.ID.make("alias")),
|
||||||
api: { id: ModelV2.ID.make("sonar"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("sonar"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ function withEnv<A, E, R>(vars: Record<string, string | undefined>, effect: () =
|
|||||||
}
|
}
|
||||||
|
|
||||||
function model(providerID: string) {
|
function model(providerID: string) {
|
||||||
return new ModelV2.Info({
|
return ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make(providerID), ModelV2.ID.make("sap-model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make(providerID), ModelV2.ID.make("sap-model")),
|
||||||
api: { id: ModelV2.ID.make("sap-model"), type: "aisdk", package: fixtureProvider },
|
api: { id: ModelV2.ID.make("sap-model"), type: "aisdk", package: fixtureProvider },
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ describe("SnowflakeCortexPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("openai"), ModelV2.ID.make("gpt-4")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("openai"), ModelV2.ID.make("gpt-4")),
|
||||||
api: { id: ModelV2.ID.make("gpt-4"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("gpt-4"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -73,7 +73,7 @@ describe("SnowflakeCortexPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("snowflake-cortex"), ModelV2.ID.make("claude-sonnet-4-6")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("snowflake-cortex"), ModelV2.ID.make("claude-sonnet-4-6")),
|
||||||
api: { id: ModelV2.ID.make("claude-sonnet-4-6"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("claude-sonnet-4-6"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -92,7 +92,7 @@ describe("SnowflakeCortexPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("snowflake-cortex"), ModelV2.ID.make("claude-sonnet-4-6")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("snowflake-cortex"), ModelV2.ID.make("claude-sonnet-4-6")),
|
||||||
api: { id: ModelV2.ID.make("claude-sonnet-4-6"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("claude-sonnet-4-6"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -115,7 +115,7 @@ describe("SnowflakeCortexPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("snowflake-cortex"), ModelV2.ID.make("claude-sonnet-4-6")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("snowflake-cortex"), ModelV2.ID.make("claude-sonnet-4-6")),
|
||||||
api: { id: ModelV2.ID.make("claude-sonnet-4-6"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("claude-sonnet-4-6"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -134,7 +134,7 @@ describe("SnowflakeCortexPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("snowflake-cortex"), ModelV2.ID.make("claude-sonnet-4-6")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("snowflake-cortex"), ModelV2.ID.make("claude-sonnet-4-6")),
|
||||||
api: { id: ModelV2.ID.make("claude-sonnet-4-6"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("claude-sonnet-4-6"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -157,7 +157,7 @@ describe("SnowflakeCortexPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("snowflake-cortex"), ModelV2.ID.make("claude-sonnet-4-6")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("snowflake-cortex"), ModelV2.ID.make("claude-sonnet-4-6")),
|
||||||
api: { id: ModelV2.ID.make("claude-sonnet-4-6"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("claude-sonnet-4-6"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ describe("TogetherAIPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("togetherai"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("togetherai"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -57,7 +57,7 @@ describe("TogetherAIPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
const ignored = yield* aisdk.runSDK({
|
const ignored = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("togetherai"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("togetherai"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -67,7 +67,7 @@ describe("TogetherAIPlugin", () => {
|
|||||||
expect(ignored.sdk).toBeUndefined()
|
expect(ignored.sdk).toBeUndefined()
|
||||||
|
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("togetherai"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("togetherai"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -85,7 +85,7 @@ describe("TogetherAIPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom-togetherai"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom-togetherai"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -105,7 +105,7 @@ describe("TogetherAIPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
const result = yield* aisdk.runLanguage({
|
const result = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(
|
...ModelV2.Info.empty(
|
||||||
ProviderV2.ID.make("togetherai"),
|
ProviderV2.ID.make("togetherai"),
|
||||||
ModelV2.ID.make("meta-llama/Llama-3.3-70B-Instruct-Turbo"),
|
ModelV2.ID.make("meta-llama/Llama-3.3-70B-Instruct-Turbo"),
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ describe("VenicePlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("venice"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("venice"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -56,7 +56,7 @@ describe("VenicePlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom-venice"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom-venice"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -74,7 +74,7 @@ describe("VenicePlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const similar = yield* aisdk.runSDK({
|
const similar = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("venice"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("venice"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -82,7 +82,7 @@ describe("VenicePlugin", () => {
|
|||||||
options: { name: "venice" },
|
options: { name: "venice" },
|
||||||
})
|
})
|
||||||
const other = yield* aisdk.runSDK({
|
const other = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("venice"), ModelV2.ID.make("model")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("venice"), ModelV2.ID.make("model")),
|
||||||
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
@@ -101,7 +101,7 @@ describe("VenicePlugin", () => {
|
|||||||
const calls: string[] = []
|
const calls: string[] = []
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runLanguage({
|
const result = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("venice"), ModelV2.ID.make("alias")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("venice"), ModelV2.ID.make("alias")),
|
||||||
api: { id: ModelV2.ID.make("alias"), type: "aisdk", package: "test-provider" },
|
api: { id: ModelV2.ID.make("alias"), type: "aisdk", package: "test-provider" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ describe("VercelPlugin", () => {
|
|||||||
const aisdk = yield* AISDK.Service
|
const aisdk = yield* AISDK.Service
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const event = yield* aisdk.runSDK({
|
const event = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom-vercel"), ModelV2.ID.make("v0-1.0-md")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom-vercel"), ModelV2.ID.make("v0-1.0-md")),
|
||||||
api: { id: ModelV2.ID.make("v0-1.0-md"), type: "aisdk", package: "@ai-sdk/vercel" },
|
api: { id: ModelV2.ID.make("v0-1.0-md"), type: "aisdk", package: "@ai-sdk/vercel" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ describe("XAIPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
const ignored = yield* aisdk.runSDK({
|
const ignored = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("xai"), ModelV2.ID.make("grok-4")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("xai"), ModelV2.ID.make("grok-4")),
|
||||||
api: { id: ModelV2.ID.make("grok-4"), type: "aisdk", package: "@ai-sdk/xai" },
|
api: { id: ModelV2.ID.make("grok-4"), type: "aisdk", package: "@ai-sdk/xai" },
|
||||||
}),
|
}),
|
||||||
@@ -49,7 +49,7 @@ describe("XAIPlugin", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("xai"), ModelV2.ID.make("grok-4")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("xai"), ModelV2.ID.make("grok-4")),
|
||||||
api: { id: ModelV2.ID.make("grok-4"), type: "aisdk", package: "@ai-sdk/xai" },
|
api: { id: ModelV2.ID.make("grok-4"), type: "aisdk", package: "@ai-sdk/xai" },
|
||||||
}),
|
}),
|
||||||
@@ -69,7 +69,7 @@ describe("XAIPlugin", () => {
|
|||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
|
|
||||||
const result = yield* aisdk.runSDK({
|
const result = yield* aisdk.runSDK({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("custom-xai"), ModelV2.ID.make("grok-4")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("custom-xai"), ModelV2.ID.make("grok-4")),
|
||||||
api: { id: ModelV2.ID.make("grok-4"), type: "aisdk", package: "@ai-sdk/xai" },
|
api: { id: ModelV2.ID.make("grok-4"), type: "aisdk", package: "@ai-sdk/xai" },
|
||||||
}),
|
}),
|
||||||
@@ -89,7 +89,7 @@ describe("XAIPlugin", () => {
|
|||||||
|
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runLanguage({
|
const result = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.make("xai"), ModelV2.ID.make("alias")),
|
...ModelV2.Info.empty(ProviderV2.ID.make("xai"), ModelV2.ID.make("alias")),
|
||||||
api: { id: ModelV2.ID.make("grok-4"), type: "aisdk", package: "@ai-sdk/xai" },
|
api: { id: ModelV2.ID.make("grok-4"), type: "aisdk", package: "@ai-sdk/xai" },
|
||||||
}),
|
}),
|
||||||
@@ -110,7 +110,7 @@ describe("XAIPlugin", () => {
|
|||||||
|
|
||||||
yield* addPlugin()
|
yield* addPlugin()
|
||||||
const result = yield* aisdk.runLanguage({
|
const result = yield* aisdk.runLanguage({
|
||||||
model: new ModelV2.Info({
|
model: ModelV2.Info.make({
|
||||||
...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("grok-4")),
|
...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("grok-4")),
|
||||||
api: { id: ModelV2.ID.make("grok-4"), type: "aisdk", package: "@ai-sdk/xai" },
|
api: { id: ModelV2.ID.make("grok-4"), type: "aisdk", package: "@ai-sdk/xai" },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ describe("ReferenceGuidance", () => {
|
|||||||
name: "docs",
|
name: "docs",
|
||||||
path: AbsolutePath.make("/docs"),
|
path: AbsolutePath.make("/docs"),
|
||||||
description: "Use for product documentation",
|
description: "Use for product documentation",
|
||||||
source: new Reference.LocalSource({
|
source: Reference.LocalSource.make({
|
||||||
type: "local",
|
type: "local",
|
||||||
path: AbsolutePath.make("/docs"),
|
path: AbsolutePath.make("/docs"),
|
||||||
description: "Use for product documentation",
|
description: "Use for product documentation",
|
||||||
@@ -63,7 +63,7 @@ describe("ReferenceGuidance", () => {
|
|||||||
new Reference.Info({
|
new Reference.Info({
|
||||||
name: "docs",
|
name: "docs",
|
||||||
path: AbsolutePath.make("/docs"),
|
path: AbsolutePath.make("/docs"),
|
||||||
source: new Reference.LocalSource({ type: "local", path: AbsolutePath.make("/docs") }),
|
source: Reference.LocalSource.make({ type: "local", path: AbsolutePath.make("/docs") }),
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ describe("Reference", () => {
|
|||||||
const references = yield* Reference.Service
|
const references = yield* Reference.Service
|
||||||
const scope = yield* Scope.make()
|
const scope = yield* Scope.make()
|
||||||
const path = AbsolutePath.make("/docs")
|
const path = AbsolutePath.make("/docs")
|
||||||
const source = new Reference.LocalSource({
|
const source = Reference.LocalSource.make({
|
||||||
type: "local",
|
type: "local",
|
||||||
path,
|
path,
|
||||||
description: "Use for API documentation",
|
description: "Use for API documentation",
|
||||||
@@ -44,7 +44,7 @@ describe("Reference", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const references = yield* Reference.Service
|
const references = yield* Reference.Service
|
||||||
const repository = Repository.parseRemote("owner/repo")
|
const repository = Repository.parseRemote("owner/repo")
|
||||||
const source = new Reference.GitSource({ type: "git", repository: "owner/repo", branch: "main" })
|
const source = Reference.GitSource.make({ type: "git", repository: "owner/repo", branch: "main" })
|
||||||
yield* references.transform((editor) => editor.add("sdk", source))
|
yield* references.transform((editor) => editor.add("sdk", source))
|
||||||
|
|
||||||
expect(yield* references.list()).toEqual([
|
expect(yield* references.list()).toEqual([
|
||||||
@@ -67,7 +67,7 @@ describe("Reference", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const references = yield* Reference.Service
|
const references = yield* Reference.Service
|
||||||
const repository = Repository.parseRemote("owner/repo")
|
const repository = Repository.parseRemote("owner/repo")
|
||||||
const source = new Reference.GitSource({
|
const source = Reference.GitSource.make({
|
||||||
type: "git",
|
type: "git",
|
||||||
repository: "owner/repo",
|
repository: "owner/repo",
|
||||||
description: "Use for SDK implementation details",
|
description: "Use for SDK implementation details",
|
||||||
|
|||||||
@@ -55,21 +55,6 @@ const location = Location.Ref.make({ directory: AbsolutePath.make("/project") })
|
|||||||
const id = SessionV2.ID.create()
|
const id = SessionV2.ID.create()
|
||||||
|
|
||||||
describe("SessionV2.create", () => {
|
describe("SessionV2.create", () => {
|
||||||
it.effect("derives stable namespaced external IDs", () =>
|
|
||||||
Effect.sync(() => {
|
|
||||||
const input = { namespace: "opencord.agent-thread", key: "thread-1" }
|
|
||||||
|
|
||||||
expect(SessionV2.ID.fromExternal(input)).toBe(SessionV2.ID.fromExternal(input))
|
|
||||||
expect(SessionV2.ID.fromExternal(input)).toMatch(/^ses_[a-f0-9]{64}$/)
|
|
||||||
expect(SessionV2.ID.fromExternal({ ...input, namespace: "another-app" })).not.toBe(
|
|
||||||
SessionV2.ID.fromExternal(input),
|
|
||||||
)
|
|
||||||
expect(SessionV2.ID.fromExternal({ namespace: "a:b", key: "c" })).not.toBe(
|
|
||||||
SessionV2.ID.fromExternal({ namespace: "a", key: "b:c" }),
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
it.effect("creates a fresh projected session when the ID is omitted", () =>
|
it.effect("creates a fresh projected session when the ID is omitted", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
@@ -218,7 +203,7 @@ describe("SessionV2.create", () => {
|
|||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
const { db } = yield* Database.Service
|
const { db } = yield* Database.Service
|
||||||
const created = yield* session.create({ location })
|
const created = yield* session.create({ location })
|
||||||
yield* session.prompt({ sessionID: created.id, prompt: new Prompt({ text: "Hello" }), resume: false })
|
yield* session.prompt({ sessionID: created.id, prompt: Prompt.make({ text: "Hello" }), resume: false })
|
||||||
yield* SessionInput.promoteSteers(db, events, created.id, Number.MAX_SAFE_INTEGER)
|
yield* SessionInput.promoteSteers(db, events, created.id, Number.MAX_SAFE_INTEGER)
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@@ -238,7 +223,7 @@ describe("SessionV2.create", () => {
|
|||||||
const created = yield* session.create({ id: SessionV2.ID.make("ses_fresh_target_replay"), location })
|
const created = yield* session.create({ id: SessionV2.ID.make("ses_fresh_target_replay"), location })
|
||||||
const admitted = yield* session.prompt({
|
const admitted = yield* session.prompt({
|
||||||
sessionID: created.id,
|
sessionID: created.id,
|
||||||
prompt: new Prompt({ text: "Replay lifecycle" }),
|
prompt: Prompt.make({ text: "Replay lifecycle" }),
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
yield* SessionInput.promoteSteers(sourceDb, sourceEvents, created.id, Number.MAX_SAFE_INTEGER)
|
yield* SessionInput.promoteSteers(sourceDb, sourceEvents, created.id, Number.MAX_SAFE_INTEGER)
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const assistantRow = (
|
|||||||
id: _,
|
id: _,
|
||||||
type,
|
type,
|
||||||
...data
|
...data
|
||||||
} = encodeMessage(new SessionMessage.Assistant({ id, type: "assistant", agent: "build", model, content: [], time }))
|
} = encodeMessage(SessionMessage.Assistant.make({ id, type: "assistant", agent: "build", model, content: [], time }))
|
||||||
return { id, session_id: sessionID, type, seq, time_created: DateTime.toEpochMillis(time.created), data }
|
return { id, session_id: sessionID, type, seq, time_created: DateTime.toEpochMillis(time.created), data }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ describe("SessionProjector", () => {
|
|||||||
sessionID,
|
sessionID,
|
||||||
messageID: SessionMessage.ID.make("msg_first"),
|
messageID: SessionMessage.ID.make("msg_first"),
|
||||||
timestamp: created,
|
timestamp: created,
|
||||||
prompt: new Prompt({ text: "first" }),
|
prompt: Prompt.make({ text: "first" }),
|
||||||
delivery: "steer",
|
delivery: "steer",
|
||||||
},
|
},
|
||||||
{ id: EventV2.ID.make("evt_z") },
|
{ id: EventV2.ID.make("evt_z") },
|
||||||
@@ -80,7 +80,7 @@ describe("SessionProjector", () => {
|
|||||||
sessionID,
|
sessionID,
|
||||||
messageID: SessionMessage.ID.make("msg_second"),
|
messageID: SessionMessage.ID.make("msg_second"),
|
||||||
timestamp: created,
|
timestamp: created,
|
||||||
prompt: new Prompt({ text: "second" }),
|
prompt: Prompt.make({ text: "second" }),
|
||||||
delivery: "steer",
|
delivery: "steer",
|
||||||
},
|
},
|
||||||
{ id: EventV2.ID.make("evt_a") },
|
{ id: EventV2.ID.make("evt_a") },
|
||||||
@@ -145,7 +145,7 @@ describe("SessionProjector", () => {
|
|||||||
const admitted = yield* SessionInput.admit(db, events, {
|
const admitted = yield* SessionInput.admit(db, events, {
|
||||||
id,
|
id,
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "promote me" }),
|
prompt: Prompt.make({ text: "promote me" }),
|
||||||
delivery: "steer",
|
delivery: "steer",
|
||||||
})
|
})
|
||||||
if (!admitted) return yield* Effect.die("Prompt admission failed")
|
if (!admitted) return yield* Effect.die("Prompt admission failed")
|
||||||
@@ -154,7 +154,7 @@ describe("SessionProjector", () => {
|
|||||||
sessionID,
|
sessionID,
|
||||||
timestamp: admitted.timeCreated,
|
timestamp: admitted.timeCreated,
|
||||||
messageID: id,
|
messageID: id,
|
||||||
prompt: new Prompt({ text: "promote me" }),
|
prompt: Prompt.make({ text: "promote me" }),
|
||||||
delivery: "steer",
|
delivery: "steer",
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -334,7 +334,7 @@ describe("SessionProjector", () => {
|
|||||||
|
|
||||||
it.effect("does not revive a stale incomplete in-memory assistant projection", () =>
|
it.effect("does not revive a stale incomplete in-memory assistant projection", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const stale = new SessionMessage.Assistant({
|
const stale = SessionMessage.Assistant.make({
|
||||||
id: SessionMessage.ID.make("msg_assistant_stale"),
|
id: SessionMessage.ID.make("msg_assistant_stale"),
|
||||||
type: "assistant",
|
type: "assistant",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
@@ -342,7 +342,7 @@ describe("SessionProjector", () => {
|
|||||||
content: [],
|
content: [],
|
||||||
time: { created },
|
time: { created },
|
||||||
})
|
})
|
||||||
const completed = new SessionMessage.Assistant({
|
const completed = SessionMessage.Assistant.make({
|
||||||
id: SessionMessage.ID.make("msg_assistant_completed"),
|
id: SessionMessage.ID.make("msg_assistant_completed"),
|
||||||
type: "assistant",
|
type: "assistant",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
@@ -466,15 +466,15 @@ describe("SessionProjector", () => {
|
|||||||
Schema.decodeUnknownSync(SessionMessage.Message)({ ...row.data, id: row.id, type: row.type }),
|
Schema.decodeUnknownSync(SessionMessage.Message)({ ...row.data, id: row.id, type: row.type }),
|
||||||
)
|
)
|
||||||
expect(messages).toEqual([
|
expect(messages).toEqual([
|
||||||
new SessionMessage.Assistant({
|
SessionMessage.Assistant.make({
|
||||||
id: SessionMessage.ID.make("msg_assistant_completed"),
|
id: SessionMessage.ID.make("msg_assistant_completed"),
|
||||||
type: "assistant",
|
type: "assistant",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
model,
|
model,
|
||||||
content: [new SessionMessage.AssistantText({ type: "text", id: "text-stale", text: "" })],
|
content: [SessionMessage.AssistantText.make({ type: "text", id: "text-stale", text: "" })],
|
||||||
time: { created: DateTime.makeUnsafe(1), completed: DateTime.makeUnsafe(2) },
|
time: { created: DateTime.makeUnsafe(1), completed: DateTime.makeUnsafe(2) },
|
||||||
}),
|
}),
|
||||||
new SessionMessage.Assistant({
|
SessionMessage.Assistant.make({
|
||||||
id: SessionMessage.ID.make("msg_assistant_stale"),
|
id: SessionMessage.ID.make("msg_assistant_stale"),
|
||||||
type: "assistant",
|
type: "assistant",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ describe("SessionV2.prompt", () => {
|
|||||||
|
|
||||||
const message = yield* session.prompt({
|
const message = yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Fix the failing tests" }),
|
prompt: Prompt.make({ text: "Fix the failing tests" }),
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -171,8 +171,8 @@ describe("SessionV2.prompt", () => {
|
|||||||
const fiber = yield* session.events({ sessionID }).pipe(Stream.take(4), Stream.runCollect, Effect.forkScoped)
|
const fiber = yield* session.events({ sessionID }).pipe(Stream.take(4), Stream.runCollect, Effect.forkScoped)
|
||||||
yield* Effect.yieldNow
|
yield* Effect.yieldNow
|
||||||
|
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "First" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false })
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Second" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false })
|
||||||
yield* SessionInput.promoteSteers(db, events, sessionID, Number.MAX_SAFE_INTEGER)
|
yield* SessionInput.promoteSteers(db, events, sessionID, Number.MAX_SAFE_INTEGER)
|
||||||
const streamed = Array.from(yield* Fiber.join(fiber))
|
const streamed = Array.from(yield* Fiber.join(fiber))
|
||||||
|
|
||||||
@@ -198,7 +198,7 @@ describe("SessionV2.prompt", () => {
|
|||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const message = yield* session.prompt({
|
const message = yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Fix the failing tests" }),
|
prompt: Prompt.make({ text: "Fix the failing tests" }),
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -217,7 +217,7 @@ describe("SessionV2.prompt", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const input = { sessionID, prompt: new Prompt({ text: "Fix the failing tests" }), resume: false }
|
const input = { sessionID, prompt: Prompt.make({ text: "Fix the failing tests" }), resume: false }
|
||||||
|
|
||||||
const first = yield* session.prompt(input)
|
const first = yield* session.prompt(input)
|
||||||
const second = yield* session.prompt(input)
|
const second = yield* session.prompt(input)
|
||||||
@@ -235,7 +235,7 @@ describe("SessionV2.prompt", () => {
|
|||||||
const input = {
|
const input = {
|
||||||
sessionID,
|
sessionID,
|
||||||
id: messageID,
|
id: messageID,
|
||||||
prompt: new Prompt({ text: "Fix the failing tests" }),
|
prompt: Prompt.make({ text: "Fix the failing tests" }),
|
||||||
resume: false,
|
resume: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +255,7 @@ describe("SessionV2.prompt", () => {
|
|||||||
const input = {
|
const input = {
|
||||||
sessionID,
|
sessionID,
|
||||||
id: messageID,
|
id: messageID,
|
||||||
prompt: new Prompt({ text: "Recover committed prompt" }),
|
prompt: Prompt.make({ text: "Recover committed prompt" }),
|
||||||
resume: false,
|
resume: false,
|
||||||
}
|
}
|
||||||
const first = yield* session.prompt(input)
|
const first = yield* session.prompt(input)
|
||||||
@@ -276,13 +276,13 @@ describe("SessionV2.prompt", () => {
|
|||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
id: messageID,
|
id: messageID,
|
||||||
prompt: new Prompt({ text: "Fix the failing tests" }),
|
prompt: Prompt.make({ text: "Fix the failing tests" }),
|
||||||
})
|
})
|
||||||
const failure = yield* session
|
const failure = yield* session
|
||||||
.prompt({
|
.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
id: messageID,
|
id: messageID,
|
||||||
prompt: new Prompt({ text: "Delete the failing tests" }),
|
prompt: Prompt.make({ text: "Delete the failing tests" }),
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
.pipe(Effect.flip)
|
.pipe(Effect.flip)
|
||||||
@@ -301,14 +301,14 @@ describe("SessionV2.prompt", () => {
|
|||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
id: messageID,
|
id: messageID,
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Fix the failing tests" }),
|
prompt: Prompt.make({ text: "Fix the failing tests" }),
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
const failure = yield* session
|
const failure = yield* session
|
||||||
.prompt({
|
.prompt({
|
||||||
id: messageID,
|
id: messageID,
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Fix the failing tests" }),
|
prompt: Prompt.make({ text: "Fix the failing tests" }),
|
||||||
delivery: "queue",
|
delivery: "queue",
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
@@ -325,7 +325,7 @@ describe("SessionV2.prompt", () => {
|
|||||||
const input = {
|
const input = {
|
||||||
sessionID,
|
sessionID,
|
||||||
id: messageID,
|
id: messageID,
|
||||||
prompt: new Prompt({ text: "Fix the failing tests" }),
|
prompt: Prompt.make({ text: "Fix the failing tests" }),
|
||||||
resume: false,
|
resume: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,7 +344,7 @@ describe("SessionV2.prompt", () => {
|
|||||||
const { db } = yield* Database.Service
|
const { db } = yield* Database.Service
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
yield* session.prompt({ id: messageID, sessionID, prompt: new Prompt({ text: "Promote once" }), resume: false })
|
yield* session.prompt({ id: messageID, sessionID, prompt: Prompt.make({ text: "Promote once" }), resume: false })
|
||||||
|
|
||||||
yield* Effect.all(
|
yield* Effect.all(
|
||||||
[
|
[
|
||||||
@@ -368,9 +368,9 @@ describe("SessionV2.prompt", () => {
|
|||||||
const { db } = yield* Database.Service
|
const { db } = yield* Database.Service
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
const first = yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Before cutoff" }), resume: false })
|
const first = yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Before cutoff" }), resume: false })
|
||||||
const cutoff = first.admittedSeq
|
const cutoff = first.admittedSeq
|
||||||
const second = yield* session.prompt({ sessionID, prompt: new Prompt({ text: "After cutoff" }), resume: false })
|
const second = yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "After cutoff" }), resume: false })
|
||||||
|
|
||||||
yield* SessionInput.promoteSteers(db, events, sessionID, cutoff)
|
yield* SessionInput.promoteSteers(db, events, sessionID, cutoff)
|
||||||
|
|
||||||
@@ -386,7 +386,12 @@ describe("SessionV2.prompt", () => {
|
|||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
wakeCalls.length = 0
|
wakeCalls.length = 0
|
||||||
yield* session.prompt({ id: messageID, sessionID, prompt: new Prompt({ text: "Replay pending" }), resume: false })
|
yield* session.prompt({
|
||||||
|
id: messageID,
|
||||||
|
sessionID,
|
||||||
|
prompt: Prompt.make({ text: "Replay pending" }),
|
||||||
|
resume: false,
|
||||||
|
})
|
||||||
const recorded = yield* db
|
const recorded = yield* db
|
||||||
.select()
|
.select()
|
||||||
.from(EventTable)
|
.from(EventTable)
|
||||||
@@ -422,7 +427,7 @@ describe("SessionV2.prompt", () => {
|
|||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
const prompt = new Prompt({ text: "Historical prompt" })
|
const prompt = Prompt.make({ text: "Historical prompt" })
|
||||||
yield* events.publish(SessionEvent.Prompted, {
|
yield* events.publish(SessionEvent.Prompted, {
|
||||||
sessionID,
|
sessionID,
|
||||||
messageID,
|
messageID,
|
||||||
@@ -443,7 +448,7 @@ describe("SessionV2.prompt", () => {
|
|||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
const prompt = new Prompt({ text: "Historical queued prompt" })
|
const prompt = Prompt.make({ text: "Historical queued prompt" })
|
||||||
yield* events.publish(SessionEvent.Prompted, {
|
yield* events.publish(SessionEvent.Prompted, {
|
||||||
sessionID,
|
sessionID,
|
||||||
messageID,
|
messageID,
|
||||||
@@ -478,7 +483,7 @@ describe("SessionV2.prompt", () => {
|
|||||||
.onConflictDoNothing()
|
.onConflictDoNothing()
|
||||||
.run()
|
.run()
|
||||||
.pipe(Effect.orDie)
|
.pipe(Effect.orDie)
|
||||||
const prompt = new Prompt({ text: "Fix the failing tests" })
|
const prompt = Prompt.make({ text: "Fix the failing tests" })
|
||||||
|
|
||||||
yield* session.prompt({ id: messageID, sessionID, prompt, resume: false })
|
yield* session.prompt({ id: messageID, sessionID, prompt, resume: false })
|
||||||
const failure = yield* session
|
const failure = yield* session
|
||||||
@@ -502,7 +507,7 @@ describe("SessionV2.prompt", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const failure = yield* session
|
const failure = yield* session
|
||||||
.prompt({ id: messageID, sessionID, prompt: new Prompt({ text: "Conflicting prompt" }), resume: false })
|
.prompt({ id: messageID, sessionID, prompt: Prompt.make({ text: "Conflicting prompt" }), resume: false })
|
||||||
.pipe(Effect.flip)
|
.pipe(Effect.flip)
|
||||||
|
|
||||||
expect(failure).toMatchObject({ _tag: "Session.PromptConflictError", sessionID, messageID })
|
expect(failure).toMatchObject({ _tag: "Session.PromptConflictError", sessionID, messageID })
|
||||||
@@ -517,7 +522,7 @@ describe("SessionV2.prompt", () => {
|
|||||||
executionCalls.length = 0
|
executionCalls.length = 0
|
||||||
wakeCalls.length = 0
|
wakeCalls.length = 0
|
||||||
|
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Run by default" }) })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Run by default" }) })
|
||||||
|
|
||||||
expect(executionCalls).toEqual([])
|
expect(executionCalls).toEqual([])
|
||||||
expect(wakeCalls).toEqual([sessionID])
|
expect(wakeCalls).toEqual([sessionID])
|
||||||
@@ -533,7 +538,7 @@ describe("SessionV2.prompt", () => {
|
|||||||
|
|
||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Run explicitly" }),
|
prompt: Prompt.make({ text: "Run explicitly" }),
|
||||||
resume: true,
|
resume: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -549,7 +554,7 @@ describe("SessionV2.prompt", () => {
|
|||||||
executionCalls.length = 0
|
executionCalls.length = 0
|
||||||
wakeCalls.length = 0
|
wakeCalls.length = 0
|
||||||
|
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Do not run" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Do not run" }), resume: false })
|
||||||
|
|
||||||
expect(executionCalls).toEqual([])
|
expect(executionCalls).toEqual([])
|
||||||
expect(wakeCalls).toEqual([])
|
expect(wakeCalls).toEqual([])
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const model = Model.make({ id: "model", provider: "provider", route: OpenAIChat.
|
|||||||
describe("toLLMMessages", () => {
|
describe("toLLMMessages", () => {
|
||||||
test("omits empty assistant turns", () => {
|
test("omits empty assistant turns", () => {
|
||||||
const assistant = (value: string, content: SessionMessage.Assistant["content"]) =>
|
const assistant = (value: string, content: SessionMessage.Assistant["content"]) =>
|
||||||
new SessionMessage.Assistant({
|
SessionMessage.Assistant.make({
|
||||||
id: id(value),
|
id: id(value),
|
||||||
type: "assistant",
|
type: "assistant",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
@@ -27,13 +27,13 @@ describe("toLLMMessages", () => {
|
|||||||
const messages = toLLMMessages(
|
const messages = toLLMMessages(
|
||||||
[
|
[
|
||||||
assistant("empty", []),
|
assistant("empty", []),
|
||||||
assistant("empty-text", [new SessionMessage.AssistantText({ type: "text", id: "empty", text: "" })]),
|
assistant("empty-text", [SessionMessage.AssistantText.make({ type: "text", id: "empty", text: "" })]),
|
||||||
assistant("empty-reasoning", [
|
assistant("empty-reasoning", [
|
||||||
new SessionMessage.AssistantReasoning({ type: "reasoning", id: "empty-reasoning", text: "" }),
|
SessionMessage.AssistantReasoning.make({ type: "reasoning", id: "empty-reasoning", text: "" }),
|
||||||
]),
|
]),
|
||||||
assistant("text", [new SessionMessage.AssistantText({ type: "text", id: "text", text: "Partial" })]),
|
assistant("text", [SessionMessage.AssistantText.make({ type: "text", id: "text", text: "Partial" })]),
|
||||||
assistant("reasoning", [
|
assistant("reasoning", [
|
||||||
new SessionMessage.AssistantReasoning({
|
SessionMessage.AssistantReasoning.make({
|
||||||
type: "reasoning",
|
type: "reasoning",
|
||||||
id: "reasoning",
|
id: "reasoning",
|
||||||
text: "",
|
text: "",
|
||||||
@@ -48,43 +48,43 @@ describe("toLLMMessages", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("maps every top-level V2 Session message type", () => {
|
test("maps every top-level V2 Session message type", () => {
|
||||||
const file = new FileAttachment({ uri: "data:image/png;base64,aGVsbG8=", mime: "image/png", name: "hello.png" })
|
const file = FileAttachment.make({ uri: "data:image/png;base64,aGVsbG8=", mime: "image/png", name: "hello.png" })
|
||||||
const messages = toLLMMessages(
|
const messages = toLLMMessages(
|
||||||
[
|
[
|
||||||
new SessionMessage.AgentSwitched({
|
SessionMessage.AgentSwitched.make({
|
||||||
id: id("agent"),
|
id: id("agent"),
|
||||||
type: "agent-switched",
|
type: "agent-switched",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
time: { created },
|
time: { created },
|
||||||
}),
|
}),
|
||||||
new SessionMessage.ModelSwitched({
|
SessionMessage.ModelSwitched.make({
|
||||||
id: id("model"),
|
id: id("model"),
|
||||||
type: "model-switched",
|
type: "model-switched",
|
||||||
model: { id: ModelV2.ID.make("model"), providerID: ProviderV2.ID.make("provider") },
|
model: { id: ModelV2.ID.make("model"), providerID: ProviderV2.ID.make("provider") },
|
||||||
time: { created },
|
time: { created },
|
||||||
}),
|
}),
|
||||||
new SessionMessage.System({
|
SessionMessage.System.make({
|
||||||
id: id("system"),
|
id: id("system"),
|
||||||
type: "system",
|
type: "system",
|
||||||
text: "Updated context\n\nOther context",
|
text: "Updated context\n\nOther context",
|
||||||
time: { created },
|
time: { created },
|
||||||
}),
|
}),
|
||||||
new SessionMessage.User({
|
SessionMessage.User.make({
|
||||||
id: id("user"),
|
id: id("user"),
|
||||||
type: "user",
|
type: "user",
|
||||||
text: "Inspect this image",
|
text: "Inspect this image",
|
||||||
files: [file],
|
files: [file],
|
||||||
agents: [new AgentAttachment({ name: "build" })],
|
agents: [AgentAttachment.make({ name: "build" })],
|
||||||
time: { created },
|
time: { created },
|
||||||
}),
|
}),
|
||||||
new SessionMessage.Synthetic({
|
SessionMessage.Synthetic.make({
|
||||||
id: id("synthetic"),
|
id: id("synthetic"),
|
||||||
type: "synthetic",
|
type: "synthetic",
|
||||||
sessionID: SessionV2.ID.make("ses_translate"),
|
sessionID: SessionV2.ID.make("ses_translate"),
|
||||||
text: "Synthetic context",
|
text: "Synthetic context",
|
||||||
time: { created },
|
time: { created },
|
||||||
}),
|
}),
|
||||||
new SessionMessage.Shell({
|
SessionMessage.Shell.make({
|
||||||
id: id("shell"),
|
id: id("shell"),
|
||||||
type: "shell",
|
type: "shell",
|
||||||
callID: "shell-1",
|
callID: "shell-1",
|
||||||
@@ -92,7 +92,7 @@ describe("toLLMMessages", () => {
|
|||||||
output: "/project",
|
output: "/project",
|
||||||
time: { created, completed: created },
|
time: { created, completed: created },
|
||||||
}),
|
}),
|
||||||
new SessionMessage.Compaction({
|
SessionMessage.Compaction.make({
|
||||||
id: id("compaction"),
|
id: id("compaction"),
|
||||||
type: "compaction",
|
type: "compaction",
|
||||||
reason: "auto",
|
reason: "auto",
|
||||||
@@ -142,31 +142,31 @@ Recent work
|
|||||||
test("replays durable tool media into canonical tool messages without structured base64", () => {
|
test("replays durable tool media into canonical tool messages without structured base64", () => {
|
||||||
const messages = toLLMMessages(
|
const messages = toLLMMessages(
|
||||||
[
|
[
|
||||||
new SessionMessage.Assistant({
|
SessionMessage.Assistant.make({
|
||||||
id: id("assistant"),
|
id: id("assistant"),
|
||||||
type: "assistant",
|
type: "assistant",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
model: { id: ModelV2.ID.make("model"), providerID: ProviderV2.ID.make("provider") },
|
model: { id: ModelV2.ID.make("model"), providerID: ProviderV2.ID.make("provider") },
|
||||||
content: [
|
content: [
|
||||||
new SessionMessage.AssistantText({ type: "text", id: "text-1", text: "Checking" }),
|
SessionMessage.AssistantText.make({ type: "text", id: "text-1", text: "Checking" }),
|
||||||
new SessionMessage.AssistantReasoning({
|
SessionMessage.AssistantReasoning.make({
|
||||||
type: "reasoning",
|
type: "reasoning",
|
||||||
id: "reasoning-1",
|
id: "reasoning-1",
|
||||||
text: "Think",
|
text: "Think",
|
||||||
providerMetadata: { anthropic: { signature: "sig_1" } },
|
providerMetadata: { anthropic: { signature: "sig_1" } },
|
||||||
}),
|
}),
|
||||||
new SessionMessage.AssistantTool({
|
SessionMessage.AssistantTool.make({
|
||||||
type: "tool",
|
type: "tool",
|
||||||
id: "pending",
|
id: "pending",
|
||||||
name: "read",
|
name: "read",
|
||||||
state: new SessionMessage.ToolStatePending({ status: "pending", input: '{"path":"README.md"}' }),
|
state: SessionMessage.ToolStatePending.make({ status: "pending", input: '{"path":"README.md"}' }),
|
||||||
time: { created },
|
time: { created },
|
||||||
}),
|
}),
|
||||||
new SessionMessage.AssistantTool({
|
SessionMessage.AssistantTool.make({
|
||||||
type: "tool",
|
type: "tool",
|
||||||
id: "running",
|
id: "running",
|
||||||
name: "read",
|
name: "read",
|
||||||
state: new SessionMessage.ToolStateRunning({
|
state: SessionMessage.ToolStateRunning.make({
|
||||||
status: "running",
|
status: "running",
|
||||||
input: { path: "README.md" },
|
input: { path: "README.md" },
|
||||||
content: [],
|
content: [],
|
||||||
@@ -174,11 +174,11 @@ Recent work
|
|||||||
}),
|
}),
|
||||||
time: { created },
|
time: { created },
|
||||||
}),
|
}),
|
||||||
new SessionMessage.AssistantTool({
|
SessionMessage.AssistantTool.make({
|
||||||
type: "tool",
|
type: "tool",
|
||||||
id: "completed",
|
id: "completed",
|
||||||
name: "read",
|
name: "read",
|
||||||
state: new SessionMessage.ToolStateCompleted({
|
state: SessionMessage.ToolStateCompleted.make({
|
||||||
status: "completed",
|
status: "completed",
|
||||||
input: { path: "README.md" },
|
input: { path: "README.md" },
|
||||||
content: [
|
content: [
|
||||||
@@ -194,7 +194,7 @@ Recent work
|
|||||||
}),
|
}),
|
||||||
time: { created, completed: created },
|
time: { created, completed: created },
|
||||||
}),
|
}),
|
||||||
new SessionMessage.AssistantTool({
|
SessionMessage.AssistantTool.make({
|
||||||
type: "tool",
|
type: "tool",
|
||||||
id: "hosted",
|
id: "hosted",
|
||||||
name: "web_search",
|
name: "web_search",
|
||||||
@@ -203,7 +203,7 @@ Recent work
|
|||||||
metadata: { fake: { continuation: "hosted-call" } },
|
metadata: { fake: { continuation: "hosted-call" } },
|
||||||
resultMetadata: { fake: { continuation: "hosted-result" } },
|
resultMetadata: { fake: { continuation: "hosted-result" } },
|
||||||
},
|
},
|
||||||
state: new SessionMessage.ToolStateCompleted({
|
state: SessionMessage.ToolStateCompleted.make({
|
||||||
status: "completed",
|
status: "completed",
|
||||||
input: { query: "Effect" },
|
input: { query: "Effect" },
|
||||||
content: [{ type: "text", text: "Found it" }],
|
content: [{ type: "text", text: "Found it" }],
|
||||||
@@ -211,12 +211,12 @@ Recent work
|
|||||||
}),
|
}),
|
||||||
time: { created, completed: created },
|
time: { created, completed: created },
|
||||||
}),
|
}),
|
||||||
new SessionMessage.AssistantTool({
|
SessionMessage.AssistantTool.make({
|
||||||
type: "tool",
|
type: "tool",
|
||||||
id: "hosted-failed",
|
id: "hosted-failed",
|
||||||
name: "write",
|
name: "write",
|
||||||
provider: { executed: true, metadata: { fake: { continuation: "failed" } } },
|
provider: { executed: true, metadata: { fake: { continuation: "failed" } } },
|
||||||
state: new SessionMessage.ToolStateError({
|
state: SessionMessage.ToolStateError.make({
|
||||||
status: "error",
|
status: "error",
|
||||||
input: { path: "README.md" },
|
input: { path: "README.md" },
|
||||||
content: [],
|
content: [],
|
||||||
@@ -299,13 +299,13 @@ Recent work
|
|||||||
test("restores OpenAI encrypted reasoning metadata", () => {
|
test("restores OpenAI encrypted reasoning metadata", () => {
|
||||||
const messages = toLLMMessages(
|
const messages = toLLMMessages(
|
||||||
[
|
[
|
||||||
new SessionMessage.Assistant({
|
SessionMessage.Assistant.make({
|
||||||
id: id("assistant-openai-reasoning"),
|
id: id("assistant-openai-reasoning"),
|
||||||
type: "assistant",
|
type: "assistant",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
model: { id: ModelV2.ID.make("model"), providerID: ProviderV2.ID.make("provider") },
|
model: { id: ModelV2.ID.make("model"), providerID: ProviderV2.ID.make("provider") },
|
||||||
content: [
|
content: [
|
||||||
new SessionMessage.AssistantReasoning({
|
SessionMessage.AssistantReasoning.make({
|
||||||
type: "reasoning",
|
type: "reasoning",
|
||||||
id: "reasoning-openai",
|
id: "reasoning-openai",
|
||||||
text: "Think",
|
text: "Think",
|
||||||
@@ -330,19 +330,19 @@ Recent work
|
|||||||
test("drops provider-native continuation metadata after a model switch", () => {
|
test("drops provider-native continuation metadata after a model switch", () => {
|
||||||
const messages = toLLMMessages(
|
const messages = toLLMMessages(
|
||||||
[
|
[
|
||||||
new SessionMessage.Assistant({
|
SessionMessage.Assistant.make({
|
||||||
id: id("assistant-old-model"),
|
id: id("assistant-old-model"),
|
||||||
type: "assistant",
|
type: "assistant",
|
||||||
agent: "build",
|
agent: "build",
|
||||||
model: { id: ModelV2.ID.make("old-model"), providerID: ProviderV2.ID.make("provider") },
|
model: { id: ModelV2.ID.make("old-model"), providerID: ProviderV2.ID.make("provider") },
|
||||||
content: [
|
content: [
|
||||||
new SessionMessage.AssistantReasoning({
|
SessionMessage.AssistantReasoning.make({
|
||||||
type: "reasoning",
|
type: "reasoning",
|
||||||
id: "reasoning-old-model",
|
id: "reasoning-old-model",
|
||||||
text: "Visible thought",
|
text: "Visible thought",
|
||||||
providerMetadata: { anthropic: { signature: "sig_old" } },
|
providerMetadata: { anthropic: { signature: "sig_old" } },
|
||||||
}),
|
}),
|
||||||
new SessionMessage.AssistantTool({
|
SessionMessage.AssistantTool.make({
|
||||||
type: "tool",
|
type: "tool",
|
||||||
id: "hosted-old-model",
|
id: "hosted-old-model",
|
||||||
name: "web_search",
|
name: "web_search",
|
||||||
@@ -351,7 +351,7 @@ Recent work
|
|||||||
metadata: { openai: { itemId: "hosted-old-model" } },
|
metadata: { openai: { itemId: "hosted-old-model" } },
|
||||||
resultMetadata: { openai: { itemId: "hosted-old-model" } },
|
resultMetadata: { openai: { itemId: "hosted-old-model" } },
|
||||||
},
|
},
|
||||||
state: new SessionMessage.ToolStateCompleted({
|
state: SessionMessage.ToolStateCompleted.make({
|
||||||
status: "completed",
|
status: "completed",
|
||||||
input: { query: "Effect" },
|
input: { query: "Effect" },
|
||||||
content: [],
|
content: [],
|
||||||
@@ -360,7 +360,7 @@ Recent work
|
|||||||
}),
|
}),
|
||||||
time: { created, completed: created },
|
time: { created, completed: created },
|
||||||
}),
|
}),
|
||||||
new SessionMessage.AssistantTool({
|
SessionMessage.AssistantTool.make({
|
||||||
type: "tool",
|
type: "tool",
|
||||||
id: "local-old-model",
|
id: "local-old-model",
|
||||||
name: "read",
|
name: "read",
|
||||||
@@ -369,7 +369,7 @@ Recent work
|
|||||||
metadata: { fake: { call: "old" } },
|
metadata: { fake: { call: "old" } },
|
||||||
resultMetadata: { fake: { result: "old" } },
|
resultMetadata: { fake: { result: "old" } },
|
||||||
},
|
},
|
||||||
state: new SessionMessage.ToolStateCompleted({
|
state: SessionMessage.ToolStateCompleted.make({
|
||||||
status: "completed",
|
status: "completed",
|
||||||
input: { path: "README.md" },
|
input: { path: "README.md" },
|
||||||
content: [],
|
content: [],
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ type Api =
|
|||||||
| { readonly type: "native"; readonly url?: string; readonly settings: Record<string, unknown> }
|
| { readonly type: "native"; readonly url?: string; readonly settings: Record<string, unknown> }
|
||||||
|
|
||||||
const model = (api: Api, variants: ModelV2.Info["variants"] = []) =>
|
const model = (api: Api, variants: ModelV2.Info["variants"] = []) =>
|
||||||
new ModelV2.Info({
|
ModelV2.Info.make({
|
||||||
id: ModelV2.ID.make("test-model"),
|
id: ModelV2.ID.make("test-model"),
|
||||||
providerID: ProviderV2.ID.make("test-provider"),
|
providerID: ProviderV2.ID.make("test-provider"),
|
||||||
name: "Test model",
|
name: "Test model",
|
||||||
@@ -79,7 +79,7 @@ describe("SessionRunnerModel", () => {
|
|||||||
it.effect("uses merged API settings for OpenAI-compatible auth and request defaults", () =>
|
it.effect("uses merged API settings for OpenAI-compatible auth and request defaults", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const resolved = yield* SessionRunnerModel.fromCatalogModel(
|
const resolved = yield* SessionRunnerModel.fromCatalogModel(
|
||||||
new ModelV2.Info({
|
ModelV2.Info.make({
|
||||||
...model({
|
...model({
|
||||||
type: "aisdk",
|
type: "aisdk",
|
||||||
package: "@ai-sdk/openai-compatible",
|
package: "@ai-sdk/openai-compatible",
|
||||||
@@ -114,7 +114,7 @@ describe("SessionRunnerModel", () => {
|
|||||||
options: { reasoningEffort: "high" },
|
options: { reasoningEffort: "high" },
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
const catalog = new ModelV2.Info({
|
const catalog = ModelV2.Info.make({
|
||||||
...base,
|
...base,
|
||||||
request: { ...base.request, options: { ...base.request.options, reasoningEffort: "medium" } },
|
request: { ...base.request, options: { ...base.request.options, reasoningEffort: "medium" } },
|
||||||
})
|
})
|
||||||
@@ -264,11 +264,11 @@ describe("SessionRunnerModel", () => {
|
|||||||
it.effect("uses resolved credentials for bearer auth", () =>
|
it.effect("uses resolved credentials for bearer auth", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const resolved = yield* SessionRunnerModel.fromCatalogModel(
|
const resolved = yield* SessionRunnerModel.fromCatalogModel(
|
||||||
new ModelV2.Info({
|
ModelV2.Info.make({
|
||||||
...model({ type: "aisdk", package: "@ai-sdk/openai", url: "https://openai.example/v1" }),
|
...model({ type: "aisdk", package: "@ai-sdk/openai", url: "https://openai.example/v1" }),
|
||||||
request: { headers: {}, body: {}, generation: {}, options: {} },
|
request: { headers: {}, body: {}, generation: {}, options: {} },
|
||||||
}),
|
}),
|
||||||
new Credential.Key({ type: "key", key: "secret" }),
|
Credential.Key.make({ type: "key", key: "secret" }),
|
||||||
)
|
)
|
||||||
const request = LLM.request({ model: resolved, prompt: "Hello" })
|
const request = LLM.request({ model: resolved, prompt: "Hello" })
|
||||||
const headers = yield* resolved.route.auth.apply({
|
const headers = yield* resolved.route.auth.apply({
|
||||||
@@ -285,9 +285,9 @@ describe("SessionRunnerModel", () => {
|
|||||||
|
|
||||||
it.effect("prefers stored credentials over configured auth", () =>
|
it.effect("prefers stored credentials over configured auth", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const credential = new Credential.Key({ type: "key", key: "stored-secret", metadata: { tenant: "work" } })
|
const credential = Credential.Key.make({ type: "key", key: "stored-secret", metadata: { tenant: "work" } })
|
||||||
const resolved = yield* SessionRunnerModel.fromCatalogModel(
|
const resolved = yield* SessionRunnerModel.fromCatalogModel(
|
||||||
new ModelV2.Info({
|
ModelV2.Info.make({
|
||||||
...model({ type: "aisdk", package: "@ai-sdk/openai", url: "https://openai.example/v1" }),
|
...model({ type: "aisdk", package: "@ai-sdk/openai", url: "https://openai.example/v1" }),
|
||||||
request: { headers: {}, body: { apiKey: "configured-secret" }, generation: {}, options: {} },
|
request: { headers: {}, body: { apiKey: "configured-secret" }, generation: {}, options: {} },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ describe("SessionRunnerLLM recorded", () => {
|
|||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const prompt = yield* session.prompt({
|
const prompt = yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Say hello in one short sentence." }),
|
prompt: Prompt.make({ text: "Say hello in one short sentence." }),
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import { SessionMessage } from "@opencode-ai/core/session/message"
|
|||||||
import { Prompt } from "@opencode-ai/core/session/prompt"
|
import { Prompt } from "@opencode-ai/core/session/prompt"
|
||||||
import { SessionProjector } from "@opencode-ai/core/session/projector"
|
import { SessionProjector } from "@opencode-ai/core/session/projector"
|
||||||
import { SessionExecution } from "@opencode-ai/core/session/execution"
|
import { SessionExecution } from "@opencode-ai/core/session/execution"
|
||||||
import { SessionContextEpoch } from "@opencode-ai/core/session/context-epoch"
|
|
||||||
import { SessionRunCoordinator } from "@opencode-ai/core/session/run-coordinator"
|
import { SessionRunCoordinator } from "@opencode-ai/core/session/run-coordinator"
|
||||||
import { SessionRunner } from "@opencode-ai/core/session/runner"
|
import { SessionRunner } from "@opencode-ai/core/session/runner"
|
||||||
import * as SessionRunnerLLM from "@opencode-ai/core/session/runner/llm"
|
import * as SessionRunnerLLM from "@opencode-ai/core/session/runner/llm"
|
||||||
@@ -351,7 +350,7 @@ const setupOverflowRecovery = Effect.gen(function* () {
|
|||||||
response = fragmentFixture("text", "text-earlier", ["Earlier answer"]).completeEvents
|
response = fragmentFixture("text", "text-earlier", ["Earlier answer"]).completeEvents
|
||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Earlier question ".repeat(700) }),
|
prompt: Prompt.make({ text: "Earlier question ".repeat(700) }),
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
@@ -476,7 +475,7 @@ const verifyEphemeralDeltas = (kind: FragmentKind) =>
|
|||||||
const chunks = Array.from({ length: 32 }, (_, index) => `${index},`)
|
const chunks = Array.from({ length: 32 }, (_, index) => `${index},`)
|
||||||
const fixture = fragmentFixture(kind, fragmentID(kind, "many"), chunks)
|
const fixture = fragmentFixture(kind, fragmentID(kind, "many"), chunks)
|
||||||
const expectedContext = [{ type: "user", text: prompt }, fixture.expectedAssistant]
|
const expectedContext = [{ type: "user", text: prompt }, fixture.expectedAssistant]
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: prompt }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: prompt }), resume: false })
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
const live = yield* events.subscribe(fixture.delta).pipe(Stream.take(32), Stream.runCollect, Effect.forkScoped)
|
const live = yield* events.subscribe(fixture.delta).pipe(Stream.take(32), Stream.runCollect, Effect.forkScoped)
|
||||||
yield* Effect.yieldNow
|
yield* Effect.yieldNow
|
||||||
@@ -507,7 +506,7 @@ const verifyPartialFlushOnFailure = (kind: FragmentKind) =>
|
|||||||
const prompt = `Fail after ${kind}`
|
const prompt = `Fail after ${kind}`
|
||||||
const fixture = fragmentFixture(kind, fragmentID(kind, "partial"), ["Partial"])
|
const fixture = fragmentFixture(kind, fragmentID(kind, "partial"), ["Partial"])
|
||||||
const failure = providerUnavailable()
|
const failure = providerUnavailable()
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: prompt }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: prompt }), resume: false })
|
||||||
responseStream = Stream.concat(Stream.fromIterable(fixture.partialEvents), Stream.fail(failure))
|
responseStream = Stream.concat(Stream.fromIterable(fixture.partialEvents), Stream.fail(failure))
|
||||||
|
|
||||||
expect(yield* session.resume(sessionID).pipe(Effect.flip)).toBe(failure)
|
expect(yield* session.resume(sessionID).pipe(Effect.flip)).toBe(failure)
|
||||||
@@ -529,7 +528,7 @@ const verifyPartialFlushOnInterruption = (kind: FragmentKind) =>
|
|||||||
const prompt = `Interrupt after ${kind}`
|
const prompt = `Interrupt after ${kind}`
|
||||||
const fixture = fragmentFixture(kind, fragmentID(kind, "interrupted"), ["Partial"])
|
const fixture = fragmentFixture(kind, fragmentID(kind, "interrupted"), ["Partial"])
|
||||||
const streamed = yield* Deferred.make<void>()
|
const streamed = yield* Deferred.make<void>()
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: prompt }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: prompt }), resume: false })
|
||||||
responseStream = Stream.concat(
|
responseStream = Stream.concat(
|
||||||
Stream.fromIterable(fixture.partialEvents),
|
Stream.fromIterable(fixture.partialEvents),
|
||||||
Stream.fromEffect(Deferred.succeed(streamed, undefined)).pipe(Stream.flatMap(() => Stream.never)),
|
Stream.fromEffect(Deferred.succeed(streamed, undefined)).pipe(Stream.flatMap(() => Stream.never)),
|
||||||
@@ -573,7 +572,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Use application context" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Use application context" }), resume: false })
|
||||||
responses = [
|
responses = [
|
||||||
[
|
[
|
||||||
LLMEvent.stepStart({ index: 0 }),
|
LLMEvent.stepStart({ index: 0 }),
|
||||||
@@ -621,7 +620,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
streamStarted = undefined
|
streamStarted = undefined
|
||||||
response = []
|
response = []
|
||||||
|
|
||||||
const message = yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Run automatically" }) })
|
const message = yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Run automatically" }) })
|
||||||
|
|
||||||
expect(requests).toHaveLength(1)
|
expect(requests).toHaveLength(1)
|
||||||
expect(yield* session.messages({ sessionID })).toMatchObject([
|
expect(yield* session.messages({ sessionID })).toMatchObject([
|
||||||
@@ -634,8 +633,8 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "First" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false })
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Second" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = undefined
|
responses = undefined
|
||||||
@@ -662,7 +661,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
const { db } = yield* Database.Service
|
const { db } = yield* Database.Service
|
||||||
const messageID = SessionMessage.ID.create()
|
const messageID = SessionMessage.ID.create()
|
||||||
systemUnavailable = true
|
systemUnavailable = true
|
||||||
yield* session.prompt({ id: messageID, sessionID, prompt: new Prompt({ text: "First" }), resume: false })
|
yield* session.prompt({ id: messageID, sessionID, prompt: Prompt.make({ text: "First" }), resume: false })
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
|
|
||||||
const exit = yield* session.resume(sessionID).pipe(Effect.exit)
|
const exit = yield* session.resume(sessionID).pipe(Effect.exit)
|
||||||
@@ -680,7 +679,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
).toBeUndefined()
|
).toBeUndefined()
|
||||||
|
|
||||||
systemUnavailable = false
|
systemUnavailable = false
|
||||||
yield* session.prompt({ id: messageID, sessionID, prompt: new Prompt({ text: "First" }) })
|
yield* session.prompt({ id: messageID, sessionID, prompt: Prompt.make({ text: "First" }) })
|
||||||
|
|
||||||
expect(requests).toHaveLength(1)
|
expect(requests).toHaveLength(1)
|
||||||
expect(requests[0]?.messages.map((message) => message.role)).toEqual(["user"])
|
expect(requests[0]?.messages.map((message) => message.role)).toEqual(["user"])
|
||||||
@@ -693,7 +692,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
const { db } = yield* Database.Service
|
const { db } = yield* Database.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "First" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false })
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = []
|
response = []
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
@@ -711,7 +710,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
.get(),
|
.get(),
|
||||||
).toBeUndefined()
|
).toBeUndefined()
|
||||||
|
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Second" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false })
|
||||||
const exit = yield* session.resume(sessionID).pipe(Effect.exit)
|
const exit = yield* session.resume(sessionID).pipe(Effect.exit)
|
||||||
|
|
||||||
expect(Exit.isFailure(exit) && Cause.hasInterruptsOnly(exit.cause)).toBe(true)
|
expect(Exit.isFailure(exit) && Cause.hasInterruptsOnly(exit.cause)).toBe(true)
|
||||||
@@ -725,7 +724,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const { db } = yield* Database.Service
|
const { db } = yield* Database.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "First" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false })
|
||||||
response = []
|
response = []
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
yield* db
|
yield* db
|
||||||
@@ -734,7 +733,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
.where(eq(SessionContextEpochTable.session_id, sessionID))
|
.where(eq(SessionContextEpochTable.session_id, sessionID))
|
||||||
.run()
|
.run()
|
||||||
.pipe(Effect.orDie)
|
.pipe(Effect.orDie)
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Second" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false })
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
|
|
||||||
const exit = yield* session.resume(sessionID).pipe(Effect.exit)
|
const exit = yield* session.resume(sessionID).pipe(Effect.exit)
|
||||||
@@ -749,13 +748,13 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "First" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = []
|
response = []
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
systemBaseline = "Changed context"
|
systemBaseline = "Changed context"
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Second" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false })
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
|
|
||||||
expect(requests.map((request) => request.system.map((part) => part.text))).toEqual([
|
expect(requests.map((request) => request.system.map((part) => part.text))).toEqual([
|
||||||
@@ -790,7 +789,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "First" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = fragmentFixture("text", "text-build", ["Done"]).completeEvents
|
response = fragmentFixture("text", "text-build", ["Done"]).completeEvents
|
||||||
@@ -816,7 +815,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
editor.default(AgentV2.ID.make("reviewer"))
|
editor.default(AgentV2.ID.make("reviewer"))
|
||||||
})
|
})
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "First" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = fragmentFixture("text", "text-reviewer", ["Done"]).completeEvents
|
response = fragmentFixture("text", "text-reviewer", ["Done"]).completeEvents
|
||||||
@@ -845,7 +844,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
.run()
|
.run()
|
||||||
.pipe(Effect.orDie)
|
.pipe(Effect.orDie)
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "First" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = fragmentFixture("text", "text-selected", ["Done"]).completeEvents
|
response = fragmentFixture("text", "text-selected", ["Done"]).completeEvents
|
||||||
@@ -862,7 +861,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
skillBaselines.set(AgentV2.ID.make("build"), "Build skills")
|
skillBaselines.set(AgentV2.ID.make("build"), "Build skills")
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "First" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = []
|
response = []
|
||||||
@@ -874,7 +873,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
timestamp: DateTime.makeUnsafe(1),
|
timestamp: DateTime.makeUnsafe(1),
|
||||||
agent: "reviewer",
|
agent: "reviewer",
|
||||||
})
|
})
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Second" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false })
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
|
|
||||||
expect(requests.map((request) => request.system.map((part) => part.text))).toEqual([
|
expect(requests.map((request) => request.system.map((part) => part.text))).toEqual([
|
||||||
@@ -905,7 +904,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
})
|
})
|
||||||
.pipe(Effect.asVoid)
|
.pipe(Effect.asVoid)
|
||||||
})
|
})
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "First" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = []
|
response = []
|
||||||
@@ -935,7 +934,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
})
|
})
|
||||||
.pipe(Effect.asVoid)
|
.pipe(Effect.asVoid)
|
||||||
})
|
})
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "First" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = []
|
response = []
|
||||||
@@ -949,13 +948,13 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "First" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = []
|
response = []
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
systemRemoved = true
|
systemRemoved = true
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Second" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false })
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
|
|
||||||
expect(requests[1]?.messages.map((message) => message.role)).toEqual(["user", "user", "system"])
|
expect(requests[1]?.messages.map((message) => message.role)).toEqual(["user", "user", "system"])
|
||||||
@@ -971,13 +970,13 @@ describe("SessionRunnerLLM", () => {
|
|||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "First" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = []
|
response = []
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
systemBaseline = "Changed context"
|
systemBaseline = "Changed context"
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Second" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false })
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
yield* events.publish(SessionEvent.ModelSwitched, {
|
yield* events.publish(SessionEvent.ModelSwitched, {
|
||||||
sessionID,
|
sessionID,
|
||||||
@@ -986,7 +985,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
model: { id: ModelV2.ID.make("replacement"), providerID: ProviderV2.ID.make("fake") },
|
model: { id: ModelV2.ID.make("replacement"), providerID: ProviderV2.ID.make("fake") },
|
||||||
})
|
})
|
||||||
systemBaseline = "Replacement context"
|
systemBaseline = "Replacement context"
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Third" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Third" }), resume: false })
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
|
|
||||||
expect(requests.map((request) => request.system.map((part) => part.text))).toEqual([
|
expect(requests.map((request) => request.system.map((part) => part.text))).toEqual([
|
||||||
@@ -1006,7 +1005,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
])
|
])
|
||||||
yield* replaySessionProjection(sessionID)
|
yield* replaySessionProjection(sessionID)
|
||||||
expect(yield* session.messages({ sessionID })).toHaveLength(6)
|
expect(yield* session.messages({ sessionID })).toHaveLength(6)
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Fourth" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fourth" }), resume: false })
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
@@ -1016,7 +1015,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "First" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = []
|
response = []
|
||||||
@@ -1028,11 +1027,11 @@ describe("SessionRunnerLLM", () => {
|
|||||||
model: { id: ModelV2.ID.make("replacement"), providerID: ProviderV2.ID.make("fake") },
|
model: { id: ModelV2.ID.make("replacement"), providerID: ProviderV2.ID.make("fake") },
|
||||||
})
|
})
|
||||||
systemUnavailable = true
|
systemUnavailable = true
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Second" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false })
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
systemUnavailable = false
|
systemUnavailable = false
|
||||||
systemBaseline = "Replacement context"
|
systemBaseline = "Replacement context"
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Third" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Third" }), resume: false })
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
|
|
||||||
expect(requests.map((request) => request.system.map((part) => part.text))).toEqual([
|
expect(requests.map((request) => request.system.map((part) => part.text))).toEqual([
|
||||||
@@ -1048,7 +1047,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "First" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = []
|
response = []
|
||||||
@@ -1069,7 +1068,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
recent: "",
|
recent: "",
|
||||||
})
|
})
|
||||||
systemBaseline = "Replacement context"
|
systemBaseline = "Replacement context"
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Second" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false })
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
|
|
||||||
expect(requests.map((request) => request.system.map((part) => part.text))).toEqual([
|
expect(requests.map((request) => request.system.map((part) => part.text))).toEqual([
|
||||||
@@ -1077,7 +1076,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
["Replacement context"],
|
["Replacement context"],
|
||||||
])
|
])
|
||||||
yield* replaySessionProjection(sessionID)
|
yield* replaySessionProjection(sessionID)
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Third" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Third" }), resume: false })
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
@@ -1089,7 +1088,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
response = fragmentFixture("text", "text-first", ["Earlier answer"]).completeEvents
|
response = fragmentFixture("text", "text-first", ["Earlier answer"]).completeEvents
|
||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Earlier question ".repeat(180) }),
|
prompt: Prompt.make({ text: "Earlier question ".repeat(180) }),
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
@@ -1102,7 +1101,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
]
|
]
|
||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Recent exact request ".repeat(180) }),
|
prompt: Prompt.make({ text: "Recent exact request ".repeat(180) }),
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
@@ -1128,7 +1127,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
]
|
]
|
||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Newest exact request ".repeat(180) }),
|
prompt: Prompt.make({ text: "Newest exact request ".repeat(180) }),
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
@@ -1156,7 +1155,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
fragmentFixture("text", "text-summary", ["## Goal\n- Recover overflow"]).completeEvents,
|
fragmentFixture("text", "text-summary", ["## Goal\n- Recover overflow"]).completeEvents,
|
||||||
fragmentFixture("text", "text-final", ["Recovered"]).completeEvents,
|
fragmentFixture("text", "text-final", ["Recovered"]).completeEvents,
|
||||||
]
|
]
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Continue" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Continue" }), resume: false })
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
|
|
||||||
expect(requests).toHaveLength(3)
|
expect(requests).toHaveLength(3)
|
||||||
@@ -1186,7 +1185,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
fragmentFixture("text", "text-summary", ["## Goal\n- Recover once"]).completeEvents,
|
fragmentFixture("text", "text-summary", ["## Goal\n- Recover once"]).completeEvents,
|
||||||
overflow(),
|
overflow(),
|
||||||
]
|
]
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Continue" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Continue" }), resume: false })
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
|
|
||||||
expect(requests).toHaveLength(3)
|
expect(requests).toHaveLength(3)
|
||||||
@@ -1214,7 +1213,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
fragmentFixture("text", "text-summary", ["## Goal\n- Recover raw overflow"]).completeEvents,
|
fragmentFixture("text", "text-summary", ["## Goal\n- Recover raw overflow"]).completeEvents,
|
||||||
fragmentFixture("text", "text-final", ["Recovered"]).completeEvents,
|
fragmentFixture("text", "text-final", ["Recovered"]).completeEvents,
|
||||||
]
|
]
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Continue" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Continue" }), resume: false })
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
|
|
||||||
expect(requests).toHaveLength(3)
|
expect(requests).toHaveLength(3)
|
||||||
@@ -1232,7 +1231,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
[LLMEvent.providerError({ message: "prompt too long", classification: "context-overflow" })],
|
[LLMEvent.providerError({ message: "prompt too long", classification: "context-overflow" })],
|
||||||
[LLMEvent.providerError({ message: "summary unavailable" })],
|
[LLMEvent.providerError({ message: "summary unavailable" })],
|
||||||
]
|
]
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Continue" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Continue" }), resume: false })
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
|
|
||||||
expect(requests).toHaveLength(2)
|
expect(requests).toHaveLength(2)
|
||||||
@@ -1255,7 +1254,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
const firstGate = yield* Deferred.make<void>()
|
const firstGate = yield* Deferred.make<void>()
|
||||||
const summaryGate = yield* Deferred.make<void>()
|
const summaryGate = yield* Deferred.make<void>()
|
||||||
streamGate = firstGate
|
streamGate = firstGate
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Continue" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Continue" }), resume: false })
|
||||||
const run = yield* session.resume(sessionID).pipe(Effect.forkChild)
|
const run = yield* session.resume(sessionID).pipe(Effect.forkChild)
|
||||||
while (requests.length < 1) yield* Effect.yieldNow
|
while (requests.length < 1) yield* Effect.yieldNow
|
||||||
streamGate = summaryGate
|
streamGate = summaryGate
|
||||||
@@ -1275,13 +1274,13 @@ describe("SessionRunnerLLM", () => {
|
|||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "First" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = []
|
response = []
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
systemBaseline = "Changed context"
|
systemBaseline = "Changed context"
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Second" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false })
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
const compactionID = SessionMessage.ID.create()
|
const compactionID = SessionMessage.ID.create()
|
||||||
yield* events.publish(SessionEvent.Compaction.Started, {
|
yield* events.publish(SessionEvent.Compaction.Started, {
|
||||||
@@ -1299,7 +1298,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
recent: "",
|
recent: "",
|
||||||
})
|
})
|
||||||
systemUnavailable = true
|
systemUnavailable = true
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Third" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Third" }), resume: false })
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
|
|
||||||
expect(requests.at(-1)?.system.map((part) => part.text)).toEqual(["Initial context"])
|
expect(requests.at(-1)?.system.map((part) => part.text)).toEqual(["Initial context"])
|
||||||
@@ -1311,7 +1310,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Use tools" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Use tools" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = undefined
|
responses = undefined
|
||||||
@@ -1409,7 +1408,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Echo this" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Echo this" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
authorizations.length = 0
|
authorizations.length = 0
|
||||||
@@ -1468,7 +1467,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Echo this" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Echo this" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = [
|
responses = [
|
||||||
@@ -1512,7 +1511,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Think first" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Think first" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = [
|
response = [
|
||||||
@@ -1550,7 +1549,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Continue" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Continue" }), resume: false })
|
||||||
response = []
|
response = []
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
|
|
||||||
@@ -1569,7 +1568,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Search first" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Search first" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = [
|
response = [
|
||||||
@@ -1594,7 +1593,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
yield* replaySessionProjection(sessionID)
|
yield* replaySessionProjection(sessionID)
|
||||||
|
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Continue" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Continue" }), resume: false })
|
||||||
response = []
|
response = []
|
||||||
yield* session.resume(sessionID)
|
yield* session.resume(sessionID)
|
||||||
|
|
||||||
@@ -1624,7 +1623,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Echo five times" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Echo five times" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
executions.length = 0
|
executions.length = 0
|
||||||
@@ -1685,7 +1684,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Echo twice" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Echo twice" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
executions.length = 0
|
executions.length = 0
|
||||||
@@ -1773,7 +1772,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Run once" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Run once" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = undefined
|
responses = undefined
|
||||||
@@ -1812,7 +1811,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Start working" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Start working" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = [
|
responses = [
|
||||||
@@ -1832,7 +1831,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
|
|
||||||
const first = yield* session.resume(sessionID).pipe(Effect.forkChild)
|
const first = yield* session.resume(sessionID).pipe(Effect.forkChild)
|
||||||
yield* Deferred.await(streamStarted)
|
yield* Deferred.await(streamStarted)
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Change direction" }) })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Change direction" }) })
|
||||||
yield* Deferred.succeed(streamGate, undefined)
|
yield* Deferred.succeed(streamGate, undefined)
|
||||||
yield* Fiber.join(first)
|
yield* Fiber.join(first)
|
||||||
streamGate = undefined
|
streamGate = undefined
|
||||||
@@ -1855,7 +1854,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Start working" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Start working" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = [
|
responses = [
|
||||||
@@ -1883,7 +1882,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
yield* Deferred.await(streamStarted)
|
yield* Deferred.await(streamStarted)
|
||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Wait until continuation ends" }),
|
prompt: Prompt.make({ text: "Wait until continuation ends" }),
|
||||||
delivery: "queue",
|
delivery: "queue",
|
||||||
})
|
})
|
||||||
yield* Deferred.succeed(streamGate, undefined)
|
yield* Deferred.succeed(streamGate, undefined)
|
||||||
@@ -1903,7 +1902,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const { db } = yield* Database.Service
|
const { db } = yield* Database.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Interrupt current work" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Interrupt current work" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = [
|
responses = [
|
||||||
@@ -1921,7 +1920,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
yield* Deferred.await(streamStarted)
|
yield* Deferred.await(streamStarted)
|
||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Run after interrupt" }),
|
prompt: Prompt.make({ text: "Run after interrupt" }),
|
||||||
delivery: "queue",
|
delivery: "queue",
|
||||||
})
|
})
|
||||||
yield* session.interrupt(sessionID)
|
yield* session.interrupt(sessionID)
|
||||||
@@ -1946,7 +1945,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const { db } = yield* Database.Service
|
const { db } = yield* Database.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Interrupt current work" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Interrupt current work" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = [
|
responses = [
|
||||||
@@ -1964,7 +1963,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
yield* Deferred.await(streamStarted)
|
yield* Deferred.await(streamStarted)
|
||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Steer after interrupt" }),
|
prompt: Prompt.make({ text: "Steer after interrupt" }),
|
||||||
})
|
})
|
||||||
yield* session.interrupt(sessionID)
|
yield* session.interrupt(sessionID)
|
||||||
expect(yield* Fiber.await(run)).toMatchObject({ _tag: "Failure" })
|
expect(yield* Fiber.await(run)).toMatchObject({ _tag: "Failure" })
|
||||||
@@ -1988,7 +1987,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Start working" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Start working" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = [
|
responses = [
|
||||||
@@ -2013,8 +2012,8 @@ describe("SessionRunnerLLM", () => {
|
|||||||
|
|
||||||
const first = yield* session.resume(sessionID).pipe(Effect.forkChild)
|
const first = yield* session.resume(sessionID).pipe(Effect.forkChild)
|
||||||
yield* Deferred.await(streamStarted)
|
yield* Deferred.await(streamStarted)
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Queue first" }), delivery: "queue" })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Queue first" }), delivery: "queue" })
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Queue second" }), delivery: "queue" })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Queue second" }), delivery: "queue" })
|
||||||
yield* Deferred.succeed(streamGate, undefined)
|
yield* Deferred.succeed(streamGate, undefined)
|
||||||
yield* Fiber.join(first)
|
yield* Fiber.join(first)
|
||||||
streamGate = undefined
|
streamGate = undefined
|
||||||
@@ -2031,10 +2030,10 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Start steering" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Start steering" }), resume: false })
|
||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Queue for later" }),
|
prompt: Prompt.make({ text: "Queue for later" }),
|
||||||
delivery: "queue",
|
delivery: "queue",
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
@@ -2065,7 +2064,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Start working" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Start working" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = [
|
responses = [
|
||||||
@@ -2096,13 +2095,13 @@ describe("SessionRunnerLLM", () => {
|
|||||||
|
|
||||||
const first = yield* session.resume(sessionID).pipe(Effect.forkChild)
|
const first = yield* session.resume(sessionID).pipe(Effect.forkChild)
|
||||||
while (requests.length < 1) yield* Effect.yieldNow
|
while (requests.length < 1) yield* Effect.yieldNow
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Queue first" }), delivery: "queue" })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Queue first" }), delivery: "queue" })
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Queue second" }), delivery: "queue" })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Queue second" }), delivery: "queue" })
|
||||||
streamGate = secondGate
|
streamGate = secondGate
|
||||||
yield* Deferred.succeed(firstGate, undefined)
|
yield* Deferred.succeed(firstGate, undefined)
|
||||||
while (requests.length < 2) yield* Effect.yieldNow
|
while (requests.length < 2) yield* Effect.yieldNow
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Steer before next queued input" }) })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Steer before next queued input" }) })
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Also steer before next queued input" }) })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Also steer before next queued input" }) })
|
||||||
yield* Deferred.succeed(secondGate, undefined)
|
yield* Deferred.succeed(secondGate, undefined)
|
||||||
yield* Fiber.join(first)
|
yield* Fiber.join(first)
|
||||||
streamGate = undefined
|
streamGate = undefined
|
||||||
@@ -2130,7 +2129,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Start working" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Start working" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = [
|
responses = [
|
||||||
@@ -2150,8 +2149,8 @@ describe("SessionRunnerLLM", () => {
|
|||||||
|
|
||||||
const first = yield* session.resume(sessionID).pipe(Effect.forkChild)
|
const first = yield* session.resume(sessionID).pipe(Effect.forkChild)
|
||||||
yield* Deferred.await(streamStarted)
|
yield* Deferred.await(streamStarted)
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "First steer" }) })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First steer" }) })
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Second steer" }) })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second steer" }) })
|
||||||
yield* Deferred.succeed(streamGate, undefined)
|
yield* Deferred.succeed(streamGate, undefined)
|
||||||
yield* Fiber.join(first)
|
yield* Fiber.join(first)
|
||||||
streamGate = undefined
|
streamGate = undefined
|
||||||
@@ -2170,7 +2169,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Start working" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Start working" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = undefined
|
responses = undefined
|
||||||
@@ -2181,7 +2180,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
|
|
||||||
const first = yield* session.resume(sessionID).pipe(Effect.forkChild)
|
const first = yield* session.resume(sessionID).pipe(Effect.forkChild)
|
||||||
yield* Deferred.await(streamStarted)
|
yield* Deferred.await(streamStarted)
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Recover with this" }) })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Recover with this" }) })
|
||||||
yield* Deferred.succeed(streamGate, undefined)
|
yield* Deferred.succeed(streamGate, undefined)
|
||||||
expect(yield* Fiber.join(first).pipe(Effect.flip)).toBe(streamFailure)
|
expect(yield* Fiber.join(first).pipe(Effect.flip)).toBe(streamFailure)
|
||||||
|
|
||||||
@@ -2200,7 +2199,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Recover interrupted tool" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Recover interrupted tool" }), resume: false })
|
||||||
yield* SessionInput.promoteSteers((yield* Database.Service).db, events, sessionID, Number.MAX_SAFE_INTEGER)
|
yield* SessionInput.promoteSteers((yield* Database.Service).db, events, sessionID, Number.MAX_SAFE_INTEGER)
|
||||||
const assistantMessageID = SessionMessage.ID.create()
|
const assistantMessageID = SessionMessage.ID.create()
|
||||||
yield* events.publish(SessionEvent.Step.Started, {
|
yield* events.publish(SessionEvent.Step.Started, {
|
||||||
@@ -2262,7 +2261,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Recover interrupted hosted tool" }),
|
prompt: Prompt.make({ text: "Recover interrupted hosted tool" }),
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
yield* SessionInput.promoteSteers((yield* Database.Service).db, events, sessionID, Number.MAX_SAFE_INTEGER)
|
yield* SessionInput.promoteSteers((yield* Database.Service).db, events, sessionID, Number.MAX_SAFE_INTEGER)
|
||||||
@@ -2322,7 +2321,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Recover interrupted tool input" }),
|
prompt: Prompt.make({ text: "Recover interrupted tool input" }),
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
yield* SessionInput.promoteSteers((yield* Database.Service).db, events, sessionID, Number.MAX_SAFE_INTEGER)
|
yield* SessionInput.promoteSteers((yield* Database.Service).db, events, sessionID, Number.MAX_SAFE_INTEGER)
|
||||||
@@ -2360,7 +2359,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Wait in queue" }),
|
prompt: Prompt.make({ text: "Wait in queue" }),
|
||||||
delivery: "queue",
|
delivery: "queue",
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
@@ -2382,7 +2381,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
const defect = new Error("fail after prompt promotion")
|
const defect = new Error("fail after prompt promotion")
|
||||||
let fail = true
|
let fail = true
|
||||||
yield* events.project(SessionEvent.Prompted, () => (fail ? Effect.die(defect) : Effect.void))
|
yield* events.project(SessionEvent.Prompted, () => (fail ? Effect.die(defect) : Effect.void))
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Recover promoted input" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Recover promoted input" }), resume: false })
|
||||||
|
|
||||||
expect(yield* session.resume(sessionID).pipe(Effect.catchDefect(Effect.succeed))).toBe(defect)
|
expect(yield* session.resume(sessionID).pipe(Effect.catchDefect(Effect.succeed))).toBe(defect)
|
||||||
fail = false
|
fail = false
|
||||||
@@ -2410,7 +2409,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
)
|
)
|
||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Run committed promotion" }),
|
prompt: Prompt.make({ text: "Run committed promotion" }),
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -2427,8 +2426,8 @@ describe("SessionRunnerLLM", () => {
|
|||||||
yield* setup
|
yield* setup
|
||||||
yield* insertSession(otherSessionID)
|
yield* insertSession(otherSessionID)
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Run first" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Run first" }), resume: false })
|
||||||
yield* session.prompt({ sessionID: otherSessionID, prompt: new Prompt({ text: "Run second" }), resume: false })
|
yield* session.prompt({ sessionID: otherSessionID, prompt: Prompt.make({ text: "Run second" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = undefined
|
responses = undefined
|
||||||
@@ -2454,37 +2453,31 @@ describe("SessionRunnerLLM", () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.effect("bounds external session prompt cache keys", () =>
|
it.effect("bounds 64-character session prompt cache keys", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const externalSessionID = SessionV2.ID.fromExternal({
|
const longSessionID = SessionV2.ID.make(`ses_${"a".repeat(64)}`)
|
||||||
namespace: "discord",
|
const otherLongSessionID = SessionV2.ID.make(`ses_${"b".repeat(64)}`)
|
||||||
key: "thread-one",
|
yield* insertSession(longSessionID)
|
||||||
})
|
yield* insertSession(otherLongSessionID)
|
||||||
const otherExternalSessionID = SessionV2.ID.fromExternal({
|
|
||||||
namespace: "discord",
|
|
||||||
key: "thread-two",
|
|
||||||
})
|
|
||||||
yield* insertSession(externalSessionID)
|
|
||||||
yield* insertSession(otherExternalSessionID)
|
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID: externalSessionID,
|
sessionID: longSessionID,
|
||||||
prompt: new Prompt({ text: "Run external session" }),
|
prompt: Prompt.make({ text: "Run long session" }),
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID: otherExternalSessionID,
|
sessionID: otherLongSessionID,
|
||||||
prompt: new Prompt({ text: "Run other external session" }),
|
prompt: Prompt.make({ text: "Run other long session" }),
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
yield* session.resume(externalSessionID)
|
yield* session.resume(longSessionID)
|
||||||
yield* session.resume(otherExternalSessionID)
|
yield* session.resume(otherLongSessionID)
|
||||||
|
|
||||||
const keys = requests.map((request) => request.providerOptions?.openai?.promptCacheKey)
|
const keys = requests.map((request) => request.providerOptions?.openai?.promptCacheKey)
|
||||||
expect(keys).toEqual([externalSessionID.slice(4), otherExternalSessionID.slice(4)])
|
expect(keys).toEqual([longSessionID.slice(4), otherLongSessionID.slice(4)])
|
||||||
expect(keys.every((key) => typeof key === "string" && key.length === 64)).toBe(true)
|
expect(keys.every((key) => typeof key === "string" && key.length === 64)).toBe(true)
|
||||||
expect(keys[0]).not.toBe(keys[1])
|
expect(keys[0]).not.toBe(keys[1])
|
||||||
}),
|
}),
|
||||||
@@ -2494,7 +2487,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Retry after failure" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Retry after failure" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = undefined
|
responses = undefined
|
||||||
@@ -2525,7 +2518,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Call missing" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Call missing" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = [
|
responses = [
|
||||||
@@ -2571,7 +2564,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Call defect" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Call defect" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = [
|
responses = [
|
||||||
@@ -2620,7 +2613,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
questions.ask({ sessionID: context.sessionID, questions: [] }).pipe(Effect.as({}), Effect.orDie),
|
questions.ask({ sessionID: context.sessionID, questions: [] }).pipe(Effect.as({}), Effect.orDie),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Ask then stop" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Ask then stop" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = [
|
responses = [
|
||||||
@@ -2665,7 +2658,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Settle before failing" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Settle before failing" }), resume: false })
|
||||||
const failure = providerUnavailable()
|
const failure = providerUnavailable()
|
||||||
toolExecutionGate = yield* Deferred.make<void>()
|
toolExecutionGate = yield* Deferred.make<void>()
|
||||||
responseStream = Stream.concat(
|
responseStream = Stream.concat(
|
||||||
@@ -2699,7 +2692,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Interrupt blocked tool" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Interrupt blocked tool" }), resume: false })
|
||||||
executions.length = 0
|
executions.length = 0
|
||||||
toolExecutionGate = yield* Deferred.make<void>()
|
toolExecutionGate = yield* Deferred.make<void>()
|
||||||
responseStream = Stream.concat(
|
responseStream = Stream.concat(
|
||||||
@@ -2749,7 +2742,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Interrupt provider" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Interrupt provider" }), resume: false })
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = []
|
response = []
|
||||||
streamGate = yield* Deferred.make<void>()
|
streamGate = yield* Deferred.make<void>()
|
||||||
@@ -2772,7 +2765,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Interrupt tool settlement" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Interrupt tool settlement" }), resume: false })
|
||||||
executions.length = 0
|
executions.length = 0
|
||||||
toolExecutionGate = yield* Deferred.make<void>()
|
toolExecutionGate = yield* Deferred.make<void>()
|
||||||
response = [
|
response = [
|
||||||
@@ -2815,7 +2808,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Finish at the limit" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Finish at the limit" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
executions.length = 0
|
executions.length = 0
|
||||||
@@ -2863,7 +2856,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Start work" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Start work" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
executions.length = 0
|
executions.length = 0
|
||||||
@@ -2891,7 +2884,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
|
|
||||||
const run = yield* session.resume(sessionID).pipe(Effect.forkChild)
|
const run = yield* session.resume(sessionID).pipe(Effect.forkChild)
|
||||||
yield* Deferred.await(streamStarted)
|
yield* Deferred.await(streamStarted)
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Change direction" }) })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Change direction" }) })
|
||||||
yield* Deferred.succeed(streamGate, undefined)
|
yield* Deferred.succeed(streamGate, undefined)
|
||||||
yield* Fiber.join(run)
|
yield* Fiber.join(run)
|
||||||
streamGate = undefined
|
streamGate = undefined
|
||||||
@@ -2909,7 +2902,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Fail durably" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fail durably" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
responses = undefined
|
responses = undefined
|
||||||
@@ -2931,7 +2924,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Fail before step" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fail before step" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = [LLMEvent.providerError({ message: "Provider unavailable" })]
|
response = [LLMEvent.providerError({ message: "Provider unavailable" })]
|
||||||
@@ -2950,7 +2943,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Fail after output" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fail after output" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = [
|
response = [
|
||||||
@@ -2979,7 +2972,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Fail raw stream durably" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fail raw stream durably" }), resume: false })
|
||||||
const failure = providerUnavailable()
|
const failure = providerUnavailable()
|
||||||
responseStream = Stream.fail(failure)
|
responseStream = Stream.fail(failure)
|
||||||
|
|
||||||
@@ -2998,7 +2991,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Do not continue failed provider" }),
|
prompt: Prompt.make({ text: "Do not continue failed provider" }),
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -3021,7 +3014,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Fail hosted tool durably" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fail hosted tool durably" }), resume: false })
|
||||||
|
|
||||||
requests.length = 0
|
requests.length = 0
|
||||||
response = [
|
response = [
|
||||||
@@ -3052,7 +3045,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Fail hosted tool at EOF" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fail hosted tool at EOF" }), resume: false })
|
||||||
response = [
|
response = [
|
||||||
LLMEvent.stepStart({ index: 0 }),
|
LLMEvent.stepStart({ index: 0 }),
|
||||||
LLMEvent.toolCall({
|
LLMEvent.toolCall({
|
||||||
@@ -3079,7 +3072,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({
|
yield* session.prompt({
|
||||||
sessionID,
|
sessionID,
|
||||||
prompt: new Prompt({ text: "Fail hosted tool on raw failure" }),
|
prompt: Prompt.make({ text: "Fail hosted tool on raw failure" }),
|
||||||
resume: false,
|
resume: false,
|
||||||
})
|
})
|
||||||
const failure = providerUnavailable()
|
const failure = providerUnavailable()
|
||||||
@@ -3114,7 +3107,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Two blocks" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Two blocks" }), resume: false })
|
||||||
|
|
||||||
responses = undefined
|
responses = undefined
|
||||||
streamGate = undefined
|
streamGate = undefined
|
||||||
@@ -3177,7 +3170,7 @@ describe("SessionRunnerLLM", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
const session = yield* SessionV2.Service
|
const session = yield* SessionV2.Service
|
||||||
yield* session.prompt({ sessionID, prompt: new Prompt({ text: "Call provider tool" }), resume: false })
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Call provider tool" }), resume: false })
|
||||||
|
|
||||||
responses = undefined
|
responses = undefined
|
||||||
streamGate = undefined
|
streamGate = undefined
|
||||||
|
|||||||
@@ -0,0 +1,183 @@
|
|||||||
|
import { expect, test } from "bun:test"
|
||||||
|
import { Schema } from "effect"
|
||||||
|
import { AgentV2 } from "@opencode-ai/core/agent"
|
||||||
|
import { ModelV2 } from "@opencode-ai/core/model"
|
||||||
|
import { SessionV2 } from "@opencode-ai/core/session"
|
||||||
|
import { Agent } from "@opencode-ai/schema/agent"
|
||||||
|
import { Location } from "@opencode-ai/schema/location"
|
||||||
|
import { Model } from "@opencode-ai/schema/model"
|
||||||
|
import { AgentAttachment, FileAttachment, Prompt, Source } from "@opencode-ai/schema/prompt"
|
||||||
|
import { Provider } from "@opencode-ai/schema/provider"
|
||||||
|
import { Project } from "@opencode-ai/schema/project"
|
||||||
|
import { Session } from "@opencode-ai/schema/session"
|
||||||
|
import { SessionInput } from "@opencode-ai/schema/session-input"
|
||||||
|
import { SessionMessage } from "@opencode-ai/schema/session-message"
|
||||||
|
import { Workspace } from "@opencode-ai/schema/workspace"
|
||||||
|
import { Command } from "@opencode-ai/schema/command"
|
||||||
|
import { Connection } from "@opencode-ai/schema/connection"
|
||||||
|
import { Credential } from "@opencode-ai/schema/credential"
|
||||||
|
import { FileSystem } from "@opencode-ai/schema/filesystem"
|
||||||
|
import { Integration } from "@opencode-ai/schema/integration"
|
||||||
|
import { LLM } from "@opencode-ai/schema/llm"
|
||||||
|
import { ModelRequest } from "@opencode-ai/schema/model-request"
|
||||||
|
import { Permission } from "@opencode-ai/schema/permission"
|
||||||
|
import { Reference } from "@opencode-ai/schema/reference"
|
||||||
|
import { Skill } from "@opencode-ai/schema/skill"
|
||||||
|
import { AbsolutePath, DateTimeUtcFromMillis } from "@opencode-ai/schema/schema"
|
||||||
|
import { ProviderV2 } from "@opencode-ai/core/provider"
|
||||||
|
|
||||||
|
test("Core reuses the canonical shared schemas", async () => {
|
||||||
|
const [
|
||||||
|
coreCommand,
|
||||||
|
coreConnection,
|
||||||
|
coreCredential,
|
||||||
|
coreFileSystem,
|
||||||
|
coreIntegration,
|
||||||
|
coreLocation,
|
||||||
|
coreLLM,
|
||||||
|
coreModelRequest,
|
||||||
|
corePermission,
|
||||||
|
coreProject,
|
||||||
|
coreReference,
|
||||||
|
coreSessionInput,
|
||||||
|
coreSessionMessage,
|
||||||
|
corePrompt,
|
||||||
|
coreSkill,
|
||||||
|
coreV2Schema,
|
||||||
|
coreWorkspace,
|
||||||
|
] = await Promise.all([
|
||||||
|
import("@opencode-ai/core/command"),
|
||||||
|
import("@opencode-ai/core/integration/connection"),
|
||||||
|
import("@opencode-ai/core/credential"),
|
||||||
|
import("@opencode-ai/core/filesystem/schema"),
|
||||||
|
import("@opencode-ai/core/integration"),
|
||||||
|
import("@opencode-ai/core/location"),
|
||||||
|
import("@opencode-ai/llm"),
|
||||||
|
import("@opencode-ai/core/model-request"),
|
||||||
|
import("@opencode-ai/core/permission/schema"),
|
||||||
|
import("@opencode-ai/core/project/schema"),
|
||||||
|
import("@opencode-ai/core/reference"),
|
||||||
|
import("@opencode-ai/core/session/input"),
|
||||||
|
import("@opencode-ai/core/session/message"),
|
||||||
|
import("@opencode-ai/core/session/prompt"),
|
||||||
|
import("@opencode-ai/core/skill"),
|
||||||
|
import("@opencode-ai/core/v2-schema"),
|
||||||
|
import("@opencode-ai/core/workspace"),
|
||||||
|
])
|
||||||
|
|
||||||
|
const schemas = [
|
||||||
|
[AgentV2.ID, Agent.ID],
|
||||||
|
[AgentV2.Color, Agent.Color],
|
||||||
|
[AgentV2.Info, Agent.Info],
|
||||||
|
[coreCommand.Info, Command.Info],
|
||||||
|
[coreConnection.CredentialInfo, Connection.CredentialInfo],
|
||||||
|
[coreConnection.EnvInfo, Connection.EnvInfo],
|
||||||
|
[coreConnection.Info, Connection.Info],
|
||||||
|
[coreCredential.ID, Credential.ID],
|
||||||
|
[coreCredential.OAuth, Credential.OAuth],
|
||||||
|
[coreCredential.Key, Credential.Key],
|
||||||
|
[coreCredential.Value, Credential.Value],
|
||||||
|
[coreFileSystem.Entry, FileSystem.Entry],
|
||||||
|
[coreFileSystem.Submatch, FileSystem.Submatch],
|
||||||
|
[coreFileSystem.Match, FileSystem.Match],
|
||||||
|
[coreIntegration.When, Integration.When],
|
||||||
|
[coreIntegration.TextPrompt, Integration.TextPrompt],
|
||||||
|
[coreIntegration.SelectPrompt, Integration.SelectPrompt],
|
||||||
|
[coreIntegration.Prompt, Integration.Prompt],
|
||||||
|
[coreIntegration.OAuthMethod, Integration.OAuthMethod],
|
||||||
|
[coreIntegration.KeyMethod, Integration.KeyMethod],
|
||||||
|
[coreIntegration.EnvMethod, Integration.EnvMethod],
|
||||||
|
[coreIntegration.Method, Integration.Method],
|
||||||
|
[coreIntegration.Inputs, Integration.Inputs],
|
||||||
|
[coreIntegration.Ref, Integration.Ref],
|
||||||
|
[coreLocation.Ref, Location.Ref],
|
||||||
|
[coreLLM.ProviderMetadata, LLM.ProviderMetadata],
|
||||||
|
[coreLLM.ToolTextContent, LLM.ToolTextContent],
|
||||||
|
[coreLLM.ToolFileContent, LLM.ToolFileContent],
|
||||||
|
[coreLLM.ToolContent, LLM.ToolContent],
|
||||||
|
[ModelV2.ID, Model.ID],
|
||||||
|
[ModelV2.VariantID, Model.VariantID],
|
||||||
|
[ModelV2.Ref, Model.Ref],
|
||||||
|
[ModelV2.Family, Model.Family],
|
||||||
|
[ModelV2.Capabilities, Model.Capabilities],
|
||||||
|
[ModelV2.Cost, Model.Cost],
|
||||||
|
[ModelV2.Api, Model.Api],
|
||||||
|
[ModelV2.Info, Model.Info],
|
||||||
|
[ProviderV2.ID, Provider.ID],
|
||||||
|
[ProviderV2.AISDK, Provider.AISDK],
|
||||||
|
[ProviderV2.Native, Provider.Native],
|
||||||
|
[ProviderV2.Api, Provider.Api],
|
||||||
|
[ProviderV2.Request, Provider.Request],
|
||||||
|
[ProviderV2.Info, Provider.Info],
|
||||||
|
[coreModelRequest.Generation, ModelRequest.Generation],
|
||||||
|
[coreModelRequest.Request, ModelRequest.Request],
|
||||||
|
[corePermission.Effect, Permission.Effect],
|
||||||
|
[corePermission.Rule, Permission.Rule],
|
||||||
|
[corePermission.Ruleset, Permission.Ruleset],
|
||||||
|
[coreProject.ID, Project.ID],
|
||||||
|
[coreReference.LocalSource, Reference.LocalSource],
|
||||||
|
[coreReference.GitSource, Reference.GitSource],
|
||||||
|
[coreReference.Source, Reference.Source],
|
||||||
|
[SessionV2.ID, Session.ID],
|
||||||
|
[SessionV2.Info, Session.Info],
|
||||||
|
[SessionV2.ListAnchor, Session.ListAnchor],
|
||||||
|
[coreSessionInput.Delivery, SessionInput.Delivery],
|
||||||
|
[coreSessionInput.Admitted, SessionInput.Admitted],
|
||||||
|
[coreSessionMessage.ID, SessionMessage.ID],
|
||||||
|
[coreSessionMessage.UnknownError, SessionMessage.UnknownError],
|
||||||
|
[coreSessionMessage.AgentSwitched, SessionMessage.AgentSwitched],
|
||||||
|
[coreSessionMessage.ModelSwitched, SessionMessage.ModelSwitched],
|
||||||
|
[coreSessionMessage.User, SessionMessage.User],
|
||||||
|
[coreSessionMessage.Synthetic, SessionMessage.Synthetic],
|
||||||
|
[coreSessionMessage.System, SessionMessage.System],
|
||||||
|
[coreSessionMessage.Shell, SessionMessage.Shell],
|
||||||
|
[coreSessionMessage.ToolStatePending, SessionMessage.ToolStatePending],
|
||||||
|
[coreSessionMessage.ToolStateRunning, SessionMessage.ToolStateRunning],
|
||||||
|
[coreSessionMessage.ToolStateCompleted, SessionMessage.ToolStateCompleted],
|
||||||
|
[coreSessionMessage.ToolStateError, SessionMessage.ToolStateError],
|
||||||
|
[coreSessionMessage.ToolState, SessionMessage.ToolState],
|
||||||
|
[coreSessionMessage.AssistantTool, SessionMessage.AssistantTool],
|
||||||
|
[coreSessionMessage.AssistantText, SessionMessage.AssistantText],
|
||||||
|
[coreSessionMessage.AssistantReasoning, SessionMessage.AssistantReasoning],
|
||||||
|
[coreSessionMessage.AssistantContent, SessionMessage.AssistantContent],
|
||||||
|
[coreSessionMessage.Assistant, SessionMessage.Assistant],
|
||||||
|
[coreSessionMessage.Compaction, SessionMessage.Compaction],
|
||||||
|
[coreSessionMessage.Message, SessionMessage.Message],
|
||||||
|
[corePrompt.Source, Source],
|
||||||
|
[corePrompt.FileAttachment, FileAttachment],
|
||||||
|
[corePrompt.AgentAttachment, AgentAttachment],
|
||||||
|
[corePrompt.Prompt, Prompt],
|
||||||
|
[coreSkill.DirectorySource, Skill.DirectorySource],
|
||||||
|
[coreSkill.UrlSource, Skill.UrlSource],
|
||||||
|
[coreSkill.EmbeddedSource, Skill.EmbeddedSource],
|
||||||
|
[coreSkill.Source, Skill.Source],
|
||||||
|
[coreSkill.Info, Skill.Info],
|
||||||
|
[coreV2Schema.DateTimeUtcFromMillis, DateTimeUtcFromMillis],
|
||||||
|
[coreWorkspace.ID, Workspace.ID],
|
||||||
|
]
|
||||||
|
for (const [core, shared] of schemas) expect(core).toBe(shared)
|
||||||
|
|
||||||
|
expect(Agent.Info.empty(Agent.ID.make("test"))).toEqual(AgentV2.Info.empty(AgentV2.ID.make("test")))
|
||||||
|
expect(Model.Info.empty(Provider.ID.make("test"), Model.ID.make("model"))).toEqual(
|
||||||
|
ModelV2.Info.empty(ProviderV2.ID.make("test"), ModelV2.ID.make("model")),
|
||||||
|
)
|
||||||
|
expect(Provider.Info.empty(Provider.ID.make("test"))).toEqual(ProviderV2.Info.empty(ProviderV2.ID.make("test")))
|
||||||
|
expect(Skill.Source.key(Skill.DirectorySource.make({ type: "directory", path: AbsolutePath.make("/tmp") }))).toBe(
|
||||||
|
"directory:/tmp",
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("shared record schemas construct and decode plain objects", () => {
|
||||||
|
const made = Prompt.make({ text: "hello" })
|
||||||
|
const decoded = Schema.decodeUnknownSync(Prompt)({ text: "hello" })
|
||||||
|
const content = Schema.decodeUnknownSync(SessionMessage.AssistantText)({ type: "text", id: "part_1", text: "hi" })
|
||||||
|
|
||||||
|
expect(Object.getPrototypeOf(made)).toBe(Object.prototype)
|
||||||
|
expect(Object.getPrototypeOf(decoded)).toBe(Object.prototype)
|
||||||
|
expect(Object.getPrototypeOf(content)).toBe(Object.prototype)
|
||||||
|
expect(Prompt.ast.annotations?.identifier).toBe("Prompt")
|
||||||
|
expect(SessionMessage.AssistantText.ast.annotations?.identifier).toBe("Session.Message.Assistant.Text")
|
||||||
|
expect(Prompt.equivalence(Prompt.make({ text: "hello" }), decoded)).toBe(true)
|
||||||
|
expect(Prompt.fromUserMessage({ text: "hello" })).toEqual(made)
|
||||||
|
expect(Workspace.ID.ascending("")).toStartWith("wrk_")
|
||||||
|
})
|
||||||
@@ -74,7 +74,7 @@ describe("SkillV2", () => {
|
|||||||
{ type: "directory", path: AbsolutePath.make(second) },
|
{ type: "directory", path: AbsolutePath.make(second) },
|
||||||
])
|
])
|
||||||
expect(yield* skill.list()).toEqual([
|
expect(yield* skill.list()).toEqual([
|
||||||
new SkillV2.Info({
|
SkillV2.Info.make({
|
||||||
name: "foo",
|
name: "foo",
|
||||||
slash: true,
|
slash: true,
|
||||||
location: AbsolutePath.make(path.join(first, "foo.md")),
|
location: AbsolutePath.make(path.join(first, "foo.md")),
|
||||||
|
|||||||
@@ -9,18 +9,18 @@ import { SkillGuidance } from "@opencode-ai/core/skill/guidance"
|
|||||||
import { it } from "../lib/effect"
|
import { it } from "../lib/effect"
|
||||||
|
|
||||||
const build = AgentV2.ID.make("build")
|
const build = AgentV2.ID.make("build")
|
||||||
const effect = new SkillV2.Info({
|
const effect = SkillV2.Info.make({
|
||||||
name: "effect",
|
name: "effect",
|
||||||
description: "Build applications with Effect",
|
description: "Build applications with Effect",
|
||||||
location: AbsolutePath.make(path.resolve("/skills/effect/SKILL.md")),
|
location: AbsolutePath.make(path.resolve("/skills/effect/SKILL.md")),
|
||||||
content: "Effect guidance",
|
content: "Effect guidance",
|
||||||
})
|
})
|
||||||
const hidden = new SkillV2.Info({
|
const hidden = SkillV2.Info.make({
|
||||||
name: "hidden",
|
name: "hidden",
|
||||||
location: AbsolutePath.make(path.resolve("/skills/hidden/SKILL.md")),
|
location: AbsolutePath.make(path.resolve("/skills/hidden/SKILL.md")),
|
||||||
content: "Undescribed guidance",
|
content: "Undescribed guidance",
|
||||||
})
|
})
|
||||||
const denied = new SkillV2.Info({
|
const denied = SkillV2.Info.make({
|
||||||
name: "denied",
|
name: "denied",
|
||||||
description: "Must not be advertised",
|
description: "Must not be advertised",
|
||||||
location: AbsolutePath.make(path.resolve("/skills/denied/SKILL.md")),
|
location: AbsolutePath.make(path.resolve("/skills/denied/SKILL.md")),
|
||||||
@@ -32,7 +32,7 @@ const layer = (list: () => SkillV2.Info[]) =>
|
|||||||
|
|
||||||
describe("SkillGuidance", () => {
|
describe("SkillGuidance", () => {
|
||||||
it.effect("renders described agent skills and reconciles the complete available list", () => {
|
it.effect("renders described agent skills and reconciles the complete available list", () => {
|
||||||
const agent = new AgentV2.Info({
|
const agent = AgentV2.Info.make({
|
||||||
...AgentV2.Info.empty(build),
|
...AgentV2.Info.empty(build),
|
||||||
permissions: [{ action: "skill", resource: "denied", effect: "deny" }],
|
permissions: [{ action: "skill", resource: "denied", effect: "deny" }],
|
||||||
})
|
})
|
||||||
@@ -69,7 +69,7 @@ describe("SkillGuidance", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it.effect("omits guidance when the selected agent denies all skills", () => {
|
it.effect("omits guidance when the selected agent denies all skills", () => {
|
||||||
const agent = new AgentV2.Info({
|
const agent = AgentV2.Info.make({
|
||||||
...AgentV2.Info.empty(build),
|
...AgentV2.Info.empty(build),
|
||||||
permissions: [{ action: "skill", resource: "*", effect: "deny" }],
|
permissions: [{ action: "skill", resource: "*", effect: "deny" }],
|
||||||
})
|
})
|
||||||
@@ -85,7 +85,7 @@ describe("SkillGuidance", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it.effect("omits guidance when a resource-specific denial follows the global denial", () => {
|
it.effect("omits guidance when a resource-specific denial follows the global denial", () => {
|
||||||
const agent = new AgentV2.Info({
|
const agent = AgentV2.Info.make({
|
||||||
...AgentV2.Info.empty(build),
|
...AgentV2.Info.empty(build),
|
||||||
permissions: [
|
permissions: [
|
||||||
{ action: "skill", resource: "*", effect: "deny" },
|
{ action: "skill", resource: "*", effect: "deny" },
|
||||||
@@ -104,7 +104,7 @@ describe("SkillGuidance", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it.effect("retains specifically allowed skills after a global denial", () => {
|
it.effect("retains specifically allowed skills after a global denial", () => {
|
||||||
const agent = new AgentV2.Info({
|
const agent = AgentV2.Info.make({
|
||||||
...AgentV2.Info.empty(build),
|
...AgentV2.Info.empty(build),
|
||||||
permissions: [
|
permissions: [
|
||||||
{ action: "skill", resource: "*", effect: "deny" },
|
{ action: "skill", resource: "*", effect: "deny" },
|
||||||
@@ -120,7 +120,7 @@ describe("SkillGuidance", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it.effect("omits guidance when a specifically allowed skill is denied again", () => {
|
it.effect("omits guidance when a specifically allowed skill is denied again", () => {
|
||||||
const agent = new AgentV2.Info({
|
const agent = AgentV2.Info.make({
|
||||||
...AgentV2.Info.empty(build),
|
...AgentV2.Info.empty(build),
|
||||||
permissions: [
|
permissions: [
|
||||||
{ action: "skill", resource: "*", effect: "deny" },
|
{ action: "skill", resource: "*", effect: "deny" },
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ describe("SkillTool", () => {
|
|||||||
}),
|
}),
|
||||||
).toEqual({ type: "error", value: "Unable to load skill effect" })
|
).toEqual({ type: "error", value: "Unable to load skill effect" })
|
||||||
deny = false
|
deny = false
|
||||||
const flat = new SkillV2.Info({
|
const flat = SkillV2.Info.make({
|
||||||
name: "public",
|
name: "public",
|
||||||
description: "Public guidance",
|
description: "Public guidance",
|
||||||
location: AbsolutePath.make(path.join(tmp.path, "public.md")),
|
location: AbsolutePath.make(path.join(tmp.path, "public.md")),
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@smithy/eventstream-codec": "4.2.14",
|
"@smithy/eventstream-codec": "4.2.14",
|
||||||
"@smithy/util-utf8": "4.2.2",
|
"@smithy/util-utf8": "4.2.2",
|
||||||
|
"@opencode-ai/schema": "workspace:*",
|
||||||
"aws4fetch": "1.0.20",
|
"aws4fetch": "1.0.20",
|
||||||
"effect": "catalog:"
|
"effect": "catalog:"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import { Schema } from "effect"
|
import { Schema } from "effect"
|
||||||
|
import { ProviderMetadata } from "@opencode-ai/schema/llm"
|
||||||
|
|
||||||
|
export { ProviderMetadata }
|
||||||
|
|
||||||
/** Stable string identifier for a protocol implementation. */
|
/** Stable string identifier for a protocol implementation. */
|
||||||
export const ProtocolID = Schema.String
|
export const ProtocolID = Schema.String
|
||||||
@@ -38,6 +41,3 @@ export type FinishReason = Schema.Schema.Type<typeof FinishReason>
|
|||||||
|
|
||||||
export const JsonSchema = Schema.Record(Schema.String, Schema.Unknown)
|
export const JsonSchema = Schema.Record(Schema.String, Schema.Unknown)
|
||||||
export type JsonSchema = Schema.Schema.Type<typeof JsonSchema>
|
export type JsonSchema = Schema.Schema.Type<typeof JsonSchema>
|
||||||
|
|
||||||
export const ProviderMetadata = Schema.Record(Schema.String, Schema.Record(Schema.String, Schema.Unknown))
|
|
||||||
export type ProviderMetadata = Schema.Schema.Type<typeof ProviderMetadata>
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Schema } from "effect"
|
import { Schema } from "effect"
|
||||||
|
import { ToolContent, ToolFileContent, ToolTextContent } from "@opencode-ai/schema/llm"
|
||||||
import { JsonSchema, MessageRole, ProviderMetadata } from "./ids"
|
import { JsonSchema, MessageRole, ProviderMetadata } from "./ids"
|
||||||
import { CacheHint, CachePolicy, GenerationOptions, HttpOptions, ModelSchema, ProviderOptions } from "./options"
|
import { CacheHint, CachePolicy, GenerationOptions, HttpOptions, ModelSchema, ProviderOptions } from "./options"
|
||||||
import { isRecord } from "../utils/record"
|
import { isRecord } from "../utils/record"
|
||||||
@@ -39,23 +40,7 @@ export const MediaPart = Schema.Struct({
|
|||||||
}).annotate({ identifier: "LLM.Content.Media" })
|
}).annotate({ identifier: "LLM.Content.Media" })
|
||||||
export type MediaPart = Schema.Schema.Type<typeof MediaPart>
|
export type MediaPart = Schema.Schema.Type<typeof MediaPart>
|
||||||
|
|
||||||
export const ToolTextContent = Schema.Struct({
|
export { ToolContent, ToolFileContent, ToolTextContent }
|
||||||
type: Schema.Literal("text"),
|
|
||||||
text: Schema.String,
|
|
||||||
}).annotate({ identifier: "Tool.TextContent" })
|
|
||||||
export type ToolTextContent = typeof ToolTextContent.Type
|
|
||||||
|
|
||||||
export const ToolFileContent = Schema.Struct({
|
|
||||||
type: Schema.Literal("file"),
|
|
||||||
uri: Schema.String,
|
|
||||||
mime: Schema.String,
|
|
||||||
name: Schema.optional(Schema.String),
|
|
||||||
}).annotate({ identifier: "Tool.FileContent" })
|
|
||||||
export type ToolFileContent = typeof ToolFileContent.Type
|
|
||||||
|
|
||||||
/** Ordered, provider-independent content shown to models and UIs after a tool succeeds. */
|
|
||||||
export const ToolContent = Schema.Union([ToolTextContent, ToolFileContent]).pipe(Schema.toTaggedUnion("type"))
|
|
||||||
export type ToolContent = Schema.Schema.Type<typeof ToolContent>
|
|
||||||
|
|
||||||
const isToolResultValue = (value: unknown): value is ToolResultValue =>
|
const isToolResultValue = (value: unknown): value is ToolResultValue =>
|
||||||
isRecord(value) &&
|
isRecord(value) &&
|
||||||
|
|||||||
@@ -1086,12 +1086,12 @@ export const layer = Layer.effect(
|
|||||||
}
|
}
|
||||||
if (part.type === "file") {
|
if (part.type === "file") {
|
||||||
result.files.push(
|
result.files.push(
|
||||||
new FileAttachment({
|
FileAttachment.make({
|
||||||
uri: part.url,
|
uri: part.url,
|
||||||
mime: part.mime,
|
mime: part.mime,
|
||||||
name: part.filename,
|
name: part.filename,
|
||||||
source: part.source
|
source: part.source
|
||||||
? new Source({
|
? Source.make({
|
||||||
start: part.source.text.start,
|
start: part.source.text.start,
|
||||||
end: part.source.text.end,
|
end: part.source.text.end,
|
||||||
text: part.source.text.value,
|
text: part.source.text.value,
|
||||||
@@ -1102,10 +1102,10 @@ export const layer = Layer.effect(
|
|||||||
}
|
}
|
||||||
if (part.type === "agent") {
|
if (part.type === "agent") {
|
||||||
result.agents.push(
|
result.agents.push(
|
||||||
new AgentAttachment({
|
AgentAttachment.make({
|
||||||
name: part.name,
|
name: part.name,
|
||||||
source: part.source
|
source: part.source
|
||||||
? new Source({
|
? Source.make({
|
||||||
start: part.source.start,
|
start: part.source.start,
|
||||||
end: part.source.end,
|
end: part.source.end,
|
||||||
text: part.source.value,
|
text: part.source.value,
|
||||||
@@ -1130,7 +1130,7 @@ export const layer = Layer.effect(
|
|||||||
messageID: SessionMessage.ID.create(),
|
messageID: SessionMessage.ID.create(),
|
||||||
timestamp: DateTime.makeUnsafe(info.time.created),
|
timestamp: DateTime.makeUnsafe(info.time.created),
|
||||||
delivery: "steer",
|
delivery: "steer",
|
||||||
prompt: new Prompt({
|
prompt: Prompt.make({
|
||||||
text: nextPrompt.text.join("\n"),
|
text: nextPrompt.text.join("\n"),
|
||||||
files: nextPrompt.files,
|
files: nextPrompt.files,
|
||||||
agents: nextPrompt.agents,
|
agents: nextPrompt.agents,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user