Selaa lähdekoodia

fix: enable thinking for zhipuai-coding-plan & prevent Korean IME truncation (#22041)

Co-authored-by: claudianus <[email protected]>
Co-authored-by: Aiden Cline <[email protected]>
Co-authored-by: Sisyphus <[email protected]>
ryan.h.park 5 päivää sitten
vanhempi
sitoutus
63035f977f

+ 12 - 1
packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx

@@ -589,6 +589,13 @@ export function Prompt(props: PromptProps) {
   ])
 
   async function submit() {
+    // IME: double-defer may fire before onContentChange flushes the last
+    // composed character (e.g. Korean hangul) to the store, so read
+    // plainText directly and sync before any downstream reads.
+    if (input && !input.isDestroyed && input.plainText !== store.prompt.input) {
+      setStore("prompt", "input", input.plainText)
+      syncExtmarksWithPromptParts()
+    }
     if (props.disabled) return
     if (autocomplete?.visible) return
     if (!store.prompt.input) return
@@ -994,7 +1001,11 @@ export function Prompt(props: PromptProps) {
                     input.cursorOffset = input.plainText.length
                 }
               }}
-              onSubmit={submit}
+              onSubmit={() => {
+                // IME: double-defer so the last composed character (e.g. Korean
+                // hangul) is flushed to plainText before we read it for submission.
+                setTimeout(() => setTimeout(() => submit(), 0), 0)
+              }}
               onPaste={async (event: PasteEvent) => {
                 if (props.disabled) {
                   event.preventDefault()

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 61472
packages/opencode/src/provider/models-snapshot.js


+ 4 - 1
packages/opencode/src/provider/transform.ts

@@ -774,7 +774,10 @@ export namespace ProviderTransform {
       result["chat_template_args"] = { enable_thinking: true }
     }
 
-    if (["zai", "zhipuai"].includes(input.model.providerID) && input.model.api.npm === "@ai-sdk/openai-compatible") {
+    if (
+      ["zai", "zhipuai"].some((id) => input.model.providerID.includes(id)) &&
+      input.model.api.npm === "@ai-sdk/openai-compatible"
+    ) {
       result["thinking"] = {
         type: "enabled",
         clear_thinking: false,

+ 52 - 0
packages/opencode/test/provider/transform.test.ts

@@ -104,6 +104,58 @@ describe("ProviderTransform.options - setCacheKey", () => {
   })
 })
 
+describe("ProviderTransform.options - zai/zhipuai thinking", () => {
+  const sessionID = "test-session-123"
+
+  const createModel = (providerID: string) =>
+    ({
+      id: `${providerID}/glm-4.6`,
+      providerID,
+      api: {
+        id: "glm-4.6",
+        url: "https://open.bigmodel.cn/api/paas/v4",
+        npm: "@ai-sdk/openai-compatible",
+      },
+      name: "GLM 4.6",
+      capabilities: {
+        temperature: true,
+        reasoning: true,
+        attachment: true,
+        toolcall: true,
+        input: { text: true, audio: false, image: true, video: false, pdf: true },
+        output: { text: true, audio: false, image: false, video: false, pdf: false },
+        interleaved: false,
+      },
+      cost: {
+        input: 0.001,
+        output: 0.002,
+        cache: { read: 0.0001, write: 0.0002 },
+      },
+      limit: {
+        context: 128000,
+        output: 8192,
+      },
+      status: "active",
+      options: {},
+      headers: {},
+    }) as any
+
+  for (const providerID of ["zai-coding-plan", "zai", "zhipuai-coding-plan", "zhipuai"]) {
+    test(`${providerID} should set thinking cfg`, () => {
+      const result = ProviderTransform.options({
+        model: createModel(providerID),
+        sessionID,
+        providerOptions: {},
+      })
+
+      expect(result.thinking).toEqual({
+        type: "enabled",
+        clear_thinking: false,
+      })
+    })
+  }
+})
+
 describe("ProviderTransform.options - google thinkingConfig gating", () => {
   const sessionID = "test-session-123"
 

+ 120 - 0
patches/install-korean-ime-fix.sh

@@ -0,0 +1,120 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# opencode Korean IME Fix Installer
+# https://github.com/anomalyco/opencode/issues/14371
+#
+# Patches opencode to prevent Korean (and other CJK) IME last character
+# truncation when pressing Enter in Kitty and other terminals.
+#
+# Usage:
+#   curl -fsSL https://raw.githubusercontent.com/claudianus/opencode/fix-zhipuai-coding-plan-thinking/patches/install-korean-ime-fix.sh | bash
+#   # or from a cloned repo:
+#   ./patches/install-korean-ime-fix.sh
+
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+ORANGE='\033[38;5;214m'
+MUTED='\033[0;2m'
+NC='\033[0m'
+
+OPENCODE_DIR="${OPENCODE_DIR:-$HOME/.opencode}"
+OPENCODE_SRC="${OPENCODE_SRC:-$HOME/.opencode-src}"
+FORK_REPO="${FORK_REPO:-https://github.com/claudianus/opencode.git}"
+FORK_BRANCH="${FORK_BRANCH:-fix-zhipuai-coding-plan-thinking}"
+
+info()  { echo -e "${MUTED}$*${NC}"; }
+warn()  { echo -e "${ORANGE}$*${NC}"; }
+err()   { echo -e "${RED}$*${NC}" >&2; }
+ok()    { echo -e "${GREEN}$*${NC}"; }
+
+need() {
+  if ! command -v "$1" >/dev/null 2>&1; then
+    err "Error: $1 is required but not installed."
+    exit 1
+  fi
+}
+
+need git
+need bun
+
+# ── 1. Clone or update fork ────────────────────────────────────────────
+if [ -d "$OPENCODE_SRC/.git" ]; then
+  info "Updating existing source at $OPENCODE_SRC ..."
+  git -C "$OPENCODE_SRC" fetch origin "$FORK_BRANCH"
+  git -C "$OPENCODE_SRC" checkout "$FORK_BRANCH"
+  git -C "$OPENCODE_SRC" reset --hard "origin/$FORK_BRANCH"
+else
+  info "Cloning fork (shallow) to $OPENCODE_SRC ..."
+  git clone --depth 1 --branch "$FORK_BRANCH" "$FORK_REPO" "$OPENCODE_SRC"
+fi
+
+# ── 2. Verify the IME fix is present in source ────────────────────────
+PROMPT_FILE="$OPENCODE_SRC/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx"
+if [ ! -f "$PROMPT_FILE" ]; then
+  err "Prompt file not found: $PROMPT_FILE"
+  exit 1
+fi
+
+if grep -q "setTimeout(() => setTimeout" "$PROMPT_FILE"; then
+  ok "IME fix already present in source."
+else
+  warn "IME fix not found. Applying patch ..."
+  # Apply the fix: replace onSubmit={submit} with double-deferred version
+  sed -i 's|onSubmit={submit}|onSubmit={() => {\n                // IME: double-defer so the last composed character (e.g. Korean\n                // hangul) is flushed to plainText before we read it for submission.\n                setTimeout(() => setTimeout(() => submit(), 0), 0)\n              }}|' "$PROMPT_FILE"
+  if grep -q "setTimeout(() => setTimeout" "$PROMPT_FILE"; then
+    ok "Patch applied."
+  else
+    err "Failed to apply patch. The source may have changed."
+    exit 1
+  fi
+fi
+
+# ── 3. Install dependencies ────────────────────────────────────────────
+info "Installing dependencies (this may take a minute) ..."
+cd "$OPENCODE_SRC"
+bun install --frozen-lockfile 2>/dev/null || bun install
+
+# ── 4. Build (current platform only) ──────────────────────────────────
+info "Building opencode for current platform ..."
+cd "$OPENCODE_SRC/packages/opencode"
+bun run build --single
+
+# ── 5. Install binary ──────────────────────────────────────────────────
+mkdir -p "$OPENCODE_DIR/bin"
+
+PLATFORM=$(uname -s | tr '[:upper:]' '[:lower:]')
+ARCH=$(uname -m)
+[ "$ARCH" = "aarch64" ] && ARCH="arm64"
+[ "$ARCH" = "x86_64" ] && ARCH="x64"
+[ "$PLATFORM" = "darwin" ] && true
+[ "$PLATFORM" = "linux" ] && true
+
+BUILT_BINARY="$OPENCODE_SRC/packages/opencode/dist/opencode-${PLATFORM}-${ARCH}/bin/opencode"
+
+if [ ! -f "$BUILT_BINARY" ]; then
+  BUILT_BINARY=$(find "$OPENCODE_SRC/packages/opencode/dist" -name "opencode" -type f -executable 2>/dev/null | head -1)
+fi
+
+if [ -f "$BUILT_BINARY" ]; then
+  if [ -f "$OPENCODE_DIR/bin/opencode" ]; then
+    cp "$OPENCODE_DIR/bin/opencode" "$OPENCODE_DIR/bin/opencode.bak.$(date +%Y%m%d%H%M%S)"
+  fi
+  cp "$BUILT_BINARY" "$OPENCODE_DIR/bin/opencode"
+  chmod +x "$OPENCODE_DIR/bin/opencode"
+  ok "Installed to $OPENCODE_DIR/bin/opencode"
+else
+  err "Build failed - binary not found in dist/"
+  info "Try running manually:"
+  echo "  cd $OPENCODE_SRC/packages/opencode && bun run build --single"
+  exit 1
+fi
+
+echo ""
+ok "Done! Korean IME fix is now active."
+echo ""
+info "To uninstall and revert to the official release:"
+echo "  curl -fsSL https://opencode.ai/install | bash"
+echo ""
+info "To update (re-pull and rebuild):"
+echo "  $0"

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä