@lark-apaas/openclaw-extension-miaoda-coding 1.0.3-beta.2 → 1.0.3-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +5 -5
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{createRequire as e}from"node:module";import{spawn as t}from"node:child_process";import n from"node:fs";import r,{join as i,resolve as a}from"node:path";import{appendFile as o,mkdir as s,readFile as c,readdir as l,rm as u,writeFile as d}from"node:fs/promises";var f=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),p=e(import.meta.url);function m(){return a(process.env.OPENCLAW_STATE_DIR||process.cwd())}function h(e){return i(e,`.agent`)}function g(e,t){return i(e,t)}function _(e){let t=typeof e.workspaceDir==`string`&&e.workspaceDir!==``,n=typeof e.agentDir==`string`&&e.agentDir!==``;if(!t||!n)throw Error(`resolveToolPaths: workspaceDir and agentDir are required in tool factory context`);return{workspaceDir:e.workspaceDir,agentDir:e.agentDir,agentId:e.agentId,sessionKey:e.sessionKey}}var v=f(((e,t)=>{var n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,o=(e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})},s=(e,t,o,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of i(t))!a.call(e,c)&&c!==o&&n(e,c,{get:()=>t[c],enumerable:!(s=r(t,c))||s.enumerable});return e},c=e=>s(n({},`__esModule`,{value:!0}),e),l={};o(l,{DEFAULT_CLOCK_TOLERANCE_SEC:()=>f,DEFAULT_JWT_EXPIRE_TIME_MS:()=>d,HttpClient:()=>N,HttpError:()=>A,generateJWTToken:()=>h,parseJWTTokenWithVerify:()=>g,registerPlatformPlugin:()=>T,resolvePlatformBaseURL:()=>w}),t.exports=c(l);var u=p(`crypto`),d=1800*1e3,f=60,m={alg:`HS256`,typ:`JWT`};function h(e,t){let n=Math.floor(Date.now()/1e3),r={...e,iss:e.access_key,iat:n,nbf:n,exp:n+Math.floor(t.expireTimeMs/1e3),jti:(0,u.randomUUID)()},i=v(JSON.stringify(m)),a=v(JSON.stringify(r));return`${i}.${a}.${_(`${i}.${a}`,t.secretKey)}`}function g(e,t,n){let r=e.split(`.`);if(r.length!==3)throw Error(`invalid JWT token format`);let[i,a,o]=r;if(JSON.parse(y(i)).alg!==`HS256`)throw Error(`unsupported JWT alg`);let s=_(`${i}.${a}`,t.secretKey),c=Buffer.from(s),l=Buffer.from(o);if(c.length!==l.length||!(0,u.timingSafeEqual)(c,l))throw Error(`JWT signature verification failed`);let d=JSON.parse(y(a));if(!n?.skipExpiration){let e=n?.clockTolerance??f,t=Math.floor(Date.now()/1e3);if(d.exp!==void 0&&d.exp+e<t)throw Error(`JWT token expired at ${new Date(d.exp*1e3).toISOString()}`);if(d.nbf!==void 0&&d.nbf-e>t)throw Error(`JWT token not yet valid, will be valid at ${new Date(d.nbf*1e3).toISOString()}`);if(d.iat!==void 0&&d.iat-e>t)throw Error(`JWT token issued in the future at ${new Date(d.iat*1e3).toISOString()}`)}return d}function _(e,t){return(0,u.createHmac)(`sha256`,t).update(e).digest(`base64`).replace(/=/g,``).replace(/\+/g,`-`).replace(/\//g,`_`)}function v(e){return Buffer.from(e).toString(`base64`).replace(/=/g,``).replace(/\+/g,`-`).replace(/\//g,`_`)}function y(e){let t=(4-(e.length%4||4))%4,n=`${e}${`=`.repeat(t)}`.replace(/-/g,`+`).replace(/_/g,`/`);return Buffer.from(n,`base64`).toString(`utf8`)}var b=class{cache=new Map;config;constructor(e){this.config={refreshBeforeMs:300*1e3,...e}}getToken(e){let t=this.getCacheKey(e),n=this.cache.get(t),r=Date.now();if(n&&n.expiresAtMs-r>this.config.refreshBeforeMs)return n.token;let i=h(e,this.config),a=r+this.config.expireTimeMs;return this.cache.set(t,{token:i,expiresAtMs:a}),i}clearCache(){this.cache.clear()}clearCacheFor(e){let t=this.getCacheKey(e);this.cache.delete(t)}getCacheKey(e){return[e.access_key,e.tenant_id?.toString()||``,e.user_id||``,e.app_id||``,e.app_env||``,e.sandbox_id||``].join(`:`)}getCacheStats(){let e=Date.now(),t=0,n=0;for(let r of this.cache.values())r.expiresAtMs>e?t++:n++;return{total:this.cache.size,valid:t,expired:n}}},x=`FORCE_AUTHN_INNERAPI_DOMAIN`,S=`FORCE_AUTHN_ACCESS_KEY`,C=`FORCE_AUTHN_ACCESS_SECRET`;function w(e){if(!e?.enabled)return e?.baseURL;if(e.baseURL)return e.baseURL;let t=e.domainEnv||x,n=process.env[t];if(!n)throw Error(`\u5E73\u53F0\u6A21\u5F0F\u9700\u8981\u57FA\u7840\u57DF\u540D\uFF0C\u8BF7\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF ${t}`);return n}function T(e,t){if(!t.enabled)return;E(`platform.defaultClaims`,t.defaultClaims);let n=t.accessKeyEnv||S,r=t.secretKeyEnv||C,i=t.accessKey??(process.env[n]||``),a=new b({accessKey:i,secretKey:t.secretKey??(process.env[r]||``),expireTimeMs:t.expireTimeMs??d,refreshBeforeMs:t.refreshBeforeMs});return e.request.use(e=>{E(`request.platformAuth.customClaims`,e.platformAuth?.customClaims);let n={...t.defaultClaims||{},...e.platformAuth?.customClaims||{},access_key:i},r=a.getToken(n),o={...e.headers,Authorization:`Bearer ${r}`,"x-api-key":i};return{...e,headers:o}}),a}function E(e,t){if(t&&Object.prototype.hasOwnProperty.call(t,`access_key`))throw Error(`${e} \u4E0D\u5141\u8BB8\u8BBE\u7F6E access_key`)}var D=class{interceptors=[];use(e,t){return this.interceptors.push({onFulfilled:e,onRejected:t}),this.interceptors.length-1}eject(e){this.interceptors[e]&&(this.interceptors[e]=null)}clear(){this.interceptors=[]}forEach(e){this.interceptors.forEach(t=>{t!==null&&e(t)})}};function O(e){if(typeof e!=`object`||!e)return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function k(e){if(!e)return{};if(e instanceof Headers){let t={};return e.forEach((e,n)=>{t[n]=e}),t}if(Array.isArray(e))return e.reduce((e,[t,n])=>(e[t]=n,e),{});let t={};return Object.entries(e).forEach(([e,n])=>{t[e]=Array.isArray(n)?n.join(`,`):n}),t}var A=class e extends Error{isHttpError=!0;response;config;constructor(t,n,r){super(r||`Request failed with status ${t?.status||`unknown`}`),this.name=`HttpError`,this.response=t,this.config=j(n),Object.setPrototypeOf(this,e.prototype)}};function j(e){let{headers:t,...n}=e;return{...n,headers:M(t)}}function M(e){if(!e)return;let t=k(e),n={},r=[`authorization`,`x-api-key`,`cookie`,`x-secret`];for(let[e,i]of Object.entries(t)){let t=e.toLowerCase();r.includes(t)?n[e]=`[REDACTED]`:n[e]=i}return n}var N=class{defaultConfig;securityConfig;interceptors={request:new D,response:new D};constructor(e){let{platform:t,security:n,...r}=e||{};this.defaultConfig={timeout:5e3,...r};let i=n?.strictMode??!1;this.securityConfig={allowedProtocols:i?[`http:`,`https:`]:null,maxResponseSize:i?50*1024*1024:0,strictMode:i,...n},t?.enabled&&(this.defaultConfig.baseURL||(this.defaultConfig.baseURL=w(t)),T(this.interceptors,t))}async get(e,t){return this.request({...t,url:e,method:`GET`})}async post(e,t,n){let r={...n?.headers},i=t;return O(t)&&(i=JSON.stringify(t),Object.keys(r).some(e=>e.toLowerCase()===`content-type`)||(r[`Content-Type`]=`application/json`)),this.request({...n,url:e,method:`POST`,body:i,headers:r})}async put(e,t,n){let r={...n?.headers},i=t;return O(t)&&(i=JSON.stringify(t),Object.keys(r).some(e=>e.toLowerCase()===`content-type`)||(r[`Content-Type`]=`application/json`)),this.request({...n,url:e,method:`PUT`,body:i,headers:r})}async delete(e,t){return this.request({...t,url:e,method:`DELETE`})}async patch(e,t,n){let r={...n?.headers},i=t;return O(t)&&(i=JSON.stringify(t),Object.keys(r).some(e=>e.toLowerCase()===`content-type`)||(r[`Content-Type`]=`application/json`)),this.request({...n,url:e,method:`PATCH`,body:i,headers:r})}async request(e){let t=k(this.defaultConfig.headers),n=k(e.headers),r={};for(let e in t)r[e.toLowerCase()]={key:e,value:t[e]};for(let e in n)r[e.toLowerCase()]={key:e,value:n[e]};let i={};for(let e in r){let{key:t,value:n}=r[e];i[t]=n}let a={...this.defaultConfig,...e,headers:i};try{a=await this.runRequestInterceptors(a)}catch(e){return Promise.reject(e)}a.headers=k(a.headers);let o=this.buildUrl(a.url,a.params),s=a.timeout||this.defaultConfig.timeout||5e3,c=new AbortController,l=setTimeout(()=>c.abort(),s),u=a.signal;u&&(u.aborted?(clearTimeout(l),c.abort()):u.addEventListener(`abort`,()=>c.abort(),{once:!0}));let{platformAuth:d,params:f,timeout:p,baseURL:m,url:h,...g}=a;try{let e=await fetch(o,{...g,signal:c.signal});if(clearTimeout(l),this.securityConfig.maxResponseSize>0){let t=e.headers.get(`content-length`);if(t){let e=parseInt(t,10);if(e>this.securityConfig.maxResponseSize)throw Error(`Response size ${e} bytes exceeds limit of ${this.securityConfig.maxResponseSize} bytes`)}}if(!e.ok){let t=new A(e,a);return this.runResponseInterceptors(Promise.reject(t))}return this.runResponseInterceptors(Promise.resolve(e))}catch(e){clearTimeout(l);let t=e instanceof A?e:new A(void 0,a,e.name===`AbortError`?`Request aborted`:e.message);return this.runResponseInterceptors(Promise.reject(t))}}runRequestInterceptors(e){let t=Promise.resolve(e),n=[];this.interceptors.request.forEach(e=>{n.push(e)});for(let e of n)t=t.then(e.onFulfilled,e.onRejected);return t}async runResponseInterceptors(e){let t=e,n=[];this.interceptors.response.forEach(e=>{n.push(e)});for(let e of n)t=t.then(e.onFulfilled,e.onRejected);return t}buildUrl(e,t){let n=this.defaultConfig.baseURL,r;r=!n||/^https?:\/\//i.test(e)?e:n.replace(/\/+$/,``)+`/`+e.replace(/^\/+/,``);let i=new URL(r),{allowedProtocols:a}=this.securityConfig;if(a&&!a.includes(i.protocol))throw Error(`Protocol ${i.protocol} is not allowed. Allowed: ${a.join(`, `)}`);if(t)for(let[e,n]of Object.entries(t))n!=null&&i.searchParams.set(e,String(n));return i.href}}}))();function y(){let e=process.env.app_id,t=process.env.FORCE_AUTHN_INNERAPI_DOMAIN,n=process.env.FORCE_AUTHN_ACCESS_SECRET,r=process.env.FORCE_AUTHN_ACCESS_KEY;if(!e||!t||!n||!r)throw Error(`studio-client: 缺少环境变量,需要: app_id, FORCE_AUTHN_INNERAPI_DOMAIN, FORCE_AUTHN_ACCESS_KEY, FORCE_AUTHN_ACCESS_SECRET`);return{appId:e,apiUrl:t,accessSecret:n,accessKey:r}}const b=new Set([`k_st_ec_400002683`]);var x=class extends Error{userFacing=!0;constructor(e,t){super(e),this.statusCode=t,this.name=`UserFacingError`}};function S(...e){for(let t of e)if(typeof t==`string`&&t)return t}async function*C(e){let t=new TextDecoder,n=``,r;for await(let i of e){n+=t.decode(i,{stream:!0});let e=n.split(`
|
|
1
|
+
import{createRequire as e}from"node:module";import{spawn as t}from"node:child_process";import n,{readFileSync as r}from"node:fs";import i,{dirname as a,join as o,resolve as s}from"node:path";import{appendFile as c,mkdir as l,readFile as u,readdir as d,rm as f,writeFile as p}from"node:fs/promises";import{fileURLToPath as m}from"node:url";var h=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),g=e(import.meta.url);function _(){return s(process.env.OPENCLAW_STATE_DIR||process.cwd())}function v(e){return o(e,`.agent`)}function y(e,t){return o(e,t)}function b(e){let t=typeof e.workspaceDir==`string`&&e.workspaceDir!==``,n=typeof e.agentDir==`string`&&e.agentDir!==``;if(!t||!n)throw Error(`resolveToolPaths: workspaceDir and agentDir are required in tool factory context`);return{workspaceDir:e.workspaceDir,agentDir:e.agentDir,agentId:e.agentId,sessionKey:e.sessionKey}}var x=h(((e,t)=>{var n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,o=(e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})},s=(e,t,o,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of i(t))!a.call(e,c)&&c!==o&&n(e,c,{get:()=>t[c],enumerable:!(s=r(t,c))||s.enumerable});return e},c=e=>s(n({},`__esModule`,{value:!0}),e),l={};o(l,{DEFAULT_CLOCK_TOLERANCE_SEC:()=>f,DEFAULT_JWT_EXPIRE_TIME_MS:()=>d,HttpClient:()=>N,HttpError:()=>A,generateJWTToken:()=>m,parseJWTTokenWithVerify:()=>h,registerPlatformPlugin:()=>T,resolvePlatformBaseURL:()=>w}),t.exports=c(l);var u=g(`crypto`),d=1800*1e3,f=60,p={alg:`HS256`,typ:`JWT`};function m(e,t){let n=Math.floor(Date.now()/1e3),r={...e,iss:e.access_key,iat:n,nbf:n,exp:n+Math.floor(t.expireTimeMs/1e3),jti:(0,u.randomUUID)()},i=v(JSON.stringify(p)),a=v(JSON.stringify(r));return`${i}.${a}.${_(`${i}.${a}`,t.secretKey)}`}function h(e,t,n){let r=e.split(`.`);if(r.length!==3)throw Error(`invalid JWT token format`);let[i,a,o]=r;if(JSON.parse(y(i)).alg!==`HS256`)throw Error(`unsupported JWT alg`);let s=_(`${i}.${a}`,t.secretKey),c=Buffer.from(s),l=Buffer.from(o);if(c.length!==l.length||!(0,u.timingSafeEqual)(c,l))throw Error(`JWT signature verification failed`);let d=JSON.parse(y(a));if(!n?.skipExpiration){let e=n?.clockTolerance??f,t=Math.floor(Date.now()/1e3);if(d.exp!==void 0&&d.exp+e<t)throw Error(`JWT token expired at ${new Date(d.exp*1e3).toISOString()}`);if(d.nbf!==void 0&&d.nbf-e>t)throw Error(`JWT token not yet valid, will be valid at ${new Date(d.nbf*1e3).toISOString()}`);if(d.iat!==void 0&&d.iat-e>t)throw Error(`JWT token issued in the future at ${new Date(d.iat*1e3).toISOString()}`)}return d}function _(e,t){return(0,u.createHmac)(`sha256`,t).update(e).digest(`base64`).replace(/=/g,``).replace(/\+/g,`-`).replace(/\//g,`_`)}function v(e){return Buffer.from(e).toString(`base64`).replace(/=/g,``).replace(/\+/g,`-`).replace(/\//g,`_`)}function y(e){let t=(4-(e.length%4||4))%4,n=`${e}${`=`.repeat(t)}`.replace(/-/g,`+`).replace(/_/g,`/`);return Buffer.from(n,`base64`).toString(`utf8`)}var b=class{cache=new Map;config;constructor(e){this.config={refreshBeforeMs:300*1e3,...e}}getToken(e){let t=this.getCacheKey(e),n=this.cache.get(t),r=Date.now();if(n&&n.expiresAtMs-r>this.config.refreshBeforeMs)return n.token;let i=m(e,this.config),a=r+this.config.expireTimeMs;return this.cache.set(t,{token:i,expiresAtMs:a}),i}clearCache(){this.cache.clear()}clearCacheFor(e){let t=this.getCacheKey(e);this.cache.delete(t)}getCacheKey(e){return[e.access_key,e.tenant_id?.toString()||``,e.user_id||``,e.app_id||``,e.app_env||``,e.sandbox_id||``].join(`:`)}getCacheStats(){let e=Date.now(),t=0,n=0;for(let r of this.cache.values())r.expiresAtMs>e?t++:n++;return{total:this.cache.size,valid:t,expired:n}}},x=`FORCE_AUTHN_INNERAPI_DOMAIN`,S=`FORCE_AUTHN_ACCESS_KEY`,C=`FORCE_AUTHN_ACCESS_SECRET`;function w(e){if(!e?.enabled)return e?.baseURL;if(e.baseURL)return e.baseURL;let t=e.domainEnv||x,n=process.env[t];if(!n)throw Error(`\u5E73\u53F0\u6A21\u5F0F\u9700\u8981\u57FA\u7840\u57DF\u540D\uFF0C\u8BF7\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF ${t}`);return n}function T(e,t){if(!t.enabled)return;E(`platform.defaultClaims`,t.defaultClaims);let n=t.accessKeyEnv||S,r=t.secretKeyEnv||C,i=t.accessKey??(process.env[n]||``),a=new b({accessKey:i,secretKey:t.secretKey??(process.env[r]||``),expireTimeMs:t.expireTimeMs??d,refreshBeforeMs:t.refreshBeforeMs});return e.request.use(e=>{E(`request.platformAuth.customClaims`,e.platformAuth?.customClaims);let n={...t.defaultClaims||{},...e.platformAuth?.customClaims||{},access_key:i},r=a.getToken(n),o={...e.headers,Authorization:`Bearer ${r}`,"x-api-key":i};return{...e,headers:o}}),a}function E(e,t){if(t&&Object.prototype.hasOwnProperty.call(t,`access_key`))throw Error(`${e} \u4E0D\u5141\u8BB8\u8BBE\u7F6E access_key`)}var D=class{interceptors=[];use(e,t){return this.interceptors.push({onFulfilled:e,onRejected:t}),this.interceptors.length-1}eject(e){this.interceptors[e]&&(this.interceptors[e]=null)}clear(){this.interceptors=[]}forEach(e){this.interceptors.forEach(t=>{t!==null&&e(t)})}};function O(e){if(typeof e!=`object`||!e)return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function k(e){if(!e)return{};if(e instanceof Headers){let t={};return e.forEach((e,n)=>{t[n]=e}),t}if(Array.isArray(e))return e.reduce((e,[t,n])=>(e[t]=n,e),{});let t={};return Object.entries(e).forEach(([e,n])=>{t[e]=Array.isArray(n)?n.join(`,`):n}),t}var A=class e extends Error{isHttpError=!0;response;config;constructor(t,n,r){super(r||`Request failed with status ${t?.status||`unknown`}`),this.name=`HttpError`,this.response=t,this.config=j(n),Object.setPrototypeOf(this,e.prototype)}};function j(e){let{headers:t,...n}=e;return{...n,headers:M(t)}}function M(e){if(!e)return;let t=k(e),n={},r=[`authorization`,`x-api-key`,`cookie`,`x-secret`];for(let[e,i]of Object.entries(t)){let t=e.toLowerCase();r.includes(t)?n[e]=`[REDACTED]`:n[e]=i}return n}var N=class{defaultConfig;securityConfig;interceptors={request:new D,response:new D};constructor(e){let{platform:t,security:n,...r}=e||{};this.defaultConfig={timeout:5e3,...r};let i=n?.strictMode??!1;this.securityConfig={allowedProtocols:i?[`http:`,`https:`]:null,maxResponseSize:i?50*1024*1024:0,strictMode:i,...n},t?.enabled&&(this.defaultConfig.baseURL||(this.defaultConfig.baseURL=w(t)),T(this.interceptors,t))}async get(e,t){return this.request({...t,url:e,method:`GET`})}async post(e,t,n){let r={...n?.headers},i=t;return O(t)&&(i=JSON.stringify(t),Object.keys(r).some(e=>e.toLowerCase()===`content-type`)||(r[`Content-Type`]=`application/json`)),this.request({...n,url:e,method:`POST`,body:i,headers:r})}async put(e,t,n){let r={...n?.headers},i=t;return O(t)&&(i=JSON.stringify(t),Object.keys(r).some(e=>e.toLowerCase()===`content-type`)||(r[`Content-Type`]=`application/json`)),this.request({...n,url:e,method:`PUT`,body:i,headers:r})}async delete(e,t){return this.request({...t,url:e,method:`DELETE`})}async patch(e,t,n){let r={...n?.headers},i=t;return O(t)&&(i=JSON.stringify(t),Object.keys(r).some(e=>e.toLowerCase()===`content-type`)||(r[`Content-Type`]=`application/json`)),this.request({...n,url:e,method:`PATCH`,body:i,headers:r})}async request(e){let t=k(this.defaultConfig.headers),n=k(e.headers),r={};for(let e in t)r[e.toLowerCase()]={key:e,value:t[e]};for(let e in n)r[e.toLowerCase()]={key:e,value:n[e]};let i={};for(let e in r){let{key:t,value:n}=r[e];i[t]=n}let a={...this.defaultConfig,...e,headers:i};try{a=await this.runRequestInterceptors(a)}catch(e){return Promise.reject(e)}a.headers=k(a.headers);let o=this.buildUrl(a.url,a.params),s=a.timeout||this.defaultConfig.timeout||5e3,c=new AbortController,l=setTimeout(()=>c.abort(),s),u=a.signal;u&&(u.aborted?(clearTimeout(l),c.abort()):u.addEventListener(`abort`,()=>c.abort(),{once:!0}));let{platformAuth:d,params:f,timeout:p,baseURL:m,url:h,...g}=a;try{let e=await fetch(o,{...g,signal:c.signal});if(clearTimeout(l),this.securityConfig.maxResponseSize>0){let t=e.headers.get(`content-length`);if(t){let e=parseInt(t,10);if(e>this.securityConfig.maxResponseSize)throw Error(`Response size ${e} bytes exceeds limit of ${this.securityConfig.maxResponseSize} bytes`)}}if(!e.ok){let t=new A(e,a);return this.runResponseInterceptors(Promise.reject(t))}return this.runResponseInterceptors(Promise.resolve(e))}catch(e){clearTimeout(l);let t=e instanceof A?e:new A(void 0,a,e.name===`AbortError`?`Request aborted`:e.message);return this.runResponseInterceptors(Promise.reject(t))}}runRequestInterceptors(e){let t=Promise.resolve(e),n=[];this.interceptors.request.forEach(e=>{n.push(e)});for(let e of n)t=t.then(e.onFulfilled,e.onRejected);return t}async runResponseInterceptors(e){let t=e,n=[];this.interceptors.response.forEach(e=>{n.push(e)});for(let e of n)t=t.then(e.onFulfilled,e.onRejected);return t}buildUrl(e,t){let n=this.defaultConfig.baseURL,r;r=!n||/^https?:\/\//i.test(e)?e:n.replace(/\/+$/,``)+`/`+e.replace(/^\/+/,``);let i=new URL(r),{allowedProtocols:a}=this.securityConfig;if(a&&!a.includes(i.protocol))throw Error(`Protocol ${i.protocol} is not allowed. Allowed: ${a.join(`, `)}`);if(t)for(let[e,n]of Object.entries(t))n!=null&&i.searchParams.set(e,String(n));return i.href}}}))();let S;function C(){if(S)return S;try{let e=s(a(m(import.meta.url)),`..`,`package.json`);S=JSON.parse(r(e,`utf-8`))}catch(e){console.warn(`[miaoda-coding] failed to read package.json: ${e instanceof Error?e.message:e}`),S={}}return S}function w(){let e=process.env.app_id,t=process.env.FORCE_AUTHN_INNERAPI_DOMAIN,n=process.env.FORCE_AUTHN_ACCESS_SECRET,r=process.env.FORCE_AUTHN_ACCESS_KEY;if(!e||!t||!n||!r)throw Error(`studio-client: 缺少环境变量,需要: app_id, FORCE_AUTHN_INNERAPI_DOMAIN, FORCE_AUTHN_ACCESS_KEY, FORCE_AUTHN_ACCESS_SECRET`);return{appId:e,apiUrl:t,accessSecret:n,accessKey:r}}const T=new Set([`k_st_ec_400002683`]);var E=class extends Error{userFacing=!0;constructor(e,t){super(e),this.statusCode=t,this.name=`UserFacingError`}};function D(e){return!!e&&typeof e==`object`&&!Array.isArray(e)&&Object.values(e).every(e=>typeof e==`string`)}function O(...e){for(let t of e)if(typeof t==`string`&&t)return t}async function*k(e){let t=new TextDecoder,n=``,r;for await(let i of e){n+=t.decode(i,{stream:!0});let e=n.split(`
|
|
2
2
|
|
|
3
3
|
`);n=e.pop();for(let t of e){let e=t.split(`
|
|
4
|
-
`),n=e.find(e=>e.startsWith(`id:`));n&&(r=n.slice(3).trim());let i=e.find(e=>e.startsWith(`data:`));if(!i)continue;let a=i.slice(5).trim();if(a){if(a===`[DONE]`){yield{data:null,id:r,done:!0};return}try{yield{data:JSON.parse(a),id:r,done:!1}}catch{}}}}}var w=class{#e;#t;constructor(){this.#t=y(),this.#e=new v.HttpClient({baseURL:this.#t.apiUrl,timeout:9e5,platform:{enabled:!0,baseURL:this.#t.apiUrl,accessKey:this.#t.accessKey,secretKey:this.#t.accessSecret,defaultClaims:{appId:this.#t.appId}}})}async createSubApp(e={}){let t=`${this.#t.apiUrl}/api/v1/studio/innerapi/openclaw/sub_app/create`,n={};e.message&&(n.message=e.message),e.agentId&&(n.agentId=e.agentId);let r;try{r=await this.#e.post(t,n,{headers:{"Content-Type":`application/json`}})}catch(e){if(e instanceof v.HttpError&&e.response){let t=e.response.headers.get(`x-tt-logid`)??``;throw Error(`createSubApp 请求失败 (logID: ${t}): ${e.response.status}`)}throw e}let i=r.headers?.get?.(`x-tt-logid`)??``,a=await r.json();if(a.BaseResp?.StatusCode!==0&&a.BaseResp?.StatusMessage)throw Error(`createSubApp 业务错误 (logID: ${i}): ${a.BaseResp.StatusMessage}`);if(a.error_msg&&a.status_code!==`0`)throw b.has(a.status_code)?new x(a.error_msg,a.status_code):Error(`createSubApp 服务错误 (logID: ${i}): ${a.error_msg}`);let o=S(a.appID,a.appId,a.app_id,a.data?.appID,a.data?.appId,a.data?.app_id),s=S(a.conversationID,a.conversationId,a.conversation_id,a.data?.conversationID,a.data?.conversationId,a.data?.conversation_id);if(!o){let e=Object.keys(a).join(`,`)||`(none)`,t=a.data&&typeof a.data==`object`&&Object.keys(a.data).join(`,`)||`(none)`;throw Error(`createSubApp 返回异常 (logID: ${i}): 缺少 appID,topLevelKeys=${e} dataKeys=${t}`)}return{appID:o,conversationID:s,logId:i}}async*streamChat(e){let t=`${this.#t.apiUrl}/api/v1/studio/innerapi/openclaw/sub_app/${e.appID}/stream_chat`,n={appID:e.appID,message:e.message};e.workDir&&(n.workDir=e.workDir);let r={"Content-Type":`application/json`,Accept:`text/event-stream`};e.lastEventID&&(r[`Last-Event-ID`]=e.lastEventID);let i;try{i=await this.#e.post(t,n,{headers:r})}catch(e){if(e instanceof v.HttpError&&e.response){let t=e.response.headers.get(`x-tt-logid`)??``,n=Error(`streamChat 请求失败 (logID: ${t}): ${e.response.status}`);throw n.logId=t,n}let t=e.cause?` cause: ${e.cause.message||e.cause}`:``,n=e.code?` code: ${e.code}`:``;throw Error(`streamChat 网络错误: ${e.message}${n}${t}`)}yield{__meta:!0,logId:i.headers?.get?.(`x-tt-logid`)??``},yield*C(i.body)}};const T=`.spark`,E=`meta.json`;function D(e){return i(e,T,E)}async function O(e){try{return JSON.parse(await c(D(e),`utf8`))}catch{return null}}async function k(e){for(let t of[i(e,`..`,`..`,T,E),i(e,`..`,T,E)])try{return JSON.parse(await c(t,`utf8`))}catch{}return null}async function A(e,t){await s(i(e,T),{recursive:!0});let n=await O(e),r={...n??{},...t};if(!n){let t=await k(e);if(t)for(let[e,n]of Object.entries(t))e in r||(r[e]=n)}await d(D(e),JSON.stringify(r,null,2),`utf8`)}function j(e){let t=e;return t?.data?.message??t?.Data?.Message??null}async function M(e){let t=e.maxReconnect??2,n=e.maxTotalReconnect??10,r=e.reconnectDelayMs??1500,i,a=0,o=0,s=0,c,l;for(;;){let u=!1,d=!1,f=!1,p=i;try{for await(let t of e.createStream(p)){if(e.signal?.aborted)return{totalEvents:s,reconnectCount:o,lastEventId:i,finalText:c,logId:l,success:!1,error:`cancelled`};let n=t;if(n?.__meta){l=n.logId||l;continue}let r=n;if(r.id&&(i=r.id),r.id&&p&&r.id===p)continue;if(r.done)break;s++,a>0&&(a=0);let d=j(r.data);if(d?.type===`metadata`&&d?.status!==`in_progress`&&(u=!0),d?.role===`assistant`&&d?.type===`message`&&d?.status===`completed`&&typeof d?.content==`string`&&d.content&&(c=d.content),e.onEvent&&e.onEvent(r,{lastEventId:i,reconnectCount:o})===!1){f=!0;break}}}catch(e){if(!u){let t=e instanceof Error?e.message:String(e);if(/\b4[0-9]{2}\b/.test(t)||t.includes(`业务错误`))return{totalEvents:s,reconnectCount:o,lastEventId:i,finalText:c,logId:l,success:!1,error:t};d=!0}}if(f)break;if(s===0&&!u&&!d)return{totalEvents:s,reconnectCount:o,lastEventId:i,finalText:c,logId:l,success:!1,error:`stream returned no events`};if(u)break;if(d||i){if(a++,o++,a<=t&&o<=n&&i){if(e.onReconnect?.(o,i),await new Promise(t=>{let n=setTimeout(t,r);e.signal&&e.signal.addEventListener(`abort`,()=>{clearTimeout(n),t()},{once:!0})}),e.signal?.aborted)return{totalEvents:s,reconnectCount:o,lastEventId:i,finalText:c,logId:l,success:!1,error:`cancelled`};continue}let u=`stream disconnected, reconnect exhausted`;return e.onFailed?.(u),{totalEvents:s,reconnectCount:o,lastEventId:i,finalText:c,logId:l,success:!1,error:u}}break}return e.onComplete?.({totalEvents:s,reconnectCount:o,lastEventId:i}),{totalEvents:s,reconnectCount:o,lastEventId:i,finalText:c,logId:l,success:!0}}const N=`.spark`,P=new Intl.DateTimeFormat(`en-CA`,{timeZone:`Asia/Shanghai`,year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1,timeZoneName:`longOffset`});function F(e){return i(e,N,`progress.txt`)}function I(){let e=Object.fromEntries(P.formatToParts(new Date).filter(e=>e.type!==`literal`).map(e=>[e.type,e.value])),t=e.timeZoneName===`GMT`?`+00:00`:e.timeZoneName.replace(/^GMT/,``);return`${e.year}-${e.month}-${e.day}T${e.hour}:${e.minute}:${e.second}${t}`}async function L(e){await s(i(e,N),{recursive:!0});let t=F(e);try{if((await c(t,`utf8`)).trim()){await o(t,`\n--- 新一轮任务 [${I()}] ---\n\n`,`utf8`);return}}catch{}await d(t,``,`utf8`)}async function R(e,t){await o(F(e),`[${I()}] ${t}\n`,`utf8`)}async function*z(e){let{cwd:t,task:n,agentId:r,signal:i}=e;try{let e=new w;await L(t),await R(t,`已接收需求`),yield{type:`progress`,message:`已接收需求`};let a=await O(t),o=!a?.appId,s=I();if(o){let i;try{i=await e.createSubApp({message:n,agentId:r})}catch(e){let n=e instanceof Error?e.message:String(e),r=e instanceof x;try{await R(t,`失败: ${n}`)}catch{}yield{type:`failed`,error:n,phase:`create`,userFacing:r};return}let{appID:o,conversationID:c,logId:l}=i;a={appId:o,conversationId:c,createdAt:s,updatedAt:s},await A(t,a),await R(t,`应用已创建(appId: ${o})`),yield{type:`app_created`,appId:o,conversationId:c,logId:l}}await R(t,`正在处理`),yield{type:`progress`,message:`正在处理`};let c=!1,l=Date.now(),u=setInterval(()=>{R(t,`正在开发中(已 ${Math.floor((Date.now()-l)/6e4)} 分钟)`).catch(()=>{})},3e4),d;try{d=await M({createStream:r=>e.streamChat({appID:a.appId,message:n,workDir:t,...r?{lastEventID:r}:{}}),onEvent:e=>{if(i?.aborted)return!1;let n=j(e.data),r=n?.delta?.type;!c&&n?.role===`assistant`&&(n?.status===`in_progress`||r===`text`)&&(c=!0,R(t,`正在输出结果`).catch(()=>{}))},onReconnect:(e,n)=>{R(t,`流中断,正在重连(第 ${e} 次)`).catch(()=>{})},onFailed:e=>{R(t,`失败: ${e}`).catch(()=>{})},signal:i})}finally{clearInterval(u)}if(!d.success){let e=d.error?.includes(`disconnected`)||d.error?.includes(`no events`);yield{type:`failed`,error:d.error||`stream failed`,retryable:e};return}let{finalText:f,logId:p}=d;if(c&&(yield{type:`progress`,message:`正在输出结果`,logId:p||void 0}),i?.aborted){await R(t,`失败: cancelled`),yield{type:`failed`,error:`cancelled`};return}let m=I();await A(t,{...a,updatedAt:m,finalText:f}),await R(t,`处理完成`),yield{type:`completed`,appId:a.appId,logId:p||void 0,finalText:f}}catch(e){let n=e instanceof Error?e.message:String(e);try{await R(t,`失败: ${n}`)}catch{}yield{type:`failed`,error:n,logId:e?.logId}}}const B=[`research`,`design`,`feedback`];function V(e){return e.replace(/[^a-zA-Z0-9\u4e00-\u9fff-]/g,`-`).replace(/-+/g,`-`).replace(/^-|-$/g,``).slice(0,60)||`reference`}async function H(e){let t;try{t=await l(e)}catch{return 1}let n=0;for(let e of t){let t=e.match(/^(\d{3})-/);if(t){let e=parseInt(t[1],10);e>n&&(n=e)}}return n+1}async function U(e){try{let t=await c(i(e,`reference`,`manifest.json`),`utf8`);return JSON.parse(t)}catch{return{updatedAt:new Date().toISOString(),files:[]}}}async function W(e,t){await s(i(e,`reference`),{recursive:!0}),await d(i(e,`reference`,`manifest.json`),JSON.stringify(t,null,2),`utf8`)}async function G(e){let{appCwd:t,category:n,content:r,filename:a,mode:o=`append`}=e,c=i(t,`reference`,n);if(o===`replace`)try{await u(c,{recursive:!0,force:!0})}catch{}await s(c,{recursive:!0});let l=await H(c),f=`${n}/${`${String(l).padStart(3,`0`)}-${V(a??`reference`)}.md`}`,p=`reference/${f}`;await d(i(t,p),r,`utf8`);let m=await U(t);return o===`replace`&&(m.files=m.files.filter(e=>e.category!==n)),m.files.push({path:f,category:n,writtenAt:new Date().toISOString()}),m.updatedAt=new Date().toISOString(),await W(t,m),{relativePath:p,category:n,seq:l}}async function K(e){let t=i(e,`reference`),n;try{n=await l(t)}catch{return{totalFiles:0,categories:{}}}let r={},a=0;for(let e of n){if(!B.includes(e))continue;let n;try{n=(await l(i(t,e))).filter(e=>e.endsWith(`.md`)).sort()}catch{continue}n.length>0&&(r[e]={count:n.length,files:n},a+=n.length)}return{totalFiles:a,categories:r}}async function ee(e){return(await K(e)).totalFiles>0}const te=/^[a-z0-9][a-z0-9-]{0,63}$/,ne=new Set([`.`,`..`,`con`,`nul`,`prn`,`aux`]);function q(e){let t=e?.config?.plugins?.entries?.[`openclaw-extension-miaoda-coding`]?.config??{};return{verbose:t?.verbose===!0,hooks:{allowPromptInjection:t?.hooks?.allowPromptInjection!==!1}}}function J(e,n){if(!e)return;let i=r.dirname(process.execPath),a=t(`openclaw`,[`message`,`send`,`--channel`,`feishu`,`--target`,e,`--message`,n],{stdio:[`ignore`,`ignore`,`pipe`],env:{...process.env,PATH:`${i}:${process.env.PATH||``}`}});a.stderr.on(`data`,()=>{}),a.on(`close`,()=>{}),a.unref()}function Y(e){return String(e??``).replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g,``).replace(/\s+/g,` `).trim()}function re(e){let t=String(e??``).replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g,``).trim();if(!t)throw Error(`task 不能为空`);if(t.length>4e3)throw Error(`task 不能超过 4000 个字符`);return t}function X(e){let t=Y(e);if(!Z(t))throw Error(`project_id 不合法: "${t}"`);return t}function Z(e){return te.test(e)&&!ne.has(e)}function ie(e){if(e==null||e===``)return;let t=Y(e);if(!/^(user|chat|thread):\S+$/.test(t))throw Error(`target 不合法`);return t}function ae(e){try{return n.readFileSync(e,`utf8`).split(`
|
|
5
|
-
`).map(e=>e.trim()).filter(Boolean)}catch{return[]}}function
|
|
6
|
-
`).filter(Boolean),s=null;try{s=JSON.parse(n.readFileSync(
|
|
7
|
-
`);return{content:[{type:`text`,text:JSON.stringify({status:`ok`,project_id:e,lines:o.length,progress:l,delivery_ready:c,finalTextAvailable:c,note:`miaoda_check_progress 只用于查看进度,不能根据 appId 或进度文本推导预览链接;最终链接只以 subagent completion result 中的 output/finalText 为准。`})}]}}catch{return{content:[{type:`text`,text:JSON.stringify({status:`no_progress`,project_id:
|
|
4
|
+
`),n=e.find(e=>e.startsWith(`id:`));n&&(r=n.slice(3).trim());let i=e.find(e=>e.startsWith(`data:`));if(!i)continue;let a=i.slice(5).trim();if(a){if(a===`[DONE]`){yield{data:null,id:r,done:!0};return}try{yield{data:JSON.parse(a),id:r,done:!1}}catch{}}}}}var A=class{#e;#t;constructor(){this.#t=w();let e=C().headers;this.#e=new x.HttpClient({baseURL:this.#t.apiUrl,timeout:9e5,...process.env.FORCE_FRAMEWORK_ENVIRONMENT!==`online`&&D(e)?{headers:e}:{},platform:{enabled:!0,baseURL:this.#t.apiUrl,accessKey:this.#t.accessKey,secretKey:this.#t.accessSecret,defaultClaims:{appId:this.#t.appId}}})}async createSubApp(e={}){let t=`${this.#t.apiUrl}/api/v1/studio/innerapi/openclaw/sub_app/create`,n={};e.message&&(n.message=e.message),e.agentId&&(n.agentId=e.agentId);let r;try{r=await this.#e.post(t,n,{headers:{"Content-Type":`application/json`}})}catch(e){if(e instanceof x.HttpError&&e.response){let t=e.response.headers.get(`x-tt-logid`)??``;throw Error(`createSubApp 请求失败 (logID: ${t}): ${e.response.status}`)}throw e}let i=r.headers?.get?.(`x-tt-logid`)??``,a=await r.json();if(a.BaseResp?.StatusCode!==0&&a.BaseResp?.StatusMessage)throw Error(`createSubApp 业务错误 (logID: ${i}): ${a.BaseResp.StatusMessage}`);if(a.error_msg&&a.status_code!==`0`)throw T.has(a.status_code)?new E(a.error_msg,a.status_code):Error(`createSubApp 服务错误 (logID: ${i}): ${a.error_msg}`);let o=O(a.appID,a.appId,a.app_id,a.data?.appID,a.data?.appId,a.data?.app_id),s=O(a.conversationID,a.conversationId,a.conversation_id,a.data?.conversationID,a.data?.conversationId,a.data?.conversation_id);if(!o){let e=Object.keys(a).join(`,`)||`(none)`,t=a.data&&typeof a.data==`object`&&Object.keys(a.data).join(`,`)||`(none)`;throw Error(`createSubApp 返回异常 (logID: ${i}): 缺少 appID,topLevelKeys=${e} dataKeys=${t}`)}return{appID:o,conversationID:s,logId:i}}async*streamChat(e){let t=`${this.#t.apiUrl}/api/v1/studio/innerapi/openclaw/sub_app/${e.appID}/stream_chat`,n={appID:e.appID,message:e.message};e.workDir&&(n.workDir=e.workDir);let r={"Content-Type":`application/json`,Accept:`text/event-stream`};e.lastEventID&&(r[`Last-Event-ID`]=e.lastEventID);let i;try{i=await this.#e.post(t,n,{headers:r})}catch(e){if(e instanceof x.HttpError&&e.response){let t=e.response.headers.get(`x-tt-logid`)??``,n=Error(`streamChat 请求失败 (logID: ${t}): ${e.response.status}`);throw n.logId=t,n}let t=e.cause?` cause: ${e.cause.message||e.cause}`:``,n=e.code?` code: ${e.code}`:``;throw Error(`streamChat 网络错误: ${e.message}${n}${t}`)}yield{__meta:!0,logId:i.headers?.get?.(`x-tt-logid`)??``},yield*k(i.body)}};const j=`.spark`,M=`meta.json`;function N(e){return o(e,j,M)}async function P(e){try{return JSON.parse(await u(N(e),`utf8`))}catch{return null}}async function F(e){for(let t of[o(e,`..`,`..`,j,M),o(e,`..`,j,M)])try{return JSON.parse(await u(t,`utf8`))}catch{}return null}async function I(e,t){await l(o(e,j),{recursive:!0});let n=await P(e),r={...n??{},...t};if(!n){let t=await F(e);if(t)for(let[e,n]of Object.entries(t))e in r||(r[e]=n)}await p(N(e),JSON.stringify(r,null,2),`utf8`)}function L(e){let t=e;return t?.data?.message??t?.Data?.Message??null}async function ee(e){let t=e.maxReconnect??2,n=e.maxTotalReconnect??10,r=e.reconnectDelayMs??1500,i,a=0,o=0,s=0,c,l;for(;;){let u=!1,d=!1,f=!1,p=i;try{for await(let t of e.createStream(p)){if(e.signal?.aborted)return{totalEvents:s,reconnectCount:o,lastEventId:i,finalText:c,logId:l,success:!1,error:`cancelled`};let n=t;if(n?.__meta){l=n.logId||l;continue}let r=n;if(r.id&&(i=r.id),r.id&&p&&r.id===p)continue;if(r.done)break;s++,a>0&&(a=0);let d=L(r.data);if(d?.type===`metadata`&&d?.status!==`in_progress`&&(u=!0),d?.role===`assistant`&&d?.type===`message`&&d?.status===`completed`&&typeof d?.content==`string`&&d.content&&(c=d.content),e.onEvent&&e.onEvent(r,{lastEventId:i,reconnectCount:o})===!1){f=!0;break}}}catch(e){if(!u){let t=e instanceof Error?e.message:String(e);if(/\b4[0-9]{2}\b/.test(t)||t.includes(`业务错误`))return{totalEvents:s,reconnectCount:o,lastEventId:i,finalText:c,logId:l,success:!1,error:t};d=!0}}if(f)break;if(s===0&&!u&&!d)return{totalEvents:s,reconnectCount:o,lastEventId:i,finalText:c,logId:l,success:!1,error:`stream returned no events`};if(u)break;if(d||i){if(a++,o++,a<=t&&o<=n&&i){if(e.onReconnect?.(o,i),await new Promise(t=>{let n=setTimeout(t,r);e.signal&&e.signal.addEventListener(`abort`,()=>{clearTimeout(n),t()},{once:!0})}),e.signal?.aborted)return{totalEvents:s,reconnectCount:o,lastEventId:i,finalText:c,logId:l,success:!1,error:`cancelled`};continue}let u=`stream disconnected, reconnect exhausted`;return e.onFailed?.(u),{totalEvents:s,reconnectCount:o,lastEventId:i,finalText:c,logId:l,success:!1,error:u}}break}return e.onComplete?.({totalEvents:s,reconnectCount:o,lastEventId:i}),{totalEvents:s,reconnectCount:o,lastEventId:i,finalText:c,logId:l,success:!0}}const R=`.spark`,z=new Intl.DateTimeFormat(`en-CA`,{timeZone:`Asia/Shanghai`,year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1,timeZoneName:`longOffset`});function B(e){return o(e,R,`progress.txt`)}function V(){let e=Object.fromEntries(z.formatToParts(new Date).filter(e=>e.type!==`literal`).map(e=>[e.type,e.value])),t=e.timeZoneName===`GMT`?`+00:00`:e.timeZoneName.replace(/^GMT/,``);return`${e.year}-${e.month}-${e.day}T${e.hour}:${e.minute}:${e.second}${t}`}async function H(e){await l(o(e,R),{recursive:!0});let t=B(e);try{if((await u(t,`utf8`)).trim()){await c(t,`\n--- 新一轮任务 [${V()}] ---\n\n`,`utf8`);return}}catch{}await p(t,``,`utf8`)}async function U(e,t){await c(B(e),`[${V()}] ${t}\n`,`utf8`)}async function*W(e){let{cwd:t,task:n,agentId:r,signal:i}=e;try{let e=new A;await H(t),await U(t,`已接收需求`),yield{type:`progress`,message:`已接收需求`};let a=await P(t),o=!a?.appId,s=V();if(o){let i;try{i=await e.createSubApp({message:n,agentId:r})}catch(e){let n=e instanceof Error?e.message:String(e),r=e instanceof E;try{await U(t,`失败: ${n}`)}catch{}yield{type:`failed`,error:n,phase:`create`,userFacing:r};return}let{appID:o,conversationID:c,logId:l}=i;a={appId:o,conversationId:c,createdAt:s,updatedAt:s},await I(t,a),await U(t,`应用已创建(appId: ${o})`),yield{type:`app_created`,appId:o,conversationId:c,logId:l}}await U(t,`正在处理`),yield{type:`progress`,message:`正在处理`};let c=!1,l=Date.now(),u=setInterval(()=>{U(t,`正在开发中(已 ${Math.floor((Date.now()-l)/6e4)} 分钟)`).catch(()=>{})},3e4),d;try{d=await ee({createStream:r=>e.streamChat({appID:a.appId,message:n,workDir:t,...r?{lastEventID:r}:{}}),onEvent:e=>{if(i?.aborted)return!1;let n=L(e.data),r=n?.delta?.type;!c&&n?.role===`assistant`&&(n?.status===`in_progress`||r===`text`)&&(c=!0,U(t,`正在输出结果`).catch(()=>{}))},onReconnect:(e,n)=>{U(t,`流中断,正在重连(第 ${e} 次)`).catch(()=>{})},onFailed:e=>{U(t,`失败: ${e}`).catch(()=>{})},signal:i})}finally{clearInterval(u)}if(!d.success){let e=d.error?.includes(`disconnected`)||d.error?.includes(`no events`);yield{type:`failed`,error:d.error||`stream failed`,retryable:e};return}let{finalText:f,logId:p}=d;if(c&&(yield{type:`progress`,message:`正在输出结果`,logId:p||void 0}),i?.aborted){await U(t,`失败: cancelled`),yield{type:`failed`,error:`cancelled`};return}let m=V();await I(t,{...a,updatedAt:m,finalText:f}),await U(t,`处理完成`),yield{type:`completed`,appId:a.appId,logId:p||void 0,finalText:f}}catch(e){let n=e instanceof Error?e.message:String(e);try{await U(t,`失败: ${n}`)}catch{}yield{type:`failed`,error:n,logId:e?.logId}}}const G=[`research`,`design`,`feedback`];function te(e){return e.replace(/[^a-zA-Z0-9\u4e00-\u9fff-]/g,`-`).replace(/-+/g,`-`).replace(/^-|-$/g,``).slice(0,60)||`reference`}async function ne(e){let t;try{t=await d(e)}catch{return 1}let n=0;for(let e of t){let t=e.match(/^(\d{3})-/);if(t){let e=parseInt(t[1],10);e>n&&(n=e)}}return n+1}async function re(e){try{let t=await u(o(e,`reference`,`manifest.json`),`utf8`);return JSON.parse(t)}catch{return{updatedAt:new Date().toISOString(),files:[]}}}async function ie(e,t){await l(o(e,`reference`),{recursive:!0}),await p(o(e,`reference`,`manifest.json`),JSON.stringify(t,null,2),`utf8`)}async function ae(e){let{appCwd:t,category:n,content:r,filename:i,mode:a=`append`}=e,s=o(t,`reference`,n);if(a===`replace`)try{await f(s,{recursive:!0,force:!0})}catch{}await l(s,{recursive:!0});let c=await ne(s),u=`${n}/${`${String(c).padStart(3,`0`)}-${te(i??`reference`)}.md`}`,d=`reference/${u}`;await p(o(t,d),r,`utf8`);let m=await re(t);return a===`replace`&&(m.files=m.files.filter(e=>e.category!==n)),m.files.push({path:u,category:n,writtenAt:new Date().toISOString()}),m.updatedAt=new Date().toISOString(),await ie(t,m),{relativePath:d,category:n,seq:c}}async function K(e){let t=o(e,`reference`),n;try{n=await d(t)}catch{return{totalFiles:0,categories:{}}}let r={},i=0;for(let e of n){if(!G.includes(e))continue;let n;try{n=(await d(o(t,e))).filter(e=>e.endsWith(`.md`)).sort()}catch{continue}n.length>0&&(r[e]={count:n.length,files:n},i+=n.length)}return{totalFiles:i,categories:r}}async function oe(e){return(await K(e)).totalFiles>0}const se=/^[a-z0-9][a-z0-9-]{0,63}$/,ce=new Set([`.`,`..`,`con`,`nul`,`prn`,`aux`]);function q(e){let t=e?.config?.plugins?.entries?.[`openclaw-extension-miaoda-coding`]?.config??{};return{verbose:t?.verbose===!0,hooks:{allowPromptInjection:t?.hooks?.allowPromptInjection!==!1}}}function J(e,n){if(!e)return;let r=i.dirname(process.execPath),a=t(`openclaw`,[`message`,`send`,`--channel`,`feishu`,`--target`,e,`--message`,n],{stdio:[`ignore`,`ignore`,`pipe`],env:{...process.env,PATH:`${r}:${process.env.PATH||``}`}});a.stderr.on(`data`,()=>{}),a.on(`close`,()=>{}),a.unref()}function Y(e){return String(e??``).replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g,``).replace(/\s+/g,` `).trim()}function le(e){let t=String(e??``).replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g,``).trim();if(!t)throw Error(`task 不能为空`);if(t.length>4e3)throw Error(`task 不能超过 4000 个字符`);return t}function X(e){let t=Y(e);if(!Z(t))throw Error(`project_id 不合法: "${t}"`);return t}function Z(e){return se.test(e)&&!ce.has(e)}function ue(e){if(e==null||e===``)return;let t=Y(e);if(!/^(user|chat|thread):\S+$/.test(t))throw Error(`target 不合法`);return t}function de(e){try{return n.readFileSync(e,`utf8`).split(`
|
|
5
|
+
`).map(e=>e.trim()).filter(Boolean)}catch{return[]}}function fe(e){return e.replace(/^\[[^\]]+\]\s*/,``)}function Q(e){return e.replace(/应用已创建(appId:\s*[^)]+)/g,`应用已创建`)}function $(e){return e.slice(-3).map(fe).map(Q).join(` | `)||`暂无进度记录`}function pe(e){let t=$(e);return t.includes(`失败:`)?`failed`:t.includes(`处理完成`)?`completed`:t===`暂无进度记录`?`pending`:`running`}var me={id:`openclaw-extension-miaoda-coding`,name:`妙搭`,description:`妙搭制品创建与修改`,register(e){let t={verbose:!1,hooks:{allowPromptInjection:!0}},r=new Set([`miaoda_coding`]),a=new Set([`miaoda_write_reference`,`miaoda_check_progress`]);e.on(`before_tool_call`,(e,t)=>{let n=e.toolName,i=(t?.sessionKey??``).toLowerCase().split(`:`).includes(`subagent`);if(r.has(n)&&!i)return{block:!0,blockReason:`${n} 只能由 subagent 调用。请通过 sessions_spawn(runtime="subagent", mode="run") 派活,不要直接调用此工具。读 miaoda-coding skill 了解完整流程。`};if(a.has(n)&&i)return{block:!0,blockReason:`${n} 不能由 subagent 调用。subagent 不应直接操作参考资料或查询进度。`}}),e.on(`before_prompt_build`,(e,t)=>{if(q(t).hooks.allowPromptInjection)return{prependSystemContext:[`【硬规则 — 妙搭】`,`当用户要求创建或修改应用、网页、页面时,必须通过 sessions_spawn(runtime="subagent", mode="run") 交给妙搭。`,`读 miaoda-coding skill 后严格按指示操作。只传 runtime、mode、task 三个参数,不要传 streamTo/sandbox 等。`,`绝对不要自己写代码或用 exec 生成文件。如果 spawn 失败,重试而不是 fallback。`,`如果对话中有需要传递给 code agent 的上下文(研究结果、用户偏好等),先调 miaoda_write_reference 写入 reference 目录,再 spawn。用户反悔或需要替换之前的上下文时,使用 miaoda_write_reference 的 mode=replace。妙搭只做制品生成,不做研究。`,`不要用 sessions_history 读取子 agent 的 session,查进度用 miaoda_check_progress tool。`,`subagent 完成后只发一条消息(总结+预览链接),严禁发多条。不要调 message tool。预览链接必须使用加粗 Markdown 链接格式 **[url](url)**,不要发裸 URL。`].join(` `)}}),e.registerTool(e=>{let t=b(e);return{name:`list_projects`,label:`列出妙搭项目`,description:`列出已创建的妙搭项目,返回 project_id、appId、updatedAt、finalText、status 和进度摘要。修改已有项目时必须先调此工具。`,parameters:{type:`object`,properties:{}},async execute(){let e=[];try{e=n.readdirSync(t.workspaceDir,{withFileTypes:!0}).filter(e=>e.isDirectory()&&Z(e.name)).map(e=>{let r=i.join(t.workspaceDir,e.name,`.spark`,`meta.json`),a=i.join(t.workspaceDir,e.name,`.spark`,`progress.txt`),o=null;try{o=JSON.parse(n.readFileSync(r,`utf8`))}catch{}let s=de(a);return{project_id:e.name,appId:o?.appId??null,updatedAt:o?.updatedAt??null,finalText:o?.finalText??null,status:pe(s),progressSummary:$(s)}})}catch{}return{content:[{type:`text`,text:JSON.stringify({projects:e},null,2)}]}}}}),e.registerTool(e=>{let t=b(e);return{name:`miaoda_check_progress`,label:`查看妙搭项目进度`,description:`查看妙搭项目的生成进度。用户问"做到哪了"、"进度如何"、"好了吗"时调此工具。`,parameters:{type:`object`,properties:{project_id:{type:`string`,description:`项目目录名(从 list_projects 获取)`}},required:[`project_id`]},async execute(e,r){try{let e=X(r.project_id),a=i.join(t.workspaceDir,e,`.spark`,`progress.txt`),o=n.readFileSync(a,`utf8`).trim().split(`
|
|
6
|
+
`).filter(Boolean),s=null;try{s=JSON.parse(n.readFileSync(i.join(t.workspaceDir,e,`.spark`,`meta.json`),`utf8`))}catch{}let c=!!s?.finalText,l=o.slice(-20).map(Q).join(`
|
|
7
|
+
`);return{content:[{type:`text`,text:JSON.stringify({status:`ok`,project_id:e,lines:o.length,progress:l,delivery_ready:c,finalTextAvailable:c,note:`miaoda_check_progress 只用于查看进度,不能根据 appId 或进度文本推导预览链接;最终链接只以 subagent completion result 中的 output/finalText 为准。`})}]}}catch{return{content:[{type:`text`,text:JSON.stringify({status:`no_progress`,project_id:r.project_id,message:`暂无进度记录`,delivery_ready:!1,finalTextAvailable:!1,note:`miaoda_check_progress 只用于查看进度,不能根据 appId 或进度文本推导预览链接;最终链接只以 subagent completion result 中的 output/finalText 为准。`})}]}}}}}),e.registerTool(e=>{let t=b(e);return{name:`miaoda_write_reference`,label:`写入妙搭参考资料`,description:`将参考资料写入妙搭项目的 reference 目录,供 code agent 在生成时自行查阅。按 category 分类写入。mode=append(默认)追加,mode=replace 替换该 category 全部内容(用于反悔/调整场景)。`,parameters:{type:`object`,properties:{project_id:{type:`string`,description:`项目目录名`},category:{type:`string`,enum:[`research`,`design`,`feedback`],description:`资料类别:research(调研结果)、design(设计要求)、feedback(用户反馈)`},content:{type:`string`,description:`参考资料内容(Markdown 格式,摘要+关键原文引用)`},filename:{type:`string`,description:`可选文件名(不含扩展名)`},mode:{type:`string`,enum:[`append`,`replace`],description:`写入模式:append(追加,默认)、replace(替换该 category 全部内容)`}},required:[`project_id`,`category`,`content`]},async execute(e,n){try{let e=X(n.project_id);if(!G.includes(n.category))throw Error(`category 不合法,必须是 ${G.join(`、`)} 之一`);let r=n.content?.trim();if(!r)throw Error(`content 不能为空`);if(r.length>5e4)throw Error(`content 不能超过 50000 个字符`);let i=n.mode===`replace`?`replace`:`append`,a=y(t.workspaceDir,e),o=await ae({appCwd:a,category:n.category,content:r,filename:n.filename,mode:i}),s=await K(a);return{content:[{type:`text`,text:JSON.stringify({status:`ok`,...o,summary:s},null,2)}]}}catch(e){return{content:[{type:`text`,text:JSON.stringify({status:`error`,error:e instanceof Error?e.message:String(e)})}]}}}}});let o=900*1e3;e.registerTool(e=>{let r=b(e);return{name:`miaoda_coding`,label:`妙搭`,description:`创建或修改妙搭应用/网页。只接受生成指令,不接受搜索/调研等任务。如有参考资料,应事先通过 miaoda_write_reference 写入 reference 目录。修改已有项目时必须先调 list_projects 获取 project_id。返回结构化 JSON(status/appId/finalText/output/meta)。`,parameters:{type:`object`,properties:{generation_request:{type:`string`,description:`生成指令(如'做一个学习网站,包含章节、题库、测验')`},project_id:{type:`string`,description:`本地项目目录名,仅允许小写字母、数字和短横线`},target:{type:`string`,description:`飞书消息推送目标(如 user:ou_xxx)`}},required:[`generation_request`,`project_id`]},async execute(e,a){try{let e=le(a.generation_request),s=X(a.project_id),c=ue(a.target),l=y(r.workspaceDir,s);n.mkdirSync(l,{recursive:!0});let u=await oe(l)?`工作目录下有 reference/ 目录,包含参考资料,请先查阅再开始工作。\n\n${e}`:e,d=i.join(l,`.agent`);if(!n.existsSync(d)){let e=v(_());if(n.existsSync(e))try{n.symlinkSync(e,d)}catch{}}let f=[],p,m=!1,h=!1,g=null,b=new AbortController,x=setTimeout(()=>b.abort(),o);try{for await(let e of W({cwd:l,task:u,agentId:r.agentId,signal:b.signal})){if(`logId`in e&&e.logId&&f.push(e.logId),t.verbose&&c)switch(e.type){case`app_created`:J(c,`应用已创建(appId: ${e.appId})`);break;case`failed`:J(c,`处理失败: ${e.error}`);break}if(e.type===`completed`&&(g={appId:e.appId,finalText:e.finalText}),e.type===`failed`&&(p=e.error,m=e.retryable??!1,e.phase===`create`)){clearTimeout(x),c&&J(c,e.userFacing?e.error:`createSubApp 失败: ${e.error}`);let t=e.userFacing?{status:`error`,project_id:s,appId:null,meta:null,hint:`创建失败,详情已通过飞书发送给用户,不要重复发送错误内容`}:{status:`error`,project_id:s,appId:null,error:e.error,meta:null,hint:`createSubApp 失败,错误已通过飞书发送。根据 error 内容用通俗语言告诉用户具体原因,不要重试`};return{content:[{type:`text`,text:JSON.stringify(t)}]}}}}catch{}clearTimeout(x),h=b.signal.aborted;let S=null;try{S=JSON.parse(n.readFileSync(i.join(l,`.spark`,`meta.json`),`utf8`))}catch{}let C={status:h?`timeout`:p?`error`:`ok`,project_id:s,appId:g?.appId??S?.appId??null,finalText:g?.finalText??S?.finalText,output:g?.finalText??S?.finalText,logIds:f.length?f:void 0,meta:S};return h?(C.error=`执行超时(${o/1e3}秒)`,C.retryable=!0,C.hint=`执行超时,任务可能仍在后台运行。建议先调用 miaoda_check_progress 查看进度,再决定是否重试`):p?(C.error=p,m&&(C.retryable=!0,C.hint=`网络连接中断,任务可能已部分完成。建议先调用 miaoda_check_progress 查看当前状态,再决定下一步`)):C.status===`ok`&&(C.output?C.output.includes(`预览链接`)||(C.hint=`任务完成但未检测到预览链接,建议调用 miaoda_check_progress 查看最新状态`):C.hint=`任务完成但未获取到输出内容,建议调用 miaoda_check_progress 查看最新状态`),{content:[{type:`text`,text:JSON.stringify(C,null,2)}]}}catch(e){return{content:[{type:`text`,text:JSON.stringify({status:`error`,error:e instanceof Error?e.message:String(e)})}]}}}}}),e.registerService({id:`miaoda-coding-config`,async start(e){t=q(e)},async stop(){}})}};export{me as default};
|