opencode-translate 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -2
- package/dist/index.js +21 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -64,14 +64,28 @@ $en 프로젝트 루트의 package.json을 읽고 요약해줘
|
|
|
64
64
|
All subsequent messages in the same session are translated automatically — no need to repeat `$en`.
|
|
65
65
|
|
|
66
66
|
- Your original message and its English translation remain visible in the transcript.
|
|
67
|
+
- The first successful `$en` prompt includes a `Translation enabled:` confirmation with the language and translator model.
|
|
67
68
|
- English assistant text streams normally; a translated Markdown section is appended when the text segment completes.
|
|
68
69
|
- Both the **terminal and web UI** display the same persisted bilingual assistant text. No UI-specific plugin is needed.
|
|
69
70
|
- Question forms are translated, with selected labels and custom answers converted back to English for the model.
|
|
70
71
|
- Translation activates only in root sessions. Its state survives plugin/server restarts.
|
|
71
72
|
|
|
72
73
|
Before model requests, the plugin removes its recorded display translations from context. It does not remove arbitrary
|
|
73
|
-
Markdown based on its appearance. On inbound translation failure, the
|
|
74
|
-
|
|
74
|
+
Markdown based on its appearance. On inbound translation failure, the transcript shows `Translation failed:` and the
|
|
75
|
+
error reason. The main model receives the original text without `$en` or the diagnostic; failed first-time activation
|
|
76
|
+
remains inactive, so retry with `$en` after fixing the error. On outbound failure, the English response is retained with
|
|
77
|
+
a translation-unavailable notice.
|
|
78
|
+
|
|
79
|
+
### If `$en` has no effect
|
|
80
|
+
|
|
81
|
+
`$en` is a plugin control keyword, not an instruction for the main model. If the model comments on `$en`, inbound
|
|
82
|
+
translation did not complete. In version 2.0.0, an inbound failure was only logged on the server and left `$en` in the
|
|
83
|
+
prompt, making it indistinguishable from an unloaded plugin in the transcript.
|
|
84
|
+
|
|
85
|
+
Check the active server's plugin list and configuration, including the selected project location. It must load the v2
|
|
86
|
+
package, not an old pinned `opencode-translate@1.x`. Also check the configured **translation** model and variant; changing
|
|
87
|
+
the main-chat model does not change the translator. An API-key login or OAuth connection must exist on that server.
|
|
88
|
+
The server log message `[opencode-translate] inbound translation failed` contains the underlying generation error.
|
|
75
89
|
|
|
76
90
|
## Authentication
|
|
77
91
|
|
|
@@ -114,6 +128,9 @@ bun run test:package
|
|
|
114
128
|
|
|
115
129
|
# Requires Node 24 and an OpenCode v2 binary; uses an isolated server and fake provider.
|
|
116
130
|
OPENCODE_BINARY=/path/to/opencode bun run test:host
|
|
131
|
+
|
|
132
|
+
# Exercise a registry-installed package through OpenCode's actual package loader.
|
|
133
|
+
OPENCODE_BINARY=/path/to/opencode OPENCODE_TRANSLATE_PACKAGE=opencode-translate@latest bun run test:host
|
|
117
134
|
```
|
|
118
135
|
|
|
119
136
|
Tests include OpenCode's actual native protocol parsers. The real-host smoke test loads the built plugin, creates and
|
package/dist/index.js
CHANGED
|
@@ -636,7 +636,7 @@ function readMetadata(value) {
|
|
|
636
636
|
return;
|
|
637
637
|
const item = value;
|
|
638
638
|
if (typeof item.lang === "string" && typeof item.english === "string" && typeof item.display === "string") {
|
|
639
|
-
return { lang: item.lang, english: item.english, display: item.display };
|
|
639
|
+
return { lang: item.lang, english: item.english, display: item.display, enabled: item.enabled !== false };
|
|
640
640
|
}
|
|
641
641
|
}
|
|
642
642
|
function createState(ctx) {
|
|
@@ -667,7 +667,7 @@ function createState(ctx) {
|
|
|
667
667
|
const messages = await ctx.session.context({ sessionID });
|
|
668
668
|
for (const message of messages) {
|
|
669
669
|
const data = readMetadata(message.metadata?.[METADATA_KEY]);
|
|
670
|
-
if (message.type === "user" && data) {
|
|
670
|
+
if (message.type === "user" && data?.enabled) {
|
|
671
671
|
await ctx.storage.set(`sessions/${sessionID}`, data.lang);
|
|
672
672
|
return data.lang;
|
|
673
673
|
}
|
|
@@ -784,13 +784,7 @@ async function setup(ctx) {
|
|
|
784
784
|
if (source === undefined)
|
|
785
785
|
return;
|
|
786
786
|
const userLanguage = lang ?? options.lang;
|
|
787
|
-
|
|
788
|
-
const english = await translator.text(source, userLanguage, LLM_LANGUAGE);
|
|
789
|
-
const display = source === english ? source : `${source}
|
|
790
|
-
|
|
791
|
-
→ EN: ${english}`;
|
|
792
|
-
await state.remember(event.sessionID, display, english);
|
|
793
|
-
await ctx.storage.set(`sessions/${event.sessionID}`, userLanguage);
|
|
787
|
+
function apply(display, english, enabled) {
|
|
794
788
|
event.prompt.text = display;
|
|
795
789
|
for (const attachment of [
|
|
796
790
|
...event.prompt.files ?? [],
|
|
@@ -799,9 +793,26 @@ async function setup(ctx) {
|
|
|
799
793
|
]) {
|
|
800
794
|
delete attachment.mention;
|
|
801
795
|
}
|
|
802
|
-
event.metadata = { ...event.metadata, [METADATA_KEY]: { lang: userLanguage, english, display } };
|
|
796
|
+
event.metadata = { ...event.metadata, [METADATA_KEY]: { lang: userLanguage, english, display, enabled } };
|
|
797
|
+
}
|
|
798
|
+
try {
|
|
799
|
+
const english = await translator.text(source, userLanguage, LLM_LANGUAGE);
|
|
800
|
+
const content = source === english ? source : `${source}
|
|
801
|
+
|
|
802
|
+
→ EN: ${english}`;
|
|
803
|
+
const display = lang ? content : `${content}
|
|
804
|
+
|
|
805
|
+
\uD83C\uDF10 Translation enabled: ${userLanguage} ↔ ${LLM_LANGUAGE} (${options.model})`;
|
|
806
|
+
await state.remember(event.sessionID, display, english);
|
|
807
|
+
await ctx.storage.set(`sessions/${event.sessionID}`, userLanguage);
|
|
808
|
+
apply(display, english, true);
|
|
803
809
|
} catch (error) {
|
|
804
810
|
console.error(`[${PLUGIN_NAME}] inbound translation failed; sending original text`, error);
|
|
811
|
+
const reason = error && typeof error === "object" && "message" in error && typeof error.message === "string" ? error.message : String(error);
|
|
812
|
+
const display = `${source}
|
|
813
|
+
|
|
814
|
+
⚠️ Translation failed: ${reason}. Original text was sent to the model.`;
|
|
815
|
+
apply(display, source, Boolean(lang));
|
|
805
816
|
}
|
|
806
817
|
});
|
|
807
818
|
async function context(event) {
|
package/package.json
CHANGED