diff options
| author | Dax Raad <[email protected]> | 2025-11-06 13:03:02 -0500 |
|---|---|---|
| committer | Dax Raad <[email protected]> | 2025-11-06 13:03:12 -0500 |
| commit | 1ea3a8eb9beeb7d510fd29164ea741acec1ee04d (patch) | |
| tree | 22c35a0003c6c2cfb998431f8e5180879cbab9d3 | |
| parent | 8729edc5e059a9a29346044b016a6e05d9aca835 (diff) | |
| download | opencode-1ea3a8eb9beeb7d510fd29164ea741acec1ee04d.tar.gz opencode-1ea3a8eb9beeb7d510fd29164ea741acec1ee04d.zip | |
big format
183 files changed, 2691 insertions, 2559 deletions
@@ -21,27 +21,27 @@ json { - "recipient_name": "multi_tool_use.parallel", - "parameters": { - "tool_uses": [ - { - "recipient_name": "functions.read", - "parameters": { - "filePath": "path/to/file.tsx" - } - }, - { - "recipient_name": "functions.read", - "parameters": { - "filePath": "path/to/file.ts" - } - }, - { - "recipient_name": "functions.read", - "parameters": { - "filePath": "path/to/file.md" - } - } - ] - } +"recipient_name": "multi_tool_use.parallel", +"parameters": { +"tool_uses": [ +{ +"recipient_name": "functions.read", +"parameters": { +"filePath": "path/to/file.tsx" +} +}, +{ +"recipient_name": "functions.read", +"parameters": { +"filePath": "path/to/file.ts" +} +}, +{ +"recipient_name": "functions.read", +"parameters": { +"filePath": "path/to/file.md" +} +} +] +} } diff --git a/github/sst-env.d.ts b/github/sst-env.d.ts index f742a1200..6b69016e7 100644 --- a/github/sst-env.d.ts +++ b/github/sst-env.d.ts @@ -6,4 +6,4 @@ /// <reference path="../sst-env.d.ts" /> import "sst" -export {}
\ No newline at end of file +export {} diff --git a/logs/.2c5480b3b2480f80fa29b850af461dce619c0b2f-audit.json b/logs/.2c5480b3b2480f80fa29b850af461dce619c0b2f-audit.json index 7c57ef350..41cb01a2b 100644 --- a/logs/.2c5480b3b2480f80fa29b850af461dce619c0b2f-audit.json +++ b/logs/.2c5480b3b2480f80fa29b850af461dce619c0b2f-audit.json @@ -1,15 +1,15 @@ { - "keep": { - "days": true, - "amount": 14 - }, - "auditLog": "/home/thdxr/dev/projects/sst/opencode/logs/.2c5480b3b2480f80fa29b850af461dce619c0b2f-audit.json", - "files": [ - { - "date": 1759827172859, - "name": "/home/thdxr/dev/projects/sst/opencode/logs/mcp-puppeteer-2025-10-07.log", - "hash": "a3d98b26edd793411b968a0d24cfeee8332138e282023c3b83ec169d55c67f16" - } - ], - "hashType": "sha256" -}
\ No newline at end of file + "keep": { + "days": true, + "amount": 14 + }, + "auditLog": "/home/thdxr/dev/projects/sst/opencode/logs/.2c5480b3b2480f80fa29b850af461dce619c0b2f-audit.json", + "files": [ + { + "date": 1759827172859, + "name": "/home/thdxr/dev/projects/sst/opencode/logs/mcp-puppeteer-2025-10-07.log", + "hash": "a3d98b26edd793411b968a0d24cfeee8332138e282023c3b83ec169d55c67f16" + } + ], + "hashType": "sha256" +} diff --git a/packages/console/app/src/component/dropdown.css b/packages/console/app/src/component/dropdown.css index 982367c6b..242940e6a 100644 --- a/packages/console/app/src/component/dropdown.css +++ b/packages/console/app/src/component/dropdown.css @@ -77,4 +77,4 @@ background-color: var(--color-accent-alpha); } } -}
\ No newline at end of file +} diff --git a/packages/console/app/src/component/faq.tsx b/packages/console/app/src/component/faq.tsx index 753a0dce4..47dca9513 100644 --- a/packages/console/app/src/component/faq.tsx +++ b/packages/console/app/src/component/faq.tsx @@ -13,7 +13,10 @@ export function Faq(props: ParentProps & { question: string }) { fill="currentColor" xmlns="http://www.w3.org/2000/svg" > - <path d="M12.5 11.5H19V12.5H12.5V19H11.5V12.5H5V11.5H11.5V5H12.5V11.5Z" fill="currentColor" /> + <path + d="M12.5 11.5H19V12.5H12.5V19H11.5V12.5H5V11.5H11.5V5H12.5V11.5Z" + fill="currentColor" + /> </svg> <svg data-slot="faq-icon-minus" diff --git a/packages/console/app/src/component/icon.tsx b/packages/console/app/src/component/icon.tsx index 0395cad52..d0bce947b 100644 --- a/packages/console/app/src/component/icon.tsx +++ b/packages/console/app/src/component/icon.tsx @@ -9,10 +9,23 @@ export function IconLogo(props: JSX.SvgSVGAttributes<SVGSVGElement>) { <path d="M13.7124 9.14333V4.5719H18.2838V9.14333H13.7124Z" fill="currentColor" /> <path d="M13.7124 13.7136V9.14221H18.2838V13.7136H13.7124Z" fill="currentColor" /> <path d="M0 18.2857V13.7142H4.57143V18.2857H0Z" fill="currentColor" fill-opacity="0.2" /> - <rect width="4.57143" height="4.57143" transform="translate(4.57178 13.7141)" fill="currentColor" /> - <path d="M4.57178 18.2855V13.7141H9.14321V18.2855H4.57178Z" fill="currentColor" fill-opacity="0.2" /> + <rect + width="4.57143" + height="4.57143" + transform="translate(4.57178 13.7141)" + fill="currentColor" + /> + <path + d="M4.57178 18.2855V13.7141H9.14321V18.2855H4.57178Z" + fill="currentColor" + fill-opacity="0.2" + /> <path d="M9.1438 18.2855V13.7141H13.7152V18.2855H9.1438Z" fill="currentColor" /> - <path d="M13.7156 18.2855V13.7141H18.287V18.2855H13.7156Z" fill="currentColor" fill-opacity="0.2" /> + <path + d="M13.7156 18.2855V13.7141H18.287V18.2855H13.7156Z" + fill="currentColor" + fill-opacity="0.2" + /> <rect width="4.57143" height="4.57143" transform="translate(0 18.2859)" fill="currentColor" /> <path d="M0 22.8572V18.2858H4.57143V22.8572H0Z" fill="currentColor" fill-opacity="0.2" /> <rect @@ -23,8 +36,16 @@ export function IconLogo(props: JSX.SvgSVGAttributes<SVGSVGElement>) { fill-opacity="0.2" /> <path d="M4.57178 22.8573V18.2859H9.14321V22.8573H4.57178Z" fill="currentColor" /> - <path d="M9.1438 22.8573V18.2859H13.7152V22.8573H9.1438Z" fill="currentColor" fill-opacity="0.2" /> - <path d="M13.7156 22.8573V18.2859H18.287V22.8573H13.7156Z" fill="currentColor" fill-opacity="0.2" /> + <path + d="M9.1438 22.8573V18.2859H13.7152V22.8573H9.1438Z" + fill="currentColor" + fill-opacity="0.2" + /> + <path + d="M13.7156 22.8573V18.2859H18.287V22.8573H13.7156Z" + fill="currentColor" + fill-opacity="0.2" + /> <path d="M0 27.4292V22.8578H4.57143V27.4292H0Z" fill="currentColor" /> <path d="M4.57178 27.4292V22.8578H9.14321V27.4292H4.57178Z" fill="currentColor" /> <path d="M9.1438 27.4276V22.8562H13.7152V27.4276H9.1438Z" fill="currentColor" /> @@ -40,9 +61,21 @@ export function IconLogo(props: JSX.SvgSVGAttributes<SVGSVGElement>) { <path d="M32.001 18.2855V13.7141H36.5724V18.2855H32.001Z" fill="currentColor" /> <path d="M36.5698 18.2855V13.7141H41.1413V18.2855H36.5698Z" fill="currentColor" /> <path d="M22.8572 22.8573V18.2859H27.4286V22.8573H22.8572Z" fill="currentColor" /> - <path d="M27.4292 22.8573V18.2859H32.0006V22.8573H27.4292Z" fill="currentColor" fill-opacity="0.2" /> - <path d="M32.001 22.8573V18.2859H36.5724V22.8573H32.001Z" fill="currentColor" fill-opacity="0.2" /> - <path d="M36.5698 22.8573V18.2859H41.1413V22.8573H36.5698Z" fill="currentColor" fill-opacity="0.2" /> + <path + d="M27.4292 22.8573V18.2859H32.0006V22.8573H27.4292Z" + fill="currentColor" + fill-opacity="0.2" + /> + <path + d="M32.001 22.8573V18.2859H36.5724V22.8573H32.001Z" + fill="currentColor" + fill-opacity="0.2" + /> + <path + d="M36.5698 22.8573V18.2859H41.1413V22.8573H36.5698Z" + fill="currentColor" + fill-opacity="0.2" + /> <path d="M22.8572 27.4292V22.8578H27.4286V27.4292H22.8572Z" fill="currentColor" /> <path d="M27.4292 27.4276V22.8562H32.0006V27.4276H27.4292Z" fill="currentColor" /> <path d="M32.001 27.4276V22.8562H36.5724V27.4276H32.001Z" fill="currentColor" /> @@ -53,16 +86,40 @@ export function IconLogo(props: JSX.SvgSVGAttributes<SVGSVGElement>) { <path d="M45.7144 13.7136V9.14221H50.2858V13.7136H45.7144Z" fill="currentColor" /> <path d="M59.4299 13.7152V9.1438H64.0014V13.7152H59.4299Z" fill="currentColor" /> <path d="M45.7144 18.2855V13.7141H50.2858V18.2855H45.7144Z" fill="currentColor" /> - <path d="M50.2861 18.2857V13.7142H54.8576V18.2857H50.2861Z" fill="currentColor" fill-opacity="0.2" /> - <path d="M54.8579 18.2855V13.7141H59.4293V18.2855H54.8579Z" fill="currentColor" fill-opacity="0.2" /> + <path + d="M50.2861 18.2857V13.7142H54.8576V18.2857H50.2861Z" + fill="currentColor" + fill-opacity="0.2" + /> + <path + d="M54.8579 18.2855V13.7141H59.4293V18.2855H54.8579Z" + fill="currentColor" + fill-opacity="0.2" + /> <path d="M59.4299 18.2855V13.7141H64.0014V18.2855H59.4299Z" fill="currentColor" /> <path d="M45.7144 22.8573V18.2859H50.2858V22.8573H45.7144Z" fill="currentColor" /> - <path d="M50.2861 22.8572V18.2858H54.8576V22.8572H50.2861Z" fill="currentColor" fill-opacity="0.2" /> - <path d="M54.8579 22.8573V18.2859H59.4293V22.8573H54.8579Z" fill="currentColor" fill-opacity="0.2" /> + <path + d="M50.2861 22.8572V18.2858H54.8576V22.8572H50.2861Z" + fill="currentColor" + fill-opacity="0.2" + /> + <path + d="M54.8579 22.8573V18.2859H59.4293V22.8573H54.8579Z" + fill="currentColor" + fill-opacity="0.2" + /> <path d="M59.4299 22.8573V18.2859H64.0014V22.8573H59.4299Z" fill="currentColor" /> <path d="M45.7144 27.4292V22.8578H50.2858V27.4292H45.7144Z" fill="currentColor" /> - <path d="M50.2861 27.4286V22.8572H54.8576V27.4286H50.2861Z" fill="currentColor" fill-opacity="0.2" /> - <path d="M54.8579 27.4285V22.8571H59.4293V27.4285H54.8579Z" fill="currentColor" fill-opacity="0.2" /> + <path + d="M50.2861 27.4286V22.8572H54.8576V27.4286H50.2861Z" + fill="currentColor" + fill-opacity="0.2" + /> + <path + d="M54.8579 27.4285V22.8571H59.4293V27.4285H54.8579Z" + fill="currentColor" + fill-opacity="0.2" + /> <path d="M59.4299 27.4292V22.8578H64.0014V27.4292H59.4299Z" fill="currentColor" /> </svg> ) @@ -70,7 +127,14 @@ export function IconLogo(props: JSX.SvgSVGAttributes<SVGSVGElement>) { export function IconCopy(props: JSX.SvgSVGAttributes<SVGSVGElement>) { return ( - <svg {...props} width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> + <svg + {...props} + width="24" + height="24" + viewBox="0 0 24 24" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > <path d="M8.75 8.75V2.75H21.25V15.25H15.25M15.25 8.75H2.75V21.25H15.25V8.75Z" stroke="currentColor" @@ -83,8 +147,20 @@ export function IconCopy(props: JSX.SvgSVGAttributes<SVGSVGElement>) { export function IconCheck(props: JSX.SvgSVGAttributes<SVGSVGElement>) { return ( - <svg {...props} width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M2.75 15.0938L9 20.25L21.25 3.75" stroke="#03B000" stroke-width="2" stroke-linecap="square" /> + <svg + {...props} + width="24" + height="24" + viewBox="0 0 24 24" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M2.75 15.0938L9 20.25L21.25 3.75" + stroke="#03B000" + stroke-width="2" + stroke-linecap="square" + /> </svg> ) } @@ -113,7 +189,14 @@ export function IconStripe(props: JSX.SvgSVGAttributes<SVGSVGElement>) { export function IconChevron(props: JSX.SvgSVGAttributes<SVGSVGElement>) { return ( - <svg {...props} width="8" height="6" viewBox="0 0 8 6" fill="none" xmlns="http://www.w3.org/2000/svg"> + <svg + {...props} + width="8" + height="6" + viewBox="0 0 8 6" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > <path fill="currentColor" d="M4.00024 5.04041L7.37401 1.66663L6.66691 0.959525L4.00024 3.62619L1.33357 0.959525L0.626465 1.66663L4.00024 5.04041Z" @@ -124,7 +207,14 @@ export function IconChevron(props: JSX.SvgSVGAttributes<SVGSVGElement>) { export function IconWorkspaceLogo(props: JSX.SvgSVGAttributes<SVGSVGElement>) { return ( - <svg {...props} width="24" height="30" viewBox="0 0 24 30" fill="none" xmlns="http://www.w3.org/2000/svg"> + <svg + {...props} + width="24" + height="30" + viewBox="0 0 24 30" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > <path d="M18 6H6V24H18V6ZM24 30H0V0H24V30Z" fill="currentColor" /> </svg> ) @@ -144,7 +234,10 @@ export function IconOpenAI(props: JSX.SvgSVGAttributes<SVGSVGElement>) { export function IconAnthropic(props: JSX.SvgSVGAttributes<SVGSVGElement>) { return ( <svg {...props} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path fill="currentColor" d="M13.7891 3.93188L20.2223 20.068H23.7502L17.317 3.93188H13.7891Z" /> + <path + fill="currentColor" + d="M13.7891 3.93188L20.2223 20.068H23.7502L17.317 3.93188H13.7891Z" + /> <path fill="currentColor" d="M6.32538 13.6827L8.52662 8.01201L10.7279 13.6827H6.32538ZM6.68225 3.93188L0.25 20.068H3.84652L5.16202 16.6794H11.8914L13.2067 20.068H16.8033L10.371 3.93188H6.68225Z" diff --git a/packages/console/app/src/component/modal.css b/packages/console/app/src/component/modal.css index 23b6831c9..1f47f395d 100644 --- a/packages/console/app/src/component/modal.css +++ b/packages/console/app/src/component/modal.css @@ -63,4 +63,4 @@ font-weight: 600; color: var(--color-text); } -}
\ No newline at end of file +} diff --git a/packages/console/app/src/routes/auth/authorize.ts b/packages/console/app/src/routes/auth/authorize.ts index 166466ef8..293e9ede7 100644 --- a/packages/console/app/src/routes/auth/authorize.ts +++ b/packages/console/app/src/routes/auth/authorize.ts @@ -2,6 +2,9 @@ import type { APIEvent } from "@solidjs/start/server" import { AuthClient } from "~/context/auth" export async function GET(input: APIEvent) { - const result = await AuthClient.authorize(new URL("./callback", input.request.url).toString(), "code") + const result = await AuthClient.authorize( + new URL("./callback", input.request.url).toString(), + "code", + ) return Response.redirect(result.url, 302) } diff --git a/packages/console/app/src/routes/brand/index.css b/packages/console/app/src/routes/brand/index.css index 5a445f298..058d150b6 100644 --- a/packages/console/app/src/routes/brand/index.css +++ b/packages/console/app/src/routes/brand/index.css @@ -299,7 +299,6 @@ transition: all 0.2s ease; text-decoration: none; - &:hover:not(:disabled) { background: var(--color-background-strong-hover); } @@ -385,23 +384,21 @@ 0 1px 2px -1px rgba(19, 16, 16, 0.12); @media (max-width: 40rem) { - box-shadow: - 0 0 0 1px rgba(19, 16, 16, 0.16) + box-shadow: 0 0 0 1px rgba(19, 16, 16, 0.16); } - &:hover { background: var(--color-background); } &:active { transform: scale(0.98); - box-shadow: 0 0 0 1px rgba(19, 16, 16, 0.08), 0 6px 8px -8px rgba(19, 16, 16, 0.50); + box-shadow: + 0 0 0 1px rgba(19, 16, 16, 0.08), + 0 6px 8px -8px rgba(19, 16, 16, 0.5); } } - - @media (max-width: 60rem) { padding: 2rem 1.5rem; } diff --git a/packages/console/app/src/routes/user-menu.css b/packages/console/app/src/routes/user-menu.css index 15700579a..21008e98d 100644 --- a/packages/console/app/src/routes/user-menu.css +++ b/packages/console/app/src/routes/user-menu.css @@ -14,4 +14,4 @@ color: var(--color-danger); } } -}
\ No newline at end of file +} diff --git a/packages/console/app/src/routes/workspace-picker.css b/packages/console/app/src/routes/workspace-picker.css index ab7f5be66..dd0aafaf5 100644 --- a/packages/console/app/src/routes/workspace-picker.css +++ b/packages/console/app/src/routes/workspace-picker.css @@ -71,4 +71,4 @@ color: var(--color-text-muted); } } -}
\ No newline at end of file +} diff --git a/packages/console/app/src/routes/workspace-picker.tsx b/packages/console/app/src/routes/workspace-picker.tsx index fa8cf1d21..4e218227c 100644 --- a/packages/console/app/src/routes/workspace-picker.tsx +++ b/packages/console/app/src/routes/workspace-picker.tsx @@ -85,7 +85,10 @@ export function WorkspacePicker() { <Dropdown trigger={currentWorkspace()} align="left"> <For each={workspaces()}> {(workspace) => ( - <DropdownItem selected={workspace.id === params.id} onClick={() => handleSelectWorkspace(workspace.id)}> + <DropdownItem + selected={workspace.id === params.id} + onClick={() => handleSelectWorkspace(workspace.id)} + > {workspace.name || workspace.slug} </DropdownItem> )} @@ -95,7 +98,11 @@ export function WorkspacePicker() { </button> </Dropdown> - <Modal open={store.showForm} onClose={() => setStore("showForm", false)} title="Create New Workspace"> + <Modal + open={store.showForm} + onClose={() => setStore("showForm", false)} + title="Create New Workspace" + > <form data-slot="create-form" action={createWorkspace} method="post"> <div data-slot="create-input-group"> <input diff --git a/packages/console/app/src/routes/workspace.css b/packages/console/app/src/routes/workspace.css index e8f12796e..ddb13ab74 100644 --- a/packages/console/app/src/routes/workspace.css +++ b/packages/console/app/src/routes/workspace.css @@ -104,4 +104,4 @@ } } } -}
\ No newline at end of file +} diff --git a/packages/console/app/src/routes/workspace/[id]/billing/billing-section.module.css b/packages/console/app/src/routes/workspace/[id]/billing/billing-section.module.css index aef008a48..24b405391 100644 --- a/packages/console/app/src/routes/workspace/[id]/billing/billing-section.module.css +++ b/packages/console/app/src/routes/workspace/[id]/billing/billing-section.module.css @@ -182,4 +182,4 @@ padding: var(--space-4); min-width: 150px; } -}
\ No newline at end of file +} diff --git a/packages/console/app/src/routes/workspace/[id]/billing/monthly-limit-section.module.css b/packages/console/app/src/routes/workspace/[id]/billing/monthly-limit-section.module.css index 4f0f8b2e6..a45bbf1a6 100644 --- a/packages/console/app/src/routes/workspace/[id]/billing/monthly-limit-section.module.css +++ b/packages/console/app/src/routes/workspace/[id]/billing/monthly-limit-section.module.css @@ -93,4 +93,4 @@ margin: 0; line-height: 1.4; } -}
\ No newline at end of file +} diff --git a/packages/console/app/src/routes/workspace/[id]/billing/payment-section.tsx b/packages/console/app/src/routes/workspace/[id]/billing/payment-section.tsx index 0fb2a0df6..a7218546d 100644 --- a/packages/console/app/src/routes/workspace/[id]/billing/payment-section.tsx +++ b/packages/console/app/src/routes/workspace/[id]/billing/payment-section.tsx @@ -89,7 +89,10 @@ export function PaymentSection() { <td data-slot="payment-receipt"> <button onClick={async () => { - const receiptUrl = await downloadReceiptAction(params.id, payment.paymentID!) + const receiptUrl = await downloadReceiptAction( + params.id, + payment.paymentID!, + ) if (receiptUrl) { window.open(receiptUrl, "_blank") } diff --git a/packages/console/app/src/routes/workspace/[id]/billing/reload-section.module.css b/packages/console/app/src/routes/workspace/[id]/billing/reload-section.module.css index 11ab789b2..e37bad696 100644 --- a/packages/console/app/src/routes/workspace/[id]/billing/reload-section.module.css +++ b/packages/console/app/src/routes/workspace/[id]/billing/reload-section.module.css @@ -259,4 +259,3 @@ } } } - diff --git a/packages/console/app/src/routes/workspace/[id]/keys/key-section.module.css b/packages/console/app/src/routes/workspace/[id]/keys/key-section.module.css index 1066b7f09..5705549e3 100644 --- a/packages/console/app/src/routes/workspace/[id]/keys/key-section.module.css +++ b/packages/console/app/src/routes/workspace/[id]/keys/key-section.module.css @@ -171,7 +171,6 @@ } @media (max-width: 40rem) { - th, td { padding: var(--space-2) var(--space-3); @@ -181,8 +180,7 @@ th { &:nth-child(3) - /* Date */ - { + /* Date */ { display: none; } } @@ -190,11 +188,10 @@ td { &:nth-child(3) - /* Date */ - { + /* Date */ { display: none; } } } } -}
\ No newline at end of file +} diff --git a/packages/console/app/src/routes/workspace/[id]/keys/key-section.tsx b/packages/console/app/src/routes/workspace/[id]/keys/key-section.tsx index 565981c7f..e1c2c00cf 100644 --- a/packages/console/app/src/routes/workspace/[id]/keys/key-section.tsx +++ b/packages/console/app/src/routes/workspace/[id]/keys/key-section.tsx @@ -146,14 +146,20 @@ export function KeySection() { title="Copy API key" > <span>{key.keyDisplay}</span> - <Show when={copied()} fallback={<IconCopy style={{ width: "14px", height: "14px" }} />}> + <Show + when={copied()} + fallback={<IconCopy style={{ width: "14px", height: "14px" }} />} + > <IconCheck style={{ width: "14px", height: "14px" }} /> </Show> </button> </Show> </td> <td data-slot="key-user-email">{key.email}</td> - <td data-slot="key-last-used" title={key.timeUsed ? formatDateUTC(key.timeUsed) : undefined}> + <td + data-slot="key-last-used" + title={key.timeUsed ? formatDateUTC(key.timeUsed) : undefined} + > {key.timeUsed ? formatDateForTable(key.timeUsed) : "-"} </td> <td data-slot="key-actions"> diff --git a/packages/console/app/src/routes/workspace/[id]/members/member-section.tsx b/packages/console/app/src/routes/workspace/[id]/members/member-section.tsx index 5aa1b969e..4b2a12fdc 100644 --- a/packages/console/app/src/routes/workspace/[id]/members/member-section.tsx +++ b/packages/console/app/src/routes/workspace/[id]/members/member-section.tsx @@ -85,7 +85,12 @@ const updateMember = action(async (form: FormData) => { ) }, "member.update") -function MemberRow(props: { member: any; workspaceID: string; actorID: string; actorRole: string }) { +function MemberRow(props: { + member: any + workspaceID: string + actorID: string + actorRole: string +}) { const submission = useSubmission(updateMember) const isCurrentUser = () => props.actorID === props.member.id const isAdmin = () => props.actorRole === "admin" diff --git a/packages/console/app/src/routes/workspace/[id]/members/role-dropdown.css b/packages/console/app/src/routes/workspace/[id]/members/role-dropdown.css index 29f55a977..7a64fd9c7 100644 --- a/packages/console/app/src/routes/workspace/[id]/members/role-dropdown.css +++ b/packages/console/app/src/routes/workspace/[id]/members/role-dropdown.css @@ -69,4 +69,4 @@ } } } -}
\ No newline at end of file +} diff --git a/packages/console/app/src/routes/workspace/[id]/new-user-section.module.css b/packages/console/app/src/routes/workspace/[id]/new-user-section.module.css index aaad823ab..bb58df79b 100644 --- a/packages/console/app/src/routes/workspace/[id]/new-user-section.module.css +++ b/packages/console/app/src/routes/workspace/[id]/new-user-section.module.css @@ -140,4 +140,4 @@ } } } -}
\ No newline at end of file +} diff --git a/packages/console/app/src/routes/workspace/[id]/new-user-section.tsx b/packages/console/app/src/routes/workspace/[id]/new-user-section.tsx index 65edc6847..7b949c661 100644 --- a/packages/console/app/src/routes/workspace/[id]/new-user-section.tsx +++ b/packages/console/app/src/routes/workspace/[id]/new-user-section.tsx @@ -43,15 +43,24 @@ export function NewUserSection() { <div data-component="feature-grid"> <div data-slot="feature"> <h3>Tested & Verified Models</h3> - <p>We've benchmarked and tested models specifically for coding agents to ensure the best performance.</p> + <p> + We've benchmarked and tested models specifically for coding agents to ensure the best + performance. + </p> </div> <div data-slot="feature"> <h3>Highest Quality</h3> - <p>Access models configured for optimal performance - no downgrades or routing to cheaper providers.</p> + <p> + Access models configured for optimal performance - no downgrades or routing to cheaper + providers. + </p> </div> <div data-slot="feature"> <h3>No Lock-in</h3> - <p>Use Zen with any coding agent, and continue using other providers with opencode whenever you want.</p> + <p> + Use Zen with any coding agent, and continue using other providers with opencode + whenever you want. + </p> </div> </div> diff --git a/packages/console/app/src/routes/workspace/[id]/provider-section.module.css b/packages/console/app/src/routes/workspace/[id]/provider-section.module.css index 1a450d3dc..1dc7085b7 100644 --- a/packages/console/app/src/routes/workspace/[id]/provider-section.module.css +++ b/packages/console/app/src/routes/workspace/[id]/provider-section.module.css @@ -128,7 +128,6 @@ } @media (max-width: 40rem) { - th, td { padding: var(--space-2) var(--space-3); @@ -136,4 +135,4 @@ } } } -}
\ No newline at end of file +} diff --git a/packages/console/app/src/routes/workspace/[id]/provider-section.tsx b/packages/console/app/src/routes/workspace/[id]/provider-section.tsx index 6ec8477b4..67314fbdc 100644 --- a/packages/console/app/src/routes/workspace/[id]/provider-section.tsx +++ b/packages/console/app/src/routes/workspace/[id]/provider-section.tsx @@ -22,7 +22,9 @@ const removeProvider = action(async (form: FormData) => { if (!provider) return { error: "Provider is required" } const workspaceID = form.get("workspaceID")?.toString() if (!workspaceID) return { error: "Workspace ID is required" } - return json(await withActor(() => Provider.remove({ provider }), workspaceID), { revalidate: listProviders.key }) + return json(await withActor(() => Provider.remove({ provider }), workspaceID), { + revalidate: listProviders.key, + }) }, "provider.remove") const saveProvider = action(async (form: FormData) => { @@ -53,7 +55,10 @@ const listProviders = query(async (workspaceID: string) => { function ProviderRow(props: { provider: Provider }) { const params = useParams() const providers = createAsync(() => listProviders(params.id)) - const saveSubmission = useSubmission(saveProvider, ([fd]) => fd.get("provider")?.toString() === props.provider.key) + const saveSubmission = useSubmission( + saveProvider, + ([fd]) => fd.get("provider")?.toString() === props.provider.key, + ) const removeSubmission = useSubmission( removeProvider, ([fd]) => fd.get("provider")?.toString() === props.provider.key, @@ -89,9 +94,16 @@ function ProviderRow(props: { provider: Provider }) { <td data-slot="provider-key"> <Show when={store.editing} - fallback={<span>{providerData() ? maskCredentials(providerData()!.credentials) : "-"}</span>} + fallback={ + <span>{providerData() ? maskCredentials(providerData()!.credentials) : "-"}</span> + } > - <form id={`provider-form-${props.provider.key}`} action={saveProvider} method="post" data-slot="edit-form"> + <form + id={`provider-form-${props.provider.key}`} + action={saveProvider} + method="post" + data-slot="edit-form" + > <div data-slot="input-wrapper"> <input ref={(r) => (input = r)} diff --git a/packages/console/app/src/routes/workspace/[id]/settings/settings-section.module.css b/packages/console/app/src/routes/workspace/[id]/settings/settings-section.module.css index 058fbe301..6764a0534 100644 --- a/packages/console/app/src/routes/workspace/[id]/settings/settings-section.module.css +++ b/packages/console/app/src/routes/workspace/[id]/settings/settings-section.module.css @@ -31,7 +31,7 @@ margin: 0; } - >button { + > button { align-self: flex-start; } } @@ -80,7 +80,7 @@ } } - >button[type="reset"] { + > button[type="reset"] { align-self: flex-start; } @@ -91,4 +91,4 @@ margin-top: calc(var(--space-1) * -1); } } -}
\ No newline at end of file +} diff --git a/packages/console/app/src/routes/zen/index.tsx b/packages/console/app/src/routes/zen/index.tsx index 08e58e160..92cc0a508 100644 --- a/packages/console/app/src/routes/zen/index.tsx +++ b/packages/console/app/src/routes/zen/index.tsx @@ -28,7 +28,10 @@ export default function Home() { createAsync(() => checkLoggedIn()) return ( <main data-page="zen"> - <HttpHeader name="Cache-Control" value="public, max-age=1, s-maxage=3600, stale-while-revalidate=86400" /> + <HttpHeader + name="Cache-Control" + value="public, max-age=1, s-maxage=3600, stale-while-revalidate=86400" + /> <Title>OpenCode Zen | A curated set of reliable optimized models for coding agents</Title> <Link rel="icon" type="image/svg+xml" href="/favicon-zen.svg" /> <Meta property="og:image" content="/social-share-zen.png" /> @@ -44,13 +47,19 @@ export default function Home() { <img data-slot="zen logo dark" src={zenLogoDark} alt="zen logo dark" /> <strong>Reliable optimized models for coding agents</strong> <p> - Zen gives you access to a curated set of AI models that OpenCode has tested and benchmarked specifically - for coding agents. No need to worry about inconsistent performance and quality, use validated models - that work. + Zen gives you access to a curated set of AI models that OpenCode has tested and + benchmarked specifically for coding agents. No need to worry about inconsistent + performance and quality, use validated models that work. </p> <div data-slot="model-logos"> <div> - <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> + <svg + width="24" + height="24" + viewBox="0 0 24 24" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > <mask id="mask0_79_128586" style="mask-type:luminance" @@ -71,8 +80,17 @@ export default function Home() { </svg> </div> <div> - <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M13.7891 3.93164L20.2223 20.0677H23.7502L17.317 3.93164H13.7891Z" fill="currentColor" /> + <svg + width="24" + height="24" + viewBox="0 0 24 24" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M13.7891 3.93164L20.2223 20.0677H23.7502L17.317 3.93164H13.7891Z" + fill="currentColor" + /> <path d="M6.32538 13.6824L8.52662 8.01177L10.7279 13.6824H6.32538ZM6.68225 3.93164L0.25 20.0677H3.84652L5.16202 16.6791H11.8914L13.2067 20.0677H16.8033L10.371 3.93164H6.68225Z" fill="currentColor" @@ -80,7 +98,13 @@ export default function Home() { </svg> </div> <div> - <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> + <svg + width="24" + height="24" + viewBox="0 0 24 24" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > <path d="M9.16861 16.0529L17.2018 9.85156C17.5957 9.54755 18.1586 9.66612 18.3463 10.1384C19.3339 12.6288 18.8926 15.6217 16.9276 17.6766C14.9626 19.7314 12.2285 20.1821 9.72948 19.1557L6.9995 20.4775C10.9151 23.2763 15.6699 22.5841 18.6411 19.4749C20.9979 17.0103 21.7278 13.6508 21.0453 10.6214L21.0515 10.6278C20.0617 6.17736 21.2948 4.39847 23.8207 0.760904C23.8804 0.674655 23.9402 0.588405 24 0.5L20.6762 3.97585V3.96506L9.16658 16.0551" fill="currentColor" @@ -92,7 +116,13 @@ export default function Home() { </svg> </div> <div> - <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> + <svg + width="24" + height="24" + viewBox="0 0 24 24" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > <path fill-rule="evenodd" clip-rule="evenodd" @@ -102,7 +132,13 @@ export default function Home() { </svg> </div> <div> - <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> + <svg + width="24" + height="24" + viewBox="0 0 24 24" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > <path d="M12.6241 11.346L20.3848 3.44816C20.5309 3.29931 20.4487 3 20.2601 3H16.0842C16.0388 3 15.9949 3.01897 15.9594 3.05541L7.59764 11.5629C7.46721 11.6944 7.27446 11.5771 7.27446 11.3666V3.25183C7.27446 3.11242 7.18515 3 7.07594 3H4.19843C4.08932 3 4 3.11242 4 3.25183V20.7482C4 20.8876 4.08932 21 4.19843 21H7.07594C7.18515 21 7.27446 20.8876 7.27446 20.7482V17.1834C7.27446 17.1073 7.30136 17.0344 7.34815 16.987L9.94075 14.3486C10.0031 14.2853 10.0895 14.2757 10.159 14.3232L17.0934 19.5573C18.2289 20.3412 19.4975 20.8226 20.786 20.9652C20.9008 20.9778 21 20.8606 21 20.7133V17.3559C21 17.2276 20.9249 17.1232 20.8243 17.1073C20.0659 16.9853 19.326 16.6845 18.6569 16.222L12.6538 11.764C12.5291 11.6785 12.5135 11.4584 12.6241 11.346Z" fill="currentColor" @@ -112,7 +148,13 @@ export default function Home() { </div> <a href="/auth"> <span>Get started with Zen </span> - <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> + <svg + width="24" + height="24" + viewBox="0 0 24 24" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > <path d="M6.5 12L17 12M13 16.5L17.5 12L13 7.5" stroke="currentColor" @@ -124,14 +166,23 @@ export default function Home() { </div> <div data-slot="pricing-copy"> <p> - <strong>Add $20 Pay as you go balance</strong> <span>(+$1.23 card processing fee)</span> + <strong>Add $20 Pay as you go balance</strong>{" "} + <span>(+$1.23 card processing fee)</span> </p> <p>Use with any agent. Set monthly spend limits. Cancel any time.</p> </div> </section> <section data-component="comparison"> - <video src={compareVideo} autoplay playsinline loop muted preload="auto" poster={compareVideoPoster}> + <video + src={compareVideo} + autoplay + playsinline + loop + muted + preload="auto" + poster={compareVideoPoster} + > Your browser does not support the video tag. </video> </section> @@ -140,8 +191,8 @@ export default function Home() { <div data-slot="section-title"> <h3>What problem is Zen solving?</h3> <p> - There are so many models available, but only a few work well with coding agents. Most providers - configure them differently with varying results. + There are so many models available, but only a few work well with coding agents. + Most providers configure them differently with varying results. </p> </div> <p>We're fixing this for everyone, not just OpenCode users.</p> @@ -176,14 +227,15 @@ export default function Home() { <li> <span>[2]</span> <div> - <strong>Use Zen with transparent pricing</strong> - <a href="/docs/zen/#pricing">pay per request</a>{" "} - with zero markups + <strong>Use Zen with transparent pricing</strong> -{" "} + <a href="/docs/zen/#pricing">pay per request</a> with zero markups </div> </li> <li> <span>[3]</span> <div> - <strong>Auto-top up</strong> - when your balance reaches $5 we’ll automatically add $20 + <strong>Auto-top up</strong> - when your balance reaches $5 we’ll automatically + add $20 </div> </li> </ul> @@ -195,8 +247,9 @@ export default function Home() { <div> <span>[*]</span> <p> - All Zen models are hosted in the US. Providers follow a zero-retention policy and do not use your data - for model training, with the <a href="/docs/zen/#privacy">following exceptions</a>. + All Zen models are hosted in the US. Providers follow a zero-retention policy and + do not use your data for model training, with the{" "} + <a href="/docs/zen/#privacy">following exceptions</a>. </p> </div> </div> @@ -251,7 +304,8 @@ export default function Home() { <span>ex-Head of Design, Laravel</span> </div> <div data-slot="quote"> - With <span>@OpenCode</span> Zen I know all the models are tested and perfect for coding agents. + With <span>@OpenCode</span> Zen I know all the models are tested and perfect for + coding agents. </div> </div> </a> @@ -275,38 +329,44 @@ export default function Home() { <ul> <li> <Faq question="What is OpenCode Zen?"> - Zen is a curated set of AI models tested and benchmarked for coding agents created by the team behind - OpenCode. + Zen is a curated set of AI models tested and benchmarked for coding agents created + by the team behind OpenCode. </Faq> </li> <li> <Faq question="What makes Zen more accurate?"> - Zen only provides models that have been specifically tested and benchmarked for coding agents. You - wouldn’t use a butter knife to cut steak, don’t use poor models for coding. + Zen only provides models that have been specifically tested and benchmarked for + coding agents. You wouldn’t use a butter knife to cut steak, don’t use poor models + for coding. </Faq> </li> <li> <Faq question="Is Zen cheaper?"> - Zen is not for profit. Zen passes through the costs from the model providers to you. The higher Zen’s - usage the more OpenCode can negotiate better rates and pass those to you. + Zen is not for profit. Zen passes through the costs from the model providers to + you. The higher Zen’s usage the more OpenCode can negotiate better rates and pass + those to you. </Faq> </li> <li> <Faq question="How much does Zen cost?"> - Zen <a href="/docs/zen/#pricing">charges per request</a> with zero markups, so you pay exactly what - the model provider charges. Your total cost depends on usage, and you can set monthly spend limits in - your <a href="/auth">account</a>. To cover costs, OpenCode adds only a small payment processing fee of - $1.23 per $20 balance top-up. + Zen <a href="/docs/zen/#pricing">charges per request</a> with zero markups, so you + pay exactly what the model provider charges. Your total cost depends on usage, and + you can set monthly spend limits in your <a href="/auth">account</a>. To cover + costs, OpenCode adds only a small payment processing fee of $1.23 per $20 balance + top-up. </Faq> </li> <li> <Faq question="What about data and privacy?"> - All Zen models are hosted in the US. Providers follow a zero-retention policy and do not use your data - for model training, with the <a href="/docs/zen/#privacy">following exceptions</a>. + All Zen models are hosted in the US. Providers follow a zero-retention policy and + do not use your data for model training, with the{" "} + <a href="/docs/zen/#privacy">following exceptions</a>. </Faq> </li> <li> - <Faq question="Can I set spend limits?">Yes, you can set monthly spending limits in your account.</Faq> + <Faq question="Can I set spend limits?"> + Yes, you can set monthly spending limits in your account. + </Faq> </li> <li> <Faq question="Can I cancel?"> @@ -315,8 +375,8 @@ export default function Home() { </li> <li> <Faq question="Can I use Zen with other coding agents?"> - While Zen works great with OpenCode, you can use Zen with any agent. Follow the setup instructions in - your preferred coding agent. + While Zen works great with OpenCode, you can use Zen with any agent. Follow the + setup instructions in your preferred coding agent. </Faq> </li> </ul> diff --git a/packages/console/app/src/routes/zen/util/provider/anthropic.ts b/packages/console/app/src/routes/zen/util/provider/anthropic.ts index 603d8917b..f4e8dc44d 100644 --- a/packages/console/app/src/routes/zen/util/provider/anthropic.ts +++ b/packages/console/app/src/routes/zen/util/provider/anthropic.ts @@ -98,7 +98,10 @@ export function fromAnthropicRequest(body: any): CommonRequest { typeof (src as any).media_type === "string" && typeof (src as any).data === "string" ) - return { type: "image_url", image_url: { url: `data:${(src as any).media_type};base64,${(src as any).data}` } } + return { + type: "image_url", + image_url: { url: `data:${(src as any).media_type};base64,${(src as any).data}` }, + } return undefined } @@ -120,12 +123,15 @@ export function fromAnthropicRequest(body: any): CommonRequest { if ((p as any).type === "tool_result") { const id = (p as any).tool_use_id const content = - typeof (p as any).content === "string" ? (p as any).content : JSON.stringify((p as any).content) + typeof (p as any).content === "string" + ? (p as any).content + : JSON.stringify((p as any).content) msgs.push({ role: "tool", tool_call_id: id, content }) } } if (partsOut.length > 0) { - if (partsOut.length === 1 && partsOut[0].type === "text") msgs.push({ role: "user", content: partsOut[0].text }) + if (partsOut.length === 1 && partsOut[0].type === "text") + msgs.push({ role: "user", content: partsOut[0].text }) else msgs.push({ role: "user", content: partsOut }) } continue @@ -137,7 +143,8 @@ export function fromAnthropicRequest(body: any): CommonRequest { const tcs: any[] = [] for (const p of partsIn) { if (!p || !(p as any).type) continue - if ((p as any).type === "text" && typeof (p as any).text === "string") texts.push((p as any).text) + if ((p as any).type === "text" && typeof (p as any).text === "string") + texts.push((p as any).text) if ((p as any).type === "tool_use") { const name = (p as any).name const id = (p as any).id @@ -165,7 +172,11 @@ export function fromAnthropicRequest(body: any): CommonRequest { .filter((t: any) => t && typeof t === "object" && "input_schema" in t) .map((t: any) => ({ type: "function", - function: { name: (t as any).name, description: (t as any).description, parameters: (t as any).input_schema }, + function: { + name: (t as any).name, + description: (t as any).description, + parameters: (t as any).input_schema, + }, })) : undefined @@ -203,7 +214,9 @@ export function fromAnthropicRequest(body: any): CommonRequest { export function toAnthropicRequest(body: CommonRequest) { if (!body || typeof body !== "object") return body - const sysIn = Array.isArray(body.messages) ? body.messages.filter((m: any) => m && m.role === "system") : [] + const sysIn = Array.isArray(body.messages) + ? body.messages.filter((m: any) => m && m.role === "system") + : [] let ccCount = 0 const cc = () => { ccCount++ @@ -354,7 +367,9 @@ export function fromAnthropicResponse(resp: any): CommonResponse { const idIn = (resp as any).id const id = - typeof idIn === "string" ? idIn.replace(/^msg_/, "chatcmpl_") : `chatcmpl_${Math.random().toString(36).slice(2)}` + typeof idIn === "string" + ? idIn.replace(/^msg_/, "chatcmpl_") + : `chatcmpl_${Math.random().toString(36).slice(2)}` const model = (resp as any).model const blocks: any[] = Array.isArray((resp as any).content) ? (resp as any).content : [] @@ -397,7 +412,9 @@ export function fromAnthropicResponse(resp: any): CommonResponse { const ct = typeof (u as any).output_tokens === "number" ? (u as any).output_tokens : undefined const total = pt != null && ct != null ? pt + ct : undefined const cached = - typeof (u as any).cache_read_input_tokens === "number" ? (u as any).cache_read_input_tokens : undefined + typeof (u as any).cache_read_input_tokens === "number" + ? (u as any).cache_read_input_tokens + : undefined const details = cached != null ? { cached_tokens: cached } : undefined return { prompt_tokens: pt, @@ -452,7 +469,12 @@ export function toAnthropicResponse(resp: CommonResponse) { } catch { input = (tc as any).function.arguments } - content.push({ type: "tool_use", id: (tc as any).id, name: (tc as any).function.name, input }) + content.push({ + type: "tool_use", + id: (tc as any).id, + name: (tc as any).function.name, + input, + }) } } } @@ -511,13 +533,22 @@ export function fromAnthropicChunk(chunk: string): CommonChunk | string { if (json.type === "content_block_start") { const cb = json.content_block if (cb?.type === "text") { - out.choices.push({ index: json.index ?? 0, delta: { role: "assistant", content: "" }, finish_reason: null }) + out.choices.push({ + index: json.index ?? 0, + delta: { role: "assistant", content: "" }, + finish_reason: null, + }) } else if (cb?.type === "tool_use") { out.choices.push({ index: json.index ?? 0, delta: { tool_calls: [ - { index: json.index ?? 0, id: cb.id, type: "function", function: { name: cb.name, arguments: "" } }, + { + index: json.index ?? 0, + id: cb.id, + type: "function", + function: { name: cb.name, arguments: "" }, + }, ], }, finish_reason: null, @@ -532,7 +563,9 @@ export function fromAnthropicChunk(chunk: string): CommonChunk | string { } else if (d?.type === "input_json_delta") { out.choices.push({ index: json.index ?? 0, - delta: { tool_calls: [{ index: json.index ?? 0, function: { arguments: d.partial_json } }] }, + delta: { + tool_calls: [{ index: json.index ?? 0, function: { arguments: d.partial_json } }], + }, finish_reason: null, }) } @@ -558,7 +591,9 @@ export function fromAnthropicChunk(chunk: string): CommonChunk | string { prompt_tokens: u.input_tokens, completion_tokens: u.output_tokens, total_tokens: (u.input_tokens || 0) + (u.output_tokens || 0), - ...(u.cache_read_input_tokens ? { prompt_tokens_details: { cached_tokens: u.cache_read_input_tokens } } : {}), + ...(u.cache_read_input_tokens + ? { prompt_tokens_details: { cached_tokens: u.cache_read_input_tokens } } + : {}), } } diff --git a/packages/console/app/src/routes/zen/util/provider/openai-compatible.ts b/packages/console/app/src/routes/zen/util/provider/openai-compatible.ts index daf650275..d69985728 100644 --- a/packages/console/app/src/routes/zen/util/provider/openai-compatible.ts +++ b/packages/console/app/src/routes/zen/util/provider/openai-compatible.ts @@ -57,7 +57,8 @@ export const oaCompatHelper = { const inputTokens = usage.prompt_tokens ?? 0 const outputTokens = usage.completion_tokens ?? 0 const reasoningTokens = usage.completion_tokens_details?.reasoning_tokens ?? undefined - const cacheReadTokens = usage.cached_tokens ?? usage.prompt_tokens_details?.cached_tokens ?? undefined + const cacheReadTokens = + usage.cached_tokens ?? usage.prompt_tokens_details?.cached_tokens ?? undefined return { inputTokens: inputTokens - (cacheReadTokens ?? 0), outputTokens, @@ -79,7 +80,8 @@ export function fromOaCompatibleRequest(body: any): CommonRequest { if (!m || !m.role) continue if (m.role === "system") { - if (typeof m.content === "string" && m.content.length > 0) msgsOut.push({ role: "system", content: m.content }) + if (typeof m.content === "string" && m.content.length > 0) + msgsOut.push({ role: "system", content: m.content }) continue } @@ -90,10 +92,12 @@ export function fromOaCompatibleRequest(body: any): CommonRequest { const parts: any[] = [] for (const p of m.content) { if (!p || !p.type) continue - if (p.type === "text" && typeof p.text === "string") parts.push({ type: "text", text: p.text }) + if (p.type === "text" && typeof p.text === "string") + parts.push({ type: "text", text: p.text }) if (p.type === "image_url") parts.push({ type: "image_url", image_url: p.image_url }) } - if (parts.length === 1 && parts[0].type === "text") msgsOut.push({ role: "user", content: parts[0].text }) + if (parts.length === 1 && parts[0].type === "text") + msgsOut.push({ role: "user", content: parts[0].text }) else if (parts.length > 0) msgsOut.push({ role: "user", content: parts }) } continue @@ -137,7 +141,8 @@ export function toOaCompatibleRequest(body: CommonRequest) { if (p.type === "image_url" && p.image_url) return { type: "image_url", image_url: p.image_url } const s = (p as any).source if (!s || typeof s !== "object") return undefined - if (s.type === "url" && typeof s.url === "string") return { type: "image_url", image_url: { url: s.url } } + if (s.type === "url" && typeof s.url === "string") + return { type: "image_url", image_url: { url: s.url } } if (s.type === "base64" && typeof s.media_type === "string" && typeof s.data === "string") return { type: "image_url", image_url: { url: `data:${s.media_type};base64,${s.data}` } } return undefined @@ -147,7 +152,8 @@ export function toOaCompatibleRequest(body: CommonRequest) { if (!m || !m.role) continue if (m.role === "system") { - if (typeof m.content === "string" && m.content.length > 0) msgsOut.push({ role: "system", content: m.content }) + if (typeof m.content === "string" && m.content.length > 0) + msgsOut.push({ role: "system", content: m.content }) continue } @@ -160,11 +166,13 @@ export function toOaCompatibleRequest(body: CommonRequest) { const parts: any[] = [] for (const p of m.content) { if (!p || !p.type) continue - if (p.type === "text" && typeof p.text === "string") parts.push({ type: "text", text: p.text }) + if (p.type === "text" && typeof p.text === "string") + parts.push({ type: "text", text: p.text }) const ip = toImg(p) if (ip) parts.push(ip) } - if (parts.length === 1 && parts[0].type === "text") msgsOut.push({ role: "user", content: parts[0].text }) + if (parts.length === 1 && parts[0].type === "text") + msgsOut.push({ role: "user", content: parts[0].text }) else if (parts.length > 0) msgsOut.push({ role: "user", content: parts }) } continue @@ -317,7 +325,9 @@ export function toOaCompatibleResponse(resp: CommonResponse) { const idIn = (resp as any).id const id = - typeof idIn === "string" ? idIn.replace(/^msg_/, "chatcmpl_") : `chatcmpl_${Math.random().toString(36).slice(2)}` + typeof idIn === "string" + ? idIn.replace(/^msg_/, "chatcmpl_") + : `chatcmpl_${Math.random().toString(36).slice(2)}` const model = (resp as any).model const blocks: any[] = Array.isArray((resp as any).content) ? (resp as any).content : [] @@ -359,7 +369,8 @@ export function toOaCompatibleResponse(resp: CommonResponse) { const pt = typeof u.input_tokens === "number" ? u.input_tokens : undefined const ct = typeof u.output_tokens === "number" ? u.output_tokens : undefined const total = pt != null && ct != null ? pt + ct : undefined - const cached = typeof u.cache_read_input_tokens === "number" ? u.cache_read_input_tokens : undefined + const cached = + typeof u.cache_read_input_tokens === "number" ? u.cache_read_input_tokens : undefined const details = cached != null ? { cached_tokens: cached } : undefined return { prompt_tokens: pt, @@ -532,7 +543,9 @@ export function toOaCompatibleChunk(chunk: CommonChunk): string { total_tokens: chunk.usage.total_tokens, ...(chunk.usage.prompt_tokens_details?.cached_tokens ? { - prompt_tokens_details: { cached_tokens: chunk.usage.prompt_tokens_details.cached_tokens }, + prompt_tokens_details: { + cached_tokens: chunk.usage.prompt_tokens_details.cached_tokens, + }, } : {}), } diff --git a/packages/console/app/src/routes/zen/util/provider/openai.ts b/packages/console/app/src/routes/zen/util/provider/openai.ts index d17300991..fa0776b7a 100644 --- a/packages/console/app/src/routes/zen/util/provider/openai.ts +++ b/packages/console/app/src/routes/zen/util/provider/openai.ts @@ -77,13 +77,20 @@ export function fromOpenaiRequest(body: any): CommonRequest { typeof (s as any).media_type === "string" && typeof (s as any).data === "string" ) - return { type: "image_url", image_url: { url: `data:${(s as any).media_type};base64,${(s as any).data}` } } + return { + type: "image_url", + image_url: { url: `data:${(s as any).media_type};base64,${(s as any).data}` }, + } return undefined } const msgs: any[] = [] - const inMsgs = Array.isArray(body.input) ? body.input : Array.isArray(body.messages) ? body.messages : [] + const inMsgs = Array.isArray(body.input) + ? body.input + : Array.isArray(body.messages) + ? body.messages + : [] for (const m of inMsgs) { if (!m) continue @@ -96,7 +103,9 @@ export function fromOpenaiRequest(body: any): CommonRequest { const args = typeof a === "string" ? a : JSON.stringify(a ?? {}) msgs.push({ role: "assistant", - tool_calls: [{ id: (m as any).id, type: "function", function: { name, arguments: args } }], + tool_calls: [ + { id: (m as any).id, type: "function", function: { name, arguments: args } }, + ], }) } if ((m as any).type === "function_call_output") { @@ -113,7 +122,8 @@ export function fromOpenaiRequest(body: any): CommonRequest { if (typeof c === "string" && c.length > 0) msgs.push({ role: "system", content: c }) if (Array.isArray(c)) { const t = c.find((p: any) => p && typeof p.text === "string") - if (t && typeof t.text === "string" && t.text.length > 0) msgs.push({ role: "system", content: t.text }) + if (t && typeof t.text === "string" && t.text.length > 0) + msgs.push({ role: "system", content: t.text }) } continue } @@ -126,18 +136,24 @@ export function fromOpenaiRequest(body: any): CommonRequest { const parts: any[] = [] for (const p of c) { if (!p || !(p as any).type) continue - if (((p as any).type === "text" || (p as any).type === "input_text") && typeof (p as any).text === "string") + if ( + ((p as any).type === "text" || (p as any).type === "input_text") && + typeof (p as any).text === "string" + ) parts.push({ type: "text", text: (p as any).text }) const ip = toImg(p) if (ip) parts.push(ip) if ((p as any).type === "tool_result") { const id = (p as any).tool_call_id const content = - typeof (p as any).content === "string" ? (p as any).content : JSON.stringify((p as any).content) + typeof (p as any).content === "string" + ? (p as any).content + : JSON.stringify((p as any).content) msgs.push({ role: "tool", tool_call_id: id, content }) } } - if (parts.length === 1 && parts[0].type === "text") msgs.push({ role: "user", content: parts[0].text }) + if (parts.length === 1 && parts[0].type === "text") + msgs.push({ role: "user", content: parts[0].text }) else if (parts.length > 0) msgs.push({ role: "user", content: parts }) } continue @@ -153,7 +169,11 @@ export function fromOpenaiRequest(body: any): CommonRequest { } if ((m as any).role === "tool") { - msgs.push({ role: "tool", tool_call_id: (m as any).tool_call_id, content: (m as any).content }) + msgs.push({ + role: "tool", + tool_call_id: (m as any).tool_call_id, + content: (m as any).content, + }) continue } } @@ -210,7 +230,10 @@ export function toOpenaiRequest(body: CommonRequest) { typeof (s as any).media_type === "string" && typeof (s as any).data === "string" ) - return { type: "input_image", image_url: { url: `data:${(s as any).media_type};base64,${(s as any).data}` } } + return { + type: "input_image", + image_url: { url: `data:${(s as any).media_type};base64,${(s as any).data}` }, + } return undefined } @@ -257,7 +280,10 @@ export function toOpenaiRequest(body: CommonRequest) { } if ((m as any).role === "tool") { - const out = typeof (m as any).content === "string" ? (m as any).content : JSON.stringify((m as any).content) + const out = + typeof (m as any).content === "string" + ? (m as any).content + : JSON.stringify((m as any).content) input.push({ type: "function_call_output", call_id: (m as any).tool_call_id, output: out }) continue } @@ -325,7 +351,9 @@ export function fromOpenaiResponse(resp: any): CommonResponse { const idIn = (r as any).id const id = - typeof idIn === "string" ? idIn.replace(/^resp_/, "chatcmpl_") : `chatcmpl_${Math.random().toString(36).slice(2)}` + typeof idIn === "string" + ? idIn.replace(/^resp_/, "chatcmpl_") + : `chatcmpl_${Math.random().toString(36).slice(2)}` const model = (r as any).model ?? (resp as any).model const out = Array.isArray((r as any).output) ? (r as any).output : [] @@ -452,7 +480,9 @@ export function toOpenaiResponse(resp: CommonResponse) { })() return { - id: (resp as any).id?.replace(/^chatcmpl_/, "resp_") ?? `resp_${Math.random().toString(36).slice(2)}`, + id: + (resp as any).id?.replace(/^chatcmpl_/, "resp_") ?? + `resp_${Math.random().toString(36).slice(2)}`, object: "response", model: (resp as any).model, output: outputItems, @@ -498,7 +528,9 @@ export function fromOpenaiChunk(chunk: string): CommonChunk | string { if (typeof name === "string" && name.length > 0) { out.choices.push({ index: 0, - delta: { tool_calls: [{ index: 0, id, type: "function", function: { name, arguments: "" } }] }, + delta: { + tool_calls: [{ index: 0, id, type: "function", function: { name, arguments: "" } }], + }, finish_reason: null, }) } @@ -555,7 +587,12 @@ export function toOpenaiChunk(chunk: CommonChunk): string { const model = chunk.model if (d.content) { - const data = { id, type: "response.output_text.delta", delta: d.content, response: { id, model } } + const data = { + id, + type: "response.output_text.delta", + delta: d.content, + response: { id, model }, + } return `event: response.output_text.delta\ndata: ${JSON.stringify(data)}` } @@ -565,7 +602,13 @@ export function toOpenaiChunk(chunk: CommonChunk): string { const data = { type: "response.output_item.added", output_index: 0, - item: { id: tc.id, type: "function_call", name: tc.function.name, call_id: tc.id, arguments: "" }, + item: { + id: tc.id, + type: "function_call", + name: tc.function.name, + call_id: tc.id, + arguments: "", + }, } return `event: response.output_item.added\ndata: ${JSON.stringify(data)}` } @@ -593,7 +636,11 @@ export function toOpenaiChunk(chunk: CommonChunk): string { } : undefined - const data: any = { id, type: "response.completed", response: { id, model, ...(usage ? { usage } : {}) } } + const data: any = { + id, + type: "response.completed", + response: { id, model, ...(usage ? { usage } : {}) }, + } return `event: response.completed\ndata: ${JSON.stringify(data)}` } diff --git a/packages/console/app/src/style/token/font.css b/packages/console/app/src/style/token/font.css index 67143e662..dc0d298f1 100644 --- a/packages/console/app/src/style/token/font.css +++ b/packages/console/app/src/style/token/font.css @@ -15,6 +15,7 @@ body { --font-size-9xl: 8rem; --font-mono: - "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", + "Courier New", monospace; --font-sans: var(--font-mono); } diff --git a/packages/console/app/sst-env.d.ts b/packages/console/app/sst-env.d.ts index 9b9de7327..bd5588217 100644 --- a/packages/console/app/sst-env.d.ts +++ b/packages/console/app/sst-env.d.ts @@ -6,4 +6,4 @@ /// <reference path="../../../sst-env.d.ts" /> import "sst" -export {}
\ No newline at end of file +export {} diff --git a/packages/console/core/migrations/meta/0018_snapshot.json b/packages/console/core/migrations/meta/0018_snapshot.json index 398ba2619..3e3c64c73 100644 --- a/packages/console/core/migrations/meta/0018_snapshot.json +++ b/packages/console/core/migrations/meta/0018_snapshot.json @@ -48,9 +48,7 @@ "indexes": { "email": { "name": "email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": true } }, @@ -180,9 +178,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -190,10 +186,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -280,10 +273,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -398,10 +388,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -486,17 +473,12 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true }, "name": { "name": "name", - "columns": [ - "workspace_id", - "name" - ], + "columns": ["workspace_id", "name"], "isUnique": true } }, @@ -504,10 +486,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -599,10 +578,7 @@ "indexes": { "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true } }, @@ -610,10 +586,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -670,9 +643,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -680,9 +651,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -699,4 +668,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0019_snapshot.json b/packages/console/core/migrations/meta/0019_snapshot.json index 8f1afeb51..9a0d4d243 100644 --- a/packages/console/core/migrations/meta/0019_snapshot.json +++ b/packages/console/core/migrations/meta/0019_snapshot.json @@ -48,9 +48,7 @@ "indexes": { "email": { "name": "email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": true } }, @@ -180,9 +178,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -190,10 +186,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -280,10 +273,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -398,10 +388,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -486,17 +473,12 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true }, "name": { "name": "name", - "columns": [ - "workspace_id", - "name" - ], + "columns": ["workspace_id", "name"], "isUnique": true } }, @@ -504,10 +486,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -599,10 +578,7 @@ "indexes": { "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true } }, @@ -610,10 +586,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -670,9 +643,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -680,9 +651,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -699,4 +668,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0020_snapshot.json b/packages/console/core/migrations/meta/0020_snapshot.json index 662093f55..9defceb5a 100644 --- a/packages/console/core/migrations/meta/0020_snapshot.json +++ b/packages/console/core/migrations/meta/0020_snapshot.json @@ -48,9 +48,7 @@ "indexes": { "email": { "name": "email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": true } }, @@ -180,9 +178,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -190,10 +186,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -280,10 +273,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -398,10 +388,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -486,17 +473,12 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true }, "name": { "name": "name", - "columns": [ - "workspace_id", - "name" - ], + "columns": ["workspace_id", "name"], "isUnique": true } }, @@ -504,10 +486,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -592,10 +571,7 @@ "indexes": { "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true } }, @@ -603,10 +579,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -663,9 +636,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -673,9 +644,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -692,4 +661,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0021_snapshot.json b/packages/console/core/migrations/meta/0021_snapshot.json index b285e34fa..64d3e9d24 100644 --- a/packages/console/core/migrations/meta/0021_snapshot.json +++ b/packages/console/core/migrations/meta/0021_snapshot.json @@ -48,9 +48,7 @@ "indexes": { "email": { "name": "email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": true } }, @@ -180,9 +178,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -190,10 +186,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -280,10 +273,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -398,10 +388,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -486,17 +473,12 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true }, "name": { "name": "name", - "columns": [ - "workspace_id", - "name" - ], + "columns": ["workspace_id", "name"], "isUnique": true } }, @@ -504,10 +486,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -599,10 +578,7 @@ "indexes": { "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true } }, @@ -610,10 +586,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -670,9 +643,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -680,9 +651,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -699,4 +668,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0022_snapshot.json b/packages/console/core/migrations/meta/0022_snapshot.json index 9486ee345..8a1c4e7d8 100644 --- a/packages/console/core/migrations/meta/0022_snapshot.json +++ b/packages/console/core/migrations/meta/0022_snapshot.json @@ -48,9 +48,7 @@ "indexes": { "email": { "name": "email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": true } }, @@ -180,9 +178,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -190,10 +186,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -280,10 +273,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -398,10 +388,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -486,17 +473,12 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true }, "name": { "name": "name", - "columns": [ - "workspace_id", - "name" - ], + "columns": ["workspace_id", "name"], "isUnique": true } }, @@ -504,10 +486,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -613,18 +592,12 @@ "indexes": { "user_account_id": { "name": "user_account_id", - "columns": [ - "workspace_id", - "account_id" - ], + "columns": ["workspace_id", "account_id"], "isUnique": true }, "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true } }, @@ -632,10 +605,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -692,9 +662,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -702,9 +670,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -721,4 +687,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0023_snapshot.json b/packages/console/core/migrations/meta/0023_snapshot.json index 8a40e42a4..4f6f66283 100644 --- a/packages/console/core/migrations/meta/0023_snapshot.json +++ b/packages/console/core/migrations/meta/0023_snapshot.json @@ -48,9 +48,7 @@ "indexes": { "email": { "name": "email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": true } }, @@ -180,9 +178,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -190,10 +186,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -280,10 +273,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -398,10 +388,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -486,17 +473,12 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true }, "name": { "name": "name", - "columns": [ - "workspace_id", - "name" - ], + "columns": ["workspace_id", "name"], "isUnique": true } }, @@ -504,10 +486,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -613,32 +592,22 @@ "indexes": { "user_account_id": { "name": "user_account_id", - "columns": [ - "workspace_id", - "account_id" - ], + "columns": ["workspace_id", "account_id"], "isUnique": true }, "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true }, "global_account_id": { "name": "global_account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false }, "global_email": { "name": "global_email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": false } }, @@ -646,10 +615,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -706,9 +672,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -716,9 +680,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -735,4 +697,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0024_snapshot.json b/packages/console/core/migrations/meta/0024_snapshot.json index 4f50945d6..1ef25970a 100644 --- a/packages/console/core/migrations/meta/0024_snapshot.json +++ b/packages/console/core/migrations/meta/0024_snapshot.json @@ -48,9 +48,7 @@ "indexes": { "email": { "name": "email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": true } }, @@ -180,9 +178,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -190,10 +186,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -280,10 +273,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -398,10 +388,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -486,17 +473,12 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true }, "name": { "name": "name", - "columns": [ - "workspace_id", - "name" - ], + "columns": ["workspace_id", "name"], "isUnique": true } }, @@ -504,10 +486,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -599,32 +578,22 @@ "indexes": { "user_account_id": { "name": "user_account_id", - "columns": [ - "workspace_id", - "account_id" - ], + "columns": ["workspace_id", "account_id"], "isUnique": true }, "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true }, "global_account_id": { "name": "global_account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false }, "global_email": { "name": "global_email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": false } }, @@ -632,10 +601,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -692,9 +658,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -702,9 +666,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -721,4 +683,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0025_snapshot.json b/packages/console/core/migrations/meta/0025_snapshot.json index 4b0cef0c0..6746a6e8c 100644 --- a/packages/console/core/migrations/meta/0025_snapshot.json +++ b/packages/console/core/migrations/meta/0025_snapshot.json @@ -48,9 +48,7 @@ "indexes": { "email": { "name": "email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": true } }, @@ -180,9 +178,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -190,10 +186,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -280,10 +273,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -398,10 +388,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -493,17 +480,12 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true }, "name": { "name": "name", - "columns": [ - "workspace_id", - "name" - ], + "columns": ["workspace_id", "name"], "isUnique": true } }, @@ -511,10 +493,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -606,32 +585,22 @@ "indexes": { "user_account_id": { "name": "user_account_id", - "columns": [ - "workspace_id", - "account_id" - ], + "columns": ["workspace_id", "account_id"], "isUnique": true }, "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true }, "global_account_id": { "name": "global_account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false }, "global_email": { "name": "global_email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": false } }, @@ -639,10 +608,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -699,9 +665,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -709,9 +673,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -728,4 +690,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0026_snapshot.json b/packages/console/core/migrations/meta/0026_snapshot.json index 543ab44c3..d3c7dc496 100644 --- a/packages/console/core/migrations/meta/0026_snapshot.json +++ b/packages/console/core/migrations/meta/0026_snapshot.json @@ -48,9 +48,7 @@ "indexes": { "email": { "name": "email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": true } }, @@ -180,9 +178,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -190,10 +186,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -280,10 +273,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -398,10 +388,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -493,9 +480,7 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true } }, @@ -503,10 +488,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -598,32 +580,22 @@ "indexes": { "user_account_id": { "name": "user_account_id", - "columns": [ - "workspace_id", - "account_id" - ], + "columns": ["workspace_id", "account_id"], "isUnique": true }, "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true }, "global_account_id": { "name": "global_account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false }, "global_email": { "name": "global_email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": false } }, @@ -631,10 +603,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -691,9 +660,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -701,9 +668,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -720,4 +685,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0027_snapshot.json b/packages/console/core/migrations/meta/0027_snapshot.json index 9b6910223..408766f71 100644 --- a/packages/console/core/migrations/meta/0027_snapshot.json +++ b/packages/console/core/migrations/meta/0027_snapshot.json @@ -48,9 +48,7 @@ "indexes": { "email": { "name": "email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": true } }, @@ -180,9 +178,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -190,10 +186,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -280,10 +273,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -398,10 +388,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -479,9 +466,7 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true } }, @@ -489,10 +474,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -584,32 +566,22 @@ "indexes": { "user_account_id": { "name": "user_account_id", - "columns": [ - "workspace_id", - "account_id" - ], + "columns": ["workspace_id", "account_id"], "isUnique": true }, "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true }, "global_account_id": { "name": "global_account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false }, "global_email": { "name": "global_email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": false } }, @@ -617,10 +589,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -677,9 +646,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -687,9 +654,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -706,4 +671,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0028_snapshot.json b/packages/console/core/migrations/meta/0028_snapshot.json index 8242ae52d..827cb53c5 100644 --- a/packages/console/core/migrations/meta/0028_snapshot.json +++ b/packages/console/core/migrations/meta/0028_snapshot.json @@ -48,9 +48,7 @@ "indexes": { "email": { "name": "email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": true } }, @@ -180,9 +178,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -190,10 +186,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -280,10 +273,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -398,10 +388,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -479,9 +466,7 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true } }, @@ -489,10 +474,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -584,32 +566,22 @@ "indexes": { "user_account_id": { "name": "user_account_id", - "columns": [ - "workspace_id", - "account_id" - ], + "columns": ["workspace_id", "account_id"], "isUnique": true }, "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true }, "global_account_id": { "name": "global_account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false }, "global_email": { "name": "global_email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": false } }, @@ -617,10 +589,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -677,9 +646,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -687,9 +654,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -706,4 +671,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0029_snapshot.json b/packages/console/core/migrations/meta/0029_snapshot.json index 959004f33..d235697cc 100644 --- a/packages/console/core/migrations/meta/0029_snapshot.json +++ b/packages/console/core/migrations/meta/0029_snapshot.json @@ -48,9 +48,7 @@ "indexes": { "email": { "name": "email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": true } }, @@ -180,9 +178,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -190,10 +186,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -280,10 +273,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -398,10 +388,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -479,9 +466,7 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true } }, @@ -489,10 +474,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -605,32 +587,22 @@ "indexes": { "user_account_id": { "name": "user_account_id", - "columns": [ - "workspace_id", - "account_id" - ], + "columns": ["workspace_id", "account_id"], "isUnique": true }, "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true }, "global_account_id": { "name": "global_account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false }, "global_email": { "name": "global_email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": false } }, @@ -638,10 +610,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -698,9 +667,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -708,9 +675,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -727,4 +692,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0030_snapshot.json b/packages/console/core/migrations/meta/0030_snapshot.json index 6a6eb38cb..66978dfa5 100644 --- a/packages/console/core/migrations/meta/0030_snapshot.json +++ b/packages/console/core/migrations/meta/0030_snapshot.json @@ -48,9 +48,7 @@ "indexes": { "email": { "name": "email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": true } }, @@ -180,9 +178,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -190,10 +186,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -280,10 +273,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -398,10 +388,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -479,9 +466,7 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true } }, @@ -489,10 +474,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -549,10 +531,7 @@ "indexes": { "model_workspace_model": { "name": "model_workspace_model", - "columns": [ - "workspace_id", - "model" - ], + "columns": ["workspace_id", "model"], "isUnique": true } }, @@ -560,10 +539,7 @@ "compositePrimaryKeys": { "model_workspace_id_id_pk": { "name": "model_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -676,32 +652,22 @@ "indexes": { "user_account_id": { "name": "user_account_id", - "columns": [ - "workspace_id", - "account_id" - ], + "columns": ["workspace_id", "account_id"], "isUnique": true }, "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true }, "global_account_id": { "name": "global_account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false }, "global_email": { "name": "global_email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": false } }, @@ -709,10 +675,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -769,9 +732,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -779,9 +740,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -798,4 +757,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0031_snapshot.json b/packages/console/core/migrations/meta/0031_snapshot.json index ba964881d..c47165925 100644 --- a/packages/console/core/migrations/meta/0031_snapshot.json +++ b/packages/console/core/migrations/meta/0031_snapshot.json @@ -48,9 +48,7 @@ "indexes": { "email": { "name": "email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": true } }, @@ -180,9 +178,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -190,10 +186,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -280,10 +273,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -398,10 +388,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -479,9 +466,7 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true } }, @@ -489,10 +474,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -549,10 +531,7 @@ "indexes": { "model_workspace_model": { "name": "model_workspace_model", - "columns": [ - "workspace_id", - "model" - ], + "columns": ["workspace_id", "model"], "isUnique": true } }, @@ -560,10 +539,7 @@ "compositePrimaryKeys": { "model_workspace_id_id_pk": { "name": "model_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -627,10 +603,7 @@ "indexes": { "workspace_provider": { "name": "workspace_provider", - "columns": [ - "workspace_id", - "provider" - ], + "columns": ["workspace_id", "provider"], "isUnique": true } }, @@ -638,10 +611,7 @@ "compositePrimaryKeys": { "provider_workspace_id_id_pk": { "name": "provider_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -754,32 +724,22 @@ "indexes": { "user_account_id": { "name": "user_account_id", - "columns": [ - "workspace_id", - "account_id" - ], + "columns": ["workspace_id", "account_id"], "isUnique": true }, "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true }, "global_account_id": { "name": "global_account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false }, "global_email": { "name": "global_email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": false } }, @@ -787,10 +747,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -847,9 +804,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -857,9 +812,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -876,4 +829,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0032_snapshot.json b/packages/console/core/migrations/meta/0032_snapshot.json index 344fde6fd..51e84a1d3 100644 --- a/packages/console/core/migrations/meta/0032_snapshot.json +++ b/packages/console/core/migrations/meta/0032_snapshot.json @@ -48,9 +48,7 @@ "indexes": { "email": { "name": "email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": true } }, @@ -180,9 +178,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -190,10 +186,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -280,10 +273,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -405,10 +395,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -486,9 +473,7 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true } }, @@ -496,10 +481,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -556,10 +538,7 @@ "indexes": { "model_workspace_model": { "name": "model_workspace_model", - "columns": [ - "workspace_id", - "model" - ], + "columns": ["workspace_id", "model"], "isUnique": true } }, @@ -567,10 +546,7 @@ "compositePrimaryKeys": { "model_workspace_id_id_pk": { "name": "model_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -634,10 +610,7 @@ "indexes": { "workspace_provider": { "name": "workspace_provider", - "columns": [ - "workspace_id", - "provider" - ], + "columns": ["workspace_id", "provider"], "isUnique": true } }, @@ -645,10 +618,7 @@ "compositePrimaryKeys": { "provider_workspace_id_id_pk": { "name": "provider_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -761,32 +731,22 @@ "indexes": { "user_account_id": { "name": "user_account_id", - "columns": [ - "workspace_id", - "account_id" - ], + "columns": ["workspace_id", "account_id"], "isUnique": true }, "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true }, "global_account_id": { "name": "global_account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false }, "global_email": { "name": "global_email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": false } }, @@ -794,10 +754,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -854,9 +811,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -864,9 +819,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -883,4 +836,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0033_snapshot.json b/packages/console/core/migrations/meta/0033_snapshot.json index eb682adca..76d4720e8 100644 --- a/packages/console/core/migrations/meta/0033_snapshot.json +++ b/packages/console/core/migrations/meta/0033_snapshot.json @@ -48,9 +48,7 @@ "indexes": { "email": { "name": "email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": true } }, @@ -187,9 +185,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -197,10 +193,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -287,10 +280,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -412,10 +402,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -493,9 +480,7 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true } }, @@ -503,10 +488,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -563,10 +545,7 @@ "indexes": { "model_workspace_model": { "name": "model_workspace_model", - "columns": [ - "workspace_id", - "model" - ], + "columns": ["workspace_id", "model"], "isUnique": true } }, @@ -574,10 +553,7 @@ "compositePrimaryKeys": { "model_workspace_id_id_pk": { "name": "model_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -641,10 +617,7 @@ "indexes": { "workspace_provider": { "name": "workspace_provider", - "columns": [ - "workspace_id", - "provider" - ], + "columns": ["workspace_id", "provider"], "isUnique": true } }, @@ -652,10 +625,7 @@ "compositePrimaryKeys": { "provider_workspace_id_id_pk": { "name": "provider_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -768,32 +738,22 @@ "indexes": { "user_account_id": { "name": "user_account_id", - "columns": [ - "workspace_id", - "account_id" - ], + "columns": ["workspace_id", "account_id"], "isUnique": true }, "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true }, "global_account_id": { "name": "global_account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false }, "global_email": { "name": "global_email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": false } }, @@ -801,10 +761,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -861,9 +818,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -871,9 +826,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -890,4 +843,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0034_snapshot.json b/packages/console/core/migrations/meta/0034_snapshot.json index 36acbdef4..e9c999be7 100644 --- a/packages/console/core/migrations/meta/0034_snapshot.json +++ b/packages/console/core/migrations/meta/0034_snapshot.json @@ -48,9 +48,7 @@ "indexes": { "email": { "name": "email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": true } }, @@ -117,10 +115,7 @@ "indexes": { "provider": { "name": "provider", - "columns": [ - "provider", - "subject" - ], + "columns": ["provider", "subject"], "isUnique": true } }, @@ -257,9 +252,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -267,10 +260,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -357,10 +347,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -482,10 +469,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -563,9 +547,7 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true } }, @@ -573,10 +555,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -633,10 +612,7 @@ "indexes": { "model_workspace_model": { "name": "model_workspace_model", - "columns": [ - "workspace_id", - "model" - ], + "columns": ["workspace_id", "model"], "isUnique": true } }, @@ -644,10 +620,7 @@ "compositePrimaryKeys": { "model_workspace_id_id_pk": { "name": "model_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -711,10 +684,7 @@ "indexes": { "workspace_provider": { "name": "workspace_provider", - "columns": [ - "workspace_id", - "provider" - ], + "columns": ["workspace_id", "provider"], "isUnique": true } }, @@ -722,10 +692,7 @@ "compositePrimaryKeys": { "provider_workspace_id_id_pk": { "name": "provider_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -838,32 +805,22 @@ "indexes": { "user_account_id": { "name": "user_account_id", - "columns": [ - "workspace_id", - "account_id" - ], + "columns": ["workspace_id", "account_id"], "isUnique": true }, "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true }, "global_account_id": { "name": "global_account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false }, "global_email": { "name": "global_email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": false } }, @@ -871,10 +828,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -931,9 +885,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -941,9 +893,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -960,4 +910,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0035_snapshot.json b/packages/console/core/migrations/meta/0035_snapshot.json index 7478337b5..815d120ea 100644 --- a/packages/console/core/migrations/meta/0035_snapshot.json +++ b/packages/console/core/migrations/meta/0035_snapshot.json @@ -102,17 +102,12 @@ "indexes": { "provider": { "name": "provider", - "columns": [ - "provider", - "subject" - ], + "columns": ["provider", "subject"], "isUnique": true }, "account_id": { "name": "account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false } }, @@ -249,9 +244,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -259,10 +252,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -349,10 +339,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -474,10 +461,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -555,9 +539,7 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true } }, @@ -565,10 +547,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -625,10 +604,7 @@ "indexes": { "model_workspace_model": { "name": "model_workspace_model", - "columns": [ - "workspace_id", - "model" - ], + "columns": ["workspace_id", "model"], "isUnique": true } }, @@ -636,10 +612,7 @@ "compositePrimaryKeys": { "model_workspace_id_id_pk": { "name": "model_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -703,10 +676,7 @@ "indexes": { "workspace_provider": { "name": "workspace_provider", - "columns": [ - "workspace_id", - "provider" - ], + "columns": ["workspace_id", "provider"], "isUnique": true } }, @@ -714,10 +684,7 @@ "compositePrimaryKeys": { "provider_workspace_id_id_pk": { "name": "provider_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -830,32 +797,22 @@ "indexes": { "user_account_id": { "name": "user_account_id", - "columns": [ - "workspace_id", - "account_id" - ], + "columns": ["workspace_id", "account_id"], "isUnique": true }, "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true }, "global_account_id": { "name": "global_account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false }, "global_email": { "name": "global_email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": false } }, @@ -863,10 +820,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -923,9 +877,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -933,9 +885,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -952,4 +902,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0036_snapshot.json b/packages/console/core/migrations/meta/0036_snapshot.json index b030e30ea..926b143eb 100644 --- a/packages/console/core/migrations/meta/0036_snapshot.json +++ b/packages/console/core/migrations/meta/0036_snapshot.json @@ -43,9 +43,7 @@ "compositePrimaryKeys": { "account_id_pk": { "name": "account_id_pk", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -109,17 +107,12 @@ "indexes": { "provider": { "name": "provider", - "columns": [ - "provider", - "subject" - ], + "columns": ["provider", "subject"], "isUnique": true }, "account_id": { "name": "account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false } }, @@ -127,9 +120,7 @@ "compositePrimaryKeys": { "auth_id_pk": { "name": "auth_id_pk", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -263,9 +254,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -273,10 +262,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -363,10 +349,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -488,10 +471,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -569,9 +549,7 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true } }, @@ -579,10 +557,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -639,10 +614,7 @@ "indexes": { "model_workspace_model": { "name": "model_workspace_model", - "columns": [ - "workspace_id", - "model" - ], + "columns": ["workspace_id", "model"], "isUnique": true } }, @@ -650,10 +622,7 @@ "compositePrimaryKeys": { "model_workspace_id_id_pk": { "name": "model_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -717,10 +686,7 @@ "indexes": { "workspace_provider": { "name": "workspace_provider", - "columns": [ - "workspace_id", - "provider" - ], + "columns": ["workspace_id", "provider"], "isUnique": true } }, @@ -728,10 +694,7 @@ "compositePrimaryKeys": { "provider_workspace_id_id_pk": { "name": "provider_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -844,32 +807,22 @@ "indexes": { "user_account_id": { "name": "user_account_id", - "columns": [ - "workspace_id", - "account_id" - ], + "columns": ["workspace_id", "account_id"], "isUnique": true }, "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true }, "global_account_id": { "name": "global_account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false }, "global_email": { "name": "global_email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": false } }, @@ -877,10 +830,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -937,9 +887,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -947,9 +895,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -966,4 +912,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/0037_snapshot.json b/packages/console/core/migrations/meta/0037_snapshot.json index 690bae87a..8a80ea522 100644 --- a/packages/console/core/migrations/meta/0037_snapshot.json +++ b/packages/console/core/migrations/meta/0037_snapshot.json @@ -43,9 +43,7 @@ "compositePrimaryKeys": { "account_id_pk": { "name": "account_id_pk", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -109,17 +107,12 @@ "indexes": { "provider": { "name": "provider", - "columns": [ - "provider", - "subject" - ], + "columns": ["provider", "subject"], "isUnique": true }, "account_id": { "name": "account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false } }, @@ -127,9 +120,7 @@ "compositePrimaryKeys": { "auth_id_pk": { "name": "auth_id_pk", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -277,9 +268,7 @@ "indexes": { "global_customer_id": { "name": "global_customer_id", - "columns": [ - "customer_id" - ], + "columns": ["customer_id"], "isUnique": true } }, @@ -287,10 +276,7 @@ "compositePrimaryKeys": { "billing_workspace_id_id_pk": { "name": "billing_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -377,10 +363,7 @@ "compositePrimaryKeys": { "payment_workspace_id_id_pk": { "name": "payment_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -502,10 +485,7 @@ "compositePrimaryKeys": { "usage_workspace_id_id_pk": { "name": "usage_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -583,9 +563,7 @@ "indexes": { "global_key": { "name": "global_key", - "columns": [ - "key" - ], + "columns": ["key"], "isUnique": true } }, @@ -593,10 +571,7 @@ "compositePrimaryKeys": { "key_workspace_id_id_pk": { "name": "key_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -653,10 +628,7 @@ "indexes": { "model_workspace_model": { "name": "model_workspace_model", - "columns": [ - "workspace_id", - "model" - ], + "columns": ["workspace_id", "model"], "isUnique": true } }, @@ -664,10 +636,7 @@ "compositePrimaryKeys": { "model_workspace_id_id_pk": { "name": "model_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -731,10 +700,7 @@ "indexes": { "workspace_provider": { "name": "workspace_provider", - "columns": [ - "workspace_id", - "provider" - ], + "columns": ["workspace_id", "provider"], "isUnique": true } }, @@ -742,10 +708,7 @@ "compositePrimaryKeys": { "provider_workspace_id_id_pk": { "name": "provider_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -858,32 +821,22 @@ "indexes": { "user_account_id": { "name": "user_account_id", - "columns": [ - "workspace_id", - "account_id" - ], + "columns": ["workspace_id", "account_id"], "isUnique": true }, "user_email": { "name": "user_email", - "columns": [ - "workspace_id", - "email" - ], + "columns": ["workspace_id", "email"], "isUnique": true }, "global_account_id": { "name": "global_account_id", - "columns": [ - "account_id" - ], + "columns": ["account_id"], "isUnique": false }, "global_email": { "name": "global_email", - "columns": [ - "email" - ], + "columns": ["email"], "isUnique": false } }, @@ -891,10 +844,7 @@ "compositePrimaryKeys": { "user_workspace_id_id_pk": { "name": "user_workspace_id_id_pk", - "columns": [ - "workspace_id", - "id" - ] + "columns": ["workspace_id", "id"] } }, "uniqueConstraints": {}, @@ -951,9 +901,7 @@ "indexes": { "slug": { "name": "slug", - "columns": [ - "slug" - ], + "columns": ["slug"], "isUnique": true } }, @@ -961,9 +909,7 @@ "compositePrimaryKeys": { "workspace_id": { "name": "workspace_id", - "columns": [ - "id" - ] + "columns": ["id"] } }, "uniqueConstraints": {}, @@ -980,4 +926,4 @@ "tables": {}, "indexes": {} } -}
\ No newline at end of file +} diff --git a/packages/console/core/migrations/meta/_journal.json b/packages/console/core/migrations/meta/_journal.json index f2c6c6fc5..250fe59b3 100644 --- a/packages/console/core/migrations/meta/_journal.json +++ b/packages/console/core/migrations/meta/_journal.json @@ -269,4 +269,4 @@ "breakpoints": true } ] -}
\ No newline at end of file +} diff --git a/packages/console/core/src/aws.ts b/packages/console/core/src/aws.ts index e87ada6ef..ce4a20f44 100644 --- a/packages/console/core/src/aws.ts +++ b/packages/console/core/src/aws.ts @@ -24,37 +24,40 @@ export namespace AWS { body: z.string(), }), async (input) => { - const res = await createClient().fetch("https://email.us-east-1.amazonaws.com/v2/email/outbound-emails", { - method: "POST", - headers: { - "X-Amz-Target": "SES.SendEmail", - "Content-Type": "application/json", - }, - body: JSON.stringify({ - FromEmailAddress: `OpenCode Zen <[email protected]>`, - Destination: { - ToAddresses: [input.to], + const res = await createClient().fetch( + "https://email.us-east-1.amazonaws.com/v2/email/outbound-emails", + { + method: "POST", + headers: { + "X-Amz-Target": "SES.SendEmail", + "Content-Type": "application/json", }, - Content: { - Simple: { - Subject: { - Charset: "UTF-8", - Data: input.subject, - }, - Body: { - Text: { + body: JSON.stringify({ + FromEmailAddress: `OpenCode Zen <[email protected]>`, + Destination: { + ToAddresses: [input.to], + }, + Content: { + Simple: { + Subject: { Charset: "UTF-8", - Data: input.body, + Data: input.subject, }, - Html: { - Charset: "UTF-8", - Data: input.body, + Body: { + Text: { + Charset: "UTF-8", + Data: input.body, + }, + Html: { + Charset: "UTF-8", + Data: input.body, + }, }, }, }, - }, - }), - }) + }), + }, + ) if (!res.ok) { throw new Error(`Failed to send email: ${res.statusText}`) } diff --git a/packages/console/core/src/drizzle/index.ts b/packages/console/core/src/drizzle/index.ts index f0f065de4..8b37b1f9c 100644 --- a/packages/console/core/src/drizzle/index.ts +++ b/packages/console/core/src/drizzle/index.ts @@ -5,7 +5,10 @@ import { Client } from "@planetscale/database" import { MySqlTransaction, type MySqlTransactionConfig } from "drizzle-orm/mysql-core" import type { ExtractTablesWithRelations } from "drizzle-orm" -import type { PlanetScalePreparedQueryHKT, PlanetscaleQueryResultHKT } from "drizzle-orm/planetscale-serverless" +import type { + PlanetScalePreparedQueryHKT, + PlanetscaleQueryResultHKT, +} from "drizzle-orm/planetscale-serverless" import { Context } from "../context" import { memo } from "../util/memo" @@ -67,7 +70,10 @@ export namespace Database { } } - export async function transaction<T>(callback: (tx: TxOrDb) => Promise<T>, config?: MySqlTransactionConfig) { + export async function transaction<T>( + callback: (tx: TxOrDb) => Promise<T>, + config?: MySqlTransactionConfig, + ) { try { const { tx } = TransactionContext.use() return callback(tx) diff --git a/packages/console/core/src/key.ts b/packages/console/core/src/key.ts index 688f19b3d..6396fd0b8 100644 --- a/packages/console/core/src/key.ts +++ b/packages/console/core/src/key.ts @@ -20,8 +20,14 @@ export namespace Key { email: AuthTable.subject, }) .from(KeyTable) - .innerJoin(UserTable, and(eq(KeyTable.userID, UserTable.id), eq(KeyTable.workspaceID, UserTable.workspaceID))) - .innerJoin(AuthTable, and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email"))) + .innerJoin( + UserTable, + and(eq(KeyTable.userID, UserTable.id), eq(KeyTable.workspaceID, UserTable.workspaceID)), + ) + .innerJoin( + AuthTable, + and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email")), + ) .where( and( ...[ diff --git a/packages/console/core/src/provider.ts b/packages/console/core/src/provider.ts index cf2040b59..0af642f71 100644 --- a/packages/console/core/src/provider.ts +++ b/packages/console/core/src/provider.ts @@ -11,7 +11,9 @@ export namespace Provider { tx .select() .from(ProviderTable) - .where(and(eq(ProviderTable.workspaceID, Actor.workspace()), isNull(ProviderTable.timeDeleted))), + .where( + and(eq(ProviderTable.workspaceID, Actor.workspace()), isNull(ProviderTable.timeDeleted)), + ), ), ) @@ -50,7 +52,12 @@ export namespace Provider { return Database.transaction((tx) => tx .delete(ProviderTable) - .where(and(eq(ProviderTable.provider, provider), eq(ProviderTable.workspaceID, Actor.workspace()))), + .where( + and( + eq(ProviderTable.provider, provider), + eq(ProviderTable.workspaceID, Actor.workspace()), + ), + ), ) }, ) diff --git a/packages/console/core/src/schema/auth.sql.ts b/packages/console/core/src/schema/auth.sql.ts index 27c926d6f..d55e605aa 100644 --- a/packages/console/core/src/schema/auth.sql.ts +++ b/packages/console/core/src/schema/auth.sql.ts @@ -1,4 +1,11 @@ -import { index, mysqlEnum, mysqlTable, primaryKey, uniqueIndex, varchar } from "drizzle-orm/mysql-core" +import { + index, + mysqlEnum, + mysqlTable, + primaryKey, + uniqueIndex, + varchar, +} from "drizzle-orm/mysql-core" import { id, timestamps, ulid } from "../drizzle/types" export const AuthProvider = ["email", "github", "google"] as const diff --git a/packages/console/core/src/schema/model.sql.ts b/packages/console/core/src/schema/model.sql.ts index 1c032aad2..343b0c4f3 100644 --- a/packages/console/core/src/schema/model.sql.ts +++ b/packages/console/core/src/schema/model.sql.ts @@ -9,5 +9,8 @@ export const ModelTable = mysqlTable( ...timestamps, model: varchar("model", { length: 64 }).notNull(), }, - (table) => [...workspaceIndexes(table), uniqueIndex("model_workspace_model").on(table.workspaceID, table.model)], + (table) => [ + ...workspaceIndexes(table), + uniqueIndex("model_workspace_model").on(table.workspaceID, table.model), + ], ) diff --git a/packages/console/core/src/schema/provider.sql.ts b/packages/console/core/src/schema/provider.sql.ts index 11be5b4d7..04d11e2e5 100644 --- a/packages/console/core/src/schema/provider.sql.ts +++ b/packages/console/core/src/schema/provider.sql.ts @@ -10,5 +10,8 @@ export const ProviderTable = mysqlTable( provider: varchar("provider", { length: 64 }).notNull(), credentials: text("credentials").notNull(), }, - (table) => [...workspaceIndexes(table), uniqueIndex("workspace_provider").on(table.workspaceID, table.provider)], + (table) => [ + ...workspaceIndexes(table), + uniqueIndex("workspace_provider").on(table.workspaceID, table.provider), + ], ) diff --git a/packages/console/core/src/schema/user.sql.ts b/packages/console/core/src/schema/user.sql.ts index 7fd7f5e1e..ce5b6c53e 100644 --- a/packages/console/core/src/schema/user.sql.ts +++ b/packages/console/core/src/schema/user.sql.ts @@ -1,4 +1,12 @@ -import { mysqlTable, uniqueIndex, varchar, int, mysqlEnum, index, bigint } from "drizzle-orm/mysql-core" +import { + mysqlTable, + uniqueIndex, + varchar, + int, + mysqlEnum, + index, + bigint, +} from "drizzle-orm/mysql-core" import { timestamps, ulid, utc, workspaceColumns } from "../drizzle/types" import { workspaceIndexes } from "./workspace.sql" diff --git a/packages/console/core/src/user.ts b/packages/console/core/src/user.ts index 8b7a96f44..cbb1ac827 100644 --- a/packages/console/core/src/user.ts +++ b/packages/console/core/src/user.ts @@ -26,7 +26,10 @@ export namespace User { authEmail: AuthTable.subject, }) .from(UserTable) - .leftJoin(AuthTable, and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email"))) + .leftJoin( + AuthTable, + and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email")), + ) .where(and(eq(UserTable.workspaceID, Actor.workspace()), isNull(UserTable.timeDeleted))), ), ) @@ -36,7 +39,13 @@ export namespace User { tx .select() .from(UserTable) - .where(and(eq(UserTable.workspaceID, Actor.workspace()), eq(UserTable.id, id), isNull(UserTable.timeDeleted))) + .where( + and( + eq(UserTable.workspaceID, Actor.workspace()), + eq(UserTable.id, id), + isNull(UserTable.timeDeleted), + ), + ) .then((rows) => rows[0]), ), ) @@ -48,7 +57,10 @@ export namespace User { email: AuthTable.subject, }) .from(UserTable) - .leftJoin(AuthTable, and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email"))) + .leftJoin( + AuthTable, + and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email")), + ) .where(and(eq(UserTable.workspaceID, Actor.workspace()), eq(UserTable.id, id))) .then((rows) => rows[0]?.email), ), @@ -130,10 +142,16 @@ export namespace User { workspaceName: WorkspaceTable.name, }) .from(UserTable) - .innerJoin(AuthTable, and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email"))) + .innerJoin( + AuthTable, + and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email")), + ) .innerJoin(WorkspaceTable, eq(WorkspaceTable.id, workspaceID)) .where( - and(eq(UserTable.workspaceID, workspaceID), eq(UserTable.id, Actor.assert("user").properties.userID)), + and( + eq(UserTable.workspaceID, workspaceID), + eq(UserTable.id, Actor.assert("user").properties.userID), + ), ) .then((rows) => rows[0]), ) diff --git a/packages/console/core/sst-env.d.ts b/packages/console/core/sst-env.d.ts index 01407434e..ba4c5a623 100644 --- a/packages/console/core/sst-env.d.ts +++ b/packages/console/core/sst-env.d.ts @@ -6,99 +6,99 @@ import "sst" declare module "sst" { export interface Resource { - "ADMIN_SECRET": { - "type": "sst.sst.Secret" - "value": string - } - "AUTH_API_URL": { - "type": "sst.sst.Linkable" - "value": string - } - "AWS_SES_ACCESS_KEY_ID": { - "type": "sst.sst.Secret" - "value": string - } - "AWS_SES_SECRET_ACCESS_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "Console": { - "type": "sst.cloudflare.SolidStart" - "url": string - } - "Database": { - "database": string - "host": string - "password": string - "port": number - "type": "sst.sst.Linkable" - "username": string - } - "Desktop": { - "type": "sst.cloudflare.StaticSite" - "url": string - } - "EMAILOCTOPUS_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_ID": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_PRIVATE_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_ID_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_SECRET_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GOOGLE_CLIENT_ID": { - "type": "sst.sst.Secret" - "value": string - } - "HONEYCOMB_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_SECRET_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_WEBHOOK_SECRET": { - "type": "sst.sst.Linkable" - "value": string - } - "Web": { - "type": "sst.cloudflare.Astro" - "url": string - } - "ZEN_MODELS1": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS2": { - "type": "sst.sst.Secret" - "value": string + ADMIN_SECRET: { + type: "sst.sst.Secret" + value: string + } + AUTH_API_URL: { + type: "sst.sst.Linkable" + value: string + } + AWS_SES_ACCESS_KEY_ID: { + type: "sst.sst.Secret" + value: string + } + AWS_SES_SECRET_ACCESS_KEY: { + type: "sst.sst.Secret" + value: string + } + Console: { + type: "sst.cloudflare.SolidStart" + url: string + } + Database: { + database: string + host: string + password: string + port: number + type: "sst.sst.Linkable" + username: string + } + Desktop: { + type: "sst.cloudflare.StaticSite" + url: string + } + EMAILOCTOPUS_API_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_ID: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_PRIVATE_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_ID_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_SECRET_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GOOGLE_CLIENT_ID: { + type: "sst.sst.Secret" + value: string + } + HONEYCOMB_API_KEY: { + type: "sst.sst.Secret" + value: string + } + STRIPE_SECRET_KEY: { + type: "sst.sst.Secret" + value: string + } + STRIPE_WEBHOOK_SECRET: { + type: "sst.sst.Linkable" + value: string + } + Web: { + type: "sst.cloudflare.Astro" + url: string + } + ZEN_MODELS1: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS2: { + type: "sst.sst.Secret" + value: string } } } -// cloudflare -import * as cloudflare from "@cloudflare/workers-types"; +// cloudflare +import * as cloudflare from "@cloudflare/workers-types" declare module "sst" { export interface Resource { - "Api": cloudflare.Service - "AuthApi": cloudflare.Service - "AuthStorage": cloudflare.KVNamespace - "Bucket": cloudflare.R2Bucket - "LogProcessor": cloudflare.Service + Api: cloudflare.Service + AuthApi: cloudflare.Service + AuthStorage: cloudflare.KVNamespace + Bucket: cloudflare.R2Bucket + LogProcessor: cloudflare.Service } } import "sst" -export {}
\ No newline at end of file +export {} diff --git a/packages/console/function/sst-env.d.ts b/packages/console/function/sst-env.d.ts index 01407434e..ba4c5a623 100644 --- a/packages/console/function/sst-env.d.ts +++ b/packages/console/function/sst-env.d.ts @@ -6,99 +6,99 @@ import "sst" declare module "sst" { export interface Resource { - "ADMIN_SECRET": { - "type": "sst.sst.Secret" - "value": string - } - "AUTH_API_URL": { - "type": "sst.sst.Linkable" - "value": string - } - "AWS_SES_ACCESS_KEY_ID": { - "type": "sst.sst.Secret" - "value": string - } - "AWS_SES_SECRET_ACCESS_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "Console": { - "type": "sst.cloudflare.SolidStart" - "url": string - } - "Database": { - "database": string - "host": string - "password": string - "port": number - "type": "sst.sst.Linkable" - "username": string - } - "Desktop": { - "type": "sst.cloudflare.StaticSite" - "url": string - } - "EMAILOCTOPUS_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_ID": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_PRIVATE_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_ID_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_SECRET_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GOOGLE_CLIENT_ID": { - "type": "sst.sst.Secret" - "value": string - } - "HONEYCOMB_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_SECRET_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_WEBHOOK_SECRET": { - "type": "sst.sst.Linkable" - "value": string - } - "Web": { - "type": "sst.cloudflare.Astro" - "url": string - } - "ZEN_MODELS1": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS2": { - "type": "sst.sst.Secret" - "value": string + ADMIN_SECRET: { + type: "sst.sst.Secret" + value: string + } + AUTH_API_URL: { + type: "sst.sst.Linkable" + value: string + } + AWS_SES_ACCESS_KEY_ID: { + type: "sst.sst.Secret" + value: string + } + AWS_SES_SECRET_ACCESS_KEY: { + type: "sst.sst.Secret" + value: string + } + Console: { + type: "sst.cloudflare.SolidStart" + url: string + } + Database: { + database: string + host: string + password: string + port: number + type: "sst.sst.Linkable" + username: string + } + Desktop: { + type: "sst.cloudflare.StaticSite" + url: string + } + EMAILOCTOPUS_API_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_ID: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_PRIVATE_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_ID_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_SECRET_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GOOGLE_CLIENT_ID: { + type: "sst.sst.Secret" + value: string + } + HONEYCOMB_API_KEY: { + type: "sst.sst.Secret" + value: string + } + STRIPE_SECRET_KEY: { + type: "sst.sst.Secret" + value: string + } + STRIPE_WEBHOOK_SECRET: { + type: "sst.sst.Linkable" + value: string + } + Web: { + type: "sst.cloudflare.Astro" + url: string + } + ZEN_MODELS1: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS2: { + type: "sst.sst.Secret" + value: string } } } -// cloudflare -import * as cloudflare from "@cloudflare/workers-types"; +// cloudflare +import * as cloudflare from "@cloudflare/workers-types" declare module "sst" { export interface Resource { - "Api": cloudflare.Service - "AuthApi": cloudflare.Service - "AuthStorage": cloudflare.KVNamespace - "Bucket": cloudflare.R2Bucket - "LogProcessor": cloudflare.Service + Api: cloudflare.Service + AuthApi: cloudflare.Service + AuthStorage: cloudflare.KVNamespace + Bucket: cloudflare.R2Bucket + LogProcessor: cloudflare.Service } } import "sst" -export {}
\ No newline at end of file +export {} diff --git a/packages/console/mail/emails/templates/InviteEmail.tsx b/packages/console/mail/emails/templates/InviteEmail.tsx index baf0d383f..e94eb564c 100644 --- a/packages/console/mail/emails/templates/InviteEmail.tsx +++ b/packages/console/mail/emails/templates/InviteEmail.tsx @@ -1,6 +1,18 @@ // @ts-nocheck import React from "react" -import { Img, Row, Html, Link, Body, Head, Button, Column, Preview, Section, Container } from "@jsx-email/all" +import { + Img, + Row, + Html, + Link, + Body, + Head, + Button, + Column, + Preview, + Section, + Container, +} from "@jsx-email/all" import { Text, Fonts, Title, A, Span } from "../components" import { unit, @@ -52,8 +64,8 @@ export const InviteEmail = ({ <Section style={{ padding: `${unit * 2}px 0 0 0` }}> <Text style={headingText}>Join your team's OpenCode workspace</Text> <Text style={contentText}> - You have been invited by <Span style={contentHighlightText}>{inviter}</Span> to join the{" "} - <Span style={contentHighlightText}>{workspaceName}</Span> workspace on OpenCode. + You have been invited by <Span style={contentHighlightText}>{inviter}</Span> to join + the <Span style={contentHighlightText}>{workspaceName}</Span> workspace on OpenCode. </Text> </Section> @@ -61,7 +73,12 @@ export const InviteEmail = ({ <Button style={button} href={url}> <Text style={buttonText}> Join workspace - <Img width="24" height="24" src={`${assetsUrl}/right-arrow.png`} alt="Arrow right" /> + <Img + width="24" + height="24" + src={`${assetsUrl}/right-arrow.png`} + alt="Arrow right" + /> </Text> </Button> </Section> diff --git a/packages/console/mail/sst-env.d.ts b/packages/console/mail/sst-env.d.ts index 9b9de7327..bd5588217 100644 --- a/packages/console/mail/sst-env.d.ts +++ b/packages/console/mail/sst-env.d.ts @@ -6,4 +6,4 @@ /// <reference path="../../../sst-env.d.ts" /> import "sst" -export {}
\ No newline at end of file +export {} diff --git a/packages/console/resource/sst-env.d.ts b/packages/console/resource/sst-env.d.ts index 01407434e..ba4c5a623 100644 --- a/packages/console/resource/sst-env.d.ts +++ b/packages/console/resource/sst-env.d.ts @@ -6,99 +6,99 @@ import "sst" declare module "sst" { export interface Resource { - "ADMIN_SECRET": { - "type": "sst.sst.Secret" - "value": string - } - "AUTH_API_URL": { - "type": "sst.sst.Linkable" - "value": string - } - "AWS_SES_ACCESS_KEY_ID": { - "type": "sst.sst.Secret" - "value": string - } - "AWS_SES_SECRET_ACCESS_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "Console": { - "type": "sst.cloudflare.SolidStart" - "url": string - } - "Database": { - "database": string - "host": string - "password": string - "port": number - "type": "sst.sst.Linkable" - "username": string - } - "Desktop": { - "type": "sst.cloudflare.StaticSite" - "url": string - } - "EMAILOCTOPUS_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_ID": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_PRIVATE_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_ID_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_SECRET_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GOOGLE_CLIENT_ID": { - "type": "sst.sst.Secret" - "value": string - } - "HONEYCOMB_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_SECRET_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_WEBHOOK_SECRET": { - "type": "sst.sst.Linkable" - "value": string - } - "Web": { - "type": "sst.cloudflare.Astro" - "url": string - } - "ZEN_MODELS1": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS2": { - "type": "sst.sst.Secret" - "value": string + ADMIN_SECRET: { + type: "sst.sst.Secret" + value: string + } + AUTH_API_URL: { + type: "sst.sst.Linkable" + value: string + } + AWS_SES_ACCESS_KEY_ID: { + type: "sst.sst.Secret" + value: string + } + AWS_SES_SECRET_ACCESS_KEY: { + type: "sst.sst.Secret" + value: string + } + Console: { + type: "sst.cloudflare.SolidStart" + url: string + } + Database: { + database: string + host: string + password: string + port: number + type: "sst.sst.Linkable" + username: string + } + Desktop: { + type: "sst.cloudflare.StaticSite" + url: string + } + EMAILOCTOPUS_API_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_ID: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_PRIVATE_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_ID_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_SECRET_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GOOGLE_CLIENT_ID: { + type: "sst.sst.Secret" + value: string + } + HONEYCOMB_API_KEY: { + type: "sst.sst.Secret" + value: string + } + STRIPE_SECRET_KEY: { + type: "sst.sst.Secret" + value: string + } + STRIPE_WEBHOOK_SECRET: { + type: "sst.sst.Linkable" + value: string + } + Web: { + type: "sst.cloudflare.Astro" + url: string + } + ZEN_MODELS1: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS2: { + type: "sst.sst.Secret" + value: string } } } -// cloudflare -import * as cloudflare from "@cloudflare/workers-types"; +// cloudflare +import * as cloudflare from "@cloudflare/workers-types" declare module "sst" { export interface Resource { - "Api": cloudflare.Service - "AuthApi": cloudflare.Service - "AuthStorage": cloudflare.KVNamespace - "Bucket": cloudflare.R2Bucket - "LogProcessor": cloudflare.Service + Api: cloudflare.Service + AuthApi: cloudflare.Service + AuthStorage: cloudflare.KVNamespace + Bucket: cloudflare.R2Bucket + LogProcessor: cloudflare.Service } } import "sst" -export {}
\ No newline at end of file +export {} diff --git a/packages/desktop/src/sst-env.d.ts b/packages/desktop/src/sst-env.d.ts index 47a8fbec7..1b1683a1e 100644 --- a/packages/desktop/src/sst-env.d.ts +++ b/packages/desktop/src/sst-env.d.ts @@ -2,9 +2,7 @@ /* tslint:disable */ /* eslint-disable */ /// <reference types="vite/client" /> -interface ImportMetaEnv { - -} +interface ImportMetaEnv {} interface ImportMeta { readonly env: ImportMetaEnv -}
\ No newline at end of file +} diff --git a/packages/desktop/sst-env.d.ts b/packages/desktop/sst-env.d.ts index b6a7e9066..0397645b5 100644 --- a/packages/desktop/sst-env.d.ts +++ b/packages/desktop/sst-env.d.ts @@ -6,4 +6,4 @@ /// <reference path="../../sst-env.d.ts" /> import "sst" -export {}
\ No newline at end of file +export {} diff --git a/packages/function/src/api.ts b/packages/function/src/api.ts index 6f00dae9a..3475f5d72 100644 --- a/packages/function/src/api.ts +++ b/packages/function/src/api.ts @@ -268,7 +268,11 @@ export default new Hono<{ Bindings: Env }>() // Verify permissions const userClient = new Octokit({ auth: token }) const { data: repoData } = await userClient.repos.get({ owner, repo }) - if (!repoData.permissions.admin && !repoData.permissions.push && !repoData.permissions.maintain) + if ( + !repoData.permissions.admin && + !repoData.permissions.push && + !repoData.permissions.maintain + ) throw new Error("User does not have write permissions") // Get installation token diff --git a/packages/function/sst-env.d.ts b/packages/function/sst-env.d.ts index 01407434e..ba4c5a623 100644 --- a/packages/function/sst-env.d.ts +++ b/packages/function/sst-env.d.ts @@ -6,99 +6,99 @@ import "sst" declare module "sst" { export interface Resource { - "ADMIN_SECRET": { - "type": "sst.sst.Secret" - "value": string - } - "AUTH_API_URL": { - "type": "sst.sst.Linkable" - "value": string - } - "AWS_SES_ACCESS_KEY_ID": { - "type": "sst.sst.Secret" - "value": string - } - "AWS_SES_SECRET_ACCESS_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "Console": { - "type": "sst.cloudflare.SolidStart" - "url": string - } - "Database": { - "database": string - "host": string - "password": string - "port": number - "type": "sst.sst.Linkable" - "username": string - } - "Desktop": { - "type": "sst.cloudflare.StaticSite" - "url": string - } - "EMAILOCTOPUS_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_ID": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_APP_PRIVATE_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_ID_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GITHUB_CLIENT_SECRET_CONSOLE": { - "type": "sst.sst.Secret" - "value": string - } - "GOOGLE_CLIENT_ID": { - "type": "sst.sst.Secret" - "value": string - } - "HONEYCOMB_API_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_SECRET_KEY": { - "type": "sst.sst.Secret" - "value": string - } - "STRIPE_WEBHOOK_SECRET": { - "type": "sst.sst.Linkable" - "value": string - } - "Web": { - "type": "sst.cloudflare.Astro" - "url": string - } - "ZEN_MODELS1": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS2": { - "type": "sst.sst.Secret" - "value": string + ADMIN_SECRET: { + type: "sst.sst.Secret" + value: string + } + AUTH_API_URL: { + type: "sst.sst.Linkable" + value: string + } + AWS_SES_ACCESS_KEY_ID: { + type: "sst.sst.Secret" + value: string + } + AWS_SES_SECRET_ACCESS_KEY: { + type: "sst.sst.Secret" + value: string + } + Console: { + type: "sst.cloudflare.SolidStart" + url: string + } + Database: { + database: string + host: string + password: string + port: number + type: "sst.sst.Linkable" + username: string + } + Desktop: { + type: "sst.cloudflare.StaticSite" + url: string + } + EMAILOCTOPUS_API_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_ID: { + type: "sst.sst.Secret" + value: string + } + GITHUB_APP_PRIVATE_KEY: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_ID_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GITHUB_CLIENT_SECRET_CONSOLE: { + type: "sst.sst.Secret" + value: string + } + GOOGLE_CLIENT_ID: { + type: "sst.sst.Secret" + value: string + } + HONEYCOMB_API_KEY: { + type: "sst.sst.Secret" + value: string + } + STRIPE_SECRET_KEY: { + type: "sst.sst.Secret" + value: string + } + STRIPE_WEBHOOK_SECRET: { + type: "sst.sst.Linkable" + value: string + } + Web: { + type: "sst.cloudflare.Astro" + url: string + } + ZEN_MODELS1: { + type: "sst.sst.Secret" + value: string + } + ZEN_MODELS2: { + type: "sst.sst.Secret" + value: string } } } -// cloudflare -import * as cloudflare from "@cloudflare/workers-types"; +// cloudflare +import * as cloudflare from "@cloudflare/workers-types" declare module "sst" { export interface Resource { - "Api": cloudflare.Service - "AuthApi": cloudflare.Service - "AuthStorage": cloudflare.KVNamespace - "Bucket": cloudflare.R2Bucket - "LogProcessor": cloudflare.Service + Api: cloudflare.Service + AuthApi: cloudflare.Service + AuthStorage: cloudflare.KVNamespace + Bucket: cloudflare.R2Bucket + LogProcessor: cloudflare.Service } } import "sst" -export {}
\ No newline at end of file +export {} diff --git a/packages/opencode/script/postinstall.mjs b/packages/opencode/script/postinstall.mjs index b875d158f..41865273d 100644 --- a/packages/opencode/script/postinstall.mjs +++ b/packages/opencode/script/postinstall.mjs @@ -77,7 +77,8 @@ async function regenerateWindowsCmdWrappers() { // npm_config_global is string | undefined // if it exists, the value is true - const isGlobal = process.env.npm_config_global === "true" || pkgPath.includes(path.join("npm", "node_modules")) + const isGlobal = + process.env.npm_config_global === "true" || pkgPath.includes(path.join("npm", "node_modules")) // The npm rebuild command does 2 things - Execute lifecycle scripts and rebuild bin links // We want to skip lifecycle scripts to avoid infinite loops, so we use --ignore-scripts @@ -93,7 +94,9 @@ async function regenerateWindowsCmdWrappers() { console.log("Successfully rebuilt npm bin links") } catch (error) { console.error("Error rebuilding npm links:", error.message) - console.error("npm rebuild failed. You may need to manually run: npm rebuild opencode-ai --ignore-scripts") + console.error( + "npm rebuild failed. You may need to manually run: npm rebuild opencode-ai --ignore-scripts", + ) } } diff --git a/packages/opencode/script/schema.ts b/packages/opencode/script/schema.ts index 585701c95..48bf65442 100755 --- a/packages/opencode/script/schema.ts +++ b/packages/opencode/script/schema.ts @@ -19,12 +19,23 @@ const result = z.toJSONSchema(Config.Info, { const schema = ctx.jsonSchema // Preserve strictness: set additionalProperties: false for objects - if (schema && typeof schema === "object" && schema.type === "object" && schema.additionalProperties === undefined) { + if ( + schema && + typeof schema === "object" && + schema.type === "object" && + schema.additionalProperties === undefined + ) { schema.additionalProperties = false } // Add examples and default descriptions for string fields with defaults - if (schema && typeof schema === "object" && "type" in schema && schema.type === "string" && schema?.default) { + if ( + schema && + typeof schema === "object" && + "type" in schema && + schema.type === "string" && + schema?.default + ) { if (!schema.examples) { schema.examples = [schema.default] } diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index a6933708b..16f401629 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -143,7 +143,18 @@ export namespace Agent { tools: {}, builtIn: false, } - const { name, model, prompt, tools, description, temperature, top_p, mode, permission, ...extra } = value + const { + name, + model, + prompt, + tools, + description, + temperature, + top_p, + mode, + permission, + ...extra + } = value item.options = { ...item.options, ...extra, @@ -212,7 +223,10 @@ export namespace Agent { } } -function mergeAgentPermissions(basePermission: any, overridePermission: any): Agent.Info["permission"] { +function mergeAgentPermissions( + basePermission: any, + overridePermission: any, +): Agent.Info["permission"] { if (typeof basePermission.bash === "string") { basePermission.bash = { "*": basePermission.bash, diff --git a/packages/opencode/src/bus/index.ts b/packages/opencode/src/bus/index.ts index f4dd3ed2c..c424eb879 100644 --- a/packages/opencode/src/bus/index.ts +++ b/packages/opencode/src/bus/index.ts @@ -19,7 +19,10 @@ export namespace Bus { const registry = new Map<string, EventDefinition>() - export function event<Type extends string, Properties extends ZodType>(type: Type, properties: Properties) { + export function event<Type extends string, Properties extends ZodType>( + type: Type, + properties: Properties, + ) { const result = { type, properties, @@ -70,7 +73,10 @@ export namespace Bus { export function subscribe<Definition extends EventDefinition>( def: Definition, - callback: (event: { type: Definition["type"]; properties: z.infer<Definition["properties"]> }) => void, + callback: (event: { + type: Definition["type"] + properties: z.infer<Definition["properties"]> + }) => void, ) { return raw(def.type, callback) } diff --git a/packages/opencode/src/cli/cmd/auth.ts b/packages/opencode/src/cli/cmd/auth.ts index aa833e977..b4c47f0a4 100644 --- a/packages/opencode/src/cli/cmd/auth.ts +++ b/packages/opencode/src/cli/cmd/auth.ts @@ -14,7 +14,11 @@ export const AuthCommand = cmd({ command: "auth", describe: "manage credentials", builder: (yargs) => - yargs.command(AuthLoginCommand).command(AuthLogoutCommand).command(AuthListCommand).demandCommand(), + yargs + .command(AuthLoginCommand) + .command(AuthLogoutCommand) + .command(AuthListCommand) + .demandCommand(), async handler() {}, }) @@ -60,7 +64,9 @@ export const AuthListCommand = cmd({ prompts.log.info(`${provider} ${UI.Style.TEXT_DIM}${envVar}`) } - prompts.outro(`${activeEnvVars.length} environment variable` + (activeEnvVars.length === 1 ? "" : "s")) + prompts.outro( + `${activeEnvVars.length} environment variable` + (activeEnvVars.length === 1 ? "" : "s"), + ) } }, }) @@ -80,7 +86,9 @@ export const AuthLoginCommand = cmd({ UI.empty() prompts.intro("Add credential") if (args.url) { - const wellknown = await fetch(`${args.url}/.well-known/opencode`).then((x) => x.json() as any) + const wellknown = await fetch(`${args.url}/.well-known/opencode`).then( + (x) => x.json() as any, + ) prompts.log.info(`Running \`${wellknown.auth.command.join(" ")}\``) const proc = Bun.spawn({ cmd: wellknown.auth.command, @@ -102,223 +110,224 @@ export const AuthLoginCommand = cmd({ prompts.outro("Done") return } - await ModelsDev.refresh().catch(() => {}) - const providers = await ModelsDev.get() - const priority: Record<string, number> = { - opencode: 0, - anthropic: 1, - "github-copilot": 2, - openai: 3, - google: 4, - openrouter: 5, - vercel: 6, - } - let provider = await prompts.autocomplete({ - message: "Select provider", - maxItems: 8, - options: [ - ...pipe( - providers, - values(), - sortBy( - (x) => priority[x.id] ?? 99, - (x) => x.name ?? x.id, + await ModelsDev.refresh().catch(() => {}) + const providers = await ModelsDev.get() + const priority: Record<string, number> = { + opencode: 0, + anthropic: 1, + "github-copilot": 2, + openai: 3, + google: 4, + openrouter: 5, + vercel: 6, + } + let provider = await prompts.autocomplete({ + message: "Select provider", + maxItems: 8, + options: [ + ...pipe( + providers, + values(), + sortBy( + (x) => priority[x.id] ?? 99, + (x) => x.name ?? x.id, + ), + map((x) => ({ + label: x.name, + value: x.id, + hint: priority[x.id] <= 1 ? "recommended" : undefined, + })), ), - map((x) => ({ - label: x.name, - value: x.id, - hint: priority[x.id] <= 1 ? "recommended" : undefined, - })), - ), - { - value: "other", - label: "Other", - }, - ], - }) + { + value: "other", + label: "Other", + }, + ], + }) - if (prompts.isCancel(provider)) throw new UI.CancelledError() + if (prompts.isCancel(provider)) throw new UI.CancelledError() - const plugin = await Plugin.list().then((x) => x.find((x) => x.auth?.provider === provider)) - if (plugin && plugin.auth) { - let index = 0 - if (plugin.auth.methods.length > 1) { - const method = await prompts.select({ - message: "Login method", - options: [ - ...plugin.auth.methods.map((x, index) => ({ - label: x.label, - value: index.toString(), - })), - ], - }) - if (prompts.isCancel(method)) throw new UI.CancelledError() - index = parseInt(method) - } - const method = plugin.auth.methods[index] + const plugin = await Plugin.list().then((x) => x.find((x) => x.auth?.provider === provider)) + if (plugin && plugin.auth) { + let index = 0 + if (plugin.auth.methods.length > 1) { + const method = await prompts.select({ + message: "Login method", + options: [ + ...plugin.auth.methods.map((x, index) => ({ + label: x.label, + value: index.toString(), + })), + ], + }) + if (prompts.isCancel(method)) throw new UI.CancelledError() + index = parseInt(method) + } + const method = plugin.auth.methods[index] - // Handle prompts for all auth types - await new Promise((resolve) => setTimeout(resolve, 10)) - const inputs: Record<string, string> = {} - if (method.prompts) { - for (const prompt of method.prompts) { - if (prompt.condition && !prompt.condition(inputs)) { - continue - } - if (prompt.type === "select") { - const value = await prompts.select({ - message: prompt.message, - options: prompt.options, - }) - if (prompts.isCancel(value)) throw new UI.CancelledError() - inputs[prompt.key] = value - } else { - const value = await prompts.text({ - message: prompt.message, - placeholder: prompt.placeholder, - validate: prompt.validate ? (v) => prompt.validate!(v ?? "") : undefined, - }) - if (prompts.isCancel(value)) throw new UI.CancelledError() - inputs[prompt.key] = value + // Handle prompts for all auth types + await new Promise((resolve) => setTimeout(resolve, 10)) + const inputs: Record<string, string> = {} + if (method.prompts) { + for (const prompt of method.prompts) { + if (prompt.condition && !prompt.condition(inputs)) { + continue + } + if (prompt.type === "select") { + const value = await prompts.select({ + message: prompt.message, + options: prompt.options, + }) + if (prompts.isCancel(value)) throw new UI.CancelledError() + inputs[prompt.key] = value + } else { + const value = await prompts.text({ + message: prompt.message, + placeholder: prompt.placeholder, + validate: prompt.validate ? (v) => prompt.validate!(v ?? "") : undefined, + }) + if (prompts.isCancel(value)) throw new UI.CancelledError() + inputs[prompt.key] = value + } } } - } - if (method.type === "oauth") { - const authorize = await method.authorize(inputs) - - if (authorize.url) { - prompts.log.info("Go to: " + authorize.url) - } + if (method.type === "oauth") { + const authorize = await method.authorize(inputs) - if (authorize.method === "auto") { - if (authorize.instructions) { - prompts.log.info(authorize.instructions) + if (authorize.url) { + prompts.log.info("Go to: " + authorize.url) } - const spinner = prompts.spinner() - spinner.start("Waiting for authorization...") - const result = await authorize.callback() - if (result.type === "failed") { - spinner.stop("Failed to authorize", 1) + + if (authorize.method === "auto") { + if (authorize.instructions) { + prompts.log.info(authorize.instructions) + } + const spinner = prompts.spinner() + spinner.start("Waiting for authorization...") + const result = await authorize.callback() + if (result.type === "failed") { + spinner.stop("Failed to authorize", 1) + } + if (result.type === "success") { + const saveProvider = result.provider ?? provider + if ("refresh" in result) { + const { type: _, provider: __, refresh, access, expires, ...extraFields } = result + await Auth.set(saveProvider, { + type: "oauth", + refresh, + access, + expires, + ...extraFields, + }) + } + if ("key" in result) { + await Auth.set(saveProvider, { + type: "api", + key: result.key, + }) + } + spinner.stop("Login successful") + } } - if (result.type === "success") { - const saveProvider = result.provider ?? provider - if ("refresh" in result) { - const { type: _, provider: __, refresh, access, expires, ...extraFields } = result - await Auth.set(saveProvider, { - type: "oauth", - refresh, - access, - expires, - ...extraFields, - }) + + if (authorize.method === "code") { + const code = await prompts.text({ + message: "Paste the authorization code here: ", + validate: (x) => (x && x.length > 0 ? undefined : "Required"), + }) + if (prompts.isCancel(code)) throw new UI.CancelledError() + const result = await authorize.callback(code) + if (result.type === "failed") { + prompts.log.error("Failed to authorize") } - if ("key" in result) { - await Auth.set(saveProvider, { - type: "api", - key: result.key, - }) + if (result.type === "success") { + const saveProvider = result.provider ?? provider + if ("refresh" in result) { + const { type: _, provider: __, refresh, access, expires, ...extraFields } = result + await Auth.set(saveProvider, { + type: "oauth", + refresh, + access, + expires, + ...extraFields, + }) + } + if ("key" in result) { + await Auth.set(saveProvider, { + type: "api", + key: result.key, + }) + } + prompts.log.success("Login successful") } - spinner.stop("Login successful") } + + prompts.outro("Done") + return } - if (authorize.method === "code") { - const code = await prompts.text({ - message: "Paste the authorization code here: ", - validate: (x) => (x && x.length > 0 ? undefined : "Required"), - }) - if (prompts.isCancel(code)) throw new UI.CancelledError() - const result = await authorize.callback(code) - if (result.type === "failed") { - prompts.log.error("Failed to authorize") - } - if (result.type === "success") { - const saveProvider = result.provider ?? provider - if ("refresh" in result) { - const { type: _, provider: __, refresh, access, expires, ...extraFields } = result - await Auth.set(saveProvider, { - type: "oauth", - refresh, - access, - expires, - ...extraFields, - }) + if (method.type === "api") { + if (method.authorize) { + const result = await method.authorize(inputs) + if (result.type === "failed") { + prompts.log.error("Failed to authorize") } - if ("key" in result) { + if (result.type === "success") { + const saveProvider = result.provider ?? provider await Auth.set(saveProvider, { type: "api", key: result.key, }) + prompts.log.success("Login successful") } - prompts.log.success("Login successful") + prompts.outro("Done") + return } } + } + if (provider === "other") { + provider = await prompts.text({ + message: "Enter provider id", + validate: (x) => + x && x.match(/^[0-9a-z-]+$/) ? undefined : "a-z, 0-9 and hyphens only", + }) + if (prompts.isCancel(provider)) throw new UI.CancelledError() + provider = provider.replace(/^@ai-sdk\//, "") + if (prompts.isCancel(provider)) throw new UI.CancelledError() + prompts.log.warn( + `This only stores a credential for ${provider} - you will need configure it in opencode.json, check the docs for examples.`, + ) + } + + if (provider === "amazon-bedrock") { + prompts.log.info( + "Amazon bedrock can be configured with standard AWS environment variables like AWS_BEARER_TOKEN_BEDROCK, AWS_PROFILE or AWS_ACCESS_KEY_ID", + ) prompts.outro("Done") return } - if (method.type === "api") { - if (method.authorize) { - const result = await method.authorize(inputs) - if (result.type === "failed") { - prompts.log.error("Failed to authorize") - } - if (result.type === "success") { - const saveProvider = result.provider ?? provider - await Auth.set(saveProvider, { - type: "api", - key: result.key, - }) - prompts.log.success("Login successful") - } - prompts.outro("Done") - return - } + if (provider === "opencode") { + prompts.log.info("Create an api key at https://opencode.ai/auth") + } + + if (provider === "vercel") { + prompts.log.info("You can create an api key at https://vercel.link/ai-gateway-token") } - } - if (provider === "other") { - provider = await prompts.text({ - message: "Enter provider id", - validate: (x) => (x && x.match(/^[0-9a-z-]+$/) ? undefined : "a-z, 0-9 and hyphens only"), + const key = await prompts.password({ + message: "Enter your API key", + validate: (x) => (x && x.length > 0 ? undefined : "Required"), + }) + if (prompts.isCancel(key)) throw new UI.CancelledError() + await Auth.set(provider, { + type: "api", + key, }) - if (prompts.isCancel(provider)) throw new UI.CancelledError() - provider = provider.replace(/^@ai-sdk\//, "") - if (prompts.isCancel(provider)) throw new UI.CancelledError() - prompts.log.warn( - `This only stores a credential for ${provider} - you will need configure it in opencode.json, check the docs for examples.`, - ) - } - if (provider === "amazon-bedrock") { - prompts.log.info( - "Amazon bedrock can be configured with standard AWS environment variables like AWS_BEARER_TOKEN_BEDROCK, AWS_PROFILE or AWS_ACCESS_KEY_ID", - ) prompts.outro("Done") - return - } - - if (provider === "opencode") { - prompts.log.info("Create an api key at https://opencode.ai/auth") - } - - if (provider === "vercel") { - prompts.log.info("You can create an api key at https://vercel.link/ai-gateway-token") - } - - const key = await prompts.password({ - message: "Enter your API key", - validate: (x) => (x && x.length > 0 ? undefined : "Required"), - }) - if (prompts.isCancel(key)) throw new UI.CancelledError() - await Auth.set(provider, { - type: "api", - key, - }) - - prompts.outro("Done") }, }) }, diff --git a/packages/opencode/src/cli/cmd/debug/lsp.ts b/packages/opencode/src/cli/cmd/debug/lsp.ts index 2f5977195..8492395d1 100644 --- a/packages/opencode/src/cli/cmd/debug/lsp.ts +++ b/packages/opencode/src/cli/cmd/debug/lsp.ts @@ -7,7 +7,11 @@ import { EOL } from "os" export const LSPCommand = cmd({ command: "lsp", builder: (yargs) => - yargs.command(DiagnosticsCommand).command(SymbolsCommand).command(DocumentSymbolsCommand).demandCommand(), + yargs + .command(DiagnosticsCommand) + .command(SymbolsCommand) + .command(DocumentSymbolsCommand) + .demandCommand(), async handler() {}, }) diff --git a/packages/opencode/src/cli/cmd/debug/ripgrep.ts b/packages/opencode/src/cli/cmd/debug/ripgrep.ts index 66cfba20d..7c1d0d96a 100644 --- a/packages/opencode/src/cli/cmd/debug/ripgrep.ts +++ b/packages/opencode/src/cli/cmd/debug/ripgrep.ts @@ -6,7 +6,8 @@ import { cmd } from "../cmd" export const RipgrepCommand = cmd({ command: "rg", - builder: (yargs) => yargs.command(TreeCommand).command(FilesCommand).command(SearchCommand).demandCommand(), + builder: (yargs) => + yargs.command(TreeCommand).command(FilesCommand).command(SearchCommand).demandCommand(), async handler() {}, }) @@ -18,7 +19,9 @@ const TreeCommand = cmd({ }), async handler(args) { await bootstrap(process.cwd(), async () => { - process.stdout.write(await Ripgrep.tree({ cwd: Instance.directory, limit: args.limit }) + EOL) + process.stdout.write( + (await Ripgrep.tree({ cwd: Instance.directory, limit: args.limit })) + EOL, + ) }) }, }) diff --git a/packages/opencode/src/cli/cmd/debug/snapshot.ts b/packages/opencode/src/cli/cmd/debug/snapshot.ts index 1849fe270..b114122b7 100644 --- a/packages/opencode/src/cli/cmd/debug/snapshot.ts +++ b/packages/opencode/src/cli/cmd/debug/snapshot.ts @@ -4,7 +4,8 @@ import { cmd } from "../cmd" export const SnapshotCommand = cmd({ command: "snapshot", - builder: (yargs) => yargs.command(TrackCommand).command(PatchCommand).command(DiffCommand).demandCommand(), + builder: (yargs) => + yargs.command(TrackCommand).command(PatchCommand).command(DiffCommand).demandCommand(), async handler() {}, }) diff --git a/packages/opencode/src/cli/cmd/generate.ts b/packages/opencode/src/cli/cmd/generate.ts index 0cefb2533..c29a22a82 100644 --- a/packages/opencode/src/cli/cmd/generate.ts +++ b/packages/opencode/src/cli/cmd/generate.ts @@ -6,7 +6,7 @@ export const GenerateCommand = { handler: async () => { const specs = await Server.openapi() const json = JSON.stringify(specs, null, 2) - + // Wait for stdout to finish writing before process.exit() is called await new Promise<void>((resolve, reject) => { process.stdout.write(json, (err) => { diff --git a/packages/opencode/src/cli/cmd/github.ts b/packages/opencode/src/cli/cmd/github.ts index cd3ceb94b..6fbeee2ea 100644 --- a/packages/opencode/src/cli/cmd/github.ts +++ b/packages/opencode/src/cli/cmd/github.ts @@ -189,7 +189,9 @@ export const GithubInstallCommand = cmd({ async function getAppInfo() { const project = Instance.project if (project.vcs !== "git") { - prompts.log.error(`Could not find git repository. Please run this command from a git repository.`) + prompts.log.error( + `Could not find git repository. Please run this command from a git repository.`, + ) throw new UI.CancelledError() } @@ -202,9 +204,13 @@ export const GithubInstallCommand = cmd({ // ie. [email protected]:sst/opencode // ie. ssh://[email protected]/sst/opencode.git // ie. ssh://[email protected]/sst/opencode - const parsed = info.match(/^(?:(?:https?|ssh):\/\/)?(?:git@)?github\.com[:/]([^/]+)\/([^/.]+?)(?:\.git)?$/) + const parsed = info.match( + /^(?:(?:https?|ssh):\/\/)?(?:git@)?github\.com[:/]([^/]+)\/([^/.]+?)(?:\.git)?$/, + ) if (!parsed) { - prompts.log.error(`Could not find git repository. Please run this command from a git repository.`) + prompts.log.error( + `Could not find git repository. Please run this command from a git repository.`, + ) throw new UI.CancelledError() } const [, owner, repo] = parsed @@ -445,7 +451,9 @@ export const GithubRunCommand = cmd({ const summary = await summarize(response) await pushToLocalBranch(summary) } - const hasShared = prData.comments.nodes.some((c) => c.body.includes(`${shareBaseUrl}/s/${shareId}`)) + const hasShared = prData.comments.nodes.some((c) => + c.body.includes(`${shareBaseUrl}/s/${shareId}`), + ) await updateComment(`${response}${footer({ image: !hasShared })}`) } // Fork PR @@ -457,7 +465,9 @@ export const GithubRunCommand = cmd({ const summary = await summarize(response) await pushToForkBranch(summary, prData) } - const hasShared = prData.comments.nodes.some((c) => c.body.includes(`${shareBaseUrl}/s/${shareId}`)) + const hasShared = prData.comments.nodes.some((c) => + c.body.includes(`${shareBaseUrl}/s/${shareId}`), + ) await updateComment(`${response}${footer({ image: !hasShared })}`) } } @@ -547,8 +557,12 @@ export const GithubRunCommand = cmd({ // ie. <img alt="Image" src="https://github.com/user-attachments/assets/xxxx" /> // ie. [api.json](https://github.com/user-attachments/files/21433810/api.json) // ie.  - const mdMatches = prompt.matchAll(/!?\[.*?\]\((https:\/\/github\.com\/user-attachments\/[^)]+)\)/gi) - const tagMatches = prompt.matchAll(/<img .*?src="(https:\/\/github\.com\/user-attachments\/[^"]+)" \/>/gi) + const mdMatches = prompt.matchAll( + /!?\[.*?\]\((https:\/\/github\.com\/user-attachments\/[^)]+)\)/gi, + ) + const tagMatches = prompt.matchAll( + /<img .*?src="(https:\/\/github\.com\/user-attachments\/[^"]+)" \/>/gi, + ) const matches = [...mdMatches, ...tagMatches].sort((a, b) => a.index - b.index) console.log("Images", JSON.stringify(matches, null, 2)) @@ -573,7 +587,10 @@ export const GithubRunCommand = cmd({ // Replace img tag with file path, ie. @image.png const replacement = `@${filename}` - prompt = prompt.slice(0, start + offset) + replacement + prompt.slice(start + offset + tag.length) + prompt = + prompt.slice(0, start + offset) + + replacement + + prompt.slice(start + offset + tag.length) offset += replacement.length - tag.length const contentType = res.headers.get("content-type") @@ -856,7 +873,8 @@ Co-authored-by: ${actor} <${actor}@users.noreply.github.com>"` throw new Error(`Failed to check permissions for user ${actor}: ${error}`) } - if (!["admin", "write"].includes(permission)) throw new Error(`User ${actor} does not have write permissions`) + if (!["admin", "write"].includes(permission)) + throw new Error(`User ${actor} does not have write permissions`) } async function createComment() { @@ -904,7 +922,9 @@ Co-authored-by: ${actor} <${actor}@users.noreply.github.com>"` return `<a href="${shareBaseUrl}/s/${shareId}"><img width="200" alt="${titleAlt}" src="https://social-cards.sst.dev/opencode-share/${title64}.png?model=${providerID}/${modelID}&version=${session.version}&id=${shareId}" /></a>\n` })() - const shareUrl = shareId ? `[opencode session](${shareBaseUrl}/s/${shareId}) | ` : "" + const shareUrl = shareId + ? `[opencode session](${shareBaseUrl}/s/${shareId}) | ` + : "" return `\n\n${image}${shareUrl}[github run](${runUrl})` } @@ -1080,9 +1100,13 @@ query($owner: String!, $repo: String!, $number: Int!) { }) .map((c) => `- ${c.author.login} at ${c.createdAt}: ${c.body}`) - const files = (pr.files.nodes || []).map((f) => `- ${f.path} (${f.changeType}) +${f.additions}/-${f.deletions}`) + const files = (pr.files.nodes || []).map( + (f) => `- ${f.path} (${f.changeType}) +${f.additions}/-${f.deletions}`, + ) const reviewData = (pr.reviews.nodes || []).map((r) => { - const comments = (r.comments.nodes || []).map((c) => ` - ${c.path}:${c.line ?? "?"}: ${c.body}`) + const comments = (r.comments.nodes || []).map( + (c) => ` - ${c.path}:${c.line ?? "?"}: ${c.body}`, + ) return [ `- ${r.author.login} at ${r.submittedAt}:`, ` - Review body: ${r.body}`, @@ -1104,9 +1128,15 @@ query($owner: String!, $repo: String!, $number: Int!) { `Deletions: ${pr.deletions}`, `Total Commits: ${pr.commits.totalCount}`, `Changed Files: ${pr.files.nodes.length} files`, - ...(comments.length > 0 ? ["<pull_request_comments>", ...comments, "</pull_request_comments>"] : []), - ...(files.length > 0 ? ["<pull_request_changed_files>", ...files, "</pull_request_changed_files>"] : []), - ...(reviewData.length > 0 ? ["<pull_request_reviews>", ...reviewData, "</pull_request_reviews>"] : []), + ...(comments.length > 0 + ? ["<pull_request_comments>", ...comments, "</pull_request_comments>"] + : []), + ...(files.length > 0 + ? ["<pull_request_changed_files>", ...files, "</pull_request_changed_files>"] + : []), + ...(reviewData.length > 0 + ? ["<pull_request_reviews>", ...reviewData, "</pull_request_reviews>"] + : []), "</pull_request>", ].join("\n") } diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts index 39b0a55fd..9add4bff7 100644 --- a/packages/opencode/src/cli/cmd/run.ts +++ b/packages/opencode/src/cli/cmd/run.ts @@ -137,7 +137,9 @@ export const RunCommand = cmd({ const outputJsonEvent = (type: string, data: any) => { if (args.format === "json") { - process.stdout.write(JSON.stringify({ type, timestamp: Date.now(), sessionID, ...data }) + EOL) + process.stdout.write( + JSON.stringify({ type, timestamp: Date.now(), sessionID, ...data }) + EOL, + ) return true } return false @@ -157,7 +159,9 @@ export const RunCommand = cmd({ const [tool, color] = TOOL[part.tool] ?? [part.tool, UI.Style.TEXT_INFO_BOLD] const title = part.state.title || - (Object.keys(part.state.input).length > 0 ? JSON.stringify(part.state.input) : "Unknown") + (Object.keys(part.state.input).length > 0 + ? JSON.stringify(part.state.input) + : "Unknown") printEvent(color, tool, title) if (part.tool === "bash" && part.state.output?.trim()) { UI.println() @@ -280,7 +284,10 @@ export const RunCommand = cmd({ } const cfgResult = await sdk.config.get() - if (cfgResult.data && (cfgResult.data.share === "auto" || Flag.OPENCODE_AUTO_SHARE || args.share)) { + if ( + cfgResult.data && + (cfgResult.data.share === "auto" || Flag.OPENCODE_AUTO_SHARE || args.share) + ) { const shareResult = await sdk.session.share({ path: { id: sessionID } }).catch((error) => { if (error instanceof Error && error.message.includes("disabled")) { UI.println(UI.Style.TEXT_DANGER_BOLD + "! " + error.message) @@ -333,7 +340,10 @@ export const RunCommand = cmd({ } const cfgResult = await sdk.config.get() - if (cfgResult.data && (cfgResult.data.share === "auto" || Flag.OPENCODE_AUTO_SHARE || args.share)) { + if ( + cfgResult.data && + (cfgResult.data.share === "auto" || Flag.OPENCODE_AUTO_SHARE || args.share) + ) { const shareResult = await sdk.session.share({ path: { id: sessionID } }).catch((error) => { if (error instanceof Error && error.message.includes("disabled")) { UI.println(UI.Style.TEXT_DANGER_BOLD + "! " + error.message) diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-model.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-model.tsx index 04f2f6523..154995997 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-model.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-model.tsx @@ -52,7 +52,11 @@ export function DialogModel() { description: provider.name, category: provider.name, })), - filter((x) => Boolean(ref()?.filter) || !local.model.recent().find((y) => isDeepEqual(y, x.value))), + filter( + (x) => + Boolean(ref()?.filter) || + !local.model.recent().find((y) => isDeepEqual(y, x.value)), + ), ), ), ), diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx index 95792ad83..dc770ce28 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx @@ -20,8 +20,8 @@ export function DialogSessionList() { const deleteKeybind = "ctrl+d" - const currentSessionID = createMemo(() => - route.data.type === "session" ? route.data.sessionID : undefined + const currentSessionID = createMemo(() => + route.data.type === "session" ? route.data.sessionID : undefined, ) const options = createMemo(() => { diff --git a/packages/opencode/src/cli/cmd/tui/component/logo.tsx b/packages/opencode/src/cli/cmd/tui/component/logo.tsx index 59db5fe7d..7cac51ecc 100644 --- a/packages/opencode/src/cli/cmd/tui/component/logo.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/logo.tsx @@ -3,9 +3,19 @@ import { TextAttributes } from "@opentui/core" import { For } from "solid-js" import { useTheme } from "@tui/context/theme" -const LOGO_LEFT = [` `, `█▀▀█ █▀▀█ █▀▀█ █▀▀▄`, `█░░█ █░░█ █▀▀▀ █░░█`, `▀▀▀▀ █▀▀▀ ▀▀▀▀ ▀ ▀`] +const LOGO_LEFT = [ + ` `, + `█▀▀█ █▀▀█ █▀▀█ █▀▀▄`, + `█░░█ █░░█ █▀▀▀ █░░█`, + `▀▀▀▀ █▀▀▀ ▀▀▀▀ ▀ ▀`, +] -const LOGO_RIGHT = [` ▄ `, `█▀▀▀ █▀▀█ █▀▀█ █▀▀█`, `█░░░ █░░█ █░░█ █▀▀▀`, `▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀`] +const LOGO_RIGHT = [ + ` ▄ `, + `█▀▀▀ █▀▀█ █▀▀█ █▀▀█`, + `█░░░ █░░█ █░░█ █▀▀▀`, + `▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀`, +] export function Logo() { const { theme } = useTheme() diff --git a/packages/opencode/src/cli/cmd/tui/context/route.tsx b/packages/opencode/src/cli/cmd/tui/context/route.tsx index ef230dc98..dd8ede156 100644 --- a/packages/opencode/src/cli/cmd/tui/context/route.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/route.tsx @@ -17,13 +17,11 @@ export const { use: useRoute, provider: RouteProvider } = createSimpleContext({ init: (props: { data?: Route }) => { const [store, setStore] = createStore<Route>( props.data ?? - ( - process.env["OPENCODE_ROUTE"] + (process.env["OPENCODE_ROUTE"] ? JSON.parse(process.env["OPENCODE_ROUTE"]) : { - type: "home", - } - ), + type: "home", + }), ) return { diff --git a/packages/opencode/src/cli/cmd/tui/context/sync.tsx b/packages/opencode/src/cli/cmd/tui/context/sync.tsx index 5d8f1dac8..8ba73a4b6 100644 --- a/packages/opencode/src/cli/cmd/tui/context/sync.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/sync.tsx @@ -269,6 +269,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ }, async sync(sessionID: string) { const now = Date.now() + console.log("syncing", sessionID) const [session, messages, todo, diff] = await Promise.all([ sdk.client.session.get({ path: { id: sessionID }, throwOnError: true }), sdk.client.session.messages({ path: { id: sessionID } }), diff --git a/packages/opencode/src/cli/cmd/tui/context/theme/nightowl.json b/packages/opencode/src/cli/cmd/tui/context/theme/nightowl.json index 8eff42c5f..24c74733d 100644 --- a/packages/opencode/src/cli/cmd/tui/context/theme/nightowl.json +++ b/packages/opencode/src/cli/cmd/tui/context/theme/nightowl.json @@ -218,4 +218,4 @@ "light": "nightOwlFg" } } -}
\ No newline at end of file +} diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-message.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/dialog-message.tsx index ee2b77afc..cfdd4d694 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-message.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/dialog-message.tsx @@ -7,7 +7,9 @@ import { useRoute } from "@tui/context/route" export function DialogMessage(props: { messageID: string; sessionID: string }) { const sync = useSync() const sdk = useSDK() - const message = createMemo(() => sync.data.message[props.sessionID]?.find((x) => x.id === props.messageID)) + const message = createMemo(() => + sync.data.message[props.sessionID]?.find((x) => x.id === props.messageID), + ) const route = useRoute() return ( diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-timeline.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/dialog-timeline.tsx index f5976cdf0..b440ee1a0 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/dialog-timeline.tsx @@ -19,7 +19,9 @@ export function DialogTimeline(props: { sessionID: string; onMove: (messageID: s const result = [] as DialogSelectOption<string>[] for (const message of messages) { if (message.role !== "user") continue - const part = (sync.data.part[message.id] ?? []).find((x) => x.type === "text" && !x.synthetic) as TextPart + const part = (sync.data.part[message.id] ?? []).find( + (x) => x.type === "text" && !x.synthetic, + ) as TextPart if (!part) continue result.push({ title: part.text.replace(/\n/g, " "), @@ -33,5 +35,11 @@ export function DialogTimeline(props: { sessionID: string; onMove: (messageID: s return result }) - return <DialogSelect onMove={(option) => props.onMove(option.value)} title="Timeline" options={options()} /> + return ( + <DialogSelect + onMove={(option) => props.onMove(option.value)} + title="Timeline" + options={options()} + /> + ) } diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index 971ed8170..7aa8ab2f4 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -105,14 +105,15 @@ export function Session() { const sidebarVisible = createMemo(() => sidebar() === "show" || (sidebar() === "auto" && wide())) const contentWidth = createMemo(() => dimensions().width - (sidebarVisible() ? 42 : 0) - 4) - createEffect(() => { - sync.session.sync(route.sessionID).catch(() => { + createEffect(async () => { + await sync.session.sync(route.sessionID).catch(() => { toast.show({ message: `Session not found: ${route.sessionID}`, variant: "error", }) return navigate({ type: "home" }) }) + scroll.scrollBy(100_000) }) const toast = useToast() diff --git a/packages/opencode/src/cli/cmd/tui/spawn.ts b/packages/opencode/src/cli/cmd/tui/spawn.ts index 29c9a3590..6a1975131 100644 --- a/packages/opencode/src/cli/cmd/tui/spawn.ts +++ b/packages/opencode/src/cli/cmd/tui/spawn.ts @@ -41,7 +41,12 @@ export const TuiSpawnCommand = cmd({ ) cwd = new URL("../../../../", import.meta.url).pathname } else cmd.push(process.execPath) - cmd.push("attach", server.url.toString(), "--dir", args.project ? path.resolve(args.project) : process.cwd()) + cmd.push( + "attach", + server.url.toString(), + "--dir", + args.project ? path.resolve(args.project) : process.cwd(), + ) const proc = Bun.spawn({ cmd, cwd, diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-confirm.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-confirm.tsx index dd5b238b1..f79ae0555 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-confirm.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-confirm.tsx @@ -53,7 +53,9 @@ export function DialogConfirm(props: DialogConfirmProps) { dialog.clear() }} > - <text fg={key === store.active ? theme.background : theme.textMuted}>{Locale.titlecase(key)}</text> + <text fg={key === store.active ? theme.background : theme.textMuted}> + {Locale.titlecase(key)} + </text> </box> )} </For> diff --git a/packages/opencode/src/cli/cmd/tui/util/editor.ts b/packages/opencode/src/cli/cmd/tui/util/editor.ts index 0aa69dcd8..18a1400c9 100644 --- a/packages/opencode/src/cli/cmd/tui/util/editor.ts +++ b/packages/opencode/src/cli/cmd/tui/util/editor.ts @@ -5,7 +5,10 @@ import { join } from "node:path" import { CliRenderer } from "@opentui/core" export namespace Editor { - export async function open(opts: { value: string; renderer: CliRenderer }): Promise<string | undefined> { + export async function open(opts: { + value: string + renderer: CliRenderer + }): Promise<string | undefined> { const editor = process.env["EDITOR"] if (!editor) return diff --git a/packages/opencode/src/cli/cmd/upgrade.ts b/packages/opencode/src/cli/cmd/upgrade.ts index 65f3bab4d..f0ca48014 100644 --- a/packages/opencode/src/cli/cmd/upgrade.ts +++ b/packages/opencode/src/cli/cmd/upgrade.ts @@ -27,7 +27,9 @@ export const UpgradeCommand = { const detectedMethod = await Installation.method() const method = (args.method as Installation.Method) ?? detectedMethod if (method === "unknown") { - prompts.log.error(`opencode is installed to ${process.execPath} and may be managed by a package manager`) + prompts.log.error( + `opencode is installed to ${process.execPath} and may be managed by a package manager`, + ) const install = await prompts.select({ message: "Install anyways?", options: [ diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index efd31ccba..c2ee63c61 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -574,7 +574,10 @@ export namespace Config { .object({ apiKey: z.string().optional(), baseURL: z.string().optional(), - enterpriseUrl: z.string().optional().describe("GitHub Enterprise URL for copilot authentication"), + enterpriseUrl: z + .string() + .optional() + .describe("GitHub Enterprise URL for copilot authentication"), timeout: z .union([ z diff --git a/packages/opencode/src/file/fzf.ts b/packages/opencode/src/file/fzf.ts index cd0aa4fc8..702688b17 100644 --- a/packages/opencode/src/file/fzf.ts +++ b/packages/opencode/src/file/fzf.ts @@ -81,7 +81,9 @@ export namespace Fzf { }) } if (config.extension === "zip") { - const zipFileReader = new ZipReader(new BlobReader(new Blob([await Bun.file(archivePath).arrayBuffer()]))) + const zipFileReader = new ZipReader( + new BlobReader(new Blob([await Bun.file(archivePath).arrayBuffer()])), + ) const entries = await zipFileReader.getEntries() let fzfEntry: any for (const entry of entries) { diff --git a/packages/opencode/src/file/ripgrep.ts b/packages/opencode/src/file/ripgrep.ts index 29014d199..84a45e386 100644 --- a/packages/opencode/src/file/ripgrep.ts +++ b/packages/opencode/src/file/ripgrep.ts @@ -161,7 +161,9 @@ export namespace Ripgrep { } if (config.extension === "zip") { if (config.extension === "zip") { - const zipFileReader = new ZipReader(new BlobReader(new Blob([await Bun.file(archivePath).arrayBuffer()]))) + const zipFileReader = new ZipReader( + new BlobReader(new Blob([await Bun.file(archivePath).arrayBuffer()])), + ) const entries = await zipFileReader.getEntries() let rgEntry: any for (const entry of entries) { @@ -354,7 +356,12 @@ export namespace Ripgrep { return lines.join("\n") } - export async function search(input: { cwd: string; pattern: string; glob?: string[]; limit?: number }) { + export async function search(input: { + cwd: string + pattern: string + glob?: string[] + limit?: number + }) { const args = [`${await filepath()}`, "--json", "--hidden", "--glob='!.git/*'"] if (input.glob) { diff --git a/packages/opencode/src/file/time.ts b/packages/opencode/src/file/time.ts index 5cba5e820..fe1dcff49 100644 --- a/packages/opencode/src/file/time.ts +++ b/packages/opencode/src/file/time.ts @@ -27,7 +27,10 @@ export namespace FileTime { export async function assert(sessionID: string, filepath: string) { const time = get(sessionID, filepath) - if (!time) throw new Error(`You must read the file ${filepath} before overwriting it. Use the Read tool first`) + if (!time) + throw new Error( + `You must read the file ${filepath} before overwriting it. Use the Read tool first`, + ) const stats = await Bun.file(filepath).stat() if (stats.mtime.getTime() > time.getTime()) { throw new Error( diff --git a/packages/opencode/src/file/watcher.ts b/packages/opencode/src/file/watcher.ts index d5985b582..e9304af70 100644 --- a/packages/opencode/src/file/watcher.ts +++ b/packages/opencode/src/file/watcher.ts @@ -51,8 +51,10 @@ export namespace FileWatcher { for (const evt of evts) { log.info("event", evt) if (evt.type === "create") Bus.publish(Event.Updated, { file: evt.path, event: "add" }) - if (evt.type === "update") Bus.publish(Event.Updated, { file: evt.path, event: "change" }) - if (evt.type === "delete") Bus.publish(Event.Updated, { file: evt.path, event: "unlink" }) + if (evt.type === "update") + Bus.publish(Event.Updated, { file: evt.path, event: "change" }) + if (evt.type === "delete") + Bus.publish(Event.Updated, { file: evt.path, event: "unlink" }) } }, { diff --git a/packages/opencode/src/id/id.ts b/packages/opencode/src/id/id.ts index 99eb6c9ff..76b6a46be 100644 --- a/packages/opencode/src/id/id.ts +++ b/packages/opencode/src/id/id.ts @@ -49,7 +49,11 @@ export namespace Identifier { return result } - export function create(prefix: keyof typeof prefixes, descending: boolean, timestamp?: number): string { + export function create( + prefix: keyof typeof prefixes, + descending: boolean, + timestamp?: number, + ): string { const currentTimestamp = timestamp ?? Date.now() if (currentTimestamp !== lastTimestamp) { diff --git a/packages/opencode/src/lsp/client.ts b/packages/opencode/src/lsp/client.ts index 1a6e2cb71..920cecc62 100644 --- a/packages/opencode/src/lsp/client.ts +++ b/packages/opencode/src/lsp/client.ts @@ -1,5 +1,9 @@ import path from "path" -import { createMessageConnection, StreamMessageReader, StreamMessageWriter } from "vscode-jsonrpc/node" +import { + createMessageConnection, + StreamMessageReader, + StreamMessageWriter, +} from "vscode-jsonrpc/node" import type { Diagnostic as VSCodeDiagnostic } from "vscode-languageserver-types" import { Log } from "../util/log" import { LANGUAGE_EXTENSIONS } from "./language" @@ -34,7 +38,11 @@ export namespace LSPClient { ), } - export async function create(input: { serverID: string; server: LSPServer.Handle; root: string }) { + export async function create(input: { + serverID: string + server: LSPServer.Handle + root: string + }) { const l = log.clone().tag("serverID", input.serverID) l.info("starting client") @@ -129,7 +137,9 @@ export namespace LSPClient { }, notify: { async open(input: { path: string }) { - input.path = path.isAbsolute(input.path) ? input.path : path.resolve(Instance.directory, input.path) + input.path = path.isAbsolute(input.path) + ? input.path + : path.resolve(Instance.directory, input.path) const file = Bun.file(input.path) const text = await file.text() const extension = path.extname(input.path) @@ -171,13 +181,18 @@ export namespace LSPClient { return diagnostics }, async waitForDiagnostics(input: { path: string }) { - input.path = path.isAbsolute(input.path) ? input.path : path.resolve(Instance.directory, input.path) + input.path = path.isAbsolute(input.path) + ? input.path + : path.resolve(Instance.directory, input.path) log.info("waiting for diagnostics", input) let unsub: () => void return await withTimeout( new Promise<void>((resolve) => { unsub = Bus.subscribe(Event.Diagnostics, (event) => { - if (event.properties.path === input.path && event.properties.serverID === result.serverID) { + if ( + event.properties.path === input.path && + event.properties.serverID === result.serverID + ) { log.info("got diagnostics", input) unsub?.() resolve() diff --git a/packages/opencode/src/patch/index.ts b/packages/opencode/src/patch/index.ts index c6e25c5cc..46467e0ba 100644 --- a/packages/opencode/src/patch/index.ts +++ b/packages/opencode/src/patch/index.ts @@ -20,7 +20,7 @@ export namespace Patch { workdir?: string } - export type Hunk = + export type Hunk = | { type: "add"; path: string; contents: string } | { type: "delete"; path: string } | { type: "update"; path: string; move_path?: string; chunks: UpdateFileChunk[] } @@ -71,60 +71,66 @@ export namespace Patch { } // Parser implementation - function parsePatchHeader(lines: string[], startIdx: number): { filePath: string; movePath?: string; nextIdx: number } | null { + function parsePatchHeader( + lines: string[], + startIdx: number, + ): { filePath: string; movePath?: string; nextIdx: number } | null { const line = lines[startIdx] - + if (line.startsWith("*** Add File:")) { const filePath = line.split(":", 2)[1]?.trim() return filePath ? { filePath, nextIdx: startIdx + 1 } : null } - + if (line.startsWith("*** Delete File:")) { const filePath = line.split(":", 2)[1]?.trim() return filePath ? { filePath, nextIdx: startIdx + 1 } : null } - + if (line.startsWith("*** Update File:")) { const filePath = line.split(":", 2)[1]?.trim() let movePath: string | undefined let nextIdx = startIdx + 1 - + // Check for move directive if (nextIdx < lines.length && lines[nextIdx].startsWith("*** Move to:")) { movePath = lines[nextIdx].split(":", 2)[1]?.trim() nextIdx++ } - + return filePath ? { filePath, movePath, nextIdx } : null } - + return null } - function parseUpdateFileChunks(lines: string[], startIdx: number): { chunks: UpdateFileChunk[]; nextIdx: number } { + function parseUpdateFileChunks( + lines: string[], + startIdx: number, + ): { chunks: UpdateFileChunk[]; nextIdx: number } { const chunks: UpdateFileChunk[] = [] let i = startIdx - + while (i < lines.length && !lines[i].startsWith("***")) { if (lines[i].startsWith("@@")) { // Parse context line const contextLine = lines[i].substring(2).trim() i++ - + const oldLines: string[] = [] const newLines: string[] = [] let isEndOfFile = false - + // Parse change lines while (i < lines.length && !lines[i].startsWith("@@") && !lines[i].startsWith("***")) { const changeLine = lines[i] - + if (changeLine === "*** End of File") { isEndOfFile = true i++ break } - + if (changeLine.startsWith(" ")) { // Keep line - appears in both old and new const content = changeLine.substring(1) @@ -137,10 +143,10 @@ export namespace Patch { // Add line - only in new newLines.push(changeLine.substring(1)) } - + i++ } - + chunks.push({ old_lines: oldLines, new_lines: newLines, @@ -151,26 +157,29 @@ export namespace Patch { i++ } } - + return { chunks, nextIdx: i } } - function parseAddFileContent(lines: string[], startIdx: number): { content: string; nextIdx: number } { + function parseAddFileContent( + lines: string[], + startIdx: number, + ): { content: string; nextIdx: number } { let content = "" let i = startIdx - + while (i < lines.length && !lines[i].startsWith("***")) { if (lines[i].startsWith("+")) { content += lines[i].substring(1) + "\n" } i++ } - + // Remove trailing newline if (content.endsWith("\n")) { content = content.slice(0, -1) } - + return { content, nextIdx: i } } @@ -178,28 +187,28 @@ export namespace Patch { const lines = patchText.split("\n") const hunks: Hunk[] = [] let i = 0 - + // Look for Begin/End patch markers const beginMarker = "*** Begin Patch" const endMarker = "*** End Patch" - - const beginIdx = lines.findIndex(line => line.trim() === beginMarker) - const endIdx = lines.findIndex(line => line.trim() === endMarker) - + + const beginIdx = lines.findIndex((line) => line.trim() === beginMarker) + const endIdx = lines.findIndex((line) => line.trim() === endMarker) + if (beginIdx === -1 || endIdx === -1 || beginIdx >= endIdx) { throw new Error("Invalid patch format: missing Begin/End markers") } - + // Parse content between markers i = beginIdx + 1 - + while (i < endIdx) { const header = parsePatchHeader(lines, i) if (!header) { i++ continue } - + if (lines[i].startsWith("*** Add File:")) { const { content, nextIdx } = parseAddFileContent(lines, header.nextIdx) hunks.push({ @@ -227,18 +236,19 @@ export namespace Patch { i++ } } - + return { hunks } } // Apply patch functionality - export function maybeParseApplyPatch(argv: string[]): + export function maybeParseApplyPatch( + argv: string[], + ): | { type: MaybeApplyPatch.Body; args: ApplyPatchArgs } | { type: MaybeApplyPatch.PatchParseError; error: Error } | { type: MaybeApplyPatch.NotApplyPatch } { - const APPLY_PATCH_COMMANDS = ["apply_patch", "applypatch"] - + // Direct invocation: apply_patch <patch> if (argv.length === 2 && APPLY_PATCH_COMMANDS.includes(argv[0])) { try { @@ -257,13 +267,13 @@ export namespace Patch { } } } - + // Bash heredoc form: bash -lc 'apply_patch <<"EOF" ...' if (argv.length === 3 && argv[0] === "bash" && argv[1] === "-lc") { // Simple extraction - in real implementation would need proper bash parsing const script = argv[2] const heredocMatch = script.match(/apply_patch\s*<<['"](\w+)['"]\s*\n([\s\S]*?)\n\1/) - + if (heredocMatch) { const patchContent = heredocMatch[2] try { @@ -283,7 +293,7 @@ export namespace Patch { } } } - + return { type: MaybeApplyPatch.NotApplyPatch } } @@ -293,7 +303,10 @@ export namespace Patch { content: string } - export function deriveNewContentsFromChunks(filePath: string, chunks: UpdateFileChunk[]): ApplyPatchFileUpdate { + export function deriveNewContentsFromChunks( + filePath: string, + chunks: UpdateFileChunk[], + ): ApplyPatchFileUpdate { // Read original file content let originalContent: string try { @@ -301,37 +314,41 @@ export namespace Patch { } catch (error) { throw new Error(`Failed to read file ${filePath}: ${error}`) } - + let originalLines = originalContent.split("\n") - + // Drop trailing empty element for consistent line counting if (originalLines.length > 0 && originalLines[originalLines.length - 1] === "") { originalLines.pop() } - + const replacements = computeReplacements(originalLines, filePath, chunks) let newLines = applyReplacements(originalLines, replacements) - + // Ensure trailing newline if (newLines.length === 0 || newLines[newLines.length - 1] !== "") { newLines.push("") } - + const newContent = newLines.join("\n") - + // Generate unified diff const unifiedDiff = generateUnifiedDiff(originalContent, newContent) - + return { unified_diff: unifiedDiff, content: newContent, } } - function computeReplacements(originalLines: string[], filePath: string, chunks: UpdateFileChunk[]): Array<[number, number, string[]]> { + function computeReplacements( + originalLines: string[], + filePath: string, + chunks: UpdateFileChunk[], + ): Array<[number, number, string[]]> { const replacements: Array<[number, number, string[]]> = [] let lineIndex = 0 - + for (const chunk of chunks) { // Handle context-based seeking if (chunk.change_context) { @@ -341,21 +358,22 @@ export namespace Patch { } lineIndex = contextIdx + 1 } - + // Handle pure addition (no old lines) if (chunk.old_lines.length === 0) { - const insertionIdx = originalLines.length > 0 && originalLines[originalLines.length - 1] === "" - ? originalLines.length - 1 - : originalLines.length + const insertionIdx = + originalLines.length > 0 && originalLines[originalLines.length - 1] === "" + ? originalLines.length - 1 + : originalLines.length replacements.push([insertionIdx, 0, chunk.new_lines]) continue } - + // Try to match old lines in the file let pattern = chunk.old_lines let newSlice = chunk.new_lines let found = seekSequence(originalLines, pattern, lineIndex) - + // Retry without trailing empty line if not found if (found === -1 && pattern.length > 0 && pattern[pattern.length - 1] === "") { pattern = pattern.slice(0, -1) @@ -364,79 +382,82 @@ export namespace Patch { } found = seekSequence(originalLines, pattern, lineIndex) } - + if (found !== -1) { replacements.push([found, pattern.length, newSlice]) lineIndex = found + pattern.length } else { throw new Error( - `Failed to find expected lines in ${filePath}:\n${chunk.old_lines.join("\n")}` + `Failed to find expected lines in ${filePath}:\n${chunk.old_lines.join("\n")}`, ) } } - + // Sort replacements by index to apply in order replacements.sort((a, b) => a[0] - b[0]) - + return replacements } - function applyReplacements(lines: string[], replacements: Array<[number, number, string[]]>): string[] { + function applyReplacements( + lines: string[], + replacements: Array<[number, number, string[]]>, + ): string[] { // Apply replacements in reverse order to avoid index shifting const result = [...lines] - + for (let i = replacements.length - 1; i >= 0; i--) { const [startIdx, oldLen, newSegment] = replacements[i] - + // Remove old lines result.splice(startIdx, oldLen) - + // Insert new lines for (let j = 0; j < newSegment.length; j++) { result.splice(startIdx + j, 0, newSegment[j]) } } - + return result } function seekSequence(lines: string[], pattern: string[], startIndex: number): number { if (pattern.length === 0) return -1 - + // Simple substring search implementation for (let i = startIndex; i <= lines.length - pattern.length; i++) { let matches = true - + for (let j = 0; j < pattern.length; j++) { if (lines[i + j] !== pattern[j]) { matches = false break } } - + if (matches) { return i } } - + return -1 } function generateUnifiedDiff(oldContent: string, newContent: string): string { const oldLines = oldContent.split("\n") const newLines = newContent.split("\n") - + // Simple diff generation - in a real implementation you'd use a proper diff algorithm let diff = "@@ -1 +1 @@\n" - + // Find changes (simplified approach) const maxLen = Math.max(oldLines.length, newLines.length) let hasChanges = false - + for (let i = 0; i < maxLen; i++) { const oldLine = oldLines[i] || "" const newLine = newLines[i] || "" - + if (oldLine !== newLine) { if (oldLine) diff += `-${oldLine}\n` if (newLine) diff += `+${newLine}\n` @@ -445,7 +466,7 @@ export namespace Patch { diff += ` ${oldLine}\n` } } - + return hasChanges ? diff : "" } @@ -454,11 +475,11 @@ export namespace Patch { if (hunks.length === 0) { throw new Error("No files were modified.") } - + const added: string[] = [] const modified: string[] = [] const deleted: string[] = [] - + for (const hunk of hunks) { switch (hunk.type) { case "add": @@ -467,28 +488,28 @@ export namespace Patch { if (addDir !== "." && addDir !== "/") { await fs.mkdir(addDir, { recursive: true }) } - + await fs.writeFile(hunk.path, hunk.contents, "utf-8") added.push(hunk.path) log.info(`Added file: ${hunk.path}`) break - + case "delete": await fs.unlink(hunk.path) deleted.push(hunk.path) log.info(`Deleted file: ${hunk.path}`) break - + case "update": const fileUpdate = deriveNewContentsFromChunks(hunk.path, hunk.chunks) - + if (hunk.move_path) { // Handle file move const moveDir = path.dirname(hunk.move_path) if (moveDir !== "." && moveDir !== "/") { await fs.mkdir(moveDir, { recursive: true }) } - + await fs.writeFile(hunk.move_path, fileUpdate.content, "utf-8") await fs.unlink(hunk.path) modified.push(hunk.move_path) @@ -502,7 +523,7 @@ export namespace Patch { break } } - + return { added, modified, deleted } } @@ -513,7 +534,10 @@ export namespace Patch { } // Async version of maybeParseApplyPatchVerified - export async function maybeParseApplyPatchVerified(argv: string[], cwd: string): Promise< + export async function maybeParseApplyPatchVerified( + argv: string[], + cwd: string, + ): Promise< | { type: MaybeApplyPatchVerified.Body; action: ApplyPatchAction } | { type: MaybeApplyPatchVerified.CorrectnessError; error: Error } | { type: MaybeApplyPatchVerified.NotApplyPatch } @@ -530,18 +554,21 @@ export namespace Patch { // Not a patch, continue } } - + const result = maybeParseApplyPatch(argv) - + switch (result.type) { case MaybeApplyPatch.Body: const { args } = result const effectiveCwd = args.workdir ? path.resolve(cwd, args.workdir) : cwd const changes = new Map<string, ApplyPatchFileChange>() - + for (const hunk of args.hunks) { - const resolvedPath = path.resolve(effectiveCwd, hunk.type === "update" && hunk.move_path ? hunk.move_path : hunk.path) - + const resolvedPath = path.resolve( + effectiveCwd, + hunk.type === "update" && hunk.move_path ? hunk.move_path : hunk.path, + ) + switch (hunk.type) { case "add": changes.set(resolvedPath, { @@ -549,7 +576,7 @@ export namespace Patch { content: hunk.contents, }) break - + case "delete": // For delete, we need to read the current content const deletePath = path.resolve(effectiveCwd, hunk.path) @@ -566,7 +593,7 @@ export namespace Patch { } } break - + case "update": const updatePath = path.resolve(effectiveCwd, hunk.path) try { @@ -574,7 +601,9 @@ export namespace Patch { changes.set(resolvedPath, { type: "update", unified_diff: fileUpdate.unified_diff, - move_path: hunk.move_path ? path.resolve(effectiveCwd, hunk.move_path) : undefined, + move_path: hunk.move_path + ? path.resolve(effectiveCwd, hunk.move_path) + : undefined, new_content: fileUpdate.content, }) } catch (error) { @@ -586,7 +615,7 @@ export namespace Patch { break } } - + return { type: MaybeApplyPatchVerified.Body, action: { @@ -595,15 +624,15 @@ export namespace Patch { cwd: effectiveCwd, }, } - + case MaybeApplyPatch.PatchParseError: return { type: MaybeApplyPatchVerified.CorrectnessError, error: result.error, } - + case MaybeApplyPatch.NotApplyPatch: return { type: MaybeApplyPatchVerified.NotApplyPatch } } } -}
\ No newline at end of file +} diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index 6212edff8..9e095f5bf 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -40,7 +40,8 @@ export namespace ProviderTransform { } for (const msg of unique([...system, ...final])) { - const shouldUseContentOptions = providerID !== "anthropic" && Array.isArray(msg.content) && msg.content.length > 0 + const shouldUseContentOptions = + providerID !== "anthropic" && Array.isArray(msg.content) && msg.content.length > 0 if (shouldUseContentOptions) { const lastContent = msg.content[msg.content.length - 1] @@ -84,7 +85,11 @@ export namespace ProviderTransform { return undefined } - export function options(providerID: string, modelID: string, sessionID: string): Record<string, any> | undefined { + export function options( + providerID: string, + modelID: string, + sessionID: string, + ): Record<string, any> | undefined { const result: Record<string, any> = {} if (providerID === "openai") { @@ -109,7 +114,11 @@ export namespace ProviderTransform { return result } - export function providerOptions(npm: string | undefined, providerID: string, options: { [x: string]: any }) { + export function providerOptions( + npm: string | undefined, + providerID: string, + options: { [x: string]: any }, + ) { switch (npm) { case "@ai-sdk/openai": case "@ai-sdk/azure": @@ -142,7 +151,8 @@ export namespace ProviderTransform { if (providerID === "anthropic") { const thinking = options?.["thinking"] - const budgetTokens = typeof thinking?.["budgetTokens"] === "number" ? thinking["budgetTokens"] : 0 + const budgetTokens = + typeof thinking?.["budgetTokens"] === "number" ? thinking["budgetTokens"] : 0 const enabled = thinking?.["type"] === "enabled" if (enabled && budgetTokens > 0) { // Return text tokens so that text + thinking <= model cap, preferring 32k text when possible. diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index 59e066e15..308ed4380 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -755,7 +755,7 @@ export namespace Server { ), async (c) => { const messages = await Session.messages(c.req.valid("param").id) - return c.json(messages) + return c.json(messages.slice(-100)) }, ) .get( diff --git a/packages/opencode/src/session/compaction.ts b/packages/opencode/src/session/compaction.ts index cc6351675..021b544e0 100644 --- a/packages/opencode/src/session/compaction.ts +++ b/packages/opencode/src/session/compaction.ts @@ -1,4 +1,4 @@ -import { streamText, type ModelMessage, LoadAPIKeyError, type StreamTextResult, type Tool as AITool } from "ai" +import { streamText, type ModelMessage, type StreamTextResult, type Tool as AITool } from "ai" import { Session } from "." import { Identifier } from "../id/id" import { Instance } from "../project/instance" @@ -30,12 +30,17 @@ export namespace SessionCompaction { ), } - export function isOverflow(input: { tokens: MessageV2.Assistant["tokens"]; model: ModelsDev.Model }) { + export function isOverflow(input: { + tokens: MessageV2.Assistant["tokens"] + model: ModelsDev.Model + }) { if (Flag.OPENCODE_DISABLE_AUTOCOMPACT) return false const context = input.model.limit.context if (context === 0) return false const count = input.tokens.input + input.tokens.cache.read + input.tokens.output - const output = Math.min(input.model.limit.output, SessionPrompt.OUTPUT_TOKEN_MAX) || SessionPrompt.OUTPUT_TOKEN_MAX + const output = + Math.min(input.model.limit.output, SessionPrompt.OUTPUT_TOKEN_MAX) || + SessionPrompt.OUTPUT_TOKEN_MAX const usable = context - output return count > usable } @@ -87,9 +92,15 @@ export namespace SessionCompaction { } } - export async function run(input: { sessionID: string; providerID: string; modelID: string; signal?: AbortSignal }) { + export async function run(input: { + sessionID: string + providerID: string + modelID: string + signal?: AbortSignal + }) { if (!input.signal) SessionLock.assertUnlocked(input.sessionID) - await using lock = input.signal === undefined ? SessionLock.acquire({ sessionID: input.sessionID }) : undefined + await using lock = + input.signal === undefined ? SessionLock.acquire({ sessionID: input.sessionID }) : undefined const signal = input.signal ?? lock!.signal await Session.update(input.sessionID, (draft) => { @@ -113,7 +124,6 @@ export namespace SessionCompaction { role: "assistant", parentID: toSummarize.findLast((m) => m.info.role === "user")?.info.id!, sessionID: input.sessionID, - system, mode: "build", path: { cwd: Instance.directory, @@ -150,7 +160,11 @@ export namespace SessionCompaction { // set to 0, we handle loop maxRetries: 0, model: model.language, - providerOptions: ProviderTransform.providerOptions(model.npm, model.providerID, model.info.options), + providerOptions: ProviderTransform.providerOptions( + model.npm, + model.providerID, + model.info.options, + ), headers: model.info.headers, abortSignal: signal, onError(error) { @@ -230,7 +244,11 @@ export namespace SessionCompaction { error: e, }) const error = MessageV2.fromError(e, { providerID: input.providerID }) - if (retries.count < retries.max && MessageV2.APIError.isInstance(error) && error.data.isRetryable) { + if ( + retries.count < retries.max && + MessageV2.APIError.isInstance(error) && + error.data.isRetryable + ) { shouldRetry = true await Session.updatePart({ id: Identifier.ascending("part"), diff --git a/packages/opencode/src/session/lock.ts b/packages/opencode/src/session/lock.ts index ed024edab..22eb8187c 100644 --- a/packages/opencode/src/session/lock.ts +++ b/packages/opencode/src/session/lock.ts @@ -50,7 +50,10 @@ export namespace SessionLock { export function acquire(input: { sessionID: string }) { const lock = get(input.sessionID) if (lock) { - throw new LockedError({ sessionID: input.sessionID, message: `Session ${input.sessionID} is locked` }) + throw new LockedError({ + sessionID: input.sessionID, + message: `Session ${input.sessionID} is locked`, + }) } const controller = new AbortController() state().locks.set(input.sessionID, { diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts index 3b28afe0f..f35735b71 100644 --- a/packages/opencode/src/session/message-v2.ts +++ b/packages/opencode/src/session/message-v2.ts @@ -2,14 +2,23 @@ import z from "zod" import { Bus } from "../bus" import { NamedError } from "../util/error" import { Message } from "./message" -import { APICallError, convertToModelMessages, LoadAPIKeyError, type ModelMessage, type UIMessage } from "ai" +import { + APICallError, + convertToModelMessages, + LoadAPIKeyError, + type ModelMessage, + type UIMessage, +} from "ai" import { Identifier } from "../id/id" import { LSP } from "../lsp" import { Snapshot } from "@/snapshot" export namespace MessageV2 { export const OutputLengthError = NamedError.create("MessageOutputLengthError", z.object({})) - export const AbortedError = NamedError.create("MessageAbortedError", z.object({ message: z.string() })) + export const AbortedError = NamedError.create( + "MessageAbortedError", + z.object({ message: z.string() }), + ) export const AuthError = NamedError.create( "ProviderAuthError", z.object({ @@ -242,7 +251,12 @@ export namespace MessageV2 { export type ToolStateError = z.infer<typeof ToolStateError> export const ToolState = z - .discriminatedUnion("status", [ToolStatePending, ToolStateRunning, ToolStateCompleted, ToolStateError]) + .discriminatedUnion("status", [ + ToolStatePending, + ToolStateRunning, + ToolStateCompleted, + ToolStateError, + ]) .meta({ ref: "ToolState", }) @@ -313,7 +327,6 @@ export namespace MessageV2 { APIError.Schema, ]) .optional(), - system: z.string().array(), parentID: z.string(), modelID: z.string(), providerID: z.string(), @@ -397,7 +410,6 @@ export namespace MessageV2 { tokens: v1.metadata.assistant!.tokens, modelID: v1.metadata.assistant!.modelID, providerID: v1.metadata.assistant!.providerID, - system: v1.metadata.assistant!.system, mode: "build", error: v1.metadata.error, } @@ -440,7 +452,8 @@ export namespace MessageV2 { } } - const { title, time, ...metadata } = v1.metadata.tool[part.toolInvocation.toolCallId] ?? {} + const { title, time, ...metadata } = + v1.metadata.tool[part.toolInvocation.toolCallId] ?? {} if (part.toolInvocation.state === "call") { return { status: "running", @@ -541,7 +554,11 @@ export namespace MessageV2 { }, ] // text/plain and directory files are converted into text parts, ignore them - if (part.type === "file" && part.mime !== "text/plain" && part.mime !== "application/x-directory") + if ( + part.type === "file" && + part.mime !== "text/plain" && + part.mime !== "application/x-directory" + ) return [ { type: "file", @@ -600,7 +617,9 @@ export namespace MessageV2 { state: "output-available", toolCallId: part.callID, input: part.state.input, - output: part.state.time.compacted ? "[Old tool result content cleared]" : part.state.output, + output: part.state.time.compacted + ? "[Old tool result content cleared]" + : part.state.output, callProviderMetadata: part.metadata, }, ] diff --git a/packages/opencode/src/session/message.ts b/packages/opencode/src/session/message.ts index 4471f9235..baa8c00f1 100644 --- a/packages/opencode/src/session/message.ts +++ b/packages/opencode/src/session/message.ts @@ -51,9 +51,11 @@ export namespace Message { }) export type ToolResult = z.infer<typeof ToolResult> - export const ToolInvocation = z.discriminatedUnion("state", [ToolCall, ToolPartialCall, ToolResult]).meta({ - ref: "ToolInvocation", - }) + export const ToolInvocation = z + .discriminatedUnion("state", [ToolCall, ToolPartialCall, ToolResult]) + .meta({ + ref: "ToolInvocation", + }) export type ToolInvocation = z.infer<typeof ToolInvocation> export const TextPart = z @@ -122,7 +124,14 @@ export namespace Message { export type StepStartPart = z.infer<typeof StepStartPart> export const MessagePart = z - .discriminatedUnion("type", [TextPart, ReasoningPart, ToolInvocationPart, SourceUrlPart, FilePart, StepStartPart]) + .discriminatedUnion("type", [ + TextPart, + ReasoningPart, + ToolInvocationPart, + SourceUrlPart, + FilePart, + StepStartPart, + ]) .meta({ ref: "MessagePart", }) @@ -140,7 +149,11 @@ export namespace Message { completed: z.number().optional(), }), error: z - .discriminatedUnion("name", [AuthError.Schema, NamedError.Unknown.Schema, OutputLengthError.Schema]) + .discriminatedUnion("name", [ + AuthError.Schema, + NamedError.Unknown.Schema, + OutputLengthError.Schema, + ]) .optional(), sessionID: z.string(), tool: z.record( diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index a70045349..9072135f6 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -961,7 +961,6 @@ export namespace SessionPrompt { id: Identifier.ascending("message"), parentID, role: "assistant", - system: input.system, mode: input.agent, path: { cwd: Instance.directory, @@ -1412,7 +1411,6 @@ export namespace SessionPrompt { id: Identifier.ascending("message"), sessionID: input.sessionID, parentID: userMsg.id, - system: [], mode: input.agent, cost: 0, path: { @@ -1709,7 +1707,6 @@ export namespace SessionPrompt { id: Identifier.ascending("message"), sessionID: input.sessionID, parentID: userMsg.id, - system: [], mode: agentName, cost: 0, path: { diff --git a/packages/opencode/src/session/revert.ts b/packages/opencode/src/session/revert.ts index a88b5f08f..7439d59cf 100644 --- a/packages/opencode/src/session/revert.ts +++ b/packages/opencode/src/session/revert.ts @@ -45,7 +45,9 @@ export namespace SessionRevert { if (!revert) { if ((msg.info.id === input.messageID && !input.partID) || part.id === input.partID) { // if no useful parts left in message, same as reverting whole message - const partID = remaining.some((item) => ["text", "tool"].includes(item.type)) ? input.partID : undefined + const partID = remaining.some((item) => ["text", "tool"].includes(item.type)) + ? input.partID + : undefined revert = { messageID: !partID && lastUser ? lastUser.id : msg.info.id, partID, diff --git a/packages/opencode/src/session/system.ts b/packages/opencode/src/session/system.ts index 3173dcac5..3bff0772b 100644 --- a/packages/opencode/src/session/system.ts +++ b/packages/opencode/src/session/system.ts @@ -24,7 +24,8 @@ export namespace SystemPrompt { export function provider(modelID: string) { if (modelID.includes("gpt-5")) return [PROMPT_CODEX] - if (modelID.includes("gpt-") || modelID.includes("o1") || modelID.includes("o3")) return [PROMPT_BEAST] + if (modelID.includes("gpt-") || modelID.includes("o1") || modelID.includes("o3")) + return [PROMPT_BEAST] if (modelID.includes("gemini-")) return [PROMPT_GEMINI] if (modelID.includes("claude")) return [PROMPT_ANTHROPIC] return [PROMPT_ANTHROPIC_WITHOUT_TODO] @@ -99,7 +100,11 @@ export namespace SystemPrompt { }), ).catch(() => []) } else { - matches = await Filesystem.globUp(instruction, Instance.directory, Instance.worktree).catch(() => []) + matches = await Filesystem.globUp( + instruction, + Instance.directory, + Instance.worktree, + ).catch(() => []) } matches.forEach((path) => paths.add(path)) } diff --git a/packages/opencode/src/session/todo.ts b/packages/opencode/src/session/todo.ts index d52087739..4d9a2650d 100644 --- a/packages/opencode/src/session/todo.ts +++ b/packages/opencode/src/session/todo.ts @@ -6,7 +6,9 @@ export namespace Todo { export const Info = z .object({ content: z.string().describe("Brief description of the task"), - status: z.string().describe("Current status of the task: pending, in_progress, completed, cancelled"), + status: z + .string() + .describe("Current status of the task: pending, in_progress, completed, cancelled"), priority: z.string().describe("Priority level of the task: high, medium, low"), id: z.string().describe("Unique identifier for the todo item"), }) diff --git a/packages/opencode/src/share/share.ts b/packages/opencode/src/share/share.ts index 1006b23d5..d48d76f89 100644 --- a/packages/opencode/src/share/share.ts +++ b/packages/opencode/src/share/share.ts @@ -50,7 +50,10 @@ export namespace Share { await sync("session/info/" + evt.properties.info.id, evt.properties.info) }) Bus.subscribe(MessageV2.Event.Updated, async (evt) => { - await sync("session/message/" + evt.properties.info.sessionID + "/" + evt.properties.info.id, evt.properties.info) + await sync( + "session/message/" + evt.properties.info.sessionID + "/" + evt.properties.info.id, + evt.properties.info, + ) }) Bus.subscribe(MessageV2.Event.PartUpdated, async (evt) => { await sync( @@ -67,7 +70,9 @@ export namespace Share { export const URL = process.env["OPENCODE_API"] ?? - (Installation.isPreview() || Installation.isLocal() ? "https://api.dev.opencode.ai" : "https://api.opencode.ai") + (Installation.isPreview() || Installation.isLocal() + ? "https://api.dev.opencode.ai" + : "https://api.opencode.ai") export async function create(sessionID: string) { return fetch(`${URL}/share_create`, { diff --git a/packages/opencode/src/snapshot/index.ts b/packages/opencode/src/snapshot/index.ts index 98b316804..b4deee97c 100644 --- a/packages/opencode/src/snapshot/index.ts +++ b/packages/opencode/src/snapshot/index.ts @@ -27,7 +27,11 @@ export namespace Snapshot { log.info("initialized") } await $`git --git-dir ${git} add .`.quiet().cwd(Instance.directory).nothrow() - const hash = await $`git --git-dir ${git} write-tree`.quiet().cwd(Instance.directory).nothrow().text() + const hash = await $`git --git-dir ${git} write-tree` + .quiet() + .cwd(Instance.directory) + .nothrow() + .text() log.info("tracking", { hash, cwd: Instance.directory, git }) return hash.trim() } @@ -41,7 +45,10 @@ export namespace Snapshot { export async function patch(hash: string): Promise<Patch> { const git = gitdir() await $`git --git-dir ${git} add .`.quiet().cwd(Instance.directory).nothrow() - const result = await $`git --git-dir ${git} diff --name-only ${hash} -- .`.quiet().cwd(Instance.directory).nothrow() + const result = await $`git --git-dir ${git} diff --name-only ${hash} -- .` + .quiet() + .cwd(Instance.directory) + .nothrow() // If git diff fails, return empty patch if (result.exitCode !== 0) { @@ -64,10 +71,11 @@ export namespace Snapshot { export async function restore(snapshot: string) { log.info("restore", { commit: snapshot }) const git = gitdir() - const result = await $`git --git-dir=${git} read-tree ${snapshot} && git --git-dir=${git} checkout-index -a -f` - .quiet() - .cwd(Instance.worktree) - .nothrow() + const result = + await $`git --git-dir=${git} read-tree ${snapshot} && git --git-dir=${git} checkout-index -a -f` + .quiet() + .cwd(Instance.worktree) + .nothrow() if (result.exitCode !== 0) { log.error("failed to restore snapshot", { @@ -113,7 +121,10 @@ export namespace Snapshot { export async function diff(hash: string) { const git = gitdir() await $`git --git-dir ${git} add .`.quiet().cwd(Instance.directory).nothrow() - const result = await $`git --git-dir=${git} diff ${hash} -- .`.quiet().cwd(Instance.worktree).nothrow() + const result = await $`git --git-dir=${git} diff ${hash} -- .` + .quiet() + .cwd(Instance.worktree) + .nothrow() if (result.exitCode !== 0) { log.warn("failed to get diff", { diff --git a/packages/opencode/src/tool/edit.ts b/packages/opencode/src/tool/edit.ts index ba3d2c0bf..057fb9e8f 100644 --- a/packages/opencode/src/tool/edit.ts +++ b/packages/opencode/src/tool/edit.ts @@ -23,8 +23,13 @@ export const EditTool = Tool.define("edit", { parameters: z.object({ filePath: z.string().describe("The absolute path to the file to modify"), oldString: z.string().describe("The text to replace"), - newString: z.string().describe("The text to replace it with (must be different from oldString)"), - replaceAll: z.boolean().optional().describe("Replace all occurrences of oldString (default false)"), + newString: z + .string() + .describe("The text to replace it with (must be different from oldString)"), + replaceAll: z + .boolean() + .optional() + .describe("Replace all occurrences of oldString (default false)"), }), async execute(params, ctx) { if (!params.filePath) { @@ -35,7 +40,9 @@ export const EditTool = Tool.define("edit", { throw new Error("oldString and newString must be different") } - const filePath = path.isAbsolute(params.filePath) ? params.filePath : path.join(Instance.directory, params.filePath) + const filePath = path.isAbsolute(params.filePath) + ? params.filePath + : path.join(Instance.directory, params.filePath) if (!Filesystem.contains(Instance.directory, filePath)) { const parentDir = path.dirname(filePath) await Permission.ask({ @@ -172,7 +179,11 @@ function levenshtein(a: string, b: string): number { for (let i = 1; i <= a.length; i++) { for (let j = 1; j <= b.length; j++) { const cost = a[i - 1] === b[j - 1] ? 0 : 1 - matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost) + matrix[i][j] = Math.min( + matrix[i - 1][j] + 1, + matrix[i][j - 1] + 1, + matrix[i - 1][j - 1] + cost, + ) } } return matrix[a.length][b.length] @@ -374,7 +385,9 @@ export const WhitespaceNormalizedReplacer: Replacer = function* (content, find) // Find the actual substring in the original line that matches const words = find.trim().split(/\s+/) if (words.length > 0) { - const pattern = words.map((word) => word.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("\\s+") + const pattern = words + .map((word) => word.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")) + .join("\\s+") try { const regex = new RegExp(pattern) const match = line.match(regex) @@ -612,7 +625,12 @@ export function trimDiff(diff: string): string { return trimmedLines.join("\n") } -export function replace(content: string, oldString: string, newString: string, replaceAll = false): string { +export function replace( + content: string, + oldString: string, + newString: string, + replaceAll = false, +): string { if (oldString === newString) { throw new Error("oldString and newString must be different") } diff --git a/packages/opencode/src/tool/grep.ts b/packages/opencode/src/tool/grep.ts index 5390be21a..9f7d04ea1 100644 --- a/packages/opencode/src/tool/grep.ts +++ b/packages/opencode/src/tool/grep.ts @@ -9,8 +9,14 @@ export const GrepTool = Tool.define("grep", { description: DESCRIPTION, parameters: z.object({ pattern: z.string().describe("The regex pattern to search for in file contents"), - path: z.string().optional().describe("The directory to search in. Defaults to the current working directory."), - include: z.string().optional().describe('File pattern to include in the search (e.g. "*.js", "*.{ts,tsx}")'), + path: z + .string() + .optional() + .describe("The directory to search in. Defaults to the current working directory."), + include: z + .string() + .optional() + .describe('File pattern to include in the search (e.g. "*.js", "*.{ts,tsx}")'), }), async execute(params) { if (!params.pattern) { diff --git a/packages/opencode/src/tool/ls.ts b/packages/opencode/src/tool/ls.ts index 95c36e745..4fcfcaa8c 100644 --- a/packages/opencode/src/tool/ls.ts +++ b/packages/opencode/src/tool/ls.ts @@ -37,13 +37,18 @@ const LIMIT = 100 export const ListTool = Tool.define("list", { description: DESCRIPTION, parameters: z.object({ - path: z.string().describe("The absolute path to the directory to list (must be absolute, not relative)").optional(), + path: z + .string() + .describe("The absolute path to the directory to list (must be absolute, not relative)") + .optional(), ignore: z.array(z.string()).describe("List of glob patterns to ignore").optional(), }), async execute(params) { const searchPath = path.resolve(Instance.directory, params.path || ".") - const ignoreGlobs = IGNORE_PATTERNS.map((p) => `!${p}*`).concat(params.ignore?.map((p) => `!${p}`) || []) + const ignoreGlobs = IGNORE_PATTERNS.map((p) => `!${p}*`).concat( + params.ignore?.map((p) => `!${p}`) || [], + ) const files = [] for await (const file of Ripgrep.files({ cwd: searchPath, glob: ignoreGlobs })) { files.push(file) diff --git a/packages/opencode/src/tool/lsp-diagnostics.ts b/packages/opencode/src/tool/lsp-diagnostics.ts index 18a6868b6..78c8c3cae 100644 --- a/packages/opencode/src/tool/lsp-diagnostics.ts +++ b/packages/opencode/src/tool/lsp-diagnostics.ts @@ -11,7 +11,9 @@ export const LspDiagnosticTool = Tool.define("lsp_diagnostics", { path: z.string().describe("The path to the file to get diagnostics."), }), execute: async (args) => { - const normalized = path.isAbsolute(args.path) ? args.path : path.join(Instance.directory, args.path) + const normalized = path.isAbsolute(args.path) + ? args.path + : path.join(Instance.directory, args.path) await LSP.touchFile(normalized, true) const diagnostics = await LSP.diagnostics() const file = diagnostics[normalized] diff --git a/packages/opencode/src/tool/multiedit.ts b/packages/opencode/src/tool/multiedit.ts index 7f562f473..f3a657354 100644 --- a/packages/opencode/src/tool/multiedit.ts +++ b/packages/opencode/src/tool/multiedit.ts @@ -14,8 +14,13 @@ export const MultiEditTool = Tool.define("multiedit", { z.object({ filePath: z.string().describe("The absolute path to the file to modify"), oldString: z.string().describe("The text to replace"), - newString: z.string().describe("The text to replace it with (must be different from oldString)"), - replaceAll: z.boolean().optional().describe("Replace all occurrences of oldString (default false)"), + newString: z + .string() + .describe("The text to replace it with (must be different from oldString)"), + replaceAll: z + .boolean() + .optional() + .describe("Replace all occurrences of oldString (default false)"), }), ) .describe("Array of edit operations to perform sequentially on the file"), diff --git a/packages/opencode/src/tool/read.ts b/packages/opencode/src/tool/read.ts index 963636fd1..56a67bb03 100644 --- a/packages/opencode/src/tool/read.ts +++ b/packages/opencode/src/tool/read.ts @@ -18,7 +18,10 @@ export const ReadTool = Tool.define("read", { description: DESCRIPTION, parameters: z.object({ filePath: z.string().describe("The path to the file to read"), - offset: z.coerce.number().describe("The line number to start reading from (0-based)").optional(), + offset: z.coerce + .number() + .describe("The line number to start reading from (0-based)") + .optional(), limit: z.coerce.number().describe("The number of lines to read (defaults to 2000)").optional(), }), async execute(params, ctx) { @@ -53,13 +56,16 @@ export const ReadTool = Tool.define("read", { const suggestions = dirEntries .filter( (entry) => - entry.toLowerCase().includes(base.toLowerCase()) || base.toLowerCase().includes(entry.toLowerCase()), + entry.toLowerCase().includes(base.toLowerCase()) || + base.toLowerCase().includes(entry.toLowerCase()), ) .map((entry) => path.join(dir, entry)) .slice(0, 3) if (suggestions.length > 0) { - throw new Error(`File not found: ${filepath}\n\nDid you mean one of these?\n${suggestions.join("\n")}`) + throw new Error( + `File not found: ${filepath}\n\nDid you mean one of these?\n${suggestions.join("\n")}`, + ) } throw new Error(`File not found: ${filepath}`) diff --git a/packages/opencode/src/tool/registry.ts b/packages/opencode/src/tool/registry.ts index c4d54597d..6234a4e61 100644 --- a/packages/opencode/src/tool/registry.ts +++ b/packages/opencode/src/tool/registry.ts @@ -24,7 +24,12 @@ export namespace ToolRegistry { const glob = new Bun.Glob("tool/*.{js,ts}") for (const dir of await Config.directories()) { - for await (const match of glob.scan({ cwd: dir, absolute: true, followSymlinks: true, dot: true })) { + for await (const match of glob.scan({ + cwd: dir, + absolute: true, + followSymlinks: true, + dot: true, + })) { const namespace = path.basename(match, path.extname(match)) const mod = await import(match) for (const [id, def] of Object.entries<ToolDefinition>(mod)) { diff --git a/packages/opencode/src/tool/task.ts b/packages/opencode/src/tool/task.ts index 342645c30..ac0b204ba 100644 --- a/packages/opencode/src/tool/task.ts +++ b/packages/opencode/src/tool/task.ts @@ -14,7 +14,10 @@ export const TaskTool = Tool.define("task", async () => { const description = DESCRIPTION.replace( "{agents}", agents - .map((a) => `- ${a.name}: ${a.description ?? "This subagent should only be called manually by the user."}`) + .map( + (a) => + `- ${a.name}: ${a.description ?? "This subagent should only be called manually by the user."}`, + ) .join("\n"), ) return { @@ -26,7 +29,8 @@ export const TaskTool = Tool.define("task", async () => { }), async execute(params, ctx) { const agent = await Agent.get(params.subagent_type) - if (!agent) throw new Error(`Unknown agent type: ${params.subagent_type} is not a valid agent type`) + if (!agent) + throw new Error(`Unknown agent type: ${params.subagent_type} is not a valid agent type`) const session = await Session.create({ parentID: ctx.sessionID, title: params.description + ` (@${agent.name} subagent)`, @@ -91,7 +95,9 @@ export const TaskTool = Tool.define("task", async () => { let all all = await Session.messages(session.id) all = all.filter((x) => x.info.role === "assistant") - all = all.flatMap((msg) => msg.parts.filter((x: any) => x.type === "tool") as MessageV2.ToolPart[]) + all = all.flatMap( + (msg) => msg.parts.filter((x: any) => x.type === "tool") as MessageV2.ToolPart[], + ) return { title: params.description, metadata: { diff --git a/packages/opencode/src/tool/webfetch.ts b/packages/opencode/src/tool/webfetch.ts index 0333bb018..d85351ffe 100644 --- a/packages/opencode/src/tool/webfetch.ts +++ b/packages/opencode/src/tool/webfetch.ts @@ -48,13 +48,15 @@ export const WebFetchTool = Tool.define("webfetch", { let acceptHeader = "*/*" switch (params.format) { case "markdown": - acceptHeader = "text/markdown;q=1.0, text/x-markdown;q=0.9, text/plain;q=0.8, text/html;q=0.7, */*;q=0.1" + acceptHeader = + "text/markdown;q=1.0, text/x-markdown;q=0.9, text/plain;q=0.8, text/html;q=0.7, */*;q=0.1" break case "text": acceptHeader = "text/plain;q=1.0, text/markdown;q=0.9, text/html;q=0.8, */*;q=0.1" break case "html": - acceptHeader = "text/html;q=1.0, application/xhtml+xml;q=0.9, text/plain;q=0.8, text/markdown;q=0.7, */*;q=0.1" + acceptHeader = + "text/html;q=1.0, application/xhtml+xml;q=0.9, text/plain;q=0.8, text/markdown;q=0.7, */*;q=0.1" break default: acceptHeader = @@ -158,7 +160,9 @@ async function extractTextFromHTML(html: string) { .on("*", { element(element) { // Reset skip flag when entering other elements - if (!["script", "style", "noscript", "iframe", "object", "embed"].includes(element.tagName)) { + if ( + !["script", "style", "noscript", "iframe", "object", "embed"].includes(element.tagName) + ) { skipContent = false } }, diff --git a/packages/opencode/src/tool/write.ts b/packages/opencode/src/tool/write.ts index acaa12392..c7b998160 100644 --- a/packages/opencode/src/tool/write.ts +++ b/packages/opencode/src/tool/write.ts @@ -15,10 +15,14 @@ export const WriteTool = Tool.define("write", { description: DESCRIPTION, parameters: z.object({ content: z.string().describe("The content to write to the file"), - filePath: z.string().describe("The absolute path to the file to write (must be absolute, not relative)"), + filePath: z + .string() + .describe("The absolute path to the file to write (must be absolute, not relative)"), }), async execute(params, ctx) { - const filepath = path.isAbsolute(params.filePath) ? params.filePath : path.join(Instance.directory, params.filePath) + const filepath = path.isAbsolute(params.filePath) + ? params.filePath + : path.join(Instance.directory, params.filePath) if (!Filesystem.contains(Instance.directory, filepath)) { const parentDir = path.dirname(filepath) await Permission.ask({ diff --git a/packages/opencode/src/util/binary.ts b/packages/opencode/src/util/binary.ts index 3d8f61851..d72cc85d4 100644 --- a/packages/opencode/src/util/binary.ts +++ b/packages/opencode/src/util/binary.ts @@ -1,5 +1,9 @@ export namespace Binary { - export function search<T>(array: T[], id: string, compare: (item: T) => string): { found: boolean; index: number } { + export function search<T>( + array: T[], + id: string, + compare: (item: T) => string, + ): { found: boolean; index: number } { let left = 0 let right = array.length - 1 diff --git a/packages/opencode/src/util/defer.ts b/packages/opencode/src/util/defer.ts index 8de21528c..69b5c1788 100644 --- a/packages/opencode/src/util/defer.ts +++ b/packages/opencode/src/util/defer.ts @@ -1,6 +1,8 @@ export function defer<T extends () => void | Promise<void>>( fn: T, -): T extends () => Promise<void> ? { [Symbol.asyncDispose]: () => Promise<void> } : { [Symbol.dispose]: () => void } { +): T extends () => Promise<void> + ? { [Symbol.asyncDispose]: () => Promise<void> } + : { [Symbol.dispose]: () => void } { return { [Symbol.dispose]() { fn() diff --git a/packages/opencode/src/util/eventloop.ts b/packages/opencode/src/util/eventloop.ts index 87f6eef41..f7096d383 100644 --- a/packages/opencode/src/util/eventloop.ts +++ b/packages/opencode/src/util/eventloop.ts @@ -4,11 +4,17 @@ export namespace EventLoop { export async function wait() { return new Promise<void>((resolve) => { const check = () => { - const active = [...(process as any)._getActiveHandles(), ...(process as any)._getActiveRequests()] + const active = [ + ...(process as any)._getActiveHandles(), + ...(process as any)._getActiveRequests(), + ] Log.Default.info("eventloop", { active, }) - if ((process as any)._getActiveHandles().length === 0 && (process as any)._getActiveRequests().length === 0) { + if ( + (process as any)._getActiveHandles().length === 0 && + (process as any)._getActiveRequests().length === 0 + ) { resolve() } else { setImmediate(check) diff --git a/packages/opencode/src/util/lock.ts b/packages/opencode/src/util/lock.ts index 3aea64394..c503ddd33 100644 --- a/packages/opencode/src/util/lock.ts +++ b/packages/opencode/src/util/lock.ts @@ -39,7 +39,12 @@ export namespace Lock { } // Clean up empty locks - if (lock.readers === 0 && !lock.writer && lock.waitingReaders.length === 0 && lock.waitingWriters.length === 0) { + if ( + lock.readers === 0 && + !lock.writer && + lock.waitingReaders.length === 0 && + lock.waitingWriters.length === 0 + ) { locks.delete(key) } } diff --git a/packages/opencode/src/util/rpc.ts b/packages/opencode/src/util/rpc.ts index 57c695c48..981cc0714 100644 --- a/packages/opencode/src/util/rpc.ts +++ b/packages/opencode/src/util/rpc.ts @@ -30,7 +30,10 @@ export namespace Rpc { } } return { - call<Method extends keyof T>(method: Method, input: Parameters<T[Method]>[0]): Promise<ReturnType<T[Method]>> { + call<Method extends keyof T>( + method: Method, + input: Parameters<T[Method]>[0], + ): Promise<ReturnType<T[Method]>> { const requestId = id++ return new Promise((resolve) => { pending.set(requestId, resolve) diff --git a/packages/opencode/src/util/wildcard.ts b/packages/opencode/src/util/wildcard.ts index 9b595a0a9..feda96961 100644 --- a/packages/opencode/src/util/wildcard.ts +++ b/packages/opencode/src/util/wildcard.ts @@ -15,7 +15,11 @@ export namespace Wildcard { } export function all(input: string, patterns: Record<string, any>) { - const sorted = pipe(patterns, Object.entries, sortBy([([key]) => key.length, "asc"], [([key]) => key, "asc"])) + const sorted = pipe( + patterns, + Object.entries, + sortBy([([key]) => key.length, "asc"], [([key]) => key, "asc"]), + ) let result = undefined for (const [pattern, value] of sorted) { if (match(input, pattern)) { @@ -26,8 +30,15 @@ export namespace Wildcard { return result } - export function allStructured(input: { head: string; tail: string[] }, patterns: Record<string, any>) { - const sorted = pipe(patterns, Object.entries, sortBy([([key]) => key.length, "asc"], [([key]) => key, "asc"])) + export function allStructured( + input: { head: string; tail: string[] }, + patterns: Record<string, any>, + ) { + const sorted = pipe( + patterns, + Object.entries, + sortBy([([key]) => key.length, "asc"], [([key]) => key, "asc"]), + ) let result = undefined for (const [pattern, value] of sorted) { const parts = pattern.split(/\s+/) diff --git a/packages/opencode/sst-env.d.ts b/packages/opencode/sst-env.d.ts index b6a7e9066..0397645b5 100644 --- a/packages/opencode/sst-env.d.ts +++ b/packages/opencode/sst-env.d.ts @@ -6,4 +6,4 @@ /// <reference path="../../sst-env.d.ts" /> import "sst" -export {}
\ No newline at end of file +export {} diff --git a/packages/opencode/test/patch/patch.test.ts b/packages/opencode/test/patch/patch.test.ts index 51076c34f..020253bfe 100644 --- a/packages/opencode/test/patch/patch.test.ts +++ b/packages/opencode/test/patch/patch.test.ts @@ -6,23 +6,23 @@ import { tmpdir } from "os" describe("Patch namespace", () => { let tempDir: string - + beforeEach(async () => { tempDir = await fs.mkdtemp(path.join(tmpdir(), "patch-test-")) }) - + afterEach(async () => { // Clean up temp directory await fs.rm(tempDir, { recursive: true, force: true }) }) - + describe("parsePatch", () => { test("should parse simple add file patch", () => { const patchText = `*** Begin Patch *** Add File: test.txt +Hello World *** End Patch` - + const result = Patch.parsePatch(patchText) expect(result.hunks).toHaveLength(1) expect(result.hunks[0]).toEqual({ @@ -31,19 +31,19 @@ describe("Patch namespace", () => { contents: "Hello World", }) }) - + test("should parse delete file patch", () => { const patchText = `*** Begin Patch *** Delete File: old.txt *** End Patch` - + const result = Patch.parsePatch(patchText) expect(result.hunks).toHaveLength(1) const hunk = result.hunks[0] expect(hunk.type).toBe("delete") expect(hunk.path).toBe("old.txt") }) - + test("should parse patch with multiple hunks", () => { const patchText = `*** Begin Patch *** Add File: new.txt @@ -54,13 +54,13 @@ describe("Patch namespace", () => { -new line +updated line *** End Patch` - + const result = Patch.parsePatch(patchText) expect(result.hunks).toHaveLength(2) expect(result.hunks[0].type).toBe("add") expect(result.hunks[1].type).toBe("update") }) - + test("should parse file move operation", () => { const patchText = `*** Begin Patch *** Update File: old-name.txt @@ -69,7 +69,7 @@ describe("Patch namespace", () => { -Old content +New content *** End Patch` - + const result = Patch.parsePatch(patchText) expect(result.hunks).toHaveLength(1) const hunk = result.hunks[0] @@ -79,21 +79,21 @@ describe("Patch namespace", () => { expect(hunk.move_path).toBe("new-name.txt") } }) - + test("should throw error for invalid patch format", () => { const invalidPatch = `This is not a valid patch` - + expect(() => Patch.parsePatch(invalidPatch)).toThrow("Invalid patch format") }) }) - + describe("maybeParseApplyPatch", () => { test("should parse direct apply_patch command", () => { const patchText = `*** Begin Patch *** Add File: test.txt +Content *** End Patch` - + const result = Patch.maybeParseApplyPatch(["apply_patch", patchText]) expect(result.type).toBe(Patch.MaybeApplyPatch.Body) if (result.type === Patch.MaybeApplyPatch.Body) { @@ -101,17 +101,17 @@ describe("Patch namespace", () => { expect(result.args.hunks).toHaveLength(1) } }) - + test("should parse applypatch command", () => { const patchText = `*** Begin Patch *** Add File: test.txt +Content *** End Patch` - + const result = Patch.maybeParseApplyPatch(["applypatch", patchText]) expect(result.type).toBe(Patch.MaybeApplyPatch.Body) }) - + test("should handle bash heredoc format", () => { const script = `apply_patch <<'PATCH' *** Begin Patch @@ -119,20 +119,20 @@ describe("Patch namespace", () => { +Content *** End Patch PATCH` - + const result = Patch.maybeParseApplyPatch(["bash", "-lc", script]) expect(result.type).toBe(Patch.MaybeApplyPatch.Body) if (result.type === Patch.MaybeApplyPatch.Body) { expect(result.args.hunks).toHaveLength(1) } }) - + test("should return NotApplyPatch for non-patch commands", () => { const result = Patch.maybeParseApplyPatch(["echo", "hello"]) expect(result.type).toBe(Patch.MaybeApplyPatch.NotApplyPatch) }) }) - + describe("applyPatch", () => { test("should add a new file", async () => { const patchText = `*** Begin Patch @@ -140,36 +140,39 @@ PATCH` +Hello World +This is a new file *** End Patch` - + const result = await Patch.applyPatch(patchText) expect(result.added).toHaveLength(1) expect(result.modified).toHaveLength(0) expect(result.deleted).toHaveLength(0) - + const content = await fs.readFile(result.added[0], "utf-8") expect(content).toBe("Hello World\nThis is a new file") }) - + test("should delete an existing file", async () => { const filePath = path.join(tempDir, "to-delete.txt") await fs.writeFile(filePath, "This file will be deleted") - + const patchText = `*** Begin Patch *** Delete File: ${filePath} *** End Patch` - + const result = await Patch.applyPatch(patchText) expect(result.deleted).toHaveLength(1) expect(result.deleted[0]).toBe(filePath) - - const exists = await fs.access(filePath).then(() => true).catch(() => false) + + const exists = await fs + .access(filePath) + .then(() => true) + .catch(() => false) expect(exists).toBe(false) }) - + test("should update an existing file", async () => { const filePath = path.join(tempDir, "to-update.txt") await fs.writeFile(filePath, "line 1\nline 2\nline 3\n") - + const patchText = `*** Begin Patch *** Update File: ${filePath} @@ @@ -178,20 +181,20 @@ PATCH` +line 2 updated line 3 *** End Patch` - + const result = await Patch.applyPatch(patchText) expect(result.modified).toHaveLength(1) expect(result.modified[0]).toBe(filePath) - + const content = await fs.readFile(filePath, "utf-8") expect(content).toBe("line 1\nline 2 updated\nline 3\n") }) - + test("should move and update a file", async () => { const oldPath = path.join(tempDir, "old-name.txt") const newPath = path.join(tempDir, "new-name.txt") await fs.writeFile(oldPath, "old content\n") - + const patchText = `*** Begin Patch *** Update File: ${oldPath} *** Move to: ${newPath} @@ -199,26 +202,29 @@ PATCH` -old content +new content *** End Patch` - + const result = await Patch.applyPatch(patchText) expect(result.modified).toHaveLength(1) expect(result.modified[0]).toBe(newPath) - - const oldExists = await fs.access(oldPath).then(() => true).catch(() => false) + + const oldExists = await fs + .access(oldPath) + .then(() => true) + .catch(() => false) expect(oldExists).toBe(false) - + const newContent = await fs.readFile(newPath, "utf-8") expect(newContent).toBe("new content\n") }) - + test("should handle multiple operations in one patch", async () => { const file1 = path.join(tempDir, "file1.txt") const file2 = path.join(tempDir, "file2.txt") const file3 = path.join(tempDir, "file3.txt") - + await fs.writeFile(file1, "content 1") await fs.writeFile(file2, "content 2") - + const patchText = `*** Begin Patch *** Add File: ${file3} +new file content @@ -228,95 +234,98 @@ PATCH` +updated content 1 *** Delete File: ${file2} *** End Patch` - + const result = await Patch.applyPatch(patchText) expect(result.added).toHaveLength(1) expect(result.modified).toHaveLength(1) expect(result.deleted).toHaveLength(1) }) - + test("should create parent directories when adding files", async () => { const nestedPath = path.join(tempDir, "deep", "nested", "file.txt") - + const patchText = `*** Begin Patch *** Add File: ${nestedPath} +Deep nested content *** End Patch` - + const result = await Patch.applyPatch(patchText) expect(result.added).toHaveLength(1) expect(result.added[0]).toBe(nestedPath) - - const exists = await fs.access(nestedPath).then(() => true).catch(() => false) + + const exists = await fs + .access(nestedPath) + .then(() => true) + .catch(() => false) expect(exists).toBe(true) }) }) - + describe("error handling", () => { test("should throw error when updating non-existent file", async () => { const nonExistent = path.join(tempDir, "does-not-exist.txt") - + const patchText = `*** Begin Patch *** Update File: ${nonExistent} @@ -old line +new line *** End Patch` - + await expect(Patch.applyPatch(patchText)).rejects.toThrow() }) - + test("should throw error when deleting non-existent file", async () => { const nonExistent = path.join(tempDir, "does-not-exist.txt") - + const patchText = `*** Begin Patch *** Delete File: ${nonExistent} *** End Patch` - + await expect(Patch.applyPatch(patchText)).rejects.toThrow() }) }) - + describe("edge cases", () => { test("should handle empty files", async () => { const emptyFile = path.join(tempDir, "empty.txt") await fs.writeFile(emptyFile, "") - + const patchText = `*** Begin Patch *** Update File: ${emptyFile} @@ +First line *** End Patch` - + const result = await Patch.applyPatch(patchText) expect(result.modified).toHaveLength(1) - + const content = await fs.readFile(emptyFile, "utf-8") expect(content).toBe("First line\n") }) - + test("should handle files with no trailing newline", async () => { const filePath = path.join(tempDir, "no-newline.txt") await fs.writeFile(filePath, "no newline") - + const patchText = `*** Begin Patch *** Update File: ${filePath} @@ -no newline +has newline now *** End Patch` - + const result = await Patch.applyPatch(patchText) expect(result.modified).toHaveLength(1) - + const content = await fs.readFile(filePath, "utf-8") expect(content).toBe("has newline now\n") }) - + test("should handle multiple update chunks in single file", async () => { const filePath = path.join(tempDir, "multi-chunk.txt") await fs.writeFile(filePath, "line 1\nline 2\nline 3\nline 4\n") - + const patchText = `*** Begin Patch *** Update File: ${filePath} @@ @@ -328,12 +337,12 @@ PATCH` -line 4 +LINE 4 *** End Patch` - + const result = await Patch.applyPatch(patchText) expect(result.modified).toHaveLength(1) - + const content = await fs.readFile(filePath, "utf-8") expect(content).toBe("line 1\nLINE 2\nline 3\nLINE 4\n") }) }) -})
\ No newline at end of file +}) diff --git a/packages/opencode/test/session/retry.test.ts b/packages/opencode/test/session/retry.test.ts index edce412c2..ebcee80df 100644 --- a/packages/opencode/test/session/retry.test.ts +++ b/packages/opencode/test/session/retry.test.ts @@ -13,7 +13,9 @@ function apiError(headers?: Record<string, string>): MessageV2.APIError { describe("session.retry.getRetryDelayInMs", () => { test("doubles delay on each attempt when headers missing", () => { const error = apiError() - const delays = Array.from({ length: 7 }, (_, index) => SessionRetry.getRetryDelayInMs(error, index + 1)) + const delays = Array.from({ length: 7 }, (_, index) => + SessionRetry.getRetryDelayInMs(error, index + 1), + ) expect(delays).toStrictEqual([2000, 4000, 8000, 16000, 32000, 64000, 128000]) }) diff --git a/packages/opencode/test/util/wildcard.test.ts b/packages/opencode/test/util/wildcard.test.ts index f7f1e1545..968b4f288 100644 --- a/packages/opencode/test/util/wildcard.test.ts +++ b/packages/opencode/test/util/wildcard.test.ts @@ -24,9 +24,12 @@ test("allStructured matches command sequences", () => { "git status*": "allow", } expect(Wildcard.allStructured({ head: "git", tail: ["status", "--short"] }, rules)).toBe("allow") - expect(Wildcard.allStructured({ head: "npm", tail: ["run", "build", "--watch"] }, { "npm run *": "allow" })).toBe( - "allow", - ) + expect( + Wildcard.allStructured( + { head: "npm", tail: ["run", "build", "--watch"] }, + { "npm run *": "allow" }, + ), + ).toBe("allow") expect(Wildcard.allStructured({ head: "ls", tail: ["-la"] }, rules)).toBeUndefined() }) @@ -51,5 +54,7 @@ test("allStructured handles sed flags", () => { expect(Wildcard.allStructured({ head: "sed", tail: ["-i", "file"] }, rules)).toBe("ask") expect(Wildcard.allStructured({ head: "sed", tail: ["-i.bak", "file"] }, rules)).toBe("ask") expect(Wildcard.allStructured({ head: "sed", tail: ["-n", "1p", "file"] }, rules)).toBe("allow") - expect(Wildcard.allStructured({ head: "sed", tail: ["-i", "-n", "/./p", "myfile.txt"] }, rules)).toBe("ask") + expect( + Wildcard.allStructured({ head: "sed", tail: ["-i", "-n", "/./p", "myfile.txt"] }, rules), + ).toBe("ask") }) diff --git a/packages/plugin/package.json b/packages/plugin/package.json index c510b519b..9206efe1e 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -24,4 +24,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -}
\ No newline at end of file +} diff --git a/packages/plugin/src/index.ts b/packages/plugin/src/index.ts index f103749bd..1c8c6d2a1 100644 --- a/packages/plugin/src/index.ts +++ b/packages/plugin/src/index.ts @@ -151,7 +151,10 @@ export interface Hooks { input: { model: Model; provider: Provider; message: UserMessage }, output: { temperature: number; topP: number; options: Record<string, any> }, ) => Promise<void> - "permission.ask"?: (input: Permission, output: { status: "ask" | "deny" | "allow" }) => Promise<void> + "permission.ask"?: ( + input: Permission, + output: { status: "ask" | "deny" | "allow" }, + ) => Promise<void> "tool.execute.before"?: ( input: { tool: string; sessionID: string; callID: string }, output: { args: any }, diff --git a/packages/plugin/sst-env.d.ts b/packages/plugin/sst-env.d.ts index b6a7e9066..0397645b5 100644 --- a/packages/plugin/sst-env.d.ts +++ b/packages/plugin/sst-env.d.ts @@ -6,4 +6,4 @@ /// <reference path="../../sst-env.d.ts" /> import "sst" -export {}
\ No newline at end of file +export {} diff --git a/packages/script/sst-env.d.ts b/packages/script/sst-env.d.ts index b6a7e9066..0397645b5 100644 --- a/packages/script/sst-env.d.ts +++ b/packages/script/sst-env.d.ts @@ -6,4 +6,4 @@ /// <reference path="../../sst-env.d.ts" /> import "sst" -export {}
\ No newline at end of file +export {} diff --git a/packages/sdk/go/.github/workflows/ci.yml b/packages/sdk/go/.github/workflows/ci.yml index 4bf1e907c..0f5d45dc2 100644 --- a/packages/sdk/go/.github/workflows/ci.yml +++ b/packages/sdk/go/.github/workflows/ci.yml @@ -2,15 +2,15 @@ name: CI on: push: branches-ignore: - - 'generated' - - 'codegen/**' - - 'integrated/**' - - 'stl-preview-head/**' - - 'stl-preview-base/**' + - "generated" + - "codegen/**" + - "integrated/**" + - "stl-preview-head/**" + - "stl-preview-base/**" pull_request: branches-ignore: - - 'stl-preview-head/**' - - 'stl-preview-base/**' + - "stl-preview-head/**" + - "stl-preview-base/**" jobs: lint: diff --git a/packages/sdk/go/.release-please-manifest.json b/packages/sdk/go/.release-please-manifest.json index 4ad3fef33..5e39b9417 100644 --- a/packages/sdk/go/.release-please-manifest.json +++ b/packages/sdk/go/.release-please-manifest.json @@ -1,3 +1,3 @@ { ".": "0.18.0" -}
\ No newline at end of file +} diff --git a/packages/sdk/go/CHANGELOG.md b/packages/sdk/go/CHANGELOG.md index 498a78029..937fbfdd0 100644 --- a/packages/sdk/go/CHANGELOG.md +++ b/packages/sdk/go/CHANGELOG.md @@ -6,7 +6,7 @@ Full Changelog: [v0.17.0...v0.18.0](https://github.com/sst/opencode-sdk-go/compa ### Features -* **api:** api update ([0a7f5e7](https://github.com/sst/opencode-sdk-go/commit/0a7f5e710911506512a132ba39e0593c412beb77)) +- **api:** api update ([0a7f5e7](https://github.com/sst/opencode-sdk-go/commit/0a7f5e710911506512a132ba39e0593c412beb77)) ## 0.17.0 (2025-10-07) @@ -14,7 +14,7 @@ Full Changelog: [v0.16.2...v0.17.0](https://github.com/sst/opencode-sdk-go/compa ### Features -* **api:** api update ([84a3df5](https://github.com/sst/opencode-sdk-go/commit/84a3df50a7ff3d87e5593e4f29dfb5d561f71cc3)) +- **api:** api update ([84a3df5](https://github.com/sst/opencode-sdk-go/commit/84a3df50a7ff3d87e5593e4f29dfb5d561f71cc3)) ## 0.16.2 (2025-09-26) @@ -22,7 +22,7 @@ Full Changelog: [v0.16.1...v0.16.2](https://github.com/sst/opencode-sdk-go/compa ### Bug Fixes -* bugfix for setting JSON keys with special characters ([ac9a36f](https://github.com/sst/opencode-sdk-go/commit/ac9a36feb1c185ebf766d76909d0b86ac805e8a6)) +- bugfix for setting JSON keys with special characters ([ac9a36f](https://github.com/sst/opencode-sdk-go/commit/ac9a36feb1c185ebf766d76909d0b86ac805e8a6)) ## 0.16.1 (2025-09-20) @@ -30,14 +30,13 @@ Full Changelog: [v0.16.0...v0.16.1](https://github.com/sst/opencode-sdk-go/compa ### Bug Fixes -* use slices.Concat instead of sometimes modifying r.Options ([12e8b40](https://github.com/sst/opencode-sdk-go/commit/12e8b40809071095b0abb9b8031686353c8ac149)) - +- use slices.Concat instead of sometimes modifying r.Options ([12e8b40](https://github.com/sst/opencode-sdk-go/commit/12e8b40809071095b0abb9b8031686353c8ac149)) ### Chores -* bump minimum go version to 1.22 ([1a61c5c](https://github.com/sst/opencode-sdk-go/commit/1a61c5cc7e8f68cc1b0c219738cab530cb6aa3a2)) -* do not install brew dependencies in ./scripts/bootstrap by default ([f6d3eaf](https://github.com/sst/opencode-sdk-go/commit/f6d3eafffc20e124bbfae6ac5ddc1b1122ad3e27)) -* update more docs for 1.22 ([a3d0b0f](https://github.com/sst/opencode-sdk-go/commit/a3d0b0f26ed92ce1a6433f5bcf37a6436d268ba5)) +- bump minimum go version to 1.22 ([1a61c5c](https://github.com/sst/opencode-sdk-go/commit/1a61c5cc7e8f68cc1b0c219738cab530cb6aa3a2)) +- do not install brew dependencies in ./scripts/bootstrap by default ([f6d3eaf](https://github.com/sst/opencode-sdk-go/commit/f6d3eafffc20e124bbfae6ac5ddc1b1122ad3e27)) +- update more docs for 1.22 ([a3d0b0f](https://github.com/sst/opencode-sdk-go/commit/a3d0b0f26ed92ce1a6433f5bcf37a6436d268ba5)) ## 0.16.0 (2025-09-17) @@ -45,7 +44,7 @@ Full Changelog: [v0.15.0...v0.16.0](https://github.com/sst/opencode-sdk-go/compa ### Features -* **api:** api update ([46e978e](https://github.com/sst/opencode-sdk-go/commit/46e978e43aee733d5c1c09dc5be6d8ac2a752427)) +- **api:** api update ([46e978e](https://github.com/sst/opencode-sdk-go/commit/46e978e43aee733d5c1c09dc5be6d8ac2a752427)) ## 0.15.0 (2025-09-16) @@ -53,7 +52,7 @@ Full Changelog: [v0.14.0...v0.15.0](https://github.com/sst/opencode-sdk-go/compa ### Features -* **api:** api update ([397048f](https://github.com/sst/opencode-sdk-go/commit/397048faca7a1de7a028edd2254a0ad7797b151f)) +- **api:** api update ([397048f](https://github.com/sst/opencode-sdk-go/commit/397048faca7a1de7a028edd2254a0ad7797b151f)) ## 0.14.0 (2025-09-14) @@ -61,7 +60,7 @@ Full Changelog: [v0.13.0...v0.14.0](https://github.com/sst/opencode-sdk-go/compa ### Features -* **api:** api update ([dad0bc3](https://github.com/sst/opencode-sdk-go/commit/dad0bc3da99f20a0d002a6b94e049fb70f8e6a77)) +- **api:** api update ([dad0bc3](https://github.com/sst/opencode-sdk-go/commit/dad0bc3da99f20a0d002a6b94e049fb70f8e6a77)) ## 0.13.0 (2025-09-14) @@ -69,7 +68,7 @@ Full Changelog: [v0.12.0...v0.13.0](https://github.com/sst/opencode-sdk-go/compa ### Features -* **api:** api update ([80da4fb](https://github.com/sst/opencode-sdk-go/commit/80da4fb4ea9c6afb51a7e7135d9f5560ce6f2a6c)) +- **api:** api update ([80da4fb](https://github.com/sst/opencode-sdk-go/commit/80da4fb4ea9c6afb51a7e7135d9f5560ce6f2a6c)) ## 0.12.0 (2025-09-14) @@ -77,7 +76,7 @@ Full Changelog: [v0.11.0...v0.12.0](https://github.com/sst/opencode-sdk-go/compa ### Features -* **api:** api update ([7e3808b](https://github.com/sst/opencode-sdk-go/commit/7e3808ba349dc653174b32b48a1120c18d2975c2)) +- **api:** api update ([7e3808b](https://github.com/sst/opencode-sdk-go/commit/7e3808ba349dc653174b32b48a1120c18d2975c2)) ## 0.11.0 (2025-09-14) @@ -85,7 +84,7 @@ Full Changelog: [v0.10.0...v0.11.0](https://github.com/sst/opencode-sdk-go/compa ### Features -* **api:** api update ([a3d37f5](https://github.com/sst/opencode-sdk-go/commit/a3d37f5671545866547d351fc21b49809cc8b3c2)) +- **api:** api update ([a3d37f5](https://github.com/sst/opencode-sdk-go/commit/a3d37f5671545866547d351fc21b49809cc8b3c2)) ## 0.10.0 (2025-09-11) @@ -93,7 +92,7 @@ Full Changelog: [v0.9.0...v0.10.0](https://github.com/sst/opencode-sdk-go/compar ### Features -* **api:** api update ([0dc01f6](https://github.com/sst/opencode-sdk-go/commit/0dc01f6695c9b8400a4dc92166c5002bb120cf50)) +- **api:** api update ([0dc01f6](https://github.com/sst/opencode-sdk-go/commit/0dc01f6695c9b8400a4dc92166c5002bb120cf50)) ## 0.9.0 (2025-09-10) @@ -101,7 +100,7 @@ Full Changelog: [v0.8.0...v0.9.0](https://github.com/sst/opencode-sdk-go/compare ### Features -* **api:** api update ([2d3a28d](https://github.com/sst/opencode-sdk-go/commit/2d3a28df5657845aa4d73087e1737d1fc8c3ce1c)) +- **api:** api update ([2d3a28d](https://github.com/sst/opencode-sdk-go/commit/2d3a28df5657845aa4d73087e1737d1fc8c3ce1c)) ## 0.8.0 (2025-09-01) @@ -109,7 +108,7 @@ Full Changelog: [v0.7.0...v0.8.0](https://github.com/sst/opencode-sdk-go/compare ### Features -* **api:** api update ([ae87a71](https://github.com/sst/opencode-sdk-go/commit/ae87a71949994590ace8285a39f0991ef34b664d)) +- **api:** api update ([ae87a71](https://github.com/sst/opencode-sdk-go/commit/ae87a71949994590ace8285a39f0991ef34b664d)) ## 0.7.0 (2025-09-01) @@ -117,7 +116,7 @@ Full Changelog: [v0.6.0...v0.7.0](https://github.com/sst/opencode-sdk-go/compare ### Features -* **api:** api update ([64bb1b1](https://github.com/sst/opencode-sdk-go/commit/64bb1b1ee0cbe153abc6fb7bd9703b47911724d4)) +- **api:** api update ([64bb1b1](https://github.com/sst/opencode-sdk-go/commit/64bb1b1ee0cbe153abc6fb7bd9703b47911724d4)) ## 0.6.0 (2025-09-01) @@ -125,7 +124,7 @@ Full Changelog: [v0.5.0...v0.6.0](https://github.com/sst/opencode-sdk-go/compare ### Features -* **api:** api update ([928e384](https://github.com/sst/opencode-sdk-go/commit/928e3843355f96899f046f002b84372281dad0c8)) +- **api:** api update ([928e384](https://github.com/sst/opencode-sdk-go/commit/928e3843355f96899f046f002b84372281dad0c8)) ## 0.5.0 (2025-08-31) @@ -133,7 +132,7 @@ Full Changelog: [v0.4.0...v0.5.0](https://github.com/sst/opencode-sdk-go/compare ### Features -* **api:** api update ([44b281d](https://github.com/sst/opencode-sdk-go/commit/44b281d0bb39c5022a984ac9d0fca1529ccc0604)) +- **api:** api update ([44b281d](https://github.com/sst/opencode-sdk-go/commit/44b281d0bb39c5022a984ac9d0fca1529ccc0604)) ## 0.4.0 (2025-08-31) @@ -141,7 +140,7 @@ Full Changelog: [v0.3.0...v0.4.0](https://github.com/sst/opencode-sdk-go/compare ### Features -* **api:** api update ([fa9d6ec](https://github.com/sst/opencode-sdk-go/commit/fa9d6ec6472e62f4f6605d0a71a7aa8bf8a24559)) +- **api:** api update ([fa9d6ec](https://github.com/sst/opencode-sdk-go/commit/fa9d6ec6472e62f4f6605d0a71a7aa8bf8a24559)) ## 0.3.0 (2025-08-31) @@ -149,7 +148,7 @@ Full Changelog: [v0.2.0...v0.3.0](https://github.com/sst/opencode-sdk-go/compare ### Features -* **api:** api update ([aae1c06](https://github.com/sst/opencode-sdk-go/commit/aae1c06bb5a93a1cd9c589846a84b3f16246f5da)) +- **api:** api update ([aae1c06](https://github.com/sst/opencode-sdk-go/commit/aae1c06bb5a93a1cd9c589846a84b3f16246f5da)) ## 0.2.0 (2025-08-31) @@ -157,7 +156,7 @@ Full Changelog: [v0.1.0...v0.2.0](https://github.com/sst/opencode-sdk-go/compare ### Features -* **api:** api update ([1472790](https://github.com/sst/opencode-sdk-go/commit/1472790542515f47bd46e2a9e28d8afea024cf9c)) +- **api:** api update ([1472790](https://github.com/sst/opencode-sdk-go/commit/1472790542515f47bd46e2a9e28d8afea024cf9c)) ## 0.1.0 (2025-08-31) @@ -165,61 +164,59 @@ Full Changelog: [v0.0.1...v0.1.0](https://github.com/sst/opencode-sdk-go/compare ### Features -* **api:** api update ([3f03ddd](https://github.com/sst/opencode-sdk-go/commit/3f03dddd5ec0de98f99ce48679077dcae9ceffd6)) -* **api:** api update ([e9f79c4](https://github.com/sst/opencode-sdk-go/commit/e9f79c4792b21ef64ab0431ffd76f5a71e04d182)) -* **api:** api update ([139a686](https://github.com/sst/opencode-sdk-go/commit/139a6862d2f0ab0c8ea791663d736868be3e96e6)) -* **api:** api update ([2ed0800](https://github.com/sst/opencode-sdk-go/commit/2ed0800b2c5b99877e9f7fde669a6c005fad6b77)) -* **api:** api update ([88a87a4](https://github.com/sst/opencode-sdk-go/commit/88a87a458f56ce0c18b502c73da933f614f56e8b)) -* **api:** api update ([0e5d65b](https://github.com/sst/opencode-sdk-go/commit/0e5d65b571e7b30dc6347e6730098878ebba3a42)) -* **api:** api update ([ba381f1](https://github.com/sst/opencode-sdk-go/commit/ba381f1e07aad24e9824df7d53befae2a644f69f)) -* **api:** api update ([3f429f5](https://github.com/sst/opencode-sdk-go/commit/3f429f5b4be5607433ef5fdc0d5bf67fe590d039)) -* **api:** api update ([9f34787](https://github.com/sst/opencode-sdk-go/commit/9f347876b35b7f898060c1a5f71c322e95978e3e)) -* **api:** api update ([379c8e0](https://github.com/sst/opencode-sdk-go/commit/379c8e00197e13aebaf2f2d61277b125f1f90011)) -* **api:** api update ([550511c](https://github.com/sst/opencode-sdk-go/commit/550511c4c5b5055ac8ff22b7b11731331bd9d088)) -* **api:** api update ([547f0c2](https://github.com/sst/opencode-sdk-go/commit/547f0c262f2df1ce83eaa7267d68be64bb29b841)) -* **api:** api update ([b7b0720](https://github.com/sst/opencode-sdk-go/commit/b7b07204bff314da24b1819c128835a43ef64065)) -* **api:** api update ([7250ffc](https://github.com/sst/opencode-sdk-go/commit/7250ffcba262b916c958ddecc2a42927982db39f)) -* **api:** api update ([17fbab7](https://github.com/sst/opencode-sdk-go/commit/17fbab73111a3eae488737c69b12370bc69c65f7)) -* **api:** api update ([1270b5c](https://github.com/sst/opencode-sdk-go/commit/1270b5cd81e6ac769dcd92ade6d877891bf51bd5)) -* **api:** api update ([a238d4a](https://github.com/sst/opencode-sdk-go/commit/a238d4abd6ed7d15f3547d27a4b6ecf4aec8431e)) -* **api:** api update ([7475655](https://github.com/sst/opencode-sdk-go/commit/7475655aca577fe4f807c2f02f92171f6a358e9c)) -* **api:** api update ([429d258](https://github.com/sst/opencode-sdk-go/commit/429d258bb56e9cdeb1528be3944bf5537ac26a96)) -* **api:** api update ([f250915](https://github.com/sst/opencode-sdk-go/commit/f2509157eaf1b453e741ee9482127cad2e3ace25)) -* **api:** api update ([5efc987](https://github.com/sst/opencode-sdk-go/commit/5efc987353801d1e772c20edf162b1c75da32743)) -* **api:** api update ([98a8350](https://github.com/sst/opencode-sdk-go/commit/98a83504f7cfc361e83314c3e79a4e9ff53f0560)) -* **api:** api update ([6da8bf8](https://github.com/sst/opencode-sdk-go/commit/6da8bf8bfe91d45991fb580753d77c5534fc0b1b)) -* **api:** api update ([f8c7148](https://github.com/sst/opencode-sdk-go/commit/f8c7148ae56143823186e2675a78e82676154956)) -* **api:** manual updates ([7cf038f](https://github.com/sst/opencode-sdk-go/commit/7cf038ffae5da1b77e1cef11b5fa166a53b467f2)) -* **api:** update via SDK Studio ([068a0eb](https://github.com/sst/opencode-sdk-go/commit/068a0eb025010da0c8d86fa1bb496a39dbedcef9)) -* **api:** update via SDK Studio ([ca651ed](https://github.com/sst/opencode-sdk-go/commit/ca651edaf71d1f3678f929287474f5bc4f1aad10)) -* **api:** update via SDK Studio ([13550a5](https://github.com/sst/opencode-sdk-go/commit/13550a5c65d77325e945ed99fe0799cd1107b775)) -* **api:** update via SDK Studio ([7b73730](https://github.com/sst/opencode-sdk-go/commit/7b73730c7fa62ba966dda3541c3e97b49be8d2bf)) -* **api:** update via SDK Studio ([9e39a59](https://github.com/sst/opencode-sdk-go/commit/9e39a59b3d5d1bd5e64633732521fb28362cc70e)) -* **api:** update via SDK Studio ([9609d1b](https://github.com/sst/opencode-sdk-go/commit/9609d1b1db7806d00cb846c9914cb4935cdedf52)) -* **api:** update via SDK Studio ([51315fa](https://github.com/sst/opencode-sdk-go/commit/51315fa2eae424743ea79701e67d44447c44144d)) -* **api:** update via SDK Studio ([af07955](https://github.com/sst/opencode-sdk-go/commit/af0795543240aefaf04fc7663a348825541c79ed)) -* **api:** update via SDK Studio ([5e3468a](https://github.com/sst/opencode-sdk-go/commit/5e3468a0aaa5ed3b13e019c3a24e0ba9147d1675)) -* **api:** update via SDK Studio ([0a73e04](https://github.com/sst/opencode-sdk-go/commit/0a73e04c23c90b2061611edaa8fd6282dc0ce397)) -* **api:** update via SDK Studio ([9b7883a](https://github.com/sst/opencode-sdk-go/commit/9b7883a144eeac526d9d04538e0876a9d18bb844)) -* **client:** expand max streaming buffer size ([76303e5](https://github.com/sst/opencode-sdk-go/commit/76303e51067e78e732af26ced9d83b8bad7655c3)) -* **client:** support optional json html escaping ([449748f](https://github.com/sst/opencode-sdk-go/commit/449748f35a1d8cb6f91dc36d25bf9489f4f371bd)) - +- **api:** api update ([3f03ddd](https://github.com/sst/opencode-sdk-go/commit/3f03dddd5ec0de98f99ce48679077dcae9ceffd6)) +- **api:** api update ([e9f79c4](https://github.com/sst/opencode-sdk-go/commit/e9f79c4792b21ef64ab0431ffd76f5a71e04d182)) +- **api:** api update ([139a686](https://github.com/sst/opencode-sdk-go/commit/139a6862d2f0ab0c8ea791663d736868be3e96e6)) +- **api:** api update ([2ed0800](https://github.com/sst/opencode-sdk-go/commit/2ed0800b2c5b99877e9f7fde669a6c005fad6b77)) +- **api:** api update ([88a87a4](https://github.com/sst/opencode-sdk-go/commit/88a87a458f56ce0c18b502c73da933f614f56e8b)) +- **api:** api update ([0e5d65b](https://github.com/sst/opencode-sdk-go/commit/0e5d65b571e7b30dc6347e6730098878ebba3a42)) +- **api:** api update ([ba381f1](https://github.com/sst/opencode-sdk-go/commit/ba381f1e07aad24e9824df7d53befae2a644f69f)) +- **api:** api update ([3f429f5](https://github.com/sst/opencode-sdk-go/commit/3f429f5b4be5607433ef5fdc0d5bf67fe590d039)) +- **api:** api update ([9f34787](https://github.com/sst/opencode-sdk-go/commit/9f347876b35b7f898060c1a5f71c322e95978e3e)) +- **api:** api update ([379c8e0](https://github.com/sst/opencode-sdk-go/commit/379c8e00197e13aebaf2f2d61277b125f1f90011)) +- **api:** api update ([550511c](https://github.com/sst/opencode-sdk-go/commit/550511c4c5b5055ac8ff22b7b11731331bd9d088)) +- **api:** api update ([547f0c2](https://github.com/sst/opencode-sdk-go/commit/547f0c262f2df1ce83eaa7267d68be64bb29b841)) +- **api:** api update ([b7b0720](https://github.com/sst/opencode-sdk-go/commit/b7b07204bff314da24b1819c128835a43ef64065)) +- **api:** api update ([7250ffc](https://github.com/sst/opencode-sdk-go/commit/7250ffcba262b916c958ddecc2a42927982db39f)) +- **api:** api update ([17fbab7](https://github.com/sst/opencode-sdk-go/commit/17fbab73111a3eae488737c69b12370bc69c65f7)) +- **api:** api update ([1270b5c](https://github.com/sst/opencode-sdk-go/commit/1270b5cd81e6ac769dcd92ade6d877891bf51bd5)) +- **api:** api update ([a238d4a](https://github.com/sst/opencode-sdk-go/commit/a238d4abd6ed7d15f3547d27a4b6ecf4aec8431e)) +- **api:** api update ([7475655](https://github.com/sst/opencode-sdk-go/commit/7475655aca577fe4f807c2f02f92171f6a358e9c)) +- **api:** api update ([429d258](https://github.com/sst/opencode-sdk-go/commit/429d258bb56e9cdeb1528be3944bf5537ac26a96)) +- **api:** api update ([f250915](https://github.com/sst/opencode-sdk-go/commit/f2509157eaf1b453e741ee9482127cad2e3ace25)) +- **api:** api update ([5efc987](https://github.com/sst/opencode-sdk-go/commit/5efc987353801d1e772c20edf162b1c75da32743)) +- **api:** api update ([98a8350](https://github.com/sst/opencode-sdk-go/commit/98a83504f7cfc361e83314c3e79a4e9ff53f0560)) +- **api:** api update ([6da8bf8](https://github.com/sst/opencode-sdk-go/commit/6da8bf8bfe91d45991fb580753d77c5534fc0b1b)) +- **api:** api update ([f8c7148](https://github.com/sst/opencode-sdk-go/commit/f8c7148ae56143823186e2675a78e82676154956)) +- **api:** manual updates ([7cf038f](https://github.com/sst/opencode-sdk-go/commit/7cf038ffae5da1b77e1cef11b5fa166a53b467f2)) +- **api:** update via SDK Studio ([068a0eb](https://github.com/sst/opencode-sdk-go/commit/068a0eb025010da0c8d86fa1bb496a39dbedcef9)) +- **api:** update via SDK Studio ([ca651ed](https://github.com/sst/opencode-sdk-go/commit/ca651edaf71d1f3678f929287474f5bc4f1aad10)) +- **api:** update via SDK Studio ([13550a5](https://github.com/sst/opencode-sdk-go/commit/13550a5c65d77325e945ed99fe0799cd1107b775)) +- **api:** update via SDK Studio ([7b73730](https://github.com/sst/opencode-sdk-go/commit/7b73730c7fa62ba966dda3541c3e97b49be8d2bf)) +- **api:** update via SDK Studio ([9e39a59](https://github.com/sst/opencode-sdk-go/commit/9e39a59b3d5d1bd5e64633732521fb28362cc70e)) +- **api:** update via SDK Studio ([9609d1b](https://github.com/sst/opencode-sdk-go/commit/9609d1b1db7806d00cb846c9914cb4935cdedf52)) +- **api:** update via SDK Studio ([51315fa](https://github.com/sst/opencode-sdk-go/commit/51315fa2eae424743ea79701e67d44447c44144d)) +- **api:** update via SDK Studio ([af07955](https://github.com/sst/opencode-sdk-go/commit/af0795543240aefaf04fc7663a348825541c79ed)) +- **api:** update via SDK Studio ([5e3468a](https://github.com/sst/opencode-sdk-go/commit/5e3468a0aaa5ed3b13e019c3a24e0ba9147d1675)) +- **api:** update via SDK Studio ([0a73e04](https://github.com/sst/opencode-sdk-go/commit/0a73e04c23c90b2061611edaa8fd6282dc0ce397)) +- **api:** update via SDK Studio ([9b7883a](https://github.com/sst/opencode-sdk-go/commit/9b7883a144eeac526d9d04538e0876a9d18bb844)) +- **client:** expand max streaming buffer size ([76303e5](https://github.com/sst/opencode-sdk-go/commit/76303e51067e78e732af26ced9d83b8bad7655c3)) +- **client:** support optional json html escaping ([449748f](https://github.com/sst/opencode-sdk-go/commit/449748f35a1d8cb6f91dc36d25bf9489f4f371bd)) ### Bug Fixes -* **client:** process custom base url ahead of time ([9b360d6](https://github.com/sst/opencode-sdk-go/commit/9b360d642cf6f302104308af5622e17099899e5f)) -* **client:** resolve lint errors in streaming tests ([4d36cb0](https://github.com/sst/opencode-sdk-go/commit/4d36cb09fc9d436734d5dab1c499acaa88568ff7)) -* close body before retrying ([4da3f7f](https://github.com/sst/opencode-sdk-go/commit/4da3f7f372bad222a189ba3eabcfde3373166ae5)) -* don't try to deserialize as json when ResponseBodyInto is []byte ([595291f](https://github.com/sst/opencode-sdk-go/commit/595291f6dba6af472f160b9f8e3d145002f43a4a)) - +- **client:** process custom base url ahead of time ([9b360d6](https://github.com/sst/opencode-sdk-go/commit/9b360d642cf6f302104308af5622e17099899e5f)) +- **client:** resolve lint errors in streaming tests ([4d36cb0](https://github.com/sst/opencode-sdk-go/commit/4d36cb09fc9d436734d5dab1c499acaa88568ff7)) +- close body before retrying ([4da3f7f](https://github.com/sst/opencode-sdk-go/commit/4da3f7f372bad222a189ba3eabcfde3373166ae5)) +- don't try to deserialize as json when ResponseBodyInto is []byte ([595291f](https://github.com/sst/opencode-sdk-go/commit/595291f6dba6af472f160b9f8e3d145002f43a4a)) ### Chores -* **ci:** only run for pushes and fork pull requests ([bea59b8](https://github.com/sst/opencode-sdk-go/commit/bea59b886800ef555f89c47a9256d6392ed2e53d)) -* **internal:** codegen related update ([6a22ce6](https://github.com/sst/opencode-sdk-go/commit/6a22ce6df155f5003e80b8a75686a9e513a5568a)) -* **internal:** fix lint script for tests ([391c482](https://github.com/sst/opencode-sdk-go/commit/391c482148ed0a77c4ad52807abeb2d540b56797)) -* **internal:** update comment in script ([b7f1c3e](https://github.com/sst/opencode-sdk-go/commit/b7f1c3e16935c71e243004b8f321d661cd8e9474)) -* lint tests ([616796b](https://github.com/sst/opencode-sdk-go/commit/616796b761704bde6be5c6c2428f28c79c7f05ff)) -* lint tests in subpackages ([50c82ff](https://github.com/sst/opencode-sdk-go/commit/50c82ff0757c973834b68adc22566b70f767b611)) -* sync repo ([2f34d5d](https://github.com/sst/opencode-sdk-go/commit/2f34d5d53e56e9cdc3df99be7ee7efc83dd977a3)) -* update @stainless-api/prism-cli to v5.15.0 ([2f24852](https://github.com/sst/opencode-sdk-go/commit/2f2485216d4f4891d1fbfbc23ff8410c2f35152a)) +- **ci:** only run for pushes and fork pull requests ([bea59b8](https://github.com/sst/opencode-sdk-go/commit/bea59b886800ef555f89c47a9256d6392ed2e53d)) +- **internal:** codegen related update ([6a22ce6](https://github.com/sst/opencode-sdk-go/commit/6a22ce6df155f5003e80b8a75686a9e513a5568a)) +- **internal:** fix lint script for tests ([391c482](https://github.com/sst/opencode-sdk-go/commit/391c482148ed0a77c4ad52807abeb2d540b56797)) +- **internal:** update comment in script ([b7f1c3e](https://github.com/sst/opencode-sdk-go/commit/b7f1c3e16935c71e243004b8f321d661cd8e9474)) +- lint tests ([616796b](https://github.com/sst/opencode-sdk-go/commit/616796b761704bde6be5c6c2428f28c79c7f05ff)) +- lint tests in subpackages ([50c82ff](https://github.com/sst/opencode-sdk-go/commit/50c82ff0757c973834b68adc22566b70f767b611)) +- sync repo ([2f34d5d](https://github.com/sst/opencode-sdk-go/commit/2f34d5d53e56e9cdc3df99be7ee7efc83dd977a3)) +- update @stainless-api/prism-cli to v5.15.0 ([2f24852](https://github.com/sst/opencode-sdk-go/commit/2f2485216d4f4891d1fbfbc23ff8410c2f35152a)) diff --git a/packages/sdk/go/release-please-config.json b/packages/sdk/go/release-please-config.json index a38198eca..32960ce27 100644 --- a/packages/sdk/go/release-please-config.json +++ b/packages/sdk/go/release-please-config.json @@ -60,8 +60,5 @@ } ], "release-type": "go", - "extra-files": [ - "internal/version.go", - "README.md" - ] -}
\ No newline at end of file + "extra-files": ["internal/version.go", "README.md"] +} diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 97830ba1b..bff4866a0 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -26,4 +26,4 @@ "publishConfig": { "directory": "dist" } -}
\ No newline at end of file +} diff --git a/packages/sdk/js/src/server.ts b/packages/sdk/js/src/server.ts index a09e14ab2..151477457 100644 --- a/packages/sdk/js/src/server.ts +++ b/packages/sdk/js/src/server.ts @@ -28,13 +28,17 @@ export async function createOpencodeServer(options?: ServerOptions) { options ?? {}, ) - const proc = spawn(`opencode`, [`serve`, `--hostname=${options.hostname}`, `--port=${options.port}`], { - signal: options.signal, - env: { - ...process.env, - OPENCODE_CONFIG_CONTENT: JSON.stringify(options.config ?? {}), + const proc = spawn( + `opencode`, + [`serve`, `--hostname=${options.hostname}`, `--port=${options.port}`], + { + signal: options.signal, + env: { + ...process.env, + OPENCODE_CONFIG_CONTENT: JSON.stringify(options.config ?? {}), + }, }, - }) + ) const url = await new Promise<string>((resolve, reject) => { const id = setTimeout(() => { diff --git a/packages/sdk/js/sst-env.d.ts b/packages/sdk/js/sst-env.d.ts index 9b9de7327..bd5588217 100644 --- a/packages/sdk/js/sst-env.d.ts +++ b/packages/sdk/js/sst-env.d.ts @@ -6,4 +6,4 @@ /// <reference path="../../../sst-env.d.ts" /> import "sst" -export {}
\ No newline at end of file +export {} diff --git a/packages/sdk/python/README.md b/packages/sdk/python/README.md index a17c36ab3..5d54434af 100644 --- a/packages/sdk/python/README.md +++ b/packages/sdk/python/README.md @@ -2,50 +2,59 @@ This package provides a Python SDK for the Opencode API. It is generated using openapi-python-client (not Stainless). - Documentation + - Full docs: see `mkdocs` site under `packages/sdk/python/docs/` - Preview locally: + ```bash uv run --project packages/sdk/python mkdocs serve -f packages/sdk/python/mkdocs.yml ``` Badges + - PyPI: https://img.shields.io/pypi/v/opencode-ai?style=flat-square Requirements + - Python 3.8+ - uv (recommended) -> https://docs.astral.sh/uv/ - openapi-python-client (invoked via `uvx`) Install uv + ```bash # macOS/Linux curl -LsSf https://astral.sh/uv/install.sh | sh ``` Set up the environment (from this directory) + ```bash uv sync --dev ``` Generate client code (from CLI-generated spec) + ```bash # From repository root OR from this directory uv run python packages/sdk/python/scripts/generate.py --source cli ``` Alternatively, fetch spec from a running server + ```bash uv run python packages/sdk/python/scripts/generate.py --source server --server-url http://localhost:4096/doc ``` This will: -1) Produce an OpenAPI spec from the local CLI or a running server -2) Run openapi-python-client (via `uvx`) to generate client code -3) Copy the generated Python package into src/opencode_ai + +1. Produce an OpenAPI spec from the local CLI or a running server +2. Run openapi-python-client (via `uvx`) to generate client code +3. Copy the generated Python package into src/opencode_ai Usage (after generation) + ```python from opencode_ai import OpenCodeClient @@ -77,6 +86,7 @@ client = OpenCodeClient(retries=2, backoff_factor=0.1) ``` Notes + - We intentionally do not use Stainless for the Python SDK. - The generator targets OpenAPI 3.1 emitted by the opencode server at /doc. - See scripts/generate.py for details and customization points. diff --git a/packages/sdk/python/docs/generation.md b/packages/sdk/python/docs/generation.md index f949760a1..2151e3709 100644 --- a/packages/sdk/python/docs/generation.md +++ b/packages/sdk/python/docs/generation.md @@ -3,10 +3,12 @@ The SDK is generated from the Opencode server's OpenAPI 3.1 spec. Two source modes are supported: + - CLI (default): runs `bun dev generate` to emit the OpenAPI JSON - Server: fetches `http://localhost:4096/doc` from a running server Generator command + ```bash # From repo root uv run --project packages/sdk/python python packages/sdk/python/scripts/generate.py --source cli @@ -15,5 +17,6 @@ uv run --project packages/sdk/python python packages/sdk/python/scripts/generate ``` Post-generation + - The generator injects `extras.py` (OpenCodeClient) and patches `__init__.py` to export it - Code is formatted with `ruff` (imports) and `black` diff --git a/packages/sdk/python/docs/index.md b/packages/sdk/python/docs/index.md index bc7b550f9..e0cfe5d5d 100644 --- a/packages/sdk/python/docs/index.md +++ b/packages/sdk/python/docs/index.md @@ -3,6 +3,7 @@ The official Python client for the Opencode API, generated from the OpenAPI spec and extended with ergonomic helpers. Highlights + - Provider-agnostic client generated from OpenAPI 3.1 - Thin convenience wrapper (OpenCodeClient) for common tasks - Sync and async SSE streaming for live event feeds diff --git a/packages/sdk/python/docs/installation.md b/packages/sdk/python/docs/installation.md index f66e217ae..fe48f5189 100644 --- a/packages/sdk/python/docs/installation.md +++ b/packages/sdk/python/docs/installation.md @@ -1,26 +1,31 @@ # Installation Requirements + - Python 3.8+ - uv (recommended) -> https://docs.astral.sh/uv/ Install uv + ```bash curl -LsSf https://astral.sh/uv/install.sh | sh ``` Project setup + ```bash # From repo root or this directory uv sync --dev --project packages/sdk/python ``` Using pip (alternative) + ```bash pip install opencode-ai ``` Preview docs locally + ```bash # From repo root uv run --project packages/sdk/python mkdocs serve -f packages/sdk/python/mkdocs.yml diff --git a/packages/sdk/python/docs/publishing.md b/packages/sdk/python/docs/publishing.md index c598baa88..c05a12a33 100644 --- a/packages/sdk/python/docs/publishing.md +++ b/packages/sdk/python/docs/publishing.md @@ -3,6 +3,7 @@ Automated publishing runs on GitHub Releases. Workflow + - Create a new Release (the tag value becomes the package version) - The `publish-python-sdk` workflow will: - Generate the SDK from OpenAPI (CLI path) @@ -10,9 +11,11 @@ Workflow - Build wheel/sdist and upload to PyPI Prerequisites + - Repository secret: `PYPI_API_TOKEN` Manual publish + ```bash # TestPyPI REPOSITORY=testpypi PYPI_TOKEN=$TEST_PYPI_API_TOKEN \ diff --git a/packages/sdk/python/docs/testing.md b/packages/sdk/python/docs/testing.md index 3119035d0..e2c777e31 100644 --- a/packages/sdk/python/docs/testing.md +++ b/packages/sdk/python/docs/testing.md @@ -11,5 +11,6 @@ uv run --project packages/sdk/python pytest -q ``` Notes + - Integration test starts a headless opencode server via Bun in a subprocess - SSE behavior is validated using real streaming from the server diff --git a/packages/sdk/python/mkdocs.yml b/packages/sdk/python/mkdocs.yml index 25de28fb3..565eb7701 100644 --- a/packages/sdk/python/mkdocs.yml +++ b/packages/sdk/python/mkdocs.yml @@ -3,7 +3,7 @@ site_description: Official Python SDK for the Opencode API site_url: https://opencode.ai repo_url: https://github.com/sst/opencode repo_name: sst/opencode -edit_uri: '' +edit_uri: "" theme: name: material features: diff --git a/packages/slack/src/index.ts b/packages/slack/src/index.ts index 046f069e2..2a952b63e 100644 --- a/packages/slack/src/index.ts +++ b/packages/slack/src/index.ts @@ -19,7 +19,10 @@ const opencode = await createOpencode({ }) console.log("✅ Opencode server ready") -const sessions = new Map<string, { client: any; server: any; sessionId: string; channel: string; thread: string }>() +const sessions = new Map< + string, + { client: any; server: any; sessionId: string; channel: string; thread: string } +>() ;(async () => { const events = await opencode.client.event.subscribe() for await (const event of events.stream) { @@ -81,7 +84,10 @@ app.message(async ({ message, say }) => { if (createResult.error) { console.error("❌ Failed to create session:", createResult.error) - await say({ text: "Sorry, I had trouble creating a session. Please try again.", thread_ts: thread }) + await say({ + text: "Sorry, I had trouble creating a session. Please try again.", + thread_ts: thread, + }) return } @@ -108,7 +114,10 @@ app.message(async ({ message, say }) => { if (result.error) { console.error("❌ Failed to send message:", result.error) - await say({ text: "Sorry, I had trouble processing your message. Please try again.", thread_ts: thread }) + await say({ + text: "Sorry, I had trouble processing your message. Please try again.", + thread_ts: thread, + }) return } diff --git a/packages/slack/sst-env.d.ts b/packages/slack/sst-env.d.ts index b6a7e9066..0397645b5 100644 --- a/packages/slack/sst-env.d.ts +++ b/packages/slack/sst-env.d.ts @@ -6,4 +6,4 @@ /// <reference path="../../sst-env.d.ts" /> import "sst" -export {}
\ No newline at end of file +export {} diff --git a/packages/ui/src/assets/favicon/site.webmanifest b/packages/ui/src/assets/favicon/site.webmanifest index f7522f8f3..41290e840 100644 --- a/packages/ui/src/assets/favicon/site.webmanifest +++ b/packages/ui/src/assets/favicon/site.webmanifest @@ -18,4 +18,4 @@ "theme_color": "#ffffff", "background_color": "#ffffff", "display": "standalone" -}
\ No newline at end of file +} diff --git a/packages/ui/src/components/checkbox.tsx b/packages/ui/src/components/checkbox.tsx index 2009a430b..ac9abfdab 100644 --- a/packages/ui/src/components/checkbox.tsx +++ b/packages/ui/src/components/checkbox.tsx @@ -9,7 +9,14 @@ export interface CheckboxProps extends ParentProps<ComponentProps<typeof Kobalte } export function Checkbox(props: CheckboxProps) { - const [local, others] = splitProps(props, ["children", "class", "label", "hideLabel", "description", "icon"]) + const [local, others] = splitProps(props, [ + "children", + "class", + "label", + "hideLabel", + "description", + "icon", + ]) const resolved = children(() => local.children) return ( <Kobalte {...others} data-component="checkbox"> @@ -35,7 +42,9 @@ export function Checkbox(props: CheckboxProps) { </Kobalte.Label> </Show> <Show when={local.description}> - <Kobalte.Description data-slot="checkbox-description">{local.description}</Kobalte.Description> + <Kobalte.Description data-slot="checkbox-description"> + {local.description} + </Kobalte.Description> </Show> <Kobalte.ErrorMessage data-slot="checkbox-error" /> </div> diff --git a/packages/ui/src/components/dialog.tsx b/packages/ui/src/components/dialog.tsx index ce7a4b3ac..fdbb9022d 100644 --- a/packages/ui/src/components/dialog.tsx +++ b/packages/ui/src/components/dialog.tsx @@ -38,7 +38,11 @@ export function DialogRoot(props: DialogProps) { return ( <Kobalte {...others}> <Show when={props.trigger}> - <Kobalte.Trigger ref={trigger} data-component="dialog-trigger" onFocusIn={handleTriggerFocus}> + <Kobalte.Trigger + ref={trigger} + data-component="dialog-trigger" + onFocusIn={handleTriggerFocus} + > {props.trigger} </Kobalte.Trigger> </Show> diff --git a/packages/ui/src/styles/base.css b/packages/ui/src/styles/base.css index b80398e1d..02b473238 100644 --- a/packages/ui/src/styles/base.css +++ b/packages/ui/src/styles/base.css @@ -269,8 +269,8 @@ textarea, crash when using `color-mix(…)` with `currentcolor`. (https://github.com/tailwindlabs/tailwindcss/issues/17194) */ -@supports (not (-webkit-appearance: -apple-pay-button)) /* Not Safari */ or (contain-intrinsic-size: 1px) - /* Safari 17+ */ { +@supports (not (-webkit-appearance: -apple-pay-button)) /* Not Safari */ or + (contain-intrinsic-size: 1px) /* Safari 17+ */ { ::placeholder { color: color-mix(in oklab, currentcolor 50%, transparent); } diff --git a/packages/ui/src/styles/tailwind/colors.css b/packages/ui/src/styles/tailwind/colors.css index 527c43109..a5f982d6f 100644 --- a/packages/ui/src/styles/tailwind/colors.css +++ b/packages/ui/src/styles/tailwind/colors.css @@ -232,4 +232,4 @@ --color-border-weaker-focus: var(--border-weaker-focus); --color-button-ghost-hover: var(--button-ghost-hover); --color-button-ghost-hover2: var(--button-ghost-hover2); -}
\ No newline at end of file +} diff --git a/packages/ui/src/styles/theme.css b/packages/ui/src/styles/theme.css index 20c43b10e..6187eef9d 100644 --- a/packages/ui/src/styles/theme.css +++ b/packages/ui/src/styles/theme.css @@ -56,23 +56,18 @@ 0 6px 8px -4px rgba(19, 16, 16, 0.12), 0 4px 3px -2px rgba(19, 16, 16, 0.12), 0 1px 2px -1px rgba(19, 16, 16, 0.12); --shadow-xs-border: - 0 0 0 1px var(--border-base, rgba(11, 6, 0, 0.20)), - 0 1px 2px -1px rgba(19, 16, 16, 0.04), - 0 1px 2px 0 rgba(19, 16, 16, 0.06), - 0 1px 3px 0 rgba(19, 16, 16, 0.08); + 0 0 0 1px var(--border-base, rgba(11, 6, 0, 0.2)), 0 1px 2px -1px rgba(19, 16, 16, 0.04), + 0 1px 2px 0 rgba(19, 16, 16, 0.06), 0 1px 3px 0 rgba(19, 16, 16, 0.08); --shadow-xs-border-select: 0 0 0 3px var(--border-weak-selected, rgba(1, 103, 255, 0.29)), 0 0 0 1px var(--border-selected, rgba(0, 74, 255, 0.99)), 0 1px 2px -1px rgba(19, 16, 16, 0.25), 0 1px 2px 0 rgba(19, 16, 16, 0.08), 0 1px 3px 0 rgba(19, 16, 16, 0.12); --shadow-xs-border-focus: - 0 0 0 1px var(--border-base, rgba(11, 6, 0, 0.20)), - 0 1px 2px -1px rgba(19, 16, 16, 0.25), - 0 1px 2px 0 rgba(19, 16, 16, 0.08), - 0 1px 3px 0 rgba(19, 16, 16, 0.12), - 0 0 0 2px var(--background-weak, #F1F0F0), + 0 0 0 1px var(--border-base, rgba(11, 6, 0, 0.2)), 0 1px 2px -1px rgba(19, 16, 16, 0.25), + 0 1px 2px 0 rgba(19, 16, 16, 0.08), 0 1px 3px 0 rgba(19, 16, 16, 0.12), + 0 0 0 2px var(--background-weak, #f1f0f0), 0 0 0 3px var(--border-selected, rgba(0, 74, 255, 0.99)); - --text-mix-blend-mode: multiply; } @@ -413,7 +408,7 @@ --text-on-brand-weaker: var(--smoke-dark-alpha-8); --text-on-brand-strong: var(--smoke-dark-alpha-12); --button-secondary-base: var(--smoke-dark-4); - --button-secondary-hover: #2A2727; + --button-secondary-hover: #2a2727; --border-base: var(--smoke-dark-alpha-7); --border-hover: var(--smoke-dark-alpha-8); --border-active: var(--smoke-dark-alpha-9); diff --git a/packages/ui/sst-env.d.ts b/packages/ui/sst-env.d.ts index b6a7e9066..0397645b5 100644 --- a/packages/ui/sst-env.d.ts +++ b/packages/ui/sst-env.d.ts @@ -6,4 +6,4 @@ /// <reference path="../../sst-env.d.ts" /> import "sst" -export {}
\ No newline at end of file +export {} diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json index 440aa8f9b..c35314407 100644 --- a/packages/ui/tsconfig.json +++ b/packages/ui/tsconfig.json @@ -13,16 +13,9 @@ "module": "ESNext", "moduleResolution": "bundler", "noEmit": true, - "lib": [ - "es2022", - "dom", - "dom.iterable" - ], + "lib": ["es2022", "dom", "dom.iterable"], // Type Checking & Safety "strict": true, - "types": [ - "vite/client", - "bun" - ] + "types": ["vite/client", "bun"] } } diff --git a/packages/web/config.mjs b/packages/web/config.mjs index 5e2c8d3e4..7adb147cd 100644 --- a/packages/web/config.mjs +++ b/packages/web/config.mjs @@ -2,7 +2,8 @@ const stage = process.env.SST_STAGE || "dev" export default { url: stage === "production" ? "https://opencode.ai" : `https://${stage}.opencode.ai`, - console: stage === "production" ? "https://opencode.ai/auth" : `https://${stage}.opencode.ai/auth`, + console: + stage === "production" ? "https://opencode.ai/auth" : `https://${stage}.opencode.ai/auth`, email: "[email protected]", socialCard: "https://social-cards.sst.dev", github: "https://github.com/sst/opencode", diff --git a/packages/web/src/components/Share.tsx b/packages/web/src/components/Share.tsx index 062449712..486b6e44b 100644 --- a/packages/web/src/components/Share.tsx +++ b/packages/web/src/components/Share.tsx @@ -1,4 +1,14 @@ -import { For, Show, onMount, Suspense, onCleanup, createMemo, createSignal, SuspenseList, createEffect } from "solid-js" +import { + For, + Show, + onMount, + Suspense, + onCleanup, + createMemo, + createSignal, + SuspenseList, + createEffect, +} from "solid-js" import { DateTime } from "luxon" import { createStore, reconcile, unwrap } from "solid-js/store" import { IconArrowDown } from "./icons" @@ -66,8 +76,13 @@ export default function Share(props: { id: string; api: string; info: Session.In }, messages: {}, }) - const messages = createMemo(() => Object.values(store.messages).toSorted((a, b) => a.id?.localeCompare(b.id))) - const [connectionStatus, setConnectionStatus] = createSignal<[Status, string?]>(["disconnected", "Disconnected"]) + const messages = createMemo(() => + Object.values(store.messages).toSorted((a, b) => a.id?.localeCompare(b.id)), + ) + const [connectionStatus, setConnectionStatus] = createSignal<[Status, string?]>([ + "disconnected", + "Disconnected", + ]) createEffect(() => { console.log(unwrap(store)) }) @@ -330,7 +345,9 @@ export default function Share(props: { id: string; api: string; info: Session.In </ul> <div data-component="header-time" - title={DateTime.fromMillis(data().created || 0).toLocaleString(DateTime.DATETIME_FULL_WITH_SECONDS)} + title={DateTime.fromMillis(data().created || 0).toLocaleString( + DateTime.DATETIME_FULL_WITH_SECONDS, + )} > {DateTime.fromMillis(data().created || 0).toLocaleString(DateTime.DATETIME_MED)} </div> @@ -352,7 +369,10 @@ export default function Share(props: { id: string; api: string; info: Session.In if (x.type === "text" && x.synthetic === true) return false if (x.type === "tool" && x.tool === "todoread") return false if (x.type === "text" && !x.text) return false - if (x.type === "tool" && (x.state.status === "pending" || x.state.status === "running")) + if ( + x.type === "tool" && + (x.state.status === "pending" || x.state.status === "running") + ) return false return true }), @@ -364,7 +384,8 @@ export default function Share(props: { id: string; api: string; info: Session.In {(part, partIndex) => { const last = createMemo( () => - data().messages.length === msgIndex() + 1 && filteredParts().length === partIndex() + 1, + data().messages.length === msgIndex() + 1 && + filteredParts().length === partIndex() + 1, ) onMount(() => { @@ -381,7 +402,9 @@ export default function Share(props: { id: string; api: string; info: Session.In } }) - return <Part last={last()} part={part} index={partIndex()} message={msg} /> + return ( + <Part last={last()} part={part} index={partIndex()} message={msg} /> + ) }} </For> </Suspense> @@ -406,7 +429,11 @@ export default function Share(props: { id: string; api: string; info: Session.In </li> <li> <span data-element-label>Input Tokens</span> - {data().tokens.input ? <span>{data().tokens.input}</span> : <span data-placeholder>—</span>} + {data().tokens.input ? ( + <span>{data().tokens.input}</span> + ) : ( + <span data-placeholder>—</span> + )} </li> <li> <span data-element-label>Output Tokens</span> @@ -560,7 +587,8 @@ export function fromV1(v1: Message.Info): MessageWithParts { } } - const { title, time, ...metadata } = v1.metadata.tool[part.toolInvocation.toolCallId] + const { title, time, ...metadata } = + v1.metadata.tool[part.toolInvocation.toolCallId] if (part.toolInvocation.state === "call") { return { status: "running", diff --git a/packages/web/src/components/icons/index.tsx b/packages/web/src/components/icons/index.tsx index 62445611f..9aef7a927 100644 --- a/packages/web/src/components/icons/index.tsx +++ b/packages/web/src/components/icons/index.tsx @@ -4418,7 +4418,14 @@ export function IconMultiSelect(props: JSX.SvgSVGAttributes<SVGSVGElement>) { } export function IconSettings(props: JSX.SvgSVGAttributes<SVGSVGElement>) { return ( - <svg {...props} width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> + <svg + {...props} + width="16" + height="16" + viewBox="0 0 16 16" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > <g clip-path="url(#clip0_1256_16163)"> <path fill-rule="evenodd" diff --git a/packages/web/src/components/share/common.tsx b/packages/web/src/components/share/common.tsx index cab2dbdb0..9520516c6 100644 --- a/packages/web/src/components/share/common.tsx +++ b/packages/web/src/components/share/common.tsx @@ -10,7 +10,12 @@ export function AnchorIcon(props: AnchorProps) { const [copied, setCopied] = createSignal(false) return ( - <div {...rest} data-element-anchor title="Link to this message" data-status={copied() ? "copied" : ""}> + <div + {...rest} + data-element-anchor + title="Link to this message" + data-status={copied() ? "copied" : ""} + > <a href={`#${local.id}`} onClick={(e) => { diff --git a/packages/web/src/components/share/content-code.tsx b/packages/web/src/components/share/content-code.tsx index 2f383b8be..0f9d28fa3 100644 --- a/packages/web/src/components/share/content-code.tsx +++ b/packages/web/src/components/share/content-code.tsx @@ -26,7 +26,11 @@ export function ContentCode(props: Props) { ) return ( <Suspense> - <div innerHTML={html()} class={style.root} data-flush={props.flush === true ? true : undefined} /> + <div + innerHTML={html()} + class={style.root} + data-flush={props.flush === true ? true : undefined} + /> </Suspense> ) } diff --git a/packages/web/src/components/share/content-diff.tsx b/packages/web/src/components/share/content-diff.tsx index 9ccd554d0..79c2723cb 100644 --- a/packages/web/src/components/share/content-diff.tsx +++ b/packages/web/src/components/share/content-diff.tsx @@ -124,7 +124,9 @@ export function ContentDiff(props: Props) { // Collect consecutive modified/removed/added rows while ( i < currentRows.length && - (currentRows[i].type === "modified" || currentRows[i].type === "removed" || currentRows[i].type === "added") + (currentRows[i].type === "modified" || + currentRows[i].type === "removed" || + currentRows[i].type === "added") ) { const row = currentRows[i] if (row.left && (row.type === "removed" || row.type === "modified")) { @@ -162,10 +164,16 @@ export function ContentDiff(props: Props) { <div data-component="desktop"> {rows().map((r) => ( <div data-component="diff-row" data-type={r.type}> - <div data-slot="before" data-diff-type={r.type === "removed" || r.type === "modified" ? "removed" : ""}> + <div + data-slot="before" + data-diff-type={r.type === "removed" || r.type === "modified" ? "removed" : ""} + > <ContentCode code={r.left} flush lang={props.lang} /> </div> - <div data-slot="after" data-diff-type={r.type === "added" || r.type === "modified" ? "added" : ""}> + <div + data-slot="after" + data-diff-type={r.type === "added" || r.type === "modified" ? "added" : ""} + > <ContentCode code={r.right} lang={props.lang} flush /> </div> </div> @@ -176,7 +184,11 @@ export function ContentDiff(props: Props) { {mobileRows().map((block) => ( <div data-component="diff-block" data-type={block.type}> {block.lines.map((line) => ( - <div data-diff-type={block.type === "removed" ? "removed" : block.type === "added" ? "added" : ""}> + <div + data-diff-type={ + block.type === "removed" ? "removed" : block.type === "added" ? "added" : "" + } + > <ContentCode code={line} lang={props.lang} flush /> </div> ))} diff --git a/packages/web/src/components/share/copy-button.tsx b/packages/web/src/components/share/copy-button.tsx index 892d5553f..6f51bb4d8 100644 --- a/packages/web/src/components/share/copy-button.tsx +++ b/packages/web/src/components/share/copy-button.tsx @@ -21,7 +21,11 @@ export function CopyButton(props: CopyButtonProps) { return ( <div data-component="copy-button" class={styles.root}> <button type="button" onClick={handleCopyClick} data-copied={copied() ? true : undefined}> - {copied() ? <IconCheckCircle width={16} height={16} /> : <IconClipboard width={16} height={16} />} + {copied() ? ( + <IconCheckCircle width={16} height={16} /> + ) : ( + <IconClipboard width={16} height={16} /> + )} </button> </div> ) diff --git a/packages/web/src/components/share/part.tsx b/packages/web/src/components/share/part.tsx index f7a6a9304..6ad18273b 100644 --- a/packages/web/src/components/share/part.tsx +++ b/packages/web/src/components/share/part.tsx @@ -1,6 +1,15 @@ import map from "lang-map" import { DateTime } from "luxon" -import { For, Show, Match, Switch, type JSX, createMemo, createSignal, type ParentProps } from "solid-js" +import { + For, + Show, + Match, + Switch, + type JSX, + createMemo, + createSignal, + type ParentProps, +} from "solid-js" import { IconHashtag, IconSparkles, @@ -19,7 +28,14 @@ import { IconMagnifyingGlass, IconDocumentMagnifyingGlass, } from "../icons" -import { IconMeta, IconRobot, IconOpenAI, IconGemini, IconAnthropic, IconBrain } from "../icons/custom" +import { + IconMeta, + IconRobot, + IconOpenAI, + IconGemini, + IconAnthropic, + IconBrain, +} from "../icons/custom" import { ContentCode } from "./content-code" import { ContentDiff } from "./content-diff" import { ContentText } from "./content-text" @@ -79,7 +95,11 @@ export function Part(props: PartProps) { <IconPaperClip width={18} height={18} /> </Match> <Match - when={props.part.type === "step-start" && props.message.role === "assistant" && props.message.modelID} + when={ + props.part.type === "step-start" && + props.message.role === "assistant" && + props.message.modelID + } > {(model) => <ProviderIcon model={model()} size={18} />} </Match> @@ -147,7 +167,9 @@ export function Part(props: PartProps) { DateTime.DATETIME_FULL_WITH_SECONDS, )} > - {DateTime.fromMillis(props.message.time.completed).toLocaleString(DateTime.DATETIME_MED)} + {DateTime.fromMillis(props.message.time.completed).toLocaleString( + DateTime.DATETIME_MED, + )} </Footer> )} </div> @@ -343,7 +365,10 @@ function getShikiLang(filename: string) { return type ? (overrides[type] ?? type) : "plaintext" } -function getDiagnostics(diagnosticsByFile: Record<string, Diagnostic[]>, currentFile: string): JSX.Element[] { +function getDiagnostics( + diagnosticsByFile: Record<string, Diagnostic[]>, + currentFile: string, +): JSX.Element[] { const result: JSX.Element[] = [] if (diagnosticsByFile === undefined || diagnosticsByFile[currentFile] === undefined) return result @@ -397,7 +422,9 @@ export function TodoWriteTool(props: ToolProps) { completed: 2, } const todos = createMemo(() => - ((props.state.input?.todos ?? []) as Todo[]).slice().sort((a, b) => priority[a.status] - priority[b.status]), + ((props.state.input?.todos ?? []) as Todo[]) + .slice() + .sort((a, b) => priority[a.status] - priority[b.status]), ) const starting = () => todos().every((t: Todo) => t.status === "pending") const finished = () => todos().every((t: Todo) => t.status === "completed") @@ -439,13 +466,23 @@ export function GrepTool(props: ToolProps) { <Switch> <Match when={props.state.metadata?.matches && props.state.metadata?.matches > 0}> <ResultsButton - showCopy={props.state.metadata?.matches === 1 ? "1 match" : `${props.state.metadata?.matches} matches`} + showCopy={ + props.state.metadata?.matches === 1 + ? "1 match" + : `${props.state.metadata?.matches} matches` + } > <ContentText expand compact text={props.state.output} /> </ResultsButton> </Match> <Match when={props.state.output}> - <ContentText expand compact text={props.state.output} data-size="sm" data-color="dimmed" /> + <ContentText + expand + compact + text={props.state.output} + data-size="sm" + data-color="dimmed" + /> </Match> </Switch> </div> @@ -505,7 +542,9 @@ export function WebFetchTool(props: ToolProps) { } export function ReadTool(props: ToolProps) { - const filePath = createMemo(() => stripWorkingDirectory(props.state.input?.filePath, props.message.path.cwd)) + const filePath = createMemo(() => + stripWorkingDirectory(props.state.input?.filePath, props.message.path.cwd), + ) return ( <> @@ -522,7 +561,10 @@ export function ReadTool(props: ToolProps) { </Match> <Match when={typeof props.state.metadata?.preview === "string"}> <ResultsButton showCopy="Show preview" hideCopy="Hide preview"> - <ContentCode lang={getShikiLang(filePath() || "")} code={props.state.metadata?.preview} /> + <ContentCode + lang={getShikiLang(filePath() || "")} + code={props.state.metadata?.preview} + /> </ResultsButton> </Match> <Match when={typeof props.state.metadata?.preview !== "string" && props.state.output}> @@ -537,8 +579,12 @@ export function ReadTool(props: ToolProps) { } export function WriteTool(props: ToolProps) { - const filePath = createMemo(() => stripWorkingDirectory(props.state.input?.filePath, props.message.path.cwd)) - const diagnostics = createMemo(() => getDiagnostics(props.state.metadata?.diagnostics, props.state.input.filePath)) + const filePath = createMemo(() => + stripWorkingDirectory(props.state.input?.filePath, props.message.path.cwd), + ) + const diagnostics = createMemo(() => + getDiagnostics(props.state.metadata?.diagnostics, props.state.input.filePath), + ) return ( <> @@ -558,7 +604,10 @@ export function WriteTool(props: ToolProps) { </Match> <Match when={props.state.input?.content}> <ResultsButton showCopy="Show contents" hideCopy="Hide contents"> - <ContentCode lang={getShikiLang(filePath() || "")} code={props.state.input?.content} /> + <ContentCode + lang={getShikiLang(filePath() || "")} + code={props.state.input?.content} + /> </ResultsButton> </Match> </Switch> @@ -568,8 +617,12 @@ export function WriteTool(props: ToolProps) { } export function EditTool(props: ToolProps) { - const filePath = createMemo(() => stripWorkingDirectory(props.state.input.filePath, props.message.path.cwd)) - const diagnostics = createMemo(() => getDiagnostics(props.state.metadata?.diagnostics, props.state.input.filePath)) + const filePath = createMemo(() => + stripWorkingDirectory(props.state.input.filePath, props.message.path.cwd), + ) + const diagnostics = createMemo(() => + getDiagnostics(props.state.metadata?.diagnostics, props.state.input.filePath), + ) return ( <> @@ -586,7 +639,10 @@ export function EditTool(props: ToolProps) { </Match> <Match when={props.state.metadata?.diff}> <div data-component="diff"> - <ContentDiff diff={props.state.metadata?.diff} lang={getShikiLang(filePath() || "")} /> + <ContentDiff + diff={props.state.metadata?.diff} + lang={getShikiLang(filePath() || "")} + /> </div> </Match> </Switch> @@ -619,7 +675,11 @@ export function GlobTool(props: ToolProps) { <Match when={props.state.metadata?.count && props.state.metadata?.count > 0}> <div data-component="tool-result"> <ResultsButton - showCopy={props.state.metadata?.count === 1 ? "1 result" : `${props.state.metadata?.count} results`} + showCopy={ + props.state.metadata?.count === 1 + ? "1 result" + : `${props.state.metadata?.count} results` + } > <ContentText expand compact text={props.state.output} /> </ResultsButton> @@ -642,7 +702,12 @@ function ResultsButton(props: ResultsButtonProps) { return ( <> - <button type="button" data-component="button-text" data-more onClick={() => setShow((e) => !e)}> + <button + type="button" + data-component="button-text" + data-more + onClick={() => setShow((e) => !e)} + > <span>{show() ? props.hideCopy || "Hide results" : props.showCopy || "Show results"}</span> <span data-slot="icon"> <Show when={show()} fallback={<IconChevronRight width={11} height={11} />}> @@ -668,7 +733,11 @@ function Footer(props: ParentProps<{ title: string }>) { } function ToolFooter(props: { time: number }) { - return props.time > MIN_DURATION && <Footer title={`${props.time}ms`}>{formatDuration(props.time)}</Footer> + return ( + props.time > MIN_DURATION && ( + <Footer title={`${props.time}ms`}>{formatDuration(props.time)}</Footer> + ) + ) } function TaskTool(props: ToolProps) { @@ -709,7 +778,13 @@ export function FallbackTool(props: ToolProps) { <Match when={props.state.output}> <div data-component="tool-result"> <ResultsButton> - <ContentText expand compact text={props.state.output} data-size="sm" data-color="dimmed" /> + <ContentText + expand + compact + text={props.state.output} + data-size="sm" + data-color="dimmed" + /> </ResultsButton> </div> </Match> diff --git a/packages/web/src/content/docs/1-0.mdx b/packages/web/src/content/docs/1-0.mdx index 49db53d72..6737482a7 100644 --- a/packages/web/src/content/docs/1-0.mdx +++ b/packages/web/src/content/docs/1-0.mdx @@ -16,13 +16,14 @@ The new TUI works like the old one since it connects to the same opencode server You should not be autoupgraded to 1.0 if you are currently using a previous version. However some older versions of OpenCode always grab latest. - To upgrade manually, run + ```bash $ opencode upgrade 1.0.0 ``` To downgrade back to 0.x, run + ```bash $ opencode upgrade 0.15.31 ``` diff --git a/packages/web/src/content/docs/index.mdx b/packages/web/src/content/docs/index.mdx index f6d2b3129..33658b135 100644 --- a/packages/web/src/content/docs/index.mdx +++ b/packages/web/src/content/docs/index.mdx @@ -42,26 +42,10 @@ You can also install it with the following commands: - **Using Node.js** <Tabs> - <TabItem label="npm"> - ```bash - npm install -g opencode-ai - ``` - </TabItem> - <TabItem label="Bun"> - ```bash - bun install -g opencode-ai - ``` - </TabItem> - <TabItem label="pnpm"> - ```bash - pnpm install -g opencode-ai - ``` - </TabItem> - <TabItem label="Yarn"> - ```bash - yarn global add opencode-ai - ``` - </TabItem> + <TabItem label="npm">```bash npm install -g opencode-ai ```</TabItem> + <TabItem label="Bun">```bash bun install -g opencode-ai ```</TabItem> + <TabItem label="pnpm">```bash pnpm install -g opencode-ai ```</TabItem> + <TabItem label="Yarn">```bash yarn global add opencode-ai ```</TabItem> </Tabs> - **Using Homebrew on macOS and Linux** diff --git a/packages/web/src/content/docs/permissions.mdx b/packages/web/src/content/docs/permissions.mdx index 4579c2127..a0ba5d5d9 100644 --- a/packages/web/src/content/docs/permissions.mdx +++ b/packages/web/src/content/docs/permissions.mdx @@ -187,4 +187,3 @@ permission: Only analyze code and suggest changes. ``` - diff --git a/packages/web/src/content/docs/rules.mdx b/packages/web/src/content/docs/rules.mdx index aa5590bb5..6346a02ea 100644 --- a/packages/web/src/content/docs/rules.mdx +++ b/packages/web/src/content/docs/rules.mdx @@ -107,7 +107,11 @@ The recommended approach is to use the `instructions` field in `opencode.json`: ```json title="opencode.json" { "$schema": "https://opencode.ai/config.json", - "instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"] + "instructions": [ + "docs/development-standards.md", + "test/testing-guidelines.md", + "packages/*/AGENTS.md" + ] } ``` diff --git a/packages/web/src/content/docs/troubleshooting.mdx b/packages/web/src/content/docs/troubleshooting.mdx index fb8e964ba..d38b892fc 100644 --- a/packages/web/src/content/docs/troubleshooting.mdx +++ b/packages/web/src/content/docs/troubleshooting.mdx @@ -90,8 +90,8 @@ If you encounter `ProviderModelNotFoundError` you are most likely incorrectly referencing a model somewhere. Models should be referenced like so: `<providerId>/<modelId>` - Examples: + - `openai/gpt-4.1` - `openrouter/google/gemini-2.5-flash` - `opencode/kimi-k2` diff --git a/packages/web/src/styles/custom.css b/packages/web/src/styles/custom.css index e947f1f18..648176e42 100644 --- a/packages/web/src/styles/custom.css +++ b/packages/web/src/styles/custom.css @@ -30,8 +30,6 @@ --sl-color-divider: var(--sl-color-gray-5); } - - body { color: var(--color-text) !important; font-size: 14px !important; @@ -60,7 +58,6 @@ body { --color-border-weak: hsl(0, 4%, 23%); --color-icon: hsl(10, 3%, 43%); - } } @@ -145,7 +142,7 @@ a[aria-current="page"] { font-weight: 600 !important; } -ul.top-level a[aria-current="page"] > span { +ul.top-level a[aria-current="page"] > span { color: var(--color-text-strong) !important; } @@ -163,7 +160,6 @@ ul.top-level a[aria-current="page"] > span { font-weight: 600 !important; } - .top-level li a { border-radius: 0; width: 100%; @@ -221,13 +217,16 @@ site-search > button span { } } - - site-search > button > kbd { font-size: 14px !important; } -h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { +h1 a, +h2 a, +h3 a, +h4 a, +h5 a, +h6 a { color: var(--color-text-strong) !important; } @@ -263,7 +262,8 @@ strong { font-weight: 500 !important; } -ul, ol { +ul, +ol { list-style: none !important; padding: 0 !important; } @@ -280,7 +280,8 @@ ul, ol { color: var(--color-text-strong) !important; } -body > .page > header, :root[data-has-sidebar] body > .page > header { +body > .page > header, +:root[data-has-sidebar] body > .page > header { background: var(--color-background) !important; padding: 24px !important; } @@ -303,7 +304,6 @@ body > .page > header, :root[data-has-sidebar] body > .page > header { max-width: 100% !important; } - nav.sidebar .sl-container ul li a, div.right-sidebar .sl-container ul li a { padding: 4px 24px !important; @@ -317,7 +317,7 @@ div.right-sidebar .sl-container ul li a:hover { background: var(--color-background-weak); @media (prefers-color-scheme: dark) { - background: var(--color-background-weak) + background: var(--color-background-weak); } } @@ -326,14 +326,12 @@ div.right-sidebar .sl-container ul li ul li { padding: 4px 12px 0 12px !important; } - nav.sidebar .sl-container ul li a[aria-current="true"], div.right-sidebar .sl-container ul li a[aria-current="true"] { color: var(--color-text-strong) !important; opacity: 100%; } - h2#starlight__on-this-page { font-size: 14px !important; color: var(--color-text-strong) !important; @@ -375,7 +373,6 @@ nav.sidebar ul.top-level > li > details > summary .group-label > span { .expressive-code { margin: 0.75rem 0 3rem 0 !important; border-radius: 6px; - } .expressive-code figure { @@ -386,8 +383,6 @@ nav.sidebar ul.top-level > li > details > summary .group-label > span { box-shadow: none; } - - @media (prefers-color-scheme: dark) { .shiki, .shiki span { diff --git a/packages/web/sst-env.d.ts b/packages/web/sst-env.d.ts index b6a7e9066..0397645b5 100644 --- a/packages/web/sst-env.d.ts +++ b/packages/web/sst-env.d.ts @@ -6,4 +6,4 @@ /// <reference path="../../sst-env.d.ts" /> import "sst" -export {}
\ No newline at end of file +export {} diff --git a/script/format.ts b/script/format.ts index c09809737..f5a54a57f 100755 --- a/script/format.ts +++ b/script/format.ts @@ -2,7 +2,7 @@ import { $ } from "bun" -await $`bun run prettier --ignore-unknown --write` +await $`bun run prettier --ignore-unknown --write .` if (process.env["CI"] && (await $`git status --porcelain`.text())) { await $`git config --local user.email "[email protected]"` diff --git a/script/stats.ts b/script/stats.ts index d5f6c103f..30e71ffd5 100755 --- a/script/stats.ts +++ b/script/stats.ts @@ -54,7 +54,9 @@ async function fetchNpmDownloads(packageName: string): Promise<number> { // Use a range from 2020 to current year + 5 years to ensure it works forever const currentYear = new Date().getFullYear() const endYear = currentYear + 5 - const response = await fetch(`https://api.npmjs.org/downloads/range/2020-01-01:${endYear}-12-31/${packageName}`) + const response = await fetch( + `https://api.npmjs.org/downloads/range/2020-01-01:${endYear}-12-31/${packageName}`, + ) if (!response.ok) { console.warn(`Failed to fetch npm downloads for ${packageName}: ${response.status}`) return 0 @@ -166,7 +168,11 @@ async function save(githubTotal: number, npmDownloads: number) { ? ` (${githubChange.toLocaleString()})` : " (+0)" const npmChangeStr = - npmChange > 0 ? ` (+${npmChange.toLocaleString()})` : npmChange < 0 ? ` (${npmChange.toLocaleString()})` : " (+0)" + npmChange > 0 + ? ` (+${npmChange.toLocaleString()})` + : npmChange < 0 + ? ` (${npmChange.toLocaleString()})` + : " (+0)" const totalChangeStr = totalChange > 0 ? ` (+${totalChange.toLocaleString()})` @@ -220,6 +226,8 @@ console.log(` npm: ${npmDownloads.toLocaleString()}`) console.log("=".repeat(60)) console.log("-".repeat(60)) -console.log(`GitHub Total: ${githubTotal.toLocaleString()} downloads across ${releases.length} releases`) +console.log( + `GitHub Total: ${githubTotal.toLocaleString()} downloads across ${releases.length} releases`, +) console.log(`npm Total: ${npmDownloads.toLocaleString()} downloads`) console.log(`Combined Total: ${totalDownloads.toLocaleString()} downloads`) diff --git a/sdks/vscode/src/extension.ts b/sdks/vscode/src/extension.ts index 77c70513f..2f90229d5 100644 --- a/sdks/vscode/src/extension.ts +++ b/sdks/vscode/src/extension.ts @@ -1,46 +1,59 @@ // This method is called when your extension is deactivated export function deactivate() {} -import * as vscode from "vscode"; +import * as vscode from "vscode" -const TERMINAL_NAME = "opencode"; +const TERMINAL_NAME = "opencode" export function activate(context: vscode.ExtensionContext) { - let openNewTerminalDisposable = vscode.commands.registerCommand("opencode.openNewTerminal", async () => { - await openTerminal(); - }); - - let openTerminalDisposable = vscode.commands.registerCommand("opencode.openTerminal", async () => { - // An opencode terminal already exists => focus it - const existingTerminal = vscode.window.terminals.find((t) => t.name === TERMINAL_NAME); - if (existingTerminal) { - existingTerminal.show(); - return; - } + let openNewTerminalDisposable = vscode.commands.registerCommand( + "opencode.openNewTerminal", + async () => { + await openTerminal() + }, + ) + + let openTerminalDisposable = vscode.commands.registerCommand( + "opencode.openTerminal", + async () => { + // An opencode terminal already exists => focus it + const existingTerminal = vscode.window.terminals.find((t) => t.name === TERMINAL_NAME) + if (existingTerminal) { + existingTerminal.show() + return + } - await openTerminal(); - }); + await openTerminal() + }, + ) - let addFilepathDisposable = vscode.commands.registerCommand("opencode.addFilepathToTerminal", async () => { - const fileRef = getActiveFile(); - if (!fileRef) {return;} + let addFilepathDisposable = vscode.commands.registerCommand( + "opencode.addFilepathToTerminal", + async () => { + const fileRef = getActiveFile() + if (!fileRef) { + return + } - const terminal = vscode.window.activeTerminal; - if (!terminal) {return;} + const terminal = vscode.window.activeTerminal + if (!terminal) { + return + } - if (terminal.name === TERMINAL_NAME) { - // @ts-ignore - const port = terminal.creationOptions.env?.["_EXTENSION_OPENCODE_PORT"]; - port ? await appendPrompt(parseInt(port), fileRef) : terminal.sendText(fileRef); - terminal.show(); - } - }); + if (terminal.name === TERMINAL_NAME) { + // @ts-ignore + const port = terminal.creationOptions.env?.["_EXTENSION_OPENCODE_PORT"] + port ? await appendPrompt(parseInt(port), fileRef) : terminal.sendText(fileRef) + terminal.show() + } + }, + ) - context.subscriptions.push(openTerminalDisposable, addFilepathDisposable); + context.subscriptions.push(openTerminalDisposable, addFilepathDisposable) async function openTerminal() { // Create a new terminal in split screen - const port = Math.floor(Math.random() * (65535 - 16384 + 1)) + 16384; + const port = Math.floor(Math.random() * (65535 - 16384 + 1)) + 16384 const terminal = vscode.window.createTerminal({ name: TERMINAL_NAME, iconPath: { @@ -55,32 +68,34 @@ export function activate(context: vscode.ExtensionContext) { _EXTENSION_OPENCODE_PORT: port.toString(), OPENCODE_CALLER: "vscode", }, - }); + }) - terminal.show(); - terminal.sendText(`opencode --port ${port}`); + terminal.show() + terminal.sendText(`opencode --port ${port}`) - const fileRef = getActiveFile(); - if (!fileRef) {return;} + const fileRef = getActiveFile() + if (!fileRef) { + return + } // Wait for the terminal to be ready - let tries = 10; - let connected = false; + let tries = 10 + let connected = false do { - await new Promise((resolve) => setTimeout(resolve, 200)); + await new Promise((resolve) => setTimeout(resolve, 200)) try { - await fetch(`http://localhost:${port}/app`); - connected = true; - break; + await fetch(`http://localhost:${port}/app`) + connected = true + break } catch (e) {} - tries--; - } while (tries > 0); + tries-- + } while (tries > 0) // If connected, append the prompt to the terminal if (connected) { - await appendPrompt(port, `In ${fileRef}`); - terminal.show(); + await appendPrompt(port, `In ${fileRef}`) + terminal.show() } } @@ -91,37 +106,41 @@ export function activate(context: vscode.ExtensionContext) { "Content-Type": "application/json", }, body: JSON.stringify({ text }), - }); + }) } function getActiveFile() { - const activeEditor = vscode.window.activeTextEditor; - if (!activeEditor) {return;} + const activeEditor = vscode.window.activeTextEditor + if (!activeEditor) { + return + } - const document = activeEditor.document; - const workspaceFolder = vscode.workspace.getWorkspaceFolder(document.uri); - if (!workspaceFolder) {return;} + const document = activeEditor.document + const workspaceFolder = vscode.workspace.getWorkspaceFolder(document.uri) + if (!workspaceFolder) { + return + } // Get the relative path from workspace root - const relativePath = vscode.workspace.asRelativePath(document.uri); - let filepathWithAt = `@${relativePath}`; + const relativePath = vscode.workspace.asRelativePath(document.uri) + let filepathWithAt = `@${relativePath}` // Check if there's a selection and add line numbers - const selection = activeEditor.selection; + const selection = activeEditor.selection if (!selection.isEmpty) { // Convert to 1-based line numbers - const startLine = selection.start.line + 1; - const endLine = selection.end.line + 1; + const startLine = selection.start.line + 1 + const endLine = selection.end.line + 1 if (startLine === endLine) { // Single line selection - filepathWithAt += `#L${startLine}`; + filepathWithAt += `#L${startLine}` } else { // Multi-line selection - filepathWithAt += `#L${startLine}-${endLine}`; + filepathWithAt += `#L${startLine}-${endLine}` } } - return filepathWithAt; + return filepathWithAt } } diff --git a/sdks/vscode/sst-env.d.ts b/sdks/vscode/sst-env.d.ts index b6a7e9066..0397645b5 100644 --- a/sdks/vscode/sst-env.d.ts +++ b/sdks/vscode/sst-env.d.ts @@ -6,4 +6,4 @@ /// <reference path="../../sst-env.d.ts" /> import "sst" -export {}
\ No newline at end of file +export {} diff --git a/sst-env.d.ts b/sst-env.d.ts index 14e3a2a5d..b80f971ab 100644 --- a/sst-env.d.ts +++ b/sst-env.d.ts @@ -5,107 +5,107 @@ declare module "sst" { export interface Resource { - "ADMIN_SECRET": { - "type": "sst.sst.Secret" - "value": string + ADMIN_SECRET: { + type: "sst.sst.Secret" + value: string } - "AUTH_API_URL": { - "type": "sst.sst.Linkable" - "value": string + AUTH_API_URL: { + type: "sst.sst.Linkable" + value: string } - "AWS_SES_ACCESS_KEY_ID": { - "type": "sst.sst.Secret" - "value": string + AWS_SES_ACCESS_KEY_ID: { + type: "sst.sst.Secret" + value: string } - "AWS_SES_SECRET_ACCESS_KEY": { - "type": "sst.sst.Secret" - "value": string + AWS_SES_SECRET_ACCESS_KEY: { + type: "sst.sst.Secret" + value: string } - "Api": { - "type": "sst.cloudflare.Worker" - "url": string + Api: { + type: "sst.cloudflare.Worker" + url: string } - "AuthApi": { - "type": "sst.cloudflare.Worker" - "url": string + AuthApi: { + type: "sst.cloudflare.Worker" + url: string } - "AuthStorage": { - "type": "sst.cloudflare.Kv" + AuthStorage: { + type: "sst.cloudflare.Kv" } - "Bucket": { - "name": string - "type": "sst.cloudflare.Bucket" + Bucket: { + name: string + type: "sst.cloudflare.Bucket" } - "Console": { - "type": "sst.cloudflare.SolidStart" - "url": string + Console: { + type: "sst.cloudflare.SolidStart" + url: string } - "Database": { - "database": string - "host": string - "password": string - "port": number - "type": "sst.sst.Linkable" - "username": string + Database: { + database: string + host: string + password: string + port: number + type: "sst.sst.Linkable" + username: string } - "Desktop": { - "type": "sst.cloudflare.StaticSite" - "url": string + Desktop: { + type: "sst.cloudflare.StaticSite" + url: string } - "EMAILOCTOPUS_API_KEY": { - "type": "sst.sst.Secret" - "value": string + EMAILOCTOPUS_API_KEY: { + type: "sst.sst.Secret" + value: string } - "GITHUB_APP_ID": { - "type": "sst.sst.Secret" - "value": string + GITHUB_APP_ID: { + type: "sst.sst.Secret" + value: string } - "GITHUB_APP_PRIVATE_KEY": { - "type": "sst.sst.Secret" - "value": string + GITHUB_APP_PRIVATE_KEY: { + type: "sst.sst.Secret" + value: string } - "GITHUB_CLIENT_ID_CONSOLE": { - "type": "sst.sst.Secret" - "value": string + GITHUB_CLIENT_ID_CONSOLE: { + type: "sst.sst.Secret" + value: string } - "GITHUB_CLIENT_SECRET_CONSOLE": { - "type": "sst.sst.Secret" - "value": string + GITHUB_CLIENT_SECRET_CONSOLE: { + type: "sst.sst.Secret" + value: string } - "GOOGLE_CLIENT_ID": { - "type": "sst.sst.Secret" - "value": string + GOOGLE_CLIENT_ID: { + type: "sst.sst.Secret" + value: string } - "HONEYCOMB_API_KEY": { - "type": "sst.sst.Secret" - "value": string + HONEYCOMB_API_KEY: { + type: "sst.sst.Secret" + value: string } - "LogProcessor": { - "type": "sst.cloudflare.Worker" + LogProcessor: { + type: "sst.cloudflare.Worker" } - "STRIPE_SECRET_KEY": { - "type": "sst.sst.Secret" - "value": string + STRIPE_SECRET_KEY: { + type: "sst.sst.Secret" + value: string } - "STRIPE_WEBHOOK_SECRET": { - "type": "sst.sst.Linkable" - "value": string + STRIPE_WEBHOOK_SECRET: { + type: "sst.sst.Linkable" + value: string } - "Web": { - "type": "sst.cloudflare.Astro" - "url": string + Web: { + type: "sst.cloudflare.Astro" + url: string } - "ZEN_MODELS1": { - "type": "sst.sst.Secret" - "value": string + ZEN_MODELS1: { + type: "sst.sst.Secret" + value: string } - "ZEN_MODELS2": { - "type": "sst.sst.Secret" - "value": string + ZEN_MODELS2: { + type: "sst.sst.Secret" + value: string } } } /// <reference path="sst-env.d.ts" /> import "sst" -export {}
\ No newline at end of file +export {} |
