mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-30 15:11:11 -04:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6cc915bcf7 |
@@ -29,7 +29,7 @@
|
||||
},
|
||||
"packages/app": {
|
||||
"name": "@opencode-ai/app",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@corvu/drawer": "catalog:",
|
||||
"@dnd-kit/abstract": "0.5.0",
|
||||
@@ -96,7 +96,7 @@
|
||||
},
|
||||
"packages/cli": {
|
||||
"name": "@opencode-ai/cli",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"bin": {
|
||||
"lildax": "./bin/lildax.cjs",
|
||||
},
|
||||
@@ -144,7 +144,7 @@
|
||||
},
|
||||
"packages/codemode": {
|
||||
"name": "@opencode-ai/codemode",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"acorn": "8.15.0",
|
||||
"effect": "catalog:",
|
||||
@@ -158,7 +158,7 @@
|
||||
},
|
||||
"packages/console/app": {
|
||||
"name": "@opencode-ai/console-app",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "1.15.2",
|
||||
"@ibm/plex": "6.4.1",
|
||||
@@ -194,7 +194,7 @@
|
||||
},
|
||||
"packages/console/core": {
|
||||
"name": "@opencode-ai/console-core",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-sts": "3.782.0",
|
||||
"@jsx-email/render": "1.1.1",
|
||||
@@ -221,7 +221,7 @@
|
||||
},
|
||||
"packages/console/function": {
|
||||
"name": "@opencode-ai/console-function",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "3.0.82",
|
||||
"@ai-sdk/openai": "3.0.48",
|
||||
@@ -243,7 +243,7 @@
|
||||
},
|
||||
"packages/console/mail": {
|
||||
"name": "@opencode-ai/console-mail",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
@@ -267,7 +267,7 @@
|
||||
},
|
||||
"packages/console/support": {
|
||||
"name": "@opencode-ai/console-support",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "1.15.2",
|
||||
"@opencode-ai/console-core": "workspace:*",
|
||||
@@ -287,7 +287,7 @@
|
||||
},
|
||||
"packages/core": {
|
||||
"name": "@opencode-ai/core",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"bin": {
|
||||
"opencode": "./bin/opencode",
|
||||
},
|
||||
@@ -381,7 +381,7 @@
|
||||
},
|
||||
"packages/desktop": {
|
||||
"name": "@opencode-ai/desktop",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@zip.js/zip.js": "2.7.62",
|
||||
"effect": "catalog:",
|
||||
@@ -435,7 +435,7 @@
|
||||
},
|
||||
"packages/effect-drizzle-sqlite": {
|
||||
"name": "@opencode-ai/effect-drizzle-sqlite",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"drizzle-orm": "catalog:",
|
||||
"effect": "catalog:",
|
||||
@@ -449,7 +449,7 @@
|
||||
},
|
||||
"packages/effect-sqlite-node": {
|
||||
"name": "@opencode-ai/effect-sqlite-node",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"effect": "catalog:",
|
||||
},
|
||||
@@ -461,7 +461,7 @@
|
||||
},
|
||||
"packages/enterprise": {
|
||||
"name": "@opencode-ai/enterprise",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@hono/standard-validator": "catalog:",
|
||||
"@opencode-ai/core": "workspace:*",
|
||||
@@ -493,7 +493,7 @@
|
||||
},
|
||||
"packages/function": {
|
||||
"name": "@opencode-ai/function",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@octokit/auth-app": "8.0.1",
|
||||
"@octokit/rest": "catalog:",
|
||||
@@ -509,7 +509,7 @@
|
||||
},
|
||||
"packages/http-recorder": {
|
||||
"name": "@opencode-ai/http-recorder",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@effect/platform-node": "4.0.0-beta.83",
|
||||
"@effect/platform-node-shared": "4.0.0-beta.83",
|
||||
@@ -540,7 +540,7 @@
|
||||
},
|
||||
"packages/llm": {
|
||||
"name": "@opencode-ai/llm",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@opencode-ai/schema": "workspace:*",
|
||||
"@smithy/eventstream-codec": "4.2.14",
|
||||
@@ -559,7 +559,7 @@
|
||||
},
|
||||
"packages/opencode": {
|
||||
"name": "opencode",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"bin": {
|
||||
"opencode": "./bin/opencode",
|
||||
},
|
||||
@@ -690,7 +690,7 @@
|
||||
},
|
||||
"packages/plugin": {
|
||||
"name": "@opencode-ai/plugin",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@ai-sdk/provider": "3.0.8",
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
@@ -766,7 +766,7 @@
|
||||
},
|
||||
"packages/sdk/js": {
|
||||
"name": "@opencode-ai/sdk",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"cross-spawn": "catalog:",
|
||||
},
|
||||
@@ -781,7 +781,7 @@
|
||||
},
|
||||
"packages/server": {
|
||||
"name": "@opencode-ai/server",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@opencode-ai/core": "workspace:*",
|
||||
"@opencode-ai/protocol": "workspace:*",
|
||||
@@ -796,7 +796,7 @@
|
||||
},
|
||||
"packages/session-ui": {
|
||||
"name": "@opencode-ai/session-ui",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@opencode-ai/client": "file:../app/vendor/opencode-ai-client-1.17.13-v2.tgz",
|
||||
@@ -841,7 +841,7 @@
|
||||
},
|
||||
"packages/slack": {
|
||||
"name": "@opencode-ai/slack",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"@slack/bolt": "^3.17.1",
|
||||
@@ -854,7 +854,7 @@
|
||||
},
|
||||
"packages/stats/app": {
|
||||
"name": "@opencode-ai/stats-app",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@ibm/plex": "6.4.1",
|
||||
"@kobalte/core": "catalog:",
|
||||
@@ -888,7 +888,7 @@
|
||||
},
|
||||
"packages/stats/core": {
|
||||
"name": "@opencode-ai/stats-core",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-athena": "3.933.0",
|
||||
"@planetscale/database": "1.19.0",
|
||||
@@ -907,7 +907,7 @@
|
||||
},
|
||||
"packages/stats/server": {
|
||||
"name": "@opencode-ai/stats-server",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-firehose": "3.933.0",
|
||||
"@effect/platform-node": "catalog:",
|
||||
@@ -949,7 +949,7 @@
|
||||
},
|
||||
"packages/tui": {
|
||||
"name": "@opencode-ai/tui",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@opencode-ai/core": "workspace:*",
|
||||
"@opencode-ai/plugin": "workspace:*",
|
||||
@@ -976,7 +976,7 @@
|
||||
},
|
||||
"packages/ui": {
|
||||
"name": "@opencode-ai/ui",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@pierre/diffs": "catalog:",
|
||||
@@ -1028,7 +1028,7 @@
|
||||
},
|
||||
"packages/web": {
|
||||
"name": "@opencode-ai/web",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@astrojs/cloudflare": "12.6.3",
|
||||
"@astrojs/markdown-remark": "6.3.1",
|
||||
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"nodeModules": {
|
||||
"x86_64-linux": "sha256-AD5kt1o035hdvYPyrvjiz2mcsXFJ7UJVEmbE9AJFDFs=",
|
||||
"aarch64-linux": "sha256-f1gVXUpIRWC/I8dxIigdGGvPsju04MXVjZhtq5EYL64=",
|
||||
"aarch64-darwin": "sha256-c+JRpjs2gsgQ2czyM6bTbYEdMbX/erOSQdX6TdrI59k=",
|
||||
"x86_64-darwin": "sha256-iB7l4PtQQ9Mx/XAdtyayiLe6pZKhuXB9lpmrbTr+uWc="
|
||||
"x86_64-linux": "sha256-fK6zAHJC3ut/KUdfqLPxVMH7Z1yv65YZ7qcHF45kPas=",
|
||||
"aarch64-linux": "sha256-CSWZY/vVUCKzlwfisQQHqHjawUwL0BRc8Y9o2y/QZYA=",
|
||||
"aarch64-darwin": "sha256-IyFm5NbnU63BaOO/F4/v1exz3VbvkY96yjg9iun+O9Q=",
|
||||
"x86_64-darwin": "sha256-XnXFoUxqXmEx7AKx5YhaJuLY2NYMtI0ICafaenU5L6k="
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/app",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import type { ServerConnection } from "./server"
|
||||
import type { Tab } from "./tabs"
|
||||
|
||||
export function migrateTabs(value: unknown, fallback: ServerConnection.Key): Tab[] {
|
||||
if (!Array.isArray(value)) return []
|
||||
return value.flatMap<Tab>((tab) => {
|
||||
if (!tab || typeof tab !== "object") return []
|
||||
if ("server" in tab && typeof tab.server !== "string") return []
|
||||
const server = ("server" in tab ? tab.server : fallback) as ServerConnection.Key
|
||||
if (tab.type === "session" && typeof tab.sessionId === "string") {
|
||||
return [{ type: tab.type, server, sessionId: tab.sessionId }]
|
||||
}
|
||||
if (
|
||||
tab.type === "draft" &&
|
||||
typeof tab.draftID === "string" &&
|
||||
typeof tab.directory === "string" &&
|
||||
(tab.worktree === undefined || typeof tab.worktree === "string")
|
||||
) {
|
||||
return [{ type: tab.type, server, draftID: tab.draftID, directory: tab.directory, worktree: tab.worktree }]
|
||||
}
|
||||
return []
|
||||
})
|
||||
}
|
||||
@@ -3,7 +3,6 @@ import { createRoot, getOwner, onCleanup } from "solid-js"
|
||||
import { createTabMemory } from "./tab-memory"
|
||||
import { nextTabAfterClose, pushClosedTab, removeClosedTabs, takeClosedTab, type ClosedTab } from "./closed-tabs"
|
||||
import type { SessionTab, Tab } from "./tabs"
|
||||
import { migrateTabs } from "./tab-migration"
|
||||
import type { ServerConnection } from "./server"
|
||||
|
||||
const server = "local\nhttp://localhost:4096" as ServerConnection.Key
|
||||
@@ -12,23 +11,6 @@ function sessionTab(sessionId: string): SessionTab {
|
||||
return { type: "session", server, sessionId }
|
||||
}
|
||||
|
||||
describe("tab migration", () => {
|
||||
test("drops null and malformed persisted tabs", () => {
|
||||
expect(
|
||||
migrateTabs([null, sessionTab("a"), { type: "session", server }, { type: "unknown", server }, "invalid"], server),
|
||||
).toEqual([sessionTab("a")])
|
||||
})
|
||||
|
||||
test("adds the fallback server to valid legacy tabs", () => {
|
||||
expect(migrateTabs([{ type: "session", sessionId: "a", dirBase64: "legacy" }], server)).toEqual([sessionTab("a")])
|
||||
})
|
||||
|
||||
test("replaces invalid top-level persisted data", () => {
|
||||
expect(migrateTabs(null, server)).toEqual([])
|
||||
expect(migrateTabs({}, server)).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
describe("tab memory", () => {
|
||||
test("keeps state until its tab is removed", () => {
|
||||
createRoot((dispose) => {
|
||||
|
||||
@@ -12,7 +12,6 @@ import { sessionHref } from "@/utils/session-route"
|
||||
import { createTabMemory } from "./tab-memory"
|
||||
import { nextTabAfterClose, pushClosedTab, removeClosedTabs, takeClosedTab, type ClosedTab } from "./closed-tabs"
|
||||
import { createDraftPromptSession, type PromptModel } from "./prompt-state"
|
||||
import { migrateTabs } from "./tab-migration"
|
||||
|
||||
export type SessionTab = {
|
||||
type: "session"
|
||||
@@ -60,7 +59,13 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({
|
||||
const [store, setStore, _, ready] = persisted(
|
||||
{
|
||||
...Persist.window("tabs"),
|
||||
migrate: (value: unknown) => migrateTabs(value, fallback),
|
||||
migrate: (value: unknown) => {
|
||||
if (!Array.isArray(value)) return value
|
||||
return value.map((tab) => {
|
||||
if (!tab || typeof tab !== "object" || "server" in tab) return tab
|
||||
return { ...tab, server: fallback }
|
||||
})
|
||||
},
|
||||
},
|
||||
createStore<Tab[]>([]),
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/cli",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const modelsUrl = process.env.OPENCODE_MODELS_URL || "https://models.opencode.ai"
|
||||
const modelsUrl = process.env.OPENCODE_MODELS_URL || "https://models.dev"
|
||||
|
||||
export const modelsData = process.env.MODELS_DEV_API_JSON
|
||||
? await Bun.file(process.env.MODELS_DEV_API_JSON).text()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/codemode",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"description": "Effect-native confined code execution over schema-described tools",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-app",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import type { Stripe } from "stripe"
|
||||
|
||||
export function liteCheckoutSubscriptionToProvision(
|
||||
type: "checkout.session.completed" | "checkout.session.async_payment_succeeded",
|
||||
session: Pick<Stripe.Checkout.Session, "mode" | "payment_status" | "subscription">,
|
||||
) {
|
||||
if (session.mode !== "subscription") return
|
||||
if (typeof session.subscription !== "string") return
|
||||
if (type === "checkout.session.completed" && session.payment_status === "unpaid") return
|
||||
return session.subscription
|
||||
}
|
||||
|
||||
export function liteSubscriptionProvisioningData(
|
||||
subscription: Pick<
|
||||
Stripe.Subscription,
|
||||
"id" | "status" | "customer" | "default_payment_method" | "metadata"
|
||||
>,
|
||||
) {
|
||||
if (subscription.metadata.type !== "lite") return
|
||||
if (subscription.status !== "active" && subscription.status !== "trialing") return
|
||||
if (typeof subscription.customer !== "string") throw new Error("Customer ID not found")
|
||||
|
||||
const workspaceID = subscription.metadata.workspaceID
|
||||
const userID = subscription.metadata.userID
|
||||
if (!workspaceID) throw new Error("Workspace ID not found")
|
||||
if (!userID) throw new Error("User ID not found")
|
||||
|
||||
return {
|
||||
subscriptionID: subscription.id,
|
||||
customerID: subscription.customer,
|
||||
workspaceID,
|
||||
userID,
|
||||
userEmail: subscription.metadata.userEmail || undefined,
|
||||
coupon: subscription.metadata.coupon || undefined,
|
||||
paymentMethodID:
|
||||
typeof subscription.default_payment_method === "string"
|
||||
? subscription.default_payment_method
|
||||
: subscription.default_payment_method?.id,
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,10 @@ import { Resource } from "@opencode-ai/console-resource"
|
||||
import { LiteData } from "@opencode-ai/console-core/lite.js"
|
||||
import { BlackData } from "@opencode-ai/console-core/black.js"
|
||||
import { Referral } from "@opencode-ai/console-core/referral.js"
|
||||
import {
|
||||
liteCheckoutSubscriptionToProvision,
|
||||
liteSubscriptionProvisioningData,
|
||||
} from "./lite-subscription.js"
|
||||
|
||||
export async function POST(input: APIEvent) {
|
||||
const body = await Billing.stripe().webhooks.constructEventAsync(
|
||||
@@ -20,6 +24,10 @@ export async function POST(input: APIEvent) {
|
||||
console.log(body.type, JSON.stringify(body, null, 2))
|
||||
|
||||
return (async () => {
|
||||
if (body.type === "checkout.session.completed" || body.type === "checkout.session.async_payment_succeeded") {
|
||||
const subscriptionID = liteCheckoutSubscriptionToProvision(body.type, body.data.object)
|
||||
if (subscriptionID) await provisionLiteSubscription(subscriptionID)
|
||||
}
|
||||
if (body.type === "customer.updated") {
|
||||
// check default payment method changed
|
||||
const prevInvoiceSettings = body.data.previous_attributes?.invoice_settings ?? {}
|
||||
@@ -105,85 +113,6 @@ export async function POST(input: APIEvent) {
|
||||
})
|
||||
})
|
||||
}
|
||||
if (body.type === "customer.subscription.created") {
|
||||
const type = body.data.object.metadata?.type
|
||||
if (type === "lite") {
|
||||
const workspaceID = body.data.object.metadata?.workspaceID
|
||||
const userID = body.data.object.metadata?.userID
|
||||
const userEmail = body.data.object.metadata?.userEmail
|
||||
const coupon = body.data.object.metadata?.coupon
|
||||
const customerID = body.data.object.customer as string
|
||||
const invoiceID = body.data.object.latest_invoice as string
|
||||
const subscriptionID = body.data.object.id as string
|
||||
const paymentMethodID = body.data.object.default_payment_method as string
|
||||
|
||||
if (!workspaceID) throw new Error("Workspace ID not found")
|
||||
if (!userID) throw new Error("User ID not found")
|
||||
if (!customerID) throw new Error("Customer ID not found")
|
||||
if (!invoiceID) throw new Error("Invoice ID not found")
|
||||
if (!subscriptionID) throw new Error("Subscription ID not found")
|
||||
if (!paymentMethodID) throw new Error("Payment method ID not found")
|
||||
|
||||
// get payment method for the payment intent
|
||||
const paymentMethod = await Billing.stripe().paymentMethods.retrieve(paymentMethodID)
|
||||
await Actor.provide("system", { workspaceID }, async () => {
|
||||
// look up current billing
|
||||
const billing = await Billing.get()
|
||||
if (!billing) throw new Error(`Workspace with ID ${workspaceID} not found`)
|
||||
if (billing.customerID && billing.customerID !== customerID) throw new Error("Customer ID mismatch")
|
||||
|
||||
// set customer metadata
|
||||
if (!billing?.customerID) {
|
||||
await Billing.stripe().customers.update(customerID, {
|
||||
metadata: {
|
||||
workspaceID,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
await Database.transaction(async (tx) => {
|
||||
await tx
|
||||
.update(BillingTable)
|
||||
.set({
|
||||
customerID,
|
||||
liteSubscriptionID: subscriptionID,
|
||||
lite: {},
|
||||
paymentMethodID: paymentMethod.id,
|
||||
paymentMethodLast4: paymentMethod.card?.last4 ?? null,
|
||||
paymentMethodType: paymentMethod.type,
|
||||
})
|
||||
.where(eq(BillingTable.workspaceID, workspaceID))
|
||||
|
||||
await tx.insert(LiteTable).values({
|
||||
workspaceID,
|
||||
id: Identifier.create("lite"),
|
||||
userID: userID,
|
||||
})
|
||||
|
||||
if (userEmail) {
|
||||
if (coupon === LiteData.firstMonth50Coupon) {
|
||||
await Billing.redeemCoupon(userEmail, "GO1MONTH50")
|
||||
} else if (coupon === LiteData.firstMonth100Coupon) {
|
||||
await Billing.redeemCoupon(userEmail, "GOFREEMONTH")
|
||||
} else if (coupon === LiteData.threeMonths100Coupon) {
|
||||
await Billing.redeemCoupon(userEmail, "GO3MONTHS100")
|
||||
} else if (coupon === LiteData.sixMonths100Coupon) {
|
||||
await Billing.redeemCoupon(userEmail, "GO6MONTHS100")
|
||||
} else if (coupon === LiteData.twelveMonths100Coupon) {
|
||||
await Billing.redeemCoupon(userEmail, "GO12MONTHS100")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
await Referral.completeFromLiteSubscription({
|
||||
workspaceID,
|
||||
userID,
|
||||
}).catch((error) => {
|
||||
console.error("Referral sync failed", error)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
if (body.type === "customer.subscription.updated" && body.data.object.status === "incomplete_expired") {
|
||||
const subscriptionID = body.data.object.id
|
||||
if (!subscriptionID) throw new Error("Subscription ID not found")
|
||||
@@ -221,6 +150,10 @@ export async function POST(input: APIEvent) {
|
||||
if (!invoiceID) throw new Error("Invoice ID not found")
|
||||
if (!subscriptionID) throw new Error("Subscription ID not found")
|
||||
|
||||
if (body.data.object.billing_reason === "subscription_create" && productID === LiteData.productID()) {
|
||||
await provisionLiteSubscription(subscriptionID)
|
||||
}
|
||||
|
||||
// get coupon id from subscription
|
||||
const invoice = await Billing.stripe().invoices.retrieve(invoiceID, {
|
||||
expand: ["discounts", "payments"],
|
||||
@@ -378,3 +311,92 @@ export async function POST(input: APIEvent) {
|
||||
return Response.json({ message: error.message }, { status: 500 })
|
||||
})
|
||||
}
|
||||
|
||||
async function provisionLiteSubscription(subscriptionID: string) {
|
||||
const stripe = Billing.stripe()
|
||||
const subscription = liteSubscriptionProvisioningData(await stripe.subscriptions.retrieve(subscriptionID))
|
||||
if (!subscription) return
|
||||
|
||||
await Actor.provide("system", { workspaceID: subscription.workspaceID }, async () => {
|
||||
const billing = await Billing.get()
|
||||
if (!billing) throw new Error(`Workspace with ID ${subscription.workspaceID} not found`)
|
||||
if (billing.customerID && billing.customerID !== subscription.customerID) throw new Error("Customer ID mismatch")
|
||||
if (billing.liteSubscriptionID === subscription.subscriptionID) return
|
||||
|
||||
const paymentMethod = subscription.paymentMethodID
|
||||
? await stripe.paymentMethods.retrieve(subscription.paymentMethodID)
|
||||
: undefined
|
||||
|
||||
if (!billing.customerID) {
|
||||
await stripe.customers.update(subscription.customerID, {
|
||||
metadata: {
|
||||
workspaceID: subscription.workspaceID,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const provisioned = await Database.transaction(async (tx) => {
|
||||
const current = await tx
|
||||
.select({
|
||||
customerID: BillingTable.customerID,
|
||||
liteSubscriptionID: BillingTable.liteSubscriptionID,
|
||||
})
|
||||
.from(BillingTable)
|
||||
.where(eq(BillingTable.workspaceID, subscription.workspaceID))
|
||||
.for("update")
|
||||
.then((rows) => rows[0])
|
||||
if (!current) throw new Error(`Workspace with ID ${subscription.workspaceID} not found`)
|
||||
if (current.customerID && current.customerID !== subscription.customerID) throw new Error("Customer ID mismatch")
|
||||
if (current.liteSubscriptionID === subscription.subscriptionID) return false
|
||||
if (current.liteSubscriptionID) throw new Error("Workspace already has another Go subscription")
|
||||
|
||||
await tx
|
||||
.update(BillingTable)
|
||||
.set({
|
||||
customerID: subscription.customerID,
|
||||
liteSubscriptionID: subscription.subscriptionID,
|
||||
lite: {},
|
||||
...(paymentMethod
|
||||
? {
|
||||
paymentMethodID: paymentMethod.id,
|
||||
paymentMethodLast4: paymentMethod.card?.last4 ?? null,
|
||||
paymentMethodType: paymentMethod.type,
|
||||
}
|
||||
: {}),
|
||||
})
|
||||
.where(eq(BillingTable.workspaceID, subscription.workspaceID))
|
||||
|
||||
await tx
|
||||
.insert(LiteTable)
|
||||
.ignore()
|
||||
.values({
|
||||
workspaceID: subscription.workspaceID,
|
||||
id: Identifier.create("lite"),
|
||||
userID: subscription.userID,
|
||||
})
|
||||
|
||||
if (subscription.userEmail) {
|
||||
if (subscription.coupon === LiteData.firstMonth50Coupon) {
|
||||
await Billing.redeemCoupon(subscription.userEmail, "GO1MONTH50")
|
||||
} else if (subscription.coupon === LiteData.firstMonth100Coupon) {
|
||||
await Billing.redeemCoupon(subscription.userEmail, "GOFREEMONTH")
|
||||
} else if (subscription.coupon === LiteData.threeMonths100Coupon) {
|
||||
await Billing.redeemCoupon(subscription.userEmail, "GO3MONTHS100")
|
||||
} else if (subscription.coupon === LiteData.sixMonths100Coupon) {
|
||||
await Billing.redeemCoupon(subscription.userEmail, "GO6MONTHS100")
|
||||
} else if (subscription.coupon === LiteData.twelveMonths100Coupon) {
|
||||
await Billing.redeemCoupon(subscription.userEmail, "GO12MONTHS100")
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
if (!provisioned) return
|
||||
|
||||
await Referral.completeFromLiteSubscription({
|
||||
workspaceID: subscription.workspaceID,
|
||||
userID: subscription.userID,
|
||||
}).catch((error) => {
|
||||
console.error("Referral sync failed", error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import { expect, test } from "bun:test"
|
||||
import {
|
||||
liteCheckoutSubscriptionToProvision,
|
||||
liteSubscriptionProvisioningData,
|
||||
} from "../src/routes/stripe/lite-subscription"
|
||||
|
||||
test("waits for an unpaid Checkout Session's asynchronous payment", () => {
|
||||
const session = {
|
||||
mode: "subscription" as const,
|
||||
payment_status: "unpaid" as const,
|
||||
subscription: "sub_go",
|
||||
}
|
||||
|
||||
expect(liteCheckoutSubscriptionToProvision("checkout.session.completed", session)).toBeUndefined()
|
||||
expect(liteCheckoutSubscriptionToProvision("checkout.session.async_payment_succeeded", session)).toBe("sub_go")
|
||||
})
|
||||
|
||||
test("provisions a paid Checkout Session immediately", () => {
|
||||
expect(
|
||||
liteCheckoutSubscriptionToProvision("checkout.session.completed", {
|
||||
mode: "subscription",
|
||||
payment_status: "paid",
|
||||
subscription: "sub_go",
|
||||
}),
|
||||
).toBe("sub_go")
|
||||
})
|
||||
|
||||
test("provisions an active Go subscription without a default payment method", () => {
|
||||
expect(
|
||||
liteSubscriptionProvisioningData({
|
||||
id: "sub_go",
|
||||
status: "active",
|
||||
customer: "cus_go",
|
||||
default_payment_method: null,
|
||||
metadata: {
|
||||
type: "lite",
|
||||
workspaceID: "wrk_go",
|
||||
userID: "usr_go",
|
||||
},
|
||||
}),
|
||||
).toEqual({
|
||||
subscriptionID: "sub_go",
|
||||
customerID: "cus_go",
|
||||
workspaceID: "wrk_go",
|
||||
userID: "usr_go",
|
||||
userEmail: undefined,
|
||||
coupon: undefined,
|
||||
paymentMethodID: undefined,
|
||||
})
|
||||
})
|
||||
|
||||
test("waits for an asynchronous Go subscription to become active", () => {
|
||||
expect(
|
||||
liteSubscriptionProvisioningData({
|
||||
id: "sub_go",
|
||||
status: "incomplete",
|
||||
customer: "cus_go",
|
||||
default_payment_method: null,
|
||||
metadata: {
|
||||
type: "lite",
|
||||
workspaceID: "wrk_go",
|
||||
userID: "usr_go",
|
||||
},
|
||||
}),
|
||||
).toBeUndefined()
|
||||
})
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/console-core",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-function",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-mail",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-support",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"name": "@opencode-ai/core",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -15,11 +15,6 @@ import { httpClient } from "./effect/app-node-platform"
|
||||
export const CatalogModelStatus = Schema.Literals(["alpha", "beta", "deprecated"])
|
||||
export type CatalogModelStatus = typeof CatalogModelStatus.Type
|
||||
|
||||
const InterleavedField = Schema.Union([
|
||||
Schema.Literals(["reasoning", "reasoning_content", "reasoning_text"]),
|
||||
Schema.String,
|
||||
])
|
||||
|
||||
const USER_AGENT = `opencode/${InstallationChannel}/${InstallationVersion}/${Flag.OPENCODE_CLIENT}`
|
||||
|
||||
const CostTier = Schema.Struct({
|
||||
@@ -76,10 +71,9 @@ export const Model = Schema.Struct({
|
||||
reasoning_options: Schema.optional(Schema.Array(ReasoningOption)),
|
||||
interleaved: Schema.optional(
|
||||
Schema.Union([
|
||||
Schema.Boolean,
|
||||
InterleavedField,
|
||||
Schema.Literal(true),
|
||||
Schema.Struct({
|
||||
field: InterleavedField,
|
||||
field: Schema.Literals(["reasoning", "reasoning_content", "reasoning_details"]),
|
||||
}),
|
||||
]),
|
||||
),
|
||||
@@ -157,10 +151,10 @@ const layer = Layer.effect(
|
||||
),
|
||||
)
|
||||
|
||||
const source = Flag.OPENCODE_MODELS_URL || "https://models.opencode.ai"
|
||||
const source = Flag.OPENCODE_MODELS_URL || "https://models.dev"
|
||||
const filepath = path.join(
|
||||
Global.Path.cache,
|
||||
source === "https://models.opencode.ai" ? "models.json" : `models-${Hash.fast(source)}.json`,
|
||||
source === "https://models.dev" ? "models.json" : `models-${Hash.fast(source)}.json`,
|
||||
)
|
||||
const ttl = Duration.minutes(5)
|
||||
const lockKey = `models-dev:${filepath}`
|
||||
|
||||
@@ -5,11 +5,6 @@ import { PositiveInt } from "../../schema"
|
||||
|
||||
export const ModelStatus = Schema.Literals(["alpha", "beta", "deprecated", "active"])
|
||||
|
||||
const InterleavedField = Schema.Union([
|
||||
Schema.Literals(["reasoning", "reasoning_content", "reasoning_text"]),
|
||||
Schema.String,
|
||||
])
|
||||
|
||||
export const Model = Schema.Struct({
|
||||
id: Schema.optional(Schema.String),
|
||||
name: Schema.optional(Schema.String),
|
||||
@@ -21,10 +16,9 @@ export const Model = Schema.Struct({
|
||||
tool_call: Schema.optional(Schema.Boolean),
|
||||
interleaved: Schema.optional(
|
||||
Schema.Union([
|
||||
Schema.Boolean,
|
||||
InterleavedField,
|
||||
Schema.Literal(true),
|
||||
Schema.Struct({
|
||||
field: InterleavedField,
|
||||
field: Schema.Literals(["reasoning", "reasoning_content", "reasoning_details"]),
|
||||
}),
|
||||
]),
|
||||
),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@opencode-ai/desktop",
|
||||
"private": true,
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"homepage": "https://opencode.ai",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"name": "@opencode-ai/effect-drizzle-sqlite",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"name": "@opencode-ai/effect-sqlite-node",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/enterprise",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/function",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"name": "@opencode-ai/http-recorder",
|
||||
"description": "Record and replay Effect HTTP client traffic with deterministic cassettes",
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"name": "@opencode-ai/llm",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as fs from "node:fs/promises"
|
||||
import * as path from "node:path"
|
||||
|
||||
const RECORDINGS_DIR = path.resolve(import.meta.dir, "..", "test", "fixtures", "recordings")
|
||||
const MODELS_DEV_URL = "https://models.opencode.ai/api.json"
|
||||
const MODELS_DEV_URL = "https://models.dev/api.json"
|
||||
|
||||
type JsonRecord = Record<string, unknown>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"name": "opencode",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -976,15 +976,10 @@ const ProviderModalities = Schema.Struct({
|
||||
pdf: Schema.Boolean,
|
||||
})
|
||||
|
||||
const ProviderInterleavedField = Schema.Union([
|
||||
Schema.Literals(["reasoning", "reasoning_content", "reasoning_text"]),
|
||||
Schema.String,
|
||||
])
|
||||
|
||||
const ProviderInterleaved = Schema.Union([
|
||||
Schema.Boolean,
|
||||
Schema.Struct({
|
||||
field: ProviderInterleavedField,
|
||||
field: Schema.Literals(["reasoning", "reasoning_content", "reasoning_details"]),
|
||||
}),
|
||||
])
|
||||
|
||||
@@ -1248,7 +1243,7 @@ function fromModelsDevModel(provider: ModelsDev.Provider, model: ModelsDev.Model
|
||||
video: model.modalities?.output?.includes("video") ?? false,
|
||||
pdf: model.modalities?.output?.includes("pdf") ?? false,
|
||||
},
|
||||
interleaved: typeof model.interleaved === "string" ? { field: model.interleaved } : (model.interleaved ?? false),
|
||||
interleaved: model.interleaved ?? false,
|
||||
},
|
||||
release_date: model.release_date ?? "",
|
||||
variants: {},
|
||||
@@ -1480,7 +1475,7 @@ const layer = Layer.effect(
|
||||
pdf: model.modalities?.output?.includes("pdf") ?? existingModel?.capabilities.output.pdf ?? false,
|
||||
},
|
||||
interleaved:
|
||||
(typeof model.interleaved === "string" ? { field: model.interleaved } : model.interleaved) ??
|
||||
model.interleaved ??
|
||||
existingModel?.capabilities.interleaved ??
|
||||
(!existingModel && apiNpm === "@ai-sdk/openai-compatible" && apiID.includes("deepseek")
|
||||
? { field: "reasoning_content" }
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
import { expect, test } from "bun:test"
|
||||
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"
|
||||
|
||||
test("does not reconnect an SSE stream after a JSON-RPC error response", async () => {
|
||||
let requests = 0
|
||||
const transport = new StreamableHTTPClientTransport(new URL("http://mcp.invalid"), {
|
||||
fetch: async () => {
|
||||
requests += 1
|
||||
return new Response(
|
||||
new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue(new TextEncoder().encode("id: prime\nretry: 1\ndata:\n\n"))
|
||||
controller.enqueue(
|
||||
new TextEncoder().encode(
|
||||
'id: error\ndata: {"jsonrpc":"2.0","error":{"code":-32601,"message":"Method not found"},"id":1}\n\n',
|
||||
),
|
||||
)
|
||||
controller.close()
|
||||
},
|
||||
}),
|
||||
{ status: 200, headers: { "content-type": "text/event-stream" } },
|
||||
)
|
||||
},
|
||||
reconnectionOptions: {
|
||||
initialReconnectionDelay: 1,
|
||||
maxReconnectionDelay: 1,
|
||||
reconnectionDelayGrowFactor: 1,
|
||||
maxRetries: 2,
|
||||
},
|
||||
})
|
||||
|
||||
await transport.start()
|
||||
await transport.send({ jsonrpc: "2.0", method: "resources/list", id: 1 })
|
||||
await Bun.sleep(25)
|
||||
await transport.close()
|
||||
|
||||
expect(requests).toBe(1)
|
||||
})
|
||||
@@ -252,8 +252,6 @@ it.instance(
|
||||
const provider = providers[ProviderV2.ID.make("custom-provider")]
|
||||
expect(provider.models["deepseek-r1"].capabilities.interleaved).toEqual({ field: "reasoning_content" })
|
||||
expect(provider.models["deepseek-details"].capabilities.interleaved).toEqual({ field: "reasoning_details" })
|
||||
expect(provider.models["deepseek-text"].capabilities.interleaved).toEqual({ field: "reasoning_text" })
|
||||
expect(provider.models["custom-reasoning"].capabilities.interleaved).toEqual({ field: "vendor_reasoning" })
|
||||
expect(provider.models["custom-model"].capabilities.interleaved).toBe(false)
|
||||
expect(
|
||||
providers[ProviderV2.ID.make("custom-anthropic-provider")].models["deepseek-r1"].capabilities.interleaved,
|
||||
@@ -269,8 +267,6 @@ it.instance(
|
||||
models: {
|
||||
"deepseek-r1": { name: "DeepSeek R1" },
|
||||
"deepseek-details": { name: "DeepSeek Details", interleaved: { field: "reasoning_details" } },
|
||||
"deepseek-text": { name: "DeepSeek Text", interleaved: "reasoning_text" },
|
||||
"custom-reasoning": { name: "Custom Reasoning", interleaved: { field: "vendor_reasoning" } },
|
||||
"custom-model": { name: "Custom Model" },
|
||||
},
|
||||
options: { apiKey: "custom-key" },
|
||||
@@ -1466,7 +1462,6 @@ test("models.dev normalization fills required response fields", () => {
|
||||
id: "gpt-5.4",
|
||||
name: "GPT-5.4",
|
||||
family: "gpt",
|
||||
interleaved: "reasoning_text",
|
||||
cost: { input: 2.5, output: 15 },
|
||||
limit: { context: 1_050_000, input: 922_000, output: 128_000 },
|
||||
},
|
||||
@@ -1479,7 +1474,6 @@ test("models.dev normalization fills required response fields", () => {
|
||||
expect(model.capabilities.reasoning).toBe(false)
|
||||
expect(model.capabilities.attachment).toBe(false)
|
||||
expect(model.capabilities.toolcall).toBe(true)
|
||||
expect(model.capabilities.interleaved).toEqual({ field: "reasoning_text" })
|
||||
expect(model.release_date).toBe("")
|
||||
})
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/plugin",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/sdk",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1768,13 +1768,9 @@ export type ProviderConfig = {
|
||||
temperature?: boolean
|
||||
tool_call?: boolean
|
||||
interleaved?:
|
||||
| boolean
|
||||
| "reasoning"
|
||||
| "reasoning_content"
|
||||
| "reasoning_text"
|
||||
| string
|
||||
| true
|
||||
| {
|
||||
field: "reasoning" | "reasoning_content" | "reasoning_text" | string
|
||||
field: "reasoning" | "reasoning_content" | "reasoning_details"
|
||||
}
|
||||
cost?: {
|
||||
input: number
|
||||
@@ -2061,7 +2057,7 @@ export type Model = {
|
||||
interleaved:
|
||||
| boolean
|
||||
| {
|
||||
field: "reasoning" | "reasoning_content" | "reasoning_text" | string
|
||||
field: "reasoning" | "reasoning_content" | "reasoning_details"
|
||||
}
|
||||
}
|
||||
cost: {
|
||||
|
||||
@@ -20820,28 +20820,15 @@
|
||||
"interleaved": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"enum": ["reasoning", "reasoning_content", "reasoning_text"]
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
"type": "boolean",
|
||||
"enum": [true]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"field": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"enum": ["reasoning", "reasoning_content", "reasoning_text"]
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
"type": "string",
|
||||
"enum": ["reasoning", "reasoning_content", "reasoning_details"]
|
||||
}
|
||||
},
|
||||
"required": ["field"],
|
||||
@@ -21654,15 +21641,8 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"field": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"enum": ["reasoning", "reasoning_content", "reasoning_text"]
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
"type": "string",
|
||||
"enum": ["reasoning", "reasoning_content", "reasoning_details"]
|
||||
}
|
||||
},
|
||||
"required": ["field"],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/server",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/session-ui",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/slack",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/stats-app",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { query } from "@solidjs/router"
|
||||
|
||||
export const modelCatalogSourceUrl = "https://models.opencode.ai/catalog.json"
|
||||
export const modelCatalogPricingUrl = "https://models.opencode.ai/api.json"
|
||||
export const modelCatalogLabSourceUrl = "https://models.opencode.ai/labs"
|
||||
export const modelCatalogSourceUrl = "https://models.dev/catalog.json"
|
||||
export const modelCatalogPricingUrl = "https://models.dev/api.json"
|
||||
export const modelCatalogLabSourceUrl = "https://models.dev/labs"
|
||||
|
||||
export type ModelCatalogCost = {
|
||||
input: number
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/stats-core",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/stats-server",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/tui",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/ui",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -45,7 +45,7 @@ function providerIconsPlugin() {
|
||||
}
|
||||
|
||||
async function fetchProviderIcons() {
|
||||
const url = process.env.OPENCODE_MODELS_URL || "https://models.opencode.ai"
|
||||
const url = process.env.OPENCODE_MODELS_URL || "https://models.dev"
|
||||
const providers = await fetch(`${url}/api.json`)
|
||||
.then((res) => res.json())
|
||||
.then((json) => Object.keys(json))
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@opencode-ai/web",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev",
|
||||
|
||||
@@ -1505,30 +1505,6 @@ To use Kimi K2 from Moonshot AI:
|
||||
|
||||
---
|
||||
|
||||
### Modal
|
||||
|
||||
1. Create a [shared Endpoint](https://modal.com/endpoints) for the model you want to use.
|
||||
|
||||
2. Create a [proxy token](https://modal.com/docs/guide/endpoints#proxy-tokens), then join its ID and secret with a period:
|
||||
|
||||
```txt
|
||||
wk-<id>.ws-<secret>
|
||||
```
|
||||
|
||||
3. Run the `/connect` command, search for **Modal**, and enter the combined proxy token.
|
||||
|
||||
```txt
|
||||
/connect
|
||||
```
|
||||
|
||||
4. Run the `/models` command to select one of the endpoints in your Modal workspace.
|
||||
|
||||
```txt
|
||||
/models
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### NVIDIA
|
||||
|
||||
NVIDIA provides access to Nemotron models and many other open models through [build.nvidia.com](https://build.nvidia.com) for free.
|
||||
|
||||
@@ -141,15 +141,6 @@ diff --git a/dist/cjs/client/streamableHttp.js b/dist/cjs/client/streamableHttp.
|
||||
index a29a7d3a0f14d9cd800ef5b296485237350c666f..c362ae5fe6c62c8c8eae7e2e61de1eedff5443c9 100644
|
||||
--- a/dist/cjs/client/streamableHttp.js
|
||||
+++ b/dist/cjs/client/streamableHttp.js
|
||||
@@ -204,7 +204,7 @@ class StreamableHTTPClientTransport {
|
||||
if (!event.event || event.event === 'message') {
|
||||
try {
|
||||
const message = types_js_1.JSONRPCMessageSchema.parse(JSON.parse(event.data));
|
||||
- if ((0, types_js_1.isJSONRPCResultResponse)(message)) {
|
||||
+ if ((0, types_js_1.isJSONRPCResultResponse)(message) || (0, types_js_1.isJSONRPCErrorResponse)(message)) {
|
||||
// Mark that we received a response - no need to reconnect for this request
|
||||
receivedResponse = true;
|
||||
if (replayMessageId !== undefined) {
|
||||
@@ -290,7 +290,38 @@ class StreamableHTTPClientTransport {
|
||||
this.onclose?.();
|
||||
}
|
||||
@@ -527,19 +518,10 @@ index 624172aa24ae255a67c083f9c19053343e4a0581..ac75b14545fda44aff7ff4d97cc5da88
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createFetchWithInit, normalizeHeaders } from '../shared/transport.js';
|
||||
-import { isInitializedNotification, isJSONRPCRequest, isJSONRPCResultResponse, JSONRPCMessageSchema } from '../types.js';
|
||||
+import { isInitializedNotification, isInitializeRequest, isJSONRPCErrorResponse, isJSONRPCRequest, isJSONRPCResultResponse, JSONRPCMessageSchema } from '../types.js';
|
||||
+import { isInitializedNotification, isInitializeRequest, isJSONRPCRequest, isJSONRPCResultResponse, JSONRPCMessageSchema } from '../types.js';
|
||||
import { auth, extractWWWAuthenticateParams, UnauthorizedError } from './auth.js';
|
||||
import { EventSourceParserStream } from 'eventsource-parser/stream';
|
||||
// Default reconnection options for StreamableHTTP connections
|
||||
@@ -200,7 +200,7 @@ export class StreamableHTTPClientTransport {
|
||||
if (!event.event || event.event === 'message') {
|
||||
try {
|
||||
const message = JSONRPCMessageSchema.parse(JSON.parse(event.data));
|
||||
- if (isJSONRPCResultResponse(message)) {
|
||||
+ if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {
|
||||
// Mark that we received a response - no need to reconnect for this request
|
||||
receivedResponse = true;
|
||||
if (replayMessageId !== undefined) {
|
||||
@@ -286,7 +286,38 @@ export class StreamableHTTPClientTransport {
|
||||
this.onclose?.();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "opencode",
|
||||
"displayName": "opencode",
|
||||
"description": "opencode for VS Code",
|
||||
"version": "1.18.10",
|
||||
"version": "1.18.9",
|
||||
"publisher": "sst-dev",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
Reference in New Issue
Block a user