@yhotamos/enja-cli 1.4.2 → 1.4.3

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 (2) hide show
  1. package/dist/index.js +34 -40
  2. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -1,28 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import*as E from'fs';import {readFileSync,promises}from'fs';import {Command}from'commander';import Pt from'ora';import d from'kleur';import*as C from'path';import*as U from'os';import Y from'openai';import {GoogleGenAI,ApiError}from'@google/genai';import {randomUUID,createHash}from'crypto';var $=class o{static DEFAULT_ENDPOINT="https://script.google.com/macros/s/AKfycbxOSbKD0aBTaQqIzHv00BMzp6WwrtWHBU3gJY0vhB2HblgUO-cgesfT1l-rrfttnWZzew/exec";static ENDPOINT_URL_PATTERN=/^https:\/\/script\.google\.com\/macros\/s\/[a-zA-Z0-9_-]+\/(exec|dev)(\?.*)?$/;static getDefaultProfile(){return {provider:"gas",endpoint:o.DEFAULT_ENDPOINT}}apiUrl;apiKey;constructor(t=o.DEFAULT_ENDPOINT,e){if(!o.ENDPOINT_URL_PATTERN.test(t))throw new Error("\u7121\u52B9\u306A GAS \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8 URL \u3067\u3059");this.apiUrl=t,this.apiKey=e;}getModel(){return null}async translate(t,e,r){let i={"Content-Type":"application/json"};this.apiKey&&(i.Authorization=`Bearer ${this.apiKey}`);let a=await fetch(this.apiUrl,{method:"POST",headers:i,body:JSON.stringify({text:t,sourceLang:e,targetLang:r})});if(!a.ok)throw new Error(`HTTP ${a.status} ${a.statusText}`);let n=await a.json();if(n.code!==200||!n.translatedText)throw new Error(`${n.error||"\u7FFB\u8A33\u306B\u5931\u6557\u3057\u307E\u3057\u305F"}`);return {text:n.translatedText,detectedSourceLang:n.detectedSourceLang}}};function T(){if(process.platform==="win32"){let e=process.env.APPDATA||C.join(U.homedir(),"AppData","Roaming");if(!e)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 C.join(e,"enja-cli")}let t=U.homedir();return C.join(t,".config","enja-cli")}function J(){return C.join(T(),"history.json")}function G(){return C.join(T(),"config.json")}var V=["ls","list","use","rm","delete","add","rename","copy","provider","endpoint","api-key","model","default"];function S(o){if(V.includes(o.toLowerCase()))throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D '${o}' \u306F\u4E88\u7D04\u8A9E\u306E\u305F\u3081\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093`);if(!o.match(/^[a-zA-Z0-9_-]+$/))throw new Error(`\u7121\u52B9\u306A\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D (${o}): \u82F1\u6570\u5B57\uFF0C\u30CF\u30A4\u30D5\u30F3\uFF0C\u30A2\u30F3\u30C0\u30FC\u30B9\u30B3\u30A2\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059`)}var P=class o{static DEFAULT_ENDPOINT="http://localhost:1234/api/v1/chat";static getDefaultProfile(){return {provider:"lmstudio",endpoint:o.DEFAULT_ENDPOINT}}baseUrl;model;apiKey;constructor(t=o.DEFAULT_ENDPOINT,e,r){this.baseUrl=t,this.model=e,this.apiKey=r;}getModel(){return this.model||null}async translate(t,e,r){let i=`You are a professional translator. Translate the following text from ${e} to ${r}. Only return the translated text without any additional explanation.`,a=this.resolveEndpoint(this.baseUrl),n={"Content-Type":"application/json",Accept:"application/json",...this.apiKey?{Authorization:`Bearer ${this.apiKey}`}:{}},l=JSON.stringify({model:this.model,system_prompt:i,input:t}),s=await fetch(a.toString(),{method:"POST",headers:n,body:l}),p=await s.text(),c=this.parseJsonSafe(p,s);if(!s.ok){if(c?.error){if(typeof c.error=="string")throw new Error(`LMStudio: ${c.error}`);let{message:g,code:m}=c.error;if(m==="model_not_found")throw new Error(`LMStudio: \u30E2\u30C7\u30EB "${this.model}" \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u30E2\u30C7\u30EB\u540D\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002`);if(m==="invalid_api_key")throw new Error("LMStudio: API\u30AD\u30FC\u304C\u7121\u52B9\u3067\u3059\u3002API \u30AD\u30FC\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002");let v=g||"LMStudio: \u4E0D\u660E\u306A\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F";throw new Error(v)}throw new Error(`LMStudio: HTTP ${s.status} ${s.statusText}`)}let f=this.extractTranslatedFromOutput(c);if(f)return {text:f.trim(),detectedSourceLang:e};throw c?.error?new Error(`LMStudio: ${c.error||"\u4E0D\u660E\u306A\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"}`):new Error("LMStudio: \u51FA\u529B\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093")}resolveEndpoint(t){let e;try{e=new URL(t);}catch{throw new Error("LMStudio: \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306E URL \u304C\u4E0D\u6B63\u3067\u3059\uFF08\u4F8B: http://localhost:1234/\uFF09")}let r=e.pathname.replace(/\/+$/,"");if(r===""||r==="/")e.pathname="/api/v1/chat";else if(r!=="/api/v1/chat")throw new Error('LMStudio: \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8 URL \u306F "/api/v1/chat" \u3092\u542B\u3081\u308B\u304B\uFF0C\u30D1\u30B9\u3092\u7A7A\u306B\u3057\u3066\u304F\u3060\u3055\u3044');return e}parseJsonSafe(t,e){if(t)try{return JSON.parse(t)}catch{if(!e.ok){let r=t?`${t.slice(0,200)}...`:"";throw new Error(`LMStudio: \u975EJSON\u30EC\u30B9\u30DD\u30F3\u30B9 (HTTP ${e.status} ${e.statusText}) ${r}`)}throw new Error("LMStudio: \u30EC\u30B9\u30DD\u30F3\u30B9\u306E JSON \u89E3\u6790\u306B\u5931\u6557\u3057\u307E\u3057\u305F")}}extractTranslatedFromOutput(t){if(!t||!Array.isArray(t.output)||t.output.length===0)return null;for(let e of t.output)if(e&&typeof e=="object"&&e.type==="message"){let r=this.extractFromItem(e);if(r)return r}for(let e of t.output){let r=this.extractFromItem(e);if(r)return r}return null}extractFromItem(t){if(!t&&t!=="")return null;if(typeof t=="string")return t;if(Array.isArray(t)){for(let e of t){let r=this.extractFromItem(e);if(r)return r}return null}if(typeof t=="object"){if(typeof t=="object"&&typeof t.text=="string")return t.text;if(typeof t=="object"&&typeof t.response=="string")return t.response;if(typeof t.content=="string")return t.content;if(t.content&&typeof t.content=="object"){let e=t.content;if(typeof e.text=="string")return e.text;if(typeof e.content=="string")return e.content;let r=this.extractFromItem(e);if(r)return r}if(Array.isArray(t.content))for(let e of t.content){let r=this.extractFromItem(e);if(r)return r}if(Array.isArray(t.output)){let e=this.extractTranslatedFromOutput({output:t.output});if(e)return e}}return null}};var L=class o{static DEFAULT_MODEL="gpt-4o-mini";static getDefaultProfile(){return {provider:"openai",model:o.DEFAULT_MODEL}}client;model;constructor(t,e=o.DEFAULT_MODEL){this.client=new Y({apiKey:t}),this.model=e;}getModel(){return this.model}async translate(t,e,r){try{let i=this.mapLanguageCode(e),a=this.mapLanguageCode(r),n=`You are a professional translator. Translate the following text from ${i} 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:n},{role:"user",content:t}],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:e}}catch(i){throw i instanceof Y.APIError?new Error(`OpenAI\u7FFB\u8A33API\u30A8\u30E9\u30FC: ${i.message}`):i instanceof Error?new Error(`OpenAI\u7FFB\u8A33\u30A8\u30E9\u30FC: ${i.message}`):i}}mapLanguageCode(t){return {en:"English",ja:"Japanese"}[t.toLowerCase()]||t}};var A=class o{static DEFAULT_MODEL="gemini-2.5-flash-lite";static getDefaultProfile(){return {provider:"gemini",model:o.DEFAULT_MODEL}}client;model;constructor(t,e=o.DEFAULT_MODEL){this.client=new GoogleGenAI({apiKey:t}),this.model=e;}getModel(){return this.model}async translate(t,e,r){try{let i=this.mapLanguageCode(e),a=this.mapLanguageCode(r),n=`You are a professional translator. Translate the following text from ${i} to ${a}. Only return the translated text without any additional explanation or comments.`,s=(await this.client.models.generateContent({model:this.model,contents:t,config:{systemInstruction:n}})).text;if(!s)throw new Error("\u7FFB\u8A33\u306B\u5931\u6557\u3057\u307E\u3057\u305F");return {text:s.trim(),detectedSourceLang:e}}catch(i){if(i instanceof ApiError){let a=JSON.parse(i.message).error.message;throw new Error(`Gemini\u7FFB\u8A33API\u30A8\u30E9\u30FC: ${a}`)}else if(i instanceof Error)throw new Error(`Gemini\u7FFB\u8A33\u30A8\u30E9\u30FC: ${i.message}`);throw i}}mapLanguageCode(t){return {en:"English",ja:"Japanese"}[t.toLowerCase()]||t}};var R="gas",x={gas:$.getDefaultProfile,openai:L.getDefaultProfile,gemini:A.getDefaultProfile,lmstudio:P.getDefaultProfile,custom:()=>({provider:"custom"})},W={version:"1.1",activeProfile:"default",profiles:{default:x[R]()}},w=class o{filePath;constructor(){this.filePath=G();}async get(){return await this.readConfig()}async getActiveProfileName(){return (await this.readAppConfig()).activeProfile}async getProfile(t){let r=(await this.readAppConfig()).profiles[t];if(!r)throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`);return r}async listProfiles(){let t=await this.readAppConfig();return Object.keys(t.profiles)}async useProfile(t){let e=await this.readAppConfig();if(!e.profiles[t]){let r=Object.keys(e.profiles).join(", ");throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
3
- \u5229\u7528\u53EF\u80FD\u306A\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB: ${r}`)}e.activeProfile=t,await this.writeAppConfig(e);}async addProfile(t,e){if(S(t),e?.provider&&!this.isTranslatorProvider(e.provider)){let l=Object.keys(x).join(", ");throw new Error(`\u7121\u52B9\u306A\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC '${e.provider}': ${l} \u306E\u3044\u305A\u308C\u304B\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044`)}let r=await this.readAppConfig();if(r.profiles[t])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059`);let i=e?.provider||R,n={...this.getDefaultProfileByProvider(i),...e};r.profiles[t]=n,await this.writeAppConfig(r);}async renameProfile(t,e){if(t==="default")throw new Error("'default' \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306F\u540D\u524D\u3092\u5909\u66F4\u3067\u304D\u307E\u305B\u3093");if(t===e)return;S(e);let r=await this.readAppConfig();if(!r.profiles[t])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`);if(r.profiles[e])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${e}' \u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059`);r.profiles[e]=r.profiles[t],delete r.profiles[t],r.activeProfile===t&&(r.activeProfile=e),await this.writeAppConfig(r);}async copyProfile(t,e){if(t===e)throw new Error("\u30B3\u30D4\u30FC\u5143\u3068\u30B3\u30D4\u30FC\u5148\u306E\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u304C\u540C\u3058\u3067\u3059");S(e);let r=await this.readAppConfig();if(!r.profiles[t])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`);if(r.profiles[e])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${e}' \u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059`);r.profiles[e]={...r.profiles[t]},await this.writeAppConfig(r);}async deleteProfile(t){if(t==="default")throw new Error("'default' \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306F\u524A\u9664\u3067\u304D\u307E\u305B\u3093");let e=await this.readAppConfig();if(!e.profiles[t])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`);delete e.profiles[t],e.activeProfile===t&&(e.activeProfile="default"),await this.writeAppConfig(e);}async setProfileConfig(t,e,r){let i=await this.readAppConfig();if(!i.profiles[t])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\uFF0E'enja config add ${t}' \u3067\u4F5C\u6210\u3057\u3066\u304F\u3060\u3055\u3044`);let a=i.profiles[t];switch(e){case "endpoint":a.endpoint=r;break;case "api-key":a.apiKey=r;break;case "provider":if(!this.isTranslatorProvider(r)){let n=Object.keys(x).join(", ");throw new Error(`\u7121\u52B9\u306A\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC (${r}): ${n} \u306E\u3044\u305A\u308C\u304B\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044`)}a.provider=r;break;case "model":a.model=r;break;default:throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${e})`)}await this.writeAppConfig(i);}async unsetProfileConfig(t,e){let r=await this.readAppConfig();if(!r.profiles[t])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`);let i=r.profiles[t],a=i.provider||R,n=this.getDefaultProfileByProvider(a);switch(e){case "provider":i.provider=n.provider;break;case "endpoint":i.endpoint=n.endpoint;break;case "api-key":i.apiKey=n.apiKey;break;case "model":i.model=n.model;break;default:throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${e})`)}await this.writeAppConfig(r);}async resetProfileConfig(t){let e=await this.readAppConfig();if(!e.profiles[t])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`);let r=this.getDefaultProfile();e.profiles[t]={...r},await this.writeAppConfig(e);}static isAppConfig(t){return !(!t||typeof t!="object"||!("profiles"in t)||!("activeProfile"in t)||typeof t.activeProfile!="string"||typeof t.profiles!="object"||t.profiles===null)}getDefaultProfile(){return x[R]()}getDefaultProfileByProvider(t){return x[t]()}isTranslatorProvider(t){return t in x}async ensureConfigDir(){let t=T();await promises.mkdir(t,{recursive:true});}async readAppConfig(){try{let t=await promises.readFile(this.filePath,"utf-8"),e=JSON.parse(t);return o.isAppConfig(e)?e:(console.warn("\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u306E\u5F62\u5F0F\u304C\u4E0D\u6B63\u3067\u3059\uFF0E\u898F\u5B9A\u5024\u3092\u4F7F\u7528\u3057\u307E\u3059"),{...W})}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"),{...W}}}async writeAppConfig(t){try{await this.ensureConfigDir();let e=`${this.filePath}.${Date.now()}.tmp`,r=JSON.stringify(t,null,2);await promises.writeFile(e,r,"utf-8"),await promises.rename(e,this.filePath);}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 t=await this.readAppConfig();return t.profiles[t.activeProfile]||this.getDefaultProfile()}async writeConfig(t){let e=await this.readAppConfig();e.profiles[e.activeProfile]=t,await this.writeAppConfig(e);}};async function z(o){let t=new w,e;if(o?.profile)try{e=await t.getProfile(o.profile);}catch{let l=await t.listProfiles();throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${o.profile}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
4
- \u5229\u7528\u53EF\u80FD\u306A\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB: ${l.join(", ")}`)}else e=await t.get();let r=o?.provider||e.provider||"gas",i=o?.endpoint||e.endpoint,a=o?.apiKey||e.apiKey,n=o?.model||e.model;return {endpoint:i,provider:r,apiKey:a,model:n}}var at=new Set(["169.254.169.254"]);function lt(o){let t=o.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);if(!t)return null;let e=t.slice(1).map(r=>Number(r));return e.some(r=>!Number.isInteger(r)||r<0||r>255)?null:e}function pt(o,t,e){return o[0]===t&&o[1]===e}function ft(o){let[t,e]=o;return t===10||t===192&&e===168||t===172&&e>=16&&e<=31}function ct(o){return o[0]===127}function dt(o){return pt(o,169,254)}function gt(o){return o==="::1"||o==="0:0:0:0:0:0:0:1"}function ut(o){return o.toLowerCase().startsWith("fe80:")}var mt=new Set(["localhost","127.0.0.1","::1"]),wt=new Set(["10.","192.168."]);function I(o,t={}){let{allowLocalEndpoint:e=false,allowPrivateEndpoint:r=false,allowHttp:i=false}=t,a;try{a=new URL(o);}catch{throw new Error("\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8 URL \u304C\u4E0D\u6B63\u3067\u3059")}let n=a.protocol;if(n!=="https:"&&n!=="http:")throw new Error("\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8 URL \u306F http:// \u307E\u305F\u306F https:// \u3067\u59CB\u307E\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059");if(a.username||a.password)throw new Error("\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8 URL \u306B\u8A8D\u8A3C\u60C5\u5831\u3092\u57CB\u3081\u8FBC\u3080\u3053\u3068\u306F\u8A31\u53EF\u3055\u308C\u3066\u3044\u307E\u305B\u3093");let l=a.hostname;if(at.has(l))throw new Error("\u6307\u5B9A\u3055\u308C\u305F\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u4E0A\u306E\u7406\u7531\u306B\u3088\u308A\u8A31\u53EF\u3055\u308C\u3066\u3044\u307E\u305B\u3093");let s=lt(l),p=s!==null,c=mt.has(l)||(p?ct(s):false)||gt(l);if((p?dt(s):false)||ut(l))throw new Error("\u6307\u5B9A\u3055\u308C\u305F\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306F\u30EA\u30F3\u30AF\u30ED\u30FC\u30AB\u30EB\u30A2\u30C9\u30EC\u30B9\u306E\u305F\u3081\u8A31\u53EF\u3055\u308C\u3066\u3044\u307E\u305B\u3093");let g=p?ft(s):Array.from(wt).some(m=>l.startsWith(m));if(n==="http:"&&!(i||e&&c))throw new Error(`\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8 URL \u306F https:// \u3067\u59CB\u307E\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
5
- HTTP \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u4F7F\u7528\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B\u5834\u5408\u306F\uFF0C--allow-http \u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044
6
- \u30ED\u30FC\u30AB\u30EB\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3067\u3042\u308C\u3070 --allow-local-endpoint \u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u3082\u8A31\u53EF\u3055\u308C\u307E\u3059`);if(c&&!e)throw new Error(`\u30ED\u30FC\u30AB\u30EB\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306E\u4F7F\u7528\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30EA\u30B9\u30AF\u304C\u3042\u308B\u305F\u3081\u8A31\u53EF\u3055\u308C\u3066\u3044\u307E\u305B\u3093
7
- \u30ED\u30FC\u30AB\u30EB\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u4F7F\u7528\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B\u5834\u5408\u306F\uFF0C--allow-local-endpoint \u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044`);if(g&&!r)throw new Error(`\u30D7\u30E9\u30A4\u30D9\u30FC\u30C8 IP \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306E\u4F7F\u7528\u306F\u65E2\u5B9A\u3067\u8A31\u53EF\u3055\u308C\u3066\u3044\u307E\u305B\u3093
8
- \u4F7F\u7528\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B\u5834\u5408\u306F\uFF0C--allow-private-endpoint \u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044`);return true}async function X(o){let t=new w,e=await z(o),r;o?.profile?r=o.profile:r=await t.getActiveProfileName();let i=o?.allowLocalEndpoint??false,a=o?.allowPrivateEndpoint??false,n=o?.allowHttp??false,l={allowLocalEndpoint:i,allowPrivateEndpoint:a,allowHttp:n};switch(e.provider){case "gas":case "custom":{let{endpoint:s,apiKey:p}=e;if(!s)throw new Error("\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8 URL \u304C\u5FC5\u8981\u3067\u3059");return I(s,l),{translator:new $(s,p),config:e,activeProfile:r}}case "openai":{let{apiKey:s,model:p}=e;if(!s)throw new Error("OpenAI \u3092\u4F7F\u7528\u3059\u308B\u306B\u306F API \u30AD\u30FC\u304C\u5FC5\u8981\u3067\u3059");return {translator:new L(s,p),config:e,activeProfile:r}}case "gemini":{let{apiKey:s,model:p}=e;if(!s)throw new Error("Gemini \u3092\u4F7F\u7528\u3059\u308B\u306B\u306F API \u30AD\u30FC\u304C\u5FC5\u8981\u3067\u3059");return {translator:new A(s,p),config:e,activeProfile:r}}case "lmstudio":{let{endpoint:s}=e;if(o?.endpoint?(I(o.endpoint,l),s=o.endpoint):s?I(s,l):(s=P.DEFAULT_ENDPOINT,I(s,{allowLocalEndpoint:true,allowPrivateEndpoint:true,allowHttp:true})),!e.model)throw new Error("LM Studio \u3092\u4F7F\u7528\u3059\u308B\u306B\u306F\u30E2\u30C7\u30EB\u540D\u304C\u5FC5\u8981\u3067\u3059");return {translator:new P(s,e.model,e.apiKey),config:e,activeProfile:r}}default:throw new Error(`\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC (${e.provider})`)}}var Z=100,j=class{filePath;constructor(){this.filePath=J();}ensureConfigDir(){let t=T();E.existsSync(t)||E.mkdirSync(t,{recursive:true});}async readHistory(){try{let t=await promises.readFile(this.filePath,"utf-8");return JSON.parse(t)}catch(t){return t instanceof Error&&"code"in 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 e=`${this.filePath}.tmp`,r=JSON.stringify(t,null,2);await promises.writeFile(e,r,"utf-8"),await promises.rename(e,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 e=await this.readHistory(),r={...t,id:randomUUID(),timestamp:new Date().toISOString()};e.unshift(r),e.length>Z&&e.splice(Z),await this.writeHistory(e);}async getAll(){return await this.readHistory()}async getRecent(t){return (await this.readHistory()).slice(0,t)}async deleteById(t){let e=await this.readHistory(),r=e.filter(i=>i.id!==t);return r.length===e.length?false:(await this.writeHistory(r),true)}async clear(){await this.writeHistory([]);}async findById(t){return (await this.readHistory()).find(r=>r.id===t)||null}async findByShortId(t){return (await this.readHistory()).filter(r=>r.id.startsWith(t))}async findByHash(t,e,r){return (await this.readHistory()).find(a=>a.sourceHash===t&&a.sourceLang===e&&a.targetLang===r)||null}};function q(o){return createHash("sha256").update(o).digest("hex")}function Q(o){o.argument("[text]","\u7FFB\u8A33\u3059\u308B\u30C6\u30AD\u30B9\u30C8\uFF08\u7701\u7565\u3057\u305F\u5834\u5408\u306F\u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306F\u6A19\u6E96\u5165\u529B\u304B\u3089\u8AAD\u307F\u8FBC\u3080\uFF09").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>","\u4E00\u6642\u7684\u306B\u30AB\u30B9\u30BF\u30E0\u7FFB\u8A33\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u6307\u5B9A\uFF08\u73FE\u5728\u306E\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306B\u9069\u7528\uFF09").option("--api-key <key>","\u4E00\u6642\u7684\u306B API \u30AD\u30FC\u3092\u6307\u5B9A\uFF08\u73FE\u5728\u306E\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306B\u9069\u7528\uFF09").option("--provider <name>","\u4E00\u6642\u7684\u306B\u7FFB\u8A33\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC\u3092\u6307\u5B9A (\u4F8B: gas, openai, gemini, lmstudio; \u73FE\u5728\u306E\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306B\u9069\u7528)").option("--model <name>","\u4E00\u6642\u7684\u306B\u4F7F\u7528\u3059\u308B\u30E2\u30C7\u30EB\u540D\u3092\u6307\u5B9A (\u4F8B: gpt-4o-mini, gemini-2.5-flash-lite; \u73FE\u5728\u306E\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306B\u9069\u7528)").option("--allow-local-endpoint","localhost\uFF08127.0.0.1\uFF09\u306E\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u8A31\u53EF\u3059\u308B").option("--allow-private-endpoint","\u30D7\u30E9\u30A4\u30D9\u30FC\u30C8\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\uFF08\u4F8B: 192.168.x.x\uFF09\u306E\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u8A31\u53EF\u3059\u308B").option("--allow-http","HTTP\uFF08\u975E TLS\uFF09\u306E\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u8A31\u53EF\u3059\u308B").addHelpText("after",`
9
- Examples:
10
- $ enja "Hello, world!" # \u6587\u5B57\u5217\u3092\u7FFB\u8A33
11
- $ docker --help | enja # \u6A19\u6E96\u5165\u529B\u3092\u7FFB\u8A33
12
- $ enja -f input.txt -o output.txt # \u30D5\u30A1\u30A4\u30EB\u5165\u51FA\u529B
13
- $ enja "Hello" -p work # \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A\u3057\u3066\u7FFB\u8A33
14
- $ enja "Hello" --provider openai --api-key YOUR_API_KEY # \u4E00\u6642\u7684\u306B\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC\u3092\u6307\u5B9A\u3057\u3066\u7FFB\u8A33`).action(Et);}async function Et(o,t){try{if(!o&&!t.file&&!process.stdin.isTTY){let e=await $t();await K(e,t,"stdin");return}if(t.file){if(!E.existsSync(t.file))throw new Error(`\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${t.file})`);let e=E.readFileSync(t.file,"utf-8");await K(e,t,"file");return}if(o){await K(o,t,"arg");return}throw new Error(`\u7FFB\u8A33\u3059\u308B\u30C6\u30AD\u30B9\u30C8\u304C\u63D0\u4F9B\u3055\u308C\u3066\u3044\u307E\u305B\u3093
15
-
16
- \u4F7F\u7528\u4F8B:
17
- enja "Hello, world!" # \u5F15\u6570\u3067\u6E21\u3055\u308C\u305F\u6587\u5B57\u5217\u3092\u7FFB\u8A33
18
- enja -f input.txt # \u30D5\u30A1\u30A4\u30EB\u304B\u3089\u30C6\u30AD\u30B9\u30C8\u3092\u8AAD\u307F\u8FBC\u3093\u3067\u7FFB\u8A33
19
- cat README.md | enja # \u30D1\u30A4\u30D7(\u6A19\u6E96\u5165\u529B)\u3067\u6E21\u3055\u308C\u305F\u30C6\u30AD\u30B9\u30C8\u3092\u7FFB\u8A33`)}catch(e){console.error(`error: ${vt(e)}`),process.exit(1);}}async function K(o,t,e){if(!o||o.trim().length===0)throw new Error("\u7FFB\u8A33\u3059\u308B\u30C6\u30AD\u30B9\u30C8\u304C\u7A7A\u3067\u3059");let r=o;if(t.stripHtml&&(r=Ct(o),!r||r.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{translator:i,config:a,activeProfile:n}=await X(t),l=new j,s=t.flip?"ja":"en",p=t.flip?"en":"ja",c=q(r),f=await l.findByHash(c,s,p);if(f&&t.cache!==false){console.log(`${d.green("\u2714")} \u30AD\u30E3\u30C3\u30B7\u30E5\u304B\u3089\u7FFB\u8A33\u7D50\u679C\u3092\u53D6\u5F97\u3057\u307E\u3057\u305F`);let y=f.translatedText;if(t.output)try{E.writeFileSync(t.output,y,"utf-8"),console.log(`${d.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(y);return}let g=`(${s} \u2192 ${p})`,m=i.getModel()||a.model,v=n||"unknown",h=`[${v} | ${a.provider}${m?` | ${m}`:""}]`,k=Pt(`\u7FFB\u8A33\u4E2D... ${g} ${h}`).start();try{let M=(await i.translate(r,s,p)).text;if(k.succeed(`\u7FFB\u8A33\u5B8C\u4E86 ${g} ${h}`),await l.add({sourceText:r,translatedText:M,sourceLang:s,targetLang:p,textLength:r.length,sourceHash:c,profile:v,provider:a.provider,model:m,options:{stripHtml:t.stripHtml,file:t.file,inputMethod:e}}),t.output)try{E.writeFileSync(t.output,M,"utf-8"),console.log(`${d.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(M);}catch(y){throw k.fail(`\u7FFB\u8A33\u5931\u6557 ${g} ${h}`),y}}function vt(o){if(o instanceof Error)return o.message;try{return String(o)}catch{return "Unknown error"}}function $t(){return new Promise((o,t)=>{let e="";process.stdin.setEncoding("utf-8"),process.stdin.on("data",r=>{e+=r;}),process.stdin.on("end",()=>{o(e);}),process.stdin.on("error",r=>{t(r);});})}function Ct(o){return o.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,`
20
- `).trim()}function D(o,t=false){return o.length===0?"\u5C65\u6B74\u306F\u3042\u308A\u307E\u305B\u3093":t?Lt(o):Tt(o)}function Tt(o){let t=[`\u5168 ${o.length} \u4EF6\u306E\u5C65\u6B74
21
- `];return o.forEach((e,r)=>{let i=et(e.timestamp),a=At(e),n=tt(e.sourceText,20),l=tt(e.translatedText||"",20),s=[d.cyan(`[${r+1}]`),e.id.substring(0,8),i,a||null].filter(Boolean).join(" | ");t.push(s),t.push(` ${e.sourceLang} \u2192 ${e.targetLang} | ${n} \u2192 ${l}`),t.push("");}),t.join(`
22
- `)}function Lt(o){let t=[`\u5168 ${o.length} \u4EF6\u306E\u5C65\u6B74\u306E\u8A73\u7D30
23
- `];return o.forEach((e,r)=>{r>0&&t.push("\u2500".repeat(60));let i=14;if(t.push(`${d.cyan("ID:".padEnd(i))} ${e.id}`),t.push(`${d.cyan("Date:".padEnd(i))} ${et(e.timestamp)}`),t.push(`${d.cyan("Direction:".padEnd(i))} ${e.sourceLang} \u2192 ${e.targetLang}`),t.push(`${d.cyan("InputLength:".padEnd(i))} ${e.textLength} characters`),t.push(`${d.cyan("OutputLength:".padEnd(i))} ${e.translatedText.length} characters`),e.profile&&t.push(`${d.cyan("Profile:".padEnd(i))} ${e.profile}`),e.provider&&t.push(`${d.cyan("Provider:".padEnd(i))} ${e.provider}`),e.model&&t.push(`${d.cyan("Model:".padEnd(i))} ${e.model}`),e.options){let a=[e.options.inputMethod&&`input=${e.options.inputMethod}`,e.options.stripHtml&&"stripHtml=true",e.options.file&&`file=${e.options.file}`].filter(Boolean).join(", ");a&&t.push(`${d.cyan("Options:".padEnd(i))} ${a}`);}t.push("",`${d.cyan("Input:")}`,e.sourceText),t.push("",`${d.cyan("Output:")}`,e.translatedText||"","");}),t.join(`
24
- `)}function et(o){return new Date(o).toLocaleString("ja-JP")}function tt(o,t){let e=o.replace(/[\r\n]+/g," ");return e.length>t?e.substring(0,t)+"...":e}function At(o){return [o.profile,o.provider,o.model].filter(t=>!!t).map(t=>d.magenta(t)).join(d.dim("\u30FB"))}function rt(o){o.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","10").option("--delete <id>","\u7279\u5B9A\u306E\u5C65\u6B74\u3092\u524A\u9664\u3059\u308B").option("--clear","\u5C65\u6B74\u3092\u30AF\u30EA\u30A2").action(xt);}async function xt(o,t){try{let e=new j;if(o){let n=o.trim();if(!n)throw new Error("\u7A7A\u306EID\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F");if(n.length>=36){let p=await e.findById(n);if(!p)throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${o})`);console.log(D([p],t.detail));return}if(n.length<8)throw new Error(`\u77ED\u7E2EID\u306F\u5C11\u306A\u304F\u3068\u30828\u6587\u5B57\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044 (${n.length})`);let l=await e.findByShortId(n);if(l.length===0)throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${o})`);let s=D(l,t.detail);console.log(s);return}if(t.delete){let n=t.delete.trim();if(!n)throw new Error("\u7A7A\u306EID\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F");if(n.length>=36){if(await e.deleteById(n))console.log(`${d.green("\u2714")} \u5C65\u6B74ID ${n} \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 (${n})`);return}if(n.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 (${n.length})`);let l=await e.findByShortId(n);if(l.length===0)throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${n})`);if(l.length>1)throw new 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
25
- ${D(l,!1)}`);let s=l[0].id;if(await e.deleteById(s))console.log(`${d.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(t.clear){await e.clear(),console.log(`${d.green("\u2714")} \u5C65\u6B74\u3092\u30AF\u30EA\u30A2\u3057\u307E\u3057\u305F`);return}let r=Number(t.number)||10,i=await e.getRecent(r),a=D(i,t.detail);console.log(a);}catch(e){console.error(e instanceof Error?`error: ${e.message}`:e),process.exit(1);}}function nt(o){o.command("config").usage("[profile|subcommand] [options]").description("\u8A2D\u5B9A\u3068\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u7BA1\u7406\u3059\u308B").allowExcessArguments(true).argument("[profile|subcommand]",`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u307E\u305F\u306F\u30B5\u30D6\u30B3\u30DE\u30F3\u30C9
2
+ import*as E from'fs';import {readFileSync,promises}from'fs';import {Command}from'commander';import g from'kleur';import {select,confirm}from'@inquirer/prompts';import*as _ from'os';import*as $ from'path';import {GoogleGenAI,ApiError}from'@google/genai';import W from'openai';import {randomUUID,createHash}from'crypto';import Dt from'ora';async function F(o,t){let r=o.map(e=>({name:e===t?g.green(`${e} (active)`):e,value:e}));try{return await select({message:"\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044",choices:r})}catch{throw new Error("\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u9078\u629E\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F")}}async function K(o){try{if(!await confirm({message:`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${o}' \u3092\u524A\u9664\u3057\u3066\u3082\u3088\u308D\u3057\u3044\u3067\u3059\u304B\uFF1F`}))return console.log("\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u524A\u9664\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F"),!1}catch{throw new Error("\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u524A\u9664\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F")}return true}function T(){if(process.platform==="win32"){let r=process.env.APPDATA||$.join(_.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 $.join(r,"enja-cli")}let t=_.homedir();return $.join(t,".config","enja-cli")}function Y(){return $.join(T(),"history.json")}function z(){return $.join(T(),"config.json")}var C=class{static getDefaultProfile(){return {provider:"custom"}}apiUrl;apiKey;model;constructor(t,r,e){this.apiUrl=t,this.apiKey=r,this.model=e;}getModel(){return this.model||null}async translate(t,r,e){let i={"Content-Type":"application/json",Accept:"application/json"};this.apiKey&&(i.Authorization=`Bearer ${this.apiKey}`);let a=await fetch(this.apiUrl,{method:"POST",headers:i,body:JSON.stringify({text:t,sourceLang:r,targetLang:e,...this.model?{model:this.model}:{}})}),n=await a.text();if(!a.ok){let l;try{let c=JSON.parse(n);if(this.isRecord(c)){let f=this.asString(c.error)??(this.isRecord(c.error)?this.asString(c.error.message):null)??this.asString(c.message);f&&(l=f);}}catch{}throw new Error(`Custom: HTTP ${a.status} ${a.statusText}${l?` - ${l}`:""}`)}let p;try{p=JSON.parse(n);}catch{if(n.trim())return {text:n.trim(),detectedSourceLang:r};throw new Error("Custom: \u30EC\u30B9\u30DD\u30F3\u30B9\u306E JSON \u89E3\u6790\u306B\u5931\u6557\u3057\u307E\u3057\u305F")}let s=this.extractText(p);if(s)return {text:s.trim(),detectedSourceLang:r};throw new Error("Custom: \u30EC\u30B9\u30DD\u30F3\u30B9\u304B\u3089\u7FFB\u8A33\u30C6\u30AD\u30B9\u30C8\u3092\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F")}extractText(t){if(!this.isRecord(t))return null;if(Array.isArray(t.choices)&&t.choices.length>0){let r=t.choices[0];if(this.isRecord(r)){let e=(this.isRecord(r.message)?this.asString(r.message.content):null)??this.asString(r.text);if(e)return e}}if(Array.isArray(t.output))for(let r of t.output){let e=this.extractFromItem(r);if(e)return e}if(Array.isArray(t.results)&&t.results.length>0){let r=t.results[0];if(this.isRecord(r)){let e=this.asString(r.content)??this.asString(r.text);if(e)return e}}return this.asString(t.translation)??this.asString(t.translated_text)??this.asString(t.translatedText)??this.asString(t.result)??this.asString(t.text)??this.asString(t.content)??this.asString(t.response)??this.asString(t.output)??null}extractFromItem(t){if(typeof t=="string")return t||null;if(!this.isRecord(t))return null;if(t.type==="message"||t.type==="text"){let r=this.asString(t.content)??this.asString(t.text);if(r)return r}return this.asString(t.content)??this.asString(t.text)??this.asString(t.response)??null}isRecord(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}asString(t){return typeof t=="string"&&t.length>0?t:null}};var x=class o{static DEFAULT_ENDPOINT="https://script.google.com/macros/s/AKfycbxOSbKD0aBTaQqIzHv00BMzp6WwrtWHBU3gJY0vhB2HblgUO-cgesfT1l-rrfttnWZzew/exec";static ENDPOINT_URL_PATTERN=/^https:\/\/script\.google\.com\/macros\/s\/[a-zA-Z0-9_-]+\/(exec|dev)(\?.*)?$/;static getDefaultProfile(){return {provider:"gas",endpoint:o.DEFAULT_ENDPOINT}}apiUrl;apiKey;constructor(t=o.DEFAULT_ENDPOINT,r){if(!o.ENDPOINT_URL_PATTERN.test(t))throw new Error("\u7121\u52B9\u306A GAS \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8 URL \u3067\u3059");this.apiUrl=t,this.apiKey=r;}getModel(){return null}async translate(t,r,e){let i={"Content-Type":"application/json"};this.apiKey&&(i.Authorization=`Bearer ${this.apiKey}`);let a=await fetch(this.apiUrl,{method:"POST",headers:i,body:JSON.stringify({text:t,sourceLang:r,targetLang:e})});if(!a.ok)throw new Error(`HTTP ${a.status} ${a.statusText}`);let n=await a.json();if(n.code!==200||!n.translatedText)throw new Error(`${n.error||"\u7FFB\u8A33\u306B\u5931\u6557\u3057\u307E\u3057\u305F"}`);return {text:n.translatedText,detectedSourceLang:n.detectedSourceLang}}};var A=class o{static DEFAULT_MODEL="gemini-2.5-flash-lite";static getDefaultProfile(){return {provider:"gemini",model:o.DEFAULT_MODEL}}client;model;constructor(t,r=o.DEFAULT_MODEL){this.client=new GoogleGenAI({apiKey:t}),this.model=r;}getModel(){return this.model}async translate(t,r,e){try{let i=this.mapLanguageCode(r),a=this.mapLanguageCode(e),n=`You are a professional translator. Translate the following text from ${i} to ${a}. Only return the translated text without any additional explanation or comments.`,s=(await this.client.models.generateContent({model:this.model,contents:t,config:{systemInstruction:n}})).text;if(!s)throw new Error("\u7FFB\u8A33\u306B\u5931\u6557\u3057\u307E\u3057\u305F");return {text:s.trim(),detectedSourceLang:r}}catch(i){if(i instanceof ApiError){let a=JSON.parse(i.message).error.message;throw new Error(`Gemini\u7FFB\u8A33API\u30A8\u30E9\u30FC: ${a}`)}else if(i instanceof Error)throw new Error(`Gemini\u7FFB\u8A33\u30A8\u30E9\u30FC: ${i.message}`);throw i}}mapLanguageCode(t){return {en:"English",ja:"Japanese"}[t.toLowerCase()]||t}};var P=class o{static DEFAULT_ENDPOINT="http://localhost:1234/api/v1/chat";static getDefaultProfile(){return {provider:"lmstudio",endpoint:o.DEFAULT_ENDPOINT}}baseUrl;model;apiKey;constructor(t=o.DEFAULT_ENDPOINT,r,e){this.baseUrl=t,this.model=r,this.apiKey=e;}getModel(){return this.model||null}async translate(t,r,e){let i=`You are a professional translator. Translate the following text from ${r} to ${e}. Only return the translated text without any additional explanation.`,a=this.resolveEndpoint(this.baseUrl),n={"Content-Type":"application/json",Accept:"application/json",...this.apiKey?{Authorization:`Bearer ${this.apiKey}`}:{}},p=JSON.stringify({model:this.model,system_prompt:i,input:t}),s=await fetch(a.toString(),{method:"POST",headers:n,body:p}),l=await s.text(),c=this.parseJsonSafe(l,s);if(!s.ok){if(c?.error){if(typeof c.error=="string")throw new Error(`LMStudio: ${c.error}`);let{message:d,code:u}=c.error;if(u==="model_not_found")throw new Error(`LMStudio: \u30E2\u30C7\u30EB "${this.model}" \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u30E2\u30C7\u30EB\u540D\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002`);if(u==="invalid_api_key")throw new Error("LMStudio: API\u30AD\u30FC\u304C\u7121\u52B9\u3067\u3059\u3002API \u30AD\u30FC\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002");let v=d||"LMStudio: \u4E0D\u660E\u306A\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F";throw new Error(v)}throw new Error(`LMStudio: HTTP ${s.status} ${s.statusText}`)}let f=this.extractTranslatedFromOutput(c);if(f)return {text:f.trim(),detectedSourceLang:r};throw c?.error?new Error(`LMStudio: ${c.error||"\u4E0D\u660E\u306A\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"}`):new Error("LMStudio: \u51FA\u529B\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093")}resolveEndpoint(t){let r;try{r=new URL(t);}catch{throw new Error("LMStudio: \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306E URL \u304C\u4E0D\u6B63\u3067\u3059\uFF08\u4F8B: http://localhost:1234/\uFF09")}let e=r.pathname.replace(/\/+$/,"");if(e===""||e==="/")r.pathname="/api/v1/chat";else if(e!=="/api/v1/chat")throw new Error('LMStudio: \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8 URL \u306F "/api/v1/chat" \u3092\u542B\u3081\u308B\u304B\uFF0C\u30D1\u30B9\u3092\u7A7A\u306B\u3057\u3066\u304F\u3060\u3055\u3044');return r}parseJsonSafe(t,r){if(t)try{return JSON.parse(t)}catch{if(!r.ok){let e=t?`${t.slice(0,200)}...`:"";throw new Error(`LMStudio: \u975EJSON\u30EC\u30B9\u30DD\u30F3\u30B9 (HTTP ${r.status} ${r.statusText}) ${e}`)}throw new Error("LMStudio: \u30EC\u30B9\u30DD\u30F3\u30B9\u306E JSON \u89E3\u6790\u306B\u5931\u6557\u3057\u307E\u3057\u305F")}}extractTranslatedFromOutput(t){if(!t||!Array.isArray(t.output)||t.output.length===0)return null;for(let r of t.output)if(r&&typeof r=="object"&&r.type==="message"){let e=this.extractFromItem(r);if(e)return e}for(let r of t.output){let e=this.extractFromItem(r);if(e)return e}return null}extractFromItem(t){if(!t&&t!=="")return null;if(typeof t=="string")return t;if(Array.isArray(t)){for(let r of t){let e=this.extractFromItem(r);if(e)return e}return null}if(typeof t=="object"){if(typeof t=="object"&&typeof t.text=="string")return t.text;if(typeof t=="object"&&typeof t.response=="string")return t.response;if(typeof t.content=="string")return t.content;if(t.content&&typeof t.content=="object"){let r=t.content;if(typeof r.text=="string")return r.text;if(typeof r.content=="string")return r.content;let e=this.extractFromItem(r);if(e)return e}if(Array.isArray(t.content))for(let r of t.content){let e=this.extractFromItem(r);if(e)return e}if(Array.isArray(t.output)){let r=this.extractTranslatedFromOutput({output:t.output});if(r)return r}}return null}};var L=class o{static DEFAULT_MODEL="gpt-4o-mini";static getDefaultProfile(){return {provider:"openai",model:o.DEFAULT_MODEL}}client;model;constructor(t,r=o.DEFAULT_MODEL){this.client=new W({apiKey:t}),this.model=r;}getModel(){return this.model}async translate(t,r,e){try{let i=this.mapLanguageCode(r),a=this.mapLanguageCode(e),n=`You are a professional translator. Translate the following text from ${i} 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:n},{role:"user",content:t}],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(i){throw i instanceof W.APIError?new Error(`OpenAI\u7FFB\u8A33API\u30A8\u30E9\u30FC: ${i.message}`):i instanceof Error?new Error(`OpenAI\u7FFB\u8A33\u30A8\u30E9\u30FC: ${i.message}`):i}}mapLanguageCode(t){return {en:"English",ja:"Japanese"}[t.toLowerCase()]||t}};var X=["ls","list","use","rm","delete","add","rename","copy","provider","endpoint","api-key","model","default"];function R(o){if(X.includes(o.toLowerCase()))throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D '${o}' \u306F\u4E88\u7D04\u8A9E\u306E\u305F\u3081\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093`);if(!o.match(/^[a-zA-Z0-9_-]+$/))throw new Error(`\u7121\u52B9\u306A\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D (${o}): \u82F1\u6570\u5B57\uFF0C\u30CF\u30A4\u30D5\u30F3\uFF0C\u30A2\u30F3\u30C0\u30FC\u30B9\u30B3\u30A2\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059`)}var b="gas",j={gas:x.getDefaultProfile,openai:L.getDefaultProfile,gemini:A.getDefaultProfile,lmstudio:P.getDefaultProfile,custom:C.getDefaultProfile},Z={version:"1.1",activeProfile:"default",profiles:{default:j[b]()}},h=class o{filePath;constructor(){this.filePath=z();}async get(){return await this.readConfig()}async getActiveProfileName(){return (await this.readAppConfig()).activeProfile}async getProfile(t){let e=(await this.readAppConfig()).profiles[t];if(!e)throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`);return e}async listProfiles(){let t=await this.readAppConfig();return Object.keys(t.profiles)}async useProfile(t){let r=await this.readAppConfig();if(!r.profiles[t]){let e=Object.keys(r.profiles).join(", ");throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
3
+ \u5229\u7528\u53EF\u80FD\u306A\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB: ${e}`)}r.activeProfile=t,await this.writeAppConfig(r);}async addProfile(t,r){if(R(t),r?.provider&&!this.isTranslatorProvider(r.provider)){let p=Object.keys(j).join(", ");throw new Error(`\u7121\u52B9\u306A\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC '${r.provider}': ${p} \u306E\u3044\u305A\u308C\u304B\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044`)}let e=await this.readAppConfig();if(e.profiles[t])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059`);let i=r?.provider||b,n={...this.getDefaultProfileByProvider(i),...r};e.profiles[t]=n,await this.writeAppConfig(e);}async renameProfile(t,r){if(t==="default")throw new Error("'default' \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306F\u540D\u524D\u3092\u5909\u66F4\u3067\u304D\u307E\u305B\u3093");if(t===r)return;R(r);let e=await this.readAppConfig();if(!e.profiles[t])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`);if(e.profiles[r])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${r}' \u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059`);e.profiles[r]=e.profiles[t],delete e.profiles[t],e.activeProfile===t&&(e.activeProfile=r),await this.writeAppConfig(e);}async copyProfile(t,r){if(t===r)throw new Error("\u30B3\u30D4\u30FC\u5143\u3068\u30B3\u30D4\u30FC\u5148\u306E\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u304C\u540C\u3058\u3067\u3059");R(r);let e=await this.readAppConfig();if(!e.profiles[t])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`);if(e.profiles[r])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${r}' \u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059`);e.profiles[r]={...e.profiles[t]},await this.writeAppConfig(e);}async deleteProfile(t){if(t==="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[t])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`);delete r.profiles[t],r.activeProfile===t&&(r.activeProfile="default"),await this.writeAppConfig(r);}async setProfileConfig(t,r,e){let i=await this.readAppConfig();if(!i.profiles[t])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\uFF0E'enja config add ${t}' \u3067\u4F5C\u6210\u3057\u3066\u304F\u3060\u3055\u3044`);let a=i.profiles[t];switch(r){case "endpoint":a.endpoint=e;break;case "api-key":a.apiKey=e;break;case "provider":if(!this.isTranslatorProvider(e)){let n=Object.keys(j).join(", ");throw new Error(`\u7121\u52B9\u306A\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC (${e}): ${n} \u306E\u3044\u305A\u308C\u304B\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044`)}a.provider=e;break;case "model":a.model=e;break;default:throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${r})`)}await this.writeAppConfig(i);}async unsetProfileConfig(t,r){let e=await this.readAppConfig();if(!e.profiles[t])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`);let i=e.profiles[t],a=i.provider||b,n=this.getDefaultProfileByProvider(a);switch(r){case "provider":i.provider=n.provider;break;case "endpoint":i.endpoint=n.endpoint;break;case "api-key":i.apiKey=n.apiKey;break;case "model":i.model=n.model;break;default:throw new Error(`\u7121\u52B9\u306A\u8A2D\u5B9A\u30AD\u30FC (${r})`)}await this.writeAppConfig(e);}async resetProfileConfig(t){let r=await this.readAppConfig();if(!r.profiles[t])throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${t}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`);let e=this.getDefaultProfile();r.profiles[t]={...e},await this.writeAppConfig(r);}static isAppConfig(t){return !(!t||typeof t!="object"||!("profiles"in t)||!("activeProfile"in t)||typeof t.activeProfile!="string"||typeof t.profiles!="object"||t.profiles===null)}getDefaultProfile(){return j[b]()}getDefaultProfileByProvider(t){return j[t]()}isTranslatorProvider(t){return t in j}async ensureConfigDir(){let t=T();await promises.mkdir(t,{recursive:true});}async readAppConfig(){try{let t=await promises.readFile(this.filePath,"utf-8"),r=JSON.parse(t);return o.isAppConfig(r)?r:(console.warn("\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u306E\u5F62\u5F0F\u304C\u4E0D\u6B63\u3067\u3059\uFF0E\u898F\u5B9A\u5024\u3092\u4F7F\u7528\u3057\u307E\u3059"),{...Z})}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"),{...Z}}}async writeAppConfig(t){try{await this.ensureConfigDir();let r=`${this.filePath}.${Date.now()}.tmp`,e=JSON.stringify(t,null,2);await promises.writeFile(r,e,"utf-8"),await promises.rename(r,this.filePath);}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 t=await this.readAppConfig();return t.profiles[t.activeProfile]||this.getDefaultProfile()}};function Q(o){o.command("config").usage("[profile|subcommand] [options]").description("\u8A2D\u5B9A\u3068\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u7BA1\u7406\u3059\u308B").allowExcessArguments(true).argument("[profile|subcommand]",`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u307E\u305F\u306F\u30B5\u30D6\u30B3\u30DE\u30F3\u30C9
26
4
 
27
5
  Profiles:
28
6
  <profile> \u6307\u5B9A\u3057\u305F\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u8A73\u7D30\u3092\u8868\u793A
@@ -52,28 +30,22 @@ Examples:
52
30
  $ enja config use work work \u3092\u30A2\u30AF\u30C6\u30A3\u30D6\u306B\u8A2D\u5B9A
53
31
  $ enja config add personal personal \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210
54
32
  $ enja config rm personal \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u524A\u9664
55
- $ enja "Hello" -p work work \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3067\u7FFB\u8A33`).action(jt);}async function jt(o,t,e){let r=new w,i=e?.opts()||{},n={...e?.parent?.opts()||{},...i};try{let l=e?.args??[],s=l.length,[,p,c]=l;if(o==="ls"||o==="list"){if(s>1)throw new Error(`\u5F15\u6570\u304C\u591A\u3059\u304E\u307E\u3059
56
-
57
- \u4F7F\u7528\u4F8B:
58
- enja config ls`);let f=await r.listProfiles(),g=await r.getActiveProfileName();console.log(d.bold("Profiles:"));for(let m of f){let v=m===g,h=await r.getProfile(m),k=v?d.green("*"):" ",y=h.model?` - ${h.model}`:"";console.log(` ${k} ${m} (${h.provider})${y}`);}return}if(o==="use"){if(!p)throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044
33
+ $ enja "Hello" -p work work \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3067\u7FFB\u8A33`).action(dt);}async function dt(o,t,r){let e=new h,i=r?.opts()||{},n={...r?.parent?.opts()||{},...i};try{let p=r?.args??[],s=p.length,[,l,c]=p;if(o==="ls"||o==="list"){if(s>1)throw new Error(`\u5F15\u6570\u304C\u591A\u3059\u304E\u307E\u3059
59
34
 
60
35
  \u4F7F\u7528\u4F8B:
61
- enja config use <profile>`);if(s>2)throw new Error(`\u5F15\u6570\u304C\u591A\u3059\u304E\u307E\u3059
36
+ enja config ls`);let f=await e.listProfiles(),d=await e.getActiveProfileName();console.log(g.bold("Profiles:"));for(let u of f){let v=u===d,w=await e.getProfile(u),k=v?g.green("*"):" ",y=w.model?` - ${w.model}`:"";console.log(` ${k} ${u} (${w.provider})${y}`);}return}if(o==="use"){if(!l){let f=await e.listProfiles(),d=await e.getActiveProfileName(),u=await F(f,d);await e.useProfile(u),console.log(`${g.green("\u2714")} \u30A2\u30AF\u30C6\u30A3\u30D6\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092 '${u}' \u306B\u8A2D\u5B9A\u3057\u307E\u3057\u305F`);return}if(s>2)throw new Error(`\u5F15\u6570\u304C\u591A\u3059\u304E\u307E\u3059
62
37
 
63
38
  \u4F7F\u7528\u4F8B:
64
- enja config use <profile>`);await r.useProfile(p),console.log(`${d.green("\u2714")} \u30A2\u30AF\u30C6\u30A3\u30D6\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092 '${p}' \u306B\u8A2D\u5B9A\u3057\u307E\u3057\u305F`);return}if(o==="rm"||o==="delete"){if(!p)throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044
39
+ enja config use <profile>`);await e.useProfile(l),console.log(`${g.green("\u2714")} \u30A2\u30AF\u30C6\u30A3\u30D6\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092 '${l}' \u306B\u8A2D\u5B9A\u3057\u307E\u3057\u305F`);return}if(o==="rm"||o==="delete"){if(!l){let f=await e.listProfiles(),d=await e.getActiveProfileName(),u=await F(f,d);if(!await K(u))return;await e.deleteProfile(u),console.log(`${g.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${u}' \u3092\u524A\u9664\u3057\u307E\u3057\u305F`);return}if(s>2)throw new Error(`\u5F15\u6570\u304C\u591A\u3059\u304E\u307E\u3059
65
40
 
66
41
  \u4F7F\u7528\u4F8B:
67
- enja config rm <profile>`);if(s>2)throw new Error(`\u5F15\u6570\u304C\u591A\u3059\u304E\u307E\u3059
68
-
69
- \u4F7F\u7528\u4F8B:
70
- enja config rm <profile>`);await r.deleteProfile(p),console.log(`${d.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${p}' \u3092\u524A\u9664\u3057\u307E\u3057\u305F`);return}if(o==="add"){if(!p)throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044
42
+ enja config rm <profile>`);if(!await K(l))return;await e.deleteProfile(l),console.log(`${g.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${l}' \u3092\u524A\u9664\u3057\u307E\u3057\u305F`);return}if(o==="add"){if(!l)throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044
71
43
 
72
44
  \u4F7F\u7528\u4F8B:
73
45
  enja config add <profile> [options]`);if(s>2)throw new Error(`\u5F15\u6570\u304C\u591A\u3059\u304E\u307E\u3059
74
46
 
75
47
  \u4F7F\u7528\u4F8B:
76
- enja config add <profile> [options]`);let f={};n?.provider&&(f.provider=n.provider),n?.endpoint&&(f.endpoint=n.endpoint),n?.apiKey&&(f.apiKey=n.apiKey),n?.model&&(f.model=n.model),await r.addProfile(p,f),console.log(`${d.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${p}' \u3092\u4F5C\u6210\u3057\u307E\u3057\u305F`);return}if(o==="rename"){if(!p)throw new Error(`\u5909\u66F4\u524D\u306E\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044
48
+ enja config add <profile> [options]`);let f={};n?.provider&&(f.provider=n.provider),n?.endpoint&&(f.endpoint=n.endpoint),n?.apiKey&&(f.apiKey=n.apiKey),n?.model&&(f.model=n.model),await e.addProfile(l,f),console.log(`${g.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${l}' \u3092\u4F5C\u6210\u3057\u307E\u3057\u305F`);return}if(o==="rename"){if(!l)throw new Error(`\u5909\u66F4\u524D\u306E\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044
77
49
 
78
50
  \u4F7F\u7528\u4F8B:
79
51
  enja config rename <oldProfile> <newProfile>`);if(!c)throw new Error(`\u65B0\u3057\u3044\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044
@@ -82,7 +54,7 @@ Examples:
82
54
  enja config rename <oldProfile> <newProfile>`);if(s>3)throw new Error(`\u5F15\u6570\u304C\u591A\u3059\u304E\u307E\u3059
83
55
 
84
56
  \u4F7F\u7528\u4F8B:
85
- enja config rename <oldProfile> <newProfile>`);await r.renameProfile(p,c),console.log(`${d.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${p}' \u3092 '${c}' \u306B\u5909\u66F4\u3057\u307E\u3057\u305F`);return}if(o==="copy"){if(!p)throw new Error(`\u30B3\u30D4\u30FC\u5143\u306E\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044
57
+ enja config rename <oldProfile> <newProfile>`);await e.renameProfile(l,c),console.log(`${g.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${l}' \u3092 '${c}' \u306B\u5909\u66F4\u3057\u307E\u3057\u305F`);return}if(o==="copy"){if(!l)throw new Error(`\u30B3\u30D4\u30FC\u5143\u306E\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044
86
58
 
87
59
  \u4F7F\u7528\u4F8B:
88
60
  enja config copy <sourceProfile> <targetProfile>`);if(!c)throw new Error(`\u30B3\u30D4\u30FC\u5148\u306E\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044
@@ -91,11 +63,11 @@ Examples:
91
63
  enja config copy <sourceProfile> <targetProfile>`);if(s>3)throw new Error(`\u5F15\u6570\u304C\u591A\u3059\u304E\u307E\u3059
92
64
 
93
65
  \u4F7F\u7528\u4F8B:
94
- enja config copy <sourceProfile> <targetProfile>`);await r.copyProfile(p,c),console.log(`${d.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${p}' \u3092 '${c}' \u306B\u30B3\u30D4\u30FC\u3057\u307E\u3057\u305F`);return}if(!o){if(n?.provider||n?.endpoint||n?.apiKey||n?.model||n?.reset||n?.unset)throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044
66
+ enja config copy <sourceProfile> <targetProfile>`);await e.copyProfile(l,c),console.log(`${g.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${l}' \u3092 '${c}' \u306B\u30B3\u30D4\u30FC\u3057\u307E\u3057\u305F`);return}if(!o){if(n?.provider||n?.endpoint||n?.apiKey||n?.model||n?.reset||n?.unset)throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044
95
67
 
96
68
  \u4F7F\u7528\u4F8B:
97
69
  enja config work --provider openai \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u8A2D\u5B9A\u3092\u5909\u66F4
98
- enja config add personal --provider gemini \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210`);let f=await r.getActiveProfileName(),g=await r.get();console.log(`${d.bold("Active Profile:")} ${f}`),console.log(`${d.blue("provider:")} ${g.provider}`),console.log(`${d.blue("endpoint:")} ${g.endpoint||"(not set)"}`),console.log(`${d.blue("apiKey:")} ${g.apiKey?ot(g.apiKey):"(not set)"}`),console.log(`${d.blue("model:")} ${g.model||"(not set)"}`);return}if(o&&!p&&(n?.provider||n?.endpoint||n?.apiKey||n?.model)){let f=!1;n.provider&&(await r.setProfileConfig(o,"provider",n.provider),f=!0),n.endpoint&&(await r.setProfileConfig(o,"endpoint",n.endpoint),f=!0),n.apiKey&&(await r.setProfileConfig(o,"api-key",n.apiKey),f=!0),n.model&&(await r.setProfileConfig(o,"model",n.model),f=!0),f&&console.log(`${d.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${o}' \u306E\u8A2D\u5B9A\u3092\u66F4\u65B0\u3057\u307E\u3057\u305F`);return}if(o&&!p&&!n?.reset&&!n?.unset&&!n?.provider&&!n?.endpoint&&!n?.apiKey&&!n?.model){let f=await r.getProfile(o);console.log(`${d.bold("Profile:")} ${o}`),console.log(`${d.blue("provider:")} ${f.provider}`),console.log(`${d.blue("endpoint:")} ${f.endpoint||"(not set)"}`),console.log(`${d.blue("apiKey:")} ${f.apiKey?ot(f.apiKey):"(not set)"}`),console.log(`${d.blue("model:")} ${f.model||"(not set)"}`);return}if(o&&n?.reset){await r.resetProfileConfig(o),console.log(`${d.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${o}' \u3092\u30EA\u30BB\u30C3\u30C8\u3057\u307E\u3057\u305F`);return}if(o&&n?.unset){await r.unsetProfileConfig(o,n.unset),console.log(`${d.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${o}' \u306E ${n.unset} \u3092\u30EA\u30BB\u30C3\u30C8\u3057\u307E\u3057\u305F`);return}throw new Error(`\u7121\u52B9\u306A\u30B3\u30DE\u30F3\u30C9\u5F62\u5F0F\u3067\u3059\uFF0E
70
+ enja config add personal --provider gemini \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210`);let f=await e.getActiveProfileName(),d=await e.get();console.log(`${g.bold("Active Profile:")} ${f}`),console.log(`${g.blue("provider:")} ${d.provider}`),console.log(`${g.blue("endpoint:")} ${d.endpoint||"(not set)"}`),console.log(`${g.blue("apiKey:")} ${d.apiKey?q(d.apiKey):"(not set)"}`),console.log(`${g.blue("model:")} ${d.model||"(not set)"}`);return}if(o&&!l&&(n?.provider||n?.endpoint||n?.apiKey||n?.model)){let f=!1;n.provider&&(await e.setProfileConfig(o,"provider",n.provider),f=!0),n.endpoint&&(await e.setProfileConfig(o,"endpoint",n.endpoint),f=!0),n.apiKey&&(await e.setProfileConfig(o,"api-key",n.apiKey),f=!0),n.model&&(await e.setProfileConfig(o,"model",n.model),f=!0),f&&console.log(`${g.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${o}' \u306E\u8A2D\u5B9A\u3092\u66F4\u65B0\u3057\u307E\u3057\u305F`);return}if(o&&!l&&!n?.reset&&!n?.unset&&!n?.provider&&!n?.endpoint&&!n?.apiKey&&!n?.model){let f=await e.getProfile(o);console.log(`${g.bold("Profile:")} ${o}`),console.log(`${g.blue("provider:")} ${f.provider}`),console.log(`${g.blue("endpoint:")} ${f.endpoint||"(not set)"}`),console.log(`${g.blue("apiKey:")} ${f.apiKey?q(f.apiKey):"(not set)"}`),console.log(`${g.blue("model:")} ${f.model||"(not set)"}`);return}if(o&&n?.reset){await e.resetProfileConfig(o),console.log(`${g.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${o}' \u3092\u30EA\u30BB\u30C3\u30C8\u3057\u307E\u3057\u305F`);return}if(o&&n?.unset){await e.unsetProfileConfig(o,n.unset),console.log(`${g.green("\u2714")} \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${o}' \u306E ${n.unset} \u3092\u30EA\u30BB\u30C3\u30C8\u3057\u307E\u3057\u305F`);return}throw new Error(`\u7121\u52B9\u306A\u30B3\u30DE\u30F3\u30C9\u5F62\u5F0F\u3067\u3059\uFF0E
99
71
 
100
72
  \u4F7F\u7528\u4F8B:
101
73
  enja config \u73FE\u5728\u306E\u8A2D\u5B9A\u3092\u8868\u793A
@@ -109,5 +81,27 @@ Examples:
109
81
  enja config rm profileName \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u524A\u9664
110
82
  enja config work --reset \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u30EA\u30BB\u30C3\u30C8
111
83
  enja config work --unset api-key \u8A2D\u5B9A\u30EA\u30BB\u30C3\u30C8
112
- `)}catch(l){l instanceof Error?console.error(`error: ${l.message}`):console.error(l),process.exit(1);}}function ot(o){if(o.length<=8)return "*".repeat(o.length);let t=4,e=o.slice(0,t),r=o.slice(-t),i="*".repeat(o.length-t*2);return `${e}${i}${r}`}var B=JSON.parse(readFileSync(new URL("../package.json",import.meta.url),"utf-8")),H=new Command;H.name("enja").usage("[arguments] [options]").description(B.description).version(B.version,"-v, --version","output the current version").addHelpText("afterAll",`
113
- Enja CLI v${B.version}`).addHelpText("afterAll","Copyright (c) 2025-2026 yhotta240").addHelpText("afterAll","GitHub: https://github.com/yhotamos/enja-cli");Q(H);rt(H);nt(H);H.parse();
84
+ `)}catch(p){p instanceof Error?console.error(`error: ${p.message}`):console.error(p),process.exit(1);}}function q(o){if(o.length<=8)return "*".repeat(o.length);let t=4,r=o.slice(0,t),e=o.slice(-t),i="*".repeat(o.length-t*2);return `${r}${i}${e}`}function S(o,t=false){return o.length===0?"\u5C65\u6B74\u306F\u3042\u308A\u307E\u305B\u3093":t?mt(o):ut(o)}function ut(o){let t=[`\u5168 ${o.length} \u4EF6\u306E\u5C65\u6B74
85
+ `];return o.forEach((r,e)=>{let i=rt(r.timestamp),a=ht(r),n=tt(r.sourceText,20),p=tt(r.translatedText||"",20),s=[g.cyan(`[${e+1}]`),r.id.substring(0,8),i,a||null].filter(Boolean).join(" | ");t.push(s),t.push(` ${r.sourceLang} \u2192 ${r.targetLang} | ${n} \u2192 ${p}`),t.push("");}),t.join(`
86
+ `)}function mt(o){let t=[`\u5168 ${o.length} \u4EF6\u306E\u5C65\u6B74\u306E\u8A73\u7D30
87
+ `];return o.forEach((r,e)=>{e>0&&t.push("\u2500".repeat(60));let i=14;if(t.push(`${g.cyan("ID:".padEnd(i))} ${r.id}`),t.push(`${g.cyan("Date:".padEnd(i))} ${rt(r.timestamp)}`),t.push(`${g.cyan("Direction:".padEnd(i))} ${r.sourceLang} \u2192 ${r.targetLang}`),t.push(`${g.cyan("InputLength:".padEnd(i))} ${r.textLength} characters`),t.push(`${g.cyan("OutputLength:".padEnd(i))} ${r.translatedText.length} characters`),r.profile&&t.push(`${g.cyan("Profile:".padEnd(i))} ${r.profile}`),r.provider&&t.push(`${g.cyan("Provider:".padEnd(i))} ${r.provider}`),r.model&&t.push(`${g.cyan("Model:".padEnd(i))} ${r.model}`),r.options){let a=[r.options.inputMethod&&`input=${r.options.inputMethod}`,r.options.stripHtml&&"stripHtml=true",r.options.file&&`file=${r.options.file}`].filter(Boolean).join(", ");a&&t.push(`${g.cyan("Options:".padEnd(i))} ${a}`);}t.push("",`${g.cyan("Input:")}`,r.sourceText),t.push("",`${g.cyan("Output:")}`,r.translatedText||"","");}),t.join(`
88
+ `)}function rt(o){return new Date(o).toLocaleString("ja-JP")}function tt(o,t){let r=o.replace(/[\r\n]+/g," ");return r.length>t?`${r.substring(0,t)}...`:r}function ht(o){return [o.profile,o.provider,o.model].filter(t=>!!t).map(t=>g.magenta(t)).join(g.dim("\u30FB"))}var et=100,I=class{filePath;constructor(){this.filePath=Y();}ensureConfigDir(){let t=T();E.existsSync(t)||E.mkdirSync(t,{recursive:true});}async readHistory(){try{let t=await promises.readFile(this.filePath,"utf-8");return JSON.parse(t)}catch(t){return t instanceof Error&&"code"in 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`,e=JSON.stringify(t,null,2);await promises.writeFile(r,e,"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(),e={...t,id:randomUUID(),timestamp:new Date().toISOString()};r.unshift(e),r.length>et&&r.splice(et),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(),e=r.filter(i=>i.id!==t);return e.length===r.length?false:(await this.writeHistory(e),true)}async clear(){await this.writeHistory([]);}async findById(t){return (await this.readHistory()).find(e=>e.id===t)||null}async findByShortId(t){return (await this.readHistory()).filter(e=>e.id.startsWith(t))}async findByHash(t,r,e){return (await this.readHistory()).find(a=>a.sourceHash===t&&a.sourceLang===r&&a.targetLang===e)||null}};function ot(o){o.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","10").option("--delete <id>","\u7279\u5B9A\u306E\u5C65\u6B74\u3092\u524A\u9664\u3059\u308B").option("--clear","\u5C65\u6B74\u3092\u30AF\u30EA\u30A2").action(yt);}async function yt(o,t){try{let r=new I;if(o){let n=o.trim();if(!n)throw new Error("\u7A7A\u306EID\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F");if(n.length>=36){let l=await r.findById(n);if(!l)throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${o})`);console.log(S([l],t.detail));return}if(n.length<8)throw new Error(`\u77ED\u7E2EID\u306F\u5C11\u306A\u304F\u3068\u30828\u6587\u5B57\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044 (${n.length})`);let p=await r.findByShortId(n);if(p.length===0)throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${o})`);let s=S(p,t.detail);console.log(s);return}if(t.delete){let n=t.delete.trim();if(!n)throw new Error("\u7A7A\u306EID\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F");if(n.length>=36){if(await r.deleteById(n))console.log(`${g.green("\u2714")} \u5C65\u6B74ID ${n} \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 (${n})`);return}if(n.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 (${n.length})`);let p=await r.findByShortId(n);if(p.length===0)throw new Error(`\u6307\u5B9A\u3055\u308C\u305FID\u306E\u5C65\u6B74\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${n})`);if(p.length>1)throw new 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
89
+ ${S(p,!1)}`);let s=p[0].id;if(await r.deleteById(s))console.log(`${g.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(t.clear){await r.clear(),console.log(`${g.green("\u2714")} \u5C65\u6B74\u3092\u30AF\u30EA\u30A2\u3057\u307E\u3057\u305F`);return}let e=Number(t.number)||10,i=await r.getRecent(e),a=S(i,t.detail);console.log(a);}catch(r){console.error(r instanceof Error?`error: ${r.message}`:r),process.exit(1);}}async function nt(o){let t=new h,r;if(o?.profile)try{r=await t.getProfile(o.profile);}catch{let p=await t.listProfiles();throw new Error(`\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB '${o.profile}' \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
90
+ \u5229\u7528\u53EF\u80FD\u306A\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB: ${p.join(", ")}`)}else r=await t.get();let e=o?.provider||r.provider||"gas",i=o?.endpoint||r.endpoint,a=o?.apiKey||r.apiKey,n=o?.model||r.model;return {endpoint:i,provider:e,apiKey:a,model:n}}var Pt=new Set(["169.254.169.254"]);function Et(o){let t=o.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);if(!t)return null;let r=t.slice(1).map(e=>Number(e));return r.some(e=>!Number.isInteger(e)||e<0||e>255)?null:r}function vt(o,t,r){return o[0]===t&&o[1]===r}function $t(o){let[t,r]=o;return t===10||t===192&&r===168||t===172&&r>=16&&r<=31}function Tt(o){return o[0]===127}function Ct(o){return vt(o,169,254)}function xt(o){return o==="::1"||o==="0:0:0:0:0:0:0:1"}function At(o){return o.toLowerCase().startsWith("fe80:")}var Lt=new Set(["localhost","127.0.0.1","::1"]),jt=new Set(["10.","192.168."]);function D(o,t={}){let{allowLocalEndpoint:r=false,allowPrivateEndpoint:e=false,allowHttp:i=false}=t,a;try{a=new URL(o);}catch{throw new Error("\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8 URL \u304C\u4E0D\u6B63\u3067\u3059")}let n=a.protocol;if(n!=="https:"&&n!=="http:")throw new Error("\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8 URL \u306F http:// \u307E\u305F\u306F https:// \u3067\u59CB\u307E\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059");if(a.username||a.password)throw new Error("\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8 URL \u306B\u8A8D\u8A3C\u60C5\u5831\u3092\u57CB\u3081\u8FBC\u3080\u3053\u3068\u306F\u8A31\u53EF\u3055\u308C\u3066\u3044\u307E\u305B\u3093");let p=a.hostname;if(Pt.has(p))throw new Error("\u6307\u5B9A\u3055\u308C\u305F\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u4E0A\u306E\u7406\u7531\u306B\u3088\u308A\u8A31\u53EF\u3055\u308C\u3066\u3044\u307E\u305B\u3093");let s=Et(p),l=s!==null,c=Lt.has(p)||(l?Tt(s):false)||xt(p);if((l?Ct(s):false)||At(p))throw new Error("\u6307\u5B9A\u3055\u308C\u305F\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306F\u30EA\u30F3\u30AF\u30ED\u30FC\u30AB\u30EB\u30A2\u30C9\u30EC\u30B9\u306E\u305F\u3081\u8A31\u53EF\u3055\u308C\u3066\u3044\u307E\u305B\u3093");let d=l?$t(s):Array.from(jt).some(u=>p.startsWith(u));if(n==="http:"&&!(i||r&&c))throw new Error(`\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8 URL \u306F https:// \u3067\u59CB\u307E\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
91
+ HTTP \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u4F7F\u7528\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B\u5834\u5408\u306F\uFF0C--allow-http \u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044
92
+ \u30ED\u30FC\u30AB\u30EB\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3067\u3042\u308C\u3070 --allow-local-endpoint \u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u3082\u8A31\u53EF\u3055\u308C\u307E\u3059`);if(c&&!r)throw new Error(`\u30ED\u30FC\u30AB\u30EB\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306E\u4F7F\u7528\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30EA\u30B9\u30AF\u304C\u3042\u308B\u305F\u3081\u8A31\u53EF\u3055\u308C\u3066\u3044\u307E\u305B\u3093
93
+ \u30ED\u30FC\u30AB\u30EB\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u4F7F\u7528\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B\u5834\u5408\u306F\uFF0C--allow-local-endpoint \u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044`);if(d&&!e)throw new Error(`\u30D7\u30E9\u30A4\u30D9\u30FC\u30C8 IP \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306E\u4F7F\u7528\u306F\u65E2\u5B9A\u3067\u8A31\u53EF\u3055\u308C\u3066\u3044\u307E\u305B\u3093
94
+ \u4F7F\u7528\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B\u5834\u5408\u306F\uFF0C--allow-private-endpoint \u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044`);return true}async function it(o){let t=new h,r=await nt(o),e;o?.profile?e=o.profile:e=await t.getActiveProfileName();let i=o?.allowLocalEndpoint??false,a=o?.allowPrivateEndpoint??false,n=o?.allowHttp??false,p={allowLocalEndpoint:i,allowPrivateEndpoint:a,allowHttp:n};switch(r.provider){case "custom":{let{endpoint:s,apiKey:l,model:c}=r;if(!s)throw new Error("\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8 URL \u304C\u5FC5\u8981\u3067\u3059");return D(s,p),{translator:new C(s,l,c),config:r,activeProfile:e}}case "gas":{let{endpoint:s,apiKey:l}=r;if(!s)throw new Error("\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8 URL \u304C\u5FC5\u8981\u3067\u3059");return D(s,p),{translator:new x(s,l),config:r,activeProfile:e}}case "openai":{let{apiKey:s,model:l}=r;if(!s)throw new Error("OpenAI \u3092\u4F7F\u7528\u3059\u308B\u306B\u306F API \u30AD\u30FC\u304C\u5FC5\u8981\u3067\u3059");return {translator:new L(s,l),config:r,activeProfile:e}}case "gemini":{let{apiKey:s,model:l}=r;if(!s)throw new Error("Gemini \u3092\u4F7F\u7528\u3059\u308B\u306B\u306F API \u30AD\u30FC\u304C\u5FC5\u8981\u3067\u3059");return {translator:new A(s,l),config:r,activeProfile:e}}case "lmstudio":{let{endpoint:s}=r;if(o?.endpoint?(D(o.endpoint,p),s=o.endpoint):s?D(s,p):(s=P.DEFAULT_ENDPOINT,D(s,{allowLocalEndpoint:true,allowPrivateEndpoint:true,allowHttp:true})),!r.model)throw new Error("LM Studio \u3092\u4F7F\u7528\u3059\u308B\u306B\u306F\u30E2\u30C7\u30EB\u540D\u304C\u5FC5\u8981\u3067\u3059");return {translator:new P(s,r.model,r.apiKey),config:r,activeProfile:e}}default:throw new Error(`\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC (${r.provider})`)}}function st(o){return createHash("sha256").update(o).digest("hex")}function at(o){o.argument("[text]","\u7FFB\u8A33\u3059\u308B\u30C6\u30AD\u30B9\u30C8\uFF08\u7701\u7565\u3057\u305F\u5834\u5408\u306F\u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306F\u6A19\u6E96\u5165\u529B\u304B\u3089\u8AAD\u307F\u8FBC\u3080\uFF09").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>","\u4E00\u6642\u7684\u306B\u30AB\u30B9\u30BF\u30E0\u7FFB\u8A33\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u6307\u5B9A\uFF08\u73FE\u5728\u306E\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306B\u9069\u7528\uFF09").option("--api-key <key>","\u4E00\u6642\u7684\u306B API \u30AD\u30FC\u3092\u6307\u5B9A\uFF08\u73FE\u5728\u306E\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306B\u9069\u7528\uFF09").option("--provider <name>","\u4E00\u6642\u7684\u306B\u7FFB\u8A33\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC\u3092\u6307\u5B9A (\u4F8B: gas, openai, gemini, lmstudio; \u73FE\u5728\u306E\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306B\u9069\u7528)").option("--model <name>","\u4E00\u6642\u7684\u306B\u4F7F\u7528\u3059\u308B\u30E2\u30C7\u30EB\u540D\u3092\u6307\u5B9A (\u4F8B: gpt-4o-mini, gemini-2.5-flash-lite; \u73FE\u5728\u306E\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306B\u9069\u7528)").option("--allow-local-endpoint","localhost\uFF08127.0.0.1\uFF09\u306E\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u8A31\u53EF\u3059\u308B").option("--allow-private-endpoint","\u30D7\u30E9\u30A4\u30D9\u30FC\u30C8\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\uFF08\u4F8B: 192.168.x.x\uFF09\u306E\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u8A31\u53EF\u3059\u308B").option("--allow-http","HTTP\uFF08\u975E TLS\uFF09\u306E\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u8A31\u53EF\u3059\u308B").addHelpText("after",`
95
+ Examples:
96
+ $ enja "Hello, world!" # \u6587\u5B57\u5217\u3092\u7FFB\u8A33
97
+ $ docker --help | enja # \u6A19\u6E96\u5165\u529B\u3092\u7FFB\u8A33
98
+ $ enja -f input.txt -o output.txt # \u30D5\u30A1\u30A4\u30EB\u5165\u51FA\u529B
99
+ $ enja "Hello" -p work # \u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A\u3057\u3066\u7FFB\u8A33
100
+ $ enja "Hello" --provider openai --api-key YOUR_API_KEY # \u4E00\u6642\u7684\u306B\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC\u3092\u6307\u5B9A\u3057\u3066\u7FFB\u8A33`).action(St);}async function St(o,t){try{if(!o&&!t.file&&!process.stdin.isTTY){let r=await kt();await G(r,t,"stdin");return}if(t.file){if(!E.existsSync(t.file))throw new Error(`\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 (${t.file})`);let r=E.readFileSync(t.file,"utf-8");await G(r,t,"file");return}if(o){await G(o,t,"arg");return}throw new Error(`\u7FFB\u8A33\u3059\u308B\u30C6\u30AD\u30B9\u30C8\u304C\u63D0\u4F9B\u3055\u308C\u3066\u3044\u307E\u305B\u3093
101
+
102
+ \u4F7F\u7528\u4F8B:
103
+ enja "Hello, world!" # \u5F15\u6570\u3067\u6E21\u3055\u308C\u305F\u6587\u5B57\u5217\u3092\u7FFB\u8A33
104
+ enja -f input.txt # \u30D5\u30A1\u30A4\u30EB\u304B\u3089\u30C6\u30AD\u30B9\u30C8\u3092\u8AAD\u307F\u8FBC\u3093\u3067\u7FFB\u8A33
105
+ cat README.md | enja # \u30D1\u30A4\u30D7(\u6A19\u6E96\u5165\u529B)\u3067\u6E21\u3055\u308C\u305F\u30C6\u30AD\u30B9\u30C8\u3092\u7FFB\u8A33`)}catch(r){console.error(`error: ${Ht(r)}`),process.exit(1);}}async function G(o,t,r){if(!o||o.trim().length===0)throw new Error("\u7FFB\u8A33\u3059\u308B\u30C6\u30AD\u30B9\u30C8\u304C\u7A7A\u3067\u3059");let e=o;if(t.stripHtml&&(e=Rt(o),!e||e.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{translator:i,config:a,activeProfile:n}=await it(t),p=new I,s=t.flip?"ja":"en",l=t.flip?"en":"ja",c=st(e),f=await p.findByHash(c,s,l);if(f&&t.cache!==false){console.log(`${g.green("\u2714")} \u30AD\u30E3\u30C3\u30B7\u30E5\u304B\u3089\u7FFB\u8A33\u7D50\u679C\u3092\u53D6\u5F97\u3057\u307E\u3057\u305F`);let y=f.translatedText;if(t.output)try{E.writeFileSync(t.output,y,"utf-8"),console.log(`${g.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(y);return}let d=`(${s} \u2192 ${l})`,u=i.getModel()||a.model,v=n||"unknown",w=`[${v} | ${a.provider}${u?` | ${u}`:""}]`,k=Dt(`\u7FFB\u8A33\u4E2D... ${d} ${w}`).start();try{let U=(await i.translate(e,s,l)).text;if(k.succeed(`\u7FFB\u8A33\u5B8C\u4E86 ${d} ${w}`),await p.add({sourceText:e,translatedText:U,sourceLang:s,targetLang:l,textLength:e.length,sourceHash:c,profile:v,provider:a.provider,model:u,options:{stripHtml:t.stripHtml,file:t.file,inputMethod:r}}),t.output)try{E.writeFileSync(t.output,U,"utf-8"),console.log(`${g.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(U);}catch(y){throw k.fail(`\u7FFB\u8A33\u5931\u6557 ${d} ${w}`),y}}function Ht(o){if(o instanceof Error)return o.message;try{return String(o)}catch{return "Unknown error"}}function kt(){return new Promise((o,t)=>{let r="";process.stdin.setEncoding("utf-8"),process.stdin.on("data",e=>{r+=e;}),process.stdin.on("end",()=>{o(r);}),process.stdin.on("error",e=>{t(e);});})}function Rt(o){return o.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,`
106
+ `).trim()}var V=JSON.parse(readFileSync(new URL("../package.json",import.meta.url),"utf-8")),H=new Command;H.name("enja").usage("[arguments] [options]").description(V.description).version(V.version,"-v, --version","output the current version").addHelpText("afterAll",`
107
+ Enja CLI v${V.version}`).addHelpText("afterAll","Copyright (c) 2025-2026 yhotta240").addHelpText("afterAll","GitHub: https://github.com/yhotamos/enja-cli");at(H);ot(H);Q(H);H.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yhotamos/enja-cli",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
4
4
  "description": "英語を日本語に翻訳するシンプルなコマンドラインツール",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -11,10 +11,10 @@
11
11
  "enja": "dist/index.js"
12
12
  },
13
13
  "scripts": {
14
- "lint": "eslint src",
15
- "lint:fix": "eslint src --fix",
14
+ "check": "biome check src",
15
+ "check:fix": "biome check --write --unsafe src",
16
16
  "typecheck": "tsc --noEmit",
17
- "build": "npm run lint && npm run typecheck && tsup",
17
+ "build": "npm run check && npm run typecheck && tsup",
18
18
  "build:dev": "tsup --sourcemap",
19
19
  "watch": "tsup --watch",
20
20
  "test": "vitest"
@@ -44,19 +44,19 @@
44
44
  "homepage": "https://github.com/yhotamos/enja-cli#readme",
45
45
  "dependencies": {
46
46
  "@google/genai": "^1.33.0",
47
+ "@inquirer/prompts": "^8.3.2",
47
48
  "commander": "^14.0.2",
48
49
  "kleur": "^4.1.5",
49
50
  "openai": "^6.9.1",
50
51
  "ora": "^9.0.0"
51
52
  },
52
53
  "devDependencies": {
54
+ "@biomejs/biome": "^2.4.10",
53
55
  "@types/node": "^24.10.1",
54
56
  "dotenv": "^17.3.1",
55
- "eslint": "^10.0.2",
56
57
  "tsup": "^8.5.1",
57
58
  "tsx": "^4.20.6",
58
59
  "typescript": "^5.9.3",
59
- "typescript-eslint": "^8.56.1",
60
60
  "vitest": "^4.0.18"
61
61
  }
62
62
  }