@yhotamos/enja-cli 1.0.1 → 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 +23 -8
  2. package/dist/index.js +38 -16
  3. package/package.json +3 -1
package/README.md CHANGED
@@ -12,9 +12,9 @@
12
12
  - Google Apps Script の LanguageApp を使用した軽量な翻訳
13
13
  - 引数,パイプ,ファイルから翻訳可能
14
14
  - HTML タグ除去機能で Web ページも翻訳可能
15
- - API キー不要,課金なし
16
- - カスタム翻訳エンドポイント対応
15
+ - OpenAI API や Gemini API を使用して高品質な翻訳も可能
17
16
  - 翻訳履歴の保存・参照機能
17
+ - 複数の翻訳API設定をプロファイルとして管理・切り替え可能
18
18
 
19
19
  ## インストール
20
20
 
@@ -38,6 +38,9 @@ enja -f input.txt -o output.txt
38
38
 
39
39
  # 翻訳方向を逆にする (日本語 → 英語)
40
40
  enja "こんにちは" -F
41
+
42
+ # OpenAI API を使用して翻訳
43
+ enja "Hello, world!" --provider openai --api-key YOUR_OPENAI_API_KEY
41
44
  ```
42
45
 
43
46
  ### 履歴と設定
@@ -46,9 +49,10 @@ enja "こんにちは" -F
46
49
  # 翻訳履歴を表示
47
50
  enja history
48
51
 
49
- # 設定を表示・変更
52
+ # 設定を表示/追加/アクティブ化
50
53
  enja config
51
- 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
52
56
  ```
53
57
 
54
58
  ### 実用例
@@ -57,8 +61,8 @@ enja config endpoint https://api.example.com/translate
57
61
  # エラーメッセージの翻訳
58
62
  npm install nonexistent-package 2>&1 | enja
59
63
 
60
- # Git コマンドのヘルプを日本語化
61
- git --help | enja
64
+ # コマンドのヘルプを日本語化
65
+ docker --help | enja
62
66
 
63
67
  # 英語のドキュメントを日本語に変換
64
68
  enja -f CONTRIBUTING.md -o CONTRIBUTING.ja.md
@@ -76,21 +80,32 @@ curl -s https://example.com/api/docs | enja
76
80
 
77
81
  ## セキュリティとプライバシー
78
82
 
83
+ ### デフォルトプロバイダー (GAS) 使用時
84
+
79
85
  - 翻訳データは保存されません(リクエストごとに処理し,即座にレスポンス)
80
86
  - 他のユーザーの翻訳内容は見えません(完全にステートレス)
81
87
  - 機密情報の翻訳は避けてください(公開エンドポイントを使用しているため)
82
88
 
89
+ ### カスタムプロバイダー使用時
90
+
91
+ OpenAI や Gemini などのカスタムプロバイダーを使用する場合は,各サービスのプライバシーポリシーに従います.
92
+
83
93
  ## 制限事項
84
94
 
95
+ ### デフォルトプロバイダー (GAS) 使用時
96
+
85
97
  - 1 日あたりのリクエスト数: すべてのユーザーで共有で約 5,000 リクエスト
86
98
  - 文字数制限: 1 リクエストあたり最大 100,000 文字
87
99
 
88
100
  制限に達した場合はエラーメッセージが表示されます.
89
101
 
102
+ ### カスタムプロバイダー使用時
103
+
104
+ 各サービスの制限に従います(OpenAI,Gemini など).
105
+
90
106
  ## 今後の予定
91
107
 
92
- - [ ] 複数言語対応
93
- - [ ] プロファイル機能(複数の設定を切り替え)
108
+ - [ ] より多くの翻訳プロバイダー対応(DeepL など)
94
109
  - [ ] API キーの暗号化保存
95
110
 
96
111
  ## 貢献
