mirror of
https://github.com/anomalyco/opencode.git
synced 2026-02-12 03:44:28 +00:00
Compare commits
4 Commits
fixup-pr-a
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5bdf1c4b96 | ||
|
|
135f8ffb2a | ||
|
|
bf5a01edd9 | ||
|
|
81ca2df6ad |
1
.github/VOUCHED.td
vendored
1
.github/VOUCHED.td
vendored
@@ -8,6 +8,7 @@
|
||||
# - Denounce with minus prefix: -username or -platform:username.
|
||||
# - Optional details after a space following the handle.
|
||||
adamdotdevin
|
||||
ariane-emory
|
||||
-florianleibert
|
||||
fwang
|
||||
iamdavidhill
|
||||
|
||||
4
.github/workflows/pr-management.yml
vendored
4
.github/workflows/pr-management.yml
vendored
@@ -60,11 +60,9 @@ jobs:
|
||||
run: |
|
||||
COMMENT=$(bun script/duplicate-pr.ts -f pr_info.txt "Check the attached file for PR details and search for duplicates")
|
||||
|
||||
if [ "$COMMENT" != "No duplicate PRs found" ]; then
|
||||
gh pr comment "$PR_NUMBER" --body "_The following comment was made by an LLM, it may be inaccurate:_
|
||||
gh pr comment "$PR_NUMBER" --body "_The following comment was made by an LLM, it may be inaccurate:_
|
||||
|
||||
$COMMENT"
|
||||
fi
|
||||
|
||||
add-contributor-label:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -2,6 +2,7 @@ import { onCleanup, onMount } from "solid-js"
|
||||
import { showToast } from "@opencode-ai/ui/toast"
|
||||
import { usePrompt, type ContentPart, type ImageAttachmentPart } from "@/context/prompt"
|
||||
import { useLanguage } from "@/context/language"
|
||||
import { uuid } from "@/utils/uuid"
|
||||
import { getCursorPosition } from "./editor-dom"
|
||||
|
||||
export const ACCEPTED_IMAGE_TYPES = ["image/png", "image/jpeg", "image/gif", "image/webp"]
|
||||
@@ -31,7 +32,7 @@ export function createPromptAttachments(input: PromptAttachmentsInput) {
|
||||
const dataUrl = reader.result as string
|
||||
const attachment: ImageAttachmentPart = {
|
||||
type: "image",
|
||||
id: crypto.randomUUID?.() ?? Math.random().toString(16).slice(2),
|
||||
id: uuid(),
|
||||
filename: file.name,
|
||||
mime: file.type,
|
||||
dataUrl,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { createSimpleContext } from "@opencode-ai/ui/context"
|
||||
import { useParams } from "@solidjs/router"
|
||||
import { Persist, persisted } from "@/utils/persist"
|
||||
import { createScopedCache } from "@/utils/scoped-cache"
|
||||
import { uuid } from "@/utils/uuid"
|
||||
import type { SelectedLineRange } from "@/context/file"
|
||||
|
||||
export type LineComment = {
|
||||
@@ -53,7 +54,7 @@ function createCommentSessionState(store: Store<CommentStore>, setStore: SetStor
|
||||
|
||||
const add = (input: Omit<LineComment, "id" | "time">) => {
|
||||
const next: LineComment = {
|
||||
id: crypto.randomUUID?.() ?? Math.random().toString(16).slice(2),
|
||||
id: uuid(),
|
||||
time: Date.now(),
|
||||
...input,
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { uuid } from "@/utils/uuid"
|
||||
|
||||
type Nav = {
|
||||
id: string
|
||||
dir?: string
|
||||
@@ -16,8 +18,6 @@ const key = (dir: string | undefined, to: string) => `${dir ?? ""}:${to}`
|
||||
|
||||
const now = () => performance.now()
|
||||
|
||||
const uid = () => crypto.randomUUID?.() ?? Math.random().toString(16).slice(2)
|
||||
|
||||
const navs = new Map<string, Nav>()
|
||||
const pending = new Map<string, string>()
|
||||
const active = new Map<string, string>()
|
||||
@@ -94,7 +94,7 @@ function ensure(id: string, data: Omit<Nav, "marks" | "logged" | "timer">) {
|
||||
export function navStart(input: { dir?: string; from?: string; to: string; trigger?: string }) {
|
||||
if (!dev) return
|
||||
|
||||
const id = uid()
|
||||
const id = uuid()
|
||||
const start = now()
|
||||
const nav = ensure(id, { ...input, id, start })
|
||||
nav.marks["navigate:start"] = start
|
||||
@@ -109,7 +109,7 @@ export function navParams(input: { dir?: string; from?: string; to: string }) {
|
||||
const k = key(input.dir, input.to)
|
||||
const pendingId = pending.get(k)
|
||||
if (pendingId) pending.delete(k)
|
||||
const id = pendingId ?? uid()
|
||||
const id = pendingId ?? uuid()
|
||||
|
||||
const start = now()
|
||||
const nav = ensure(id, { ...input, id, start, trigger: pendingId ? "key" : "route" })
|
||||
|
||||
78
packages/app/src/utils/uuid.test.ts
Normal file
78
packages/app/src/utils/uuid.test.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { afterEach, describe, expect, test } from "bun:test"
|
||||
import { uuid } from "./uuid"
|
||||
|
||||
const cryptoDescriptor = Object.getOwnPropertyDescriptor(globalThis, "crypto")
|
||||
const secureDescriptor = Object.getOwnPropertyDescriptor(globalThis, "isSecureContext")
|
||||
const randomDescriptor = Object.getOwnPropertyDescriptor(Math, "random")
|
||||
|
||||
const setCrypto = (value: Partial<Crypto>) => {
|
||||
Object.defineProperty(globalThis, "crypto", {
|
||||
configurable: true,
|
||||
value: value as Crypto,
|
||||
})
|
||||
}
|
||||
|
||||
const setSecure = (value: boolean) => {
|
||||
Object.defineProperty(globalThis, "isSecureContext", {
|
||||
configurable: true,
|
||||
value,
|
||||
})
|
||||
}
|
||||
|
||||
const setRandom = (value: () => number) => {
|
||||
Object.defineProperty(Math, "random", {
|
||||
configurable: true,
|
||||
value,
|
||||
})
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
if (cryptoDescriptor) {
|
||||
Object.defineProperty(globalThis, "crypto", cryptoDescriptor)
|
||||
}
|
||||
|
||||
if (secureDescriptor) {
|
||||
Object.defineProperty(globalThis, "isSecureContext", secureDescriptor)
|
||||
}
|
||||
|
||||
if (!secureDescriptor) {
|
||||
delete (globalThis as { isSecureContext?: boolean }).isSecureContext
|
||||
}
|
||||
|
||||
if (randomDescriptor) {
|
||||
Object.defineProperty(Math, "random", randomDescriptor)
|
||||
}
|
||||
})
|
||||
|
||||
describe("uuid", () => {
|
||||
test("uses randomUUID in secure contexts", () => {
|
||||
setCrypto({ randomUUID: () => "00000000-0000-0000-0000-000000000000" })
|
||||
setSecure(true)
|
||||
expect(uuid()).toBe("00000000-0000-0000-0000-000000000000")
|
||||
})
|
||||
|
||||
test("falls back in insecure contexts", () => {
|
||||
setCrypto({ randomUUID: () => "00000000-0000-0000-0000-000000000000" })
|
||||
setSecure(false)
|
||||
setRandom(() => 0.5)
|
||||
expect(uuid()).toBe("8")
|
||||
})
|
||||
|
||||
test("falls back when randomUUID throws", () => {
|
||||
setCrypto({
|
||||
randomUUID: () => {
|
||||
throw new DOMException("Failed", "OperationError")
|
||||
},
|
||||
})
|
||||
setSecure(true)
|
||||
setRandom(() => 0.5)
|
||||
expect(uuid()).toBe("8")
|
||||
})
|
||||
|
||||
test("falls back when randomUUID is unavailable", () => {
|
||||
setCrypto({})
|
||||
setSecure(true)
|
||||
setRandom(() => 0.5)
|
||||
expect(uuid()).toBe("8")
|
||||
})
|
||||
})
|
||||
12
packages/app/src/utils/uuid.ts
Normal file
12
packages/app/src/utils/uuid.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
const fallback = () => Math.random().toString(16).slice(2)
|
||||
|
||||
export function uuid() {
|
||||
const c = globalThis.crypto
|
||||
if (!c || typeof c.randomUUID !== "function") return fallback()
|
||||
if (typeof globalThis.isSecureContext === "boolean" && !globalThis.isSecureContext) return fallback()
|
||||
try {
|
||||
return c.randomUUID()
|
||||
} catch {
|
||||
return fallback()
|
||||
}
|
||||
}
|
||||
@@ -149,6 +149,7 @@ export function Session() {
|
||||
const [showDetails, setShowDetails] = kv.signal("tool_details_visibility", true)
|
||||
const [showAssistantMetadata, setShowAssistantMetadata] = kv.signal("assistant_metadata_visibility", true)
|
||||
const [showScrollbar, setShowScrollbar] = kv.signal("scrollbar_visible", false)
|
||||
const [showHeader, setShowHeader] = kv.signal("header_visible", true)
|
||||
const [diffWrapMode] = kv.signal<"word" | "none">("diff_wrap_mode", "word")
|
||||
const [animationsEnabled, setAnimationsEnabled] = kv.signal("animations_enabled", true)
|
||||
|
||||
@@ -582,6 +583,15 @@ export function Session() {
|
||||
dialog.clear()
|
||||
},
|
||||
},
|
||||
{
|
||||
title: showHeader() ? "Hide header" : "Show header",
|
||||
value: "session.toggle.header",
|
||||
category: "Session",
|
||||
onSelect: (dialog) => {
|
||||
setShowHeader((prev) => !prev)
|
||||
dialog.clear()
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Page up",
|
||||
value: "session.page.up",
|
||||
@@ -963,7 +973,7 @@ export function Session() {
|
||||
<box flexDirection="row">
|
||||
<box flexGrow={1} paddingBottom={1} paddingTop={1} paddingLeft={2} paddingRight={2} gap={1}>
|
||||
<Show when={session()}>
|
||||
<Show when={!sidebarVisible() || !wide()}>
|
||||
<Show when={showHeader() && (!sidebarVisible() || !wide())}>
|
||||
<Header />
|
||||
</Show>
|
||||
<scrollbox
|
||||
|
||||
@@ -401,6 +401,8 @@ export namespace ProviderTransform {
|
||||
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/xai
|
||||
case "@ai-sdk/deepinfra":
|
||||
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/deepinfra
|
||||
case "venice-ai-sdk-provider":
|
||||
// https://docs.venice.ai/overview/guides/reasoning-models#reasoning-effort
|
||||
case "@ai-sdk/openai-compatible":
|
||||
return Object.fromEntries(WIDELY_SUPPORTED_EFFORTS.map((effort) => [effort, { reasoningEffort: effort }]))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user