@yhotamos/enja-cli 1.1.0 → 1.2.0

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.
Files changed (3) hide show
  1. package/README.md +19 -6
  2. package/dist/index.js +37 -17
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -14,6 +14,7 @@
14
14
  - HTML タグ除去機能で Web ページも翻訳可能
15
15
  - OpenAI API や Gemini API を使用して高品質な翻訳も可能
16
16
  - 翻訳履歴の保存・参照機能
17
+ - 複数の翻訳API設定をプロファイルとして管理・切り替え可能
17
18
 
18
19
  ## インストール
19
20
 
@@ -48,9 +49,10 @@ enja "Hello, world!" --provider openai --api-key YOUR_OPENAI_API_KEY
48
49
  # 翻訳履歴を表示
49
50
  enja history
50
51
 
51
- # 設定を表示・変更
52
+ # 設定を表示/追加/アクティブ化
52
53
  enja config
53
- enja config endpoint https://api.example.com/translate
54
+ enja config add work --provider gemini --api-key YOUR_GEMINI_API_KEY --model gemini-2.5-flash
55
+ enja config use work
54
56
  ```
55
57
 
56
58
  ### 実用例
@@ -59,8 +61,8 @@ enja config endpoint https://api.example.com/translate
59
61
  # エラーメッセージの翻訳
60
62
  npm install nonexistent-package 2>&1 | enja
61
63
 
62
- # Git コマンドのヘルプを日本語化
63
- git --help | enja
64
+ # コマンドのヘルプを日本語化
65
+ docker --help | enja
64
66
 
65
67
  # 英語のドキュメントを日本語に変換
66
68
  enja -f CONTRIBUTING.md -o CONTRIBUTING.ja.md
@@ -78,21 +80,32 @@ curl -s https://example.com/api/docs | enja
78
80
 
79
81
  ## セキュリティとプライバシー
80
82
 
83
+ ### デフォルトプロバイダー (GAS) 使用時
84
+
81
85
  - 翻訳データは保存されません(リクエストごとに処理し,即座にレスポンス)
82
86
  - 他のユーザーの翻訳内容は見えません(完全にステートレス)
83
87
  - 機密情報の翻訳は避けてください(公開エンドポイントを使用しているため)
84
88
 
89
+ ### カスタムプロバイダー使用時
90
+
91
+ OpenAI や Gemini などのカスタムプロバイダーを使用する場合は,各サービスのプライバシーポリシーに従います.
92
+
85
93
  ## 制限事項
86
94
 
95
+ ### デフォルトプロバイダー (GAS) 使用時
96
+
87
97
  - 1 日あたりのリクエスト数: すべてのユーザーで共有で約 5,000 リクエスト
88
98
  - 文字数制限: 1 リクエストあたり最大 100,000 文字
89
99
 
90
100
  制限に達した場合はエラーメッセージが表示されます.
91
101
 
102
+ ### カスタムプロバイダー使用時
103
+
104
+ 各サービスの制限に従います(OpenAI,Gemini など).
105
+
92
106
  ## 今後の予定
93
107
 
94
- - [ ] 複数言語対応
95
- - [ ] プロファイル機能(複数の設定を切り替え)
108
+ - [ ] より多くの翻訳プロバイダー対応(DeepL など)
96
109
  - [ ] API キーの暗号化保存
97
110
 
98
111
  ## 貢献
package/dist/index.js CHANGED
@@ -1,10 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import*as l from'fs';import {readFileSync,promises}from'fs';import {Command}from'commander';import Q from'ora';import*as u from'path';import*as D from'os';import _ from'openai';import {GoogleGenAI}from'@google/genai';import {randomUUID,createHash}from'crypto';import p from'kleur';var v=class{apiUrl;apiKey;constructor(t,r){this.apiUrl=t,this.apiKey=r;}async translate(t,r,n){try{let o={"Content-Type":"application/json"};this.apiKey&&(o.Authorization=`Bearer ${this.apiKey}`);let i=await fetch(this.apiUrl,{method:"POST",headers:o,body:JSON.stringify({text:t,sourceLang:r,targetLang:n})});if(!i.ok)throw new Error(`HTTP ${i.status} ${i.statusText}`);let s=await i.json();if(s.code!==200||!s.translatedText)throw new Error(`${s.error||"\u7FFB\u8A33\u306B\u5931\u6557\u3057\u307E\u3057\u305F"}`);return {text:s.translatedText,detectedSourceLang:s.detectedSourceLang}}catch(o){throw o}}};function d(){if(process.platform==="win32"){let r=process.env.APPDATA||u.join(D.homedir(),"AppData","Roaming");if(!r)throw new Error("APPDATA \u74B0\u5883\u5909\u6570\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u304A\u3089\u305A\uFF0C\u4EE3\u66FF\u30D1\u30B9\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F");return u.join(r,"enja-cli")}let t=D.homedir();return u.join(t,".config","enja-cli")}function K(){return u.join(d(),"history.json")}function R(){return u.join(d(),"config.json")}var h={provider:"gas",endpoint:"https://script.google.com/macros/s/AKfycbxOSbKD0aBTaQqIzHv00BMzp6WwrtWHBU3gJY0vhB2HblgUO-cgesfT1l-rrfttnWZzew/exec",apiKey:void 0},w=class{filePath;constructor(){this.filePath=R();}ensureConfigDir(){let t=d();l.existsSync(t)||l.mkdirSync(t,{recursive:true});}async readConfig(){try{if(!l.existsSync(this.filePath))return {...h};let t=l.readFileSync(this.filePath,"utf-8"),r=JSON.parse(t);return {...h,...r}}catch{return console.warn("\u8A2D\u5B9A\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F\uFF0E\u898F\u5B9A\u5024\u3092\u4F7F\u7528\u3057\u307E\u3059"),{...h}}}async writeConfig(t){try{this.ensureConfigDir(),l.writeFileSync(this.filePath,JSON.stringify(t,null,2),"utf-8");}catch{throw new Error("\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u306E\u66F8\u304D\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F")}}async get(){return await this.readConfig()}async set(t,r){let n=await this.readConfig();switch(t){case "endpoint":n.endpoint=r;break;case "api-key":n.apiKey=r;break;case "provider":if(!["gas","custom","openai","gemini"].includes(r))throw new Error(`\u7121\u52B9\u306A\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC (${r}): 'gas', 'custom', 'openai', 'gemini' \u306E\u3044\u305A\u308C\u304B\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044`);n.provider=r;break;default:throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${t})`)}await this.writeConfig(n);}async unset(t){let r=await this.readConfig();switch(t){case "endpoint":r.endpoint=h.endpoint;break;case "api-key":r.apiKey=void 0;break;case "provider":r.provider=h.provider;break;default:throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${t})`)}await this.writeConfig(r);}async reset(){await this.writeConfig({...h});}};var Y="https://script.google.com/macros/s/AKfycbxOSbKD0aBTaQqIzHv00BMzp6WwrtWHBU3gJY0vhB2HblgUO-cgesfT1l-rrfttnWZzew/exec";async function k(e){let r=await new w().get(),n=e?.endpoint||r.endpoint||Y,o=e?.apiKey||r.apiKey,i=e?.provider||r.provider||"gas";return {endpoint:n,provider:i,apiKey:o}}var x=class{client;constructor(t){this.client=new _({apiKey:t});}async translate(t,r,n){try{let o=this.mapLanguageCode(r),i=this.mapLanguageCode(n),s=`You are a professional translator. Translate the following text from ${o} to ${i}. Only return the translated text without any additional explanation or comments.`,c=(await this.client.chat.completions.create({model:"gpt-4o-mini",messages:[{role:"system",content:s},{role:"user",content:t}],temperature:.3})).choices[0]?.message?.content;if(!c)throw new Error("\u7FFB\u8A33\u306B\u5931\u6557\u3057\u307E\u3057\u305F");return {text:c.trim(),detectedSourceLang:r}}catch(o){throw o instanceof Error?new Error(`OpenAI\u7FFB\u8A33\u30A8\u30E9\u30FC: ${o.message}`):o}}mapLanguageCode(t){return {en:"English",ja:"Japanese"}[t.toLowerCase()]||t}};var C=class{client;constructor(t){this.client=new GoogleGenAI({apiKey:t});}async translate(t,r,n){try{let o=this.mapLanguageCode(r),i=this.mapLanguageCode(n),s=`You are a professional translator. Translate the following text from ${o} to ${i}. Only return the translated text without any additional explanation or comments.`,c=(await this.client.models.generateContent({model:"gemini-2.5-flash-lite",contents:t,config:{systemInstruction:s}})).text;if(!c)throw new Error("\u7FFB\u8A33\u306B\u5931\u6557\u3057\u307E\u3057\u305F");return {text:c.trim(),detectedSourceLang:r}}catch(o){throw o instanceof Error?new Error(`Gemini\u7FFB\u8A33\u30A8\u30E9\u30FC: ${o.message}`):o}}mapLanguageCode(t){return {en:"English",ja:"Japanese"}[t.toLowerCase()]||t}};async function B(e){let t=await k(e);switch(t.provider){case "gas":case "custom":return new v(t.endpoint,t.apiKey);case "openai":if(!t.apiKey)throw new Error("OpenAI\u3092\u4F7F\u7528\u3059\u308B\u306B\u306FAPI\u30AD\u30FC\u304C\u5FC5\u8981\u3067\u3059");return new x(t.apiKey);case "gemini":if(!t.apiKey)throw new Error("Gemini\u3092\u4F7F\u7528\u3059\u308B\u306B\u306FAPI\u30AD\u30FC\u304C\u5FC5\u8981\u3067\u3059");return new C(t.apiKey);default:throw new Error(`\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC (${t.provider})`)}}var M=100,y=class{filePath;constructor(){this.filePath=K();}ensureConfigDir(){let t=d();l.existsSync(t)||l.mkdirSync(t,{recursive:true});}async readHistory(){try{let t=await promises.readFile(this.filePath,"utf-8");return JSON.parse(t)}catch(t){return t&&t.code==="ENOENT"?[]:(console.warn("\u5C65\u6B74\u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F\uFF0E\u7A7A\u914D\u5217\u3092\u8FD4\u3057\u307E\u3059"),[])}}async writeHistory(t){try{this.ensureConfigDir();let r=`${this.filePath}.tmp`,n=JSON.stringify(t,null,2);await promises.writeFile(r,n,"utf-8"),await promises.rename(r,this.filePath);}catch{throw new Error("\u5C65\u6B74\u30D5\u30A1\u30A4\u30EB\u306E\u66F8\u304D\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F")}}async add(t){let r=await this.readHistory(),n={...t,id:randomUUID(),timestamp:new Date().toISOString()};r.unshift(n),r.length>M&&r.splice(M),await this.writeHistory(r);}async getAll(){return await this.readHistory()}async getRecent(t){return (await this.readHistory()).slice(0,t)}async deleteById(t){let r=await this.readHistory(),n=r.filter(o=>o.id!==t);return n.length===r.length?false:(await this.writeHistory(n),true)}async clear(){await this.writeHistory([]);}async findById(t){return (await this.readHistory()).find(n=>n.id===t)||null}async findByShortId(t){return (await this.readHistory()).filter(n=>n.id.startsWith(t))}async findByHash(t,r,n){return (await this.readHistory()).find(i=>i.sourceHash===t&&i.sourceLang===r&&i.targetLang===n)||null}};function F(e){return createHash("sha256").update(e).digest("hex")}async function U(e,t){try{if(!e&&!t.file&&!process.stdin.isTTY){let r=await Z();await A(r,t,"stdin");return}if(t.file){if(!l.existsSync(t.file))throw new Error(`\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${t.file})`);let r=l.readFileSync(t.file,"utf-8");await A(r,t,"file");return}if(e){await A(e,t,"arg");return}console.error("error: \u5165\u529B\u304C\u63D0\u4F9B\u3055\u308C\u3066\u3044\u307E\u305B\u3093"),console.error("\u4F7F\u3044\u65B9: enja <\u30C6\u30AD\u30B9\u30C8> \u307E\u305F\u306F enja -f <\u30D5\u30A1\u30A4\u30EB> \u307E\u305F\u306F \u30D1\u30A4\u30D7\u5165\u529B"),process.exit(1);}catch(r){console.error(r instanceof Error?`error: ${r.message}`:r),process.exit(1);}}async function A(e,t,r){if(!e||e.trim().length===0)throw new Error("\u7FFB\u8A33\u3059\u308B\u30C6\u30AD\u30B9\u30C8\u304C\u7A7A\u3067\u3059");let n=e;if(t.stripHtml&&(n=V(e),!n||n.trim().length===0))throw new Error("HTML\u30BF\u30B0\u3092\u9664\u53BB\u3057\u305F\u7D50\u679C\uFF0C\u7FFB\u8A33\u3059\u308B\u30C6\u30AD\u30B9\u30C8\u304C\u7A7A\u306B\u306A\u308A\u307E\u3057\u305F");let o=await B(t),i=new y,s=t.flip?"ja":"en",a=t.flip?"en":"ja",c=F(n),f=await i.findByHash(c,s,a);if(f&&t.cache!==false){console.log(`${p.green("\u2714")} \u30AD\u30E3\u30C3\u30B7\u30E5\u304B\u3089\u7FFB\u8A33\u7D50\u679C\u3092\u53D6\u5F97\u3057\u307E\u3057\u305F`);let P=f.translatedText;if(t.output)try{l.writeFileSync(t.output,P,"utf-8"),console.log(`${p.green("\u2714")} ${t.output} \u306B\u7FFB\u8A33\u7D50\u679C\u3092\u4FDD\u5B58\u3057\u307E\u3057\u305F`);}catch{throw new Error(`\u30D5\u30A1\u30A4\u30EB\u3078\u306E\u66F8\u304D\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F (${t.output})`)}else console.log(P);return}let m=`(${s} \u2192 ${a})`,b=Q(`\u7FFB\u8A33\u4E2D... ${m}`).start();try{let H=(await o.translate(n,s,a)).text;if(b.succeed(`\u7FFB\u8A33\u5B8C\u4E86 ${m}`),await i.add({sourceText:n,translatedText:H,sourceLang:s,targetLang:a,textLength:n.length,sourceHash:c,options:{stripHtml:t.stripHtml,file:t.file,inputMethod:r}}),t.output)try{l.writeFileSync(t.output,H,"utf-8"),console.log(`${p.green("\u2714")} ${t.output} \u306B\u7FFB\u8A33\u7D50\u679C\u3092\u4FDD\u5B58\u3057\u307E\u3057\u305F`);}catch{throw new Error(`\u30D5\u30A1\u30A4\u30EB\u3078\u306E\u66F8\u304D\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F (${t.output})`)}else console.log(H);}catch(P){throw b.fail(`\u7FFB\u8A33\u5931\u6557 ${m}`),P}}function Z(){return new Promise((e,t)=>{let r="";process.stdin.setEncoding("utf-8"),process.stdin.on("data",n=>{r+=n;}),process.stdin.on("end",()=>{e(r);}),process.stdin.on("error",n=>{t(n);});})}function V(e){return e.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"").replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi,"").replace(/<[^>]+>/g,"").replace(/&nbsp;/g," ").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&").replace(/&quot;/g,'"').replace(/&#39;/g,"'").replace(/\n\s*\n/g,`
3
- `).trim()}function E(e,t=false){return e.length===0?"\u5C65\u6B74\u306F\u3042\u308A\u307E\u305B\u3093":t?tt(e):X(e)}function X(e){let t=[];return t.push(`\u5168 ${e.length} \u4EF6\u306E\u5C65\u6B74
4
- `),e.forEach((r,n)=>{let o=new Date(r.timestamp).toLocaleString("ja-JP"),i=r.sourceText.length>30?r.sourceText.replace(/[\r\n]+/g," ").substring(0,30)+"...":r.sourceText;t.push(`${p.cyan("["+(n+1)+"]")} ${r.id.substring(0,8)} | ${o}`),t.push(` ${r.sourceLang} \u2192 ${r.targetLang} | ${i}`),t.push("");}),t.join(`
5
- `)}function tt(e){let t=[];return t.push(`\u5168 ${e.length} \u4EF6\u306E\u5C65\u6B74\u306E\u8A73\u7D30
6
- `),e.forEach((r,n)=>{n>0&&t.push("\u2500".repeat(60));let o=new Date(r.timestamp).toLocaleString("ja-JP");if(t.push(`${p.cyan("ID:")} ${r.id}`),t.push(`${p.cyan("Date:")} ${o}`),t.push(`${p.cyan("Direction:")} ${r.sourceLang} \u2192 ${r.targetLang}`),t.push(`${p.cyan("Length:")} ${r.textLength} characters`),r.options){let i=[];r.options.inputMethod&&i.push(`input=${r.options.inputMethod}`),r.options.stripHtml&&i.push("stripHtml=true"),r.options.file&&i.push(`file=${r.options.file}`),i.length>0&&t.push(`${p.cyan("Options:")} ${i.join(", ")}`);}t.push(""),t.push(`${p.cyan("Input:")}`),t.push(r.sourceText),t.push(""),t.push(`${p.cyan("Output:")}`),t.push(r.translatedText),t.push("");}),t.join(`
7
- `)}async function G(e,t){try{let r=new y;if(e){let s=e.trim();if(!s)throw new Error("\u7A7A\u306EID\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F");if(s.length>=36){let f=await r.findById(s);if(!f)throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${e})`);console.log(E([f],t.detail));return}if(s.length<8)throw new Error(`\u77ED\u7E2EID\u306F\u5C11\u306A\u304F\u3068\u30828\u6587\u5B57\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044 (${s.length})`);let a=await r.findByShortId(s);if(a.length===0)throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${e})`);let c=E(a,t.detail);console.log(c);return}if(t.delete){let s=t.delete.trim();if(!s)throw new Error("\u7A7A\u306EID\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F");if(s.length>=36){if(await r.deleteById(s))console.log(`${p.green("\u2714")} \u5C65\u6B74ID ${s} \u3092\u524A\u9664\u3057\u307E\u3057\u305F`);else throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${s})`);return}if(s.length<8)throw new Error(`\u77ED\u7E2EID\u3067\u524A\u9664\u3059\u308B\u5834\u5408\u306F\u5C11\u306A\u304F\u3068\u30828\u6587\u5B57\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044 (${s.length})`);let a=await r.findByShortId(s);if(a.length===0)throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${s})`);if(a.length>1){console.error("error: \u6307\u5B9A\u3055\u308C\u305F\u77ED\u7E2EID\u306F\u8907\u6570\u306E\u5C65\u6B74\u306B\u4E00\u81F4\u3057\u307E\u3057\u305F\uFF0E\u5B8C\u5168\u306AID\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\uFF0E");let m=E(a,!1);console.error(m),process.exit(1);}let c=a[0].id;if(await r.deleteById(c))console.log(`${p.green("\u2714")} \u5C65\u6B74ID ${c} \u3092\u524A\u9664\u3057\u307E\u3057\u305F`);else throw new Error(`\u524A\u9664\u306B\u5931\u6557\u3057\u307E\u3057\u305F (${c})`);return}if(t.clear){await r.clear(),console.log(`${p.green("\u2714")} \u5C65\u6B74\u3092\u30AF\u30EA\u30A2\u3057\u307E\u3057\u305F`);return}let n=Number(t.number)||10,o=await r.getRecent(n),i=E(o,t.detail);console.log(i);}catch(r){console.error(r instanceof Error?`error: ${r.message}`:r),process.exit(1);}}async function N(e,t,r){let n=new w;try{if(r?.reset){await n.reset(),console.log(`${p.green("\u2714")} \u8A2D\u5B9A\u3092\u30EA\u30BB\u30C3\u30C8\u3057\u307E\u3057\u305F`);return}if(r?.unset){await n.unset(r.unset),console.log(`${p.green("\u2714")} ${r.unset} \u3092\u30EA\u30BB\u30C3\u30C8\u3057\u307E\u3057\u305F`);return}if(e&&t){await n.set(e,t),console.log(`${p.green("\u2714")} ${e} \u3092\u8A2D\u5B9A\u3057\u307E\u3057\u305F`);return}if(e&&!t){let i=await n.get();if(e==="endpoint")console.log(i.endpoint);else if(e==="api-key")console.log(i.apiKey?J(i.apiKey):"(not set)");else if(e==="provider")console.log(i.provider);else throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${e})`);return}let o=await n.get();console.log(`${p.blue("provider:")} ${o.provider}`),console.log(`${p.blue("endpoint:")} ${o.endpoint}`),console.log(`${p.blue("apiKey:")} ${o.apiKey?J(o.apiKey):"(not set)"}`);}catch(o){console.error(o instanceof Error?`error: ${o.message}`:o),process.exit(1);}}function J(e){if(e.length<=8)return "*".repeat(e.length);let t=4,r=e.slice(0,t),n=e.slice(-t),o="*".repeat(e.length-t*2);return `${r}${o}${n}`}var L=JSON.parse(readFileSync(new URL("../package.json",import.meta.url),"utf-8")),T=new Command;T.name("enja").usage("[arguments] [options]").description(`Description: ${L.description}`).version(L.version,"-v, --version","output the current version");T.argument("[text]","\u30C6\u30AD\u30B9\u30C8\u3092\u7FFB\u8A33\u3059\u308B").option("-f, --file <path>","\u30D5\u30A1\u30A4\u30EB\u3092\u7FFB\u8A33\u3059\u308B").option("-o, --output <path>","\u30D5\u30A1\u30A4\u30EB\u306B\u51FA\u529B\u3059\u308B (\u30C7\u30D5\u30A9\u30EB\u30C8: \u6A19\u6E96\u51FA\u529B)").option("-s, --strip-html","HTML\u30BF\u30B0\u3092\u9664\u53BB\u3057\u3066\u304B\u3089\u7FFB\u8A33\u3059\u308B").option("-N, --no-cache","\u30AD\u30E3\u30C3\u30B7\u30E5\u3092\u4F7F\u7528\u305B\u305A\u306B\u518D\u7FFB\u8A33\u3059\u308B").option("-F, --flip","\u7FFB\u8A33\u65B9\u5411\u3092\u9006\u306B\u3059\u308B (default: \u82F1\u8A9E\u2192\u65E5\u672C\u8A9E)").option("--endpoint <url>","\u30AB\u30B9\u30BF\u30E0\u7FFB\u8A33\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u6307\u5B9A").option("--api-key <key>","API \u30AD\u30FC\u3092\u6307\u5B9A").option("--provider <name>","\u7FFB\u8A33\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC\u3092\u6307\u5B9A (gas, custom, openai, gemini)").showHelpAfterError().addHelpText("after",`
2
+ import*as u from'fs';import {readFileSync,promises}from'fs';import {Command}from'commander';import V from'ora';import*as y from'path';import*as I from'os';import M from'openai';import {GoogleGenAI,ApiError}from'@google/genai';import {randomUUID,createHash}from'crypto';import p from'kleur';var A=class{apiUrl;apiKey;constructor(e,r){this.apiUrl=e,this.apiKey=r;}async translate(e,r,i){try{let o={"Content-Type":"application/json"};this.apiKey&&(o.Authorization=`Bearer ${this.apiKey}`);let a=await fetch(this.apiUrl,{method:"POST",headers:o,body:JSON.stringify({text:e,sourceLang:r,targetLang:i})});if(!a.ok)throw new Error(`HTTP ${a.status} ${a.statusText}`);let l=await a.json();if(l.code!==200||!l.translatedText)throw new Error(`${l.error||"\u7FFB\u8A33\u306B\u5931\u6557\u3057\u307E\u3057\u305F"}`);return {text:l.translatedText,detectedSourceLang:l.detectedSourceLang}}catch(o){throw o}}};function $(){if(process.platform==="win32"){let r=process.env.APPDATA||y.join(I.homedir(),"AppData","Roaming");if(!r)throw new Error("APPDATA \u74B0\u5883\u5909\u6570\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u304A\u3089\u305A\uFF0C\u4EE3\u66FF\u30D1\u30B9\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F");return y.join(r,"enja-cli")}let e=I.homedir();return y.join(e,".config","enja-cli")}function S(){return y.join($(),"history.json")}function R(){return y.join($(),"config.json")}var f={provider:"gas",endpoint:"https://script.google.com/macros/s/AKfycbxOSbKD0aBTaQqIzHv00BMzp6WwrtWHBU3gJY0vhB2HblgUO-cgesfT1l-rrfttnWZzew/exec",apiKey:void 0,model:void 0},B={version:"1.1",activeProfile:"default",profiles:{default:{...f}}},P=class{filePath;constructor(){this.filePath=R();}ensureConfigDir(){let e=$();u.existsSync(e)||u.mkdirSync(e,{recursive:true});}async readAppConfig(){try{if(!u.existsSync(this.filePath))return {...B};let e=u.readFileSync(this.filePath,"utf-8"),r=JSON.parse(e);if(!r.version||r.version==="1"||!r.profiles){console.log("\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u3092\u65B0\u3057\u3044\u5F62\u5F0F\u306B\u79FB\u884C\u3057\u3066\u3044\u307E\u3059...");let o={version:"1.1",activeProfile:"default",profiles:{default:{provider:r.provider||f.provider,endpoint:r.endpoint||f.endpoint,apiKey:r.apiKey,model:r.model}}};return await this.writeAppConfig(o),o}return r}catch{return console.warn("\u8A2D\u5B9A\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F\uFF0E\u898F\u5B9A\u5024\u3092\u4F7F\u7528\u3057\u307E\u3059"),{...B}}}async writeAppConfig(e){try{this.ensureConfigDir(),u.writeFileSync(this.filePath,JSON.stringify(e,null,2),"utf-8");}catch{throw new Error("\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u306E\u66F8\u304D\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F")}}async readConfig(){let e=await this.readAppConfig(),r=e.profiles[e.activeProfile];return r?{...f,...r}:{...f}}async writeConfig(e){let r=await this.readAppConfig();r.profiles[r.activeProfile]=e,await this.writeAppConfig(r);}async get(){return await this.readConfig()}async set(e,r){let i=await this.readConfig();switch(e){case "endpoint":i.endpoint=r;break;case "api-key":i.apiKey=r;break;case "provider":if(!["gas","custom","openai","gemini"].includes(r))throw new Error(`\u7121\u52B9\u306A\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC (${r}): 'gas', 'custom', 'openai', 'gemini' \u306E\u3044\u305A\u308C\u304B\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044`);i.provider=r;break;case "model":i.model=r;break;default:throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${e})`)}await this.writeConfig(i);}async unset(e){let r=await this.readConfig();switch(e){case "endpoint":r.endpoint=f.endpoint;break;case "api-key":r.apiKey=void 0;break;case "provider":r.provider=f.provider;break;case "model":r.model=f.model;break;default:throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${e})`)}await this.writeConfig(r);}async reset(){await this.writeConfig({...f});}async getActiveProfileName(){return (await this.readAppConfig()).activeProfile}async getProfile(e){let i=(await this.readAppConfig()).profiles[e];if(!i)throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${e}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`);return i}async listProfiles(){let e=await this.readAppConfig();return Object.keys(e.profiles)}async createProfile(e,r){if(["ls","list","use","rm","delete","add","provider","endpoint","api-key","model"].includes(e.toLowerCase()))throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D '${e}' \u306F\u4E88\u7D04\u8A9E\u306E\u305F\u3081\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093`);if(!e.match(/^[a-zA-Z0-9_-]+$/))throw new Error(`\u7121\u52B9\u306A\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D (${e}): \u82F1\u6570\u5B57\uFF0C\u30CF\u30A4\u30D5\u30F3\uFF0C\u30A2\u30F3\u30C0\u30FC\u30B9\u30B3\u30A2\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059`);if(r?.provider&&!["gas","custom","openai","gemini"].includes(r.provider))throw new Error(`\u7121\u52B9\u306A\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC '${r.provider}': gas, custom, openai, gemini \u306E\u3044\u305A\u308C\u304B\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044`);let o=await this.readAppConfig();if(o.profiles[e])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${e}' \u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059`);o.profiles[e]={provider:r?.provider||"gas",endpoint:r?.endpoint,apiKey:r?.apiKey,model:r?.model},await this.writeAppConfig(o);}async deleteProfile(e){if(e==="default")throw new Error("'default' \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306F\u524A\u9664\u3067\u304D\u307E\u305B\u3093");let r=await this.readAppConfig();if(!r.profiles[e])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${e}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`);delete r.profiles[e],r.activeProfile===e&&(r.activeProfile="default"),await this.writeAppConfig(r);}async useProfile(e){let r=await this.readAppConfig();if(!r.profiles[e]){let i=Object.keys(r.profiles).join(", ");throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${e}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
3
+ \u5229\u7528\u53EF\u80FD\u306A\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB: ${i}`)}r.activeProfile=e,await this.writeAppConfig(r);}async setProfileConfig(e,r,i){let o=await this.readAppConfig();if(!o.profiles[e])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${e}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\uFF0E'enja config add ${e}' \u3067\u4F5C\u6210\u3057\u3066\u304F\u3060\u3055\u3044`);let a=o.profiles[e];switch(r){case "endpoint":a.endpoint=i;break;case "api-key":a.apiKey=i;break;case "provider":if(!["gas","custom","openai","gemini"].includes(i))throw new Error(`\u7121\u52B9\u306A\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC (${i}): 'gas', 'custom', 'openai', 'gemini' \u306E\u3044\u305A\u308C\u304B\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044`);a.provider=i;break;case "model":a.model=i;break;default:throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${r})`)}await this.writeAppConfig(o);}async unsetProfileConfig(e,r){let i=await this.readAppConfig();if(!i.profiles[e])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${e}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`);let o=i.profiles[e];switch(r){case "endpoint":o.endpoint=f.endpoint;break;case "api-key":o.apiKey=void 0;break;case "provider":o.provider=f.provider;break;case "model":o.model=void 0;break;default:throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${r})`)}await this.writeAppConfig(i);}async resetProfile(e){if(e==="default")throw new Error("'default' \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306F\u30EA\u30BB\u30C3\u30C8\u306E\u307F\u53EF\u80FD\u3067\u3059");let r=await this.readAppConfig();if(!r.profiles[e])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${e}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`);r.profiles[e]={...f},await this.writeAppConfig(r);}};var Y="https://script.google.com/macros/s/AKfycbxOSbKD0aBTaQqIzHv00BMzp6WwrtWHBU3gJY0vhB2HblgUO-cgesfT1l-rrfttnWZzew/exec";async function F(t){let e=new P,r;if(t?.profile)try{r=await e.getProfile(t.profile);}catch{let s=await e.listProfiles();throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t.profile}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
4
+ \u5229\u7528\u53EF\u80FD\u306A\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB: ${s.join(", ")}`)}else r=await e.get();let i=t?.endpoint||r.endpoint||Y,o=t?.apiKey||r.apiKey,a=t?.provider||r.provider||"gas",l=t?.model||r.model;return {endpoint:i,provider:a,apiKey:o,model:l}}var H=class{client;model;constructor(e,r){this.client=new M({apiKey:e}),this.model=r;}async translate(e,r,i){try{let o=this.mapLanguageCode(r),a=this.mapLanguageCode(i),l=`You are a professional translator. Translate the following text from ${o} to ${a}. Only return the translated text without any additional explanation or comments.`,s=(await this.client.chat.completions.create({model:this.model,messages:[{role:"system",content:l},{role:"user",content:e}],temperature:.3})).choices[0]?.message?.content;if(!s)throw new Error("\u7FFB\u8A33\u306B\u5931\u6557\u3057\u307E\u3057\u305F");return {text:s.trim(),detectedSourceLang:r}}catch(o){throw o instanceof M.APIError?new Error(`OpenAI\u7FFB\u8A33API\u30A8\u30E9\u30FC: ${o.message}`):o instanceof Error?new Error(`OpenAI\u7FFB\u8A33\u30A8\u30E9\u30FC: ${o.message}`):o}}mapLanguageCode(e){return {en:"English",ja:"Japanese"}[e.toLowerCase()]||e}};var x=class{client;model;constructor(e,r){this.client=new GoogleGenAI({apiKey:e}),this.model=r;}async translate(e,r,i){try{let o=this.mapLanguageCode(r),a=this.mapLanguageCode(i),l=`You are a professional translator. Translate the following text from ${o} to ${a}. Only return the translated text without any additional explanation or comments.`,s=(await this.client.models.generateContent({model:this.model,contents:e,config:{systemInstruction:l}})).text;if(!s)throw new Error("\u7FFB\u8A33\u306B\u5931\u6557\u3057\u307E\u3057\u305F");return {text:s.trim(),detectedSourceLang:r}}catch(o){if(o instanceof ApiError){let a=JSON.parse(o.message).error.message;throw new Error(`Gemini\u7FFB\u8A33API\u30A8\u30E9\u30FC: ${a}`)}else if(o instanceof Error)throw new Error(`Gemini\u7FFB\u8A33\u30A8\u30E9\u30FC: ${o.message}`);throw o}}mapLanguageCode(e){return {en:"English",ja:"Japanese"}[e.toLowerCase()]||e}};async function G(t){let e=await F(t);switch(e.provider){case "gas":case "custom":return new A(e.endpoint,e.apiKey);case "openai":if(!e.apiKey)throw new Error("OpenAI\u3092\u4F7F\u7528\u3059\u308B\u306B\u306FAPI\u30AD\u30FC\u304C\u5FC5\u8981\u3067\u3059");return new H(e.apiKey,e.model||"gpt-4o-mini");case "gemini":if(!e.apiKey)throw new Error("Gemini\u3092\u4F7F\u7528\u3059\u308B\u306B\u306FAPI\u30AD\u30FC\u304C\u5FC5\u8981\u3067\u3059");return new x(e.apiKey,e.model||"gemini-2.5-flash-lite");default:throw new Error(`\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC (${e.provider})`)}}var U=100,v=class{filePath;constructor(){this.filePath=S();}ensureConfigDir(){let e=$();u.existsSync(e)||u.mkdirSync(e,{recursive:true});}async readHistory(){try{let e=await promises.readFile(this.filePath,"utf-8");return JSON.parse(e)}catch(e){return e&&e.code==="ENOENT"?[]:(console.warn("\u5C65\u6B74\u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F\uFF0E\u7A7A\u914D\u5217\u3092\u8FD4\u3057\u307E\u3059"),[])}}async writeHistory(e){try{this.ensureConfigDir();let r=`${this.filePath}.tmp`,i=JSON.stringify(e,null,2);await promises.writeFile(r,i,"utf-8"),await promises.rename(r,this.filePath);}catch{throw new Error("\u5C65\u6B74\u30D5\u30A1\u30A4\u30EB\u306E\u66F8\u304D\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F")}}async add(e){let r=await this.readHistory(),i={...e,id:randomUUID(),timestamp:new Date().toISOString()};r.unshift(i),r.length>U&&r.splice(U),await this.writeHistory(r);}async getAll(){return await this.readHistory()}async getRecent(e){return (await this.readHistory()).slice(0,e)}async deleteById(e){let r=await this.readHistory(),i=r.filter(o=>o.id!==e);return i.length===r.length?false:(await this.writeHistory(i),true)}async clear(){await this.writeHistory([]);}async findById(e){return (await this.readHistory()).find(i=>i.id===e)||null}async findByShortId(e){return (await this.readHistory()).filter(i=>i.id.startsWith(e))}async findByHash(e,r,i){return (await this.readHistory()).find(a=>a.sourceHash===e&&a.sourceLang===r&&a.targetLang===i)||null}};function J(t){return createHash("sha256").update(t).digest("hex")}async function _(t,e){try{if(!t&&!e.file&&!process.stdin.isTTY){let r=await ee();await K(r,e,"stdin");return}if(e.file){if(!u.existsSync(e.file))throw new Error(`\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${e.file})`);let r=u.readFileSync(e.file,"utf-8");await K(r,e,"file");return}if(t){await K(t,e,"arg");return}console.error("error: \u5165\u529B\u304C\u63D0\u4F9B\u3055\u308C\u3066\u3044\u307E\u305B\u3093"),console.error("\u4F7F\u3044\u65B9: enja <\u30C6\u30AD\u30B9\u30C8> \u307E\u305F\u306F enja -f <\u30D5\u30A1\u30A4\u30EB> \u307E\u305F\u306F \u30D1\u30A4\u30D7\u5165\u529B"),process.exit(1);}catch(r){console.error(r instanceof Error?`error: ${r.message}`:r),process.exit(1);}}async function K(t,e,r){if(!t||t.trim().length===0)throw new Error("\u7FFB\u8A33\u3059\u308B\u30C6\u30AD\u30B9\u30C8\u304C\u7A7A\u3067\u3059");let i=t;if(e.stripHtml&&(i=re(t),!i||i.trim().length===0))throw new Error("HTML\u30BF\u30B0\u3092\u9664\u53BB\u3057\u305F\u7D50\u679C\uFF0C\u7FFB\u8A33\u3059\u308B\u30C6\u30AD\u30B9\u30C8\u304C\u7A7A\u306B\u306A\u308A\u307E\u3057\u305F");let o=await G(e),a=new v,l=e.flip?"ja":"en",n=e.flip?"en":"ja",s=J(i),c=await a.findByHash(s,l,n);if(c&&e.cache!==false){console.log(`${p.green("\u2714")} \u30AD\u30E3\u30C3\u30B7\u30E5\u304B\u3089\u7FFB\u8A33\u7D50\u679C\u3092\u53D6\u5F97\u3057\u307E\u3057\u305F`);let d=c.translatedText;if(e.output)try{u.writeFileSync(e.output,d,"utf-8"),console.log(`${p.green("\u2714")} ${e.output} \u306B\u7FFB\u8A33\u7D50\u679C\u3092\u4FDD\u5B58\u3057\u307E\u3057\u305F`);}catch{throw new Error(`\u30D5\u30A1\u30A4\u30EB\u3078\u306E\u66F8\u304D\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F (${e.output})`)}else console.log(d);return}let g=`(${l} \u2192 ${n})`,T=V(`\u7FFB\u8A33\u4E2D... ${g}`).start();try{let w=(await o.translate(i,l,n)).text;if(T.succeed(`\u7FFB\u8A33\u5B8C\u4E86 ${g}`),await a.add({sourceText:i,translatedText:w,sourceLang:l,targetLang:n,textLength:i.length,sourceHash:s,options:{stripHtml:e.stripHtml,file:e.file,inputMethod:r}}),e.output)try{u.writeFileSync(e.output,w,"utf-8"),console.log(`${p.green("\u2714")} ${e.output} \u306B\u7FFB\u8A33\u7D50\u679C\u3092\u4FDD\u5B58\u3057\u307E\u3057\u305F`);}catch{throw new Error(`\u30D5\u30A1\u30A4\u30EB\u3078\u306E\u66F8\u304D\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F (${e.output})`)}else console.log(w);}catch(d){throw T.fail(`\u7FFB\u8A33\u5931\u6557 ${g}`),d}}function ee(){return new Promise((t,e)=>{let r="";process.stdin.setEncoding("utf-8"),process.stdin.on("data",i=>{r+=i;}),process.stdin.on("end",()=>{t(r);}),process.stdin.on("error",i=>{e(i);});})}function re(t){return t.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"").replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi,"").replace(/<[^>]+>/g,"").replace(/&nbsp;/g," ").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&").replace(/&quot;/g,'"').replace(/&#39;/g,"'").replace(/\n\s*\n/g,`
5
+ `).trim()}function C(t,e=false){return t.length===0?"\u5C65\u6B74\u306F\u3042\u308A\u307E\u305B\u3093":e?oe(t):te(t)}function te(t){let e=[];return e.push(`\u5168 ${t.length} \u4EF6\u306E\u5C65\u6B74
6
+ `),t.forEach((r,i)=>{let o=new Date(r.timestamp).toLocaleString("ja-JP"),a=r.sourceText.length>30?r.sourceText.replace(/[\r\n]+/g," ").substring(0,30)+"...":r.sourceText;e.push(`${p.cyan("["+(i+1)+"]")} ${r.id.substring(0,8)} | ${o}`),e.push(` ${r.sourceLang} \u2192 ${r.targetLang} | ${a}`),e.push("");}),e.join(`
7
+ `)}function oe(t){let e=[];return e.push(`\u5168 ${t.length} \u4EF6\u306E\u5C65\u6B74\u306E\u8A73\u7D30
8
+ `),t.forEach((r,i)=>{i>0&&e.push("\u2500".repeat(60));let o=new Date(r.timestamp).toLocaleString("ja-JP");if(e.push(`${p.cyan("ID:")} ${r.id}`),e.push(`${p.cyan("Date:")} ${o}`),e.push(`${p.cyan("Direction:")} ${r.sourceLang} \u2192 ${r.targetLang}`),e.push(`${p.cyan("Length:")} ${r.textLength} characters`),r.options){let a=[];r.options.inputMethod&&a.push(`input=${r.options.inputMethod}`),r.options.stripHtml&&a.push("stripHtml=true"),r.options.file&&a.push(`file=${r.options.file}`),a.length>0&&e.push(`${p.cyan("Options:")} ${a.join(", ")}`);}e.push(""),e.push(`${p.cyan("Input:")}`),e.push(r.sourceText),e.push(""),e.push(`${p.cyan("Output:")}`),e.push(r.translatedText),e.push("");}),e.join(`
9
+ `)}async function N(t,e){try{let r=new v;if(t){let l=t.trim();if(!l)throw new Error("\u7A7A\u306EID\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F");if(l.length>=36){let c=await r.findById(l);if(!c)throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${t})`);console.log(C([c],e.detail));return}if(l.length<8)throw new Error(`\u77ED\u7E2EID\u306F\u5C11\u306A\u304F\u3068\u30828\u6587\u5B57\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044 (${l.length})`);let n=await r.findByShortId(l);if(n.length===0)throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${t})`);let s=C(n,e.detail);console.log(s);return}if(e.delete){let l=e.delete.trim();if(!l)throw new Error("\u7A7A\u306EID\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F");if(l.length>=36){if(await r.deleteById(l))console.log(`${p.green("\u2714")} \u5C65\u6B74ID ${l} \u3092\u524A\u9664\u3057\u307E\u3057\u305F`);else throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${l})`);return}if(l.length<8)throw new Error(`\u77ED\u7E2EID\u3067\u524A\u9664\u3059\u308B\u5834\u5408\u306F\u5C11\u306A\u304F\u3068\u30828\u6587\u5B57\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044 (${l.length})`);let n=await r.findByShortId(l);if(n.length===0)throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${l})`);if(n.length>1){console.error("error: \u6307\u5B9A\u3055\u308C\u305F\u77ED\u7E2EID\u306F\u8907\u6570\u306E\u5C65\u6B74\u306B\u4E00\u81F4\u3057\u307E\u3057\u305F\uFF0E\u5B8C\u5168\u306AID\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\uFF0E");let g=C(n,!1);console.error(g),process.exit(1);}let s=n[0].id;if(await r.deleteById(s))console.log(`${p.green("\u2714")} \u5C65\u6B74ID ${s} \u3092\u524A\u9664\u3057\u307E\u3057\u305F`);else throw new Error(`\u524A\u9664\u306B\u5931\u6557\u3057\u307E\u3057\u305F (${s})`);return}if(e.clear){await r.clear(),console.log(`${p.green("\u2714")} \u5C65\u6B74\u3092\u30AF\u30EA\u30A2\u3057\u307E\u3057\u305F`);return}let i=Number(e.number)||10,o=await r.getRecent(i),a=C(o,e.detail);console.log(a);}catch(r){console.error(r instanceof Error?`error: ${r.message}`:r),process.exit(1);}}async function z(t,e,r,i){let o=new P,a=i?.opts()||{},n={...i?.parent?.opts()||{},...a};try{if(t==="ls"||t==="list"){let s=await o.listProfiles(),c=await o.getActiveProfileName();console.log(p.bold("Profiles:"));for(let g of s){let T=g===c,d=await o.getProfile(g),w=T?p.green("*"):" ",b=d.model?` - ${d.model}`:"";console.log(` ${w} ${g} (${d.provider})${b}`);}return}if(t==="use"&&e){await o.useProfile(e),console.log(`${p.green("\u2714")} \u30A2\u30AF\u30C6\u30A3\u30D6\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092 '${e}' \u306B\u8A2D\u5B9A\u3057\u307E\u3057\u305F`);return}if((t==="rm"||t==="delete")&&e){await o.deleteProfile(e),console.log(`${p.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${e}' \u3092\u524A\u9664\u3057\u307E\u3057\u305F`);return}if(t==="add"&&e){let s={};n?.provider&&(s.provider=n.provider),n?.endpoint&&(s.endpoint=n.endpoint),n?.apiKey&&(s.apiKey=n.apiKey),n?.model&&(s.model=n.model),await o.createProfile(e,s),console.log(`${p.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${e}' \u3092\u4F5C\u6210\u3057\u307E\u3057\u305F`);return}if(!t){(n?.provider||n?.endpoint||n?.apiKey||n?.model||n?.reset||n?.unset)&&(console.error("error: \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044"),console.log(`
10
+ \u4F7F\u7528\u4F8B:`),console.log(" enja config work --provider openai \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u8A2D\u5B9A\u3092\u5909\u66F4"),console.log(" enja config add personal --provider gemini \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210"),process.exit(1));let s=await o.getActiveProfileName(),c=await o.get();console.log(`${p.bold("Active Profile:")} ${s}`),console.log(`${p.blue("provider:")} ${c.provider}`),console.log(`${p.blue("endpoint:")} ${c.endpoint||"(not set)"}`),console.log(`${p.blue("apiKey:")} ${c.apiKey?W(c.apiKey):"(not set)"}`),console.log(`${p.blue("model:")} ${c.model||"(not set)"}`);return}if(t&&!e&&(n?.provider||n?.endpoint||n?.apiKey||n?.model)){let s=!1;n.provider&&(await o.setProfileConfig(t,"provider",n.provider),s=!0),n.endpoint&&(await o.setProfileConfig(t,"endpoint",n.endpoint),s=!0),n.apiKey&&(await o.setProfileConfig(t,"api-key",n.apiKey),s=!0),n.model&&(await o.setProfileConfig(t,"model",n.model),s=!0),s&&console.log(`${p.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u306E\u8A2D\u5B9A\u3092\u66F4\u65B0\u3057\u307E\u3057\u305F`);return}if(t&&!e&&!n?.reset&&!n?.unset&&!n?.provider&&!n?.endpoint&&!n?.apiKey&&!n?.model){let s=await o.getProfile(t);console.log(`${p.bold("Profile:")} ${t}`),console.log(`${p.blue("provider:")} ${s.provider}`),console.log(`${p.blue("endpoint:")} ${s.endpoint||"(not set)"}`),console.log(`${p.blue("apiKey:")} ${s.apiKey?W(s.apiKey):"(not set)"}`),console.log(`${p.blue("model:")} ${s.model||"(not set)"}`);return}if(t&&n?.reset){await o.resetProfile(t),console.log(`${p.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u3092\u30EA\u30BB\u30C3\u30C8\u3057\u307E\u3057\u305F`);return}if(t&&n?.unset){await o.unsetProfileConfig(t,n.unset),console.log(`${p.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u306E ${n.unset} \u3092\u30EA\u30BB\u30C3\u30C8\u3057\u307E\u3057\u305F`);return}console.error("error: \u7121\u52B9\u306A\u30B3\u30DE\u30F3\u30C9\u5F62\u5F0F\u3067\u3059"),console.log(`
11
+ \u4F7F\u7528\u4F8B:`),console.log(" enja config \u73FE\u5728\u306E\u8A2D\u5B9A\u3092\u8868\u793A"),console.log(" enja config ls \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u4E00\u89A7"),console.log(" enja config work \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u8868\u793A"),console.log(" enja config use work \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u5207\u308A\u66FF\u3048"),console.log(" enja config work --provider openai \u8A2D\u5B9A\u5909\u66F4"),console.log(" enja config add personal --provider gemini \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u4F5C\u6210"),process.exit(1);}catch(s){console.error(s instanceof Error?`error: ${s.message}`:s),process.exit(1);}}function W(t){if(t.length<=8)return "*".repeat(t.length);let e=4,r=t.slice(0,e),i=t.slice(-e),o="*".repeat(t.length-e*2);return `${r}${o}${i}`}var O=JSON.parse(readFileSync(new URL("../package.json",import.meta.url),"utf-8")),E=new Command;E.name("enja").usage("[arguments] [options]").description(`Description: ${O.description}`).version(O.version,"-v, --version","output the current version");E.argument("[text]","\u30C6\u30AD\u30B9\u30C8\u3092\u7FFB\u8A33\u3059\u308B").option("-f, --file <path>","\u30D5\u30A1\u30A4\u30EB\u3092\u7FFB\u8A33\u3059\u308B").option("-o, --output <path>","\u30D5\u30A1\u30A4\u30EB\u306B\u51FA\u529B\u3059\u308B (\u30C7\u30D5\u30A9\u30EB\u30C8: \u6A19\u6E96\u51FA\u529B)").option("-s, --strip-html","HTML\u30BF\u30B0\u3092\u9664\u53BB\u3057\u3066\u304B\u3089\u7FFB\u8A33\u3059\u308B").option("-N, --no-cache","\u30AD\u30E3\u30C3\u30B7\u30E5\u3092\u4F7F\u7528\u305B\u305A\u306B\u518D\u7FFB\u8A33\u3059\u308B").option("-F, --flip","\u7FFB\u8A33\u65B9\u5411\u3092\u9006\u306B\u3059\u308B (default: \u82F1\u8A9E\u2192\u65E5\u672C\u8A9E)").option("-p, --profile <name>","\u4F7F\u7528\u3059\u308B\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A").option("--endpoint <url>","\u30AB\u30B9\u30BF\u30E0\u7FFB\u8A33\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u6307\u5B9A").option("--api-key <key>","API \u30AD\u30FC\u3092\u6307\u5B9A").option("--provider <name>","\u7FFB\u8A33\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC\u3092\u6307\u5B9A (gas, custom, openai, gemini)").option("--model <name>","\u4F7F\u7528\u3059\u308B\u30E2\u30C7\u30EB\u540D\u3092\u6307\u5B9A (\u4F8B: gpt-4o-mini, gemini-2.5-flash-lite)").showHelpAfterError().addHelpText("after",`
8
12
  Examples:
9
13
  $ enja "Hello, world!" # \u5F15\u6570\u3067\u6E21\u3055\u308C\u305F\u6587\u5B57\u5217\u3092\u7FFB\u8A33
10
14
  $ git --help | enja # \u30D1\u30A4\u30D7(\u6A19\u6E96\u5165\u529B)\u3067\u6E21\u3055\u308C\u305F\u30C6\u30AD\u30B9\u30C8\u3092\u7FFB\u8A33
@@ -12,16 +16,32 @@ Examples:
12
16
  $ enja -f input.txt -o output.txt # \u30D5\u30A1\u30A4\u30EB\u304B\u3089\u8AAD\u307F\u8FBC\u307F\uFF0C\u7FFB\u8A33\u7D50\u679C\u3092\u30D5\u30A1\u30A4\u30EB\u306B\u4FDD\u5B58
13
17
  $ cat README.md | enja -o japanese.md # \u30D1\u30A4\u30D7\u3068\u30D5\u30A1\u30A4\u30EB\u51FA\u529B\u306E\u7D44\u307F\u5408\u308F\u305B
14
18
  $ curl -s https://example.com | enja -s # HTML\u30BF\u30B0\u3092\u9664\u53BB\u3057\u3066\u7FFB\u8A33
19
+ $ enja "Hello" -p work # work \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u4F7F\u7528\u3057\u3066\u7FFB\u8A33
15
20
  $ enja "Hello, world!" --provider openai --api-key YOUR_OPENAI_API_KEY # OpenAI API \u3092\u4F7F\u7528\u3057\u3066\u7FFB\u8A33`).addHelpText("afterAll",`
16
- Enja CLI v${L.version}`).addHelpText("afterAll","Copyright (c) 2025 yhotta240").addHelpText("afterAll","GitHub: https://github.com/yhotamos/enja-cli").action(U);T.command("history").description("Description: \u7FFB\u8A33\u5C65\u6B74\u3092\u8868\u793A\u3059\u308B").argument("[id]","ID \u3067\u5C65\u6B74\u3092\u8868\u793A\u3059\u308B\uFF08\u5B8C\u5168 ID \u307E\u305F\u306F\u77ED\u7E2E ID\uFF09").option("-d, --detail","\u8A73\u7D30\u8868\u793A").option("-n, --number <number>","\u8868\u793A\u4EF6\u6570","10").option("--delete <id>","\u7279\u5B9A\u306E\u5C65\u6B74\u3092\u524A\u9664\u3059\u308B").option("--clear","\u5C65\u6B74\u3092\u30AF\u30EA\u30A2").action(G);T.command("config").description("Description: \u8A2D\u5B9A\u3092\u7BA1\u7406\u3059\u308B").argument("[key]","\u8A2D\u5B9A\u30AD\u30FC (endpoint, api-key, provider)").argument("[value]","\u8A2D\u5B9A\u5024").option("-l, --list","\u8A2D\u5B9A\u3092\u4E00\u89A7\u8868\u793A").option("--unset <key>","\u8A2D\u5B9A\u3092\u524A\u9664\uFF08\u30C7\u30D5\u30A9\u30EB\u30C8\u306B\u623B\u3059\uFF09").option("--reset","\u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u30EA\u30BB\u30C3\u30C8").addHelpText("after",`
17
- Values for provider: gas, custom, openai, gemini
18
-
21
+ Enja CLI v${O.version}`).addHelpText("afterAll","Copyright (c) 2025 yhotta240").addHelpText("afterAll","GitHub: https://github.com/yhotamos/enja-cli").action(_);E.command("history").description("Description: \u7FFB\u8A33\u5C65\u6B74\u3092\u8868\u793A\u3059\u308B").argument("[id]","ID \u3067\u5C65\u6B74\u3092\u8868\u793A\u3059\u308B\uFF08\u5B8C\u5168 ID \u307E\u305F\u306F\u77ED\u7E2E ID\uFF09").option("-d, --detail","\u8A73\u7D30\u8868\u793A").option("-n, --number <number>","\u8868\u793A\u4EF6\u6570","10").option("--delete <id>","\u7279\u5B9A\u306E\u5C65\u6B74\u3092\u524A\u9664\u3059\u308B").option("--clear","\u5C65\u6B74\u3092\u30AF\u30EA\u30A2").action(N);E.command("config").description("Description: \u8A2D\u5B9A\u3068\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u7BA1\u7406\u3059\u308B").argument("[profile]","\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u307E\u305F\u306F\u30B5\u30D6\u30B3\u30DE\u30F3\u30C9 (ls, use, rm, add)").argument("[subcommandArg]","\u30B5\u30D6\u30B3\u30DE\u30F3\u30C9\u306E\u5F15\u6570 (\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D)").option("--provider <name>","\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC\u3092\u8A2D\u5B9A (gas, custom, openai, gemini)").option("--endpoint <url>","\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u8A2D\u5B9A").option("--api-key <key>","\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306EAPI\u30AD\u30FC\u3092\u8A2D\u5B9A").option("--model <name>","\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u30E2\u30C7\u30EB\u3092\u8A2D\u5B9A").option("--unset <key>","\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u6307\u5B9A\u3057\u305F\u8A2D\u5B9A\u3092\u30EA\u30BB\u30C3\u30C8").option("--reset","\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u5168\u4F53\u3092\u30EA\u30BB\u30C3\u30C8").addHelpText("after",`
22
+ \u6CE8\u610F: --provider, --endpoint, --api-key, --model \u30AA\u30D7\u30B7\u30E7\u30F3\u306F
23
+ \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u307E\u305F\u306F 'add' \u30B5\u30D6\u30B3\u30DE\u30F3\u30C9\u3068\u4E00\u7DD2\u306B\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044
24
+
25
+ \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u7BA1\u7406:
26
+ $ enja config \u73FE\u5728\u306E\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u8868\u793A
27
+ $ enja config ls \u5168\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u4E00\u89A7\u8868\u793A
28
+ $ enja config <profile> \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u8A73\u7D30\u3092\u8868\u793A
29
+ $ enja config use <profile> \u30A2\u30AF\u30C6\u30A3\u30D6\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u5909\u66F4
30
+ $ enja config add <profile> [options] \u65B0\u3057\u3044\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210
31
+ $ enja config rm <profile> \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u524A\u9664
32
+
33
+ \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u8A2D\u5B9A:
34
+ $ enja config <profile> --provider <value> \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E provider \u3092\u5909\u66F4
35
+ $ enja config <profile> --model <value> \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E model \u3092\u5909\u66F4
36
+ $ enja config <profile> --unset <key> \u8A2D\u5B9A\u3092\u30EA\u30BB\u30C3\u30C8
37
+ $ enja config <profile> --reset \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u5168\u4F53\u3092\u30EA\u30BB\u30C3\u30C8
38
+
19
39
  Examples:
20
- $ enja config # \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u8868\u793A
21
- $ enja config --list # \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u8868\u793A
22
- $ enja config endpoint # endpoint \u306E\u5024\u3092\u8868\u793A
23
- $ enja config endpoint <URL> # endpoint \u3092\u8A2D\u5B9A
24
- $ enja config api-key <KEY> # API \u30AD\u30FC\u3092\u8A2D\u5B9A
25
- $ enja config provider gas # \u30D7\u30ED\u30D0\u30A4\u30C0\u30FC\u3092\u8A2D\u5B9A
26
- $ enja config --unset api-key # API \u30AD\u30FC\u3092\u524A\u9664
27
- $ enja config --reset # \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u30EA\u30BB\u30C3\u30C8`).action(N);T.parse();
40
+ $ enja config \u73FE\u5728\u306E\u8A2D\u5B9A\u3092\u8868\u793A
41
+ $ enja config ls \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u4E00\u89A7
42
+ $ enja config work work \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u8868\u793A
43
+ $ enja config use work work \u3092\u30A2\u30AF\u30C6\u30A3\u30D6\u306B\u8A2D\u5B9A
44
+ $ enja config work --provider openai work \u306E provider \u3092\u8A2D\u5B9A
45
+ $ enja config work --provider openai --model gpt-4o \u8907\u6570\u8A2D\u5B9A\u3092\u540C\u6642\u5909\u66F4
46
+ $ enja config add personal --provider gemini personal \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210
47
+ $ enja "Hello" -p work work \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3067\u7FFB\u8A33`).action(z);E.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yhotamos/enja-cli",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "英語を日本語に翻訳するシンプルなコマンドラインツール",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",