package/dist/index.js CHANGED
@@ -1,10 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import*as c from'fs';import {readFileSync,promises}from'fs';import {Command}from'commander';import Y from'ora';import*as d from'path';import*as C from'os';import {randomUUID,createHash}from'crypto';import l from'kleur';var x=class{apiUrl;apiKey;constructor(t,r){this.apiUrl=t,this.apiKey=r;}async translate(t,r,o){try{let i={"Content-Type":"application/json"};this.apiKey&&(i.Authorization=`Bearer ${this.apiKey}`);let n=await fetch(this.apiUrl,{method:"POST",headers:i,body:JSON.stringify({text:t,sourceLang:r,targetLang:o})});if(!n.ok)throw new Error(`HTTP ${n.status} ${n.statusText}`);let s=await n.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(i){throw i}}};function m(){if(process.platform==="win32"){let r=process.env.APPDATA||d.join(C.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 d.join(r,"enja-cli")}let t=C.homedir();return d.join(t,".config","enja-cli")}function A(){return d.join(m(),"history.json")}function L(){return d.join(m(),"config.json")}var h={provider:"gas",endpoint:"https://script.google.com/macros/s/AKfycbxOSbKD0aBTaQqIzHv00BMzp6WwrtWHBU3gJY0vhB2HblgUO-cgesfT1l-rrfttnWZzew/exec",apiKey:void 0},y=class{filePath;constructor(){this.filePath=L();}ensureConfigDir(){let t=m();c.existsSync(t)||c.mkdirSync(t,{recursive:true});}async readConfig(){try{if(!c.existsSync(this.filePath))return {...h};let t=c.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(),c.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 o=await this.readConfig();switch(t){case "endpoint":o.endpoint=r;break;case "api-key":o.apiKey=r;break;case "provider":if(r!=="gas"&&r!=="custom")throw new Error(`\u7121\u52B9\u306A\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC (${r}): gas \u307E\u305F\u306F custom \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044`);o.provider=r;break;default:throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${t})`)}await this.writeConfig(o);}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 J="https://script.google.com/macros/s/AKfycbxOSbKD0aBTaQqIzHv00BMzp6WwrtWHBU3gJY0vhB2HblgUO-cgesfT1l-rrfttnWZzew/exec";async function K(e){let r=await new y().get(),o=e?.endpoint||r.endpoint||J,i=e?.apiKey||r.apiKey||void 0,n=e?.provider||r.provider||"gas";return {endpoint:o,provider:n,apiKey:i}}async function k(e){let t=await K(e);switch(t.provider){case "gas":case "custom":return new x(t.endpoint,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 B=100,w=class{filePath;constructor(){this.filePath=A();}ensureConfigDir(){let t=m();c.existsSync(t)||c.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`,o=JSON.stringify(t,null,2);await promises.writeFile(r,o,"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(),o={...t,id:randomUUID(),timestamp:new Date().toISOString()};r.unshift(o),r.length>B&&r.splice(B),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(),o=r.filter(i=>i.id!==t);return o.length===r.length?false:(await this.writeHistory(o),true)}async clear(){await this.writeHistory([]);}async findById(t){return (await this.readHistory()).find(o=>o.id===t)||null}async findByShortId(t){return (await this.readHistory()).filter(o=>o.id.startsWith(t))}async findByHash(t,r,o){return (await this.readHistory()).find(n=>n.sourceHash===t&&n.sourceLang===r&&n.targetLang===o)||null}};function F(e){return createHash("sha256").update(e).digest("hex")}async function R(e,t){try{if(!e&&!t.file&&!process.stdin.isTTY){let r=await _();await j(r,t,"stdin");return}if(t.file){if(!c.existsSync(t.file))throw new Error(`\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${t.file})`);let r=c.readFileSync(t.file,"utf-8");await j(r,t,"file");return}if(e){await j(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 j(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 o=e;if(t.stripHtml&&(o=G(e),!o||o.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 i=await k(t),n=new w,s=t.flip?"ja":"en",a=t.flip?"en":"ja",p=F(o),g=await n.findByHash(p,s,a);if(g&&t.cache!==false){console.log(`${l.green("\u2714")} \u30AD\u30E3\u30C3\u30B7\u30E5\u304B\u3089\u7FFB\u8A33\u7D50\u679C\u3092\u53D6\u5F97\u3057\u307E\u3057\u305F`);let H=g.translatedText;if(t.output)try{c.writeFileSync(t.output,H,"utf-8"),console.log(`${l.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);return}let u=`(${s} \u2192 ${a})`,O=Y(`\u7FFB\u8A33\u4E2D... ${u}`).start();try{let T=(await i.translate(o,s,a)).text;if(O.succeed(`\u7FFB\u8A33\u5B8C\u4E86 ${u}`),await n.add({sourceText:o,translatedText:T,sourceLang:s,targetLang:a,textLength:o.length,sourceHash:p,options:{stripHtml:t.stripHtml,file:t.file,inputMethod:r}}),t.output)try{c.writeFileSync(t.output,T,"utf-8"),console.log(`${l.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(T);}catch(H){throw O.fail(`\u7FFB\u8A33\u5931\u6557 ${u}`),H}}function _(){return new Promise((e,t)=>{let r="";process.stdin.setEncoding("utf-8"),process.stdin.on("data",o=>{r+=o;}),process.stdin.on("end",()=>{e(r);}),process.stdin.on("error",o=>{t(o);});})}function G(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?Q(e):q(e)}function q(e){let t=[];return t.push(`\u5168 ${e.length} \u4EF6\u306E\u5C65\u6B74
4
- `),e.forEach((r,o)=>{let i=new Date(r.timestamp).toLocaleString("ja-JP"),n=r.sourceText.length>30?r.sourceText.replace(/[\r\n]+/g," ").substring(0,30)+"...":r.sourceText;t.push(`${l.cyan("["+(o+1)+"]")} ${r.id.substring(0,8)} | ${i}`),t.push(` ${r.sourceLang} \u2192 ${r.targetLang} | ${n}`),t.push("");}),t.join(`
5
- `)}function Q(e){let t=[];return t.push(`\u5168 ${e.length} \u4EF6\u306E\u5C65\u6B74\u306E\u8A73\u7D30
6
- `),e.forEach((r,o)=>{o>0&&t.push("\u2500".repeat(60));let i=new Date(r.timestamp).toLocaleString("ja-JP");if(t.push(`${l.cyan("ID:")} ${r.id}`),t.push(`${l.cyan("Date:")} ${i}`),t.push(`${l.cyan("Direction:")} ${r.sourceLang} \u2192 ${r.targetLang}`),t.push(`${l.cyan("Length:")} ${r.textLength} characters`),r.options){let n=[];r.options.inputMethod&&n.push(`input=${r.options.inputMethod}`),r.options.stripHtml&&n.push("stripHtml=true"),r.options.file&&n.push(`file=${r.options.file}`),n.length>0&&t.push(`${l.cyan("Options:")} ${n.join(", ")}`);}t.push(""),t.push(`${l.cyan("Input:")}`),t.push(r.sourceText),t.push(""),t.push(`${l.cyan("Output:")}`),t.push(r.translatedText),t.push("");}),t.join(`
7
- `)}async function U(e,t){try{let r=new w;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 g=await r.findById(s);if(!g)throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${e})`);console.log(E([g],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 p=E(a,t.detail);console.log(p);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(`${l.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 u=E(a,!1);console.error(u),process.exit(1);}let p=a[0].id;if(await r.deleteById(p))console.log(`${l.green("\u2714")} \u5C65\u6B74ID ${p} \u3092\u524A\u9664\u3057\u307E\u3057\u305F`);else throw new Error(`\u524A\u9664\u306B\u5931\u6557\u3057\u307E\u3057\u305F (${p})`);return}if(t.clear){await r.clear(),console.log(`${l.green("\u2714")} \u5C65\u6B74\u3092\u30AF\u30EA\u30A2\u3057\u307E\u3057\u305F`);return}let o=Number(t.number)||10,i=await r.getRecent(o),n=E(i,t.detail);console.log(n);}catch(r){console.error(r instanceof Error?`error: ${r.message}`:r),process.exit(1);}}async function N(e,t,r){let o=new y;try{if(r?.reset){await o.reset(),console.log(`${l.green("\u2714")} \u8A2D\u5B9A\u3092\u30EA\u30BB\u30C3\u30C8\u3057\u307E\u3057\u305F`);return}if(r?.unset){await o.unset(r.unset),console.log(`${l.green("\u2714")} ${r.unset} \u3092\u30EA\u30BB\u30C3\u30C8\u3057\u307E\u3057\u305F`);return}if(e&&t){await o.set(e,t),console.log(`${l.green("\u2714")} ${e} \u3092\u8A2D\u5B9A\u3057\u307E\u3057\u305F`);return}if(e&&!t){let n=await o.get();if(e==="endpoint")console.log(n.endpoint);else if(e==="api-key")console.log(n.apiKey?M(n.apiKey):"(not set)");else if(e==="provider")console.log(n.provider);else throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${e})`);return}let i=await o.get();console.log(`${l.blue("provider:")} ${i.provider}`),console.log(`${l.blue("endpoint:")} ${i.endpoint}`),console.log(`${l.blue("apiKey:")} ${i.apiKey?M(i.apiKey):"(not set)"}`);}catch(i){console.error(i instanceof Error?`error: ${i.message}`:i),process.exit(1);}}function M(e){if(e.length<=8)return "*".repeat(e.length);let t=4,r=e.slice(0,t),o=e.slice(-t),i="*".repeat(e.length-t*2);return `${r}${i}${o}`}var b=JSON.parse(readFileSync(new URL("../package.json",import.meta.url),"utf-8")),P=new Command;P.name("enja").usage("[arguments] [options]").description(`Description: ${b.description}`).version(b.version,"-v, --version","output the current version");P.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 (\u30C7\u30D5\u30A9\u30EB\u30C8: \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)").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,14 +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
15
- $ enja "Hello" --endpoint https://api.example.com/translate --api-key YOUR_KEY # \u30AB\u30B9\u30BF\u30E0\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8`).addHelpText("afterAll",`
16
- Enja CLI v${b.version}`).addHelpText("afterAll","Copyright (c) 2025 yhotta240").addHelpText("afterAll","GitHub: https://github.com/yhotamos/enja-cli").action(R);P.command("history").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 (\u30C7\u30D5\u30A9\u30EB\u30C8: 10)","10").option("--delete <id>","\u7279\u5B9A\u306E\u5C65\u6B74\u3092\u524A\u9664\u3059\u308B").option("--clear","\u5C65\u6B74\u3092\u30AF\u30EA\u30A2").action(U);P.command("config").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",`
19
+ $ enja "Hello" -p work # work \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u4F7F\u7528\u3057\u3066\u7FFB\u8A33
20
+ $ enja "Hello, world!" --provider openai --api-key YOUR_OPENAI_API_KEY # OpenAI API \u3092\u4F7F\u7528\u3057\u3066\u7FFB\u8A33`).addHelpText("afterAll",`
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
+
17
39
  Examples:
18
- $ enja config # \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u8868\u793A
19
- $ enja config --list # \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u8868\u793A
20
- $ enja config endpoint # endpoint \u306E\u5024\u3092\u8868\u793A
21
- $ enja config endpoint <URL> # endpoint \u3092\u8A2D\u5B9A
22
- $ enja config api-key <KEY> # API \u30AD\u30FC\u3092\u8A2D\u5B9A
23
- $ enja config provider gas # \u30D7\u30ED\u30D0\u30A4\u30C0\u30FC\u3092\u8A2D\u5B9A
24
- $ enja config --unset api-key # API \u30AD\u30FC\u3092\u524A\u9664
25
- $ enja config --reset # \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u30EA\u30BB\u30C3\u30C8`).action(N);P.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.0.1",
3
+ "version": "1.2.0",
4
4
  "description": "英語を日本語に翻訳するシンプルなコマンドラインツール",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -60,8 +60,10 @@
60
60
  },
61
61
  "homepage": "https://github.com/yhotamos/enja-cli#readme",
62
62
  "dependencies": {
63
+ "@google/genai": "^1.33.0",
63
64
  "commander": "^14.0.2",
64
65
  "kleur": "^4.1.5",
66
+ "openai": "^6.9.1",
65
67
  "ora": "^9.0.0"
66
68
  },
67
69
  "devDependencies": {