@flyle/ai-contact-center-mcp 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/main.js +224 -47
- package/manifest.json.br +0 -0
- package/package.json +1 -1
package/main.js
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{homedir as e,hostname as t,userInfo as n}from"node:os";import{serveStdio as r}from"@modelcontextprotocol/server/stdio";import{createHash as i,randomBytes as a,timingSafeEqual as o}from"node:crypto";import{chmod as s,link as c,mkdir as l,open as u,readFile as d,realpath as f,rename as p,rm as m,unlink as
|
|
3
|
-
function
|
|
4
|
-
function
|
|
5
|
-
function
|
|
6
|
-
function
|
|
7
|
-
function
|
|
8
|
-
function
|
|
9
|
-
function
|
|
10
|
-
function
|
|
11
|
-
function
|
|
12
|
-
function
|
|
13
|
-
function
|
|
14
|
-
function
|
|
15
|
-
function
|
|
16
|
-
function
|
|
17
|
-
function
|
|
18
|
-
function
|
|
19
|
-
function
|
|
20
|
-
function
|
|
21
|
-
function
|
|
22
|
-
function
|
|
23
|
-
function
|
|
24
|
-
function
|
|
2
|
+
import{homedir as e,hostname as t,userInfo as n}from"node:os";import{serveStdio as r}from"@modelcontextprotocol/server/stdio";import{createHash as i,randomBytes as a,timingSafeEqual as o}from"node:crypto";import{chmod as s,link as c,mkdir as l,open as u,readFile as d,realpath as f,rename as p,rm as m,unlink as h,writeFile as g}from"node:fs/promises";import*as _ from"node:path";import{spawn as v}from"node:child_process";import{createServer as ee}from"node:http";import{parseArgs as te}from"node:util";import{constants as ne,readFileSync as re}from"node:fs";import{brotliDecompressSync as ie}from"node:zlib";import{McpServer as ae,fromJsonSchema as y}from"@modelcontextprotocol/server";var oe=class extends Error{name=`ManifestLoadError`},b=class extends Error{name=`ApiError`;info;constructor(e){super(`${e.status} ${e.code??`http_error`}: ${e.message}`),this.info=e}},x=class extends Error{name=`TransportError`;kind;status;constructor(e,t,n=null){super(t),this.kind=e,this.status=n}},S=class extends Error{name=`TransferError`;kind;status;constructor(e,t,n=null){super(t),this.kind=e,this.status=n}},C=class extends Error{name=`LocalFileError`;kind;constructor(e,t){super(t),this.kind=e}},w=class extends Error{name=`InlineFileError`;kind;constructor(e,t){super(t),this.kind=e}},T=class extends Error{name=`InvalidArgumentsError`},se=class extends Error{name=`OperationFailedError`;payload;constructor(e,t){super(e),this.payload=t}},E=class extends Error{name=`WorkspaceBindingError`;kind;constructor(e,t){super(t),this.kind=e}},D=class extends Error{name=`AuthError`;kind;constructor(e,t){super(t),this.kind=e}};const O=()=>{},ce=e=>e.operations.filter(e=>!e.responseContainsSecret);function k(e,t){return Object.hasOwn(e,t)}const le=(e,t)=>k(e,t),ue=e=>{let t=[];for(let n in e)le(e,n)&&t.push(n);return t},de=e=>{let t=[];for(let n in e)if(le(e,n)){let r=Reflect.get(e,n);t.push([n,r])}return t},fe=e=>{let t={};for(let[n,r]of e)Object.defineProperty(t,n,{configurable:!0,enumerable:!0,value:r,writable:!0});return t},A=e=>typeof e==`object`&&!!e&&!Array.isArray(e),pe={lang:void 0,message:void 0,abortEarly:void 0,abortPipeEarly:void 0};/* @__NO_SIDE_EFFECTS__ */
|
|
3
|
+
function me(e){return e?{lang:e?.lang??void 0,message:e?.message,abortEarly:e?.abortEarly??void 0,abortPipeEarly:e?.abortPipeEarly??void 0}:pe}/* @__NO_SIDE_EFFECTS__ */
|
|
4
|
+
function he(e){let t=typeof e;return t===`string`?`"${e}"`:t===`number`||t===`bigint`||t===`boolean`?`${e}`:t===`object`||t===`function`?(e&&Object.getPrototypeOf(e)?.constructor?.name)??`null`:t}function j(e,t,n,r,i){let a=i&&`input`in i?i.input:n.value,o=i?.expected??e.expects??null,s=i?.received??/* @__PURE__ */ he(a),c={kind:e.kind,type:e.type,input:a,expected:o,received:s,message:`Invalid ${t}: ${o?`Expected ${o} but r`:`R`}eceived ${s}`,requirement:e.requirement,path:i?.path,issues:i?.issues,lang:r.lang,abortEarly:r.abortEarly,abortPipeEarly:r.abortPipeEarly},l=e.kind===`schema`,u=i?.message??e.message??(e.reference,c.lang,void 0)??(l?(c.lang,void 0):null)??r.message??(c.lang,void 0);u!==void 0&&(c.message=typeof u==`function`?u(c):u),l&&(n.typed=!1),n.issues?n.issues.push(c):n.issues=[c]}/* @__NO_SIDE_EFFECTS__ */
|
|
5
|
+
function ge(e,t){return e===t||Number.isNaN(e)&&Number.isNaN(t)}/* @__NO_SIDE_EFFECTS__ */
|
|
6
|
+
function _e(e,t){let n=[...new Set(e)];return n.length>1?`(${n.join(` ${t} `)})`:n[0]??`never`}function M(e){return e[`~standard`]={version:1,vendor:`valibot`,validate:t=>e[`~run`]({value:t},/* @__PURE__ */ me())},e}const ve=/^\d{4}-(?:0[1-9]|1[0-2])-(?:[12]\d|0[1-9]|3[01])[T ](?:0\d|1\d|2[0-3])(?::[0-5]\d){2}(?:\.\d{1,9})?(?:Z| ?[+-](?:0\d|1\d|2[0-3])(?::?[0-5]\d)?)$/u;/* @__NO_SIDE_EFFECTS__ */
|
|
7
|
+
function ye(e,t){return{kind:`validation`,type:`check`,reference:ye,async:!1,expects:null,requirement:e,message:t,"~run"(e,t){return e.typed&&!this.requirement(e.value)&&j(this,`input`,e,t),e}}}/* @__NO_SIDE_EFFECTS__ */
|
|
8
|
+
function be(e,t){let n=/* @__PURE__ */ he(e);return{kind:`validation`,type:`includes`,reference:be,async:!1,expects:n,requirement:e,message:t,"~run"(e,t){return e.typed&&!e.value.includes(this.requirement)&&j(this,`content`,e,t,{received:`!${n}`}),e}}}/* @__NO_SIDE_EFFECTS__ */
|
|
9
|
+
function xe(e){return{kind:`validation`,type:`iso_timestamp`,reference:xe,async:!1,expects:null,requirement:ve,message:e,"~run"(e,t){return e.typed&&!this.requirement.test(e.value)&&j(this,`timestamp`,e,t),e}}}/* @__NO_SIDE_EFFECTS__ */
|
|
10
|
+
function N(e,t){return{kind:`validation`,type:`regex`,reference:N,async:!1,expects:`${e}`,requirement:e,message:t,"~run"(e,t){return e.typed&&!this.requirement.test(e.value)&&j(this,`format`,e,t),e}}}/* @__NO_SIDE_EFFECTS__ */
|
|
11
|
+
function Se(e){return{kind:`validation`,type:`url`,reference:Se,async:!1,expects:null,requirement(e){try{return URL.canParse?URL.canParse(e):(new URL(e),!0)}catch{return!1}},message:e,"~run"(e,t){return e.typed&&!this.requirement(e.value)&&j(this,`URL`,e,t),e}}}/* @__NO_SIDE_EFFECTS__ */
|
|
12
|
+
function Ce(e,t,n){return typeof e.fallback==`function`?e.fallback(t,n):e.fallback}/* @__NO_SIDE_EFFECTS__ */
|
|
13
|
+
function we(e,t,n){return typeof e.default==`function`?e.default(t,n):e.default}/* @__NO_SIDE_EFFECTS__ */
|
|
14
|
+
function Te(e,t){return M({kind:`schema`,type:`array`,reference:Te,expects:`Array`,async:!1,item:e,message:t,"~run"(e,t){let n=e.value;if(Array.isArray(n)){e.typed=!0,e.value=[];for(let r=0;r<n.length;r++){let i=n[r],a=this.item[`~run`]({value:i},t);if(a.issues){let o={type:`array`,origin:`value`,input:n,key:r,value:i};for(let t of a.issues)t.path?t.path.unshift(o):t.path=[o],e.issues?.push(t);if(e.issues||=a.issues,t.abortEarly){e.typed=!1;break}}a.typed||(e.typed=!1),e.value.push(a.value)}}else j(this,`type`,e,t);return e}})}/* @__NO_SIDE_EFFECTS__ */
|
|
15
|
+
function Ee(e,t){return M({kind:`schema`,type:`literal`,reference:Ee,expects:/* @__PURE__ */ he(e),async:!1,literal:e,message:t,"~run"(e,t){return/* @__PURE__ */ ge(e.value,this.literal)?e.typed=!0:j(this,`type`,e,t),e}})}/* @__NO_SIDE_EFFECTS__ */
|
|
16
|
+
function De(e,t){return M({kind:`schema`,type:`nullable`,reference:De,expects:`(${e.expects} | null)`,async:!1,wrapped:e,default:t,"~run"(e,t){return e.value===null&&(this.default!==void 0&&(e.value=/* @__PURE__ */ we(this,e,t)),e.value===null)?(e.typed=!0,e):this.wrapped[`~run`](e,t)}})}/* @__NO_SIDE_EFFECTS__ */
|
|
17
|
+
function P(e,t){return M({kind:`schema`,type:`object`,reference:P,expects:`Object`,async:!1,entries:e,message:t,"~run"(e,t){let n=e.value;if(n&&typeof n==`object`){e.typed=!0,e.value={};for(let r in this.entries){let i=this.entries[r];if(r in n||(i.type===`exact_optional`||i.type===`optional`||i.type===`nullish`)&&i.default!==void 0){let a=r in n?n[r]:/* @__PURE__ */ we(i),o=i[`~run`]({value:a},t);if(o.issues){let i={type:`object`,origin:`value`,input:n,key:r,value:a};for(let t of o.issues)t.path?t.path.unshift(i):t.path=[i],e.issues?.push(t);if(e.issues||=o.issues,t.abortEarly){e.typed=!1;break}}o.typed||(e.typed=!1),e.value[r]=o.value}else if(i.fallback!==void 0)e.value[r]=/* @__PURE__ */ Ce(i);else if(i.type!==`exact_optional`&&i.type!==`optional`&&i.type!==`nullish`&&(j(this,`key`,e,t,{input:void 0,expected:`"${r}"`,path:[{type:`object`,origin:`key`,input:n,key:r,value:n[r]}]}),t.abortEarly))break}}else j(this,`type`,e,t);return e}})}/* @__NO_SIDE_EFFECTS__ */
|
|
18
|
+
function Oe(e,t){return M({kind:`schema`,type:`optional`,reference:Oe,expects:`(${e.expects} | undefined)`,async:!1,wrapped:e,default:t,"~run"(e,t){return e.value===void 0&&(this.default!==void 0&&(e.value=/* @__PURE__ */ we(this,e,t)),e.value===void 0)?(e.typed=!0,e):this.wrapped[`~run`](e,t)}})}/* @__NO_SIDE_EFFECTS__ */
|
|
19
|
+
function ke(e,t){return M({kind:`schema`,type:`strict_object`,reference:ke,expects:`Object`,async:!1,entries:e,message:t,"~run"(e,t){let n=e.value;if(n&&typeof n==`object`){e.typed=!0,e.value={};for(let r in this.entries){let i=this.entries[r];if(r in n||(i.type===`exact_optional`||i.type===`optional`||i.type===`nullish`)&&i.default!==void 0){let a=r in n?n[r]:/* @__PURE__ */ we(i),o=i[`~run`]({value:a},t);if(o.issues){let i={type:`object`,origin:`value`,input:n,key:r,value:a};for(let t of o.issues)t.path?t.path.unshift(i):t.path=[i],e.issues?.push(t);if(e.issues||=o.issues,t.abortEarly){e.typed=!1;break}}o.typed||(e.typed=!1),e.value[r]=o.value}else if(i.fallback!==void 0)e.value[r]=/* @__PURE__ */ Ce(i);else if(i.type!==`exact_optional`&&i.type!==`optional`&&i.type!==`nullish`&&(j(this,`key`,e,t,{input:void 0,expected:`"${r}"`,path:[{type:`object`,origin:`key`,input:n,key:r,value:n[r]}]}),t.abortEarly))break}if(!e.issues||!t.abortEarly){for(let r in n)if(!Object.prototype.hasOwnProperty.call(this.entries,r)){j(this,`key`,e,t,{input:r,expected:`never`,path:[{type:`object`,origin:`key`,input:n,key:r,value:n[r]}]});break}}}else j(this,`type`,e,t);return e}})}/* @__NO_SIDE_EFFECTS__ */
|
|
20
|
+
function F(e){return M({kind:`schema`,type:`string`,reference:F,expects:`string`,async:!1,message:e,"~run"(e,t){return typeof e.value==`string`?e.typed=!0:j(this,`type`,e,t),e}})}/* @__NO_SIDE_EFFECTS__ */
|
|
21
|
+
function Ae(e){let t;if(e)for(let n of e)if(t)for(let e of n.issues)t.push(e);else t=n.issues;return t}/* @__NO_SIDE_EFFECTS__ */
|
|
22
|
+
function je(e,t){return M({kind:`schema`,type:`union`,reference:je,expects:/* @__PURE__ */ _e(e.map(e=>e.expects),`|`),async:!1,options:e,message:t,"~run"(e,t){let n,r,i;for(let a of this.options){let o=a[`~run`]({value:e.value},t);if(o.typed){if(o.issues)r?r.push(o):r=[o];else{n=o;break}}else i?i.push(o):i=[o]}if(n)return n;if(r){if(r.length===1)return r[0];j(this,`type`,e,t,{issues:/* @__PURE__ */ Ae(r)}),e.typed=!0}else if(i?.length===1)return i[0];else j(this,`type`,e,t,{issues:/* @__PURE__ */ Ae(i)});return e}})}/* @__NO_SIDE_EFFECTS__ */
|
|
23
|
+
function I(...e){return M({...e[0],pipe:e,"~run"(t,n){for(let r of e)if(r.kind!==`metadata`){if(t.issues&&(r.kind===`schema`||r.kind===`transformation`)){t.typed=!1;break}(!t.issues||!n.abortEarly&&!n.abortPipeEarly)&&(t=r[`~run`](t,n))}return t}})}/* @__NO_SIDE_EFFECTS__ */
|
|
24
|
+
function Me(e,t,n){let r=e[`~run`]({value:t},/* @__PURE__ */ me(n));return{typed:r.typed,success:!r.issues,output:r.value,issues:r.issues}}const Ne=e=>{let t=e.length;for(;t>0&&e[t-1]===`/`;)--t;return e.slice(0,t)},Pe=`0.5.1`,Fe=/^flyle_ai_contact_center_ac_[0-9A-Za-z]{43}$/,Ie=/^flyle_ai_contact_center_ut_[0-9A-Za-z]{43}$/,Le=/^flyle_ai_contact_center_rt_[0-9A-Za-z]{43}$/,Re=/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/,ze=/^[a-z0-9](-?[a-z0-9])*$/,Be=6e5,Ve=536870912;var L=class extends Error{name=`ConfigError`};const He="ログインが必要です。作業ディレクトリで `npx @flyle/ai-contact-center-mcp@latest login` を実行してください";var Ue=class extends Error{name=`InvalidGrantError`},R=class extends Error{name=`CliError`};const We={allowInsecureHttp:`FLYLE_AI_CONTACT_CENTER_MCP_ALLOW_INSECURE_HTTP`},Ge=[`FLYLE_AI_CONTACT_CENTER_API_BASE_URL`,`FLYLE_AI_CONTACT_CENTER_TENANT_NAME`,`FLYLE_AI_CONTACT_CENTER_MCP_OUTPUT_DIR`,`FLYLE_AI_CONTACT_CENTER_MCP_FILE_ROOTS`,`FLYLE_AI_CONTACT_CENTER_MCP_STORAGE_HOSTS`],Ke=[`.amazonaws.com`],qe=/* @__PURE__ */ new Set([`localhost`,`127.0.0.1`,`[::1]`]),Je=e=>qe.has(e),Ye=(e,t,n)=>{let r;try{r=new URL(e)}catch{throw new L(`${n} is not a valid URL`)}if(r.search!==``||r.hash!==``||r.username!==``||r.password!==``)throw new L(`${n} must not contain query, hash, or credentials`);let i=r.protocol===`http:`&&t&&Je(r.hostname);if(r.protocol!==`https:`&&!i)throw new L(`${n} must use https (http is allowed only for localhost with ${We.allowInsecureHttp}=1)`);let a=Ne(r.pathname);return new URL(`${r.origin}${a}`)},Xe=e=>e===`1`||e===`true`,Ze=e=>e.length>=2&&e.length<=32&&ze.test(e),Qe=(e,t)=>{if(!Ze(e))throw new L(`${t} is not a valid tenant name`);return e},$e=e=>{if(e.FLYLE_AI_CONTACT_CENTER_API_KEY!=null)throw new L("API キー方式は廃止されました。`npx @flyle/ai-contact-center-mcp@latest login` でログインしてください");let t=Ge.filter(t=>e[t]!=null);if(t.length!==0)throw new L(`${t.join(`, `)} は廃止しました。MCP の設定から削除してください。接続先(環境とテナント)は作業ディレクトリで \`npx @flyle/ai-contact-center-mcp@latest login --tenant <テナント名>\` を実行すると決まり、保存先と読込元は作業ディレクトリです。`)},et=e=>Xe(e[We.allowInsecureHttp]),z=e=>e.host,tt=(e,t,n)=>{let r=et(e);return{baseUrl:Ye(n.apiBaseUrl,r,`作業ディレクトリの接続先`),tenantName:Qe(n.tenantName,`作業ディレクトリのテナント`),outputDir:_.resolve(t,`.flyle-ai-contact-center-mcp/downloads`),fileRoots:[t],storageHostSuffixes:r?[...Ke,`s3.flyle.local`]:Ke,allowInsecureHttp:r}},nt=`flyle-ai-contact-center-mcp`,rt=`credentials`,it=()=>a(8).toString(`hex`),at=/* @__PURE__ */ ke({version:/* @__PURE__ */ Ee(1),apiBaseUrl:/* @__PURE__ */ I(/* @__PURE__ */ F(),/* @__PURE__ */ Se()),tenantName:/* @__PURE__ */ I(/* @__PURE__ */ F(),/* @__PURE__ */ ye(Ze)),loginConnectionId:/* @__PURE__ */ I(/* @__PURE__ */ F(),/* @__PURE__ */ N(Re)),accessToken:/* @__PURE__ */ I(/* @__PURE__ */ F(),/* @__PURE__ */ N(Ie)),accessTokenExpiresAt:/* @__PURE__ */ I(/* @__PURE__ */ F(),/* @__PURE__ */ xe()),refreshToken:/* @__PURE__ */ I(/* @__PURE__ */ F(),/* @__PURE__ */ N(Le)),refreshTokenExpiresAt:/* @__PURE__ */ I(/* @__PURE__ */ F(),/* @__PURE__ */ xe())}),ot=({platform:e,env:t,homeDir:n})=>{let r=t.XDG_CONFIG_HOME;if(r!=null&&_.isAbsolute(r))return _.join(r,nt,rt);let i=t.APPDATA;return e===`win32`&&i!=null&&_.isAbsolute(i)?_.join(i,nt,rt):_.join(n,`.config`,nt,rt)},st=(e,t)=>_.join(e,`${t}.json`),ct=e=>e instanceof Error&&k(e,`code`)?e.code:null,lt=async e=>{let t;try{t=await d(e,`utf8`)}catch(e){if(ct(e)===`ENOENT`)return null;throw e}let n;try{n=JSON.parse(t)}catch{n=null}let r=/* @__PURE__ */ Me(at,n);if(!r.success)throw new D(`login_required`,`保存されたログイン情報(${e})を読めません。作業ディレクトリで \`npx @flyle/ai-contact-center-mcp@latest login\` を実行し直してください`);return r.output},ut=async e=>{await l(e,{recursive:!0,mode:448}),await s(e,448)},dt=async(e,t)=>{await ut(_.dirname(e));let n={version:1,...t},r=`${e}.${it()}.tmp`;try{let t=await u(r,`wx`,384);try{await t.writeFile(`${JSON.stringify(n,null,2)}\n`)}finally{await t.close()}await p(r,e)}catch(e){throw await m(r,{force:!0}).catch(O),e}},ft=async e=>{await m(e,{force:!0})},pt=(e,t)=>({staleMs:6e4,acquireTimeoutMs:9e4,retryIntervalMs:100,now:e,sleep:t}),mt=async e=>{let t;try{t=await u(e,`r`)}catch(e){if(ct(e)===`ENOENT`)return null;throw e}try{let[e,n]=await Promise.all([t.readFile(`utf8`),t.stat()]);return{owner:e,mtimeMs:n.mtimeMs}}finally{await t.close()}},ht=async(e,t)=>{let n=`${e}.${it()}.aside`;try{await p(e,n)}catch(e){if(ct(e)===`ENOENT`)return!1;throw e}return await d(n,`utf8`)===t?(await m(n,{force:!0}),!0):(await c(n,e).catch(e=>{if(ct(e)!==`EEXIST`)throw e}),await m(n,{force:!0}),!1)},gt=async(e,t)=>{let n=await mt(e);return n==null?!0:t.now()-n.mtimeMs<t.staleMs?!1:ht(e,n.owner)},_t=async(e,t)=>{let n=`${e}.${it()}.tmp`,r=await u(n,`wx`,384);try{await r.writeFile(t)}finally{await r.close()}try{return await c(n,e),!0}catch(e){if(ct(e)===`EEXIST`)return!1;throw e}finally{await m(n,{force:!0})}},vt=async(e,t,n)=>{await ut(_.dirname(e));let r=`${e}.lock`,i=it(),a=t.now()+t.acquireTimeoutMs;for(;!await _t(r,i);)if(!await gt(r,t)){if(t.now()>=a)throw Error(`ログイン情報のロック(${r})を取得できませんでした。別の MCP プロセスが更新中です。しばらくしてから再実行してください`);await t.sleep(t.retryIntervalMs)}try{return await n()}finally{await ht(r,i)}},B=e=>{if(e?.aborted)throw new x(`aborted`,`the API request was cancelled`)},yt=(e,t,n)=>(B(t),t==null?n(e):new Promise((r,i)=>{let a=()=>{i(new x(`aborted`,`the API request was cancelled`))};t.addEventListener(`abort`,a,{once:!0}),n(e).then(()=>{t.removeEventListener(`abort`,a),r()},e=>{t.removeEventListener(`abort`,a),i(e instanceof Error?e:Error(String(e)))})})),bt=/\r\n|\n|\r/,xt=()=>{let e=``,t=!1,n=``,r=[],i=null,a=()=>{if(r.length===0)return n=``,null;let e={event:n===``?`message`:n,data:r.join(`
|
|
25
25
|
`),id:i};return n=``,r=[],e},o=e=>{if(e===``)return a();if(e.startsWith(`:`))return null;let t=e.indexOf(`:`),o=t===-1?e:e.slice(0,t),s=t===-1?``:e.slice(t+1);return s.startsWith(` `)&&(s=s.slice(1)),o===`event`?n=s:o===`data`?r.push(s):o===`id`&&!s.includes(`\0`)&&(i=s),null};return{push:n=>{e+=n,t&&(t=!1,e.startsWith(`
|
|
26
26
|
`)&&(e=e.slice(1)));let r=[],i=e.search(bt);for(;i!==-1;){let n=e.slice(0,i);e[i]===`\r`&&i===e.length-1&&(t=!0);let a=e.startsWith(`\r
|
|
27
|
-
`,i)?2:1;e=e.slice(i+a);let s=o(n);s!=null&&r.push(s),i=e.search(bt)}return r},hasPendingIncomplete:()=>e!==``||r.length>0,flush:()=>(e=``,t=!1,n=``,r=[],[])}},St=async(e,t)=>{if(t<=0)return`deadline`;let n=null,r=new Promise(e=>{n=setTimeout(e,t,`deadline`)});try{return await Promise.race([e.read(),r])}finally{n!=null&&clearTimeout(n)}},Ct=async(e,t)=>{let n=e.getReader(),r=new TextDecoder(`utf-8`),i=xt(),a=[],o=0,s=async e=>(await n.cancel().catch(T),{events:a,truncated:!0,reason:e,discardedIncomplete:!1});for(;;){let e=await St(n,t.deadlineAt-t.now());if(e===`deadline`)return await s(`deadline`);if(e.done){a.push(...i.push(r.decode()));let e=i.hasPendingIncomplete();return i.flush(),{events:a,truncated:!1,reason:`end`,discardedIncomplete:e}}if(o+=e.value.byteLength,o>t.maxBytes)return await s(`max_bytes`);if(a.push(...i.push(r.decode(e.value,{stream:!0}))),a.length>t.maxEvents)return a.length=t.maxEvents,await s(`max_events`)}},wt=e=>{try{return JSON.parse(e)}catch{return e}},Tt=`application/json`,Et=`text/event-stream`,Dt=`x-request-id`,Ot={headersTimeoutMs:6e4,maxJsonBytes:16777216,sseTotalMs:9e5,sseMaxEvents:1e4,sseMaxBytes:33554432,maxRetryAfterSeconds:30},kt=(e,t)=>{if(e.origin!==t.origin)throw new v(`network`,`refusing to send credentials outside the configured API origin`)},At=(e,t)=>{let n=Pe(e.pathname),r=new URL(`${n}${t.path}`,e);for(let[e,n]of t.query)r.searchParams.append(e,n);return kt(r,e),r},jt=e=>{switch(e){case`json`:case`empty`:return Tt;case`sse`:return Et;case`binary`:return`*/*`;default:throw Error(`unknown response kind ${String(e)}`)}},Mt=async(e,t)=>{let n=Number(e.headers.get(`content-length`));if(Number.isFinite(n)&&n>t)throw await e.body?.cancel().catch(T),new v(`response_too_large`,`response exceeds ${t} bytes`,e.status);if(e.body==null)return/* @__PURE__ */ new Uint8Array;let r=e.body.getReader(),i=[],a=0;for(;;){let{done:n,value:o}=await r.read();if(n)break;if(a+=o.byteLength,a>t)throw await r.cancel().catch(T),new v(`response_too_large`,`response exceeds ${t} bytes`,e.status);i.push(o)}let o=new Uint8Array(a),s=0;for(let e of i)o.set(e,s),s+=e.byteLength;return o},Nt=e=>new TextDecoder(`utf-8`).decode(e),Pt=(e,t)=>(e.headers.get(`content-type`)??``).toLowerCase().startsWith(t),Ft=e=>{if(e==null)return null;let t=Number(e);return Number.isInteger(t)&&t>=0?t:null},It=(e,t)=>{let n=e[t];return typeof n==`string`?n:null},Lt=e=>typeof e==`object`&&!!e&&!Array.isArray(e),Rt=async(e,t)=>{let n=e.headers.get(Dt),r=Ft(e.headers.get(`retry-after`)),i;try{i=Nt(await Mt(e,t))}catch{i=``}if(Pt(e,Tt))try{let t=JSON.parse(i),a=Lt(t)&&Lt(t.error)?t.error:null;if(a!=null)return new _({status:e.status,code:It(a,`code`),message:It(a,`message`)??e.statusText,detail:It(a,`detail`),requestId:It(a,`requestId`)??n,retryAfterSeconds:r})}catch{}return new _({status:e.status,code:null,message:i.slice(0,500)||e.statusText||`HTTP error`,detail:null,requestId:n,retryAfterSeconds:r})},zt=e=>{if(e==null)return null;let t=/filename\*=UTF-8''([^;]+)/i.exec(e);if(t?.[1]!=null)try{return decodeURIComponent(t[1].trim())}catch{return null}return/filename="?([^";]+)"?/i.exec(e)?.[1]?.trim()??null},Bt=e=>e instanceof v?e:e instanceof Error&&e.name===`AbortError`?new v(`timeout`,`the API did not respond in time`):new v(`network`,e instanceof Error?e.message:`network failure`),Vt=(e,t=Ot)=>{let{config:n,auth:r,clientWorkspaceId:i,userAgent:a,fetch:o,now:s,sleep:c,logger:l}=e,u=async(e,r)=>{let c=At(n.baseUrl,e),l=new Headers({accept:jt(e.responseKind)});a!=null&&l.set(`user-agent`,a),i!=null&&l.set(`x-flyle-client-workspace`,i),r!=null&&l.set(`authorization`,`Bearer ${r}`);let u;e.hasBody&&(u=JSON.stringify(e.body??{}),l.set(`content-type`,Tt));let d=new AbortController,f=setTimeout(()=>d.abort(),t.headersTimeoutMs),p;try{p=await o(c,{method:e.method,headers:l,...u==null?{}:{body:u},redirect:`manual`,signal:d.signal})}catch(e){throw clearTimeout(f),Bt(e)}if(p.type===`opaqueredirect`||p.status>=300&&p.status<400)throw clearTimeout(f),await p.body?.cancel().catch(T),new v(`redirect_not_followed`,`redirect responses are not followed`,p.status);if(!p.ok)try{throw await Rt(p,t.maxJsonBytes)}finally{clearTimeout(f)}let m=p.headers.get(Dt);switch(e.responseKind){case`json`:try{if(!Pt(p,Tt))throw await p.body?.cancel().catch(T),new v(`unexpected_content_type`,`expected an application/json response`,p.status);let e=Nt(await Mt(p,t.maxJsonBytes)),n;try{n=JSON.parse(e)}catch{throw new v(`invalid_json`,`the response body is not valid JSON`,p.status)}return{kind:`json`,status:p.status,requestId:m,body:n}}catch(e){throw Bt(e)}finally{clearTimeout(f)}case`empty`:return clearTimeout(f),await p.body?.cancel().catch(T),{kind:`empty`,status:p.status,requestId:m};case`sse`:{if(clearTimeout(f),!Pt(p,Et))throw await p.body?.cancel().catch(T),new v(`unexpected_content_type`,`expected a text/event-stream response`,p.status);if(p.body==null)throw new v(`empty_body`,`the stream has no body`,p.status);let e=await Ct(p.body,{deadlineAt:s()+t.sseTotalMs,maxEvents:t.sseMaxEvents,maxBytes:t.sseMaxBytes,now:s});return{kind:`sse`,status:p.status,requestId:m,...e}}case`binary`:if(clearTimeout(f),p.body==null)throw new v(`empty_body`,`the download has no body`,p.status);return{kind:`binary`,status:p.status,requestId:m,contentType:p.headers.get(`content-type`),fileName:zt(p.headers.get(`content-disposition`)),body:p.body};default:throw e.responseKind,Error(`unknown response kind ${String(e.responseKind)}`)}},d=async(e,n)=>{let r=e.method===`GET`&&(e.responseKind===`json`||e.responseKind===`empty`);try{return await u(e,n)}catch(i){if(!r)throw i;if(i instanceof _&&i.info.status===429&&i.info.retryAfterSeconds!=null&&i.info.retryAfterSeconds<=t.maxRetryAfterSeconds)return l.warn(`rate limited; retrying once`,{path:e.path,retryAfterSeconds:i.info.retryAfterSeconds}),await c(i.info.retryAfterSeconds*1e3),await u(e,n);if(i instanceof v&&i.kind===`network`)return l.warn(`network failure; retrying once`,{path:e.path}),await u(e,n);throw i}};return{request:async e=>{if(r==null)return d(e,null);let t=await r.getAccessToken();try{return await d(e,t)}catch(n){if(!(n instanceof _)||n.info.status!==401)throw n;let i=await r.refreshAfterRejection(t);if(i===t)throw n;return l.warn(`access token rejected; retrying once with a refreshed token`,{path:e.path}),await d(e,i)}}}},Ht=`{tenantName}`,Ut={...Ot,headersTimeoutMs:2e4},Wt=/* @__PURE__ */ M({authorizationUrlTemplate:/* @__PURE__ */ P(/* @__PURE__ */ N(),/* @__PURE__ */ Se(Ht))}),Gt=/* @__PURE__ */ M({accessToken:/* @__PURE__ */ P(/* @__PURE__ */ N(),/* @__PURE__ */ j(Le)),accessTokenExpiresAt:/* @__PURE__ */ P(/* @__PURE__ */ N(),/* @__PURE__ */ A()),refreshToken:/* @__PURE__ */ P(/* @__PURE__ */ N(),/* @__PURE__ */ j(Re)),refreshTokenExpiresAt:/* @__PURE__ */ P(/* @__PURE__ */ N(),/* @__PURE__ */ A()),tenantName:/* @__PURE__ */ P(/* @__PURE__ */ N(),/* @__PURE__ */ xe(Qe)),loginConnectionId:/* @__PURE__ */ P(/* @__PURE__ */ N(),/* @__PURE__ */ j(ze))}),Kt=(e,t,n)=>{let r=/* @__PURE__ */ Ne(e,t);if(!r.success)throw new v(`invalid_json`,`the login connection response does not match the contract`,n);return r.output},qt=async e=>{let t=await e.request({method:`GET`,path:`/v0/login-connections/metadata`,query:[],hasBody:!1,body:null,responseKind:`json`});if(t.kind!==`json`)throw new v(`unexpected_content_type`,`not JSON`);return Kt(Wt,t.body,t.status).authorizationUrlTemplate},Jt=async(e,t)=>{let n;try{n=await e.request({method:`POST`,path:`/v0/login-connections/token`,query:[],hasBody:!0,body:t,responseKind:`json`})}catch(e){throw e instanceof _&&e.info.code===`invalid_grant`?new We(`the authorization code or refresh token is no longer valid`):e}if(n.kind!==`json`)throw new v(`unexpected_content_type`,`not JSON`);return Kt(Gt,n.body,n.status)},Yt=(e,t,n)=>{if(e.apiBaseUrl!==t.href||e.tenantName!==n)throw new w(`credentials_mismatch`,`保存されたログイン(環境 ${L(new URL(e.apiBaseUrl))} / テナント ${e.tenantName})が、この作業ディレクトリの接続先(環境 ${L(t)} / テナント ${n})と一致しません。この作業ディレクトリで \`npx @flyle/ai-contact-center-mcp@latest login\` を実行し直してください`)},Xt=(e,t)=>({apiBaseUrl:t.href,tenantName:e.tenantName,loginConnectionId:e.loginConnectionId,accessToken:e.accessToken,accessTokenExpiresAt:e.accessTokenExpiresAt,refreshToken:e.refreshToken,refreshTokenExpiresAt:e.refreshTokenExpiresAt}),Zt=e=>{let{credentialsFile:t,baseUrl:n,tenantName:r,tokenClient:i,now:a}=e,o=null,s=null,c=[],l=(...e)=>{c.push(...e),c.splice(0,Math.max(0,c.length-8))},u=async()=>{let e=await ut(t);if(e==null||Date.parse(e.refreshTokenExpiresAt)<=a())throw new w(`login_required`,Ue);return Yt(e,n,r),e},d=e=>e-a()>6e4,f=a=>yt(t,e.lock,async()=>{let e=await u();l(e.accessToken,e.refreshToken);let s=Date.parse(e.accessTokenExpiresAt);if(e.accessToken!==a&&d(s))return o={token:e.accessToken,expiresAt:s},e.accessToken;let c;try{c=await Jt(i,{grant_type:`refresh_token`,refresh_token:e.refreshToken})}catch(e){throw e instanceof We?(await pt(t),new w(`login_required`,Ue)):e}if(l(c.accessToken,c.refreshToken),c.tenantName!==r)throw await pt(t),new w(`login_required`,`ログインの更新で、設定と違うテナント(${c.tenantName})の応答を受け取ったため、保存したログイン情報を破棄しました。${Ue}`);return await ft(t,Xt(c,n)),o={token:c.accessToken,expiresAt:Date.parse(c.accessTokenExpiresAt)},c.accessToken}),p=e=>(s??=f(e).finally(()=>{s=null}),s);return{getAccessToken:()=>o!=null&&d(o.expiresAt)?Promise.resolve(o.token):p(o?.token??null),refreshAfterRejection:e=>o!=null&&o.token!==e?Promise.resolve(o.token):(o=null,p(e)),assertLoggedIn:async()=>{o??await u()},secrets:()=>c,whenIdle:async()=>{await Promise.allSettled(s==null?[]:[s])}}},Qt=(e,t)=>e===`darwin`?[`open`,[t]]:e===`win32`?[`rundll32`,[`url.dll,FileProtocolHandler`,t]]:[`xdg-open`,[t]],$t=(e,t=process.platform)=>{let[n,r]=Qt(t,e),i=ne(n,r,{stdio:`ignore`,detached:!0,shell:!1});i.on(`error`,T),i.unref()},en=`flyle-ai-contact-center-mcp/${Fe}`,tn=(e,t=Ot)=>{let{workspaceId:n,...r}=e;return Vt({...r,clientWorkspaceId:n,userAgent:en},t)},nn=`.flyle-ai-contact-center-mcp`,rn=/* @__PURE__ */ M({tenantName:/* @__PURE__ */ N(),apiBaseUrl:/* @__PURE__ */ ke(/* @__PURE__ */ Oe(/* @__PURE__ */ N()),null)}),an=e=>h.join(e,nn,`workspace.json`),on=e=>e instanceof Error&&E(e,`code`)&&e.code===`ENOENT`,sn=e=>e instanceof Error&&E(e,`code`)&&e.code===`EEXIST`,cn=async e=>{let t;try{t=await d(an(e),`utf8`)}catch(e){if(on(e))return null;throw e}let n;try{n=JSON.parse(t)}catch{n=null}let r=/* @__PURE__ */ Ne(rn,n);if(!r.success)throw new C(`corrupted`,`${an(e)} is not a valid workspace binding. Inspect it manually; the MCP server never overwrites it.`);return r.output},ln=async e=>(await cn(e))?.tenantName??null,un=(e,t,n)=>new C(`tenant_mismatch`,`${e} is dedicated to tenant "${t}", not "${n}". Use a separate directory (and a separate Claude Code session) for each tenant.`),dn=(e,t,n)=>new C(`environment_mismatch`,`${e} is dedicated to the API ${new URL(t).host}, not ${new URL(n).host}. Use a separate directory for each environment.`),fn=e=>{let t=[],n=h.dirname(e);for(;n!==h.dirname(n);)t.push(n),n=h.dirname(n);return t.push(n),t},pn=async(e,t)=>{let n=await Promise.all(fn(e).map(async e=>({dir:e,tenant:await ln(e)})));for(let{dir:e,tenant:r}of n)if(r!=null&&r!==t)throw un(e,r,t)},mn=(e,t)=>i(`sha256`).update(`${e.hostname}\0${e.username}\0${t}`).digest(`base64url`).slice(0,32),hn=(e,t)=>{let n={version:2,tenantName:e.tenantName,apiBaseUrl:e.apiBaseUrl,boundAt:t.toISOString()};return`${JSON.stringify(n,null,2)}\n`},gn=async(e,t,n)=>{let r=an(e),i=`${r}.${a(8).toString(`hex`)}.tmp`;try{await te(i,hn(t,n),{flag:`wx`}),await p(i,r)}finally{await m(i,{force:!0})}},_n=async(e,t,n,r)=>{await l(h.join(e,nn),{recursive:!0});try{await te(an(e),hn(t,n),{flag:`wx`});return}catch(e){if(!sn(e))throw e}let i=await cn(e);if(i?.tenantName!==t.tenantName)throw un(e,i?.tenantName??`(unknown)`,t.tenantName);if(i.apiBaseUrl!==t.apiBaseUrl){if(i.apiBaseUrl==null&&r)await gn(e,t,n);else throw dn(e,i.apiBaseUrl??`(unknown)`,t.apiBaseUrl)}},vn=async e=>{let t=await f(e.cwd);if(t===await f(e.homeDir).catch(()=>e.homeDir)||t===h.parse(t).root)throw new C(`shared_directory`,`${t} is shared by everything you do and cannot be dedicated to one tenant. Create a directory for this tenant (e.g. ~/flyle-cs/<tenant>) and start the session there.`);return t},yn=async(e,t)=>{let n=await vn(e);return await pn(n,t.tenantName),await _n(n,t,e.now(),!0),{...t,root:n,workspaceId:mn(e,n)}},bn=async e=>{let t=await vn(e),n=await cn(t);return n?.apiBaseUrl==null?null:(await pn(t,n.tenantName),{tenantName:n.tenantName,apiBaseUrl:n.apiBaseUrl,root:t,workspaceId:mn(e,t)})},xn=async(e,t)=>{await _n(e.root,e,t,!1)},Sn=(e,t,n)=>new C(`outside_workspace`,`${n} (${t}) must be inside the tenant workspace ${e}; a shared location could mix files between tenants.`),Cn=async(e,t)=>{if(!t.startsWith(`${e.root}${h.sep}`))throw Sn(e.root,t,`the file`);let n=[];for(let r=h.dirname(t);r!==e.root;r=h.dirname(r))n.push(r);let r=await Promise.all(n.map(async e=>({dir:e,tenant:await ln(e)})));for(let{dir:t,tenant:n}of r)if(n!=null&&n!==e.tenantName)throw un(t,n,e.tenantName)},wn=(e,t,n)=>tn({config:{baseUrl:t},auth:null,workspaceId:n,fetch:e.fetch,now:e.now,sleep:e.sleep,logger:e.logger},Ut),Tn=async e=>{let t=await bn(e.workspaceEnv);if(t==null)return null;let n=ct(e.credentialsDir,t.workspaceId),r=await ut(n);return r==null?null:{workspace:t,file:n,stored:r,baseUrl:Xe(r.apiBaseUrl,tt(e.env),`${n} の apiBaseUrl`)}},En=(e,t)=>{let n=Zt({credentialsFile:t.file,baseUrl:t.baseUrl,tenantName:t.stored.tenantName,tokenClient:wn(e,t.baseUrl,t.workspace.workspaceId),now:e.now,lock:e.lock});return{auth:n,client:tn({config:{baseUrl:t.baseUrl},auth:n,workspaceId:t.workspace.workspaceId,fetch:e.fetch,now:e.now,sleep:e.sleep,logger:e.logger})}},Dn=(e,t)=>`/v0/tenants/${encodeURIComponent(e)}${t}`,R=e=>e instanceof I||e instanceof w||e instanceof F||e instanceof C?e.message:e instanceof _?`公開 API がエラーを返しました(${String(e.info.status)} ${e.info.code??`http_error`}): ${e.info.message}`:e instanceof v?`公開 API と通信できませんでした(${e.kind}): ${e.message}`:e instanceof Error?e.message:String(e),z=(e,t)=>{let n=e;for(let e of t)e.length!==0&&(n=n.split(e).join(`[redacted]`));return n},On=async(e,t)=>{let{client:n}=En(e,t);try{await n.request({method:`DELETE`,path:Dn(t.stored.tenantName,`/current-login-connection`),query:[],hasBody:!1,body:null,responseKind:`empty`})}catch(e){if(!(e instanceof w&&e.kind===`login_required`||e instanceof _&&e.info.status===401))throw e}},kn=async e=>{let t=await Tn(e);t==null?e.out(`この作業ディレクトリにはログイン情報がありません。`):(await On(e,t),await yt(t.file,e.lock,()=>pt(t.file)),e.out(`ログアウトしました(環境 ${L(t.baseUrl)} / テナント ${t.stored.tenantName})。`))},An=`127.0.0.1`,jn=`/callback`,Mn=e=>{try{let{values:t}=ie({args:[...e],options:{tenant:{type:`string`},"api-base-url":{type:`string`}},strict:!0,allowPositionals:!1});return{tenant:t.tenant??null,apiBaseUrl:t[`api-base-url`]??null}}catch(e){throw new I(`${e instanceof Error?e.message:String(e)}\n使い方: login [--tenant <テナント名>] [--api-base-url <URL>]`)}},Nn=(e,t,n)=>e==null?t?.apiBaseUrl==null?Xe(`https://api.flygate.flyle.io`,n,`既定の接続先`):Xe(t.apiBaseUrl,n,`作業ディレクトリの接続先`):Xe(e,n,`--api-base-url`),Pn=(e,t)=>{if(e!=null)return $e(e,`--tenant`);if(t!=null)return t.tenantName;throw new I("テナントを決められません。`login --tenant <テナント名>` で指定してください(作業ディレクトリをそのテナント専用にします)。")},Fn=()=>a(32).toString(`base64url`),In=e=>i(`sha256`).update(e).digest(`base64url`),Ln=(e,t)=>{let n=Buffer.from(e),r=Buffer.from(t);return n.length===r.length&&o(n,r)},Rn=(e,t,n)=>{let r;try{r=new URL(e.replaceAll(Ht,t))}catch{throw new I(`公開 API が返した同意画面の URL が不正です。`)}let i=r.protocol===`http:`&&n&&(Ye(r.hostname)||r.hostname.endsWith(`.localhost`));if(r.protocol!==`https:`&&!i)throw new I(`公開 API が返した同意画面の URL が https ではありません。`);return r},zn=/[\p{Cc}\p{Cf}]/gu,Bn=(e,t)=>{let n=``;for(let r of e){if(n.length+r.length>t)break;n+=r}return n},Vn=(e,t)=>{let n=e=>e.replaceAll(zn,``);return Bn(`${n(e)} / ${n(h.basename(t))}`,255)},Hn=/* @__PURE__ */ Me([/* @__PURE__ */ M({error:/* @__PURE__ */ P(/* @__PURE__ */ N(),/* @__PURE__ */ j(/^[a-z_]{1,64}$/)),state:/* @__PURE__ */ N()}),/* @__PURE__ */ M({code:/* @__PURE__ */ P(/* @__PURE__ */ N(),/* @__PURE__ */ j(Ie)),state:/* @__PURE__ */ N()})]),Un={success:`ログインが完了しました。このタブは閉じてかまいません。`,denied:`ログインを中止しました。このタブは閉じてかまいません。`,failure:`ログインを完了できませんでした。このタブを閉じて、ターミナルの表示を確認してください。`,handled:`このログインは処理済みです。このタブは閉じてかまいません。`,unknown:`実行中のログインの応答として確認できませんでした。ログインを続ける場合は、ターミナルに表示された URL から同意画面を開き直してください。`,rejected:`この宛先への要求は受け付けていません。`},B=(e,t,n)=>{e.writeHead(t,{"content-type":`text/html; charset=utf-8`,"cache-control":`no-store`,"content-security-policy":`default-src 'none'`,"referrer-policy":`no-referrer`}),e.end(`<!doctype html><html lang="ja"><meta charset="utf-8"><title>Flyle AIコンタクトセンター</title><p>${Un[n]}</p></html>`)},Wn=e=>new Promise((t,n)=>{e.once(`error`,n),e.listen(0,An,()=>{let r=e.address();r==null||typeof r==`string`?n(new I(`ログイン用の待受ポートを開けませんでした。`)):t(r.port)})}),Gn=async(e,t,n)=>{let r=!1,i=0,a=null,o=Promise.withResolvers(),s=e=>{r=!0,o.reject(new I(e))},c=(e,t,r)=>{i+=1,B(e,400,t),n(r)},l=re((t,n)=>{if(a==null||t.headers.host!==a){c(n,`rejected`,`ログイン用の待受に、想定外の宛先(Host ヘッダ)の要求が届いたため拒否しました。ログインは待ち続けています。`);return}let i=new URL(t.url??`/`,`http://${a}`);if(t.method!==`GET`||i.pathname!==jn){n.writeHead(404).end();return}if(r){B(n,410,`handled`);return}let l=i.searchParams.get(`state`);if(l==null||!Ln(l,e)){c(n,`unknown`,`このログインのものではない応答(state が一致しない、または無い)を受け取ったため無視しました。ブラウザで同意を続けてください。`);return}let u=/* @__PURE__ */ Ne(Hn,me(i.searchParams));if(!u.success){B(n,400,`failure`),s(`同意画面からの応答の形式が正しくありません(認可コードがない、または形式が違います)。もう一度 login を実行してください。`);return}let d=u.output;if(E(d,`error`)){let e=d.error===`access_denied`;B(n,200,e?`denied`:`failure`),s(e?`ブラウザでログインが拒否されました。`:`同意画面がエラーを返しました(${d.error})。`);return}r=!0;let f=!1;o.resolve({code:d.code,finish:e=>{f||(f=!0,B(n,e===`success`?200:400,e))}})}),u=await Wn(l);a=`${An}:${String(u)}`;let d=setTimeout(()=>{if(r)return;let e=i===0?``:`(このログインのものではない要求を ${String(i)} 件受け取り、無視しました)`;s(`${String(Math.round(t/1e3/60))} 分以内にブラウザでの同意が完了しませんでした${e}。もう一度 login を実行してください。`)},t);return{port:u,received:o.promise,close:()=>new Promise(e=>{clearTimeout(d),l.closeAllConnections(),l.close(()=>e())})}},Kn=`その接続は最長 30 日間有効なまま残る可能性があります。管理画面の「設定 → 外部ツール接続」から切断してください。`,qn=async(e,t)=>{if(t!=null)try{await On(e,t)}catch(n){e.err(`以前のログイン(接続 ID ${t.stored.loginConnectionId})をサーバーで切断できませんでした(${R(n)})。${Kn}`)}},Jn=async e=>{try{return await Tn(e)}catch(t){if(!(t instanceof w&&t.kind===`login_required`)&&!(t instanceof F))throw t;return e.err(`以前のログイン情報を読めなかったため、新しいログインで上書きします(${R(t)})。以前の接続はサーバーで切断できていません。${Kn}`),null}},Yn=async(e,t,n,r)=>{let i=ct(e.credentialsDir,t.workspaceId);await yt(i,e.lock,()=>ft(i,Xt(r,n)))},Xn=e=>({getAccessToken:()=>Promise.resolve(e),refreshAfterRejection:()=>Promise.resolve(e),secrets:()=>[e]}),Zn=async(e,t,n,r)=>{let i=tn({config:{baseUrl:t},auth:Xn(r.accessToken),workspaceId:n.workspaceId,fetch:e.fetch,now:e.now,sleep:e.sleep,logger:e.logger});try{return await i.request({method:`DELETE`,path:Dn(r.tenantName,`/current-login-connection`),query:[],hasBody:!1,body:null,responseKind:`empty`}),!0}catch{return!1}},Qn=async e=>{let t=Mn(e.argv),n=tt(e.env),r=await cn(e.workspaceEnv.cwd),i=Nn(t.apiBaseUrl,r,n),a=Pn(t.tenant,r),o=await yn(e.workspaceEnv,{tenantName:a,apiBaseUrl:i.href}),s=await Jn(e),c=wn(e,i,o.workspaceId),l=Rn(await qt(c),a,n),u=Fn(),d=Fn(),f=[u,d],p=await Gn(d,e.callbackTimeoutMs,e.err),m=null;try{let t=`http://${An}:${String(p.port)}${jn}`;l.searchParams.set(`tenant_name`,a),l.searchParams.set(`code_challenge`,In(u)),l.searchParams.set(`code_challenge_method`,`S256`),l.searchParams.set(`redirect_uri`,t),l.searchParams.set(`state`,d),l.searchParams.set(`connection_name`,Vn(e.workspaceEnv.hostname,o.root)),l.searchParams.set(`api_origin`,i.origin),e.err(`環境 ${L(i)} のテナント「${a}」にログインします。ブラウザで同意画面を開きます。\n開かない場合は、次の URL をブラウザで開いてください:\n${l.href}`),e.openBrowser(l.href),m=await p.received,f.push(m.code);let n;try{n=await Jt(c,{grant_type:`authorization_code`,code:m.code,code_verifier:u,redirect_uri:t})}catch(e){throw e instanceof We?new I(`認可コードを交換できませんでした。もう一度 login を実行してください。`):e}if(f.push(n.accessToken,n.refreshToken),n.tenantName!==a){let t=await Zn(e,i,o,n);throw new I(`ブラウザで同意したテナント(${n.tenantName})が、ログインしようとしたテナント(${a})と違います。ログイン情報は保存していません。`+(t?`そのテナントに作られた接続は切断しました。`:`テナント ${n.tenantName} の管理画面の「設定 → 外部ツール接続」から、作られた接続を切断してください。`))}await xn(o,new Date(e.now())),await qn(e,s),await Yn(e,o,i,n),m.finish(`success`),e.out(`ログインしました(環境 ${L(i)} / テナント ${a} / 作業ディレクトリ ${o.root})。`)}catch(e){throw m?.finish(`failure`),new I(z(R(e),f))}finally{await p.close()}},$n=/* @__PURE__ */ M({currentUser:/* @__PURE__ */ M({name:/* @__PURE__ */ Oe(/* @__PURE__ */ N()),email:/* @__PURE__ */ Oe(/* @__PURE__ */ N()),roles:/* @__PURE__ */ Ee(/* @__PURE__ */ M({roleName:/* @__PURE__ */ N()})),currentLoginConnection:/* @__PURE__ */ M({name:/* @__PURE__ */ N(),expiresAt:/* @__PURE__ */ P(/* @__PURE__ */ N(),/* @__PURE__ */ A())})})}),er="ログインしていません。作業ディレクトリで `npx @flyle/ai-contact-center-mcp@latest login` を実行してください",tr=async e=>{let t=await Tn(e);if(t==null)throw new I(er);e.out(`環境: ${L(t.baseUrl)}`),e.out(`テナント: ${t.stored.tenantName}`);let{client:n}=En(e,t),r;try{r=await n.request({method:`GET`,path:Dn(t.stored.tenantName,`/current-user`),query:[],hasBody:!1,body:null,responseKind:`json`})}catch(e){throw e instanceof w&&e.kind===`login_required`?new I(`ログインの有効期限が切れています。${er}`):e}let i=/* @__PURE__ */ Ne($n,r.kind===`json`?r.body:null);if(!i.success)throw new v(`invalid_json`,`the current user response does not match the contract`);let a=i.output.currentUser,o=a.email==null?``:` <${a.email}>`;e.out(`ユーザー: ${a.name??`(名前未設定)`}${o}`),e.out(`ロール: ${a.roles.map(e=>e.roleName).join(`, `)||`(なし)`}`),e.out(`接続名: ${a.currentLoginConnection.name}`),e.out(`ログインの有効期限: ${a.currentLoginConnection.expiresAt}(使うたびに延長。ログインから最長 90 日)`)},nr=e=>e.replaceAll(`~1`,`/`).replaceAll(`~0`,`~`),rr=e=>Array.isArray(e),V=(e,t)=>{if(t===``)return[e];let n=t.split(`/`).slice(1).map(e=>nr(e)),r=[e];for(let e of n){let t=[];for(let n of r)if(e===`*`)rr(n)&&t.push(...n);else if(rr(n)){let r=Number(e);Number.isInteger(r)&&r>=0&&r<n.length&&t.push(n[r])}else D(n)&&E(n,e)&&t.push(n[e]);r=t}return r},ir=async e=>{let t=await u(e,ae.O_RDONLY|ae.O_NONBLOCK|ae.O_NOFOLLOW);try{let e=await t.stat();if(!e.isFile())throw new b(`not_a_file`,`only regular files can be read`);return{handle:t,size:e.size}}catch(e){throw await t.close(),e}},ar=async(e,t)=>{let{handle:n,size:r}=await ir(e);try{if(r>t)throw new b(`too_large`,`the file exceeds ${String(t)} bytes`);let e=[],i=0;for(;;){let r=Buffer.allocUnsafe(Math.min(1048576,t-i+1)),{bytesRead:a}=await n.read(r,0,r.length,null);if(a===0)break;if(i+=a,i>t)throw new b(`too_large`,`the file exceeds ${String(t)} bytes`);e.push(r.subarray(0,a))}return Buffer.concat(e,i)}finally{await n.close()}},or=(e,t)=>e===t||e.startsWith(`${t}${h.sep}`),sr=async(e,t,n,r)=>{let i=h.resolve(n,e),a;try{a=await f(i)}catch{throw new b(`not_found`,`file not found: ${e}`)}if(!(await Promise.all(t.map(e=>f(e).catch(()=>e)))).some(e=>or(a,e)))throw new b(`outside_roots`,`the path is outside the configured file roots`);return await Cn(r,a),a},cr=/* @__PURE__ */ new Map([[`.md`,`text/markdown`],[`.markdown`,`text/markdown`],[`.txt`,`text/plain`],[`.csv`,`text/csv`],[`.json`,`application/json`],[`.html`,`text/html`],[`.htm`,`text/html`],[`.pdf`,`application/pdf`],[`.docx`,`application/vnd.openxmlformats-officedocument.wordprocessingml.document`],[`.xlsx`,`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`],[`.pptx`,`application/vnd.openxmlformats-officedocument.presentationml.presentation`],[`.png`,`image/png`],[`.jpg`,`image/jpeg`],[`.jpeg`,`image/jpeg`],[`.zip`,`application/zip`]]),lr=e=>cr.get(h.extname(e).toLowerCase())??`application/octet-stream`,ur=e=>new Promise((t,n)=>{let r=i(`sha256`);e.on(`data`,e=>r.update(e)).on(`error`,n).on(`end`,()=>t(r.digest()))}),dr=async(e,t,n,r)=>{let i=await sr(e,t,n,r),{handle:a,size:o}=await ir(i),s;try{s=await ur(a.createReadStream())}finally{await a.close()}let c=h.basename(i);return{path:i,fileName:c,sizeBytes:o,sha256Hex:s.toString(`hex`),sha256Base64:s.toString(`base64`),mimeType:lr(c)}},fr=(e,t=9e5,n=1e3)=>{let r=/* @__PURE__ */ new Map,i=()=>{let t=e();for(let[e,n]of r)n.expiresAt<=t&&r.delete(e)};return{get size(){return r.size},register:(a,o,s)=>{for(i();r.size>=n;){let e=r.keys().next();if(e.done)break;r.delete(e.value)}r.delete(a),r.set(a,{kind:o,headers:s,expiresAt:e()+t})},take:(t,n)=>{let i=r.get(t);if(i?.kind!==n)throw new y(`unknown_url`,`the URL was not returned by a recent API call for this kind of transfer`);if(r.delete(t),i.expiresAt<=e())throw new y(`expired_url`,`the signed URL has expired; call the API again to get a new one`);return i}}},pr=(e,t)=>{let n;try{n=new URL(e)}catch{throw new y(`not_allowed_host`,`the transfer URL is not a valid URL`)}let r=t.allowInsecureHttp&&Ye(n.hostname);if(n.protocol!==`https:`&&!(n.protocol===`http:`&&r))throw new y(`insecure_url`,`transfer URLs must use https`);if(n.username!==``||n.password!==``)throw new y(`not_allowed_host`,`transfer URLs must not contain credentials`);let i=n.hostname.toLowerCase();if(!(r||t.storageHostSuffixes.some(e=>e.startsWith(`.`)?i.endsWith(e):i===e)))throw new y(`not_allowed_host`,`the host ${i} is not an allowed storage host`);return n},mr=e=>{if(!D(e))return{};let t={};for(let[n,r]of pe(e))typeof r==`string`&&(t[n]=r);return t},hr=(e,t)=>{if(t==null)return[];let n=V(e,t.urlPointer).filter(e=>typeof e==`string`),r=t.headersPointer==null?[]:V(e,t.headersPointer).map(e=>mr(e));return n.map((e,n)=>({url:e,kind:t.kind,headers:r.length===1?r[0]??{}:r[n]??{}}))},gr=4096,_r=async e=>{if(e.body==null)return``;let t=e.body.getReader(),n=[],r=0;try{for(;r<gr;){let{done:e,value:i}=await t.read();if(e)break;n.push(i),r+=i.byteLength}}catch{}finally{await t.cancel().catch(T)}return new TextDecoder(`utf-8`).decode(Buffer.concat(n)).slice(0,gr)},vr=e=>e instanceof y?e:e instanceof Error&&(e.name===`AbortError`||e.name===`TimeoutError`)?new y(`timeout`,`the storage did not respond in time`):new y(`network`,e instanceof Error?e.message:`network failure`),yr=async e=>{if(fe(e.headers).some(e=>e.toLowerCase()===`authorization`))throw new y(`invalid_headers`,`transfer headers must not include authorization`);let t;try{t=await ar(e.filePath,e.maxBytes)}catch(e){throw e instanceof b&&(e.kind===`not_a_file`||e.kind===`too_large`)?new y(e.kind,e.kind===`not_a_file`?`only regular files can be uploaded`:e.message):e}let n;try{n=await e.fetch(e.url,{method:`PUT`,headers:e.headers,body:t,redirect:`manual`,signal:AbortSignal.timeout(e.timeoutMs)})}catch(e){throw vr(e)}if(n.status>=300&&n.status<400)throw await n.body?.cancel().catch(T),new y(`redirect_not_followed`,`redirect responses are not followed`,n.status);if(!n.ok)throw new y(`http_error`,`upload failed: ${(await _r(n)).slice(0,300)}`,n.status);return await n.body?.cancel().catch(T),{status:n.status,etag:n.headers.get(`etag`),bytes:t.byteLength}},br=/[^A-Za-z0-9._-]/g,xr=(e,t)=>{let n=h.basename(e??``).replace(br,`_`).replace(/^_+/,``).slice(0,120);return n===``||/^\.+$/.test(n)?t:n},Sr=e=>`${(/* @__PURE__ */ new Date()).toISOString().replaceAll(/[:.]/g,`-`)}-${a(3).toString(`hex`)}-${e}`,Cr=async(e,t)=>{if(t<=0)return`timeout`;let n=null,r=new Promise(e=>{n=setTimeout(e,t,`timeout`)});try{return await Promise.race([e.read(),r])}finally{n!=null&&clearTimeout(n)}},wr=async(e,t)=>{await l(t.outputDir,{recursive:!0});let n=h.join(t.outputDir,Sr(t.fileName)),r=await u(n,`wx`),a=i(`sha256`),o=e.getReader(),s=Date.now()+t.timeoutMs,c=0;try{for(;;){let e=await Cr(o,s-Date.now());if(e===`timeout`)throw await o.cancel().catch(T),new y(`timeout`,`the download did not finish within ${t.timeoutMs} ms`);let{done:n,value:i}=e;if(n)break;if(c+=i.byteLength,c>t.maxBytes)throw await o.cancel().catch(T),new y(`too_large`,`the download exceeds ${t.maxBytes} bytes`);a.update(i),await r.write(i)}}catch(e){throw await r.close(),await ee(n).catch(T),vr(e)}return await r.close(),{path:n,bytes:c,sha256Hex:a.digest(`hex`)}},Tr=async e=>{let t;try{t=await e.fetch(e.url,{method:`GET`,redirect:`manual`,signal:AbortSignal.timeout(e.timeoutMs)})}catch(e){throw vr(e)}if(t.status>=300&&t.status<400)throw await t.body?.cancel().catch(T),new y(`redirect_not_followed`,`redirect responses are not followed`,t.status);if(!t.ok)throw new y(`http_error`,`download failed: ${(await _r(t)).slice(0,300)}`,t.status);if(t.body==null)throw new y(`network`,`the download has no body`,t.status);return{...await wr(t.body,{outputDir:e.outputDir,fileName:e.fileName,maxBytes:e.maxBytes,timeoutMs:e.timeoutMs}),status:t.status,contentType:t.headers.get(`content-type`)}},Er=(e,t,n,r)=>{let i={level:e,message:t,...n,time:(/* @__PURE__ */ new Date()).toISOString()};return z(JSON.stringify(i),r)},Dr=(e,t=e=>console.error(e))=>({info:(n,r)=>t(Er(`info`,n,r,e())),warn:(n,r)=>t(Er(`warn`,n,r,e())),error:(n,r)=>t(Er(`error`,n,r,e()))}),Or=[`GET`,`POST`,`PUT`,`PATCH`,`DELETE`],kr=[`json`,`empty`,`sse`,`binary`],Ar=[`upload`,`download`],jr=[`read`,`draft`],Mr=[`wav-pcm16`,`base64`],Nr=[`pcm16le`,`base64`],H=e=>{throw new le(e)},U=e=>e===null,W=e=>Array.isArray(e)&&e.every(e=>typeof e==`string`),Pr=e=>{if(!Array.isArray(e)||e.length===0)return!1;let t=0;for(let n of e){if(typeof n!=`number`||!Number.isInteger(n)||n<200||n>=300||n<=t)return!1;t=n}return!0},Fr=e=>typeof e==`string`&&Or.some(t=>t===e),Ir=e=>typeof e==`string`&&kr.some(t=>t===e),Lr=e=>typeof e==`string`&&Ar.some(t=>t===e),Rr=e=>typeof e==`string`&&jr.some(t=>t===e),zr=(e,t)=>{if(U(e))return null;if(!D(e))return H(`${t}.transfer must be an object or null`);let{kind:n,urlPointer:r,headersPointer:i}=e;return Lr(n)?typeof r==`string`?!U(i)&&typeof i!=`string`?H(`${t}.transfer.headersPointer is invalid`):{kind:n,urlPointer:r,headersPointer:i}:H(`${t}.transfer.urlPointer is invalid`):H(`${t}.transfer.kind is invalid`)},Br=e=>typeof e==`string`&&Mr.some(t=>t===e),Vr=e=>typeof e==`string`&&Nr.some(t=>t===e),Hr=e=>typeof e==`number`&&Number.isInteger(e)&&e>0,Ur=(e,t)=>{if(U(e))return null;if(!D(e))return H(`${t} must be an object or null`);let{sampleRateHz:n,channels:r}=e;return Hr(n)?Hr(r)?{sampleRateHz:n,channels:r}:H(`${t}.channels is invalid`):H(`${t}.sampleRateHz is invalid`)},Wr=(e,t)=>{if(!D(e))return H(`${t} must be an object`);let{pointer:n,format:r,maxBytes:i,pcm:a}=e;if(typeof n!=`string`||!n.startsWith(`/`))return H(`${t}.pointer is invalid`);if(!Br(r))return H(`${t}.format is invalid`);if(!Hr(i))return H(`${t}.maxBytes is invalid`);let o=Ur(a,`${t}.pcm`);return r===`wav-pcm16`==(o!=null)?{pointer:n,format:r,maxBytes:i,pcm:o}:H(`${t}.pcm does not match the format`)},Gr=(e,t)=>{if(!D(e))return H(`${t} must be an object`);let{event:n,pointer:r,format:i,pcm:a,mediaType:o}=e;if(!U(n)&&typeof n!=`string`)return H(`${t}.event is invalid`);if(typeof r!=`string`||!r.startsWith(`/`))return H(`${t}.pointer is invalid`);if(!Vr(i))return H(`${t}.format is invalid`);if(!U(o)&&typeof o!=`string`)return H(`${t}.mediaType is invalid`);let s=Ur(a,`${t}.pcm`);return i===`pcm16le`==(s!=null)?i===`base64`==(o!=null)?{event:n,pointer:r,format:i,pcm:s,mediaType:o}:H(`${t}.mediaType does not match the format`):H(`${t}.pcm does not match the format`)},Kr=(e,t)=>{if(U(e))return null;if(!D(e))return H(`${t}.inlineFiles must be an object or null`);let{input:n,output:r}=e;return!Array.isArray(n)||!Array.isArray(r)?H(`${t}.inlineFiles is invalid`):n.length===0&&r.length===0?H(`${t}.inlineFiles must declare input or output`):{input:n.map((e,n)=>Wr(e,`${t}.inlineFiles.input[${String(n)}]`)),output:r.map((e,n)=>Gr(e,`${t}.inlineFiles.output[${String(n)}]`))}},qr=(e,t)=>{if(U(e))return null;if(!D(e))return H(`${t}.sseOutcome must be an object or null`);let{requiredEvents:n,terminalEvent:r,successPointer:i,successValue:a,failureEvents:o}=e;return W(n)?typeof r==`string`?U(i)&&U(a)?W(o)?{requiredEvents:n,terminalEvent:r,successPointer:i,successValue:a,failureEvents:o}:H(`${t}.sseOutcome.failureEvents is invalid`):typeof i!=`string`||!i.startsWith(`/`)?H(`${t}.sseOutcome.successPointer is invalid`):typeof a!=`string`&&typeof a!=`number`&&typeof a!=`boolean`?H(`${t}.sseOutcome.successValue is invalid`):W(o)?{requiredEvents:n,terminalEvent:r,successPointer:i,successValue:a,failureEvents:o}:H(`${t}.sseOutcome.failureEvents is invalid`):H(`${t}.sseOutcome.terminalEvent is invalid`):H(`${t}.sseOutcome.requiredEvents is invalid`)},Jr=(e,t)=>{let n=`operations[${t}]`;if(!D(e))return H(`${n} must be an object`);let{operationId:r,method:i,pathTemplate:a,summary:o,description:s,permission:c,effect:l,responseKind:u,successStatuses:d,pathParams:f,queryParams:p,bodyFields:m,wholeBodyField:ee,inputSchema:te,transfer:h,inlineFiles:ne,sseOutcome:re}=e;return typeof r!=`string`||r===``?H(`${n}.operationId is invalid`):Fr(i)?typeof a!=`string`||!a.startsWith(`/`)?H(`${n}.pathTemplate is invalid`):typeof o==`string`?!U(s)&&typeof s!=`string`?H(`${n}.description is invalid`):!U(l)&&!Rr(l)?H(`${n}.effect is invalid`):Ir(u)?Pr(d)?W(f)?W(p)?!U(m)&&!W(m)?H(`${n}.bodyFields is invalid`):!U(ee)&&typeof ee!=`string`?H(`${n}.wholeBodyField is invalid`):m!=null&&ee!=null?H(`${n} declares both bodyFields and wholeBodyField`):D(te)?{operationId:r,method:i,pathTemplate:a,summary:o,description:s,permission:c??null,effect:l,responseKind:u,successStatuses:d,pathParams:f,queryParams:p,bodyFields:m,wholeBodyField:ee,inputSchema:te,transfer:zr(h,n),inlineFiles:Kr(ne,n),sseOutcome:qr(re,n)}:H(`${n}.inputSchema is invalid`):H(`${n}.queryParams is invalid`):H(`${n}.pathParams is invalid`):H(`${n}.successStatuses is invalid`):H(`${n}.responseKind is invalid`):H(`${n}.summary is invalid`):H(`${n}.method is invalid`)},Yr=e=>{if(!D(e))return H(`manifest must be an object`);let t=e.source;if(!D(t)||typeof t.title!=`string`||typeof t.version!=`string`)return H(`manifest.source is invalid`);let n=e.operations;if(!Array.isArray(n))return H(`manifest.operations must be an array`);let r=n.map((e,t)=>Jr(e,t));return new Set(r.map(e=>e.operationId)).size===r.length?{source:{title:t.title,version:t.version},operations:r}:H(`manifest.operations has duplicate operationId`)},Xr=new URL(`./manifest.json.br`,import.meta.url),Zr=(e=Xr)=>{let t=oe(e),n;try{n=JSON.parse((e.pathname.endsWith(`.br`)?se(t):t).toString(`utf8`))}catch{throw new le(`manifest at ${e.pathname} is not valid JSON or brotli`)}return Yr(n)},Qr=e=>typeof e==`string`?e:Array.isArray(e)&&e.every(e=>typeof e==`string`)?e.join(`, `):null,$r={"tenant-root":e=>`${e}(テナント全体に対して)`,"any-resource":e=>`${e}(いずれかのエージェントで保持)`,"per-resource":e=>`${e}(対象エージェントに対して)`,"per-resource-all":e=>`${e} のすべて(対象エージェントに対して)`,"per-resource-any":e=>`${e} のいずれか(対象エージェントに対して)`},ei=e=>E($r,e),ti=e=>{if(!D(e))return null;let t=e.gate;if(t===`none`)return`認証のみ(ロール不要)`;let n=Qr(e.action??e.actions);return n==null||typeof t!=`string`?null:ei(t)?`必要な権限: ${$r[t](n)}`:`必要な権限: ${n}`},ni={read:null,draft:`下書きへの変更です。公開版(利用者への配信)には publish まで反映されません。`},ri=e=>e.effect==null?null:ni[e.effect],ii=(e,t)=>{let n=[e.summary];e.description!=null&&n.push(``,e.description),n.push(``,`HTTP: ${e.method} ${e.pathTemplate}`);let r=ti(e.permission);r!=null&&n.push(r);let i=ri(e);i!=null&&n.push(``,i),e.responseKind===`sse`&&n.push(``,`ストリーミング応答を終端まで収集してから返します(数分かかることがあります)。`),e.responseKind===`binary`&&n.push(``,t.binaryResponse),e.transfer?.kind===`download`&&n.push(``,t.downloadTransfer),e.transfer?.kind===`upload`&&n.push(``,t.uploadTransfer),e.wholeBodyField!=null&&n.push(``,`リクエストボディは "${e.wholeBodyField}" 引数にそのまま渡します(判別共用体)。`);for(let r of e.inlineFiles?.input??[])n.push(``,t.inlineInput(r));if((e.inlineFiles?.output.length??0)>0&&n.push(``,t.inlineOutput),e.sseOutcome!=null){let t=[...e.sseOutcome.requiredEvents,e.sseOutcome.successPointer==null?e.sseOutcome.terminalEvent:`${e.sseOutcome.terminalEvent}{${e.sseOutcome.successPointer}=${JSON.stringify(e.sseOutcome.successValue)}}`];n.push(``,`成功判定: ${t.join(` と `)} が揃ったときだけ outcome=success。欠落・異常終了・打ち切りは isError で返し、自動再送しません。`)}return e.method!==`GET`&&n.push(``,`この操作は自動再送しません。タイムアウト時は状態を再取得して確認してください。`),n.join(`
|
|
28
|
-
`)},
|
|
29
|
-
`).replaceAll(/\]\(([^)\s]+)\)/g,(e,n)=>{try{return`](${new URL(n,t).toString()})`}catch{return e}})},
|
|
30
|
-
`)},
|
|
27
|
+
`,i)?2:1;e=e.slice(i+a);let s=o(n);s!=null&&r.push(s),i=e.search(bt)}return r},hasPendingIncomplete:()=>e!==``||r.length>0,flush:()=>(e=``,t=!1,n=``,r=[],[])}},St=async(e,t)=>{if(t<=0)return`deadline`;let n=null,r=new Promise(e=>{n=setTimeout(e,t,`deadline`)});try{return await Promise.race([e.read(),r])}finally{n!=null&&clearTimeout(n)}},Ct=async(e,t)=>{let n=e.getReader(),r=new TextDecoder(`utf-8`),i=xt(),a=[],o=0,s=async e=>(await n.cancel().catch(O),{events:a,truncated:!0,reason:e,discardedIncomplete:!1});for(;;){let e=await St(n,t.deadlineAt-t.now());if(e===`deadline`)return await s(`deadline`);if(e.done){a.push(...i.push(r.decode()));let e=i.hasPendingIncomplete();return i.flush(),{events:a,truncated:!1,reason:`end`,discardedIncomplete:e}}if(o+=e.value.byteLength,o>t.maxBytes)return await s(`max_bytes`);if(a.push(...i.push(r.decode(e.value,{stream:!0}))),a.length>t.maxEvents)return a.length=t.maxEvents,await s(`max_events`)}},wt=e=>{try{return JSON.parse(e)}catch{return e}},Tt=`application/json`,Et=`text/event-stream`,Dt=`x-request-id`,Ot={headersTimeoutMs:6e4,maxJsonBytes:16777216,sseTotalMs:9e5,sseMaxEvents:1e4,sseMaxBytes:33554432,maxRetryAfterSeconds:30},kt=(e,t)=>{if(e.origin!==t.origin)throw new x(`network`,`refusing to send credentials outside the configured API origin`)},At=(e,t)=>{let n=`${Ne(e.pathname)}${t.path}`,r=new URL(n,e);if(r.pathname!==n)throw new x(`network`,`refusing to send a request whose path was normalized`);for(let[e,n]of t.query)r.searchParams.append(e,n);return kt(r,e),r},jt=e=>{switch(e){case`json`:case`empty`:return Tt;case`sse`:return Et;case`binary`:return`*/*`;default:throw Error(`unknown response kind ${String(e)}`)}},Mt=async(e,t)=>{let n=Number(e.headers.get(`content-length`));if(Number.isFinite(n)&&n>t)throw await e.body?.cancel().catch(O),new x(`response_too_large`,`response exceeds ${t} bytes`,e.status);if(e.body==null)return/* @__PURE__ */ new Uint8Array;let r=e.body.getReader(),i=[],a=0;for(;;){let{done:n,value:o}=await r.read();if(n)break;if(a+=o.byteLength,a>t)throw await r.cancel().catch(O),new x(`response_too_large`,`response exceeds ${t} bytes`,e.status);i.push(o)}let o=new Uint8Array(a),s=0;for(let e of i)o.set(e,s),s+=e.byteLength;return o},Nt=e=>new TextDecoder(`utf-8`).decode(e),Pt=(e,t)=>(e.headers.get(`content-type`)??``).toLowerCase().startsWith(t),Ft=e=>{if(e==null)return null;let t=Number(e);return Number.isInteger(t)&&t>=0?t:null},It=(e,t)=>{let n=e[t];return typeof n==`string`?n:null},Lt=e=>typeof e==`object`&&!!e&&!Array.isArray(e),Rt=async(e,t)=>{let n=e.headers.get(Dt),r=Ft(e.headers.get(`retry-after`)),i;try{i=Nt(await Mt(e,t))}catch{i=``}if(Pt(e,Tt))try{let t=JSON.parse(i),a=Lt(t)&&Lt(t.error)?t.error:null;if(a!=null)return new b({status:e.status,code:It(a,`code`),message:It(a,`message`)??e.statusText,detail:It(a,`detail`),requestId:It(a,`requestId`)??n,retryAfterSeconds:r})}catch{}return new b({status:e.status,code:null,message:i.slice(0,500)||e.statusText||`HTTP error`,detail:null,requestId:n,retryAfterSeconds:r})},zt=e=>{if(e==null)return null;let t=/filename\*=UTF-8''([^;]+)/i.exec(e);if(t?.[1]!=null)try{return decodeURIComponent(t[1].trim())}catch{return null}return/filename="?([^";]+)"?/i.exec(e)?.[1]?.trim()??null},Bt=e=>e instanceof x?e:e instanceof Error&&e.name===`AbortError`?new x(`timeout`,`the API did not respond in time`):new x(`network`,e instanceof Error?e.message:`network failure`),Vt=(e,t=Ot)=>{let{config:n,auth:r,clientWorkspaceId:i,userAgent:a,fetch:o,now:s,sleep:c,logger:l}=e,u=async(e,r,{signal:c,canSend:l,metrics:u})=>{B(c);let d=At(n.baseUrl,e),f=new Headers({accept:jt(e.responseKind)});a!=null&&f.set(`user-agent`,a),i!=null&&f.set(`x-flyle-client-workspace`,i),r!=null&&f.set(`authorization`,`Bearer ${r}`);let p;e.hasBody&&(p=JSON.stringify(e.body??{}),f.set(`content-type`,Tt));let m=new AbortController,h=setTimeout(()=>m.abort(),t.headersTimeoutMs),g;try{if(l?.()===!1)throw new x(`aborted`,`the API request was cancelled before sending`);u!=null&&(u.attempts+=1,u.requestBytes+=p==null?0:new TextEncoder().encode(p).byteLength),g=await o(d,{method:e.method,headers:f,...p==null?{}:{body:p},redirect:`manual`,signal:c==null?m.signal:AbortSignal.any([m.signal,c])})}catch(e){throw clearTimeout(h),B(c),Bt(e)}let _=g.body;if(u!=null&&_!=null){let e=g,t=_.getReader(),n=new ReadableStream({async pull(e){try{let{done:n,value:r}=await t.read();if(n){t.releaseLock(),e.close();return}u.responseBytes+=r.byteLength,e.enqueue(r)}catch(n){t.releaseLock(),e.error(n)}},async cancel(e){try{await t.cancel(e)}finally{t.releaseLock()}}},{highWaterMark:0});g=new Response(n,{status:e.status,statusText:e.statusText,headers:e.headers})}if(g.type===`opaqueredirect`||g.status>=300&&g.status<400)throw clearTimeout(h),await g.body?.cancel().catch(O),new x(`redirect_not_followed`,`redirect responses are not followed`,g.status);if(!g.ok)try{throw await Rt(g,t.maxJsonBytes)}finally{clearTimeout(h)}let v=g.headers.get(Dt);switch(e.responseKind){case`json`:try{if(!Pt(g,Tt))throw await g.body?.cancel().catch(O),new x(`unexpected_content_type`,`expected an application/json response`,g.status);let e=Nt(await Mt(g,t.maxJsonBytes)),n;try{n=JSON.parse(e)}catch{throw new x(`invalid_json`,`the response body is not valid JSON`,g.status)}return{kind:`json`,status:g.status,requestId:v,body:n}}catch(e){throw B(c),Bt(e)}finally{clearTimeout(h)}case`empty`:return clearTimeout(h),await g.body?.cancel().catch(O),{kind:`empty`,status:g.status,requestId:v};case`sse`:{if(clearTimeout(h),!Pt(g,Et))throw await g.body?.cancel().catch(O),new x(`unexpected_content_type`,`expected a text/event-stream response`,g.status);if(g.body==null)throw new x(`empty_body`,`the stream has no body`,g.status);let e=await Ct(g.body,{deadlineAt:s()+t.sseTotalMs,maxEvents:t.sseMaxEvents,maxBytes:t.sseMaxBytes,now:s});return B(c),{kind:`sse`,status:g.status,requestId:v,...e}}case`binary`:if(clearTimeout(h),g.body==null)throw new x(`empty_body`,`the download has no body`,g.status);return{kind:`binary`,status:g.status,requestId:v,contentType:g.headers.get(`content-type`),fileName:zt(g.headers.get(`content-disposition`)),body:g.body};default:throw e.responseKind,Error(`unknown response kind ${String(e.responseKind)}`)}},d=async(e,n,r)=>{let{signal:i}=r,a=e.method===`GET`&&(e.responseKind===`json`||e.responseKind===`empty`);try{return await u(e,n,r)}catch(o){if(B(i),!a)throw o;if(o instanceof b&&o.info.status===429&&o.info.retryAfterSeconds!=null&&o.info.retryAfterSeconds<=t.maxRetryAfterSeconds)return l.warn(`rate limited; retrying once`,{path:e.path,retryAfterSeconds:o.info.retryAfterSeconds}),await yt(o.info.retryAfterSeconds*1e3,i,c),await u(e,n,r);if(o instanceof x&&o.kind===`network`)return l.warn(`network failure; retrying once`,{path:e.path}),await u(e,n,r);throw o}};return{request:async(e,t,n,i)=>{B(t);let a={signal:t,canSend:n,metrics:i};if(r==null)return d(e,null,a);let o=await r.getAccessToken();try{return await d(e,o,a)}catch(n){if(!(n instanceof b)||n.info.status!==401)throw n;B(t);let i=await r.refreshAfterRejection(o);if(B(t),i===o)throw n;return l.warn(`access token rejected; retrying once with a refreshed token`,{path:e.path}),await d(e,i,a)}}}},Ht=`{tenantName}`,Ut={...Ot,headersTimeoutMs:2e4},Wt=/* @__PURE__ */ P({authorizationUrlTemplate:/* @__PURE__ */ I(/* @__PURE__ */ F(),/* @__PURE__ */ be(Ht))}),Gt=/* @__PURE__ */ P({accessToken:/* @__PURE__ */ I(/* @__PURE__ */ F(),/* @__PURE__ */ N(Ie)),accessTokenExpiresAt:/* @__PURE__ */ I(/* @__PURE__ */ F(),/* @__PURE__ */ xe()),refreshToken:/* @__PURE__ */ I(/* @__PURE__ */ F(),/* @__PURE__ */ N(Le)),refreshTokenExpiresAt:/* @__PURE__ */ I(/* @__PURE__ */ F(),/* @__PURE__ */ xe()),tenantName:/* @__PURE__ */ I(/* @__PURE__ */ F(),/* @__PURE__ */ ye(Ze)),loginConnectionId:/* @__PURE__ */ I(/* @__PURE__ */ F(),/* @__PURE__ */ N(Re))}),Kt=(e,t,n)=>{let r=/* @__PURE__ */ Me(e,t);if(!r.success)throw new x(`invalid_json`,`the login connection response does not match the contract`,n);return r.output},qt=async e=>{let t=await e.request({method:`GET`,path:`/v0/login-connections/metadata`,query:[],hasBody:!1,body:null,responseKind:`json`});if(t.kind!==`json`)throw new x(`unexpected_content_type`,`not JSON`);return Kt(Wt,t.body,t.status).authorizationUrlTemplate},Jt=async(e,t)=>{let n;try{n=await e.request({method:`POST`,path:`/v0/login-connections/token`,query:[],hasBody:!0,body:t,responseKind:`json`})}catch(e){throw e instanceof b&&e.info.code===`invalid_grant`?new Ue(`the authorization code or refresh token is no longer valid`):e}if(n.kind!==`json`)throw new x(`unexpected_content_type`,`not JSON`);return Kt(Gt,n.body,n.status)},Yt=(e,t,n)=>{if(e.apiBaseUrl!==t.href||e.tenantName!==n)throw new D(`credentials_mismatch`,`保存されたログイン(環境 ${z(new URL(e.apiBaseUrl))} / テナント ${e.tenantName})が、この作業ディレクトリの接続先(環境 ${z(t)} / テナント ${n})と一致しません。この作業ディレクトリで \`npx @flyle/ai-contact-center-mcp@latest login\` を実行し直してください`)},Xt=(e,t)=>({apiBaseUrl:t.href,tenantName:e.tenantName,loginConnectionId:e.loginConnectionId,accessToken:e.accessToken,accessTokenExpiresAt:e.accessTokenExpiresAt,refreshToken:e.refreshToken,refreshTokenExpiresAt:e.refreshTokenExpiresAt}),Zt=e=>{let{credentialsFile:t,baseUrl:n,tenantName:r,tokenClient:i,now:a}=e,o=null,s=null,c=[],l=(...e)=>{c.push(...e),c.splice(0,Math.max(0,c.length-8))},u=async()=>{let e=await lt(t);if(e==null||Date.parse(e.refreshTokenExpiresAt)<=a())throw new D(`login_required`,He);return Yt(e,n,r),e},d=e=>e-a()>6e4,f=a=>vt(t,e.lock,async()=>{let e=await u();l(e.accessToken,e.refreshToken);let s=Date.parse(e.accessTokenExpiresAt);if(e.accessToken!==a&&d(s))return o={token:e.accessToken,expiresAt:s},e.accessToken;let c;try{c=await Jt(i,{grant_type:`refresh_token`,refresh_token:e.refreshToken})}catch(e){throw e instanceof Ue?(await ft(t),new D(`login_required`,He)):e}if(l(c.accessToken,c.refreshToken),c.tenantName!==r)throw await ft(t),new D(`login_required`,`ログインの更新で、設定と違うテナント(${c.tenantName})の応答を受け取ったため、保存したログイン情報を破棄しました。${He}`);return await dt(t,Xt(c,n)),o={token:c.accessToken,expiresAt:Date.parse(c.accessTokenExpiresAt)},c.accessToken}),p=e=>(s??=f(e).finally(()=>{s=null}),s);return{getAccessToken:()=>o!=null&&d(o.expiresAt)?Promise.resolve(o.token):p(o?.token??null),refreshAfterRejection:e=>o!=null&&o.token!==e?Promise.resolve(o.token):(o=null,p(e)),assertLoggedIn:async()=>{o??await u()},secrets:()=>c,whenIdle:async()=>{await Promise.allSettled(s==null?[]:[s])}}},Qt=(e,t)=>e===`darwin`?[`open`,[t]]:e===`win32`?[`rundll32`,[`url.dll,FileProtocolHandler`,t]]:[`xdg-open`,[t]],$t=(e,t=process.platform)=>{let[n,r]=Qt(t,e),i=v(n,r,{stdio:`ignore`,detached:!0,shell:!1});i.on(`error`,O),i.unref()},en=`flyle-ai-contact-center-mcp/${Pe}`,tn=(e,t=Ot)=>{let{workspaceId:n,...r}=e;return Vt({...r,clientWorkspaceId:n,userAgent:en},t)},nn=`.flyle-ai-contact-center-mcp`,rn=/* @__PURE__ */ P({tenantName:/* @__PURE__ */ F(),apiBaseUrl:/* @__PURE__ */ Oe(/* @__PURE__ */ De(/* @__PURE__ */ F()),null)}),an=e=>_.join(e,nn,`workspace.json`),on=e=>e instanceof Error&&k(e,`code`)&&e.code===`ENOENT`,sn=e=>e instanceof Error&&k(e,`code`)&&e.code===`EEXIST`,cn=async e=>{let t;try{t=await d(an(e),`utf8`)}catch(e){if(on(e))return null;throw e}let n;try{n=JSON.parse(t)}catch{n=null}let r=/* @__PURE__ */ Me(rn,n);if(!r.success)throw new E(`corrupted`,`${an(e)} is not a valid workspace binding. Inspect it manually; the MCP server never overwrites it.`);return r.output},ln=async e=>(await cn(e))?.tenantName??null,un=(e,t,n)=>new E(`tenant_mismatch`,`${e} is dedicated to tenant "${t}", not "${n}". Use a separate directory (and a separate Claude Code session) for each tenant.`),dn=(e,t,n)=>new E(`environment_mismatch`,`${e} is dedicated to the API ${new URL(t).host}, not ${new URL(n).host}. Use a separate directory for each environment.`),fn=e=>{let t=[],n=_.dirname(e);for(;n!==_.dirname(n);)t.push(n),n=_.dirname(n);return t.push(n),t},pn=async(e,t)=>{let n=await Promise.all(fn(e).map(async e=>({dir:e,tenant:await ln(e)})));for(let{dir:e,tenant:r}of n)if(r!=null&&r!==t)throw un(e,r,t)},mn=(e,t)=>i(`sha256`).update(`${e.hostname}\0${e.username}\0${t}`).digest(`base64url`).slice(0,32),hn=(e,t)=>{let n={version:2,tenantName:e.tenantName,apiBaseUrl:e.apiBaseUrl,boundAt:t.toISOString()};return`${JSON.stringify(n,null,2)}\n`},gn=async(e,t,n)=>{let r=an(e),i=`${r}.${a(8).toString(`hex`)}.tmp`;try{await g(i,hn(t,n),{flag:`wx`}),await p(i,r)}finally{await m(i,{force:!0})}},_n=async(e,t,n,r)=>{await l(_.join(e,nn),{recursive:!0});try{await g(an(e),hn(t,n),{flag:`wx`});return}catch(e){if(!sn(e))throw e}let i=await cn(e);if(i?.tenantName!==t.tenantName)throw un(e,i?.tenantName??`(unknown)`,t.tenantName);if(i.apiBaseUrl!==t.apiBaseUrl){if(i.apiBaseUrl==null&&r)await gn(e,t,n);else throw dn(e,i.apiBaseUrl??`(unknown)`,t.apiBaseUrl)}},vn=async e=>{let t=await f(e.cwd);if(t===await f(e.homeDir).catch(()=>e.homeDir)||t===_.parse(t).root)throw new E(`shared_directory`,`${t} is shared by everything you do and cannot be dedicated to one tenant. Create a directory for this tenant (e.g. ~/flyle-cs/<tenant>) and start the session there.`);return t},yn=async(e,t)=>{let n=await vn(e);return await pn(n,t.tenantName),await _n(n,t,e.now(),!0),{...t,root:n,workspaceId:mn(e,n)}},bn=async e=>{let t=await vn(e),n=await cn(t);return n?.apiBaseUrl==null?null:(await pn(t,n.tenantName),{tenantName:n.tenantName,apiBaseUrl:n.apiBaseUrl,root:t,workspaceId:mn(e,t)})},xn=async(e,t)=>{await _n(e.root,e,t,!1)},Sn=(e,t,n)=>new E(`outside_workspace`,`${n} (${t}) must be inside the tenant workspace ${e}; a shared location could mix files between tenants.`),Cn=async(e,t)=>{if(!t.startsWith(`${e.root}${_.sep}`))throw Sn(e.root,t,`the file`);let n=[];for(let r=_.dirname(t);r!==e.root;r=_.dirname(r))n.push(r);let r=await Promise.all(n.map(async e=>({dir:e,tenant:await ln(e)})));for(let{dir:t,tenant:n}of r)if(n!=null&&n!==e.tenantName)throw un(t,n,e.tenantName)},wn=(e,t,n)=>tn({config:{baseUrl:t},auth:null,workspaceId:n,fetch:e.fetch,now:e.now,sleep:e.sleep,logger:e.logger},Ut),Tn=async e=>{let t=await bn(e.workspaceEnv);if(t==null)return null;let n=st(e.credentialsDir,t.workspaceId),r=await lt(n);return r==null?null:{workspace:t,file:n,stored:r,baseUrl:Ye(r.apiBaseUrl,et(e.env),`${n} の apiBaseUrl`)}},En=(e,t)=>{let n=Zt({credentialsFile:t.file,baseUrl:t.baseUrl,tenantName:t.stored.tenantName,tokenClient:wn(e,t.baseUrl,t.workspace.workspaceId),now:e.now,lock:e.lock});return{auth:n,client:tn({config:{baseUrl:t.baseUrl},auth:n,workspaceId:t.workspace.workspaceId,fetch:e.fetch,now:e.now,sleep:e.sleep,logger:e.logger})}},Dn=(e,t)=>`/v0/tenants/${encodeURIComponent(e)}${t}`,On=e=>e instanceof R||e instanceof D||e instanceof L||e instanceof E?e.message:e instanceof b?`公開 API がエラーを返しました(${String(e.info.status)} ${e.info.code??`http_error`}): ${e.info.message}`:e instanceof x?`公開 API と通信できませんでした(${e.kind}): ${e.message}`:e instanceof Error?e.message:String(e),V=(e,t)=>{let n=e;for(let e of t)e.length!==0&&(n=n.split(e).join(`[redacted]`));return n},kn=async(e,t)=>{let{client:n}=En(e,t);try{await n.request({method:`DELETE`,path:Dn(t.stored.tenantName,`/current-login-connection`),query:[],hasBody:!1,body:null,responseKind:`empty`})}catch(e){if(!(e instanceof D&&e.kind===`login_required`||e instanceof b&&e.info.status===401))throw e}},An=async e=>{let t=await Tn(e);t==null?e.out(`この作業ディレクトリにはログイン情報がありません。`):(await kn(e,t),await vt(t.file,e.lock,()=>ft(t.file)),e.out(`ログアウトしました(環境 ${z(t.baseUrl)} / テナント ${t.stored.tenantName})。`))},jn=`127.0.0.1`,Mn=`/callback`,Nn=e=>{try{let{values:t}=te({args:[...e],options:{tenant:{type:`string`},"api-base-url":{type:`string`}},strict:!0,allowPositionals:!1});return{tenant:t.tenant??null,apiBaseUrl:t[`api-base-url`]??null}}catch(e){throw new R(`${e instanceof Error?e.message:String(e)}\n使い方: login [--tenant <テナント名>] [--api-base-url <URL>]`)}},Pn=(e,t,n)=>e==null?t?.apiBaseUrl==null?Ye(`https://api.flygate.flyle.io`,n,`既定の接続先`):Ye(t.apiBaseUrl,n,`作業ディレクトリの接続先`):Ye(e,n,`--api-base-url`),Fn=(e,t)=>{if(e!=null)return Qe(e,`--tenant`);if(t!=null)return t.tenantName;throw new R("テナントを決められません。`login --tenant <テナント名>` で指定してください(作業ディレクトリをそのテナント専用にします)。")},In=()=>a(32).toString(`base64url`),Ln=e=>i(`sha256`).update(e).digest(`base64url`),Rn=(e,t)=>{let n=Buffer.from(e),r=Buffer.from(t);return n.length===r.length&&o(n,r)},zn=(e,t,n)=>{let r;try{r=new URL(e.replaceAll(Ht,t))}catch{throw new R(`公開 API が返した同意画面の URL が不正です。`)}let i=r.protocol===`http:`&&n&&(Je(r.hostname)||r.hostname.endsWith(`.localhost`));if(r.protocol!==`https:`&&!i)throw new R(`公開 API が返した同意画面の URL が https ではありません。`);return r},Bn=/[\p{Cc}\p{Cf}]/gu,Vn=(e,t)=>{let n=``;for(let r of e){if(n.length+r.length>t)break;n+=r}return n},Hn=(e,t)=>{let n=e=>e.replaceAll(Bn,``);return Vn(`${n(e)} / ${n(_.basename(t))}`,255)},Un=/* @__PURE__ */ je([/* @__PURE__ */ P({error:/* @__PURE__ */ I(/* @__PURE__ */ F(),/* @__PURE__ */ N(/^[a-z_]{1,64}$/)),state:/* @__PURE__ */ F()}),/* @__PURE__ */ P({code:/* @__PURE__ */ I(/* @__PURE__ */ F(),/* @__PURE__ */ N(Fe)),state:/* @__PURE__ */ F()})]),Wn={success:`ログインが完了しました。このタブは閉じてかまいません。`,denied:`ログインを中止しました。このタブは閉じてかまいません。`,failure:`ログインを完了できませんでした。このタブを閉じて、ターミナルの表示を確認してください。`,handled:`このログインは処理済みです。このタブは閉じてかまいません。`,unknown:`実行中のログインの応答として確認できませんでした。ログインを続ける場合は、ターミナルに表示された URL から同意画面を開き直してください。`,rejected:`この宛先への要求は受け付けていません。`},Gn=(e,t,n)=>{e.writeHead(t,{"content-type":`text/html; charset=utf-8`,"cache-control":`no-store`,"content-security-policy":`default-src 'none'`,"referrer-policy":`no-referrer`}),e.end(`<!doctype html><html lang="ja"><meta charset="utf-8"><title>Flyle AIコンタクトセンター</title><p>${Wn[n]}</p></html>`)},Kn=e=>new Promise((t,n)=>{e.once(`error`,n),e.listen(0,jn,()=>{let r=e.address();r==null||typeof r==`string`?n(new R(`ログイン用の待受ポートを開けませんでした。`)):t(r.port)})}),qn=async(e,t,n)=>{let r=!1,i=0,a=null,o=Promise.withResolvers(),s=e=>{r=!0,o.reject(new R(e))},c=(e,t,r)=>{i+=1,Gn(e,400,t),n(r)},l=ee((t,n)=>{if(a==null||t.headers.host!==a){c(n,`rejected`,`ログイン用の待受に、想定外の宛先(Host ヘッダ)の要求が届いたため拒否しました。ログインは待ち続けています。`);return}let i=new URL(t.url??`/`,`http://${a}`);if(t.method!==`GET`||i.pathname!==Mn){n.writeHead(404).end();return}if(r){Gn(n,410,`handled`);return}let l=i.searchParams.get(`state`);if(l==null||!Rn(l,e)){c(n,`unknown`,`このログインのものではない応答(state が一致しない、または無い)を受け取ったため無視しました。ブラウザで同意を続けてください。`);return}let u=/* @__PURE__ */ Me(Un,fe(i.searchParams));if(!u.success){Gn(n,400,`failure`),s(`同意画面からの応答の形式が正しくありません(認可コードがない、または形式が違います)。もう一度 login を実行してください。`);return}let d=u.output;if(k(d,`error`)){let e=d.error===`access_denied`;Gn(n,200,e?`denied`:`failure`),s(e?`ブラウザでログインが拒否されました。`:`同意画面がエラーを返しました(${d.error})。`);return}r=!0;let f=!1;o.resolve({code:d.code,finish:e=>{f||(f=!0,Gn(n,e===`success`?200:400,e))}})}),u=await Kn(l);a=`${jn}:${String(u)}`;let d=setTimeout(()=>{if(r)return;let e=i===0?``:`(このログインのものではない要求を ${String(i)} 件受け取り、無視しました)`;s(`${String(Math.round(t/1e3/60))} 分以内にブラウザでの同意が完了しませんでした${e}。もう一度 login を実行してください。`)},t);return{port:u,received:o.promise,close:()=>new Promise(e=>{clearTimeout(d),l.closeAllConnections(),l.close(()=>e())})}},Jn=`その接続は最長 30 日間有効なまま残る可能性があります。管理画面の「設定 → 外部ツール接続」から切断してください。`,Yn=async(e,t)=>{if(t!=null)try{await kn(e,t)}catch(n){e.err(`以前のログイン(接続 ID ${t.stored.loginConnectionId})をサーバーで切断できませんでした(${On(n)})。${Jn}`)}},Xn=async e=>{try{return await Tn(e)}catch(t){if(!(t instanceof D&&t.kind===`login_required`)&&!(t instanceof L))throw t;return e.err(`以前のログイン情報を読めなかったため、新しいログインで上書きします(${On(t)})。以前の接続はサーバーで切断できていません。${Jn}`),null}},Zn=async(e,t,n,r)=>{let i=st(e.credentialsDir,t.workspaceId);await vt(i,e.lock,()=>dt(i,Xt(r,n)))},Qn=e=>({getAccessToken:()=>Promise.resolve(e),refreshAfterRejection:()=>Promise.resolve(e),secrets:()=>[e]}),$n=async(e,t,n,r)=>{let i=tn({config:{baseUrl:t},auth:Qn(r.accessToken),workspaceId:n.workspaceId,fetch:e.fetch,now:e.now,sleep:e.sleep,logger:e.logger});try{return await i.request({method:`DELETE`,path:Dn(r.tenantName,`/current-login-connection`),query:[],hasBody:!1,body:null,responseKind:`empty`}),!0}catch{return!1}},er=async e=>{let t=Nn(e.argv),n=et(e.env),r=await cn(e.workspaceEnv.cwd),i=Pn(t.apiBaseUrl,r,n),a=Fn(t.tenant,r),o=await yn(e.workspaceEnv,{tenantName:a,apiBaseUrl:i.href}),s=await Xn(e),c=wn(e,i,o.workspaceId),l=zn(await qt(c),a,n),u=In(),d=In(),f=[u,d],p=await qn(d,e.callbackTimeoutMs,e.err),m=null;try{let t=`http://${jn}:${String(p.port)}${Mn}`;l.searchParams.set(`tenant_name`,a),l.searchParams.set(`code_challenge`,Ln(u)),l.searchParams.set(`code_challenge_method`,`S256`),l.searchParams.set(`redirect_uri`,t),l.searchParams.set(`state`,d),l.searchParams.set(`connection_name`,Hn(e.workspaceEnv.hostname,o.root)),l.searchParams.set(`api_origin`,i.origin),e.err(`環境 ${z(i)} のテナント「${a}」にログインします。ブラウザで同意画面を開きます。\n開かない場合は、次の URL をブラウザで開いてください:\n${l.href}`),e.openBrowser(l.href),m=await p.received,f.push(m.code);let n;try{n=await Jt(c,{grant_type:`authorization_code`,code:m.code,code_verifier:u,redirect_uri:t})}catch(e){throw e instanceof Ue?new R(`認可コードを交換できませんでした。もう一度 login を実行してください。`):e}if(f.push(n.accessToken,n.refreshToken),n.tenantName!==a){let t=await $n(e,i,o,n);throw new R(`ブラウザで同意したテナント(${n.tenantName})が、ログインしようとしたテナント(${a})と違います。ログイン情報は保存していません。`+(t?`そのテナントに作られた接続は切断しました。`:`テナント ${n.tenantName} の管理画面の「設定 → 外部ツール接続」から、作られた接続を切断してください。`))}await xn(o,new Date(e.now())),await Yn(e,s),await Zn(e,o,i,n),m.finish(`success`),e.out(`ログインしました(環境 ${z(i)} / テナント ${a} / 作業ディレクトリ ${o.root})。`)}catch(e){throw m?.finish(`failure`),new R(V(On(e),f))}finally{await p.close()}},tr=/* @__PURE__ */ P({currentUser:/* @__PURE__ */ P({name:/* @__PURE__ */ De(/* @__PURE__ */ F()),email:/* @__PURE__ */ De(/* @__PURE__ */ F()),roles:/* @__PURE__ */ Te(/* @__PURE__ */ P({roleName:/* @__PURE__ */ F()})),currentLoginConnection:/* @__PURE__ */ P({name:/* @__PURE__ */ F(),expiresAt:/* @__PURE__ */ I(/* @__PURE__ */ F(),/* @__PURE__ */ xe())})})}),nr="ログインしていません。作業ディレクトリで `npx @flyle/ai-contact-center-mcp@latest login` を実行してください",rr=async e=>{let t=await Tn(e);if(t==null)throw new R(nr);e.out(`環境: ${z(t.baseUrl)}`),e.out(`テナント: ${t.stored.tenantName}`);let{client:n}=En(e,t),r;try{r=await n.request({method:`GET`,path:Dn(t.stored.tenantName,`/current-user`),query:[],hasBody:!1,body:null,responseKind:`json`})}catch(e){throw e instanceof D&&e.kind===`login_required`?new R(`ログインの有効期限が切れています。${nr}`):e}let i=/* @__PURE__ */ Me(tr,r.kind===`json`?r.body:null);if(!i.success)throw new x(`invalid_json`,`the current user response does not match the contract`);let a=i.output.currentUser,o=a.email==null?``:` <${a.email}>`;e.out(`ユーザー: ${a.name??`(名前未設定)`}${o}`),e.out(`ロール: ${a.roles.map(e=>e.roleName).join(`, `)||`(なし)`}`),e.out(`接続名: ${a.currentLoginConnection.name}`),e.out(`ログインの有効期限: ${a.currentLoginConnection.expiresAt}(使うたびに延長。ログインから最長 90 日)`)},ir=async e=>{let t=await u(e,ne.O_RDONLY|ne.O_NONBLOCK|ne.O_NOFOLLOW);try{let e=await t.stat();if(!e.isFile())throw new C(`not_a_file`,`only regular files can be read`);return{handle:t,size:e.size}}catch(e){throw await t.close(),e}},ar=async(e,t)=>{let{handle:n,size:r}=await ir(e);try{if(r>t)throw new C(`too_large`,`the file exceeds ${String(t)} bytes`);let e=[],i=0;for(;;){let r=Buffer.allocUnsafe(Math.min(1048576,t-i+1)),{bytesRead:a}=await n.read(r,0,r.length,null);if(a===0)break;if(i+=a,i>t)throw new C(`too_large`,`the file exceeds ${String(t)} bytes`);e.push(r.subarray(0,a))}return Buffer.concat(e,i)}finally{await n.close()}},or=(e,t)=>e===t||e.startsWith(`${t}${_.sep}`),sr=async(e,t,n,r)=>{let i=_.resolve(n,e),a;try{a=await f(i)}catch{throw new C(`not_found`,`file not found: ${e}`)}if(!(await Promise.all(t.map(e=>f(e).catch(()=>e)))).some(e=>or(a,e)))throw new C(`outside_roots`,`the path is outside the configured file roots`);return await Cn(r,a),a},cr=/* @__PURE__ */ new Map([[`.md`,`text/markdown`],[`.markdown`,`text/markdown`],[`.txt`,`text/plain`],[`.csv`,`text/csv`],[`.json`,`application/json`],[`.html`,`text/html`],[`.htm`,`text/html`],[`.pdf`,`application/pdf`],[`.docx`,`application/vnd.openxmlformats-officedocument.wordprocessingml.document`],[`.xlsx`,`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`],[`.pptx`,`application/vnd.openxmlformats-officedocument.presentationml.presentation`],[`.png`,`image/png`],[`.jpg`,`image/jpeg`],[`.jpeg`,`image/jpeg`],[`.zip`,`application/zip`]]),lr=e=>cr.get(_.extname(e).toLowerCase())??`application/octet-stream`,ur=e=>new Promise((t,n)=>{let r=i(`sha256`);e.on(`data`,e=>r.update(e)).on(`error`,n).on(`end`,()=>t(r.digest()))}),dr=async(e,t,n,r)=>{let i=await sr(e,t,n,r),{handle:a,size:o}=await ir(i),s;try{s=await ur(a.createReadStream())}finally{await a.close()}let c=_.basename(i);return{path:i,fileName:c,sizeBytes:o,sha256Hex:s.toString(`hex`),sha256Base64:s.toString(`base64`),mimeType:lr(c)}},fr=(e,t=9e5,n=1e3)=>{let r=/* @__PURE__ */ new Map,i=()=>{let t=e();for(let[e,n]of r)n.expiresAt<=t&&r.delete(e)};return{get size(){return r.size},register:(a,o,s)=>{for(i();r.size>=n;){let e=r.keys().next();if(e.done)break;r.delete(e.value)}r.delete(a),r.set(a,{kind:o,headers:s,expiresAt:e()+t})},take:(t,n)=>{let i=r.get(t);if(i?.kind!==n)throw new S(`unknown_url`,`the URL was not returned by a recent API call for this kind of transfer`);if(r.delete(t),i.expiresAt<=e())throw new S(`expired_url`,`the signed URL has expired; call the API again to get a new one`);return i}}},pr=(e,t)=>{let n;try{n=new URL(e)}catch{throw new S(`not_allowed_host`,`the transfer URL is not a valid URL`)}let r=t.allowInsecureHttp&&Je(n.hostname);if(n.protocol!==`https:`&&!(n.protocol===`http:`&&r))throw new S(`insecure_url`,`transfer URLs must use https`);if(n.username!==``||n.password!==``)throw new S(`not_allowed_host`,`transfer URLs must not contain credentials`);let i=n.hostname.toLowerCase();if(!(r||t.storageHostSuffixes.some(e=>e.startsWith(`.`)?i.endsWith(e):i===e)))throw new S(`not_allowed_host`,`the host ${i} is not an allowed storage host`);return n},mr=4096,hr=async e=>{if(e.body==null)return``;let t=e.body.getReader(),n=[],r=0;try{for(;r<mr;){let{done:e,value:i}=await t.read();if(e)break;n.push(i),r+=i.byteLength}}catch{}finally{await t.cancel().catch(O)}return new TextDecoder(`utf-8`).decode(Buffer.concat(n)).slice(0,mr)},gr=e=>e instanceof S?e:e instanceof Error&&(e.name===`AbortError`||e.name===`TimeoutError`)?new S(`timeout`,`the storage did not respond in time`):new S(`network`,e instanceof Error?e.message:`network failure`),_r=async e=>{if(ue(e.headers).some(e=>e.toLowerCase()===`authorization`))throw new S(`invalid_headers`,`transfer headers must not include authorization`);let t;try{t=await ar(e.filePath,e.maxBytes)}catch(e){throw e instanceof C&&(e.kind===`not_a_file`||e.kind===`too_large`)?new S(e.kind,e.kind===`not_a_file`?`only regular files can be uploaded`:e.message):e}let n;try{n=await e.fetch(e.url,{method:`PUT`,headers:e.headers,body:t,redirect:`manual`,signal:AbortSignal.timeout(e.timeoutMs)})}catch(e){throw gr(e)}if(n.status>=300&&n.status<400)throw await n.body?.cancel().catch(O),new S(`redirect_not_followed`,`redirect responses are not followed`,n.status);if(!n.ok)throw new S(`http_error`,`upload failed: ${(await hr(n)).slice(0,300)}`,n.status);return await n.body?.cancel().catch(O),{status:n.status,etag:n.headers.get(`etag`),bytes:t.byteLength}},vr=/[^A-Za-z0-9._-]/g,yr=(e,t)=>{let n=_.basename(e??``).replace(vr,`_`).replace(/^_+/,``).slice(0,120);return n===``||/^\.+$/.test(n)?t:n},br=e=>`${(/* @__PURE__ */ new Date()).toISOString().replaceAll(/[:.]/g,`-`)}-${a(3).toString(`hex`)}-${e}`,xr=async(e,t)=>{if(t<=0)return`timeout`;let n=null,r=new Promise(e=>{n=setTimeout(e,t,`timeout`)});try{return await Promise.race([e.read(),r])}finally{n!=null&&clearTimeout(n)}},Sr=async(e,t)=>{await l(t.outputDir,{recursive:!0});let n=_.join(t.outputDir,br(t.fileName)),r=await u(n,`wx`),a=i(`sha256`),o=e.getReader(),s=Date.now()+t.timeoutMs,c=0;try{for(;;){let e=await xr(o,s-Date.now());if(e===`timeout`)throw await o.cancel().catch(O),new S(`timeout`,`the download did not finish within ${t.timeoutMs} ms`);let{done:n,value:i}=e;if(n)break;if(c+=i.byteLength,c>t.maxBytes)throw await o.cancel().catch(O),new S(`too_large`,`the download exceeds ${t.maxBytes} bytes`);a.update(i),await r.write(i)}}catch(e){throw await r.close(),await h(n).catch(O),gr(e)}return await r.close(),{path:n,bytes:c,sha256Hex:a.digest(`hex`)}},Cr=async e=>{let t;try{t=await e.fetch(e.url,{method:`GET`,redirect:`manual`,signal:AbortSignal.timeout(e.timeoutMs)})}catch(e){throw gr(e)}if(t.status>=300&&t.status<400)throw await t.body?.cancel().catch(O),new S(`redirect_not_followed`,`redirect responses are not followed`,t.status);if(!t.ok)throw new S(`http_error`,`download failed: ${(await hr(t)).slice(0,300)}`,t.status);if(t.body==null)throw new S(`network`,`the download has no body`,t.status);return{...await Sr(t.body,{outputDir:e.outputDir,fileName:e.fileName,maxBytes:e.maxBytes,timeoutMs:e.timeoutMs}),status:t.status,contentType:t.headers.get(`content-type`)}},wr=(e,t,n,r)=>{let i={level:e,message:t,...n,time:(/* @__PURE__ */ new Date()).toISOString()};return V(JSON.stringify(i),r)},Tr=(e,t=e=>console.error(e))=>({info:(n,r)=>t(wr(`info`,n,r,e())),warn:(n,r)=>t(wr(`warn`,n,r,e())),error:(n,r)=>t(wr(`error`,n,r,e()))}),Er=[`GET`,`POST`,`PUT`,`PATCH`,`DELETE`],Dr=[`json`,`empty`,`sse`,`binary`],Or=[`upload`,`download`],kr=[`read`,`draft`],Ar=[`wav-pcm16`,`base64`],jr=[`pcm16le`,`base64`],H=e=>{throw new oe(e)},U=e=>e===null,W=e=>Array.isArray(e)&&e.every(e=>typeof e==`string`),Mr=e=>{if(!Array.isArray(e)||e.length===0)return!1;let t=0;for(let n of e){if(typeof n!=`number`||!Number.isInteger(n)||n<200||n>=300||n<=t)return!1;t=n}return!0},Nr=e=>typeof e==`string`&&Er.some(t=>t===e),Pr=e=>typeof e==`string`&&Dr.some(t=>t===e),Fr=e=>typeof e==`string`&&Or.some(t=>t===e),Ir=e=>typeof e==`string`&&kr.some(t=>t===e),Lr=(e,t)=>{if(U(e))return null;if(!A(e))return H(`${t}.transfer must be an object or null`);let{kind:n,urlPointer:r,headersPointer:i,namePointer:a}=e;return Fr(n)?typeof r==`string`?!U(i)&&typeof i!=`string`?H(`${t}.transfer.headersPointer is invalid`):!U(a)&&typeof a!=`string`?H(`${t}.transfer.namePointer is invalid`):{kind:n,urlPointer:r,headersPointer:i,namePointer:a}:H(`${t}.transfer.urlPointer is invalid`):H(`${t}.transfer.kind is invalid`)},Rr=e=>typeof e==`string`&&Ar.some(t=>t===e),zr=e=>typeof e==`string`&&jr.some(t=>t===e),Br=e=>typeof e==`number`&&Number.isInteger(e)&&e>0,Vr=(e,t)=>{if(U(e))return null;if(!A(e))return H(`${t} must be an object or null`);let{sampleRateHz:n,channels:r}=e;return Br(n)?Br(r)?{sampleRateHz:n,channels:r}:H(`${t}.channels is invalid`):H(`${t}.sampleRateHz is invalid`)},Hr=(e,t)=>{if(!A(e))return H(`${t} must be an object`);let{pointer:n,format:r,maxBytes:i,pcm:a}=e;if(typeof n!=`string`||!n.startsWith(`/`))return H(`${t}.pointer is invalid`);if(!Rr(r))return H(`${t}.format is invalid`);if(!Br(i))return H(`${t}.maxBytes is invalid`);let o=Vr(a,`${t}.pcm`);return r===`wav-pcm16`==(o!=null)?{pointer:n,format:r,maxBytes:i,pcm:o}:H(`${t}.pcm does not match the format`)},Ur=(e,t)=>{if(!A(e))return H(`${t} must be an object`);let{event:n,pointer:r,format:i,pcm:a,mediaType:o}=e;if(!U(n)&&typeof n!=`string`)return H(`${t}.event is invalid`);if(typeof r!=`string`||!r.startsWith(`/`))return H(`${t}.pointer is invalid`);if(!zr(i))return H(`${t}.format is invalid`);if(!U(o)&&typeof o!=`string`)return H(`${t}.mediaType is invalid`);let s=Vr(a,`${t}.pcm`);return i===`pcm16le`==(s!=null)?i===`base64`==(o!=null)?{event:n,pointer:r,format:i,pcm:s,mediaType:o}:H(`${t}.mediaType does not match the format`):H(`${t}.pcm does not match the format`)},Wr=(e,t)=>{if(U(e))return null;if(!A(e))return H(`${t}.inlineFiles must be an object or null`);let{input:n,output:r}=e;return!Array.isArray(n)||!Array.isArray(r)?H(`${t}.inlineFiles is invalid`):n.length===0&&r.length===0?H(`${t}.inlineFiles must declare input or output`):{input:n.map((e,n)=>Hr(e,`${t}.inlineFiles.input[${String(n)}]`)),output:r.map((e,n)=>Ur(e,`${t}.inlineFiles.output[${String(n)}]`))}},Gr=(e,t)=>{if(U(e))return null;if(!A(e))return H(`${t}.sseOutcome must be an object or null`);let{requiredEvents:n,terminalEvent:r,successPointer:i,successValue:a,failureEvents:o}=e;return W(n)?typeof r==`string`?U(i)&&U(a)?W(o)?{requiredEvents:n,terminalEvent:r,successPointer:i,successValue:a,failureEvents:o}:H(`${t}.sseOutcome.failureEvents is invalid`):typeof i!=`string`||!i.startsWith(`/`)?H(`${t}.sseOutcome.successPointer is invalid`):typeof a!=`string`&&typeof a!=`number`&&typeof a!=`boolean`?H(`${t}.sseOutcome.successValue is invalid`):W(o)?{requiredEvents:n,terminalEvent:r,successPointer:i,successValue:a,failureEvents:o}:H(`${t}.sseOutcome.failureEvents is invalid`):H(`${t}.sseOutcome.terminalEvent is invalid`):H(`${t}.sseOutcome.requiredEvents is invalid`)},Kr=(e,t)=>{let n=`operations[${t}]`;if(!A(e))return H(`${n} must be an object`);let{operationId:r,method:i,pathTemplate:a,summary:o,label:s,description:c,permission:l,effect:u,responseContainsSecret:d,responseKind:f,successStatuses:p,pathParams:m,queryParams:h,bodyFields:g,wholeBodyField:_,inputSchema:v,transfer:ee,inlineFiles:te,sseOutcome:ne}=e;return typeof r!=`string`||r===``?H(`${n}.operationId is invalid`):Nr(i)?typeof a!=`string`||!a.startsWith(`/`)?H(`${n}.pathTemplate is invalid`):typeof o==`string`?!U(s)&&typeof s!=`string`?H(`${n}.label is invalid`):!U(c)&&typeof c!=`string`?H(`${n}.description is invalid`):!U(u)&&!Ir(u)?H(`${n}.effect is invalid`):typeof d==`boolean`?Pr(f)?Mr(p)?W(m)?W(h)?!U(g)&&!W(g)?H(`${n}.bodyFields is invalid`):!U(_)&&typeof _!=`string`?H(`${n}.wholeBodyField is invalid`):g!=null&&_!=null?H(`${n} declares both bodyFields and wholeBodyField`):A(v)?{operationId:r,method:i,pathTemplate:a,summary:o,label:s,description:c,permission:l??null,effect:u,responseContainsSecret:d,responseKind:f,successStatuses:p,pathParams:m,queryParams:h,bodyFields:g,wholeBodyField:_,inputSchema:v,transfer:Lr(ee,n),inlineFiles:Wr(te,n),sseOutcome:Gr(ne,n)}:H(`${n}.inputSchema is invalid`):H(`${n}.queryParams is invalid`):H(`${n}.pathParams is invalid`):H(`${n}.successStatuses is invalid`):H(`${n}.responseKind is invalid`):H(`${n}.responseContainsSecret is invalid`):H(`${n}.summary is invalid`):H(`${n}.method is invalid`)},qr=e=>{if(!A(e))return H(`manifest must be an object`);let t=e.source;if(!A(t)||typeof t.title!=`string`||typeof t.version!=`string`)return H(`manifest.source is invalid`);let n=e.operations;if(!Array.isArray(n))return H(`manifest.operations must be an array`);let r=n.map((e,t)=>Kr(e,t));return new Set(r.map(e=>e.operationId)).size===r.length?{source:{title:t.title,version:t.version},operations:r}:H(`manifest.operations has duplicate operationId`)},Jr=new URL(`./manifest.json.br`,import.meta.url),Yr=(e=Jr)=>{let t=re(e),n;try{n=JSON.parse((e.pathname.endsWith(`.br`)?ie(t):t).toString(`utf8`))}catch{throw new oe(`manifest at ${e.pathname} is not valid JSON or brotli`)}return qr(n)},Xr=e=>typeof e==`string`?e:Array.isArray(e)&&e.every(e=>typeof e==`string`)?e.join(`, `):null,Zr={"tenant-root":e=>`${e}(テナント全体に対して)`,"any-resource":e=>`${e}(いずれかのエージェントで保持)`,"per-resource":e=>`${e}(対象エージェントに対して)`,"per-resource-all":e=>`${e} のすべて(対象エージェントに対して)`,"per-resource-any":e=>`${e} のいずれか(対象エージェントに対して)`},Qr=e=>k(Zr,e),$r=e=>{if(!A(e))return null;let t=e.gate;if(t===`none`)return`認証のみ(ロール不要)`;let n=Xr(e.action??e.actions);return n==null||typeof t!=`string`?null:Qr(t)?`必要な権限: ${Zr[t](n)}`:`必要な権限: ${n}`},ei={read:null,draft:`下書きへの変更です。公開版(利用者への配信)には publish まで反映されません。`},ti=e=>e.effect==null?null:ei[e.effect],ni=(e,t)=>{let n=[e.summary];e.description!=null&&n.push(``,e.description),n.push(``,`HTTP: ${e.method} ${e.pathTemplate}`);let r=$r(e.permission);r!=null&&n.push(r);let i=ti(e);i!=null&&n.push(``,i),e.responseKind===`sse`&&n.push(``,`ストリーミング応答を終端まで収集してから返します(数分かかることがあります)。`),e.responseKind===`binary`&&n.push(``,t.binaryResponse),e.transfer?.kind===`download`&&n.push(``,t.downloadTransfer),e.transfer?.kind===`upload`&&n.push(``,t.uploadTransfer),e.wholeBodyField!=null&&n.push(``,`リクエストボディは "${e.wholeBodyField}" 引数にそのまま渡します(判別共用体)。`);for(let r of e.inlineFiles?.input??[])n.push(``,t.inlineInput(r));if((e.inlineFiles?.output.length??0)>0&&n.push(``,t.inlineOutput),e.sseOutcome!=null){let t=[...e.sseOutcome.requiredEvents,e.sseOutcome.successPointer==null?e.sseOutcome.terminalEvent:`${e.sseOutcome.terminalEvent}{${e.sseOutcome.successPointer}=${JSON.stringify(e.sseOutcome.successValue)}}`];n.push(``,`成功判定: ${t.join(` と `)} が揃ったときだけ outcome=success。欠落・異常終了・打ち切りは isError で返し、自動再送しません。`)}return e.method!==`GET`&&n.push(``,`この操作は自動再送しません。タイムアウト時は状態を再取得して確認してください。`),n.join(`
|
|
28
|
+
`)},ri=e=>({readOnlyHint:e.method===`GET`,destructiveHint:e.method!==`GET`,idempotentHint:e.method===`GET`||e.method===`PUT`||e.method===`DELETE`,openWorldHint:!1}),ii=e=>`${e.product}/${e.slug}`,ai=e=>({articles:e,articleByReference:new Map(e.map(e=>[ii(e),e])),searchEntries:e.map(e=>({article:e,normalizedTitle:e.title.toLowerCase(),normalizedDescription:e.description.toLowerCase(),normalizedGroup:e.group.toLowerCase(),normalizedBody:e.body.toLowerCase()}))}),oi=(e,t)=>e.articleByReference.get(t)??null,si=(e,t)=>{for(let n of t){let t=e.normalizedBody.indexOf(n);if(t===-1)continue;let{body:r}=e.article,i=Math.max(0,t-80),a=Math.min(r.length,t+n.length+80),o=i>0?`…`:``,s=a<r.length?`…`:``;return`${o}${r.slice(i,a).replaceAll(/\s+/g,` `).trim()}${s}`}return e.article.description},ci=(e,t,n)=>{let r=[...new Set(t.toLowerCase().split(/\s+/).filter(e=>e.length>0))];if(r.length===0)return[];let i=[];for(let t of e.searchEntries){let e=0,n=0;for(let i of r){let r=0;t.normalizedTitle.includes(i)&&(r+=10),t.normalizedDescription.includes(i)&&(r+=5),t.normalizedGroup.includes(i)&&(r+=3),t.normalizedBody.includes(i)&&(r+=1),r>0&&(e+=1,n+=r)}e>0&&i.push({entry:t,matchedKeywordCount:e,score:n})}return i.sort((e,t)=>t.matchedKeywordCount===e.matchedKeywordCount?t.score-e.score:t.matchedKeywordCount-e.matchedKeywordCount),i.slice(0,n).map(({entry:e})=>({article:ii(e.article),title:e.article.title,group:e.article.group,description:e.article.description,snippet:si(e,r)}))},li=(e,t)=>{let n=e.replaceAll(/!\[[^\]]*\]\([^)]*\)/g,``),r=[];for(let e of n.split(/\r?\n/))(e.trim()!==``||r.at(-1)?.trim()!==``)&&r.push(e);return r.join(`
|
|
29
|
+
`).replaceAll(/\]\(([^)\s]+)\)/g,(e,n)=>{try{return`](${new URL(n,t).toString()})`}catch{return e}})},ui=(e,t)=>{let n=[],r=null,i=null;for(let a of e)a.product!==r&&(r=a.product,i=null,n.push(`## ${t[a.product]??a.product}`,``)),a.group!==i&&(i=a.group,n.push(`### ${a.group}`)),n.push(`- ${ii(a)}: ${a.title} — ${a.description}`);return n.join(`
|
|
30
|
+
`)},di={flygate:`Flyle AIコンタクトセンター`},fi=[{product:`flygate`,slug:`index`,title:`Flyle AIコンタクトセンターのご利用ガイド`,description:`問い合わせ対応を自動化する Flyle AIコンタクトセンターの全体像と、作成から改善までの使い方を紹介します。`,group:`はじめに`,order:1,url:`https://guide.flyle.io/ja/flygate`,body:`
|
|
31
31
|
## Flyle AIコンタクトセンターとは
|
|
32
32
|
|
|
33
33
|
本製品は、ウェブサイトのチャットや電話に寄せられるお問い合わせへ、24 時間自動で応答する AI の担当者です。よくある質問への回答を任せることで、人の担当者はより重要な対応に集中できます。
|
|
@@ -4414,10 +4414,12 @@ AI が答えきれない、あるいは人による対応が望ましい会話
|
|
|
4414
4414
|
- 選択肢の回答は、送信値で表示されます([表示ラベルと別の値を送信する](/ja/flygate/form-options#表示ラベルと別の値を送信する))。
|
|
4415
4415
|
- 画像の回答は「(項目名): 画像1を表示」のように表示されます。クリックすると、画像が新しいタブで開きます。
|
|
4416
4416
|
- 回答の送信後にフォームから削除した項目は、「削除済みの項目」と表示されます。
|
|
4417
|
-
- プレビューチャットなど、会話の記録がない場所から送信された回答では、会話 ID が「—」になります。
|
|
4418
4417
|
|
|
4419
4418
|
回答が 1 件もない場合は「回答はまだありません。」と表示されます。
|
|
4420
4419
|
|
|
4420
|
+
> [!NOTE]
|
|
4421
|
+
> プレビューチャットから送信した回答は、回答一覧にも CSV にも含まれません。動作確認のための送信が、訪問者の回答に混ざらないようにするためです。
|
|
4422
|
+
|
|
4421
4423
|
## 回答を CSV でダウンロードする
|
|
4422
4424
|
|
|
4423
4425
|
1. 回答一覧の「CSV ダウンロード」をクリックします。
|
|
@@ -4550,6 +4552,162 @@ AI が答えきれない、あるいは人による対応が望ましい会話
|
|
|
4550
4552
|
## 会話履歴を CSV で書き出す
|
|
4551
4553
|
|
|
4552
4554
|
絞り込んだ会話を CSV ファイルにまとめて保存できます。手順は「[会話履歴を CSV でエクスポートする](/ja/flygate/session-export)」をご覧ください。
|
|
4555
|
+
`},{product:`flygate`,slug:`assistant`,title:`アシスタントに管理画面の作業を依頼する`,description:`管理画面のアシスタントに、エージェントの設定の確認・変更、会話履歴の分析、評価など管理画面の作業を会話で依頼する方法を説明します。開き方、変更前の確認、画面を閉じても続く作業、ファイルの添付とダウンロード、会話の管理(名前の変更など)、使える条件を扱います。`,group:`アシスタント`,order:55,url:`https://guide.flyle.io/ja/flygate/assistant`,body:`
|
|
4556
|
+
> [!NOTE]
|
|
4557
|
+
> **試験的機能として、現在は Flyle が提供を始めた組織に限定して提供しています**
|
|
4558
|
+
>
|
|
4559
|
+
> アシスタントは、Flyle がアシスタントの提供を始めた組織で、ロールで「アシスタント」の「利用」を許可されたメンバーが利用できます。今後、仕様が変わる場合や提供を終了する場合があります。
|
|
4560
|
+
|
|
4561
|
+
アシスタントは、管理画面の右側に開くチャットです。エージェントの設定の確認・変更、会話履歴の分析、ナレッジの点検、評価など、管理画面で行う作業を会話で依頼できます。アシスタントは、ご自身のロールで操作できる範囲の中でだけ操作します。依頼はサーバーで進むので、パネルやタブを閉じても作業は続きます。設定を変更する前には、既定では実行してよいかを確認します。
|
|
4562
|
+
|
|
4563
|
+
## 前提条件
|
|
4564
|
+
|
|
4565
|
+
アシスタントを使うには、次の条件をすべて満たす必要があります。条件を満たしていない場合、アシスタントを開くボタンは表示されません。
|
|
4566
|
+
|
|
4567
|
+
- ご自身のロールで、「アシスタント」の「利用」が許可されていること。既定では Owner ロールだけが持っています。付与の方法は「[ロールと権限を管理する](/ja/flygate/role-management#管理画面のアシスタントを使えるようにする)」を参照してください。
|
|
4568
|
+
- ご利用の組織で、Flyle がアシスタントの提供を始めていること(試験提供中の制限です)。
|
|
4569
|
+
|
|
4570
|
+
## アシスタントを開く
|
|
4571
|
+
|
|
4572
|
+
1. 画面右下のアシスタントのボタンをクリックします。
|
|
4573
|
+
|
|
4574
|
+
画面の右側にアシスタントが開きます。画面の幅が狭い場合は、画面全体に重ねて表示します。閉じるときは、右上の「閉じる」をクリックします。閉じても、進行中の作業は止まりません。
|
|
4575
|
+
|
|
4576
|
+
## アシスタントに依頼する
|
|
4577
|
+
|
|
4578
|
+
1. 依頼したい内容を表示している画面を開きます。
|
|
4579
|
+
2. 「依頼内容を入力」欄に、依頼内容を入力します。
|
|
4580
|
+
3. 「送信」をクリックします。
|
|
4581
|
+
|
|
4582
|
+
キーボードでは Cmd + Enter(Windows では Ctrl + Enter)で送信できます。開いたばかりのときは、入力例のボタンをクリックすると、その内容を入力欄に入れられます。
|
|
4583
|
+
|
|
4584
|
+
アシスタントは、送信したときに開いていた画面を踏まえて依頼を解釈します。たとえば、あるエージェントの画面を開いた状態で「このエージェントの設定を要約して」と依頼すると、そのエージェントの設定を調べて回答します。
|
|
4585
|
+
|
|
4586
|
+
回答は、操作が 1 つ進むごとに表示されます。依頼の途中で行った操作は、回答の中に 1 行ずつ表示されます。行をクリックすると、その操作に渡した内容と結果を確認できます。管理画面の操作の説明は英語のまま表示されます。
|
|
4587
|
+
|
|
4588
|
+
> [!TIP]
|
|
4589
|
+
> **依頼のコツ**
|
|
4590
|
+
>
|
|
4591
|
+
> 対象のエージェントの画面を開いてから、「何を」「どうしたいか」を具体的に書くと、意図どおりに進みやすくなります。
|
|
4592
|
+
|
|
4593
|
+
## 画面を閉じても作業は続きます
|
|
4594
|
+
|
|
4595
|
+
依頼はサーバーで進みます。次の場合も、作業は止まりません。
|
|
4596
|
+
|
|
4597
|
+
- アシスタントのパネルを閉じた場合
|
|
4598
|
+
- 別の画面に移動した場合や、ブラウザーのタブを閉じた場合
|
|
4599
|
+
- ログアウトした場合
|
|
4600
|
+
|
|
4601
|
+
もう一度アシスタントを開くと、その会話の続きを確認できます。パネルを閉じている間も、確認を待っている会話があると、画面右下のアシスタントのボタンに印が付きます。作業が終わると、アシスタントは回答を書いて終わります。
|
|
4602
|
+
|
|
4603
|
+
時間のかかる処理(評価の実行など)を待つときは、アシスタントは処理が終わるまで間を置いてから確認し直します。待っている間は、会話の一覧に「待機中(10:30 に再開)」のように再開の時刻が表示されます。
|
|
4604
|
+
|
|
4605
|
+
次の場合は、作業が途中で終わります。アシスタントは、終わった理由を会話に書きます。
|
|
4606
|
+
|
|
4607
|
+
- 依頼を送ってから 24 時間が経った場合
|
|
4608
|
+
- 1 つの依頼の中で、アシスタントの判断(ステップ)が 50 回に達した場合
|
|
4609
|
+
- パスワードを変更した場合、ご自身のロールの権限が変わった場合、ご自身のアカウントが停止・削除された場合
|
|
4610
|
+
- 会話が長くなり、要約しても続けられなくなった場合
|
|
4611
|
+
|
|
4612
|
+
## 設定の変更を確認してから実行する
|
|
4613
|
+
|
|
4614
|
+
設定の確認だけなら、アシスタントはそのまま操作します。既定では、設定を変更する操作の前に、会話の中に「次の変更を実行しますか?」という確認が表示されます。変更が複数ある場合は、1 件ずつ表示されます。確認を待っている間、アシスタントは先に進みません。
|
|
4615
|
+
|
|
4616
|
+
1. 「変更する項目」で、変更される項目を確認します。
|
|
4617
|
+
2. 必要に応じて「入力を表示」をクリックし、送る内容を確認します。
|
|
4618
|
+
3. 内容に問題がなければ「実行する」をクリックします。削除の操作では「削除する」と表示されます。
|
|
4619
|
+
|
|
4620
|
+
実行しない場合は「実行しない」をクリックします。アシスタントは、実行されなかったことを踏まえて作業を続けます。
|
|
4621
|
+
|
|
4622
|
+
確認を待っている会話は、会話の一覧で「承認待ち」と表示されます。ほかの会話に確認を待っているものがある場合は、ヘッダーの「会話の一覧」のボタンに印が付きます。確認は、依頼を送ってから 24 時間以内に行ってください。
|
|
4623
|
+
|
|
4624
|
+
> [!NOTE]
|
|
4625
|
+
> **アシスタントで行えない操作があります**
|
|
4626
|
+
>
|
|
4627
|
+
> 公開版への切り替えなど、お客様への応対に直接影響する操作は、アシスタントでは行えません。管理画面で操作してください。
|
|
4628
|
+
|
|
4629
|
+
## 変更を自動で実行する
|
|
4630
|
+
|
|
4631
|
+
入力欄の上にある「変更を自動で実行」をオンにすると、オフにするまで、変更を確認せずに 1 件ずつ実行します。設定の上書き・全置換、過去の版への復元、利用量に含まれる評価や生成の開始、コードの実行も対象です。自動で実行した操作の行には「自動」と表示されます。
|
|
4632
|
+
|
|
4633
|
+
次の操作は、オンの間も確認が表示されます。会話の内容などに混ざった指示で、情報が外部に送られるのを防ぐためです。
|
|
4634
|
+
|
|
4635
|
+
- 削除
|
|
4636
|
+
- URL を指定したナレッジの取り込み(指定した URL の内容をサーバーが取得します)
|
|
4637
|
+
- 連携のコードの変更(連携のコードは外部と通信します)
|
|
4638
|
+
- 添付したファイルなどを、ナレッジやエージェントの生成の資料としてアップロードする操作
|
|
4639
|
+
|
|
4640
|
+
オンにした設定は会話ごとに保存され、指示が終わってもオフに戻りません。続けて送った指示も、確認せずに実行します。確認しながら進めたい場合は、オフにしてください。
|
|
4641
|
+
|
|
4642
|
+
すでに表示されている確認は、オンにしても自動で承認されません。その操作は「実行する」か「実行しない」を選んでください。
|
|
4643
|
+
|
|
4644
|
+
途中で自動実行をやめるには、「変更を自動で実行」をオフにします。次の変更から確認が表示されます。
|
|
4645
|
+
|
|
4646
|
+
> [!WARNING]
|
|
4647
|
+
> **意図しない変更が起こる場合があります**
|
|
4648
|
+
>
|
|
4649
|
+
> 会話履歴・フォームの送信内容・ナレッジ・添付したファイルなどの文面に混ざった指示によって、意図しない変更が確認なしで実行される場合があります。情報が外部に送られる操作は確認が表示されますが、変更内容を確かめてから実行したい場合は、自動実行をオフにしてください。
|
|
4650
|
+
|
|
4651
|
+
## ファイルを添付する・ダウンロードする
|
|
4652
|
+
|
|
4653
|
+
依頼にファイルを添付できます。たとえば、検証ケースの元になる会話履歴の CSV を添付して、「このファイルから検証ケースを作って」と依頼できます。
|
|
4654
|
+
|
|
4655
|
+
1. 入力欄の「ファイルを添付」をクリックし、ファイルを選びます。パネルにファイルをドラッグ&ドロップするか、コピーした画像(スクリーンショットなど)を入力欄で Ctrl + V(Mac では Command + V)で貼り付けても添付できます。
|
|
4656
|
+
2. 依頼内容を入力して「送信」をクリックします。
|
|
4657
|
+
|
|
4658
|
+
1 回の依頼で添付できるファイルは 20 件まで、1 つのファイルは 100 MB までです(空のファイルは添付できません)。添付できなかったファイルが残っている間は送信できません。取り除いてから送信してください。1 つの会話に置けるファイルは、アシスタントが作ったものも含めて 100 件までです(送る前に添付から外したファイルは数えません)。送ったメッセージには、添付したファイルの名前が表示されます。
|
|
4659
|
+
|
|
4660
|
+
PNG・JPEG・WebP の画像を添付すると、アシスタントは画像の中身を見て答えます。たとえば、エラーが出た画面のスクリーンショットを貼り付けて「この画面のエラーの原因を調べて」と依頼できます。1 つの会話でアシスタントが見られる画像は、新しいものから 20 枚までです。大きすぎる画像や壊れた画像は見られません。
|
|
4661
|
+
|
|
4662
|
+
アシスタントが作ったファイル(評価結果の書き出しや、集計した CSV など)は、操作の行にダウンロードのボタンが表示されます。クリックするとダウンロードできます。
|
|
4663
|
+
|
|
4664
|
+
添付したファイルとアシスタントが作ったファイルは、会話を削除するまで残ります。
|
|
4665
|
+
|
|
4666
|
+
## コードを実行して集計・加工する
|
|
4667
|
+
|
|
4668
|
+
管理画面の操作だけではできない集計や加工(CSV の集計、グラフの作成など)は、アシスタントがコードを書いて実行します。コードは、外部と通信できない専用の環境で実行され、1 回の実行は 15 分までです。
|
|
4669
|
+
|
|
4670
|
+
コードを実行する前には、「次のコードを実行しますか?」という確認が表示されます。「実行するコード」と「使うファイル」を確認してから、「実行する」をクリックしてください。「変更を自動で実行」がオンの場合は、確認なしで実行します。
|
|
4671
|
+
|
|
4672
|
+
## 依頼を中断する
|
|
4673
|
+
|
|
4674
|
+
アシスタントが作業している間は、「送信」の代わりに「中断」が表示されます。
|
|
4675
|
+
|
|
4676
|
+
1. 「中断」をクリックします。
|
|
4677
|
+
|
|
4678
|
+
それまでの会話は残ります。続けて新しい依頼を送れます。
|
|
4679
|
+
|
|
4680
|
+
> [!WARNING]
|
|
4681
|
+
> **変更の結果が不明になる場合があります**
|
|
4682
|
+
>
|
|
4683
|
+
> 設定の変更を送った直後に中断した場合や、サーバーの都合で作業が引き継がれた場合は、その変更が実行されたかどうかが分からないことがあります。このとき、アシスタントには「結果が不明です(実行された可能性があります)」と伝わり、同じ変更は自動では送り直しません。続ける前に、管理画面で設定の状態を確かめてください。
|
|
4684
|
+
|
|
4685
|
+
## 会話を切り替える・名前を変える・削除する
|
|
4686
|
+
|
|
4687
|
+
会話は保存され、削除するまで残ります。ブラウザーを再読み込みしても、別のパソコンからログインしても、続きを確認できます。会話はご自身にだけ表示されます。
|
|
4688
|
+
|
|
4689
|
+
- 新しい会話を始めるには、右上の「新しい会話」をクリックします。それまでの会話は一覧に残ります。
|
|
4690
|
+
- 以前の会話を開くには、ヘッダーの「会話の一覧」をクリックし、開きたい会話を選びます。一覧には、会話の題名・状態(実行中・承認待ち・待機中)・更新した時刻が表示されます。
|
|
4691
|
+
- 会話の名前は、最初の依頼の内容から自動で付きます(たとえば「セキュリティ問い合わせへの対応追加」)。名前が付くまでは、依頼の先頭が表示されます。
|
|
4692
|
+
- 会話の名前を変えるには、一覧で会話の名前の変更のボタンをクリックし、新しい名前を入力して「変更」をクリックします。名前は 50 文字までです。名前を変えた会話には、自動で名前が付き直りません。
|
|
4693
|
+
- 会話を削除するには、一覧で会話の削除のボタンをクリックし、「削除する」をクリックします。作業中の会話を削除すると、作業も止まります。削除した会話と、その会話のファイルは元に戻せません。
|
|
4694
|
+
|
|
4695
|
+
同時に進められる会話は 3 つまでです。3 つの会話が作業中の場合は「同時に進められる会話は 3 つまでです。進行中の会話が終わるか、中断すると送れます。」と表示され、送信できません。保存できる会話は 50 件までです。50 件に達した場合は、不要な会話を削除してから新しい会話を始めてください。
|
|
4696
|
+
|
|
4697
|
+
1 つの会話が長くなると、アシスタントはそれまでのやり取りを自動で要約して、同じ会話のまま作業を続けます。要約したところには「会話が長くなったため、ここまでのやり取りを要約して続けています」と表示されます。要約した後も、会話の表示はすべて残ります。ただし、アシスタントが覚えているのは要約した内容なので、前に確認した細かい値は、必要に応じてもう一度調べ直します。
|
|
4698
|
+
|
|
4699
|
+
要約しても続けられないほど会話が長くなると、「この会話は長くなったため、これ以上送れません。新しい会話を始めてください。」と表示され、その会話には送れなくなります。必要な前提を短くまとめて、新しい会話で依頼し直してください。
|
|
4700
|
+
|
|
4701
|
+
## 使えなくなる場合
|
|
4702
|
+
|
|
4703
|
+
次の場合、アシスタントは使えなくなります。進行中の作業も止まります。
|
|
4704
|
+
|
|
4705
|
+
- ご自身のロールから「アシスタント」の「利用」が外れた場合
|
|
4706
|
+
- ご利用の組織で、アシスタントの提供が止まった場合
|
|
4707
|
+
- ご自身のアカウントが停止・削除された場合
|
|
4708
|
+
- テナントが利用制限中の場合(詳しくは「[利用制限について](/ja/flygate/usage-limit)」を参照してください)
|
|
4709
|
+
|
|
4710
|
+
アシスタントの利用は、エージェントの応対と同じくテナントの利用量に含まれます。アシスタントの接続は、「外部ツール接続」の接続一覧には表示されません。
|
|
4553
4711
|
`},{product:`flygate`,slug:`session-export`,title:`会話履歴を CSV でエクスポートする`,description:`会話履歴を絞り込んで CSV ファイルに書き出し、通知からダウンロードする方法と、CSV に含まれる内容を説明します。`,group:`5. 結果を見て改善する`,order:55,url:`https://guide.flyle.io/ja/flygate/session-export`,body:`
|
|
4554
4712
|
会話履歴で絞り込んだ会話を、1 つの CSV ファイルにまとめて保存できます。表計算ソフトで集計したり、社内の分析に使ったりするときに使います。CSV は依頼後に作成され、完成すると「通知」からダウンロードできます。
|
|
4555
4713
|
|
|
@@ -5074,7 +5232,7 @@ Flyle AIコンタクトセンターでは、操作や閲覧の権限を「ロー
|
|
|
5074
5232
|
| ロール | できること |
|
|
5075
5233
|
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
5076
5234
|
| **Owner** | テナントのすべての操作を実行できる最上位ロールです。権限は編集できません。 |
|
|
5077
|
-
| **Admin** |
|
|
5235
|
+
| **Admin** | 「テナント設定」「外部ツール接続」「アシスタント」を除くすべての権限を、全体のスコープで持ちます。メンバー・チーム・ロールの管理、エージェントの設定と運用、チャット認証情報、すべての会話への対応(会話履歴のエクスポートを含む)ができます。 |
|
|
5078
5236
|
| **Supervisor** | 自分のチームの会話を監督・介入できます。「チャットセッション」の閲覧・返信・割り当て・クローズ・エクスポートと、「機密情報」「内部メモ」「応対評価」のすべての操作を「自分のチーム」のスコープで持ちます。「チャットセッション」の「削除」は持ちません。「エージェント運用」は全体で持ちます。 |
|
|
5079
5237
|
| **Operator** | 自分のチームの会話の閲覧・対応開始・転送・担当チームの移動ができ、自分が担当している会話に返信・完了・AI に戻すができます。「内部メモ」は「自分のチーム」のスコープで閲覧・編集できます。「エージェント運用」は全体で持ちます。 |
|
|
5080
5238
|
|
|
@@ -5105,6 +5263,7 @@ Admin・Supervisor・Operator はシステムが用意したロールですが
|
|
|
5105
5263
|
| テナント管理 | テナント設定 | 閲覧・編集 | テナント全体の設定(テナントの基本情報、電話番号・SIP 接続、外部ツールからのログイン接続など)の閲覧と変更です。ロールの管理は含みません。 |
|
|
5106
5264
|
| テナント管理 | ロールの管理 | 閲覧・編集 | ロールの作成・名前の変更・削除と、ロールの権限の編集です。 |
|
|
5107
5265
|
| テナント管理 | 外部ツール接続 | 接続 | Claude Code の MCP などの外部ツールから、自分の権限でログインして操作することの許可です。 |
|
|
5266
|
+
| テナント管理 | アシスタント | 利用 | 管理画面のアシスタントに、自分の権限で設定の確認・変更・評価を依頼することの許可です。アシスタントは現在、Flyle が提供を始めた組織でだけ使えます。 |
|
|
5108
5267
|
| - | すべての機能 | すべての操作 | 現在と今後追加されるすべての機能・操作にまとめて適用します。 |
|
|
5109
5268
|
|
|
5110
5269
|
「チャットセッション」の各操作は、画面上の次の操作に対応します。
|
|
@@ -5142,7 +5301,7 @@ Admin・Supervisor・Operator はシステムが用意したロールですが
|
|
|
5142
5301
|
|
|
5143
5302
|
ロールの権限は、次の 2 つに分かれます。
|
|
5144
5303
|
|
|
5145
|
-
- **管理権限**:
|
|
5304
|
+
- **管理権限**: 「テナント設定」「メンバー・チーム管理」「ロールの管理」「外部ツール接続」「アシスタント」。「すべての機能」は管理権限をすべて含みます。
|
|
5146
5305
|
- **業務権限**: 「エージェント設定」や「チャットセッション」など、エージェントの運用とチャット対応の権限。
|
|
5147
5306
|
|
|
5148
5307
|
「テナント設定」には、ロールの管理は含まれません。電話番号や SIP 接続の設定を任せるメンバーに「テナント設定」だけを許可すると、そのメンバーはロールの権限を変更できません。
|
|
@@ -5284,11 +5443,22 @@ Admin・Supervisor・Operator はシステムが用意したロールですが
|
|
|
5284
5443
|
「外部ツール接続」の「接続」を許可したロールを持つメンバーは、Claude Code の MCP などの外部ツールからブラウザーでログインし、自分のロールの権限で操作できます。この権限の対象は「テナント全体」で、スコープはありません。
|
|
5285
5444
|
|
|
5286
5445
|
- 既定では Owner ロールだけが持っています。ほかのメンバーに使わせる場合は、そのメンバーのロールに「外部ツール接続」の「接続」を許可する行を追加するか、この権限だけを許可したロールを作成して追加で割り当てます。
|
|
5287
|
-
-
|
|
5446
|
+
- 外部ツールからは、テナント設定で外部ツールからのログイン接続が許可されている場合にだけ使えます。
|
|
5288
5447
|
- 外部ツールで操作できる範囲は、そのメンバーが管理画面で操作できる範囲と同じです。
|
|
5289
5448
|
- ロールからこの権限を外すと、そのメンバーの外部ツールは次の操作からエラーになります。接続そのものは切断されないため、権限を戻すとそのまま使えます。確実に止めたい場合は、「外部ツール接続」から接続を切断してください。
|
|
5290
5449
|
|
|
5291
5450
|
設定と利用の手順は [Claude Code から MCP で操作する](/ja/flygate/mcp-login-connection) を参照してください。
|
|
5451
|
+
|
|
5452
|
+
### 管理画面のアシスタントを使えるようにする
|
|
5453
|
+
|
|
5454
|
+
「アシスタント」の「利用」を許可したロールを持つメンバーは、管理画面のアシスタントに、自分のロールの権限で設定の確認・変更・評価を依頼できます。この権限の対象は「テナント全体」で、スコープはありません。
|
|
5455
|
+
|
|
5456
|
+
- 既定では Owner ロールだけが持っています。ほかのメンバーに使わせる場合は、そのメンバーのロールに「アシスタント」の「利用」を許可する行を追加するか、この権限だけを許可したロールを作成して追加で割り当てます。
|
|
5457
|
+
- 「外部ツール接続」の「接続」や、テナント設定の外部ツールからのログイン接続の設定とは関係なく使えます。
|
|
5458
|
+
- アシスタントで操作できる範囲は、そのメンバーが管理画面で操作できる範囲と同じです。
|
|
5459
|
+
- ロールからこの権限を外すと、そのメンバーのアシスタントは止まり、新しい依頼も送れなくなります。
|
|
5460
|
+
|
|
5461
|
+
アシスタントの使い方は「[アシスタントに設定の確認・変更を依頼する](/ja/flygate/assistant)」を参照してください。
|
|
5292
5462
|
`},{product:`flygate`,slug:`team-management`,title:`チームを管理する`,description:`チームの作成・編集・削除、メンバーの設定方法、会話の担当チームと権限スコープの関係を説明します。`,group:`権限・チームの管理`,order:62,url:`https://guide.flyle.io/ja/flygate/team-management`,body:`
|
|
5293
5463
|
チームは、応対するメンバーをまとめる単位です。チーム設定でメンバーを管理し、エージェント設定で会話の引き継ぎ先チームを選びます。チームの所属は、ロールの「自分のチーム」スコープで閲覧・対応できる会話の範囲にも使われます。
|
|
5294
5464
|
|
|
@@ -5405,7 +5575,7 @@ Admin・Supervisor・Operator はシステムが用意したロールですが
|
|
|
5405
5575
|
- テナント名は、作成後に管理画面や Flyle 認証基盤から変更できません。変更が必要な場合は、お問い合わせください。
|
|
5406
5576
|
|
|
5407
5577
|
> [!NOTE]
|
|
5408
|
-
> Flyle
|
|
5578
|
+
> Flyle が外部ツールからのログイン接続の提供を始めた組織では、このほかに「外部ツールからのログイン接続」の項目も表示されます([Claude Code から MCP で操作する](/ja/flygate/mcp-login-connection#外部ツールからのログイン接続を許可する))。
|
|
5409
5579
|
|
|
5410
5580
|
## テナントを削除する
|
|
5411
5581
|
|
|
@@ -5874,9 +6044,9 @@ export const signIdentity = (identitySecret, userId) => {
|
|
|
5874
6044
|
迷ったときは、「本人であることを前提にするなら \`identify\`、ヒントでよいなら \`setContext\`」と覚えてください。
|
|
5875
6045
|
`},{product:`flygate`,slug:`public-api`,title:`公開 API で外部システムと連携する`,description:`公開 API の認証とベース URL、エージェント設定・検証・チャネル設定・会話ログ取得に使える操作、ページング、エラーとレート制限、互換性方針を説明します。開発者向けの内容です。`,group:`開発者向け`,order:93,url:`https://guide.flyle.io/ja/flygate/public-api`,body:`
|
|
5876
6046
|
> [!NOTE]
|
|
5877
|
-
> **試験的機能として、現在は Flyle
|
|
6047
|
+
> **試験的機能として、現在は Flyle が提供を始めた組織に限定して提供しています**
|
|
5878
6048
|
>
|
|
5879
|
-
> サービスアカウントの作成と API キーの発行、外部ツール(Claude Code の MCP など)からのログイン接続は、
|
|
6049
|
+
> サービスアカウントの作成と API キーの発行、外部ツール(Claude Code の MCP など)からのログイン接続は、Flyle が提供を始めた組織でのみ利用できます。今後、仕様が変わる場合や提供を終了する場合があります。
|
|
5880
6050
|
|
|
5881
6051
|
本製品は、管理画面で行える操作の一部を、外部システムやスクリプトから直接呼び出せる公開 API として提供しています。エージェントの設定変更、検証ケースの管理、検証の実行と結果取得、改善提案の確認と適用、チャネル設定、会話ログの取得に利用できます。公開版への切り替えは管理画面で行います。開発者向けの内容です。
|
|
5882
6052
|
|
|
@@ -5891,7 +6061,7 @@ MCP ではサービスアカウントの API キーを使えません。MCP を
|
|
|
5891
6061
|
|
|
5892
6062
|
## 前提条件
|
|
5893
6063
|
|
|
5894
|
-
- 外部システムやスクリプトから公開 API を呼び出すには、先に「サービスアカウント」の作成と API キーの発行が必要です。作成・発行は、
|
|
6064
|
+
- 外部システムやスクリプトから公開 API を呼び出すには、先に「サービスアカウント」の作成と API キーの発行が必要です。作成・発行は、Owner ロールのメンバーが行います。手順は [サービスアカウントと API キーを管理する](/ja/flygate/service-accounts) を参照してください。
|
|
5895
6065
|
- 公開 API で操作できる範囲は、サービスアカウントに割り当てたロールで決まります([ロールと権限を管理する](/ja/flygate/role-management))。
|
|
5896
6066
|
|
|
5897
6067
|
## API の使い方
|
|
@@ -5921,6 +6091,10 @@ Authorization: Bearer <API キー>
|
|
|
5921
6091
|
> [!WARNING]
|
|
5922
6092
|
> API キーをブラウザー上で動作するコードに埋め込まないでください。\`http://\` での接続は拒否されるため、必ず \`https://\` で呼び出してください。
|
|
5923
6093
|
|
|
6094
|
+
### ブラウザーから呼び出す
|
|
6095
|
+
|
|
6096
|
+
外部サイトのブラウザーからは呼び出せません。サーバーから呼び出してください。
|
|
6097
|
+
|
|
5924
6098
|
### 読み取りと API キーの失効
|
|
5925
6099
|
|
|
5926
6100
|
| 用途 | メソッドとパス |
|
|
@@ -6043,9 +6217,9 @@ Authorization: Bearer <API キー>
|
|
|
6043
6217
|
- OpenAPI 定義: <https://api.flygate.flyle.io/v0/openapi.json>
|
|
6044
6218
|
`},{product:`flygate`,slug:`service-accounts`,title:`サービスアカウントと API キーを管理する`,description:`公開 API を呼び出すためのサービスアカウントの作成・名前の変更・停止と再開・ロールの変更、API キーの発行・失効の手順を説明します。開発者向けの内容です。`,group:`開発者向け`,order:94,url:`https://guide.flyle.io/ja/flygate/service-accounts`,body:`
|
|
6045
6219
|
> [!NOTE]
|
|
6046
|
-
> **試験的機能として、現在は Flyle
|
|
6220
|
+
> **試験的機能として、現在は Flyle が提供を始めた組織に限定して提供しています**
|
|
6047
6221
|
>
|
|
6048
|
-
> サービスアカウントの画面は、
|
|
6222
|
+
> サービスアカウントの画面は、Flyle が提供を始めた組織でのみ表示されます。提供を止めると、その組織の API キーはすべて使えなくなります。今後、仕様が変わる場合や提供を終了する場合があります。
|
|
6049
6223
|
|
|
6050
6224
|
公開 API は、人間のメンバーではなく「サービスアカウント」という専用のアカウントで呼び出します。この記事では、サービスアカウントと、その認証に使う API キーの管理方法を説明します。API の呼び出し方は [公開 API で外部システムと連携する](/ja/flygate/public-api) を参照してください。
|
|
6051
6225
|
|
|
@@ -6055,7 +6229,7 @@ Authorization: Bearer <API キー>
|
|
|
6055
6229
|
|
|
6056
6230
|
## 前提条件
|
|
6057
6231
|
|
|
6058
|
-
-
|
|
6232
|
+
- ご利用の組織で、Flyle がサービスアカウントの提供を始めていること(試験提供中の制限です)
|
|
6059
6233
|
- 操作ごとに、次のロールを持っていること
|
|
6060
6234
|
|
|
6061
6235
|
| 操作 | 必要なロール |
|
|
@@ -6170,9 +6344,9 @@ API キーには有効期限があり(最長 365 日)、期限が切れる
|
|
|
6170
6344
|
外部システムの側からも、認証に使っている API キーを自分で失効できます([公開 API で外部システムと連携する](/ja/flygate/public-api#読み取りと-API-キーの失効))。
|
|
6171
6345
|
`},{product:`flygate`,slug:`mcp-login-connection`,title:`Claude Code から MCP で操作する`,description:`Claude Code などの外部ツールからブラウザーでログインして MCP で操作するための、ログイン接続の許可、専用ディレクトリの準備、ログイン・登録・ログアウト、接続の確認と切断、依頼の仕方を説明します。開発者向けの内容です。`,group:`開発者向け`,order:95,url:`https://guide.flyle.io/ja/flygate/mcp-login-connection`,body:`
|
|
6172
6346
|
> [!NOTE]
|
|
6173
|
-
> **試験的機能として、現在は Flyle
|
|
6347
|
+
> **試験的機能として、現在は Flyle が提供を始めた組織に限定して提供しています**
|
|
6174
6348
|
>
|
|
6175
|
-
> 外部ツール(Claude Code の MCP など)からのログイン接続は、
|
|
6349
|
+
> 外部ツール(Claude Code の MCP など)からのログイン接続は、Flyle が提供を始めた組織でのみ利用できます。管理画面の「外部ツール接続」と、テナント設定の「外部ツールからのログイン接続」も、その組織でのみ表示されます。提供を止めると、その組織の接続はすべて使えなくなります。ただし、提供を止めた後もログイン接続を許可したままの場合は、テナント設定の編集権限を持つメンバーに「外部ツールからのログイン接続」が表示され、許可しない設定に変更(緊急停止)できます。今後、仕様が変わる場合や提供を終了する場合があります。
|
|
6176
6350
|
|
|
6177
6351
|
MCP サーバーを登録すると、Claude Code から設定の取得・更新、ナレッジやファイルの取り込み、プレビューの作成と完了確認、検証ケースの管理と試行、検証の実行と結果取得、改善分析、チャネル設定を行えます。設定を編集し、プレビューの完了を確認して検証し、結果から再調整する流れを MCP で進められます。公開の実行・昇格・取消は提供していません(公開状態の参照は可能です)。
|
|
6178
6352
|
|
|
@@ -6193,12 +6367,12 @@ MCP を使うには、次の条件をすべて満たす必要があります。
|
|
|
6193
6367
|
|
|
6194
6368
|
- テナント設定で、外部ツールからのログイン接続が許可されていること(既定では許可されていません)。手順は「[外部ツールからのログイン接続を許可する](#外部ツールからのログイン接続を許可する)」を参照してください。
|
|
6195
6369
|
- ご自身のロールで、「外部ツール接続」の「接続」が許可されていること。既定では Owner ロールだけが持っています。付与の方法は「[ロールと権限を管理する](/ja/flygate/role-management#Claude-Code-などの外部ツールから操作できるようにする)」を参照してください。
|
|
6196
|
-
-
|
|
6370
|
+
- ご利用の組織で、Flyle が外部ツールからのログイン接続の提供を始めていること(試験提供中の制限です)。
|
|
6197
6371
|
- お使いの PC に Node.js 22 以上がインストールされていること。
|
|
6198
6372
|
|
|
6199
6373
|
## 外部ツールからのログイン接続を許可する
|
|
6200
6374
|
|
|
6201
|
-
テナントの管理者向けの手順です([テナントの設定を確認する](/ja/flygate/tenant-settings))。「テナント設定」の編集権限を持つメンバーが操作できます。試験提供中は、許可する操作は
|
|
6375
|
+
テナントの管理者向けの手順です([テナントの設定を確認する](/ja/flygate/tenant-settings))。「テナント設定」の編集権限を持つメンバーが操作できます。試験提供中は、許可する操作は Flyle が提供を始めた組織でのみ行えます。許可しない設定への変更(緊急停止)は、編集権限を持つメンバーなら誰でも行えます。
|
|
6202
6376
|
|
|
6203
6377
|
1. 「設定」>「テナント」を開きます。
|
|
6204
6378
|
2. 「外部ツールからのログイン接続」の「ログイン接続を許可」をオンにします。
|
|
@@ -6207,6 +6381,8 @@ MCP を使うには、次の条件をすべて満たす必要があります。
|
|
|
6207
6381
|
|
|
6208
6382
|
許可すると、ロールで「外部ツール接続」の権限を持つメンバーが、MCP からログインできるようになります。
|
|
6209
6383
|
|
|
6384
|
+
管理画面のアシスタント([アシスタントに設定の確認・変更を依頼する](/ja/flygate/assistant))は外部ツールではないため、この設定の影響を受けません。許可しない設定にしても、アシスタントはそのまま使えます。
|
|
6385
|
+
|
|
6210
6386
|
> [!WARNING]
|
|
6211
6387
|
> **許可しない設定に戻すと、すべての接続が切断されます**
|
|
6212
6388
|
>
|
|
@@ -6249,6 +6425,7 @@ MCP を登録する前に、テナント専用ディレクトリでログイン
|
|
|
6249
6425
|
|
|
6250
6426
|
- 接続を切断した場合(「[外部ツールの接続を確認・切断する](#外部ツールの接続を確認・切断する)」を参照)
|
|
6251
6427
|
- テナント設定で、外部ツールからのログイン接続を許可しない設定にした場合
|
|
6428
|
+
- ご利用の組織で、外部ツールからのログイン接続の提供が止まった場合
|
|
6252
6429
|
- メンバーが停止・削除された場合
|
|
6253
6430
|
- ご本人がパスワードを再設定・変更・設定した場合、または二段階認証(MFA)を設定・解除した場合(管理者が解除した場合を含みます)。アカウントを不正に使われた疑いがあるときは、パスワードを変更すると、それまでに作られたログイン接続もまとめて使えなくなります
|
|
6254
6431
|
- ログイン情報の更新中に通信が切れるなどして、更新の応答を受け取れなかった場合(安全のため、同じログイン情報の再利用とみなして接続を切断します)
|
|
@@ -6501,7 +6678,7 @@ MCP の \`get_knowledge_document_original_content\` は、原本ファイルを
|
|
|
6501
6678
|
## 「公開」をクリックすると失敗する
|
|
6502
6679
|
|
|
6503
6680
|
画面右上の「公開」ボタンは、権限に関係なく表示されます。公開に必要な「エージェント設定」の編集権限が無いと、ボタンをクリックして公開を始めても失敗します。管理者に「エージェント設定」の編集権限の付与を依頼してください([ロールと権限を管理する](/ja/flygate/role-management))。
|
|
6504
|
-
`}],G=`get_product_guide`,K=`search_product_guide`,q=`read_product_guide_article`,
|
|
6681
|
+
`}],G=`get_product_guide`,K=`search_product_guide`,q=`read_product_guide_article`,pi=`# Flyle AIコンタクトセンターの全体像
|
|
6505
6682
|
|
|
6506
6683
|
Flyle AIコンタクトセンターは、Web サイトのチャットや電話に寄せられるお問い合わせへ 24 時間自動で応答する AI の担当者(エージェント)を作り、運用する製品です。利用者はコンタクトセンターの導入・運用担当者で、エンジニアではありません。
|
|
6507
6684
|
|
|
@@ -6544,7 +6721,7 @@ Flyle AIコンタクトセンターは、Web サイトのチャットや電話
|
|
|
6544
6721
|
- 応答の流れや口調を変えたい: business-flow → list_agent_nodes / get_agent_node → update_agent_node
|
|
6545
6722
|
- 外部システムと連携したい: connectors
|
|
6546
6723
|
- 有人対応への引き継ぎを設定したい: human-handoff / team-management
|
|
6547
|
-
- 応対の状況を知りたい: dashboard / improve → get_agent_session_summary / list_chat_sessions`,gi={agents:[`create-agent`,`business-flow`],"agent-generation-jobs":[`create-agent`],"agent-generation-upload-urls":[`create-agent`],"agents/generation-jobs":[`create-agent`],"agents/configuration":[`business-flow`],"agents/agent-nodes":[`business-flow`],"agents/connectors":[`connectors`],"agents/forms":[`form-options`,`business-flow`],"agents/knowledge-bases":[`knowledge`],"agents/knowledge-ingest-job-summary":[`knowledge`],"agents/synonym-entries":[`synonym-dictionary`],"agents/voice-dictionary-entries":[`voice-dictionary`],"agents/preview-builds":[`validate`,`knowledge`],"agents/preview-chat-messages":[`validate`],"agents/preview-chat-sessions":[`validate`],"agents/preview-voice-messages":[`validate`,`audio-settings`],"agents/preview-form-submissions":[`validate`,`form-options`],"agents/eval-cases":[`validate`],"agents/eval-case-imports":[`validate`],"agents/eval-images":[`validate`],"agents/eval-runs":[`validate`],"agents/eval-run-case-results":[`validate`],"agents/eval-case-result-histories":[`validate`],"agents/improvement-analyses":[`validate`,`improve`],"agents/improvement-attempts":[`validate`,`improve`],"agents/improvement-attempt-summary":[`validate`,`improve`],"improvement-proposals":[`validate`,`improve`],"agents/revisions":[`history`],"agents/latest-publish":[`history`,`embed-publish`],"agents/publishes":[`history`,`embed-publish`],"agents/publish-readiness":[`embed-publish`,`validate`],"agents/web-chat-channel":[`design`,`audio-settings`],"agents/web-chat-credentials":[`embed-publish`,`security-model`],"agents/human-handoff-settings":[`human-handoff`],"team-names":[`team-management`,`human-handoff`],"agents/session-summary":[`dashboard`],"chat-sessions":[`improve`,`operator-console`],"credit-status":[`usage-limit`],"current-user":[`role-management`],"phone-settings":[`phone-channel`],"phone-numbers":[`phone-channel`],"sip-connections":[`phone-channel`]},_i=e=>{let[t,n]=e.split(`/`).filter(e=>e!==``&&!e.startsWith(`{`)).slice(2);return t===`agents`&&n!=null?`${t}/${n}`:t??``},vi=e=>{let t=gi[_i(e)];if(t==null)return null;let n=t.map(e=>`flygate/${e}`).join(`, `);return`操作の前に読む記事(${q}): ${n}`};let yi=null;const bi=()=>(yi??=si(mi),yi),xi=()=>({isError:!1,payload:{guide:`${hi}\n\n# ご利用ガイドの記事一覧\n\n${fi(mi,pi)}`}}),Si=(e,t)=>({isError:!1,payload:{results:ui(bi(),e,t)}}),Ci=e=>{let t=ci(bi(),e);return t==null?{isError:!0,payload:{error:{kind:`guide_article_not_found`,message:`記事 "${e}" はありません。${G} の一覧か ${K} で記事を探し、"flygate/knowledge" の形式で指定してください。`}}}:{isError:!1,payload:{article:oi(t),title:t.title,group:t.group,url:t.url,body:di(t.body,t.url)}}},wi=()=>({isError:!0,payload:{error:{kind:`product_guide_required`,message:`製品の考え方を確認する前の操作は実行しません。先に ${G} を呼び、依頼に関係する記事を ${q} で読んでから、この操作をやり直してください。`}}}),Ti=(e,t)=>{let n=``,r=0,i=e.indexOf(`{`);for(;i!==-1;){let a=e.indexOf(`}`,i+1);if(a===-1)break;n+=a===i+1?e.slice(r,a+1):e.slice(r,i)+t(e.slice(i+1,a)),r=a+1,i=e.indexOf(`{`,r)}return n+e.slice(r)},Ei=(e,t)=>{if(typeof t==`string`)return t;if(typeof t==`number`||typeof t==`boolean`)return String(t);throw new S(`argument "${e}" must be a string, number, or boolean`)},Di=(e,t,n)=>{if(E(n,`tenantName`))throw new S(`"tenantName" is fixed by the server configuration`);let r=Ti(t.pathTemplate,t=>{if(t===`tenantName`)return encodeURIComponent(e.tenantName);let r=n[t];if(r==null)throw new S(`path parameter "${t}" is required`);return encodeURIComponent(Ei(t,r))}),i=[];for(let e of t.queryParams){let t=n[e];if(t!=null){if(Array.isArray(t))for(let n of t)i.push([e,Ei(e,n)]);else i.push([e,Ei(e,t)])}}let a=null,o=!1;if(t.wholeBodyField!=null){if(!E(n,t.wholeBodyField))throw new S(`argument "${t.wholeBodyField}" is required`);a=n[t.wholeBodyField],o=!0}else if(t.bodyFields!=null){let e={};for(let r of t.bodyFields)E(n,r)&&(e[r]=n[r]);a=e,o=!0}return{method:t.method,path:r,query:i,hasBody:o,body:a,responseKind:t.responseKind}},Oi=(e,t,n)=>{let r=t.findIndex(t=>t.event===e.terminalEvent),i=r===-1?null:t[r],a=r===-1?t:t.slice(0,r),o=i==null?null:wt(i.data),s=new Set(a.map(e=>e.event)),c=e.failureEvents.find(e=>s.has(e));if(c!=null)return{outcome:`failed`,reason:`received failure event "${c}"`,terminal:o};if(i==null)return n.truncated?{outcome:`unknown`,reason:`the stream was cut off by the client limit (${n.reason??`unknown`})`,terminal:o}:{outcome:`unknown`,reason:`the stream ended without the terminal event "${e.terminalEvent}"`,terminal:o};let l=e.successPointer==null?null:V(o,e.successPointer)[0];if(e.successPointer!=null&&l!==e.successValue)return{outcome:`failed`,reason:`"${e.terminalEvent}" ended with ${e.successPointer}=${JSON.stringify(l)} (expected ${JSON.stringify(e.successValue)})`,terminal:o};let u=e.requiredEvents.filter(e=>!s.has(e));return u.length>0?{outcome:`failed`,reason:`required event(s) missing before "${e.terminalEvent}": ${u.join(`, `)}`,terminal:o}:{outcome:`success`,reason:null,terminal:o}},ki=e=>({event:e.event,data:wt(e.data),...e.id==null?{}:{id:e.id}}),Ai=(e,t)=>{if(e instanceof _)return{isError:!0,payload:{error:{kind:`api`,...e.info}}};if(e instanceof v)return{isError:!0,payload:{error:{kind:`transport`,failure:e.kind,status:e.status,message:e.message}}};if(e instanceof y)return{isError:!0,payload:{error:{kind:`transfer`,failure:e.kind,status:e.status,message:e.message}}};if(e instanceof S)return{isError:!0,payload:{error:{kind:`invalid_arguments`,message:e.message}}};if(e instanceof b)return{isError:!0,payload:{error:{kind:`local_file`,failure:e.kind,message:e.message}}};if(e instanceof x)return{isError:!0,payload:{error:{kind:`inline_file`,failure:e.kind,message:e.message}}};if(e instanceof C)return{isError:!0,payload:{error:{kind:`workspace`,failure:e.kind,message:e.message}}};if(e instanceof w)return{isError:!0,payload:{error:{kind:`auth`,failure:e.kind,message:e.message}}};if(e instanceof ue)return{isError:!0,payload:e.payload};if(e instanceof Error)return{isError:!0,payload:{error:{kind:`unexpected`,message:z(e.message,t)}}};throw e},ji=async(e,t,n)=>{try{return await e.preflight(),{isError:!1,payload:await n()}}catch(n){let r=e.auth.secrets(),i=Ai(n,r),a=JSON.parse(z(JSON.stringify(i.payload),r));return e.logger.warn(`tool call failed`,{operationId:t,payload:a}),{isError:!0,payload:a}}},Mi=async(e,t,n,r)=>ji(e,t.operationId,async()=>{let i=await r.prepareArguments(t,n),a=Di(e.config,t,i),o=await e.client.request(a);switch(o.kind){case`json`:{let e=await r.processJson(t,o.body);return{status:o.status,requestId:o.requestId,body:e.body,...e.extra}}case`empty`:return{status:o.status,requestId:o.requestId};case`sse`:{let e=await r.processSse(t,o.events),n={status:o.status,requestId:o.requestId,events:e.events.map(e=>ki(e)),truncated:o.truncated,stopReason:o.reason,discardedIncomplete:o.discardedIncomplete,...e.extra};if(t.sseOutcome==null)return n;let i=Oi(t.sseOutcome,o.events,{truncated:o.truncated,reason:o.reason}),a={...n,outcome:i.outcome,outcomeReason:i.reason,terminal:i.terminal};if(i.outcome!==`success`)throw new ue(i.reason??`operation failed`,{...a,retryHint:`Not retried automatically. Check the affected resource or execution history before running this operation again.`});return a}case`binary`:return{status:o.status,requestId:o.requestId,...await r.processBinary(t,o)};default:throw Error(`unknown response kind`)}}),Ni=/^[A-Za-z0-9+/]*={0,2}$/,Pi=(e,t)=>t+8>e.length?null:{id:e.toString(`latin1`,t,t+4),size:e.readUInt32LE(t+4)},Fi=e=>{if(e.length<12||e.toString(`latin1`,0,4)!==`RIFF`||e.toString(`latin1`,8,12)!==`WAVE`)throw new x(`not_wav`,`the file is not a RIFF/WAVE file`);let t=null,n=null,r=12;for(;;){let i=Pi(e,r);if(i==null)break;let a=r+8,o=a+i.size;if(o>e.length)throw new x(`not_wav`,`the "${i.id}" chunk claims more bytes than the file holds`);if(i.id===`fmt `){if(o-a<16)throw new x(`not_wav`,`the fmt chunk is truncated`);let n=e.readUInt16LE(a);if((n===65534&&o-a>=26?e.readUInt16LE(a+24):n)!==1)throw new x(`unsupported_format`,`unsupported WAV format code ${String(n)} (only PCM is accepted)`);t={channels:e.readUInt16LE(a+2),sampleRateHz:e.readUInt32LE(a+4),bitsPerSample:e.readUInt16LE(a+14)}}else i.id===`data`&&(n=e.subarray(a,o));r=a+i.size+i.size%2}if(t==null||n==null)throw new x(`not_wav`,`the WAV file lacks a fmt or data chunk`);if(t.bitsPerSample!==16)throw new x(`unsupported_format`,`unsupported bit depth ${String(t.bitsPerSample)} (only 16-bit PCM is accepted)`);if(n.length===0)throw new x(`empty`,`the WAV file has no audio samples`);if(n.length%(2*t.channels)!=0)throw new x(`not_wav`,`the data chunk is not aligned to whole samples`);return{sampleRateHz:t.sampleRateHz,channels:t.channels,pcm:n}},Ii=(e,t)=>{let n=Buffer.alloc(44),r=2*t.channels;return n.write(`RIFF`,0,`latin1`),n.writeUInt32LE(36+e.length,4),n.write(`WAVE`,8,`latin1`),n.write(`fmt `,12,`latin1`),n.writeUInt32LE(16,16),n.writeUInt16LE(1,20),n.writeUInt16LE(t.channels,22),n.writeUInt32LE(t.sampleRateHz,24),n.writeUInt32LE(t.sampleRateHz*r,28),n.writeUInt16LE(r,32),n.writeUInt16LE(16,34),n.write(`data`,36,`latin1`),n.writeUInt32LE(e.length,40),Buffer.concat([n,e])},Li=(e,t)=>Math.round(e/(2*t.channels*t.sampleRateHz)*1e3),Ri=async(e,t,n,r)=>{let i=await sr(e,r.fileRoots,r.cwd,r.workspace);try{return await ar(i,t)}catch(e){throw e instanceof b&&e.kind===`too_large`?new x(`too_large`,`"${n}" exceeds ${String(t)} bytes`):e}},zi=async(e,t,n,r)=>{if(typeof t!=`string`||t===``)throw new x(`not_a_path`,`"${n}" must be a local file path`);let i=await Ri(t,e.format===`wav-pcm16`?e.maxBytes+44:e.maxBytes,n,r);if(e.format===`base64`){if(i.length===0)throw new x(`empty`,`"${n}" points at an empty file`);return i.toString(`base64`)}let a=Fi(i),o=e.pcm;if(o!=null&&(a.sampleRateHz!==o.sampleRateHz||a.channels!==o.channels))throw new x(`unsupported_format`,`"${n}" must be ${String(o.sampleRateHz)} Hz / ${String(o.channels)} channel PCM 16-bit WAV (got ${String(a.sampleRateHz)} Hz / ${String(a.channels)} channel)`);if(a.pcm.length>e.maxBytes)throw new x(`too_large`,`"${n}" holds ${String(a.pcm.length)} bytes of audio; at most ${String(e.maxBytes)} are accepted`);return{encoding:`pcm16le`,sampleRateHz:a.sampleRateHz,channels:a.channels,data:a.pcm.toString(`base64`)}},Bi=e=>e.replaceAll(`~1`,`/`).replaceAll(`~0`,`~`),Vi=async(e,t,n)=>{let r=async(e,t,i)=>{let[a,...o]=t;if(a==null)return n(e,i);if(a===`*`){if(!Array.isArray(e))return e;let t=[];for(let[n,a]of e.entries())t.push(await r(a,o,`${i}/${String(n)}`));return t}if(Array.isArray(e)){let t=Number(a);if(!Number.isInteger(t)||t<0||t>=e.length)return e;let n=[...e];return n[t]=await r(e[t],o,`${i}/${a}`),n}return D(e)&&E(e,a)?{...e,[a]:await r(e[a],o,`${i}/${a}`)}:e};return r(e,t.split(`/`).slice(1).map(e=>Bi(e)),``)},Hi=async(e,t,n)=>{let r=t;for(let t of e.input)r=await Vi(r,t.pointer,(e,r)=>zi(t,e,r,n));return D(r)?r:t},Ui=(e,t)=>{if(typeof e!=`string`||e.length%4!=0||!Ni.test(e))throw new x(`invalid_base64`,`"${t}" is not valid base64`);return Buffer.from(e,`base64`)},Wi=/* @__PURE__ */ new Map([[`audio/mpeg`,`.mp3`],[`audio/mp4`,`.m4a`],[`audio/ogg`,`.ogg`],[`audio/wav`,`.wav`],[`audio/webm`,`.webm`],[`image/png`,`.png`],[`image/jpeg`,`.jpg`],[`image/webp`,`.webp`],[`application/pdf`,`.pdf`]]),Gi=async(e,t,n)=>{let r=[],i=0;for(let[a,o]of t.entries()){let t=Ui(o,`${e.event??`body`}${e.pointer}[${String(a)}]`);if(e.format===`pcm16le`&&t.length%2!=0)throw new x(`unsupported_format`,`${e.event??`body`}${e.pointer} chunk ${String(a)} is not whole PCM 16-bit samples`);if(i+=t.length,i>n.maxBytes)throw new x(`too_large`,`inline output exceeds ${String(n.maxBytes)} bytes`);r.push(t)}let a=Buffer.concat(r),o=e.pcm,s=e.format===`pcm16le`&&o!=null,c=s?Ii(a,o):a,l=s?`audio/wav`:e.mediaType??`application/octet-stream`,u=s?`.wav`:Wi.get(l)??`.bin`;return{...await wr(new Blob([new Uint8Array(c)]).stream(),{outputDir:n.outputDir,fileName:xr(`${n.fileName}${u}`,`inline${u}`),maxBytes:n.maxBytes+44,timeoutMs:n.timeoutMs}),event:e.event,pointer:e.pointer,mediaType:l,chunks:t.length,durationMs:s?Li(a.length,o):null}},Ki=async(e,t,n)=>{let r=/* @__PURE__ */ new Set,i=[];for(let a of e.output){if(a.event==null)continue;r.add(a.event);let e=t.filter(e=>e.event===a.event).flatMap(e=>V(wt(e.data),a.pointer));e.length!==0&&i.push(await Gi(a,e,n))}return{events:t.filter(e=>e.event==null||!r.has(e.event)),files:i}},qi=async(e,t,n)=>{let r=t,i=[];for(let t of e.output){if(t.event!=null)continue;let e=V(r,t.pointer);if(e.length===0)continue;let a=await Gi(t,e,n);i.push(a),r=await Vi(r,t.pointer,()=>Promise.resolve(`[saved to ${a.path}]`))}return{body:r,files:i}},Ji={transferTimeoutMs:Ve,maxDownloadBytes:He,maxAutoDownloadsPerCall:20,maxInlineOutputBytes:33554432},Yi=e=>({config:e.config,auth:e.auth,client:e.client,logger:e.logger,preflight:async()=>{await xn(e.workspace,new Date(e.now())),await e.auth.assertLoggedIn()}}),Xi=async(e,t,n)=>ji(Yi(e),t,n),Zi=async(e,t,n,r)=>{let i=hr(n,t.transfer);if(i.length===0)return{};let a=[],o=[],s=[],c=[];for(let n of i){let i;try{i=pr(n.url,e.config)}catch(e){c.push({url:n.url,reason:e instanceof Error?e.message:`rejected`});continue}if(n.kind===`upload`){e.registry.register(n.url,`upload`,n.headers),a.push(n.url);continue}if(o.length>=r.maxAutoDownloadsPerCall){e.registry.register(n.url,`download`,{});continue}let l=xr(i.pathname.split(`/`).at(-1)??null,`${t.operationId}.bin`),u;try{u=await Tr({url:i,outputDir:e.config.outputDir,fileName:l,fetch:e.fetch,maxBytes:r.maxDownloadBytes,timeoutMs:r.transferTimeoutMs})}catch(r){if(!(r instanceof y))throw r;e.logger.warn(`automatic download failed`,{operationId:t.operationId,host:i.hostname,failure:r.kind}),e.registry.register(n.url,`download`,{}),s.push({url:n.url,failure:r.kind});continue}o.push({url:n.url,path:u.path,bytes:u.bytes,sha256Hex:u.sha256Hex,contentType:u.contentType})}return{...a.length===0?{}:{uploadUrls:a,uploadHint:`Call upload_file with one of these URLs and a local file path.`},...o.length===0?{}:{downloads:o},...s.length===0?{}:{failedDownloads:s,downloadHint:`The API response above is complete; only the automatic download failed. Retry it with download_file and the same URL.`},...c.length===0?{}:{rejectedTransferUrls:c}}},Qi=(e,t,n)=>({outputDir:e.config.outputDir,fileName:t.operationId,maxBytes:n.maxInlineOutputBytes,timeoutMs:n.transferTimeoutMs}),$i=e=>e.length===0?{}:{files:e},ea=(e,t)=>({prepareArguments:async(t,n)=>t.inlineFiles==null?n:await Hi(t.inlineFiles,n,{fileRoots:e.config.fileRoots,cwd:e.cwd,workspace:e.workspace}),processJson:async(n,r)=>{let i=await Zi(e,n,r,t),a=n.inlineFiles==null?{body:r,files:[]}:await qi(n.inlineFiles,r,Qi(e,n,t));return{body:a.body,extra:{...i,...$i(a.files)}}},processSse:async(n,r)=>{let i=n.inlineFiles==null?{events:r,files:[]}:await Ki(n.inlineFiles,r,Qi(e,n,t));return{events:i.events,extra:$i(i.files)}},processBinary:async(n,r)=>({file:{...await wr(r.body,{outputDir:e.config.outputDir,fileName:xr(r.fileName,`${n.operationId}.bin`),maxBytes:t.maxDownloadBytes,timeoutMs:t.transferTimeoutMs}),contentType:r.contentType,fileName:r.fileName}})}),ta=async(e,t,n,r=Ji)=>Mi(Yi(e),t,n,ea(e,r)),na=(e,t)=>`Flyle AIコンタクトセンターの公開 API を呼ぶツール群です。
|
|
6724
|
+
- 応対の状況を知りたい: dashboard / improve → get_agent_session_summary / list_chat_sessions`,mi={agents:[`create-agent`,`business-flow`],"agent-generation-jobs":[`create-agent`],"agent-generation-upload-urls":[`create-agent`],"agents/generation-jobs":[`create-agent`],"agents/configuration":[`business-flow`],"agents/agent-nodes":[`business-flow`],"agents/connectors":[`connectors`],"agents/forms":[`form-options`,`business-flow`],"agents/knowledge-bases":[`knowledge`],"agents/knowledge-ingest-job-summary":[`knowledge`],"agents/synonym-entries":[`synonym-dictionary`],"agents/voice-dictionary-entries":[`voice-dictionary`],"agents/preview-builds":[`validate`,`knowledge`],"agents/preview-chat-messages":[`validate`],"agents/preview-chat-sessions":[`validate`],"agents/preview-voice-messages":[`validate`,`audio-settings`],"agents/preview-form-submissions":[`validate`,`form-options`],"agents/eval-cases":[`validate`],"agents/eval-case-imports":[`validate`],"agents/eval-images":[`validate`],"agents/eval-runs":[`validate`],"agents/eval-run-case-results":[`validate`],"agents/eval-case-result-histories":[`validate`],"agents/improvement-analyses":[`validate`,`improve`],"agents/improvement-attempts":[`validate`,`improve`],"agents/improvement-attempt-summary":[`validate`,`improve`],"improvement-proposals":[`validate`,`improve`],"agents/revisions":[`history`],"agents/latest-publish":[`history`,`embed-publish`],"agents/publishes":[`history`,`embed-publish`],"agents/publish-readiness":[`embed-publish`,`validate`],"agents/web-chat-channel":[`design`,`audio-settings`],"agents/web-chat-credentials":[`embed-publish`,`security-model`],"agents/human-handoff-settings":[`human-handoff`],"team-names":[`team-management`,`human-handoff`],"agents/session-summary":[`dashboard`],"chat-sessions":[`improve`,`operator-console`],"credit-status":[`usage-limit`],"current-user":[`role-management`],"phone-settings":[`phone-channel`],"phone-numbers":[`phone-channel`],"sip-connections":[`phone-channel`]},hi=e=>{let[t,n]=e.split(`/`).filter(e=>e!==``&&!e.startsWith(`{`)).slice(2);return t===`agents`&&n!=null?`${t}/${n}`:t??``},gi=e=>{let t=mi[hi(e)];if(t==null)return null;let n=t.map(e=>`flygate/${e}`).join(`, `);return`操作の前に読む記事(${q}): ${n}`};let _i=null;const vi=()=>(_i??=ai(fi),_i),yi=()=>({isError:!1,payload:{guide:`${pi}\n\n# ご利用ガイドの記事一覧\n\n${ui(fi,di)}`}}),bi=(e,t)=>({isError:!1,payload:{results:ci(vi(),e,t)}}),xi=e=>{let t=oi(vi(),e);return t==null?{isError:!0,payload:{error:{kind:`guide_article_not_found`,message:`記事 "${e}" はありません。${G} の一覧か ${K} で記事を探し、"flygate/knowledge" の形式で指定してください。`}}}:{isError:!1,payload:{article:ii(t),title:t.title,group:t.group,url:t.url,body:li(t.body,t.url)}}},Si=()=>({isError:!0,payload:{error:{kind:`product_guide_required`,message:`製品の考え方を確認する前の操作は実行しません。先に ${G} を呼び、依頼に関係する記事を ${q} で読んでから、この操作をやり直してください。`}}}),Ci=e=>e.replaceAll(`~1`,`/`).replaceAll(`~0`,`~`),wi=e=>Array.isArray(e),Ti=(e,t)=>{if(t===``)return[{value:e,wildcardIndices:[]}];let n=t.split(`/`).slice(1).map(e=>Ci(e)),r=[{value:e,wildcardIndices:[]}];for(let e of n){let t=[];for(let{value:n,wildcardIndices:i}of r)if(e===`*`){if(wi(n))for(let[e,r]of n.entries())t.push({value:r,wildcardIndices:[...i,e]})}else if(wi(n)){let r=Number(e);Number.isInteger(r)&&r>=0&&r<n.length&&t.push({value:n[r],wildcardIndices:i})}else A(n)&&k(n,e)&&t.push({value:n[e],wildcardIndices:i});r=t}return r},Ei=(e,t)=>Ti(e,t).map(e=>e.value),Di=e=>{if(!A(e))return{};let t={};for(let[n,r]of de(e))typeof r==`string`&&(t[n]=r);return t},Oi=e=>e.join(`/`),ki=(e,t,n)=>{let r=t==null?[]:Ti(e,t),i=r[0]?.wildcardIndices.length??0,a=new Map(r.map(e=>[Oi(e.wildcardIndices),n(e.value)]));return e=>a.get(Oi(e.slice(0,i)))},Ai=(e,t)=>{if(t==null)return[];let n=Ti(e,t.urlPointer).filter(e=>typeof e.value==`string`),r=ki(e,t.headersPointer,Di),i=ki(e,t.namePointer,e=>typeof e==`string`?e:null);return n.map(e=>({url:e.value,kind:t.kind,headers:r(e.wildcardIndices)??{},name:i(e.wildcardIndices)??null}))},ji=(e,t)=>{let n=``,r=0,i=e.indexOf(`{`);for(;i!==-1;){let a=e.indexOf(`}`,i+1);if(a===-1)break;n+=a===i+1?e.slice(r,a+1):e.slice(r,i)+t(e.slice(i+1,a)),r=a+1,i=e.indexOf(`{`,r)}return n+e.slice(r)},Mi=(e,t)=>{if(typeof t==`string`)return t;if(typeof t==`number`||typeof t==`boolean`)return String(t);throw new T(`argument "${e}" must be a string, number, or boolean`)},Ni=/* @__PURE__ */ new Set([`.`,`..`,`%2e`,`.%2e`,`%2e.`,`%2e%2e`]),Pi=(e,t)=>{if(t===``||Ni.has(t.toLowerCase()))throw new T(`path parameter "${e}" must not be empty, "." or ".."`);return encodeURIComponent(t)},Fi=(e,t,n)=>{if(k(n,`tenantName`))throw new T(`"tenantName" is fixed by the server configuration`);let r=ji(t.pathTemplate,t=>{if(t===`tenantName`)return encodeURIComponent(e.tenantName);let r=n[t];if(r==null)throw new T(`path parameter "${t}" is required`);return Pi(t,Mi(t,r))}),i=[];for(let e of t.queryParams){let t=n[e];if(t!=null){if(Array.isArray(t))for(let n of t)i.push([e,Mi(e,n)]);else i.push([e,Mi(e,t)])}}let a=null,o=!1;if(t.wholeBodyField!=null){if(!k(n,t.wholeBodyField))throw new T(`argument "${t.wholeBodyField}" is required`);a=n[t.wholeBodyField],o=!0}else if(t.bodyFields!=null){let e={};for(let r of t.bodyFields)k(n,r)&&(e[r]=n[r]);a=e,o=!0}return{method:t.method,path:r,query:i,hasBody:o,body:a,responseKind:t.responseKind}},Ii=(e,t,n)=>{let r=t.findIndex(t=>t.event===e.terminalEvent),i=r===-1?null:t[r],a=r===-1?t:t.slice(0,r),o=i==null?null:wt(i.data),s=new Set(a.map(e=>e.event)),c=e.failureEvents.find(e=>s.has(e));if(c!=null)return{outcome:`failed`,reason:`received failure event "${c}"`,terminal:o};if(i==null)return n.truncated?{outcome:`unknown`,reason:`the stream was cut off by the client limit (${n.reason??`unknown`})`,terminal:o}:{outcome:`unknown`,reason:`the stream ended without the terminal event "${e.terminalEvent}"`,terminal:o};let l=e.successPointer==null?null:Ei(o,e.successPointer)[0];if(e.successPointer!=null&&l!==e.successValue)return{outcome:`failed`,reason:`"${e.terminalEvent}" ended with ${e.successPointer}=${JSON.stringify(l)} (expected ${JSON.stringify(e.successValue)})`,terminal:o};let u=e.requiredEvents.filter(e=>!s.has(e));return u.length>0?{outcome:`failed`,reason:`required event(s) missing before "${e.terminalEvent}": ${u.join(`, `)}`,terminal:o}:{outcome:`success`,reason:null,terminal:o}},Li=e=>({event:e.event,data:wt(e.data),...e.id==null?{}:{id:e.id}}),Ri=(e,t)=>{if(e instanceof b)return{isError:!0,payload:{error:{kind:`api`,...e.info}}};if(e instanceof x)return{isError:!0,payload:{error:{kind:`transport`,failure:e.kind,status:e.status,message:e.message}}};if(e instanceof S)return{isError:!0,payload:{error:{kind:`transfer`,failure:e.kind,status:e.status,message:e.message}}};if(e instanceof T)return{isError:!0,payload:{error:{kind:`invalid_arguments`,message:e.message}}};if(e instanceof C)return{isError:!0,payload:{error:{kind:`local_file`,failure:e.kind,message:e.message}}};if(e instanceof w)return{isError:!0,payload:{error:{kind:`inline_file`,failure:e.kind,message:e.message}}};if(e instanceof E)return{isError:!0,payload:{error:{kind:`workspace`,failure:e.kind,message:e.message}}};if(e instanceof D)return{isError:!0,payload:{error:{kind:`auth`,failure:e.kind,message:e.message}}};if(e instanceof se)return{isError:!0,payload:e.payload};if(e instanceof Error)return{isError:!0,payload:{error:{kind:`unexpected`,message:V(e.message,t)}}};throw e},zi=e=>e instanceof b?e.info.status:e instanceof x?e.status:null,Bi=e=>e instanceof b?e.info.code:e instanceof Error?e.name:`unknown`,Vi=async(e,t,n)=>{try{return await e.preflight(),{isError:!1,payload:await n()}}catch(n){let r=e.auth.secrets(),i=Ri(n,r),a=JSON.parse(V(JSON.stringify(i.payload),r));return e.logger.warn(`tool call failed`,{operationId:t,status:zi(n),code:Bi(n)}),{isError:!0,payload:a}}},Hi=async(e,t,n,{hooks:r,signal:i,canSend:a})=>{let o={attempts:0,requestBytes:0,responseBytes:0},s=async()=>{B(i??void 0);let s=await r.prepareArguments(t,n);B(i??void 0);let c=Fi(e.config,t,s),l=await e.client.request(c,i??void 0,a??void 0,o);switch(l.kind){case`json`:{let e=await r.processJson(t,l.body);return{status:l.status,requestId:l.requestId,body:e.body,...e.extra}}case`empty`:return{status:l.status,requestId:l.requestId};case`sse`:{let e=await r.processSse(t,l.events),n={status:l.status,requestId:l.requestId,events:e.events.map(e=>Li(e)),truncated:l.truncated,stopReason:l.reason,discardedIncomplete:l.discardedIncomplete,...e.extra};if(t.sseOutcome==null)return n;let i=Ii(t.sseOutcome,l.events,{truncated:l.truncated,reason:l.reason}),a={...n,outcome:i.outcome,outcomeReason:i.reason,terminal:i.terminal};if(i.outcome!==`success`)throw new se(i.reason??`operation failed`,{...a,retryHint:`Not retried automatically. Check the affected resource or execution history before running this operation again.`});return a}case`binary`:return{status:l.status,requestId:l.requestId,...await r.processBinary(t,l)};default:throw Error(`unknown response kind`)}};return{...await Vi(e,t.operationId,()=>s().catch(e=>{throw B(i??void 0),e})),metrics:o}},Ui=/^[A-Za-z0-9+/]*={0,2}$/,Wi=e=>typeof e==`string`&&e.length%4==0&&Ui.test(e),Gi=(e,t)=>{if(!Wi(e))throw new w(`invalid_base64`,`"${t}" is not valid base64`);return e},Ki=/* @__PURE__ */ new Map([[`audio/mpeg`,`.mp3`],[`audio/mp4`,`.m4a`],[`audio/ogg`,`.ogg`],[`audio/wav`,`.wav`],[`audio/webm`,`.webm`],[`image/png`,`.png`],[`image/jpeg`,`.jpg`],[`image/webp`,`.webp`],[`application/pdf`,`.pdf`]]),qi=e=>e.replaceAll(`~1`,`/`).replaceAll(`~0`,`~`),Ji=async(e,t,n)=>{let r=async(e,t,i)=>{let[a,...o]=t;if(a==null)return n(e,i);if(a===`*`){if(!Array.isArray(e))return e;let t=[];for(let[n,a]of e.entries())t.push(await r(a,o,`${i}/${String(n)}`));return t}if(Array.isArray(e)){let t=Number(a);if(!Number.isInteger(t)||t<0||t>=e.length)return e;let n=[...e];return n[t]=await r(e[t],o,`${i}/${a}`),n}return A(e)&&k(e,a)?{...e,[a]:await r(e[a],o,`${i}/${a}`)}:e};return r(e,t.split(`/`).slice(1).map(e=>qi(e)),``)},Yi=(e,t)=>{let n=/* @__PURE__ */ new Set,r=[];for(let i of e.output){if(i.event==null)continue;n.add(i.event);let e=t.filter(e=>e.event===i.event).flatMap(e=>Ei(wt(e.data),i.pointer));e.length>0&&r.push({output:i,chunks:e})}return{events:t.filter(e=>e.event==null||!n.has(e.event)),outputs:r}},Xi=(e,t)=>e.output.flatMap(e=>{if(e.event!=null)return[];let n=Ei(t,e.pointer);return n.length===0?[]:[{output:e,chunks:n}]}),Zi=(e,t,n)=>String.fromCodePoint(...e.subarray(t,n)),Qi=e=>new DataView(e.buffer,e.byteOffset,e.byteLength),$i=e=>{if(e.length<12||Zi(e,0,4)!==`RIFF`||Zi(e,8,12)!==`WAVE`)throw new w(`not_wav`,`the file is not a RIFF/WAVE file`);let t=Qi(e),n=null,r=null,i=12;for(;i+8<=e.length;){let a=Zi(e,i,i+4),o=t.getUint32(i+4,!0),s=i+8,c=s+o;if(c>e.length)throw new w(`not_wav`,`the "${a}" chunk claims more bytes than the file holds`);if(a===`fmt `){if(o<16)throw new w(`not_wav`,`the fmt chunk is truncated`);let e=t.getUint16(s,!0);if((e===65534&&o>=26?t.getUint16(s+24,!0):e)!==1)throw new w(`unsupported_format`,`unsupported WAV format code ${String(e)} (only PCM is accepted)`);n={channels:t.getUint16(s+2,!0),sampleRateHz:t.getUint32(s+4,!0),bitsPerSample:t.getUint16(s+14,!0)}}else a===`data`&&(r=e.subarray(s,c));i=c+o%2}if(n==null||r==null)throw new w(`not_wav`,`the WAV file lacks a fmt or data chunk`);if(n.channels===0||n.sampleRateHz===0)throw new w(`not_wav`,`the WAV file declares no channels or sample rate`);if(n.bitsPerSample!==16)throw new w(`unsupported_format`,`unsupported bit depth ${String(n.bitsPerSample)} (only 16-bit PCM is accepted)`);if(r.length===0)throw new w(`empty`,`the WAV file has no audio samples`);if(r.length%(2*n.channels)!=0)throw new w(`not_wav`,`the data chunk is not aligned to whole samples`);return{sampleRateHz:n.sampleRateHz,channels:n.channels,pcm:r}},ea=(e,t,n)=>{for(let r=0;r<n.length;r+=1)e[t+r]=n.codePointAt(r)??0},ta=(e,t)=>{let n=new Uint8Array(44+e.length),r=Qi(n),i=2*t.channels;return ea(n,0,`RIFF`),r.setUint32(4,36+e.length,!0),ea(n,8,`WAVE`),ea(n,12,`fmt `),r.setUint32(16,16,!0),r.setUint16(20,1,!0),r.setUint16(22,t.channels,!0),r.setUint32(24,t.sampleRateHz,!0),r.setUint32(28,t.sampleRateHz*i,!0),r.setUint16(32,i,!0),r.setUint16(34,16,!0),ea(n,36,`data`),r.setUint32(40,e.length,!0),n.set(e,44),n},na=(e,t)=>Math.round(e/(2*t.channels*t.sampleRateHz)*1e3),ra=e=>Buffer.from(e.buffer,e.byteOffset,e.byteLength),ia=e=>{let t=$i(e);return{sampleRateHz:t.sampleRateHz,channels:t.channels,pcm:ra(t.pcm)}},aa=(e,t)=>ra(ta(e,t)),oa=async(e,t,n,r)=>{let i=await sr(e,r.fileRoots,r.cwd,r.workspace);try{return await ar(i,t)}catch(e){throw e instanceof C&&e.kind===`too_large`?new w(`too_large`,`"${n}" exceeds ${String(t)} bytes`):e}},sa=async(e,t,n,r)=>{if(typeof t!=`string`||t===``)throw new w(`not_a_path`,`"${n}" must be a local file path`);let i=await oa(t,e.format===`wav-pcm16`?e.maxBytes+44:e.maxBytes,n,r);if(e.format===`base64`){if(i.length===0)throw new w(`empty`,`"${n}" points at an empty file`);return i.toString(`base64`)}let a=ia(i),o=e.pcm;if(o!=null&&(a.sampleRateHz!==o.sampleRateHz||a.channels!==o.channels))throw new w(`unsupported_format`,`"${n}" must be ${String(o.sampleRateHz)} Hz / ${String(o.channels)} channel PCM 16-bit WAV (got ${String(a.sampleRateHz)} Hz / ${String(a.channels)} channel)`);if(a.pcm.length>e.maxBytes)throw new w(`too_large`,`"${n}" holds ${String(a.pcm.length)} bytes of audio; at most ${String(e.maxBytes)} are accepted`);return{encoding:`pcm16le`,sampleRateHz:a.sampleRateHz,channels:a.channels,data:a.pcm.toString(`base64`)}},ca=async(e,t,n)=>{let r=t;for(let t of e.input)r=await Ji(r,t.pointer,(e,r)=>sa(t,e,r,n));return A(r)?r:t},la=(e,t)=>Buffer.from(Gi(e,t),`base64`),ua=async(e,t,n)=>{let r=[],i=0;for(let[a,o]of t.entries()){let t=la(o,`${e.event??`body`}${e.pointer}[${String(a)}]`);if(e.format===`pcm16le`&&t.length%2!=0)throw new w(`unsupported_format`,`${e.event??`body`}${e.pointer} chunk ${String(a)} is not whole PCM 16-bit samples`);if(i+=t.length,i>n.maxBytes)throw new w(`too_large`,`inline output exceeds ${String(n.maxBytes)} bytes`);r.push(t)}let a=Buffer.concat(r),o=e.pcm,s=e.format===`pcm16le`&&o!=null,c=s?aa(a,o):a,l=s?`audio/wav`:e.mediaType??`application/octet-stream`,u=s?`.wav`:Ki.get(l)??`.bin`;return{...await Sr(new Blob([new Uint8Array(c)]).stream(),{outputDir:n.outputDir,fileName:yr(`${n.fileName}${u}`,`inline${u}`),maxBytes:n.maxBytes+44,timeoutMs:n.timeoutMs}),event:e.event,pointer:e.pointer,mediaType:l,chunks:t.length,durationMs:s?na(a.length,o):null}},da=async(e,t,n)=>{let r=Yi(e,t),i=[];for(let{output:e,chunks:t}of r.outputs)i.push(await ua(e,t,n));return{events:r.events,files:i}},fa=async(e,t,n)=>{let r=t,i=[];for(let{output:a,chunks:o}of Xi(e,t)){let e=await ua(a,o,n);i.push(e),r=await Ji(r,a.pointer,()=>Promise.resolve(`[saved to ${e.path}]`))}return{body:r,files:i}},pa={transferTimeoutMs:Be,maxDownloadBytes:Ve,maxAutoDownloadsPerCall:20,maxInlineOutputBytes:33554432},ma=e=>({config:e.config,auth:e.auth,client:e.client,logger:e.logger,preflight:async()=>{await xn(e.workspace,new Date(e.now())),await e.auth.assertLoggedIn()}}),ha=async(e,t,n)=>Vi(ma(e),t,n),ga=async(e,t,n,r)=>{let i=Ai(n,t.transfer);if(i.length===0)return{};let a=[],o=[],s=[],c=[];for(let n of i){let i;try{i=pr(n.url,e.config)}catch(e){c.push({url:n.url,reason:e instanceof Error?e.message:`rejected`});continue}if(n.kind===`upload`){e.registry.register(n.url,`upload`,n.headers),a.push(n.url);continue}if(o.length>=r.maxAutoDownloadsPerCall){e.registry.register(n.url,`download`,{});continue}let l=yr(n.name??i.pathname.split(`/`).at(-1)??null,`${t.operationId}.bin`),u;try{u=await Cr({url:i,outputDir:e.config.outputDir,fileName:l,fetch:e.fetch,maxBytes:r.maxDownloadBytes,timeoutMs:r.transferTimeoutMs})}catch(r){if(!(r instanceof S))throw r;e.logger.warn(`automatic download failed`,{operationId:t.operationId,host:i.hostname,failure:r.kind}),e.registry.register(n.url,`download`,{}),s.push({url:n.url,failure:r.kind});continue}o.push({url:n.url,path:u.path,bytes:u.bytes,sha256Hex:u.sha256Hex,contentType:u.contentType})}return{...a.length===0?{}:{uploadUrls:a,uploadHint:`Call upload_file with one of these URLs and a local file path.`},...o.length===0?{}:{downloads:o},...s.length===0?{}:{failedDownloads:s,downloadHint:`The API response above is complete; only the automatic download failed. Retry it with download_file and the same URL.`},...c.length===0?{}:{rejectedTransferUrls:c}}},_a=(e,t,n)=>({outputDir:e.config.outputDir,fileName:t.operationId,maxBytes:n.maxInlineOutputBytes,timeoutMs:n.transferTimeoutMs}),va=e=>e.length===0?{}:{files:e},ya=(e,t)=>({prepareArguments:async(t,n)=>t.inlineFiles==null?n:await ca(t.inlineFiles,n,{fileRoots:e.config.fileRoots,cwd:e.cwd,workspace:e.workspace}),processJson:async(n,r)=>{let i=await ga(e,n,r,t),a=n.inlineFiles==null?{body:r,files:[]}:await fa(n.inlineFiles,r,_a(e,n,t));return{body:a.body,extra:{...i,...va(a.files)}}},processSse:async(n,r)=>{let i=n.inlineFiles==null?{events:r,files:[]}:await da(n.inlineFiles,r,_a(e,n,t));return{events:i.events,extra:va(i.files)}},processBinary:async(n,r)=>({file:{...await Sr(r.body,{outputDir:e.config.outputDir,fileName:yr(r.fileName,`${n.operationId}.bin`),maxBytes:t.maxDownloadBytes,timeoutMs:t.transferTimeoutMs}),contentType:r.contentType,fileName:r.fileName}})}),ba=async(e,t,n,r=pa)=>{let{isError:i,payload:a}=await Hi(ma(e),t,n,{hooks:ya(e,r),signal:null,canSend:null});return{isError:i,payload:a}},xa=(e,t)=>`Flyle AIコンタクトセンターの公開 API を呼ぶツール群です。
|
|
6548
6725
|
- 作業を始める前に必ず ${G} で製品の考え方とご利用ガイドの記事一覧を確認し、依頼に関係する記事を ${q} で読んでください。公開 API の操作は ${G} を呼ぶまで実行されません。ツールに無い操作は代わりの手順を組み立てず、該当する記事を示して管理画面での操作を案内してください。
|
|
6549
6726
|
- 接続先テナントは「${e}」、環境(公開 API のホスト)は「${t}」です。テナント・環境・ログインはサーバー起動時に固定されており、ツール引数でテナントを指定することはできません。
|
|
6550
6727
|
- この作業ディレクトリは「${e}」専用です。別の顧客(テナント)の情報・ファイル・記憶をこのテナントへの書き込みに使わないでください。別テナントの作業は別ディレクトリの別セッションで行います。
|
|
@@ -6554,7 +6731,7 @@ Flyle AIコンタクトセンターは、Web サイトのチャットや電話
|
|
|
6554
6731
|
- 書き込み系ツールは自動再送しません。タイムアウトや transport エラーの後は、対象を再取得して状態を確認してください。
|
|
6555
6732
|
- 一覧は各ツールの入力スキーマと応答に従って取得してください。cursor / limit+offset / ページングなしの全件取得があります。
|
|
6556
6733
|
- 大きな JSON 結果は出力ディレクトリに全文を保存し、保存先と先頭部分を返します。全文は保存ファイルを参照してください。
|
|
6557
|
-
-
|
|
6734
|
+
- エージェントの応答や振り分けを変える依頼(改善要望に限らず、新しい問い合わせへの対応・指示文の追記・ルーティングの変更なども含む)は、必ず検証ケースから始めます。ケースが無いと、あとで同じ問い合わせが壊れても気付けないためです。現在の設定・既存ケースの取得 → 追加するケース(問い合わせの例と期待する応答)と修正案を両方示して合意を得る → create_eval_case / import_eval_cases でケースを保存 → 変更前の検証 → 合意した修正 → プレビュー作成完了の確認 → 全ケースの再検証の順に進め、ケースを保存する前に設定を書き換えないでください。既存ケースで足りる場合は、どのケースで確かめるかを示してください。エージェントの設定(ID 情報・ノード・ルーティング・フォームなど)の変更は、プレビューと検証に直ちに反映されます。プレビュービルドはナレッジベースの検索用インデックスだけを作るため、設定だけを変えても previewRevisionSerial は変わりません。再ビルドが必要なのは、参照するナレッジベースや文書を変えたときです。create_improvement_analysis は分析結果を返すだけで、検証ケースや設定を保存しません。
|
|
6558
6735
|
- 改善提案は内容と get_improvement_proposal_plan を確認し、根拠のある actionIndexes だけを resolve_improvement_proposal で適用してください。検証の受付だけで合格と判断せず、get_eval_run と list_eval_run_case_results で完了・ケース別結果を確認してください。
|
|
6559
|
-
- ファイル取込は inspect_local_file → create_knowledge_upload_urls → upload_file → create_knowledge_import の順に進め、取込と文書の処理完了を確認します。API の byteSize には sizeBytes、checksumSha256 には sha256Hex を渡します(sha256Base64 ではありません)。URL の発行と upload_file は同じ MCP 接続で行ってください。ダウンロード系はファイルパスを返します。`,
|
|
6560
|
-
引数なしで起動すると MCP サーバー(stdio)として動きます。`,2);await
|
|
6736
|
+
- ファイル取込は inspect_local_file → create_knowledge_upload_urls → upload_file → create_knowledge_import の順に進め、取込と文書の処理完了を確認します。API の byteSize には sizeBytes、checksumSha256 には sha256Hex を渡します(sha256Base64 ではありません)。URL の発行と upload_file は同じ MCP 接続で行ってください。ダウンロード系はファイルパスを返します。`,Sa=e=>A(e)&&e.type===`object`&&A(e.properties),J=(e,t)=>{if(!Sa(e))throw Error(`${t}: input schema must be an object schema`);return e},Ca={binaryResponse:`ファイルを出力ディレクトリに保存し、パスと sha256 を返します。`,downloadTransfer:`応答に含まれる署名付き URL からその場でダウンロードし、ファイルパスを返します。`,uploadTransfer:`応答のアップロード URL は upload_file ツールで使えます(15 分・1 回限り)。`,inlineInput:e=>e.format===`wav-pcm16`&&e.pcm!=null?`"${e.pointer}" にはローカル WAV ファイルのパス(PCM 16bit / ${String(e.pcm.sampleRateHz)} Hz / ${String(e.pcm.channels)}ch、音声 ${String(e.maxBytes)} バイト以内)を渡します。base64 化はこのサーバーが行います。`:`"${e.pointer}" にはローカルファイルのパス(${String(e.maxBytes)} バイト以内)を渡します。base64 化はこのサーバーが行います。`,inlineOutput:`応答に埋め込まれた音声 / ファイルは出力ディレクトリに保存し、パスだけを返します(base64 は結果に含めません)。`},wa=e=>{let t=gi(e.pathTemplate),n=ni(e,Ca);return t==null?n:`${n}\n\n${t}`},Ta=e=>{let t=e.slice(0,4096),n=t.codePointAt(t.length-1)??0;return n>=55296&&n<=56319?t.slice(0,-1):t},Ea=e=>new ReadableStream({start(t){t.enqueue(e),t.close()}}),Da=(e,t,n)=>({content:[{type:`text`,text:JSON.stringify({environment:e.environment,tenantName:e.tenantName})},{type:`text`,text:t}],isError:n}),Y=async(e,t)=>{let{secrets:n}=t,r=V(JSON.stringify(e.payload,null,2)??`null`,n);if(r.length<=1048576)return Da(t,r,e.isError);let i=Buffer.from(V(JSON.stringify(e.payload)??`null`,n),`utf8`),a={totalChars:r.length,preview:Ta(r)};try{let n=await Sr(Ea(i),{outputDir:t.outputDir,fileName:t.fileName,maxBytes:t.maxFileBytes,timeoutMs:Be});return Da(t,JSON.stringify({file:{...n,format:`json`},...a},null,2),e.isError)}catch(e){let n=e instanceof S?e.kind:`unexpected`;return t.logger.warn(`tool result could not be saved`,{fileName:t.fileName,failure:n,bytes:i.byteLength}),Da(t,JSON.stringify({error:{kind:`result_not_saved`,failure:n,message:`The full result was not saved; only the preview below is available. The operation may have completed; check its state before retrying.`},...a},null,2),!0)}},X=(e,t)=>({environment:z(e.config.baseUrl),tenantName:e.config.tenantName,outputDir:e.config.outputDir,fileName:`${t}.result.json`,logger:e.logger,secrets:e.auth.secrets(),maxFileBytes:67108864}),Z=e=>A(e)?e:{},Oa=(e,t)=>{let n=e[t];if(typeof n!=`string`||n===``)throw new T(`argument "${t}" is required`);return n},ka={inspectLocalFile:{type:`object`,properties:{path:{type:`string`,description:`ローカルファイルのパス(相対パスは作業ディレクトリ基準)。`}},required:[`path`],additionalProperties:!1},uploadFile:{type:`object`,properties:{url:{type:`string`,description:`直前の API 応答で返されたアップロード URL。`},path:{type:`string`,description:`アップロードするローカルファイルのパス。`}},required:[`url`,`path`],additionalProperties:!1},downloadFile:{type:`object`,properties:{url:{type:`string`,description:`直前の API 応答で返されたダウンロード URL。`},fileName:{type:`string`,description:`保存名(省略時は URL の末尾から決める)。`}},required:[`url`],additionalProperties:!1}},Aa=(e,t)=>{e.registerTool(`inspect_local_file`,{title:`ローカルファイルの検査`,description:`アップロード前にローカルファイルの名前・サイズ・sha256(hex / base64)・MIME を返します。API の byteSize には sizeBytes、checksumSha256 には sha256Hex を渡してください。読めるのは起動設定の根ディレクトリ配下だけです。`,inputSchema:y(J(ka.inspectLocalFile,`inspect_local_file`)),annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},async e=>{let n=Z(e);return Y(await ha(t,`inspect_local_file`,()=>dr(Oa(n,`path`),t.config.fileRoots,t.cwd,t.workspace)),X(t,`inspect_local_file`))}),e.registerTool(`upload_file`,{title:`署名付き URL へアップロード`,description:`直前の API 応答で返されたアップロード URL へローカルファイルを PUT します。URL は応答由来のものだけを 15 分・1 回限りで受け付け、認証ヘッダは付けません。`,inputSchema:y(J(ka.uploadFile,`upload_file`)),annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!1}},async e=>{let n=Z(e);return Y(await ha(t,`upload_file`,async()=>{let e=Oa(n,`url`),r=await sr(Oa(n,`path`),t.config.fileRoots,t.cwd,t.workspace),i=t.registry.take(e,`upload`);return await _r({url:new URL(e),headers:i.headers,filePath:r,fetch:t.fetch,maxBytes:536870912,timeoutMs:Be})}),X(t,`upload_file`))}),e.registerTool(`download_file`,{title:`署名付き URL からダウンロード`,description:`直前の API 応答で返されたダウンロード URL からファイルを取得し、出力ディレクトリに保存してパスを返します。URL は応答由来のものだけを受け付けます。`,inputSchema:y(J(ka.downloadFile,`download_file`)),annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},async e=>{let n=Z(e);return Y(await ha(t,`download_file`,async()=>{let e=Oa(n,`url`);t.registry.take(e,`download`);let r=new URL(e),i=typeof n.fileName==`string`?n.fileName:null;return await Cr({url:r,outputDir:t.config.outputDir,fileName:yr(i??r.pathname.split(`/`).at(-1)??null,`download.bin`),fetch:t.fetch,maxBytes:Ve,timeoutMs:Be})}),X(t,`download_file`))})},ja={readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},Ma={getProductGuide:{type:`object`,properties:{},additionalProperties:!1},searchProductGuide:{type:`object`,properties:{query:{type:`string`,minLength:1,description:`検索キーワード(例: "検証ケース 改善提案")。`},maxResults:{type:`integer`,minimum:1,maximum:20,description:`返す記事の最大数(既定 10)。`}},required:[`query`],additionalProperties:!1},readProductGuideArticle:{type:`object`,properties:{article:{type:`string`,minLength:1,description:`記事(例: "flygate/knowledge")。`}},required:[`article`],additionalProperties:!1}},Na=(e,t,n)=>{e.registerTool(G,{title:`製品の全体像とご利用ガイドの記事一覧`,description:`作業の最初に呼びます。Flyle AIコンタクトセンターの考え方(エージェント・業務フロー・ナレッジ・検証・公開などの概念)、この MCP サーバーでできること・できないこと、よくある依頼の進め方と、ご利用ガイドの全記事の一覧を返します。これを呼ぶまで公開 API の操作は実行されません。`,inputSchema:y(J(Ma.getProductGuide,G)),annotations:ja},()=>(n(),Y(yi(),X(t,G)))),e.registerTool(K,{title:`ご利用ガイドの検索`,description:`ご利用ガイドの記事をキーワードで探します。空白区切りの複数キーワードは、より多く一致した記事を先に返します。記事の全文は ${q} で読みます。`,inputSchema:y(J(Ma.searchProductGuide,K)),annotations:ja},e=>{let n=Z(e),r=typeof n.query==`string`?n.query:``,i=typeof n.maxResults==`number`?n.maxResults:10;return Y(bi(r,i),X(t,K))}),e.registerTool(q,{title:`ご利用ガイドの記事を読む`,description:`ご利用ガイドの記事を全文読みます。記事は ${G} の一覧や ${K} の結果にある "flygate/knowledge" 形式で指定します。管理画面での操作手順・制約・用語の正はこの記事です。`,inputSchema:y(J(Ma.readProductGuideArticle,q)),annotations:ja},e=>{let n=Z(e).article;return Y(xi(typeof n==`string`?n:``),X(t,q))})},Pa=(e,t)=>{let n=new ae({name:`flyle-ai-contact-center`,version:Pe},{capabilities:{tools:{}},instructions:xa(e.config.tenantName,z(e.config.baseUrl))}),r=!1;Na(n,e,()=>{r=!0});for(let i of ce(t))n.registerTool(i.operationId,{title:i.summary,description:wa(i),inputSchema:y(J(i.inputSchema,i.operationId)),annotations:ri(i)},async t=>Y(r?await ba(e,i,Z(t)):Si(),X(e,i.operationId)));return Aa(n,e),n},Q=e=>new Promise(t=>setTimeout(t,e)),$=()=>Date.now(),Fa=()=>({cwd:process.cwd(),homeDir:e(),hostname:t(),username:n().username,now:()=>/* @__PURE__ */ new Date}),Ia=()=>ot({platform:process.platform,env:process.env,homeDir:e()}),La=(e,t)=>{console.error(e),process.exit(t)},Ra=async e=>{try{return await lt(e)}catch(e){if(e instanceof D&&e.kind===`login_required`)return null;throw e}},za=async e=>{let{cwd:t}=e;$e(process.env);let n=await bn(e);if(n==null)throw new R("この作業ディレクトリはまだログインしていません。このディレクトリで `npx @flyle/ai-contact-center-mcp@latest login --tenant <テナント名>` を実行してから、MCP サーバーを起動し直してください。");let r=tt(process.env,t,n),i=st(Ia(),n.workspaceId),a=await Ra(i);return a!=null&&Yt(a,r.baseUrl,r.tenantName),{config:r,workspace:n,credentialsFile:i,loggedIn:a!=null}},Ba=async()=>{let e=Fa(),{cwd:t}=e,n=await za(e).catch(e=>La(On(e),1)),{config:i,workspace:a,credentialsFile:o}=n,s=()=>[],c=Tr(()=>s()),l=Zt({credentialsFile:o,baseUrl:i.baseUrl,tenantName:i.tenantName,tokenClient:tn({config:i,auth:null,workspaceId:a.workspaceId,fetch:globalThis.fetch,now:$,sleep:Q,logger:c},Ut),now:$,lock:pt($,Q)});s=l.secrets;let u=Yr(),d={config:i,auth:l,client:tn({config:i,auth:l,workspaceId:a.workspaceId,fetch:globalThis.fetch,now:$,sleep:Q,logger:c}),registry:fr($),fetch:globalThis.fetch,logger:c,now:$,cwd:t,workspace:a},f=r(()=>Pa(d,u));c.info(`flygate mcp server started`,{environment:z(i.baseUrl),tenantName:i.tenantName,workspace:a.root,loggedIn:n.loggedIn,operations:ce(u).length});let p=!1,m=()=>{p||(p=!0,Promise.race([l.whenIdle(),Q(25e3)]).then(()=>f.close()).catch(O).finally(()=>process.exit(0)))};process.on(`SIGINT`,m),process.on(`SIGTERM`,m),process.stdin.once(`end`,m)},Va=()=>({env:process.env,workspaceEnv:Fa(),credentialsDir:Ia(),fetch:globalThis.fetch,now:$,sleep:Q,lock:pt($,Q),logger:Tr(()=>[]),out:e=>console.log(e),err:e=>console.error(e)}),Ha=async e=>{try{await e()}catch(e){La(On(e),1)}};await(async()=>{let[e,...t]=process.argv.slice(2);if(e==null){await Ba();return}let n={login:()=>er({...Va(),argv:t,openBrowser:e=>$t(e),callbackTimeoutMs:6e5}),logout:()=>An(Va()),status:()=>rr(Va())},r=k(n,e)?n[e]:null;if(r==null)return La(`使い方: flyle-ai-contact-center-mcp [login [--tenant <テナント名>] [--api-base-url <URL>] | logout | status]
|
|
6737
|
+
引数なしで起動すると MCP サーバー(stdio)として動きます。`,2);await Ha(async()=>{$e(process.env),await r()})})();export{};
|
package/manifest.json.br
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@flyle/ai-contact-center-mcp","version":"0.5.
|
|
1
|
+
{"name":"@flyle/ai-contact-center-mcp","version":"0.5.1","description":"MCP server for the Flyle AI Contact Center public API","keywords":["flyle","mcp","modelcontextprotocol"],"license":"SEE LICENSE IN LICENSE","author":"Flyle.inc","repository":{"type":"git","url":"git+https://github.com/flyle-io/flyle-nexus.git","directory":"apps/flygate/mcp"},"type":"module","engines":{"node":">=22.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"bin":{"flyle-ai-contact-center-mcp":"./main.js"},"dependencies":{"@modelcontextprotocol/server":"2.3.1"}}
|