@vibe-lark/larkpal 0.1.87 → 0.1.89
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/{account-id-BM1T6029-BzQ_cMoi.mjs → account-id-BM1T6029-BvcZ99G0.mjs} +1 -1
- package/dist/{activation-context--5yu1dPF-XV0Y0pTy.mjs → activation-context--5yu1dPF-DHM2x52-.mjs} +1 -1
- package/dist/{anthropic-CFZUCb1w.mjs → anthropic-gnoZ_QRy.mjs} +1 -1
- package/dist/{assistant-visible-text-DuFWokAt-BOJV_zwc.mjs → assistant-visible-text-DuFWokAt-GbRm46te.mjs} +1 -1
- package/dist/{azure-openai-responses-BEuiMaF-.mjs → azure-openai-responses-DbHzq7dt.mjs} +1 -1
- package/dist/{boundary-file-read-BSd9MXPy-gnNVhPKT.mjs → boundary-file-read-BSd9MXPy-Tpd4W7aA.mjs} +1 -1
- package/dist/{browser-lifecycle-cleanup-BdNsMhMD-BM97qA_M.mjs → browser-lifecycle-cleanup-BdNsMhMD-Bjf5GI3L.mjs} +1 -1
- package/dist/{bundled-compat-BpaDaAAu-DJtrIX6i.mjs → bundled-compat-BpaDaAAu-DElY7pj-.mjs} +1 -1
- package/dist/{bundled-dir-U738ay4K-BxbzrJOo.mjs → bundled-dir-U738ay4K-DxHVp4u1.mjs} +1 -1
- package/dist/{call-DimWbpgJ-B4pv55RH.mjs → call-DimWbpgJ-BnglLl-j.mjs} +1 -1
- package/dist/channel-bootstrap.runtime-BVclcGv1-BH-3XviM.mjs +1 -0
- package/dist/{channel-bootstrap.runtime-Cwcr38m2-Dt6QlQkX.mjs → channel-bootstrap.runtime-Cwcr38m2-K7QN0kxA.mjs} +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/{command-format-LSnUCVVF-Dn4h9IOh.mjs → command-format-LSnUCVVF-Ck0yuZRk.mjs} +1 -1
- package/dist/config-Bim2pi8a-xbw-saVR.mjs +1 -0
- package/dist/config-CtxZK_ZE.mjs +2 -0
- package/dist/{delivery-context.shared-j5hC5qb1-BSLQG47q.mjs → delivery-context.shared-j5hC5qb1-DIY5v1oC.mjs} +1 -1
- package/dist/{diagnostic-ClMwNnUA-BMKvPQJT.mjs → diagnostic-ClMwNnUA-BLmizo4w.mjs} +1 -1
- package/dist/{dist-coestTs9.mjs → dist-BUE_cxIa.mjs} +1 -1
- package/dist/{dist-J5UB83Ws.mjs → dist-Drhg3yZT.mjs} +1 -1
- package/dist/{facade-loader-DFzIYYt_-4bzFvy-b.mjs → facade-loader-DFzIYYt_--SN2-DQM.mjs} +1 -1
- package/dist/{google-ABo-1guT.mjs → google-BdoIr_xq.mjs} +1 -1
- package/dist/{google-gemini-cli-CGlN1zUA.mjs → google-gemini-cli-H9jO3Mvn.mjs} +1 -1
- package/dist/{google-shared-C60sNhwd.mjs → google-shared-DDK4NMAJ.mjs} +2 -2
- package/dist/{google-vertex-De0nAItu.mjs → google-vertex-B_OTGKnl.mjs} +1 -1
- package/dist/{ids-BPsM98Uu-CJBJAeVC.mjs → ids-BPsM98Uu-DGJB5aAM.mjs} +1 -1
- package/dist/{image-2w3cApg7-CrpUMCvm.mjs → image-2w3cApg7-B_-Jsk_m.mjs} +1 -1
- package/dist/interactive-init-CzbT0dDB.mjs +8 -0
- package/dist/{io-CH2g3vsv-JJtUIa_U.mjs → io-CH2g3vsv-BevbMdi6.mjs} +1 -1
- package/dist/{jiti-loader-cache-Bat69wam-DNIteTtO.mjs → jiti-loader-cache-Bat69wam-Cq2EONsH.mjs} +1 -1
- package/dist/{live-smoke-DpURW676.mjs → live-smoke-Be7Fzqj0.mjs} +18 -18
- package/dist/load-context-mb7uvLSn-C6DFwEWN.mjs +1 -0
- package/dist/{loader-708jrx4Y-BbJRXNlQ.mjs → loader-708jrx4Y-eFvaGnCt.mjs} +1 -1
- package/dist/main.mjs +86 -86
- package/dist/{manifest-registry-_hxKCS2K-OL8KK_o4.mjs → manifest-registry-_hxKCS2K-ezh_x2Cu.mjs} +1 -1
- package/dist/{message-channel-Bk_YHfQg-n2Hw2Y0L.mjs → message-channel-Bk_YHfQg-BGBJVvRK.mjs} +1 -1
- package/dist/{message-channel-core-DTA--Gjh-CIh10vfo.mjs → message-channel-core-DTA--Gjh-DeWCDZu1.mjs} +1 -1
- package/dist/message.config.runtime-K-k4XOyq-JWPtRES_.mjs +1 -0
- package/dist/message.gateway.runtime-DqHOHRTQ-BeYUdgSg.mjs +1 -0
- package/dist/{mistral-DyL3Zo1b.mjs → mistral-zWGv0zHS.mjs} +1 -1
- package/dist/{model-auth-env-oyg2Hexc-DJbt9J3o.mjs → model-auth-env-oyg2Hexc-B5WQGZqf.mjs} +1 -1
- package/dist/{models-config-BmpSQJQF-BL6S5qAo.mjs → models-config-BmpSQJQF-Bwnt6IgA.mjs} +1 -1
- package/dist/models-config.runtime-DkQfNKqN.mjs +1 -0
- package/dist/{multipart-parser-B9dwXBqu.mjs → multipart-parser-D_0C82Yv.mjs} +1 -1
- package/dist/{oauth-25y2wc7K.mjs → oauth-TYJ7I-Cs.mjs} +1 -1
- package/dist/{openai-codex-responses-BbyAPsP1.mjs → openai-codex-responses-CJA9360v.mjs} +1 -1
- package/dist/{openai-completions-Bu5qvQzb.mjs → openai-completions-BfXo7VuS.mjs} +1 -1
- package/dist/{openai-responses-pIdwQBc4.mjs → openai-responses-BH-GaE-g.mjs} +1 -1
- package/dist/{openai-responses-shared-DqW1JSux.mjs → openai-responses-shared-DHm7pNQU.mjs} +1 -1
- package/dist/{paths-D6msg0S1-BO4XgM1u.mjs → paths-D6msg0S1-C3GtW9t2.mjs} +1 -1
- package/dist/{paths-D92DjaZ--DdtJ-zYp.mjs → paths-D92DjaZ--CKAvIWoZ.mjs} +1 -1
- package/dist/{pi-model-discovery-Bd0TWzo8-DvSM0eWu.mjs → pi-model-discovery-Bd0TWzo8-DcalEcic.mjs} +1 -1
- package/dist/{pi-model-discovery-runtime-PrjWOmsV.mjs → pi-model-discovery-runtime-DnW_CaR2.mjs} +1 -1
- package/dist/{pi-tools.before-tool-call.runtime-Bn7uqKie-WPxU5oNX.mjs → pi-tools.before-tool-call.runtime-Bn7uqKie-CitpH_Lv.mjs} +1 -1
- package/dist/{plugin-auto-enable-DdH3n9V8-Dr_bUXkG.mjs → plugin-auto-enable-DdH3n9V8-Dd9H4luQ.mjs} +1 -1
- package/dist/{provider-discovery.runtime-DY0VWQ81.mjs → provider-discovery.runtime-CVft4TR0.mjs} +1 -1
- package/dist/{provider-model-compat-CFqcq0it-BUwZENrz.mjs → provider-model-compat-CFqcq0it-W6mE-T-j.mjs} +1 -1
- package/dist/{provider-runtime-C8rljsNs-BDvu6FW3.mjs → provider-runtime-C8rljsNs-BGpzSHUk.mjs} +1 -1
- package/dist/{provider-runtime-CT50mNIX-DImw7ZZu.mjs → provider-runtime-CT50mNIX-CC3WVtfL.mjs} +1 -1
- package/dist/{provider-stream-COLujAAo-Dpq1DSIk.mjs → provider-stream-COLujAAo-BtNcIBP4.mjs} +1 -1
- package/dist/{providers.runtime-Ba7tOlq7-B4t6ywCr.mjs → providers.runtime-Ba7tOlq7-CX4GoaJL.mjs} +1 -1
- package/dist/{public-surface-loader-BVl0NQAE-TfJ3izj1.mjs → public-surface-loader-BVl0NQAE-CTXfgfHE.mjs} +1 -1
- package/dist/{resolve-C33B7eeu-DZM_z6Wr.mjs → resolve-C33B7eeu-DhMVJCKm.mjs} +1 -1
- package/dist/{runtime-Cym-fqI8-1GOIuRRQ.mjs → runtime-Cym-fqI8-BuiEWXF-.mjs} +1 -1
- package/dist/{runtime-snapshot-C54O1-gI-DxusscPf.mjs → runtime-snapshot-C54O1-gI-0r2omPvJ.mjs} +1 -1
- package/dist/{runtime-web-tools-fallback.runtime-Ca-qn1mj-BsYE2gOd.mjs → runtime-web-tools-fallback.runtime-Ca-qn1mj-C5hD_aI-.mjs} +1 -1
- package/dist/runtime-web-tools-manifest.runtime-BgxQTjmq-BTi3YQxK.mjs +1 -0
- package/dist/runtime-web-tools-public-artifacts.runtime-D9qcoWIX-DNaDY4zG.mjs +1 -0
- package/dist/{session-archive.runtime-B52_5vs4-cU2tYbBz.mjs → session-archive.runtime-B52_5vs4-CUKEEsvr.mjs} +1 -1
- package/dist/{session-key-Cn2QoOyX-QZeYmbxd.mjs → session-key-Cn2QoOyX-BIh-9Y77.mjs} +1 -1
- package/dist/{session-transcript-files.fs-DEeFXruQ-CXIAFSsr.mjs → session-transcript-files.fs-DEeFXruQ-Dh_OJado.mjs} +1 -1
- package/dist/{src-CCDx_C-U.mjs → src-C9CsRdwI.mjs} +1 -1
- package/dist/{subagent-announce-L5WsQatW--rMn240x.mjs → subagent-announce-L5WsQatW-DyZFJvpK.mjs} +1 -1
- package/dist/{subagent-announce.registry.runtime-DiqZyeTs-DNfNHsls.mjs → subagent-announce.registry.runtime-DiqZyeTs-WCL-itg8.mjs} +1 -1
- package/dist/{subagent-registry-steer-runtime-DFgZFC0j-XYS1_qwl.mjs → subagent-registry-steer-runtime-DFgZFC0j-BlxUMPcM.mjs} +1 -1
- package/dist/{subagent-system-prompt-C1qnN--K-CsU4f97T.mjs → subagent-system-prompt-C1qnN--K-bhNPmt0u.mjs} +1 -1
- package/dist/{target-parsing-loaded-DKkb6jJY-B830OA1a.mjs → target-parsing-loaded-DKkb6jJY-Bx7-SykE.mjs} +1 -1
- package/dist/{task-registry-delivery-runtime-Dd1CUkZF-B2Hj2k8C.mjs → task-registry-delivery-runtime-Dd1CUkZF-xNioBd-k.mjs} +2 -2
- package/dist/task-registry-delivery-runtime-ragbeVx5-BXczubuw.mjs +1 -0
- package/dist/{transcript-E_-ISOkD-VTwb782D.mjs → transcript-E_-ISOkD-STFNoSGx.mjs} +2 -2
- package/dist/transcript.runtime-BqhvZZdl-BLeKq_RO.mjs +1 -0
- package/dist/{web-provider-public-artifacts-BlpRwIUS-DbVhDOrY.mjs → web-provider-public-artifacts-BlpRwIUS-CjacPoGF.mjs} +1 -1
- package/dist/{web-search-providers.runtime--0aUtC3b-Bjh4Bmrz.mjs → web-search-providers.runtime--0aUtC3b-EcJfEKJo.mjs} +1 -1
- package/package.json +2 -1
- package/dist/channel-bootstrap.runtime-BVclcGv1-CEZ0-JP9.mjs +0 -1
- package/dist/config-Bim2pi8a-03N-28sw.mjs +0 -1
- package/dist/interactive-init-C5MFL5MW.mjs +0 -8
- package/dist/load-context-mb7uvLSn-3xYwSnOZ.mjs +0 -1
- package/dist/message.config.runtime-K-k4XOyq-F_h0Cgkl.mjs +0 -1
- package/dist/message.gateway.runtime-DqHOHRTQ-ge4c5p4s.mjs +0 -1
- package/dist/models-config.runtime-SOhLEw-f.mjs +0 -1
- package/dist/runtime-web-tools-manifest.runtime-BgxQTjmq-P6MKP9gQ.mjs +0 -1
- package/dist/runtime-web-tools-public-artifacts.runtime-D9qcoWIX-5VoyjouO.mjs +0 -1
- package/dist/task-registry-delivery-runtime-ragbeVx5-Bdvo2Q5u.mjs +0 -1
- package/dist/transcript.runtime-BqhvZZdl-B4E0TiX5.mjs +0 -1
- /package/dist/{build-Bkj0hOS2.mjs → build-DSSm_dj2.mjs} +0 -0
- /package/dist/{env-api-keys-Cuz5irWW.mjs → env-api-keys-qlOAYu08.mjs} +0 -0
- /package/dist/{event-stream-B7Ei41Bu.mjs → event-stream-JP51qlT7.mjs} +0 -0
- /package/dist/{from-Ba69_5cR.mjs → from-BmSefSMV.mjs} +0 -0
- /package/dist/{gateway-method-policy-C7rf0SeV-CTJcMQCE.mjs → gateway-method-policy-C7rf0SeV-DXbYlbpG.mjs} +0 -0
- /package/dist/{github-copilot-headers-BfhryVuU.mjs → github-copilot-headers-BQ2T2OVX.mjs} +0 -0
- /package/dist/{hash-Dw-N8Y9l.mjs → hash-DtceYjXb.mjs} +0 -0
- /package/dist/{headers-Bpsp70B9.mjs → headers-KsIWdB9S.mjs} +0 -0
- /package/dist/{home-dir-C44RaPME-B5iLWwCq.mjs → home-dir-C44RaPME-BqOMy1pu.mjs} +0 -0
- /package/dist/{json-file-BQRNuxmK-hRjIgOXI.mjs → json-file-BQRNuxmK-DQHpAzI5.mjs} +0 -0
- /package/dist/{json-parse-BESd8UAM.mjs → json-parse-BJPqxncf.mjs} +0 -0
- /package/dist/{jws-YaZ38F_i.mjs → jws-EKtyH_je.mjs} +0 -0
- /package/dist/{lark-cli-provider-BLMxH6CN.mjs → lark-cli-provider-DrGmcwiB.mjs} +0 -0
- /package/dist/{openai-C-rgGb7X.mjs → openai-D-MIrxrj.mjs} +0 -0
- /package/dist/{process-scoped-map-B2cWkYET-Co-i-MXA.mjs → process-scoped-map-B2cWkYET-Bc7DvrUZ.mjs} +0 -0
- /package/dist/{runtime-channel-state-CohMybAh-BBzhl07Q.mjs → runtime-channel-state-CohMybAh-DfCjeyJq.mjs} +0 -0
- /package/dist/{runtime-state-IBOIXKOx-Cw1GA1td.mjs → runtime-state-IBOIXKOx-Cr97WVOr.mjs} +0 -0
- /package/dist/{src-DACmA9V6.mjs → src-5lm1WxWm.mjs} +0 -0
- /package/dist/{thinking-Bh-7MqXz-uApNUe6g.mjs → thinking-Bh-7MqXz-BB7ZJReA.mjs} +0 -0
- /package/dist/{transform-messages-BTA3xbAI.mjs → transform-messages-B6RF0Czv.mjs} +0 -0
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import{r as e}from"./chunk-DHbaKqs-.mjs";import{t}from"./lark-logger-xpMKNNtY.mjs";import{createWriteStream as n,existsSync as r,mkdirSync as i,readFileSync as a,writeFileSync as o}from"node:fs";import s,{basename as c,dirname as l,extname as u,join as d,resolve as f}from"node:path";import{fileURLToPath as p}from"node:url";import{copyFile as m,mkdir as h,readFile as g,readdir as _,rename as v,rm as y,stat as b,unlink as ee,writeFile as x}from"node:fs/promises";import te,{homedir as S,tmpdir as ne}from"node:os";import{execFileSync as re,spawn as ie}from"node:child_process";import{createHash as ae,randomUUID as C}from"node:crypto";import{createInterface as oe}from"node:readline";import{v4 as w,v5 as se}from"uuid";import{readFile as ce,writeFile as le}from"fs/promises";import{existsSync as ue}from"fs";import{createCipheriv as de,createDecipheriv as fe,randomBytes as pe}from"crypto";import{EventEmitter as me}from"node:events";import{pipeline as he}from"node:stream/promises";import{Transform as ge}from"node:stream";import _e from"ws";const ve=`.chats`;function ye(){return d(S(),`.larkpal`,`workspace`)}function T(e=ye()){return process.env.LARKPAL_WORKSPACE??e}function be(e=T()){return d(e,ve)}function xe(e=T()){return d(e,`.chat-history`)}const E=t(`user/credential-vault`);var Se=class{credentialPath;encryptionKey;store={};loaded=!1;constructor(e){this.credentialPath=`${e}/credentials.json`;let t=process.env.LARKPAL_ENCRYPTION_KEY;t?(this.encryptionKey=t.length===64?Buffer.from(t,`hex`):Buffer.from(t,`base64`),this.encryptionKey.length===32?E.info(`凭证加密已启用`):(E.error(`LARKPAL_ENCRYPTION_KEY 长度不正确,需要 32 字节`,{actualLength:this.encryptionKey.length}),this.encryptionKey=null)):(this.encryptionKey=null,E.warn(`LARKPAL_ENCRYPTION_KEY 未设置,凭证将以明文存储(仅限开发模式)`))}async load(){if(!ue(this.credentialPath)){E.info(`凭证文件不存在,使用空凭证`,{path:this.credentialPath}),this.store={},this.loaded=!0;return}try{let e=await ce(this.credentialPath,`utf-8`);this.store=JSON.parse(e),this.loaded=!0,E.info(`凭证文件加载完成`,{path:this.credentialPath,credentialCount:Object.keys(this.store).length})}catch(e){E.error(`凭证文件加载失败`,{path:this.credentialPath,error:e instanceof Error?e.message:String(e)}),this.store={},this.loaded=!0}}async save(){try{await le(this.credentialPath,JSON.stringify(this.store,null,2),`utf-8`),E.info(`凭证文件保存完成`,{path:this.credentialPath,credentialCount:Object.keys(this.store).length})}catch(e){throw E.error(`凭证文件保存失败`,{path:this.credentialPath,error:e instanceof Error?e.message:String(e)}),e}}async getCredential(e){this.loaded||await this.load();let t=this.store[e];return t?this.isEncrypted(t)?this.decrypt(t):t:null}async setCredential(e,t){this.loaded||await this.load(),E.info(`设置凭证`,{name:e,fields:Object.keys(t)}),this.encryptionKey?this.store[e]=this.encrypt(t):this.store[e]=t,await this.save()}async deleteCredential(e){return this.loaded||await this.load(),e in this.store?(delete this.store[e],await this.save(),E.info(`凭证已删除`,{name:e}),!0):!1}async listCredentialNames(){return this.loaded||await this.load(),Object.keys(this.store)}async getAllCredentialsAsEnv(){this.loaded||await this.load();let e={};for(let[t,n]of Object.entries(this.store))try{let r=this.isEncrypted(n)?this.decrypt(n):n;if(!r)continue;let i=`CRED_${t.toUpperCase().replace(/[^A-Z0-9]/g,`_`)}`;for(let[t,n]of Object.entries(r))if(typeof n==`string`||typeof n==`number`){let r=`${i}_${t.toUpperCase().replace(/[^A-Z0-9]/g,`_`)}`;e[r]=String(n)}}catch(e){E.warn(`凭证解密失败,跳过`,{name:t,error:e instanceof Error?e.message:String(e)})}return e}encrypt(e){if(!this.encryptionKey)throw Error(`加密密钥未设置`);let t=pe(16),n=de(`aes-256-gcm`,this.encryptionKey,t),r=JSON.stringify(e),i=Buffer.concat([n.update(r,`utf-8`),n.final()]),a=n.getAuthTag();return{encrypted:!0,iv:t.toString(`base64`),authTag:a.toString(`base64`),ciphertext:i.toString(`base64`)}}decrypt(e){if(!this.encryptionKey)throw Error(`加密密钥未设置,无法解密凭证`);let t=Buffer.from(e.iv,`base64`),n=Buffer.from(e.authTag,`base64`),r=Buffer.from(e.ciphertext,`base64`),i=fe(`aes-256-gcm`,this.encryptionKey,t);i.setAuthTag(n);let a=Buffer.concat([i.update(r),i.final()]);return JSON.parse(a.toString(`utf-8`))}isEncrypted(e){return e.encrypted===!0&&typeof e.iv==`string`&&typeof e.ciphertext==`string`}};function Ce(e,t){let n=e?.disallowedTools??[];return n.some(e=>e.tool===t)?{...e,allowedTools:e?.allowedTools??[],allowedSkills:e?.allowedSkills??[],disallowedTools:n}:{...e,allowedTools:e?.allowedTools??[],allowedSkills:e?.allowedSkills??[],disallowedTools:[...n,{tool:t}]}}function we(e){let t=e?.disallowedTools?.map(e=>e.tool.trim()).filter(Boolean);if(t?.length)return[...new Set(t)].join(`,`)}const D=t(`user/mcp-merge`),Te=s.dirname(p(import.meta.url)),Ee=s.join(te.homedir(),`.claude`,`mcp-servers.json`);function De(){let e=s.resolve(Te,`..`,`dist`,`mcp-server.mjs`);if(r(e))return{command:`node`,args:[e]};let t=s.resolve(Te,`..`,`src`,`mcp-server`,`index.ts`);return r(t)?{command:`npx`,args:[`tsx`,t]}:{command:`node`,args:[e]}}function Oe(e,t,n){let{command:r,args:i}=De(),a=we(n);return{command:r,args:i,env:{PATH:process.env.PATH||`/usr/local/bin:/usr/bin:/bin`,HOME:process.env.HOME||`/home/larkpal`,NODE_PATH:process.env.NODE_PATH||``,LARKPAL_MCP_SESSION_ID:e,...t?{LARKPAL_MCP_CWD:t}:{},...a?{LARKPAL_MCP_DISABLED_TOOLS:a}:{},LARKPAL_GATEWAY_PORT:process.env.LARKPAL_GATEWAY_PORT||`3000`}}}async function ke(e,t,n,i){let a={larkpal:Oe(t,n,i)},o={};if(r(Ee))try{let e=await g(Ee,`utf-8`);o=JSON.parse(e),D.info(`全局 MCP 配置加载完成`,{serverCount:Object.keys(o).length})}catch(e){D.warn(`全局 MCP 配置文件解析失败`,{path:Ee,error:e instanceof Error?e.message:String(e)})}let c={};if(e){let t=s.join(e.credentialDir,`mcp-servers.json`);if(r(t))try{let n=await g(t,`utf-8`);c=JSON.parse(n),D.info(`用户 MCP 配置加载完成`,{userId:e.userId,serverCount:Object.keys(c).length,servers:Object.keys(c)})}catch(n){D.warn(`用户 MCP 配置文件解析失败`,{userId:e?.userId,path:t,error:n instanceof Error?n.message:String(n)})}}let l={...a,...o,...c};D.info(`MCP 配置合并完成`,{userId:e?.userId,builtinServers:Object.keys(a),globalServers:Object.keys(o),userServers:Object.keys(c),mergedServers:Object.keys(l)});let u=s.join(te.tmpdir(),`mcp-${t}.json`);return await x(u,JSON.stringify({mcpServers:l},null,2),`utf-8`),D.info(`MCP 合并配置已写入临时文件`,{path:u,serverCount:Object.keys(l).length}),u}async function Ae(e){let t=s.join(te.tmpdir(),`mcp-${e}.json`);try{r(t)&&(await ee(t),D.debug(`MCP 临时配置文件已清理`,{path:t}))}catch{}}function je(e){let t=Array.isArray(e)?e:[],n=new Set,r=0,i=0,a=0,o=0;for(let e of t)if(Ie(e)){if(e.type===`text`){r++;continue}if(e.type===`image`){i++;let t=Ie(e.source)?e.source:void 0,r=typeof t?.media_type==`string`?t.media_type:void 0,a=typeof t?.data==`string`?t.data:void 0;r&&n.add(r),a&&(o+=Fe(a));continue}if(e.type===`document`){a++;let t=Ie(e.source)?e.source:void 0,r=typeof t?.media_type==`string`?t.media_type:void 0,i=typeof t?.data==`string`?t.data:void 0;r&&n.add(r),i&&(o+=Fe(i))}}return{contentBlockCount:t.length,textBlockCount:r,imageBlockCount:i,documentBlockCount:a,mediaBytes:o,mediaTypes:[...n].sort()}}function Me(e,t){return t.imageBlockCount===0&&t.documentBlockCount===0?null:{type:`runtime-multimodal-input`,sessionId:e,timestamp:new Date().toISOString(),imageBlockCount:t.imageBlockCount,documentBlockCount:t.documentBlockCount,contentBlockCount:t.contentBlockCount,textBlockCount:t.textBlockCount,mediaBytes:t.mediaBytes,mediaTypes:t.mediaTypes}}function Ne(e){return/(?:image|vision|visual|ocr|pdf|document)/i.test(e)}function Pe(e){return{type:`provider-multimodal-unverified`,sessionId:e.sessionId,timestamp:new Date().toISOString(),toolName:e.toolName,toolUseId:e.toolUseId,reasonCode:`visual_unknown_tool_after_multimodal_input`,imageBlockCount:e.summary?.imageBlockCount,documentBlockCount:e.summary?.documentBlockCount,mediaBytes:e.summary?.mediaBytes,mediaTypes:e.summary?.mediaTypes}}function Fe(e){let t=e.replace(/\s/g,``);if(!t)return 0;let n=t.endsWith(`==`)?2:+!!t.endsWith(`=`);return Math.max(0,Math.floor(t.length*3/4)-n)}function Ie(e){return typeof e==`object`&&!!e}const Le={Read:`正在读取文件`,Write:`正在写入文件`,Edit:`正在编辑文件`,MultiEdit:`正在批量编辑文件`,Bash:`正在执行命令`,Grep:`正在搜索工作区`,Glob:`正在查找文件`,LS:`正在浏览目录`,WebSearch:`正在搜索网页`,WebFetch:`正在获取网页内容`,TodoWrite:`正在更新任务列表`,Task:`正在执行子任务`};function Re(e){return Le[e]||`正在使用 ${e}`}const O=t(`cc-runtime/stream-parser`),ze=8e3;var Be=class extends me{toolNamesById=new Map;declaredTools=null;parseLine(e){let t=e.trim();if(!t)return;let n;try{n=JSON.parse(t)}catch(e){O.warn(`NDJSON 解析失败,跳过该行`,{error:String(e),rawLine:t.slice(0,200)}),this.emit(`parseError`,e,t);return}if(n.parent_tool_use_id!=null&&n.type!==`result`){O.debug(`跳过 subagent 内部事件`,{type:n.type,parentToolUseId:n.parent_tool_use_id});return}switch(n.type){case`stream_event`:this.handleStreamEvent(n);break;case`assistant`:this.handleAssistant(n);break;case`user`:this.handleUser(n);break;case`tool_progress`:this.handleToolProgress(n);break;case`result`:this.handleResult(n);break;case`system`:O.info(`收到 system 消息`,{subtype:n.subtype,detail:JSON.stringify(n).slice(0,500)}),this.handleSystem(n),this.emit(`system`,n);break;default:O.debug(`收到未知消息类型,已忽略`,{type:n.type});break}}handleStreamEvent(e){let t=e.event;if(t)switch(t.type){case`content_block_start`:{let e=t.content_block;if(O.debug(`content_block_start 事件`,{blockType:e?.type,toolName:e?.name,toolUseId:e?.id}),e?.type===`tool_use`&&e.name){if(!this.recordToolUse(e.name,e.id,e.input))break;O.info(`工具调用开始`,{toolName:e.name,displayName:Re(e.name),toolUseId:e.id}),this.emit(`toolUseStart`,e.name,e.input??{},e.id)}break}case`content_block_delta`:{let e=t.delta;if(!e)break;e.type===`text_delta`&&e.text?this.emit(`textDelta`,e.text):e.type===`thinking_delta`&&e.thinking&&this.emit(`thinkingDelta`,e.thinking);break}case`message_delta`:{let e=t.delta?.stop_reason;e&&(O.info(`轮次结束`,{stopReason:e}),this.emit(`turnEnd`,e));break}default:break}}handleAssistant(e){let t=e.message?.content,n=e.message?.stop_reason,r=Array.isArray(t)?t.map(e=>`${e.type}${e.name?`:`+e.name:``}`).join(`, `):`none`;if(O.info(`收到完整 assistant 消息`,{model:e.message?.model,stopReason:n,contentBlocks:t?.length,blockTypes:r}),Array.isArray(t)){for(let e of t)if(e.type===`tool_use`&&e.name){if(!this.recordToolUse(e.name,e.id,e.input))continue;O.info(`从 assistant 消息提取工具调用`,{toolName:e.name,displayName:Re(e.name),toolUseId:e.id}),this.emit(`toolUseStart`,e.name,e.input??{},e.id)}}this.emit(`assistant`,e)}handleUser(e){let t=e.message?.content;if(Array.isArray(t)){for(let n of t)if(n.type===`tool_result`&&n.tool_use_id){let t=this.buildToolResultSummary(n,e.toolUseResult);O.debug(`工具结果返回`,{toolUseId:n.tool_use_id,toolName:t.toolName,isError:t.isError,truncated:t.truncated}),this.emit(`toolResult`,n.tool_use_id,t)}}}handleSystem(e){e.subtype!==`init`||!Array.isArray(e.tools)||(this.declaredTools=new Set(e.tools))}recordToolUse(e,t,n){if(t&&this.toolNamesById.set(t,e),this.declaredTools&&!this.declaredTools.has(e)){let r=[...this.declaredTools];return O.warn(`模型请求了未声明工具,已抑制正常 toolUseStart`,{toolName:e,toolUseId:t,availableTools:r}),this.emit(`unknownToolUse`,e,t,n,r),!1}return!0}buildToolResultSummary(e,t){let n=Ve(e.content),r=Ue(n),i=He(t);return{toolCallId:e.tool_use_id,toolName:this.toolNamesById.get(e.tool_use_id),rawType:`tool_result`,isError:e.is_error,content:r.content,resultSummary:We(n,i),truncated:r.truncated||i.truncated,originalSize:Math.max(n.length,i.originalSize),toolUseResult:i.summary}}handleToolProgress(e){O.debug(`工具执行进度`,{toolName:e.tool_name,elapsed:e.elapsed_time_seconds}),this.emit(`toolProgress`,e.tool_name,e.elapsed_time_seconds)}handleResult(e){O.info(`CC 执行完成`,{subtype:e.subtype,isError:e.is_error,durationMs:e.duration_ms,totalCostUsd:e.total_cost_usd,numTurns:e.num_turns}),this.emit(`result`,{subtype:e.subtype,result:e.result,durationMs:e.duration_ms,totalCostUsd:e.total_cost_usd,numTurns:e.num_turns,isError:e.is_error})}};function Ve(e){return typeof e==`string`?e:Ge(e)}function He(e){if(e===void 0)return{originalSize:0,truncated:!1};let t=typeof e==`string`?e:Ge(e),n=Ue(t);return{summary:typeof e==`string`?n.content:Ke(n.content)??n.content,originalSize:t.length,truncated:n.truncated}}function Ue(e){return e.length<=ze?{content:e,truncated:!1}:{content:e.slice(0,ze),truncated:!0}}function We(e,t){let n=(typeof t.summary==`string`?t.summary:t.summary===void 0?void 0:Ge(t.summary))||e,r=(n.match(/<tool_use_error>([\s\S]*?)<\/tool_use_error>/)?.[1]||n).trim();return r?Ue(r).content:void 0}function Ge(e){try{return JSON.stringify(e)}catch{return String(e)}}function Ke(e){try{return JSON.parse(e)}catch{return}}const qe=t(`cc-runtime/transcript-sanitizer`),Je=at(`LARKPAL_TRANSCRIPT_SANITIZER_MAX_BYTES`,50*1024*1024);async function Ye(e){let t={changed:!1,lines:0,sanitizedImageBlocks:0,artifacts:0},n=await b(e);if(n.size>Je)return qe.warn(`跳过过大的 Claude transcript sanitizer`,{filePath:e,size:n.size}),t;let r=await g(e,`utf-8`),i=r.endsWith(`
|
|
1
|
+
import{r as e}from"./chunk-DHbaKqs-.mjs";import{t}from"./lark-logger-xpMKNNtY.mjs";import{t as n}from"./config-CtxZK_ZE.mjs";import{createWriteStream as r,existsSync as i,mkdirSync as a,readFileSync as o,writeFileSync as s}from"node:fs";import c,{basename as l,dirname as u,extname as d,join as f,resolve as p}from"node:path";import{fileURLToPath as m}from"node:url";import{copyFile as h,mkdir as g,readFile as _,readdir as v,rename as y,rm as b,stat as ee,unlink as x,writeFile as S}from"node:fs/promises";import te,{homedir as C,tmpdir as ne}from"node:os";import{execFileSync as re,spawn as ie}from"node:child_process";import{createHash as ae,randomUUID as w}from"node:crypto";import{createInterface as oe}from"node:readline";import{v4 as T,v5 as se}from"uuid";import{readFile as ce,writeFile as le}from"fs/promises";import{existsSync as ue}from"fs";import{createCipheriv as de,createDecipheriv as fe,randomBytes as pe}from"crypto";import{EventEmitter as me}from"node:events";import{pipeline as he}from"node:stream/promises";import{Transform as ge}from"node:stream";import _e from"ws";const ve=`.chats`;function ye(){return f(C(),`.larkpal`,`workspace`)}function E(e=ye()){return process.env.LARKPAL_WORKSPACE??e}function be(e=E()){return f(e,ve)}function xe(e=E()){return f(e,`.chat-history`)}const D=t(`user/credential-vault`);var Se=class{credentialPath;encryptionKey;store={};loaded=!1;constructor(e){this.credentialPath=`${e}/credentials.json`;let t=process.env.LARKPAL_ENCRYPTION_KEY;t?(this.encryptionKey=t.length===64?Buffer.from(t,`hex`):Buffer.from(t,`base64`),this.encryptionKey.length===32?D.info(`凭证加密已启用`):(D.error(`LARKPAL_ENCRYPTION_KEY 长度不正确,需要 32 字节`,{actualLength:this.encryptionKey.length}),this.encryptionKey=null)):(this.encryptionKey=null,D.warn(`LARKPAL_ENCRYPTION_KEY 未设置,凭证将以明文存储(仅限开发模式)`))}async load(){if(!ue(this.credentialPath)){D.info(`凭证文件不存在,使用空凭证`,{path:this.credentialPath}),this.store={},this.loaded=!0;return}try{let e=await ce(this.credentialPath,`utf-8`);this.store=JSON.parse(e),this.loaded=!0,D.info(`凭证文件加载完成`,{path:this.credentialPath,credentialCount:Object.keys(this.store).length})}catch(e){D.error(`凭证文件加载失败`,{path:this.credentialPath,error:e instanceof Error?e.message:String(e)}),this.store={},this.loaded=!0}}async save(){try{await le(this.credentialPath,JSON.stringify(this.store,null,2),`utf-8`),D.info(`凭证文件保存完成`,{path:this.credentialPath,credentialCount:Object.keys(this.store).length})}catch(e){throw D.error(`凭证文件保存失败`,{path:this.credentialPath,error:e instanceof Error?e.message:String(e)}),e}}async getCredential(e){this.loaded||await this.load();let t=this.store[e];return t?this.isEncrypted(t)?this.decrypt(t):t:null}async setCredential(e,t){this.loaded||await this.load(),D.info(`设置凭证`,{name:e,fields:Object.keys(t)}),this.encryptionKey?this.store[e]=this.encrypt(t):this.store[e]=t,await this.save()}async deleteCredential(e){return this.loaded||await this.load(),e in this.store?(delete this.store[e],await this.save(),D.info(`凭证已删除`,{name:e}),!0):!1}async listCredentialNames(){return this.loaded||await this.load(),Object.keys(this.store)}async getAllCredentialsAsEnv(){this.loaded||await this.load();let e={};for(let[t,n]of Object.entries(this.store))try{let r=this.isEncrypted(n)?this.decrypt(n):n;if(!r)continue;let i=`CRED_${t.toUpperCase().replace(/[^A-Z0-9]/g,`_`)}`;for(let[t,n]of Object.entries(r))if(typeof n==`string`||typeof n==`number`){let r=`${i}_${t.toUpperCase().replace(/[^A-Z0-9]/g,`_`)}`;e[r]=String(n)}}catch(e){D.warn(`凭证解密失败,跳过`,{name:t,error:e instanceof Error?e.message:String(e)})}return e}encrypt(e){if(!this.encryptionKey)throw Error(`加密密钥未设置`);let t=pe(16),n=de(`aes-256-gcm`,this.encryptionKey,t),r=JSON.stringify(e),i=Buffer.concat([n.update(r,`utf-8`),n.final()]),a=n.getAuthTag();return{encrypted:!0,iv:t.toString(`base64`),authTag:a.toString(`base64`),ciphertext:i.toString(`base64`)}}decrypt(e){if(!this.encryptionKey)throw Error(`加密密钥未设置,无法解密凭证`);let t=Buffer.from(e.iv,`base64`),n=Buffer.from(e.authTag,`base64`),r=Buffer.from(e.ciphertext,`base64`),i=fe(`aes-256-gcm`,this.encryptionKey,t);i.setAuthTag(n);let a=Buffer.concat([i.update(r),i.final()]);return JSON.parse(a.toString(`utf-8`))}isEncrypted(e){return e.encrypted===!0&&typeof e.iv==`string`&&typeof e.ciphertext==`string`}};function Ce(e,t){let n=e?.disallowedTools??[];return n.some(e=>e.tool===t)?{...e,allowedTools:e?.allowedTools??[],allowedSkills:e?.allowedSkills??[],disallowedTools:n}:{...e,allowedTools:e?.allowedTools??[],allowedSkills:e?.allowedSkills??[],disallowedTools:[...n,{tool:t}]}}function we(e){let t=e?.disallowedTools?.map(e=>e.tool.trim()).filter(Boolean);if(t?.length)return[...new Set(t)].join(`,`)}const O=t(`user/mcp-merge`),Te=c.dirname(m(import.meta.url)),Ee=c.join(te.homedir(),`.claude`,`mcp-servers.json`);function De(){let e=c.resolve(Te,`..`,`dist`,`mcp-server.mjs`);if(i(e))return{command:`node`,args:[e]};let t=c.resolve(Te,`..`,`src`,`mcp-server`,`index.ts`);return i(t)?{command:`npx`,args:[`tsx`,t]}:{command:`node`,args:[e]}}function Oe(e,t,n){let{command:r,args:i}=De(),a=we(n);return{command:r,args:i,env:{PATH:process.env.PATH||`/usr/local/bin:/usr/bin:/bin`,HOME:process.env.HOME||`/home/larkpal`,NODE_PATH:process.env.NODE_PATH||``,LARKPAL_MCP_SESSION_ID:e,...t?{LARKPAL_MCP_CWD:t}:{},...a?{LARKPAL_MCP_DISABLED_TOOLS:a}:{},LARKPAL_GATEWAY_PORT:process.env.LARKPAL_GATEWAY_PORT||`3000`}}}async function ke(e,t,n,r){let a={larkpal:Oe(t,n,r)},o={};if(i(Ee))try{let e=await _(Ee,`utf-8`);o=JSON.parse(e),O.info(`全局 MCP 配置加载完成`,{serverCount:Object.keys(o).length})}catch(e){O.warn(`全局 MCP 配置文件解析失败`,{path:Ee,error:e instanceof Error?e.message:String(e)})}let s={};if(e){let t=c.join(e.credentialDir,`mcp-servers.json`);if(i(t))try{let n=await _(t,`utf-8`);s=JSON.parse(n),O.info(`用户 MCP 配置加载完成`,{userId:e.userId,serverCount:Object.keys(s).length,servers:Object.keys(s)})}catch(n){O.warn(`用户 MCP 配置文件解析失败`,{userId:e?.userId,path:t,error:n instanceof Error?n.message:String(n)})}}let l={...a,...o,...s};O.info(`MCP 配置合并完成`,{userId:e?.userId,builtinServers:Object.keys(a),globalServers:Object.keys(o),userServers:Object.keys(s),mergedServers:Object.keys(l)});let u=c.join(te.tmpdir(),`mcp-${t}.json`);return await S(u,JSON.stringify({mcpServers:l},null,2),`utf-8`),O.info(`MCP 合并配置已写入临时文件`,{path:u,serverCount:Object.keys(l).length}),u}async function Ae(e){let t=c.join(te.tmpdir(),`mcp-${e}.json`);try{i(t)&&(await x(t),O.debug(`MCP 临时配置文件已清理`,{path:t}))}catch{}}function je(e){let t=Array.isArray(e)?e:[],n=new Set,r=0,i=0,a=0,o=0;for(let e of t)if(Ie(e)){if(e.type===`text`){r++;continue}if(e.type===`image`){i++;let t=Ie(e.source)?e.source:void 0,r=typeof t?.media_type==`string`?t.media_type:void 0,a=typeof t?.data==`string`?t.data:void 0;r&&n.add(r),a&&(o+=Fe(a));continue}if(e.type===`document`){a++;let t=Ie(e.source)?e.source:void 0,r=typeof t?.media_type==`string`?t.media_type:void 0,i=typeof t?.data==`string`?t.data:void 0;r&&n.add(r),i&&(o+=Fe(i))}}return{contentBlockCount:t.length,textBlockCount:r,imageBlockCount:i,documentBlockCount:a,mediaBytes:o,mediaTypes:[...n].sort()}}function Me(e,t){return t.imageBlockCount===0&&t.documentBlockCount===0?null:{type:`runtime-multimodal-input`,sessionId:e,timestamp:new Date().toISOString(),imageBlockCount:t.imageBlockCount,documentBlockCount:t.documentBlockCount,contentBlockCount:t.contentBlockCount,textBlockCount:t.textBlockCount,mediaBytes:t.mediaBytes,mediaTypes:t.mediaTypes}}function Ne(e){return/(?:image|vision|visual|ocr|pdf|document)/i.test(e)}function Pe(e){return{type:`provider-multimodal-unverified`,sessionId:e.sessionId,timestamp:new Date().toISOString(),toolName:e.toolName,toolUseId:e.toolUseId,reasonCode:`visual_unknown_tool_after_multimodal_input`,imageBlockCount:e.summary?.imageBlockCount,documentBlockCount:e.summary?.documentBlockCount,mediaBytes:e.summary?.mediaBytes,mediaTypes:e.summary?.mediaTypes}}function Fe(e){let t=e.replace(/\s/g,``);if(!t)return 0;let n=t.endsWith(`==`)?2:+!!t.endsWith(`=`);return Math.max(0,Math.floor(t.length*3/4)-n)}function Ie(e){return typeof e==`object`&&!!e}const Le={Read:`正在读取文件`,Write:`正在写入文件`,Edit:`正在编辑文件`,MultiEdit:`正在批量编辑文件`,Bash:`正在执行命令`,Grep:`正在搜索工作区`,Glob:`正在查找文件`,LS:`正在浏览目录`,WebSearch:`正在搜索网页`,WebFetch:`正在获取网页内容`,TodoWrite:`正在更新任务列表`,Task:`正在执行子任务`};function Re(e){return Le[e]||`正在使用 ${e}`}const k=t(`cc-runtime/stream-parser`),ze=8e3;var Be=class extends me{toolNamesById=new Map;declaredTools=null;parseLine(e){let t=e.trim();if(!t)return;let n;try{n=JSON.parse(t)}catch(e){k.warn(`NDJSON 解析失败,跳过该行`,{error:String(e),rawLine:t.slice(0,200)}),this.emit(`parseError`,e,t);return}if(n.parent_tool_use_id!=null&&n.type!==`result`){k.debug(`跳过 subagent 内部事件`,{type:n.type,parentToolUseId:n.parent_tool_use_id});return}switch(n.type){case`stream_event`:this.handleStreamEvent(n);break;case`assistant`:this.handleAssistant(n);break;case`user`:this.handleUser(n);break;case`tool_progress`:this.handleToolProgress(n);break;case`result`:this.handleResult(n);break;case`system`:k.info(`收到 system 消息`,{subtype:n.subtype,detail:JSON.stringify(n).slice(0,500)}),this.handleSystem(n),this.emit(`system`,n);break;default:k.debug(`收到未知消息类型,已忽略`,{type:n.type});break}}handleStreamEvent(e){let t=e.event;if(t)switch(t.type){case`content_block_start`:{let e=t.content_block;if(k.debug(`content_block_start 事件`,{blockType:e?.type,toolName:e?.name,toolUseId:e?.id}),e?.type===`tool_use`&&e.name){if(!this.recordToolUse(e.name,e.id,e.input))break;k.info(`工具调用开始`,{toolName:e.name,displayName:Re(e.name),toolUseId:e.id}),this.emit(`toolUseStart`,e.name,e.input??{},e.id)}break}case`content_block_delta`:{let e=t.delta;if(!e)break;e.type===`text_delta`&&e.text?this.emit(`textDelta`,e.text):e.type===`thinking_delta`&&e.thinking&&this.emit(`thinkingDelta`,e.thinking);break}case`message_delta`:{let e=t.delta?.stop_reason;e&&(k.info(`轮次结束`,{stopReason:e}),this.emit(`turnEnd`,e));break}default:break}}handleAssistant(e){let t=e.message?.content,n=e.message?.stop_reason,r=Array.isArray(t)?t.map(e=>`${e.type}${e.name?`:`+e.name:``}`).join(`, `):`none`;if(k.info(`收到完整 assistant 消息`,{model:e.message?.model,stopReason:n,contentBlocks:t?.length,blockTypes:r}),Array.isArray(t)){for(let e of t)if(e.type===`tool_use`&&e.name){if(!this.recordToolUse(e.name,e.id,e.input))continue;k.info(`从 assistant 消息提取工具调用`,{toolName:e.name,displayName:Re(e.name),toolUseId:e.id}),this.emit(`toolUseStart`,e.name,e.input??{},e.id)}}this.emit(`assistant`,e)}handleUser(e){let t=e.message?.content;if(Array.isArray(t)){for(let n of t)if(n.type===`tool_result`&&n.tool_use_id){let t=this.buildToolResultSummary(n,e.toolUseResult);k.debug(`工具结果返回`,{toolUseId:n.tool_use_id,toolName:t.toolName,isError:t.isError,truncated:t.truncated}),this.emit(`toolResult`,n.tool_use_id,t)}}}handleSystem(e){e.subtype!==`init`||!Array.isArray(e.tools)||(this.declaredTools=new Set(e.tools))}recordToolUse(e,t,n){if(t&&this.toolNamesById.set(t,e),this.declaredTools&&!this.declaredTools.has(e)){let r=[...this.declaredTools];return k.warn(`模型请求了未声明工具,已抑制正常 toolUseStart`,{toolName:e,toolUseId:t,availableTools:r}),this.emit(`unknownToolUse`,e,t,n,r),!1}return!0}buildToolResultSummary(e,t){let n=Ve(e.content),r=Ue(n),i=He(t);return{toolCallId:e.tool_use_id,toolName:this.toolNamesById.get(e.tool_use_id),rawType:`tool_result`,isError:e.is_error,content:r.content,resultSummary:We(n,i),truncated:r.truncated||i.truncated,originalSize:Math.max(n.length,i.originalSize),toolUseResult:i.summary}}handleToolProgress(e){k.debug(`工具执行进度`,{toolName:e.tool_name,elapsed:e.elapsed_time_seconds}),this.emit(`toolProgress`,e.tool_name,e.elapsed_time_seconds)}handleResult(e){k.info(`CC 执行完成`,{subtype:e.subtype,isError:e.is_error,durationMs:e.duration_ms,totalCostUsd:e.total_cost_usd,numTurns:e.num_turns}),this.emit(`result`,{subtype:e.subtype,result:e.result,durationMs:e.duration_ms,totalCostUsd:e.total_cost_usd,numTurns:e.num_turns,isError:e.is_error})}};function Ve(e){return typeof e==`string`?e:Ge(e)}function He(e){if(e===void 0)return{originalSize:0,truncated:!1};let t=typeof e==`string`?e:Ge(e),n=Ue(t);return{summary:typeof e==`string`?n.content:Ke(n.content)??n.content,originalSize:t.length,truncated:n.truncated}}function Ue(e){return e.length<=ze?{content:e,truncated:!1}:{content:e.slice(0,ze),truncated:!0}}function We(e,t){let n=(typeof t.summary==`string`?t.summary:t.summary===void 0?void 0:Ge(t.summary))||e,r=(n.match(/<tool_use_error>([\s\S]*?)<\/tool_use_error>/)?.[1]||n).trim();return r?Ue(r).content:void 0}function Ge(e){try{return JSON.stringify(e)}catch{return String(e)}}function Ke(e){try{return JSON.parse(e)}catch{return}}const qe=t(`cc-runtime/transcript-sanitizer`),Je=at(`LARKPAL_TRANSCRIPT_SANITIZER_MAX_BYTES`,50*1024*1024);async function Ye(e){let t={changed:!1,lines:0,sanitizedImageBlocks:0,artifacts:0},n=await ee(e);if(n.size>Je)return qe.warn(`跳过过大的 Claude transcript sanitizer`,{filePath:e,size:n.size}),t;let r=await _(e,`utf-8`),i=r.endsWith(`
|
|
2
2
|
`),a=r.split(`
|
|
3
|
-
`);i&&a.pop(),t.lines=a.length;let o=[],s=
|
|
3
|
+
`);i&&a.pop(),t.lines=a.length;let o=[],s=f(u(e),`larkpal-artifacts`);for(let e of a){if(!e.trim()){o.push(e);continue}if(!it(e)){o.push(e);continue}let n;try{n=JSON.parse(e)}catch{o.push(e);continue}let r=await Ze(n,s);r.sanitizedImageBlocks>0?(t.changed=!0,t.sanitizedImageBlocks+=r.sanitizedImageBlocks,t.artifacts+=r.artifacts,o.push(JSON.stringify(n))):o.push(e)}if(!t.changed)return t;let c=`${e}.larkpal-sanitized-${process.pid}-${Date.now()}`;return await S(c,o.join(`
|
|
4
4
|
`)+(i?`
|
|
5
|
-
`:``),`utf-8`),await v(c,e),qe.info(`Claude transcript 图片结果已清理`,{filePath:e,...t}),t}function Xe(){let e=process.env.LARKPAL_TRANSCRIPT_SANITIZER;return e!==`0`&&e!==`false`}async function Ze(e,t){let n=0,r=0,i=k(e.message),a=i?i.content:void 0,o=k(e.toolUseResult),s;if(Array.isArray(a))for(let e=0;e<a.length;e++){let i=k(a[e]);if(i){if(i.type===`tool_result`){let e=typeof i.tool_use_id==`string`?i.tool_use_id:void 0,a=await $e(i.content,t,e);if(!a)continue;i.content=a.content,n+=a.imageBlocks,r+=a.artifacts,s??=a.metadata[0]?.artifactUri;continue}if(nt(i)){let o=await et(t,i,void 0,e);a[e]={type:`text`,text:tt([o])},n++,r++,s??=o.artifactUri}}}let c=await Qe(o,t,s);return c&&(n+=c.sanitizedImageBlocks,r+=c.artifacts),{sanitizedImageBlocks:n,artifacts:r}}async function Qe(e,t,n){if(e?.type!==`image`)return null;let r=k(e.file);if(!r||typeof r.base64!=`string`)return null;let i=n,a=0;return i||(i=(await et(t,{type:`image`,source:{type:`base64`,media_type:typeof r.type==`string`?r.type:void 0,data:r.base64},filePath:typeof r.filePath==`string`?r.filePath:void 0},void 0,0)).artifactUri,a=1),r.artifactUri=i,r.base64=`[redacted by LarkPal: image artifact externalized]`,{sanitizedImageBlocks:1,artifacts:a}}async function $e(e,t,n){if(!Array.isArray(e))return null;let r=[],i=0,a=0;for(let o=0;o<e.length;o++){let s=k(e[o]);if(!nt(s))continue;i++;let c=await et(t,s,n,o);r.push(c),a++}return i===0?null:{content:tt(r),imageBlocks:i,artifacts:a,metadata:r}}async function et(e,t,n,r){let i=k(t.source),a=typeof i?.data==`string`?i.data:``,o=typeof i?.media_type==`string`?i.media_type:void 0,s=`${n??C()}-${r}`,c=d(e,`${s}.json`),l=`artifact://claude-transcript/${s}`,u=rt(t);return await h(e,{recursive:!0}),await x(c,JSON.stringify({artifactUri:l,originalToolName:`Read`,toolUseId:n,mimeType:o,dimensions:u,originalSize:a.length,sourcePath:typeof t.filePath==`string`?t.filePath:void 0,base64:a},null,2),{encoding:`utf-8`,flag:`w`}),{artifactUri:l,originalToolName:`Read`,toolUseId:n,mimeType:o,dimensions:u,originalSize:a.length,sourcePath:typeof t.filePath==`string`?t.filePath:void 0,summary:`Rendered image/PDF page preview externalized by LarkPal transcript sanitizer.`}}function tt(e){return JSON.stringify({larkpalSanitized:!0,reason:`Previous image tool result was externalized to avoid replaying base64 image payloads into provider requests.`,artifacts:e})}function nt(e){if(!e||e.type!==`image`)return!1;let t=k(e.source);return t?.type===`base64`&&typeof t.data==`string`}function rt(e){let t=k(e.dimensions);if(!t)return;let n=t.displayWidth??t.originalWidth,r=t.displayHeight??t.originalHeight;if(!(typeof n!=`number`||typeof r!=`number`))return`${n}x${r}`}function it(e){return e.includes(`"base64"`)&&(e.includes(`"image"`)||e.includes(`"source"`))}function k(e){return typeof e==`object`&&e?e:void 0}function at(e,t){let n=process.env[e];if(!n)return t;let r=Number.parseInt(n,10);return Number.isFinite(r)&&r>0?r:t}const A=t(`cc-runtime/process-manager`),ot=(()=>{let e=process.env.LARKPAL_CC_IDLE_TIMEOUT;if(e===void 0||e===``)return 0;let t=parseInt(e,10);return isNaN(t)||t<0?0:t*1e3})(),st=process.env.LARKPAL_CC_EFFORT||`medium`;var ct=class{processes=new Map;idleTimers=new Map;sessionCwdCache=new Map;activeCallbacks=new Map;lastUserMessageIds=new Map;lastMessageHadImages=new Map;lastMultimodalSummaries=new Map;pendingControlRequests=new Map;abortedSessions=new Set;messageCompletionResolvers=new Map;sessionLocks=new Map;markAborted(e){this.abortedSessions.add(e)}consumeAborted(e){return this.abortedSessions.has(e)?(this.abortedSessions.delete(e),!0):!1}getLastMessageHadImages(e){return this.lastMessageHadImages.get(e)===!0}createMessageCompletionPromise(e){return new Promise(t=>{this.messageCompletionResolvers.set(e,t)})}resolveMessageCompletion(e){let t=this.messageCompletionResolvers.get(e);t&&(this.messageCompletionResolvers.delete(e),t())}async executePrompt(e,t){let{sessionId:n}=e,r=Date.now(),i=this.sessionLocks.get(n);i&&(A.info(`等待上一条消息处理完成`,{sessionId:n}),await i,A.info(`[perf] 串行锁等待完成`,{sessionId:n,waitMs:Date.now()-r}));let a=()=>{},o=new Promise(e=>{a=e});this.sessionLocks.set(n,o),this.activeCallbacks.set(n,t);try{let t=this.processes.get(n);if(t&&t.status===`running`&&t.useStreamInput){A.info(`向常驻进程发送消息`,{sessionId:n,promptLength:e.prompt.length,pid:t.childProcess.pid,prepareMs:Date.now()-r});let i=this.createMessageCompletionPromise(n);this.sendMessage(n,e.prompt),this.resetIdleTimer(n),await i,A.info(`[perf] executePrompt 完成(热进程)`,{sessionId:n,totalMs:Date.now()-r});return}t&&(t.status===`stopped`||t.status===`crashed`)&&(A.info(`清理已终止的旧进程,准备重启`,{sessionId:n,oldStatus:t.status}),this.cleanup(n),this.sessionLocks.set(n,o)),t&&t.status===`running`&&!t.useStreamInput&&(A.warn(`停止旧的单次进程后重新启动为常驻模式`,{sessionId:n}),await this.stopProcess(n),this.sessionLocks.set(n,o));let i=this.createMessageCompletionPromise(n),a=Date.now();await this.startPersistentProcess(e),A.info(`[perf] 冷启动进程完成`,{sessionId:n,coldStartMs:Date.now()-a}),await i,A.info(`[perf] executePrompt 完成(冷启动)`,{sessionId:n,totalMs:Date.now()-r})}finally{e.transcriptMode===`ephemeral`&&await this.stopProcess(n).catch(e=>{A.warn(`ephemeral CC 进程清理失败`,{sessionId:n,error:e instanceof Error?e.message:String(e)})}),this.sessionLocks.get(n)===o&&this.sessionLocks.delete(n),a()}}async startPersistentProcess(e,t){let{sessionId:n,cwd:i,prompt:a}=e,o=e.transcriptMode===`ephemeral`,s=o?w():se(n,`7c9e6679-7425-40de-944b-e07fc1f90ae7`),c=this.getCCSessionFilePath(i,s),l=r(c),u=!o&&(t?._forceResume||l);u&&l&&Xe()&&await Ye(c).catch(e=>{A.warn(`Claude transcript sanitizer 失败,继续启动进程`,{sessionId:n,transcriptPath:c,error:e instanceof Error?e.message:String(e)})});let d=[`-p`,`--input-format`,`stream-json`,`--output-format`,`stream-json`,`--verbose`,`--include-partial-messages`];u?d.push(`--resume`,s):d.push(`--session-id`,s),d.push(`--permission-mode`,`bypassPermissions`),e.maxTurns&&d.push(`--max-turns`,String(e.maxTurns)),e.maxBudgetUsd&&d.push(`--max-budget-usd`,String(e.maxBudgetUsd)),e.model&&d.push(`--model`,e.model),d.push(`--effort`,st);try{let t=await ke(e.userContext&&!e.userContext.isTenantIdentity?e.userContext:null,n,i,e.policy);d.push(`--mcp-config`,t),A.info(`MCP 配置已合并并注入到 CC 进程`,{sessionId:n,userId:e.userContext?.userId,mcpConfigPath:t})}catch(e){A.warn(`MCP 配置合并失败,CC 进程将使用全局默认配置`,{sessionId:n,error:e instanceof Error?e.message:String(e)})}let f={...process.env};if(f.CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING=`1`,f.LARKPAL_MCP_SESSION_ID=n,f.LARKPAL_MCP_CWD=i,e.userContext){let{userContext:t}=e;f.LARKPAL_USER_ID=t.userId,f.LARKPAL_USER_OPEN_ID=t.openId,f.LARKPAL_USER_NAME=t.userName,f.LARKPAL_CREDENTIAL_DIR=t.credentialDir,f.LARKPAL_IS_TENANT=t.isTenantIdentity?`1`:`0`;let r=process.env.LARKPAL_DISABLE_USER_AUTH===`1`||process.env.LARKPAL_DISABLE_USER_AUTH===`true`;if(!t.isTenantIdentity)try{let e=new Se(t.credentialDir);await e.load();let i=await e.getAllCredentialsAsEnv();if(Object.assign(f,i),r)delete f.LARK_USER_ACCESS_TOKEN,A.info(`LARKPAL_DISABLE_USER_AUTH 已启用,跳过飞书 user_access_token 注入`,{sessionId:n,userId:t.userId});else{let t=await e.getCredential(`lark`);t?.user_access_token&&typeof t.user_access_token==`string`&&(f.LARK_USER_ACCESS_TOKEN=t.user_access_token)}A.info(`用户凭证已注入到 CC 进程环境`,{sessionId:n,userId:t.userId,credentialCount:Object.keys(i).length,hasLarkUserToken:!!f.LARK_USER_ACCESS_TOKEN,disableUserAuth:r})}catch(e){A.warn(`用户凭证加载失败,CC 进程将使用默认环境`,{sessionId:n,userId:t.userId,error:e instanceof Error?e.message:String(e)})}}A.info(`启动常驻 CC 进程`,{sessionId:n,claudeSessionId:s,isResuming:u,cwd:i,args:d.join(` `)});let p=ie(`claude`,d,{cwd:i,stdio:[`pipe`,`pipe`,`pipe`],env:f}),m={sessionId:n,cwd:i,childProcess:p,status:`starting`,startedAt:new Date,lastActiveAt:new Date,useStreamInput:!0};this.processes.set(n,m),this.sessionCwdCache.set(n,i);let h=new Be;this.bindParserToCallbackProxy(h,n);let g=!1;return p.stdout&&oe({input:p.stdout}).on(`line`,e=>{if(m.lastActiveAt=new Date,this.resetIdleTimer(n),e.includes(`"control_response"`))try{let t=JSON.parse(e);if(t.type===`control_response`&&t.response?.request_id){let e=this.pendingControlRequests.get(t.response.request_id);if(e){clearTimeout(e.timer),this.pendingControlRequests.delete(t.response.request_id),A.info(`收到 control_response`,{sessionId:n,requestId:t.response.request_id,subtype:t.response.subtype,responseKeys:Object.keys(t.response),fullResponse:JSON.stringify(t.response).slice(0,500)}),e.resolve(t.response);return}}}catch{}h.parseLine(e)}),p.stderr&&oe({input:p.stderr}).on(`line`,e=>{e.includes(`no stdin data received`)||(e.toLowerCase().includes(`already in use`)&&(g=!0),A.warn(`CC 进程 stderr`,{sessionId:n,line:e.slice(0,500)}))}),p.on(`close`,async(r,i)=>{let a=r??-1,o=i??`none`;if(a===1&&g&&!u){A.info(`Session ID 已被占用,准备使用 --resume 模式重试`,{sessionId:n,claudeSessionId:s}),this.processes.delete(n),this.sessionCwdCache.delete(n);try{await this.startPersistentProcess(e,{skipInitialMessage:t?.skipInitialMessage,_forceResume:!0});return}catch(e){A.error(`Session ID 重试失败`,{sessionId:n,error:e instanceof Error?e.message:String(e)})}}a===0?(A.info(`CC 常驻进程正常退出`,{sessionId:n,exitCode:a,signal:o}),m.status=`stopped`):(A.error(`CC 常驻进程异常退出`,{sessionId:n,exitCode:a,signal:o}),m.status=`crashed`,this.activeCallbacks.get(n)?.onError?.(Error(`CC 常驻进程异常退出: code=${a}, signal=${o}`))),this.resolveMessageCompletion(n),this.cleanup(n)}),p.on(`error`,e=>{A.error(`CC 常驻进程启动失败`,{sessionId:n,error:e.message}),m.status=`crashed`,this.activeCallbacks.get(n)?.onError?.(e),this.resolveMessageCompletion(n),this.cleanup(n)}),m.status=`running`,A.info(`CC 常驻进程已启动`,{sessionId:n,pid:p.pid,isResuming:u}),t?.skipInitialMessage||this.sendMessage(n,a),this.resetIdleTimer(n),m}bindParserToCallbackProxy(e,t){let n=()=>this.activeCallbacks.get(t),r=!1,i=Date.now(),a=this.processes.get(t);a&&(a._resetPerfTimer=()=>{r=!1,i=Date.now()}),e.on(`textDelta`,e=>{r||(r=!0,A.info(`[perf] 首 token (text)`,{sessionId:t,ttftMs:Date.now()-i})),n()?.onTextDelta?.(e)}),e.on(`thinkingDelta`,e=>{r||(r=!0,A.info(`[perf] 首 token (thinking)`,{sessionId:t,ttftMs:Date.now()-i})),n()?.onThinkingDelta?.(e)}),e.on(`toolUseStart`,(e,t,r)=>{n()?.onToolUseStart?.(e,t,r)}),e.on(`toolResult`,(e,t)=>{n()?.onToolResult?.(e,t)}),e.on(`unknownToolUse`,(e,r)=>{let i=n();i?.onUnknownToolUse?.(e,r),this.lastMessageHadImages.get(t)===!0&&Ne(e)&&i?.onRuntimeEvent?.(Pe({sessionId:t,toolName:e,toolUseId:r,summary:this.lastMultimodalSummaries.get(t)}))}),e.on(`toolProgress`,(e,t)=>{n()?.onToolProgress?.(e,t)}),e.on(`turnEnd`,e=>{A.info(`[perf] turnEnd`,{sessionId:t,stopReason:e,sinceMessageMs:Date.now()-i}),n()?.onTurnEnd?.(e)}),e.on(`result`,e=>{A.info(`[perf] result 事件`,{sessionId:t,sinceMessageMs:Date.now()-i}),n()?.onResult?.(e),this.resolveMessageCompletion(t)}),e.on(`parseError`,(e,n)=>{A.warn(`流解析错误`,{sessionId:t,error:e.message,rawLine:n.slice(0,200)})})}sendMessage(e,t){let n=this.processes.get(e);if(!n||!n.childProcess.stdin){A.error(`无法发送消息:进程不存在或 stdin 不可用`,{sessionId:e});return}n._resetPerfTimer?.();let r=w();this.lastUserMessageIds.set(e,r);let i=JSON.stringify({type:`user`,message:{role:`user`,content:t},parent_tool_use_id:null,uuid:r}),a=t.length,o=je(t),s=o.imageBlockCount>0;if(this.lastMessageHadImages.set(e,s),Array.isArray(t)){this.lastMultimodalSummaries.set(e,o);let t=Me(e,o);t&&this.activeCallbacks.get(e)?.onRuntimeEvent?.(t)}else this.lastMultimodalSummaries.delete(e);A.info(`通过 stdin 发送用户消息`,{sessionId:e,messageLength:a,isMultimodal:Array.isArray(t),hasImages:s,imageBlockCount:o.imageBlockCount,documentBlockCount:o.documentBlockCount,mediaBytes:o.mediaBytes,mediaTypes:o.mediaTypes,userMessageId:r,pid:n.childProcess.pid}),n.childProcess.stdin.write(i+`
|
|
6
|
-
`,t=>{t&&(
|
|
7
|
-
`,e=>{e&&(clearTimeout(c),this.pendingControlRequests.delete(i),o(Error(`控制请求 stdin 写入失败: ${e.message}`)))})})}getLastUserMessageId(e){return this.lastUserMessageIds.get(e)}getProcess(e){return this.processes.get(e)}getSessionCwd(e){return this.sessionCwdCache.get(e)}isSessionBusy(e){return this.messageCompletionResolvers.has(e)||this.sessionLocks.has(e)}async ensureProcessForRewind(e){let t=this.processes.get(e);if(t&&t.status===`running`)return
|
|
8
|
-
`,()=>{})}return new Promise(n=>{let r=t.childProcess,i=setTimeout(()=>{r.killed||(A.warn(`CC 常驻进程未在规定时间内退出,强制终止`,{sessionId:e}),r.kill(`SIGKILL`))},5e3);r.once(`close`,()=>{clearTimeout(i),this.cleanup(e),n()}),setTimeout(()=>{t.status===`stopping`&&!r.killed&&r.kill(`SIGTERM`)},1e3)})}async stopAll(){let e=Array.from(this.processes.keys());e.length!==0&&(A.info(`正在停止所有 CC 常驻进程`,{count:e.length}),await Promise.all(e.map(e=>this.stopProcess(e))),A.info(`所有 CC 常驻进程已停止`))}resetIdleTimer(e){let t=this.idleTimers.get(e);if(t&&clearTimeout(t),ot<=0)return;let n=setTimeout(()=>{A.info(`CC 常驻进程空闲超时,自动停止`,{sessionId:e,timeoutMs:ot}),this.stopProcess(e)},ot);this.idleTimers.set(e,n)}cleanup(e){this.resolveMessageCompletion(e),this.sessionLocks.delete(e),this.processes.delete(e),this.activeCallbacks.delete(e),this.lastUserMessageIds.delete(e),this.lastMessageHadImages.delete(e);for(let[t,n]of this.pendingControlRequests)n.sessionId===e&&(clearTimeout(n.timer),this.pendingControlRequests.delete(t),n.reject(Error(`进程已退出`)));let t=this.idleTimers.get(e);t&&(clearTimeout(t),this.idleTimers.delete(e)),Ae(e),A.debug(`已清理常驻进程状态`,{sessionId:e})}encodeCwdForCC(e){let t=e.replace(/[^a-zA-Z0-9]/g,`-`);if(t.length<=200)return t;let n=0;for(let t=0;t<e.length;t++)n=(n<<5)-n+e.charCodeAt(t)|0;return`${t.slice(0,200)}-${Math.abs(n).toString(36)}`}ccSessionExists(e,t){try{let n=this.getCCSessionFilePath(e,t),i=r(n);return A.debug(`检查 CC session 文件`,{cwd:e,claudeSessionId:t,sessionFile:n,exists:i}),i}catch(e){return A.warn(`检查 CC session 文件失败,默认为首次创建`,{error:e instanceof Error?e.message:String(e)}),!1}}getCCSessionFilePath(e,t){let n=this.encodeCwdForCC(e);return d(S(),`.claude`,`projects`,n,`${t}.jsonl`)}};const lt=t(`runtime/claude-code-adapter`);var ut=class e{name=`claude-code`;capabilities={followupInjection:!0,abort:!0,lastUserMessageId:!0,fileRewind:!0,imageInput:!0};processManager;lastRuntimeConfigs=new Map;static _instance=null;static getInstance(){return e._instance}constructor(){this.processManager=new ct,e._instance=this,lt.info(`ClaudeCodeAdapter 初始化完成`)}getProcessManager(){return this.processManager}async executePrompt(e,t){this.lastRuntimeConfigs.set(e.sessionId,e),lt.info(`executePrompt via ClaudeCodeAdapter`,{sessionId:e.sessionId,cwd:e.cwd,promptLength:e.prompt.length,model:e.model}),await this.processManager.executePrompt(e,t)}async stopProcess(e){lt.info(`stopProcess via ClaudeCodeAdapter`,{sessionId:e});let t=this.processManager.getProcess(e);if(t?.status===`running`){if(!t.childProcess.kill(`SIGINT`))throw Error(`停止失败:进程可能已退出`);this.processManager.markAborted(e);return}await this.processManager.stopProcess(e)}async stopAll(){lt.info(`stopAll via ClaudeCodeAdapter`),await this.processManager.stopAll()}getProcessInfo(e){let t=this.processManager.getProcess(e);if(!t)return;let n=this.lastRuntimeConfigs.get(e);return{sessionId:t.sessionId,cwd:t.cwd,status:t.status,startedAt:t.startedAt,lastActiveAt:t.lastActiveAt,runContext:n?.runContext,requestContext:n?.requestContext,authHeaders:n?.authHeaders}}getAllProcessInfo(){return this.processManager.getAllProcesses().map(e=>({sessionId:e.sessionId,cwd:e.cwd,status:e.status,startedAt:e.startedAt,lastActiveAt:e.lastActiveAt,runContext:this.lastRuntimeConfigs.get(e.sessionId)?.runContext,requestContext:this.lastRuntimeConfigs.get(e.sessionId)?.requestContext,authHeaders:this.lastRuntimeConfigs.get(e.sessionId)?.authHeaders}))}isSessionBusy(e){return this.processManager.isSessionBusy(e)}getCapabilities(){return this.capabilities}getLastUserMessageId(e){return this.processManager.getLastUserMessageId(e)}async previewRewind(e){let t=e.messageId??this.processManager.getLastUserMessageId(e.sessionId);if(!t)return dt(e.sessionId,``,`无法确定可撤销的消息`);if(!await this.processManager.ensureProcessForRewind(e.sessionId))return dt(e.sessionId,t,`会话进程不可用`);let n=await this.processManager.sendControlRequest(e.sessionId,`rewind_files`,{user_message_id:t,dry_run:!0});if(n.subtype!==`error`&&!n.response?.canRewind&&(await new Promise(e=>setTimeout(e,2e3)),n=await this.processManager.sendControlRequest(e.sessionId,`rewind_files`,{user_message_id:t,dry_run:!0})),n.subtype===`error`)return dt(e.sessionId,t,n.error??`撤销预览失败`);let r=n.response;return r?.canRewind?{canRewind:!0,sessionId:e.sessionId,messageId:t,filesChanged:r.filesChanged,insertions:r.insertions,deletions:r.deletions}:dt(e.sessionId,t)}async confirmRewind(e){let t=e.messageId??this.processManager.getLastUserMessageId(e.sessionId);if(!t)return ft(e.sessionId,``,`无法确定可撤销的消息`);if(!await this.processManager.ensureProcessForRewind(e.sessionId))return ft(e.sessionId,t,`会话进程不可用`);let n=await this.processManager.sendControlRequest(e.sessionId,`rewind_files`,{user_message_id:t,dry_run:!1});if(n.subtype===`error`)return ft(e.sessionId,t,n.error??`撤销失败`);let r=n.response;return{ok:!0,sessionId:e.sessionId,messageId:t,filesChanged:r?.filesChanged??[],insertions:r?.insertions??0,deletions:r?.deletions??0}}consumeAborted(e){return this.processManager.consumeAborted(e)}getLastMessageHadImages(e){return this.processManager.getLastMessageHadImages(e)}};function dt(e,t,n){return{canRewind:!1,sessionId:e,messageId:t,filesChanged:[],insertions:0,deletions:0,error:n}}function ft(e,t,n){return{ok:!1,sessionId:e,messageId:t,filesChanged:[],insertions:0,deletions:0,error:n}}const j=t(`codex-runtime/app-server-client`);var pt=class extends me{sessionId;cwd;childProcess;requestTimeoutMs;nextRequestId=1;closed=!1;pending=new Map;constructor(e){super(),this.sessionId=e.sessionId,this.cwd=e.cwd,this.requestTimeoutMs=e.requestTimeoutMs??6e4;let t=e.codexBin??process.env.LARKPAL_CODEX_BIN??`codex`,n=[`app-server`,`--listen`,`stdio://`,...e.extraArgs??[]];this.childProcess=ie(t,n,{cwd:e.cwd,env:e.env??process.env,stdio:[`pipe`,`pipe`,`pipe`]}),j.info(`Codex app-server 进程已启动`,{sessionId:this.sessionId,cwd:this.cwd,pid:this.childProcess.pid,args:n.join(` `)}),this.bindStreams()}request(e,t){if(this.closed)return Promise.reject(Error(`Codex app-server 已关闭,无法发送请求: ${e}`));if(!this.childProcess.stdin||this.childProcess.stdin.destroyed)return Promise.reject(Error(`Codex app-server stdin 不可用,无法发送请求: ${e}`));let n=this.nextRequestId++,r=String(n),i=t===void 0?{id:n,method:e}:{id:n,method:e,params:t};return new Promise((t,n)=>{let a=setTimeout(()=>{this.pending.delete(r),n(Error(`Codex app-server 请求超时: ${e}`))},this.requestTimeoutMs);this.pending.set(r,{method:e,timer:a,resolve:e=>t(e),reject:n}),this.writeJson(i).catch(e=>{clearTimeout(a),this.pending.delete(r),n(e)})})}respond(e,t){return this.writeJson({id:e,result:t})}respondError(e,t,n,r){return this.writeJson({id:e,error:{code:t,message:n,data:r}})}async close(){this.closed||(this.closed=!0,this.rejectAllPending(Error(`Codex app-server client closed`)),await new Promise(e=>{let t=this.childProcess;if(t.exitCode!=null||t.signalCode!=null){e();return}let n=setTimeout(()=>{t.killed||t.kill(`SIGKILL`)},5e3);t.once(`close`,()=>{clearTimeout(n),e()}),t.stdin&&!t.stdin.destroyed&&t.stdin.end(),t.kill(`SIGTERM`)}))}bindStreams(){this.childProcess.stdout&&oe({input:this.childProcess.stdout}).on(`line`,e=>this.handleLine(e)),this.childProcess.stderr&&oe({input:this.childProcess.stderr}).on(`line`,e=>{j.warn(`Codex app-server stderr`,{sessionId:this.sessionId,line:e.slice(0,500)}),this.emit(`stderr`,e)}),this.childProcess.on(`error`,e=>{j.error(`Codex app-server 进程错误`,{sessionId:this.sessionId,error:e.message}),this.emit(`error`,e),this.rejectAllPending(e)}),this.childProcess.on(`close`,(e,t)=>{this.closed=!0,j.info(`Codex app-server 进程退出`,{sessionId:this.sessionId,code:e,signal:t}),this.rejectAllPending(Error(`Codex app-server exited: code=${e}, signal=${t}`)),this.emit(`close`,e,t)})}handleLine(e){let t=e.trim();if(!t)return;let n;try{n=JSON.parse(t)}catch(e){let n=e instanceof Error?e:Error(String(e));j.warn(`Codex app-server JSONL 解析失败`,{sessionId:this.sessionId,error:n.message,line:t.slice(0,200)}),this.emit(`malformedLine`,t,n);return}if(mt(n)){this.handleResponse(n);return}if(ht(n)){this.emit(`serverRequest`,n);return}gt(n)&&this.emit(`notification`,n)}handleResponse(e){if(e.id==null){j.warn(`Codex app-server 返回无 id 错误响应`,{sessionId:this.sessionId,message:e});return}let t=String(e.id),n=this.pending.get(t);if(!n){j.warn(`Codex app-server 返回未知请求响应`,{sessionId:this.sessionId,id:e.id});return}if(clearTimeout(n.timer),this.pending.delete(t),`error`in e){n.reject(Error(`${n.method} failed: ${e.error.message}`));return}n.resolve(e.result)}writeJson(e){return new Promise((t,n)=>{let r=this.childProcess.stdin;if(!r||r.destroyed){n(Error(`Codex app-server stdin is not writable`));return}r.write(`${JSON.stringify(e)}\n`,e=>{e?n(e):t()})})}rejectAllPending(e){for(let t of this.pending.values())clearTimeout(t.timer),t.reject(e);this.pending.clear()}};function mt(e){return`id`in e&&(`result`in e||`error`in e)}function ht(e){return`id`in e&&`method`in e&&!(`result`in e)&&!(`error`in e)}function gt(e){return`method`in e&&!(`id`in e)}function _t(e,t){let n=Error(t||e);return n.userFacingMessage=e,n}function vt(e){if(!e||typeof e!=`object`)return;let t=e.userFacingMessage;return typeof t==`string`&&t.trim()?t:void 0}const M=t(`runtime/codex-app-server-adapter`),yt=d(S(),`.larkpal`,`runtime`,`codex-app-server-threads.json`),bt=12e4;function xt(e){return jt(e)}var St=class{name=`codex-app-server`;capabilities={followupInjection:!0,abort:!0,lastUserMessageId:!0,fileRewind:!0,imageInput:!1};clientFactory;statePath;processes=new Map;threadIds=new Map;threadInstructionHashes=new Map;activeCallbacks=new Map;lastRuntimeConfigs=new Map;sessionLocks=new Map;completionResolvers=new Map;busySessions=new Set;abortedSessions=new Set;itemToolNames=new Map;currentMessageIds=new Map;lastUserMessageIds=new Map;turnMessageIds=new Map;completedTurnIds=new Map;turnDiffs=new Map;turnAgentTexts=new Map;latestTokenUsage=new Map;forceCompactBeforeNextTurn=new Set;compactTurnIds=new Map;compactWaiters=new Map;stateLoaded=!1;constructor(e={}){this.statePath=e.statePath??yt,this.clientFactory=e.clientFactory??(e=>new pt({sessionId:e.sessionId,cwd:e.cwd,env:e.env,extraArgs:e.extraArgs,requestTimeoutMs:bt})),M.info(`CodexAppServerAdapter 初始化完成`,{statePath:this.statePath})}async executePrompt(e,t){await this.loadState();let{sessionId:n}=e,r=this.sessionLocks.get(n);r&&(M.info(`等待上一条 Codex 消息处理完成`,{sessionId:n}),await r);let i=this.createCompletionPromise(n);this.sessionLocks.set(n,i),this.busySessions.add(n),this.activeCallbacks.set(n,t),this.lastRuntimeConfigs.set(n,e);let a=[];try{this.logUnsupportedConfig(e),this.assertImageInputSupported(e);let t=await this.ensureProcess(e);await this.compactBeforeTurnIfNeeded(e,t);let r=await this.toCodexInput(e,a),o=this.createUserMessageId(e);this.currentMessageIds.set(n,o),this.lastUserMessageIds.set(n,o);let s=await t.client.request(`turn/start`,{threadId:t.process.threadId,clientUserMessageId:o,input:r,cwd:e.cwd,approvalPolicy:`never`,sandboxPolicy:{type:`dangerFullAccess`},model:e.model??process.env.LARKPAL_CODEX_MODEL??process.env.CODEX_MODEL??void 0});s?.turn?.id&&(t.process.currentTurnId=s.turn.id,this.rememberTurnMessageId(n,s.turn.id,o)),await i}catch(e){let r=e instanceof Error?e:Error(String(e));t.onError?.(r),this.resolveCompletion(n)}finally{if(e.transcriptMode===`ephemeral`){let e=this.processes.get(n);e&&await this.closeRecord(n,e).catch(e=>{M.warn(`ephemeral Codex app-server session 清理失败`,{sessionId:n,error:e instanceof Error?e.message:String(e)})})}this.busySessions.delete(n),this.activeCallbacks.delete(n),this.sessionLocks.delete(n),this.currentMessageIds.delete(n),await this.cleanupTempFiles(a)}}async stopProcess(e){let t=this.processes.get(e);if(!t){M.warn(`尝试停止不存在的 Codex app-server session`,{sessionId:e});return}if(this.busySessions.has(e)&&t.process.currentTurnId){this.abortedSessions.add(e),M.info(`发送 Codex turn/interrupt`,{sessionId:e,threadId:t.process.threadId,turnId:t.process.currentTurnId}),await t.client.request(`turn/interrupt`,{threadId:t.process.threadId,turnId:t.process.currentTurnId});return}await this.closeRecord(e,t)}async stopAll(){await Promise.all(Array.from(this.processes.entries()).map(([e,t])=>this.closeRecord(e,t)))}getProcessInfo(e){let t=this.processes.get(e);if(t)return this.toProcessInfo(t.process)}getAllProcessInfo(){return Array.from(this.processes.values()).map(e=>this.toProcessInfo(e.process))}isSessionBusy(e){return this.busySessions.has(e)}getCapabilities(){return this.capabilities}getLastUserMessageId(e){return this.lastUserMessageIds.get(e)}consumeAborted(e){let t=this.abortedSessions.has(e);return this.abortedSessions.delete(e),t}getLastMessageHadImages(e){let t=this.lastRuntimeConfigs.get(e);return Array.isArray(t?.prompt)&&t.prompt.some(e=>e.type===`image`)}async previewRewind(e){let t=this.findRewindRecord(e.sessionId,e.messageId);return t?{canRewind:!0,sessionId:e.sessionId,messageId:t.messageId,filesChanged:t.filesChanged,insertions:t.insertions,deletions:t.deletions}:{canRewind:!1,sessionId:e.sessionId,messageId:e.messageId??this.lastUserMessageIds.get(e.sessionId)??``,filesChanged:[],insertions:0,deletions:0,error:`没有找到可撤销的文件变更`}}async confirmRewind(e){await this.loadState();let t=e.sessionId,n=this.sessionLocks.get(t);n&&await n;let r=this.confirmRewindUnlocked(e),i=r.then(()=>void 0,()=>void 0);this.sessionLocks.set(t,i);try{return await r}finally{this.sessionLocks.get(t)===i&&this.sessionLocks.delete(t)}}async confirmRewindUnlocked(e){let t=e.sessionId,n=this.findRewindRecord(t,e.messageId);if(!n)return P(t,e.messageId??this.lastUserMessageIds.get(t)??``,`没有找到可撤销的文件变更`);let r=this.processes.get(t);if(!r?.process.threadId)return P(t,n.messageId,`Codex thread 不可用`);let i=this.completedTurnIds.get(t)??[],a=i.indexOf(n.turnId);if(a<0)return P(t,n.messageId,`无法定位需要回滚的 Codex turn`);let o=i.length-a;if(o<1)return P(t,n.messageId,`无可回滚的 Codex turn`);try{return await qt(r.process.cwd,n.diff,!0),await qt(r.process.cwd,n.diff,!1),await r.client.request(`thread/rollback`,{threadId:r.process.threadId,numTurns:o}),this.pruneRewindState(t,a),{ok:!0,sessionId:t,messageId:n.messageId,filesChanged:n.filesChanged,insertions:n.insertions,deletions:n.deletions}}catch(e){return P(t,n.messageId,e instanceof Error?e.message:String(e))}}async ensureProcess(e){let t=this.processes.get(e.sessionId);if(t&&t.process.status===`running`)return t.process.lastActiveAt=new Date,t.process.threadId||await this.ensureThread(e,t),t;let n=this.buildProcessEnv(e),r=this.buildCodexArgs(e),i=this.clientFactory({sessionId:e.sessionId,cwd:e.cwd,env:n,extraArgs:r}),a={client:i,process:{sessionId:e.sessionId,cwd:e.cwd,childProcess:i.childProcess,status:`starting`,startedAt:new Date,lastActiveAt:new Date}};return this.processes.set(e.sessionId,a),this.bindClient(e.sessionId,a),await i.request(`initialize`,{clientInfo:{name:`larkpal`,title:`LarkPal`,version:process.env.npm_package_version??`0.0.0`},capabilities:{experimentalApi:!1,requestAttestation:!1}}),a.process.status=`running`,await this.ensureThread(e,a),a}async ensureThread(e,t){let n=e.transcriptMode===`ephemeral`,r=await wt(e.cwd),i=this.threadInstructionHashes.get(e.sessionId),a=n?void 0:this.threadIds.get(e.sessionId),o=e.model??process.env.LARKPAL_CODEX_MODEL??process.env.CODEX_MODEL??void 0;if(!n&&a&&r&&i!==r&&M.info(`Codex 指令文件变化,继续复用旧 thread 并在本轮注入最新 runtime instructions`,{sessionId:e.sessionId,cwd:e.cwd,threadId:a,hadStoredInstructionsHash:!!i}),a)try{let i=await t.client.request(`thread/resume`,{threadId:a,cwd:e.cwd,model:o,approvalPolicy:`never`,sandbox:`danger-full-access`});t.process.threadId=i.thread.id,n||await this.setThreadId(e.sessionId,i.thread.id,e.cwd,r);return}catch(t){M.warn(`Codex thread/resume 失败,将新建 thread`,{sessionId:e.sessionId,threadId:a,error:t instanceof Error?t.message:String(t)})}let s=await t.client.request(`thread/start`,{cwd:e.cwd,model:o,approvalPolicy:`never`,sandbox:`danger-full-access`,sessionStartSource:`startup`,threadSource:`user`});t.process.threadId=s.thread.id,n||await this.setThreadId(e.sessionId,s.thread.id,e.cwd,r)}bindClient(e,t){t.client.on(`notification`,n=>{t.process.lastActiveAt=new Date,this.handleNotification(e,n)}),t.client.on(`serverRequest`,e=>{this.handleServerRequest(t.client,e)}),t.client.on(`error`,n=>{t.process.status=`crashed`,this.activeCallbacks.get(e)?.onError?.(n),this.resolveCompletion(e)}),t.client.on(`close`,()=>{t.process.status!==`stopping`&&t.process.status!==`stopped`&&(t.process.status=`crashed`),this.resolveCompletion(e),this.processes.delete(e)})}handleNotification(e,t){switch(t.method){case`turn/started`:this.handleTurnStarted(e,t.params);break;case`item/agentMessage/delta`:this.handleAgentMessageDelta(e,t.params);break;case`item/reasoning/summaryTextDelta`:case`item/reasoning/textDelta`:this.activeCallbacks.get(e)?.onThinkingDelta?.(t.params.delta??``);break;case`item/started`:this.handleItemStarted(e,t.params);break;case`item/completed`:this.handleItemCompleted(e,t.params);break;case`item/mcpToolCall/progress`:this.handleMcpProgress(e,t.params);break;case`turn/completed`:this.handleTurnCompleted(e,t.params);break;case`turn/diff/updated`:this.handleTurnDiffUpdated(e,t.params);break;case`error`:this.handleErrorNotification(e,t.params);break;case`thread/status/changed`:this.handleThreadStatusChanged(e,t.params);break;case`thread/compacted`:this.handleThreadCompacted(e,t.params);break;case`thread/tokenUsage/updated`:this.handleThreadTokenUsageUpdated(e,t.params);break;default:M.debug(`忽略 Codex app-server notification`,{sessionId:e,method:t.method});break}}handleTurnStarted(e,t){let n=this.processes.get(e);n&&(n.process.currentTurnId=t.turn.id);let r=this.currentMessageIds.get(e);r&&this.rememberTurnMessageId(e,t.turn.id,r)}handleItemStarted(e,t){let n=this.activeCallbacks.get(e);if(!n)return;let{toolName:r,toolInput:i}=this.describeToolItem(t.item);r&&(this.rememberToolName(e,t.item.id,r),n.onToolUseStart?.(r,i))}handleItemCompleted(e,t){if(t.item.type===`contextCompaction`){this.rememberCompactTurn(e,t.turnId),this.emitRuntimeEvent(e,{type:`codex-context-compaction-item`,timestamp:new Date().toISOString(),sessionId:e,data:{threadId:t.threadId,turnId:t.turnId,itemId:t.item.id}}),this.resolveCompactWaiter(e);return}t.item.type===`agentMessage`&&typeof t.item.text==`string`&&t.item.text.trim()!==``&&this.rememberTurnAgentText(e,t.turnId,t.item.text);let n=this.activeCallbacks.get(e);n&&(this.lookupToolName(e,t.item.id)??this.describeToolItem(t.item).toolName)&&n.onToolResult?.(t.item.id,this.summarizeToolResult(t.item))}handleAgentMessageDelta(e,t){let n=t.delta??``;n&&this.appendTurnAgentText(e,t.turnId,n),this.activeCallbacks.get(e)?.onTextDelta?.(n)}handleMcpProgress(e,t){let n=this.lookupToolName(e,t.itemId)??`mcp`;this.activeCallbacks.get(e)?.onToolProgress?.(n,0),M.debug(`Codex MCP tool progress`,{sessionId:e,itemId:t.itemId,message:t.message})}handleTurnCompleted(e,t){let n=this.activeCallbacks.get(e),r=this.processes.get(e);if(r&&(r.process.currentTurnId=void 0),this.isCompactTurn(e,t.turn.id)){M.info(`Codex compact turn completed`,{sessionId:e,threadId:t.threadId,turnId:t.turn.id,status:t.turn.status}),this.resolveCompactWaiter(e),this.forgetCompactTurn(e,t.turn.id);return}let i=this.abortedSessions.delete(e)||t.turn.status===`interrupted`,a=t.turn.status===`failed`&&!i,o=this.extractFinalText(e,t.turn),s=t.turn.error?.message??t.turn.error?.additionalDetails??void 0;n?.onTurnEnd?.(`end_turn`),n?.onResult?.({subtype:a?`error_during_execution`:`success`,result:a?s??o:o,durationMs:t.turn.durationMs??void 0,isError:a,aborted:i}),t.turn.status===`completed`&&this.rememberCompletedTurn(e,t.turn.id),this.turnAgentTexts.get(e)?.delete(t.turn.id),this.resolveCompletion(e)}handleTurnDiffUpdated(e,t){if(!t.diff.trim())return;let n=this.lookupTurnMessageId(e,t.turnId)??this.currentMessageIds.get(e);if(!n)return;let r=this.turnDiffs.get(e);r||(r=new Map,this.turnDiffs.set(e,r));let i=Kt(t.diff);r.set(t.turnId,{messageId:n,turnId:t.turnId,diff:t.diff,filesChanged:i.filesChanged,insertions:i.insertions,deletions:i.deletions})}handleErrorNotification(e,t){let n=Ft(t)??`Codex app-server error`;if(It(t)){M.warn(`Codex app-server retryable error notification`,{sessionId:e,message:n,params:Wt(t)});return}M.warn(`Codex app-server error notification`,{sessionId:e,message:n,params:Wt(t)}),this.activeCallbacks.get(e)?.onError?.(Mt(n)),Nt(n)?this.resetSessionAfterFatalError(e,`image_capability_error`):Lt(t,n)&&this.restartSessionAndCompactNextTurn(e,`fatal_stream_disconnect`),this.resolveCompletion(e)}handleThreadStatusChanged(e,t){M.info(`Codex thread status changed`,{sessionId:e,params:Wt(t)})}handleThreadCompacted(e,t){M.info(`Codex thread compacted`,{sessionId:e,threadId:t.threadId,turnId:t.turnId}),this.rememberCompactTurn(e,t.turnId),this.emitRuntimeEvent(e,{type:`codex-context-compacted`,timestamp:new Date().toISOString(),sessionId:e,data:{threadId:t.threadId,turnId:t.turnId}}),this.resolveCompactWaiter(e)}handleThreadTokenUsageUpdated(e,t){this.latestTokenUsage.set(e,t.tokenUsage),M.info(`Codex thread token usage updated`,{sessionId:e,threadId:t.threadId,turnId:t.turnId,totalTokens:t.tokenUsage.total.totalTokens,modelContextWindow:t.tokenUsage.modelContextWindow}),this.emitRuntimeEvent(e,{type:`codex-token-usage-updated`,timestamp:new Date().toISOString(),sessionId:e,data:{threadId:t.threadId,turnId:t.turnId,tokenUsage:t.tokenUsage}})}emitRuntimeEvent(e,t){let n=this.activeCallbacks.get(e);n?.onRuntimeEvent?.(t),n?.onScenarioEvent&&n.onScenarioEvent!==n.onRuntimeEvent&&n.onScenarioEvent(t)}async handleServerRequest(e,t){switch(M.warn(`Codex app-server server request 默认拒绝`,{method:t.method,id:t.id}),t.method){case`item/commandExecution/requestApproval`:await e.respond(t.id,{decision:`decline`});break;case`item/fileChange/requestApproval`:await e.respond(t.id,{decision:`decline`});break;case`item/permissions/requestApproval`:await e.respond(t.id,{permissions:{},scope:`turn`});break;default:await e.respondError(t.id,-32601,`LarkPal does not handle Codex server request: ${t.method}`);break}}describeToolItem(e){switch(e.type){case`commandExecution`:return{toolName:`Bash`,toolInput:{command:e.command,cwd:e.cwd}};case`fileChange`:return{toolName:`apply_patch`,toolInput:{changes:e.changes}};case`mcpToolCall`:return{toolName:`mcp__${typeof e.server==`string`?e.server:`mcp`}__${typeof e.tool==`string`?e.tool:`tool`}`,toolInput:e.arguments};case`dynamicToolCall`:return{toolName:`${typeof e.namespace==`string`&&e.namespace?`${e.namespace}__`:``}${typeof e.tool==`string`?e.tool:`dynamic_tool`}`,toolInput:e.arguments};case`webSearch`:return{toolName:`WebSearch`,toolInput:{query:e.query}};default:return{}}}summarizeToolResult(e){switch(e.type){case`commandExecution`:{let t=typeof e.exitCode==`number`?e.exitCode:void 0,n=typeof e.status==`string`?e.status:void 0,r=typeof e.aggregatedOutput==`string`?e.aggregatedOutput:e.aggregatedOutput??void 0;return{ok:n===`completed`&&(t==null||t===0),exitCode:t,isError:n===`failed`||typeof t==`number`&&t!==0,outputSummary:r}}case`mcpToolCall`:return{ok:e.status===`completed`&&!e.error,isError:e.status===`failed`||!!e.error,resultSummary:e.result,outputSummary:e.error??e.result};case`fileChange`:return{ok:e.status===`completed`,isError:e.status===`failed`||e.status===`declined`,outputSummary:e.changes};case`dynamicToolCall`:{let t=typeof e.success==`boolean`?e.success:void 0;return{ok:t??e.status===`completed`,isError:e.status===`failed`||t===!1,outputSummary:e.contentItems}}default:return{}}}extractFinalText(e,t){return[...Array.isArray(t.items)?t.items:[]].reverse().find(e=>e.type===`agentMessage`&&typeof e.text==`string`&&e.text.trim()!==``)?.text??this.turnAgentTexts.get(e)?.get(t.id)}rememberToolName(e,t,n){let r=this.itemToolNames.get(e);r||(r=new Map,this.itemToolNames.set(e,r)),r.set(t,n)}rememberTurnAgentText(e,t,n){let r=this.turnAgentTexts.get(e);r||(r=new Map,this.turnAgentTexts.set(e,r)),r.set(t,n)}appendTurnAgentText(e,t,n){let r=this.turnAgentTexts.get(e);r||(r=new Map,this.turnAgentTexts.set(e,r)),r.set(t,`${r.get(t)??``}${n}`)}createUserMessageId(e){return e.requestId?`${e.requestId}:user`:`codex-user-${C()}`}rememberTurnMessageId(e,t,n){let r=this.turnMessageIds.get(e);r||(r=new Map,this.turnMessageIds.set(e,r)),r.set(t,n)}lookupTurnMessageId(e,t){return this.turnMessageIds.get(e)?.get(t)}rememberCompletedTurn(e,t){let n=this.completedTurnIds.get(e)??[];n.includes(t)||(n.push(t),this.completedTurnIds.set(e,n))}findRewindRecord(e,t){let n=this.turnDiffs.get(e);if(!n)return;let r=this.completedTurnIds.get(e)??[];for(let e=r.length-1;e>=0;--e){let i=n.get(r[e]);if(i&&(!t||i.messageId===t))return i}}pruneRewindState(e,t){let n=this.completedTurnIds.get(e)??[],r=n.slice(t);this.completedTurnIds.set(e,n.slice(0,t));let i=this.turnDiffs.get(e),a=this.turnMessageIds.get(e);for(let e of r)i?.delete(e),a?.delete(e);let o=this.completedTurnIds.get(e)?.at(-1),s=o?this.lookupTurnMessageId(e,o):void 0;s&&this.lastUserMessageIds.set(e,s)}lookupToolName(e,t){return this.itemToolNames.get(e)?.get(t)}async toCodexInput(e,t){let n=[],r=await this.buildRuntimeInstructionsInput(e.cwd);r&&n.push({type:`text`,text:r,text_elements:[]});let{prompt:i}=e;if(typeof i==`string`)return n.push({type:`text`,text:i,text_elements:[]}),n;for(let e of i)if(e.type===`text`)n.push({type:`text`,text:e.text,text_elements:[]});else if(e.type===`image`){let r=await this.writeTempImage(e,t);n.push({type:`localImage`,path:r})}return n}assertImageInputSupported(e){if(!xt(e.prompt)||this.supportsImageInput(e))return;let t=e.model??process.env.LARKPAL_CODEX_MODEL??process.env.CODEX_MODEL??`当前配置`;throw Error(`当前 Codex 模型 ${t} 不支持图片输入。请改用支持视觉输入的模型,或直接用文字描述图片内容。`)}supportsImageInput(e){if(process.env.LARKPAL_CODEX_IMAGE_INPUT===`1`||process.env.LARKPAL_CODEX_IMAGE_INPUT===`true`)return!0;let t=(e.model??process.env.LARKPAL_CODEX_MODEL??process.env.CODEX_MODEL??``).toLowerCase();return!t||t.includes(`codex`)?!1:/\b(?:vision|multimodal|gpt-4o|gpt-4\.1|gpt-5(?:\.\d+)?)(?:\b|[-_])/.test(t)}async buildRuntimeInstructionsInput(e){let t=await Ct(e);if(t.length===0)return;let n=t.map(e=>`# ${e.path}\n\n${e.content.trim()}`).join(`
|
|
5
|
+
`:``),`utf-8`),await y(c,e),qe.info(`Claude transcript 图片结果已清理`,{filePath:e,...t}),t}function Xe(){let e=process.env.LARKPAL_TRANSCRIPT_SANITIZER;return e!==`0`&&e!==`false`}async function Ze(e,t){let n=0,r=0,i=A(e.message),a=i?i.content:void 0,o=A(e.toolUseResult),s;if(Array.isArray(a))for(let e=0;e<a.length;e++){let i=A(a[e]);if(i){if(i.type===`tool_result`){let e=typeof i.tool_use_id==`string`?i.tool_use_id:void 0,a=await $e(i.content,t,e);if(!a)continue;i.content=a.content,n+=a.imageBlocks,r+=a.artifacts,s??=a.metadata[0]?.artifactUri;continue}if(nt(i)){let o=await et(t,i,void 0,e);a[e]={type:`text`,text:tt([o])},n++,r++,s??=o.artifactUri}}}let c=await Qe(o,t,s);return c&&(n+=c.sanitizedImageBlocks,r+=c.artifacts),{sanitizedImageBlocks:n,artifacts:r}}async function Qe(e,t,n){if(e?.type!==`image`)return null;let r=A(e.file);if(!r||typeof r.base64!=`string`)return null;let i=n,a=0;return i||(i=(await et(t,{type:`image`,source:{type:`base64`,media_type:typeof r.type==`string`?r.type:void 0,data:r.base64},filePath:typeof r.filePath==`string`?r.filePath:void 0},void 0,0)).artifactUri,a=1),r.artifactUri=i,r.base64=`[redacted by LarkPal: image artifact externalized]`,{sanitizedImageBlocks:1,artifacts:a}}async function $e(e,t,n){if(!Array.isArray(e))return null;let r=[],i=0,a=0;for(let o=0;o<e.length;o++){let s=A(e[o]);if(!nt(s))continue;i++;let c=await et(t,s,n,o);r.push(c),a++}return i===0?null:{content:tt(r),imageBlocks:i,artifacts:a,metadata:r}}async function et(e,t,n,r){let i=A(t.source),a=typeof i?.data==`string`?i.data:``,o=typeof i?.media_type==`string`?i.media_type:void 0,s=`${n??w()}-${r}`,c=f(e,`${s}.json`),l=`artifact://claude-transcript/${s}`,u=rt(t);return await g(e,{recursive:!0}),await S(c,JSON.stringify({artifactUri:l,originalToolName:`Read`,toolUseId:n,mimeType:o,dimensions:u,originalSize:a.length,sourcePath:typeof t.filePath==`string`?t.filePath:void 0,base64:a},null,2),{encoding:`utf-8`,flag:`w`}),{artifactUri:l,originalToolName:`Read`,toolUseId:n,mimeType:o,dimensions:u,originalSize:a.length,sourcePath:typeof t.filePath==`string`?t.filePath:void 0,summary:`Rendered image/PDF page preview externalized by LarkPal transcript sanitizer.`}}function tt(e){return JSON.stringify({larkpalSanitized:!0,reason:`Previous image tool result was externalized to avoid replaying base64 image payloads into provider requests.`,artifacts:e})}function nt(e){if(!e||e.type!==`image`)return!1;let t=A(e.source);return t?.type===`base64`&&typeof t.data==`string`}function rt(e){let t=A(e.dimensions);if(!t)return;let n=t.displayWidth??t.originalWidth,r=t.displayHeight??t.originalHeight;if(!(typeof n!=`number`||typeof r!=`number`))return`${n}x${r}`}function it(e){return e.includes(`"base64"`)&&(e.includes(`"image"`)||e.includes(`"source"`))}function A(e){return typeof e==`object`&&e?e:void 0}function at(e,t){let n=process.env[e];if(!n)return t;let r=Number.parseInt(n,10);return Number.isFinite(r)&&r>0?r:t}const j=t(`cc-runtime/process-manager`),ot=(()=>{let e=process.env.LARKPAL_CC_IDLE_TIMEOUT;if(e===void 0||e===``)return 0;let t=parseInt(e,10);return isNaN(t)||t<0?0:t*1e3})(),st=process.env.LARKPAL_CC_EFFORT||`medium`;var ct=class{processes=new Map;idleTimers=new Map;sessionCwdCache=new Map;activeCallbacks=new Map;lastUserMessageIds=new Map;lastMessageHadImages=new Map;lastMultimodalSummaries=new Map;pendingControlRequests=new Map;abortedSessions=new Set;messageCompletionResolvers=new Map;sessionLocks=new Map;markAborted(e){this.abortedSessions.add(e)}consumeAborted(e){return this.abortedSessions.has(e)?(this.abortedSessions.delete(e),!0):!1}getLastMessageHadImages(e){return this.lastMessageHadImages.get(e)===!0}createMessageCompletionPromise(e){return new Promise(t=>{this.messageCompletionResolvers.set(e,t)})}resolveMessageCompletion(e){let t=this.messageCompletionResolvers.get(e);t&&(this.messageCompletionResolvers.delete(e),t())}async executePrompt(e,t){let{sessionId:n}=e,r=Date.now(),i=this.sessionLocks.get(n);i&&(j.info(`等待上一条消息处理完成`,{sessionId:n}),await i,j.info(`[perf] 串行锁等待完成`,{sessionId:n,waitMs:Date.now()-r}));let a=()=>{},o=new Promise(e=>{a=e});this.sessionLocks.set(n,o),this.activeCallbacks.set(n,t);try{let t=this.processes.get(n);if(t&&t.status===`running`&&t.useStreamInput){j.info(`向常驻进程发送消息`,{sessionId:n,promptLength:e.prompt.length,pid:t.childProcess.pid,prepareMs:Date.now()-r});let i=this.createMessageCompletionPromise(n);this.sendMessage(n,e.prompt),this.resetIdleTimer(n),await i,j.info(`[perf] executePrompt 完成(热进程)`,{sessionId:n,totalMs:Date.now()-r});return}t&&(t.status===`stopped`||t.status===`crashed`)&&(j.info(`清理已终止的旧进程,准备重启`,{sessionId:n,oldStatus:t.status}),this.cleanup(n),this.sessionLocks.set(n,o)),t&&t.status===`running`&&!t.useStreamInput&&(j.warn(`停止旧的单次进程后重新启动为常驻模式`,{sessionId:n}),await this.stopProcess(n),this.sessionLocks.set(n,o));let i=this.createMessageCompletionPromise(n),a=Date.now();await this.startPersistentProcess(e),j.info(`[perf] 冷启动进程完成`,{sessionId:n,coldStartMs:Date.now()-a}),await i,j.info(`[perf] executePrompt 完成(冷启动)`,{sessionId:n,totalMs:Date.now()-r})}finally{e.transcriptMode===`ephemeral`&&await this.stopProcess(n).catch(e=>{j.warn(`ephemeral CC 进程清理失败`,{sessionId:n,error:e instanceof Error?e.message:String(e)})}),this.sessionLocks.get(n)===o&&this.sessionLocks.delete(n),a()}}async startPersistentProcess(e,t){let{sessionId:n,cwd:r,prompt:a}=e,o=e.transcriptMode===`ephemeral`,s=o?T():se(n,`7c9e6679-7425-40de-944b-e07fc1f90ae7`),c=this.getCCSessionFilePath(r,s),l=i(c),u=!o&&(t?._forceResume||l);u&&l&&Xe()&&await Ye(c).catch(e=>{j.warn(`Claude transcript sanitizer 失败,继续启动进程`,{sessionId:n,transcriptPath:c,error:e instanceof Error?e.message:String(e)})});let d=[`-p`,`--input-format`,`stream-json`,`--output-format`,`stream-json`,`--verbose`,`--include-partial-messages`];u?d.push(`--resume`,s):d.push(`--session-id`,s),d.push(`--permission-mode`,`bypassPermissions`),e.maxTurns&&d.push(`--max-turns`,String(e.maxTurns)),e.maxBudgetUsd&&d.push(`--max-budget-usd`,String(e.maxBudgetUsd)),e.model&&d.push(`--model`,e.model),d.push(`--effort`,st);try{let t=await ke(e.userContext&&!e.userContext.isTenantIdentity?e.userContext:null,n,r,e.policy);d.push(`--mcp-config`,t),j.info(`MCP 配置已合并并注入到 CC 进程`,{sessionId:n,userId:e.userContext?.userId,mcpConfigPath:t})}catch(e){j.warn(`MCP 配置合并失败,CC 进程将使用全局默认配置`,{sessionId:n,error:e instanceof Error?e.message:String(e)})}let f={...process.env};if(f.CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING=`1`,f.LARKPAL_MCP_SESSION_ID=n,f.LARKPAL_MCP_CWD=r,e.userContext){let{userContext:t}=e;f.LARKPAL_USER_ID=t.userId,f.LARKPAL_USER_OPEN_ID=t.openId,f.LARKPAL_USER_NAME=t.userName,f.LARKPAL_CREDENTIAL_DIR=t.credentialDir,f.LARKPAL_IS_TENANT=t.isTenantIdentity?`1`:`0`;let r=process.env.LARKPAL_DISABLE_USER_AUTH===`1`||process.env.LARKPAL_DISABLE_USER_AUTH===`true`;if(!t.isTenantIdentity)try{let e=new Se(t.credentialDir);await e.load();let i=await e.getAllCredentialsAsEnv();if(Object.assign(f,i),r)delete f.LARK_USER_ACCESS_TOKEN,j.info(`LARKPAL_DISABLE_USER_AUTH 已启用,跳过飞书 user_access_token 注入`,{sessionId:n,userId:t.userId});else{let t=await e.getCredential(`lark`);t?.user_access_token&&typeof t.user_access_token==`string`&&(f.LARK_USER_ACCESS_TOKEN=t.user_access_token)}j.info(`用户凭证已注入到 CC 进程环境`,{sessionId:n,userId:t.userId,credentialCount:Object.keys(i).length,hasLarkUserToken:!!f.LARK_USER_ACCESS_TOKEN,disableUserAuth:r})}catch(e){j.warn(`用户凭证加载失败,CC 进程将使用默认环境`,{sessionId:n,userId:t.userId,error:e instanceof Error?e.message:String(e)})}}j.info(`启动常驻 CC 进程`,{sessionId:n,claudeSessionId:s,isResuming:u,cwd:r,args:d.join(` `)});let p=ie(`claude`,d,{cwd:r,stdio:[`pipe`,`pipe`,`pipe`],env:f}),m={sessionId:n,cwd:r,childProcess:p,status:`starting`,startedAt:new Date,lastActiveAt:new Date,useStreamInput:!0};this.processes.set(n,m),this.sessionCwdCache.set(n,r);let h=new Be;this.bindParserToCallbackProxy(h,n);let g=!1;return p.stdout&&oe({input:p.stdout}).on(`line`,e=>{if(m.lastActiveAt=new Date,this.resetIdleTimer(n),e.includes(`"control_response"`))try{let t=JSON.parse(e);if(t.type===`control_response`&&t.response?.request_id){let e=this.pendingControlRequests.get(t.response.request_id);if(e){clearTimeout(e.timer),this.pendingControlRequests.delete(t.response.request_id),j.info(`收到 control_response`,{sessionId:n,requestId:t.response.request_id,subtype:t.response.subtype,responseKeys:Object.keys(t.response),fullResponse:JSON.stringify(t.response).slice(0,500)}),e.resolve(t.response);return}}}catch{}h.parseLine(e)}),p.stderr&&oe({input:p.stderr}).on(`line`,e=>{e.includes(`no stdin data received`)||(e.toLowerCase().includes(`already in use`)&&(g=!0),j.warn(`CC 进程 stderr`,{sessionId:n,line:e.slice(0,500)}))}),p.on(`close`,async(r,i)=>{let a=r??-1,o=i??`none`;if(a===1&&g&&!u){j.info(`Session ID 已被占用,准备使用 --resume 模式重试`,{sessionId:n,claudeSessionId:s}),this.processes.delete(n),this.sessionCwdCache.delete(n);try{await this.startPersistentProcess(e,{skipInitialMessage:t?.skipInitialMessage,_forceResume:!0});return}catch(e){j.error(`Session ID 重试失败`,{sessionId:n,error:e instanceof Error?e.message:String(e)})}}a===0?(j.info(`CC 常驻进程正常退出`,{sessionId:n,exitCode:a,signal:o}),m.status=`stopped`):(j.error(`CC 常驻进程异常退出`,{sessionId:n,exitCode:a,signal:o}),m.status=`crashed`,this.activeCallbacks.get(n)?.onError?.(Error(`CC 常驻进程异常退出: code=${a}, signal=${o}`))),this.resolveMessageCompletion(n),this.cleanup(n)}),p.on(`error`,e=>{j.error(`CC 常驻进程启动失败`,{sessionId:n,error:e.message}),m.status=`crashed`,this.activeCallbacks.get(n)?.onError?.(e),this.resolveMessageCompletion(n),this.cleanup(n)}),m.status=`running`,j.info(`CC 常驻进程已启动`,{sessionId:n,pid:p.pid,isResuming:u}),t?.skipInitialMessage||this.sendMessage(n,a),this.resetIdleTimer(n),m}bindParserToCallbackProxy(e,t){let n=()=>this.activeCallbacks.get(t),r=!1,i=Date.now(),a=this.processes.get(t);a&&(a._resetPerfTimer=()=>{r=!1,i=Date.now()}),e.on(`textDelta`,e=>{r||(r=!0,j.info(`[perf] 首 token (text)`,{sessionId:t,ttftMs:Date.now()-i})),n()?.onTextDelta?.(e)}),e.on(`thinkingDelta`,e=>{r||(r=!0,j.info(`[perf] 首 token (thinking)`,{sessionId:t,ttftMs:Date.now()-i})),n()?.onThinkingDelta?.(e)}),e.on(`toolUseStart`,(e,t,r)=>{n()?.onToolUseStart?.(e,t,r)}),e.on(`toolResult`,(e,t)=>{n()?.onToolResult?.(e,t)}),e.on(`unknownToolUse`,(e,r)=>{let i=n();i?.onUnknownToolUse?.(e,r),this.lastMessageHadImages.get(t)===!0&&Ne(e)&&i?.onRuntimeEvent?.(Pe({sessionId:t,toolName:e,toolUseId:r,summary:this.lastMultimodalSummaries.get(t)}))}),e.on(`toolProgress`,(e,t)=>{n()?.onToolProgress?.(e,t)}),e.on(`turnEnd`,e=>{j.info(`[perf] turnEnd`,{sessionId:t,stopReason:e,sinceMessageMs:Date.now()-i}),n()?.onTurnEnd?.(e)}),e.on(`result`,e=>{j.info(`[perf] result 事件`,{sessionId:t,sinceMessageMs:Date.now()-i}),n()?.onResult?.(e),this.resolveMessageCompletion(t)}),e.on(`parseError`,(e,n)=>{j.warn(`流解析错误`,{sessionId:t,error:e.message,rawLine:n.slice(0,200)})})}sendMessage(e,t){let n=this.processes.get(e);if(!n||!n.childProcess.stdin){j.error(`无法发送消息:进程不存在或 stdin 不可用`,{sessionId:e});return}n._resetPerfTimer?.();let r=T();this.lastUserMessageIds.set(e,r);let i=JSON.stringify({type:`user`,message:{role:`user`,content:t},parent_tool_use_id:null,uuid:r}),a=t.length,o=je(t),s=o.imageBlockCount>0;if(this.lastMessageHadImages.set(e,s),Array.isArray(t)){this.lastMultimodalSummaries.set(e,o);let t=Me(e,o);t&&this.activeCallbacks.get(e)?.onRuntimeEvent?.(t)}else this.lastMultimodalSummaries.delete(e);j.info(`通过 stdin 发送用户消息`,{sessionId:e,messageLength:a,isMultimodal:Array.isArray(t),hasImages:s,imageBlockCount:o.imageBlockCount,documentBlockCount:o.documentBlockCount,mediaBytes:o.mediaBytes,mediaTypes:o.mediaTypes,userMessageId:r,pid:n.childProcess.pid}),n.childProcess.stdin.write(i+`
|
|
6
|
+
`,t=>{t&&(j.error(`stdin 写入失败`,{sessionId:e,error:t.message}),this.activeCallbacks.get(e)?.onError?.(Error(`stdin 写入失败: ${t.message}`)))})}async sendControlRequest(e,t,n){let r=this.processes.get(e);if(!r||r.status!==`running`)throw Error(`会话 ${e} 无运行中的进程`);if(!r.childProcess.stdin||r.childProcess.stdin.destroyed)throw Error(`会话 ${e} 的 stdin 不可用`);let i=T(),a=3e4,o={subtype:t};t===`rewind_files`&&(o.user_message_id=n?.user_message_id??this.lastUserMessageIds.get(e)??``,o.dry_run=n?.dry_run??!1);let s=JSON.stringify({type:`control_request`,request_id:i,request:o});return j.info(`发送控制请求`,{sessionId:e,subtype:t,requestId:i,payload:n}),new Promise((n,o)=>{let c=setTimeout(()=>{this.pendingControlRequests.delete(i),o(Error(`控制请求超时 (${a}ms): ${t}`))},a);this.pendingControlRequests.set(i,{sessionId:e,resolve:n,reject:o,timer:c}),r.childProcess.stdin.write(s+`
|
|
7
|
+
`,e=>{e&&(clearTimeout(c),this.pendingControlRequests.delete(i),o(Error(`控制请求 stdin 写入失败: ${e.message}`)))})})}getLastUserMessageId(e){return this.lastUserMessageIds.get(e)}getProcess(e){return this.processes.get(e)}getSessionCwd(e){return this.sessionCwdCache.get(e)}isSessionBusy(e){return this.messageCompletionResolvers.has(e)||this.sessionLocks.has(e)}async ensureProcessForRewind(e){let t=this.processes.get(e);if(t&&t.status===`running`)return j.info(`ensureProcessForRewind: 进程已在运行中,直接使用`,{sessionId:e}),t;let n=this.sessionCwdCache.get(e);if(!n){j.warn(`ensureProcessForRewind: 无法获取会话 cwd`,{sessionId:e});return}t&&this.cleanup(e),j.info(`ensureProcessForRewind: 启动临时进程用于 rewind`,{sessionId:e,cwd:n}),await this.startPersistentProcess({sessionId:e,cwd:n,prompt:``},{skipInitialMessage:!0});let r=this.processes.get(e);if(!r||r.status!==`running`){j.warn(`ensureProcessForRewind: 进程启动失败`,{sessionId:e,status:r?.status});return}return await new Promise(e=>setTimeout(e,3e3)),r}getAllProcesses(){return Array.from(this.processes.values())}async stopProcess(e){let t=this.processes.get(e);if(!t){j.warn(`尝试停止不存在的进程`,{sessionId:e});return}if(t.status===`stopped`||t.status===`crashed`){j.info(`进程已经停止,直接清理`,{sessionId:e,status:t.status}),this.cleanup(e);return}if(t.status=`stopping`,j.info(`正在停止 CC 常驻进程`,{sessionId:e,pid:t.childProcess.pid}),t.childProcess.stdin&&!t.childProcess.stdin.destroyed){let e=JSON.stringify({type:`control_request`,request_id:T(),request:{subtype:`end_session`}});t.childProcess.stdin.write(e+`
|
|
8
|
+
`,()=>{})}return new Promise(n=>{let r=t.childProcess,i=setTimeout(()=>{r.killed||(j.warn(`CC 常驻进程未在规定时间内退出,强制终止`,{sessionId:e}),r.kill(`SIGKILL`))},5e3);r.once(`close`,()=>{clearTimeout(i),this.cleanup(e),n()}),setTimeout(()=>{t.status===`stopping`&&!r.killed&&r.kill(`SIGTERM`)},1e3)})}async stopAll(){let e=Array.from(this.processes.keys());e.length!==0&&(j.info(`正在停止所有 CC 常驻进程`,{count:e.length}),await Promise.all(e.map(e=>this.stopProcess(e))),j.info(`所有 CC 常驻进程已停止`))}resetIdleTimer(e){let t=this.idleTimers.get(e);if(t&&clearTimeout(t),ot<=0)return;let n=setTimeout(()=>{j.info(`CC 常驻进程空闲超时,自动停止`,{sessionId:e,timeoutMs:ot}),this.stopProcess(e)},ot);this.idleTimers.set(e,n)}cleanup(e){this.resolveMessageCompletion(e),this.sessionLocks.delete(e),this.processes.delete(e),this.activeCallbacks.delete(e),this.lastUserMessageIds.delete(e),this.lastMessageHadImages.delete(e);for(let[t,n]of this.pendingControlRequests)n.sessionId===e&&(clearTimeout(n.timer),this.pendingControlRequests.delete(t),n.reject(Error(`进程已退出`)));let t=this.idleTimers.get(e);t&&(clearTimeout(t),this.idleTimers.delete(e)),Ae(e),j.debug(`已清理常驻进程状态`,{sessionId:e})}encodeCwdForCC(e){let t=e.replace(/[^a-zA-Z0-9]/g,`-`);if(t.length<=200)return t;let n=0;for(let t=0;t<e.length;t++)n=(n<<5)-n+e.charCodeAt(t)|0;return`${t.slice(0,200)}-${Math.abs(n).toString(36)}`}ccSessionExists(e,t){try{let n=this.getCCSessionFilePath(e,t),r=i(n);return j.debug(`检查 CC session 文件`,{cwd:e,claudeSessionId:t,sessionFile:n,exists:r}),r}catch(e){return j.warn(`检查 CC session 文件失败,默认为首次创建`,{error:e instanceof Error?e.message:String(e)}),!1}}getCCSessionFilePath(e,t){let n=this.encodeCwdForCC(e);return f(C(),`.claude`,`projects`,n,`${t}.jsonl`)}};const lt=t(`runtime/claude-code-adapter`);var ut=class e{name=`claude-code`;capabilities={followupInjection:!0,abort:!0,lastUserMessageId:!0,fileRewind:!0,imageInput:!0};processManager;lastRuntimeConfigs=new Map;static _instance=null;static getInstance(){return e._instance}constructor(){this.processManager=new ct,e._instance=this,lt.info(`ClaudeCodeAdapter 初始化完成`)}getProcessManager(){return this.processManager}async executePrompt(e,t){this.lastRuntimeConfigs.set(e.sessionId,e),lt.info(`executePrompt via ClaudeCodeAdapter`,{sessionId:e.sessionId,cwd:e.cwd,promptLength:e.prompt.length,model:e.model}),await this.processManager.executePrompt(e,t)}async stopProcess(e){lt.info(`stopProcess via ClaudeCodeAdapter`,{sessionId:e});let t=this.processManager.getProcess(e);if(t?.status===`running`){if(!t.childProcess.kill(`SIGINT`))throw Error(`停止失败:进程可能已退出`);this.processManager.markAborted(e);return}await this.processManager.stopProcess(e)}async stopAll(){lt.info(`stopAll via ClaudeCodeAdapter`),await this.processManager.stopAll()}getProcessInfo(e){let t=this.processManager.getProcess(e);if(!t)return;let n=this.lastRuntimeConfigs.get(e);return{sessionId:t.sessionId,cwd:t.cwd,status:t.status,startedAt:t.startedAt,lastActiveAt:t.lastActiveAt,runContext:n?.runContext,requestContext:n?.requestContext,authHeaders:n?.authHeaders}}getAllProcessInfo(){return this.processManager.getAllProcesses().map(e=>({sessionId:e.sessionId,cwd:e.cwd,status:e.status,startedAt:e.startedAt,lastActiveAt:e.lastActiveAt,runContext:this.lastRuntimeConfigs.get(e.sessionId)?.runContext,requestContext:this.lastRuntimeConfigs.get(e.sessionId)?.requestContext,authHeaders:this.lastRuntimeConfigs.get(e.sessionId)?.authHeaders}))}isSessionBusy(e){return this.processManager.isSessionBusy(e)}getCapabilities(){return this.capabilities}getLastUserMessageId(e){return this.processManager.getLastUserMessageId(e)}async previewRewind(e){let t=e.messageId??this.processManager.getLastUserMessageId(e.sessionId);if(!t)return dt(e.sessionId,``,`无法确定可撤销的消息`);if(!await this.processManager.ensureProcessForRewind(e.sessionId))return dt(e.sessionId,t,`会话进程不可用`);let n=await this.processManager.sendControlRequest(e.sessionId,`rewind_files`,{user_message_id:t,dry_run:!0});if(n.subtype!==`error`&&!n.response?.canRewind&&(await new Promise(e=>setTimeout(e,2e3)),n=await this.processManager.sendControlRequest(e.sessionId,`rewind_files`,{user_message_id:t,dry_run:!0})),n.subtype===`error`)return dt(e.sessionId,t,n.error??`撤销预览失败`);let r=n.response;return r?.canRewind?{canRewind:!0,sessionId:e.sessionId,messageId:t,filesChanged:r.filesChanged,insertions:r.insertions,deletions:r.deletions}:dt(e.sessionId,t)}async confirmRewind(e){let t=e.messageId??this.processManager.getLastUserMessageId(e.sessionId);if(!t)return ft(e.sessionId,``,`无法确定可撤销的消息`);if(!await this.processManager.ensureProcessForRewind(e.sessionId))return ft(e.sessionId,t,`会话进程不可用`);let n=await this.processManager.sendControlRequest(e.sessionId,`rewind_files`,{user_message_id:t,dry_run:!1});if(n.subtype===`error`)return ft(e.sessionId,t,n.error??`撤销失败`);let r=n.response;return{ok:!0,sessionId:e.sessionId,messageId:t,filesChanged:r?.filesChanged??[],insertions:r?.insertions??0,deletions:r?.deletions??0}}consumeAborted(e){return this.processManager.consumeAborted(e)}getLastMessageHadImages(e){return this.processManager.getLastMessageHadImages(e)}};function dt(e,t,n){return{canRewind:!1,sessionId:e,messageId:t,filesChanged:[],insertions:0,deletions:0,error:n}}function ft(e,t,n){return{ok:!1,sessionId:e,messageId:t,filesChanged:[],insertions:0,deletions:0,error:n}}const M=t(`codex-runtime/app-server-client`);var pt=class extends me{sessionId;cwd;childProcess;requestTimeoutMs;nextRequestId=1;closed=!1;pending=new Map;constructor(e){super(),this.sessionId=e.sessionId,this.cwd=e.cwd,this.requestTimeoutMs=e.requestTimeoutMs??6e4;let t=e.codexBin??process.env.LARKPAL_CODEX_BIN??`codex`,n=[`app-server`,`--listen`,`stdio://`,...e.extraArgs??[]];this.childProcess=ie(t,n,{cwd:e.cwd,env:e.env??process.env,stdio:[`pipe`,`pipe`,`pipe`]}),M.info(`Codex app-server 进程已启动`,{sessionId:this.sessionId,cwd:this.cwd,pid:this.childProcess.pid,args:n.join(` `)}),this.bindStreams()}request(e,t){if(this.closed)return Promise.reject(Error(`Codex app-server 已关闭,无法发送请求: ${e}`));if(!this.childProcess.stdin||this.childProcess.stdin.destroyed)return Promise.reject(Error(`Codex app-server stdin 不可用,无法发送请求: ${e}`));let n=this.nextRequestId++,r=String(n),i=t===void 0?{id:n,method:e}:{id:n,method:e,params:t};return new Promise((t,n)=>{let a=setTimeout(()=>{this.pending.delete(r),n(Error(`Codex app-server 请求超时: ${e}`))},this.requestTimeoutMs);this.pending.set(r,{method:e,timer:a,resolve:e=>t(e),reject:n}),this.writeJson(i).catch(e=>{clearTimeout(a),this.pending.delete(r),n(e)})})}respond(e,t){return this.writeJson({id:e,result:t})}respondError(e,t,n,r){return this.writeJson({id:e,error:{code:t,message:n,data:r}})}async close(){this.closed||(this.closed=!0,this.rejectAllPending(Error(`Codex app-server client closed`)),await new Promise(e=>{let t=this.childProcess;if(t.exitCode!=null||t.signalCode!=null){e();return}let n=setTimeout(()=>{t.killed||t.kill(`SIGKILL`)},5e3);t.once(`close`,()=>{clearTimeout(n),e()}),t.stdin&&!t.stdin.destroyed&&t.stdin.end(),t.kill(`SIGTERM`)}))}bindStreams(){this.childProcess.stdout&&oe({input:this.childProcess.stdout}).on(`line`,e=>this.handleLine(e)),this.childProcess.stderr&&oe({input:this.childProcess.stderr}).on(`line`,e=>{M.warn(`Codex app-server stderr`,{sessionId:this.sessionId,line:e.slice(0,500)}),this.emit(`stderr`,e)}),this.childProcess.on(`error`,e=>{M.error(`Codex app-server 进程错误`,{sessionId:this.sessionId,error:e.message}),this.emit(`error`,e),this.rejectAllPending(e)}),this.childProcess.on(`close`,(e,t)=>{this.closed=!0,M.info(`Codex app-server 进程退出`,{sessionId:this.sessionId,code:e,signal:t}),this.rejectAllPending(Error(`Codex app-server exited: code=${e}, signal=${t}`)),this.emit(`close`,e,t)})}handleLine(e){let t=e.trim();if(!t)return;let n;try{n=JSON.parse(t)}catch(e){let n=e instanceof Error?e:Error(String(e));M.warn(`Codex app-server JSONL 解析失败`,{sessionId:this.sessionId,error:n.message,line:t.slice(0,200)}),this.emit(`malformedLine`,t,n);return}if(mt(n)){this.handleResponse(n);return}if(ht(n)){this.emit(`serverRequest`,n);return}gt(n)&&this.emit(`notification`,n)}handleResponse(e){if(e.id==null){M.warn(`Codex app-server 返回无 id 错误响应`,{sessionId:this.sessionId,message:e});return}let t=String(e.id),n=this.pending.get(t);if(!n){M.warn(`Codex app-server 返回未知请求响应`,{sessionId:this.sessionId,id:e.id});return}if(clearTimeout(n.timer),this.pending.delete(t),`error`in e){n.reject(Error(`${n.method} failed: ${e.error.message}`));return}n.resolve(e.result)}writeJson(e){return new Promise((t,n)=>{let r=this.childProcess.stdin;if(!r||r.destroyed){n(Error(`Codex app-server stdin is not writable`));return}r.write(`${JSON.stringify(e)}\n`,e=>{e?n(e):t()})})}rejectAllPending(e){for(let t of this.pending.values())clearTimeout(t.timer),t.reject(e);this.pending.clear()}};function mt(e){return`id`in e&&(`result`in e||`error`in e)}function ht(e){return`id`in e&&`method`in e&&!(`result`in e)&&!(`error`in e)}function gt(e){return`method`in e&&!(`id`in e)}function _t(e,t){let n=Error(t||e);return n.userFacingMessage=e,n}function vt(e){if(!e||typeof e!=`object`)return;let t=e.userFacingMessage;return typeof t==`string`&&t.trim()?t:void 0}const N=t(`runtime/codex-app-server-adapter`),yt=f(C(),`.larkpal`,`runtime`,`codex-app-server-threads.json`),bt=12e4;function xt(e){return jt(e)}var St=class{name=`codex-app-server`;capabilities={followupInjection:!0,abort:!0,lastUserMessageId:!0,fileRewind:!0,imageInput:!1};clientFactory;statePath;processes=new Map;threadIds=new Map;threadInstructionHashes=new Map;activeCallbacks=new Map;lastRuntimeConfigs=new Map;sessionLocks=new Map;completionResolvers=new Map;busySessions=new Set;abortedSessions=new Set;itemToolNames=new Map;currentMessageIds=new Map;lastUserMessageIds=new Map;turnMessageIds=new Map;completedTurnIds=new Map;turnDiffs=new Map;turnAgentTexts=new Map;latestTokenUsage=new Map;forceCompactBeforeNextTurn=new Set;compactTurnIds=new Map;compactWaiters=new Map;stateLoaded=!1;constructor(e={}){this.statePath=e.statePath??yt,this.clientFactory=e.clientFactory??(e=>new pt({sessionId:e.sessionId,cwd:e.cwd,env:e.env,extraArgs:e.extraArgs,requestTimeoutMs:bt})),N.info(`CodexAppServerAdapter 初始化完成`,{statePath:this.statePath})}async executePrompt(e,t){await this.loadState();let{sessionId:n}=e,r=this.sessionLocks.get(n);r&&(N.info(`等待上一条 Codex 消息处理完成`,{sessionId:n}),await r);let i=this.createCompletionPromise(n);this.sessionLocks.set(n,i),this.busySessions.add(n),this.activeCallbacks.set(n,t),this.lastRuntimeConfigs.set(n,e);let a=[];try{this.logUnsupportedConfig(e),this.assertImageInputSupported(e);let t=await this.ensureProcess(e);await this.compactBeforeTurnIfNeeded(e,t);let r=await this.toCodexInput(e,a),o=this.createUserMessageId(e);this.currentMessageIds.set(n,o),this.lastUserMessageIds.set(n,o);let s=await t.client.request(`turn/start`,{threadId:t.process.threadId,clientUserMessageId:o,input:r,cwd:e.cwd,approvalPolicy:`never`,sandboxPolicy:{type:`dangerFullAccess`},model:e.model??process.env.LARKPAL_CODEX_MODEL??process.env.CODEX_MODEL??void 0});s?.turn?.id&&(t.process.currentTurnId=s.turn.id,this.rememberTurnMessageId(n,s.turn.id,o)),await i}catch(e){let r=e instanceof Error?e:Error(String(e));t.onError?.(r),this.resolveCompletion(n)}finally{if(e.transcriptMode===`ephemeral`){let e=this.processes.get(n);e&&await this.closeRecord(n,e).catch(e=>{N.warn(`ephemeral Codex app-server session 清理失败`,{sessionId:n,error:e instanceof Error?e.message:String(e)})})}this.busySessions.delete(n),this.activeCallbacks.delete(n),this.sessionLocks.delete(n),this.currentMessageIds.delete(n),await this.cleanupTempFiles(a)}}async stopProcess(e){let t=this.processes.get(e);if(!t){N.warn(`尝试停止不存在的 Codex app-server session`,{sessionId:e});return}if(this.busySessions.has(e)&&t.process.currentTurnId){this.abortedSessions.add(e),N.info(`发送 Codex turn/interrupt`,{sessionId:e,threadId:t.process.threadId,turnId:t.process.currentTurnId}),await t.client.request(`turn/interrupt`,{threadId:t.process.threadId,turnId:t.process.currentTurnId});return}await this.closeRecord(e,t)}async stopAll(){await Promise.all(Array.from(this.processes.entries()).map(([e,t])=>this.closeRecord(e,t)))}getProcessInfo(e){let t=this.processes.get(e);if(t)return this.toProcessInfo(t.process)}getAllProcessInfo(){return Array.from(this.processes.values()).map(e=>this.toProcessInfo(e.process))}isSessionBusy(e){return this.busySessions.has(e)}getCapabilities(){return this.capabilities}getLastUserMessageId(e){return this.lastUserMessageIds.get(e)}consumeAborted(e){let t=this.abortedSessions.has(e);return this.abortedSessions.delete(e),t}getLastMessageHadImages(e){let t=this.lastRuntimeConfigs.get(e);return Array.isArray(t?.prompt)&&t.prompt.some(e=>e.type===`image`)}async previewRewind(e){let t=this.findRewindRecord(e.sessionId,e.messageId);return t?{canRewind:!0,sessionId:e.sessionId,messageId:t.messageId,filesChanged:t.filesChanged,insertions:t.insertions,deletions:t.deletions}:{canRewind:!1,sessionId:e.sessionId,messageId:e.messageId??this.lastUserMessageIds.get(e.sessionId)??``,filesChanged:[],insertions:0,deletions:0,error:`没有找到可撤销的文件变更`}}async confirmRewind(e){await this.loadState();let t=e.sessionId,n=this.sessionLocks.get(t);n&&await n;let r=this.confirmRewindUnlocked(e),i=r.then(()=>void 0,()=>void 0);this.sessionLocks.set(t,i);try{return await r}finally{this.sessionLocks.get(t)===i&&this.sessionLocks.delete(t)}}async confirmRewindUnlocked(e){let t=e.sessionId,n=this.findRewindRecord(t,e.messageId);if(!n)return F(t,e.messageId??this.lastUserMessageIds.get(t)??``,`没有找到可撤销的文件变更`);let r=this.processes.get(t);if(!r?.process.threadId)return F(t,n.messageId,`Codex thread 不可用`);let i=this.completedTurnIds.get(t)??[],a=i.indexOf(n.turnId);if(a<0)return F(t,n.messageId,`无法定位需要回滚的 Codex turn`);let o=i.length-a;if(o<1)return F(t,n.messageId,`无可回滚的 Codex turn`);try{return await qt(r.process.cwd,n.diff,!0),await qt(r.process.cwd,n.diff,!1),await r.client.request(`thread/rollback`,{threadId:r.process.threadId,numTurns:o}),this.pruneRewindState(t,a),{ok:!0,sessionId:t,messageId:n.messageId,filesChanged:n.filesChanged,insertions:n.insertions,deletions:n.deletions}}catch(e){return F(t,n.messageId,e instanceof Error?e.message:String(e))}}async ensureProcess(e){let t=this.processes.get(e.sessionId);if(t&&t.process.status===`running`)return t.process.lastActiveAt=new Date,t.process.threadId||await this.ensureThread(e,t),t;let n=this.buildProcessEnv(e),r=this.buildCodexArgs(e),i=this.clientFactory({sessionId:e.sessionId,cwd:e.cwd,env:n,extraArgs:r}),a={client:i,process:{sessionId:e.sessionId,cwd:e.cwd,childProcess:i.childProcess,status:`starting`,startedAt:new Date,lastActiveAt:new Date}};return this.processes.set(e.sessionId,a),this.bindClient(e.sessionId,a),await i.request(`initialize`,{clientInfo:{name:`larkpal`,title:`LarkPal`,version:process.env.npm_package_version??`0.0.0`},capabilities:{experimentalApi:!1,requestAttestation:!1}}),a.process.status=`running`,await this.ensureThread(e,a),a}async ensureThread(e,t){let n=e.transcriptMode===`ephemeral`,r=await wt(e.cwd),i=this.threadInstructionHashes.get(e.sessionId),a=n?void 0:this.threadIds.get(e.sessionId),o=e.model??process.env.LARKPAL_CODEX_MODEL??process.env.CODEX_MODEL??void 0;if(!n&&a&&r&&i!==r&&N.info(`Codex 指令文件变化,继续复用旧 thread 并在本轮注入最新 runtime instructions`,{sessionId:e.sessionId,cwd:e.cwd,threadId:a,hadStoredInstructionsHash:!!i}),a)try{let i=await t.client.request(`thread/resume`,{threadId:a,cwd:e.cwd,model:o,approvalPolicy:`never`,sandbox:`danger-full-access`});t.process.threadId=i.thread.id,n||await this.setThreadId(e.sessionId,i.thread.id,e.cwd,r);return}catch(t){N.warn(`Codex thread/resume 失败,将新建 thread`,{sessionId:e.sessionId,threadId:a,error:t instanceof Error?t.message:String(t)})}let s=await t.client.request(`thread/start`,{cwd:e.cwd,model:o,approvalPolicy:`never`,sandbox:`danger-full-access`,sessionStartSource:`startup`,threadSource:`user`});t.process.threadId=s.thread.id,n||await this.setThreadId(e.sessionId,s.thread.id,e.cwd,r)}bindClient(e,t){t.client.on(`notification`,n=>{t.process.lastActiveAt=new Date,this.handleNotification(e,n)}),t.client.on(`serverRequest`,e=>{this.handleServerRequest(t.client,e)}),t.client.on(`error`,n=>{t.process.status=`crashed`,this.activeCallbacks.get(e)?.onError?.(n),this.resolveCompletion(e)}),t.client.on(`close`,()=>{t.process.status!==`stopping`&&t.process.status!==`stopped`&&(t.process.status=`crashed`),this.resolveCompletion(e),this.processes.delete(e)})}handleNotification(e,t){switch(t.method){case`turn/started`:this.handleTurnStarted(e,t.params);break;case`item/agentMessage/delta`:this.handleAgentMessageDelta(e,t.params);break;case`item/reasoning/summaryTextDelta`:case`item/reasoning/textDelta`:this.activeCallbacks.get(e)?.onThinkingDelta?.(t.params.delta??``);break;case`item/started`:this.handleItemStarted(e,t.params);break;case`item/completed`:this.handleItemCompleted(e,t.params);break;case`item/mcpToolCall/progress`:this.handleMcpProgress(e,t.params);break;case`turn/completed`:this.handleTurnCompleted(e,t.params);break;case`turn/diff/updated`:this.handleTurnDiffUpdated(e,t.params);break;case`error`:this.handleErrorNotification(e,t.params);break;case`thread/status/changed`:this.handleThreadStatusChanged(e,t.params);break;case`thread/compacted`:this.handleThreadCompacted(e,t.params);break;case`thread/tokenUsage/updated`:this.handleThreadTokenUsageUpdated(e,t.params);break;default:N.debug(`忽略 Codex app-server notification`,{sessionId:e,method:t.method});break}}handleTurnStarted(e,t){let n=this.processes.get(e);n&&(n.process.currentTurnId=t.turn.id);let r=this.currentMessageIds.get(e);r&&this.rememberTurnMessageId(e,t.turn.id,r)}handleItemStarted(e,t){let n=this.activeCallbacks.get(e);if(!n)return;let{toolName:r,toolInput:i}=this.describeToolItem(t.item);r&&(this.rememberToolName(e,t.item.id,r),n.onToolUseStart?.(r,i))}handleItemCompleted(e,t){if(t.item.type===`contextCompaction`){this.rememberCompactTurn(e,t.turnId),this.emitRuntimeEvent(e,{type:`codex-context-compaction-item`,timestamp:new Date().toISOString(),sessionId:e,data:{threadId:t.threadId,turnId:t.turnId,itemId:t.item.id}}),this.resolveCompactWaiter(e);return}t.item.type===`agentMessage`&&typeof t.item.text==`string`&&t.item.text.trim()!==``&&this.rememberTurnAgentText(e,t.turnId,t.item.text);let n=this.activeCallbacks.get(e);n&&(this.lookupToolName(e,t.item.id)??this.describeToolItem(t.item).toolName)&&n.onToolResult?.(t.item.id,this.summarizeToolResult(t.item))}handleAgentMessageDelta(e,t){let n=t.delta??``;n&&this.appendTurnAgentText(e,t.turnId,n),this.activeCallbacks.get(e)?.onTextDelta?.(n)}handleMcpProgress(e,t){let n=this.lookupToolName(e,t.itemId)??`mcp`;this.activeCallbacks.get(e)?.onToolProgress?.(n,0),N.debug(`Codex MCP tool progress`,{sessionId:e,itemId:t.itemId,message:t.message})}handleTurnCompleted(e,t){let n=this.activeCallbacks.get(e),r=this.processes.get(e);if(r&&(r.process.currentTurnId=void 0),this.isCompactTurn(e,t.turn.id)){N.info(`Codex compact turn completed`,{sessionId:e,threadId:t.threadId,turnId:t.turn.id,status:t.turn.status}),this.resolveCompactWaiter(e),this.forgetCompactTurn(e,t.turn.id);return}let i=this.abortedSessions.delete(e)||t.turn.status===`interrupted`,a=t.turn.status===`failed`&&!i,o=this.extractFinalText(e,t.turn),s=t.turn.error?.message??t.turn.error?.additionalDetails??void 0;n?.onTurnEnd?.(`end_turn`),n?.onResult?.({subtype:a?`error_during_execution`:`success`,result:a?s??o:o,durationMs:t.turn.durationMs??void 0,isError:a,aborted:i}),t.turn.status===`completed`&&this.rememberCompletedTurn(e,t.turn.id),this.turnAgentTexts.get(e)?.delete(t.turn.id),this.resolveCompletion(e)}handleTurnDiffUpdated(e,t){if(!t.diff.trim())return;let n=this.lookupTurnMessageId(e,t.turnId)??this.currentMessageIds.get(e);if(!n)return;let r=this.turnDiffs.get(e);r||(r=new Map,this.turnDiffs.set(e,r));let i=Kt(t.diff);r.set(t.turnId,{messageId:n,turnId:t.turnId,diff:t.diff,filesChanged:i.filesChanged,insertions:i.insertions,deletions:i.deletions})}handleErrorNotification(e,t){let n=Ft(t)??`Codex app-server error`;if(It(t)){N.warn(`Codex app-server retryable error notification`,{sessionId:e,message:n,params:Wt(t)});return}N.warn(`Codex app-server error notification`,{sessionId:e,message:n,params:Wt(t)}),this.activeCallbacks.get(e)?.onError?.(Mt(n)),Nt(n)?this.resetSessionAfterFatalError(e,`image_capability_error`):Lt(t,n)&&this.restartSessionAndCompactNextTurn(e,`fatal_stream_disconnect`),this.resolveCompletion(e)}handleThreadStatusChanged(e,t){N.info(`Codex thread status changed`,{sessionId:e,params:Wt(t)})}handleThreadCompacted(e,t){N.info(`Codex thread compacted`,{sessionId:e,threadId:t.threadId,turnId:t.turnId}),this.rememberCompactTurn(e,t.turnId),this.emitRuntimeEvent(e,{type:`codex-context-compacted`,timestamp:new Date().toISOString(),sessionId:e,data:{threadId:t.threadId,turnId:t.turnId}}),this.resolveCompactWaiter(e)}handleThreadTokenUsageUpdated(e,t){this.latestTokenUsage.set(e,t.tokenUsage),N.info(`Codex thread token usage updated`,{sessionId:e,threadId:t.threadId,turnId:t.turnId,totalTokens:t.tokenUsage.total.totalTokens,modelContextWindow:t.tokenUsage.modelContextWindow}),this.emitRuntimeEvent(e,{type:`codex-token-usage-updated`,timestamp:new Date().toISOString(),sessionId:e,data:{threadId:t.threadId,turnId:t.turnId,tokenUsage:t.tokenUsage}})}emitRuntimeEvent(e,t){let n=this.activeCallbacks.get(e);n?.onRuntimeEvent?.(t),n?.onScenarioEvent&&n.onScenarioEvent!==n.onRuntimeEvent&&n.onScenarioEvent(t)}async handleServerRequest(e,t){switch(N.warn(`Codex app-server server request 默认拒绝`,{method:t.method,id:t.id}),t.method){case`item/commandExecution/requestApproval`:await e.respond(t.id,{decision:`decline`});break;case`item/fileChange/requestApproval`:await e.respond(t.id,{decision:`decline`});break;case`item/permissions/requestApproval`:await e.respond(t.id,{permissions:{},scope:`turn`});break;default:await e.respondError(t.id,-32601,`LarkPal does not handle Codex server request: ${t.method}`);break}}describeToolItem(e){switch(e.type){case`commandExecution`:return{toolName:`Bash`,toolInput:{command:e.command,cwd:e.cwd}};case`fileChange`:return{toolName:`apply_patch`,toolInput:{changes:e.changes}};case`mcpToolCall`:return{toolName:`mcp__${typeof e.server==`string`?e.server:`mcp`}__${typeof e.tool==`string`?e.tool:`tool`}`,toolInput:e.arguments};case`dynamicToolCall`:return{toolName:`${typeof e.namespace==`string`&&e.namespace?`${e.namespace}__`:``}${typeof e.tool==`string`?e.tool:`dynamic_tool`}`,toolInput:e.arguments};case`webSearch`:return{toolName:`WebSearch`,toolInput:{query:e.query}};default:return{}}}summarizeToolResult(e){switch(e.type){case`commandExecution`:{let t=typeof e.exitCode==`number`?e.exitCode:void 0,n=typeof e.status==`string`?e.status:void 0,r=typeof e.aggregatedOutput==`string`?e.aggregatedOutput:e.aggregatedOutput??void 0;return{ok:n===`completed`&&(t==null||t===0),exitCode:t,isError:n===`failed`||typeof t==`number`&&t!==0,outputSummary:r}}case`mcpToolCall`:return{ok:e.status===`completed`&&!e.error,isError:e.status===`failed`||!!e.error,resultSummary:e.result,outputSummary:e.error??e.result};case`fileChange`:return{ok:e.status===`completed`,isError:e.status===`failed`||e.status===`declined`,outputSummary:e.changes};case`dynamicToolCall`:{let t=typeof e.success==`boolean`?e.success:void 0;return{ok:t??e.status===`completed`,isError:e.status===`failed`||t===!1,outputSummary:e.contentItems}}default:return{}}}extractFinalText(e,t){return[...Array.isArray(t.items)?t.items:[]].reverse().find(e=>e.type===`agentMessage`&&typeof e.text==`string`&&e.text.trim()!==``)?.text??this.turnAgentTexts.get(e)?.get(t.id)}rememberToolName(e,t,n){let r=this.itemToolNames.get(e);r||(r=new Map,this.itemToolNames.set(e,r)),r.set(t,n)}rememberTurnAgentText(e,t,n){let r=this.turnAgentTexts.get(e);r||(r=new Map,this.turnAgentTexts.set(e,r)),r.set(t,n)}appendTurnAgentText(e,t,n){let r=this.turnAgentTexts.get(e);r||(r=new Map,this.turnAgentTexts.set(e,r)),r.set(t,`${r.get(t)??``}${n}`)}createUserMessageId(e){return e.requestId?`${e.requestId}:user`:`codex-user-${w()}`}rememberTurnMessageId(e,t,n){let r=this.turnMessageIds.get(e);r||(r=new Map,this.turnMessageIds.set(e,r)),r.set(t,n)}lookupTurnMessageId(e,t){return this.turnMessageIds.get(e)?.get(t)}rememberCompletedTurn(e,t){let n=this.completedTurnIds.get(e)??[];n.includes(t)||(n.push(t),this.completedTurnIds.set(e,n))}findRewindRecord(e,t){let n=this.turnDiffs.get(e);if(!n)return;let r=this.completedTurnIds.get(e)??[];for(let e=r.length-1;e>=0;--e){let i=n.get(r[e]);if(i&&(!t||i.messageId===t))return i}}pruneRewindState(e,t){let n=this.completedTurnIds.get(e)??[],r=n.slice(t);this.completedTurnIds.set(e,n.slice(0,t));let i=this.turnDiffs.get(e),a=this.turnMessageIds.get(e);for(let e of r)i?.delete(e),a?.delete(e);let o=this.completedTurnIds.get(e)?.at(-1),s=o?this.lookupTurnMessageId(e,o):void 0;s&&this.lastUserMessageIds.set(e,s)}lookupToolName(e,t){return this.itemToolNames.get(e)?.get(t)}async toCodexInput(e,t){let n=[],r=await this.buildRuntimeInstructionsInput(e.cwd);r&&n.push({type:`text`,text:r,text_elements:[]});let{prompt:i}=e;if(typeof i==`string`)return n.push({type:`text`,text:i,text_elements:[]}),n;for(let e of i)if(e.type===`text`)n.push({type:`text`,text:e.text,text_elements:[]});else if(e.type===`image`){let r=await this.writeTempImage(e,t);n.push({type:`localImage`,path:r})}return n}assertImageInputSupported(e){if(!xt(e.prompt)||this.supportsImageInput(e))return;let t=e.model??process.env.LARKPAL_CODEX_MODEL??process.env.CODEX_MODEL??`当前配置`;throw Error(`当前 Codex 模型 ${t} 不支持图片输入。请改用支持视觉输入的模型,或直接用文字描述图片内容。`)}supportsImageInput(e){if(process.env.LARKPAL_CODEX_IMAGE_INPUT===`1`||process.env.LARKPAL_CODEX_IMAGE_INPUT===`true`)return!0;let t=(e.model??process.env.LARKPAL_CODEX_MODEL??process.env.CODEX_MODEL??``).toLowerCase();return!t||t.includes(`codex`)?!1:/\b(?:vision|multimodal|gpt-4o|gpt-4\.1|gpt-5(?:\.\d+)?)(?:\b|[-_])/.test(t)}async buildRuntimeInstructionsInput(e){let t=await Ct(e);if(t.length===0)return;let n=t.map(e=>`# ${e.path}\n\n${e.content.trim()}`).join(`
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
`),r=Tt(n);return[`<larkpal_runtime_instructions>`,`The following content is LarkPal runtime instruction context, not the user request. Follow it with higher priority than the user text that follows.`,``,r?`Your Feishu-facing name is 「${r}」.`:`Use the Feishu-facing app name defined below.`,`If the user asks who you are, answer with your Feishu-facing app name and role.`,`Do not introduce yourself as Codex unless the user explicitly asks about the underlying runtime engine.`,`Do not introduce yourself as LarkPal; LarkPal is the hosting platform.`,``,n,`</larkpal_runtime_instructions>`,``,`<user_request_follows>`].join(`
|
|
13
|
-
`)}async writeTempImage(e,t){let n=
|
|
13
|
+
`)}async writeTempImage(e,t){let n=f(ne(),`larkpal-codex-${Date.now()}-${Math.random().toString(16).slice(2)}`);await g(n,{recursive:!0}),t.push(n);let r=f(n,`image${Et(e.source.media_type)}`);return await S(r,Buffer.from(e.source.data,`base64`)),r}async cleanupTempFiles(e){await Promise.all(e.map(e=>b(e,{recursive:!0,force:!0}).catch(()=>{})))}buildProcessEnv(e){let t=we(e.policy);return{...process.env,LARKPAL_MCP_SESSION_ID:e.sessionId,LARKPAL_MCP_CWD:e.cwd,...t?{LARKPAL_MCP_DISABLED_TOOLS:t}:{},LARKPAL_USER_ID:e.userContext?.userId??process.env.LARKPAL_USER_ID,LARKPAL_USER_OPEN_ID:e.userContext?.openId??process.env.LARKPAL_USER_OPEN_ID,LARKPAL_USER_NAME:e.userContext?.userName??process.env.LARKPAL_USER_NAME,LARKPAL_CREDENTIAL_DIR:e.userContext?.credentialDir??process.env.LARKPAL_CREDENTIAL_DIR,LARKPAL_IS_TENANT:e.userContext?.isTenantIdentity?`1`:process.env.LARKPAL_IS_TENANT}}buildCodexArgs(e){let{command:t,args:n}=At(),r=we(e.policy),i={PATH:process.env.PATH||`/usr/local/bin:/usr/bin:/bin`,HOME:process.env.HOME||C(),NODE_PATH:process.env.NODE_PATH||``,LARKPAL_MCP_SESSION_ID:e.sessionId,...e.cwd?{LARKPAL_MCP_CWD:e.cwd}:{},...r?{LARKPAL_MCP_DISABLED_TOOLS:r}:{},LARKPAL_GATEWAY_PORT:process.env.LARKPAL_GATEWAY_PORT||`3000`};return[`-c`,`mcp_servers.larkpal.command=${Dt(t)}`,`-c`,`mcp_servers.larkpal.args=${Ot(n)}`,`-c`,`mcp_servers.larkpal.env=${kt(i)}`]}logUnsupportedConfig(e){e.llmConfig&&N.warn(`Codex app-server v1 暂不支持 per-request llmConfig,已忽略`,{sessionId:e.sessionId}),e.maxBudgetUsd!=null&&N.warn(`Codex app-server v1 暂不支持 maxBudgetUsd,已忽略`,{sessionId:e.sessionId}),e.maxTurns!=null&&N.warn(`Codex app-server v1 暂不支持 maxTurns,已忽略`,{sessionId:e.sessionId}),e.policy?.allowedTools?.length&&N.warn(`Codex app-server v1 暂不强制执行 tool allow policy,已忽略`,{sessionId:e.sessionId})}createCompletionPromise(e){return new Promise(t=>{this.completionResolvers.set(e,t)})}resolveCompletion(e){let t=this.completionResolvers.get(e);t&&(this.completionResolvers.delete(e),t())}async closeRecord(e,t){t.process.status=`stopping`,t.process.threadId&&await t.client.request(`thread/unsubscribe`,{threadId:t.process.threadId}).catch(n=>{N.warn(`Codex thread/unsubscribe 失败`,{sessionId:e,threadId:t.process.threadId,error:n instanceof Error?n.message:String(n)})}),await t.client.close(),t.process.status=`stopped`,this.processes.delete(e),this.resolveCompletion(e)}async compactBeforeTurnIfNeeded(e,t){let n=t.process.threadId;n&&e.transcriptMode!==`ephemeral`&&this.shouldCompactBeforeTurn(e.sessionId)&&(N.info(`Codex native compact required before user turn`,{sessionId:e.sessionId,threadId:n,reason:this.forceCompactBeforeNextTurn.has(e.sessionId)?`forced_after_fatal_error`:`token_usage_threshold`}),this.forceCompactBeforeNextTurn.delete(e.sessionId),await this.requestThreadCompact(e.sessionId,t,n),this.latestTokenUsage.delete(e.sessionId))}shouldCompactBeforeTurn(e){if(this.forceCompactBeforeNextTurn.has(e))return!0;let t=this.latestTokenUsage.get(e);if(!t)return!1;let n=Rt(process.env.LARKPAL_CODEX_AUTO_COMPACT_TOKEN_LIMIT)??Rt(process.env.CODEX_AUTO_COMPACT_TOKEN_LIMIT);if(n&&t.total.totalTokens>=n)return!0;let r=t.modelContextWindow;if(!r||r<=0)return!1;let i=zt(process.env.LARKPAL_CODEX_AUTO_COMPACT_RATIO)??.8;return i<=0?!1:t.total.totalTokens>=Math.floor(r*i)}async requestThreadCompact(e,t,n){let r,i=new Promise(t=>{r=t,this.compactWaiters.set(e,t)});try{let r=await t.client.request(`thread/compact/start`,{threadId:n}),a=Vt(r);a&&this.rememberCompactTurn(e,a),Ht(r)&&this.resolveCompactWaiter(e),await Ut(i,Bt(),`Codex compact timed out for session ${e}`)}finally{this.compactWaiters.get(e)===r&&this.compactWaiters.delete(e)}}resolveCompactWaiter(e){let t=this.compactWaiters.get(e);t&&(this.compactWaiters.delete(e),t())}rememberCompactTurn(e,t){if(!t)return;let n=this.compactTurnIds.get(e);n||(n=new Set,this.compactTurnIds.set(e,n)),n.add(t)}isCompactTurn(e,t){return this.compactTurnIds.get(e)?.has(t)??!1}forgetCompactTurn(e,t){let n=this.compactTurnIds.get(e);n&&(n.delete(t),n.size===0&&this.compactTurnIds.delete(e))}async restartSessionAndCompactNextTurn(e,t){N.warn(`Codex app-server fatal stream error; preserving thread and requiring native compact before next turn`,{sessionId:e,reason:t,threadId:this.threadIds.get(e)}),this.forceCompactBeforeNextTurn.add(e),this.completedTurnIds.delete(e),this.turnMessageIds.delete(e),this.turnDiffs.delete(e),this.turnAgentTexts.delete(e),this.currentMessageIds.delete(e),this.compactTurnIds.delete(e),this.resolveCompactWaiter(e);let n=this.processes.get(e);n&&await this.closeRecord(e,n).catch(n=>{N.warn(`Codex app-server fatal stream cleanup failed`,{sessionId:e,reason:t,error:n instanceof Error?n.message:String(n)})})}toProcessInfo(e){let t=this.lastRuntimeConfigs.get(e.sessionId),n=this.latestTokenUsage.get(e.sessionId);return{sessionId:e.sessionId,cwd:e.cwd,status:e.status,startedAt:e.startedAt,lastActiveAt:e.lastActiveAt,runContext:t?.runContext,requestContext:t?.requestContext,authHeaders:t?.authHeaders,runtimeState:{runtime:this.name,threadId:e.threadId,currentTurnId:e.currentTurnId,compactRequiredBeforeNextTurn:this.forceCompactBeforeNextTurn.has(e.sessionId),compactInProgress:this.compactWaiters.has(e.sessionId),tokenUsage:n?{totalTokens:n.total.totalTokens,inputTokens:n.total.inputTokens,cachedInputTokens:n.total.cachedInputTokens,outputTokens:n.total.outputTokens,reasoningOutputTokens:n.total.reasoningOutputTokens,modelContextWindow:n.modelContextWindow}:void 0}}}async loadState(){if(!this.stateLoaded&&(this.stateLoaded=!0,i(this.statePath)))try{let e=await _(this.statePath,`utf-8`),t=JSON.parse(e);for(let[e,n]of Object.entries(t.sessions??{}))n.threadId&&(this.threadIds.set(e,n.threadId),n.instructionsHash&&this.threadInstructionHashes.set(e,n.instructionsHash))}catch(e){N.warn(`Codex thread state 加载失败,将从空状态继续`,{path:this.statePath,error:e instanceof Error?e.message:String(e)})}}async setThreadId(e,t,n,r){this.threadIds.set(e,t),r?this.threadInstructionHashes.set(e,r):this.threadInstructionHashes.delete(e),await this.persistThreadState({sessionId:e,cwd:n})}async resetSessionAfterFatalError(e,t){N.warn(`重置 Codex app-server session,避免失败 turn 污染后续消息`,{sessionId:e,reason:t}),this.threadIds.delete(e),this.threadInstructionHashes.delete(e),this.completedTurnIds.delete(e),this.turnMessageIds.delete(e),this.turnDiffs.delete(e),this.turnAgentTexts.delete(e),this.lastUserMessageIds.delete(e),this.currentMessageIds.delete(e),await this.persistThreadState().catch(n=>{N.warn(`Codex thread state 清理失败`,{sessionId:e,reason:t,error:n instanceof Error?n.message:String(n)})});let n=this.processes.get(e);n&&await this.closeRecord(e,n).catch(n=>{N.warn(`Codex app-server session 重置关闭失败`,{sessionId:e,reason:t,error:n instanceof Error?n.message:String(n)})})}async persistThreadState(e){await g(u(this.statePath),{recursive:!0});let t={};for(let[n,r]of this.threadIds.entries())t[n]={threadId:r,cwd:n===e?.sessionId?e.cwd:``,instructionsHash:this.threadInstructionHashes.get(n),updatedAt:new Date().toISOString()};await S(this.statePath,JSON.stringify({sessions:t},null,2),`utf-8`)}};async function Ct(e){let t=[],n=p(e);for(;;){let e=f(n,`AGENTS.md`);if(i(e)){let n=await _(e,`utf-8`);t.push({path:e,content:n})}let r=u(n);if(r===n)break;n=r}return t.reverse()}async function wt(e){let t=(await Ct(e)).map(e=>`${e.path}\n${e.content}`);if(t.length!==0)return ae(`sha256`).update(t.join(`
|
|
14
14
|
--- LARKPAL_AGENTS_MD ---
|
|
15
|
-
`)).digest(`hex`)}function Tt(e){return e.match(/Your Feishu-facing name is 「([^」]+)」/)?.[1]?.trim()||e.match(/你的名字是「([^」]+)」/)?.[1]?.trim()||void 0}function Et(e){let t=e.split(`/`)[1]?.toLowerCase();if(!t)return`.png`;if(t===`jpeg`)return`.jpg`;let n=`.${t}`;return
|
|
16
|
-
`),t):Error(t)}function Nt(e){let t=Pt(e)??e;return/does not support image inputs|image inputs|vision model/i.test(t)}function Pt(e){let t=e.trim();if(t.startsWith(`{`))try{let e=JSON.parse(t),n=
|
|
17
|
-
`);return/responseStreamDisconnected|stream disconnected before completion|stream closed before response\.completed|max_output_tokens/i.test(n)}function Rt(e){if(!e)return;let t=Number.parseInt(e,10);return Number.isFinite(t)&&t>0?t:void 0}function zt(e){if(!e)return;let t=Number.parseFloat(e);return Number.isFinite(t)&&t>0?t:void 0}function Bt(){return Rt(process.env.LARKPAL_CODEX_COMPACT_TIMEOUT_MS)??bt}function Vt(e){let t=N(e,[`turn`,`id`]);return typeof t==`string`?t:void 0}function Ht(e){let t=N(e,[`turn`,`status`]);return typeof t==`string`&&[`completed`,`failed`,`interrupted`].includes(t)}function Ut(e,t,n){let r,i=new Promise((e,i)=>{r=setTimeout(()=>i(Error(n)),t)});return Promise.race([e,i]).finally(()=>{r&&clearTimeout(r)})}function Wt(e){return Gt(e,0)}function N(e,t){let n=e;for(let e of t){if(!n||typeof n!=`object`||!(e in n))return;n=n[e]}return n}function Gt(e,t){if(typeof e==`string`)return e.length>2e3?`${e.slice(0,2e3)}...[truncated ${e.length-2e3} chars]`:e;if(typeof e!=`object`||!e)return e;if(t>=6)return`[truncated: max depth]`;if(Array.isArray(e)){let n=e.slice(0,20).map(e=>Gt(e,t+1));return e.length>20&&n.push(`[truncated ${e.length-20} items]`),n}let n=Object.entries(e),r={};for(let[e,i]of n.slice(0,50))r[e]=Gt(i,t+1);return n.length>50&&(r.__truncatedKeys=n.length-50),r}function Kt(e){let t=new Set,n=0,r=0;for(let i of e.split(/\r?\n/)){let e=/^diff --git a\/(.+?) b\/(.+)$/.exec(i);if(e){t.add(e[2]);continue}let a=/^\+\+\+ b\/(.+)$/.exec(i);if(a&&a[1]!==`/dev/null`){t.add(a[1]);continue}let o=/^--- a\/(.+)$/.exec(i);if(o&&o[1]!==`/dev/null`){t.add(o[1]);continue}i.startsWith(`+`)&&!i.startsWith(`+++`)&&(n+=1),i.startsWith(`-`)&&!i.startsWith(`---`)&&(r+=1)}return{filesChanged:Array.from(t),insertions:n,deletions:r}}function P(e,t,n){return{ok:!1,sessionId:e,messageId:t,filesChanged:[],insertions:0,deletions:0,error:n}}function qt(e,t,n){return new Promise((r,i)=>{let a=[`apply`,`-R`];n&&a.push(`--check`);let o=ie(`git`,a,{cwd:e,stdio:[`pipe`,`pipe`,`pipe`]}),s=``;o.stderr?.on(`data`,e=>{s+=String(e)}),o.on(`error`,i),o.on(`close`,e=>{e===0?r():i(Error(s.trim()||`git ${a.join(` `)} failed with exit code ${e}`))}),o.stdin.end(t)})}let Jt=null;function Yt(e){Jt=e}function Xt(){return Jt}var Zt=class extends Error{constructor(e,t=400){super(e),this.statusCode=t,this.name=`ArtifactUploadError`}},Qt=class{rootDir;maxUploadBytes;ttlMs;constructor(e){let t=e?.workspaceRoot||T();this.rootDir=d(t,`.artifacts`),this.maxUploadBytes=e?.maxUploadBytes??$t(`LARKPAL_ARTIFACT_MAX_UPLOAD_BYTES`,52428800),this.ttlMs=e?.ttlMs??$t(`LARKPAL_ARTIFACT_TTL_MS`,2592e5)}async create(e){F(e.sessionId,`sessionId`),F(e.owner.tenantKey,`tenantKey`);let t=`art_${w().replace(/-/g,``)}`,r=Date.now(),i=new Date(r).toISOString(),a=new Date(r+this.ttlMs).toISOString(),o=this.getArtifactDir(e.owner.tenantKey,e.sessionId,t),s=d(o,`blob`),c=d(o,`.blob.${process.pid}.${Date.now()}.tmp`);await h(o,{recursive:!0});let l=ae(`sha256`),u=0,f=new ge({transform:(e,t,n)=>{if(u+=e.length,u>this.maxUploadBytes){n(new Zt(`Artifact exceeds max upload size ${this.maxUploadBytes} bytes`,413));return}l.update(e),n(null,e)}});try{await he(e.stream,f,n(c)),await v(c,s)}catch(e){throw await y(o,{recursive:!0,force:!0}).catch(()=>void 0),e}let p={artifactId:t,sessionId:e.sessionId,tenantKey:e.owner.tenantKey,userId:e.owner.userId,openId:e.owner.openId,kind:`workspace-file`,uri:`artifact://${t}`,fileName:en(e.fileName),mimeType:tn(e.mimeType),size:u,contentHash:`sha256:${l.digest(`hex`)}`,createdAt:i,expiresAt:a,metadata:e.metadata,blobPath:s};return await on(d(o,`meta.json`),p),nn(p)}async list(e){F(e.sessionId,`sessionId`),F(e.owner.tenantKey,`tenantKey`);let t=this.getSessionDir(e.owner.tenantKey,e.sessionId),n;try{n=await _(t)}catch{return[]}let r=[];for(let i of n){if(!i.startsWith(`art_`))continue;let n=await an(d(t,i,`meta.json`));n&&rn(n,e.owner,e.sessionId)&&(Date.parse(n.expiresAt)<=Date.now()||r.push(nn(n)))}return r.sort((e,t)=>e.createdAt.localeCompare(t.createdAt))}async statBlob(e,t){let n=await an(this.getMetadataPath(t.tenantKey,e.sessionId,e.artifactId));if(!n||!rn(n,t,e.sessionId))return null;let r=await b(n.blobPath).catch(()=>null);return r?{path:n.blobPath,size:r.size}:null}async resolveBlob(e){F(e.sessionId,`sessionId`),F(e.owner.tenantKey,`tenantKey`),F(e.artifactId,`artifactId`);let t=await an(this.getMetadataPath(e.owner.tenantKey,e.sessionId,e.artifactId));return!t||!rn(t,e.owner,e.sessionId)||Date.parse(t.expiresAt)<=Date.now()||!await b(t.blobPath).catch(()=>null)?null:{ref:nn(t),blobPath:t.blobPath}}getSessionDir(e,t){return d(this.rootDir,e,t)}getArtifactDir(e,t,n){return d(this.getSessionDir(e,t),n)}getMetadataPath(e,t,n){return d(this.getArtifactDir(e,t,n),`meta.json`)}};function $t(e,t){let n=process.env[e];if(!n)return t;let r=Number.parseInt(n,10);return Number.isFinite(r)&&r>0?r:t}function F(e,t){if(!/^[A-Za-z0-9_.:-]{1,200}$/.test(e))throw new Zt(`Invalid ${t}`,400)}function en(e){return e.replace(/[\\/\0\r\n]/g,`_`).trim()||`upload.bin`}function tn(e){return e?.trim()||`application/octet-stream`}function nn(e){let{tenantKey:t,userId:n,openId:r,blobPath:i,...a}=e;return a}function rn(e,t,n){return e.tenantKey===t.tenantKey&&e.userId===t.userId&&e.openId===t.openId&&e.sessionId===n}async function an(e){try{return JSON.parse(await g(e,`utf-8`))}catch{return null}}async function on(e,t){await h(l(e),{recursive:!0}),await x(e,JSON.stringify(t,null,2),`utf-8`)}const I=t(`runtime/larkpal-agent-factory`),sn=d(S(),`.claude`,`CLAUDE.md`);async function cn(){try{let e=await g(sn,`utf-8`);return I.info(`systemPrompt 加载成功`,{path:sn,length:e.length}),e}catch{return I.warn(`systemPrompt 文件不存在,使用默认`,{path:sn}),`你是一个 AI 助手,帮助用户完成飞书知识管理任务。`}}function ln(){let e=process.env.LARKPAL_AGENT_LLM_BASE_URL,t=process.env.LARKPAL_AGENT_LLM_API_KEY,n=process.env.LARKPAL_AGENT_LLM_MODEL;if(!e||!t||!n)throw Error(`larkpal-agent 需要配置 LLM 环境变量: LARKPAL_AGENT_LLM_BASE_URL, LARKPAL_AGENT_LLM_API_KEY, LARKPAL_AGENT_LLM_MODEL`);return{baseURL:e,apiKey:t,defaultModel:n}}function un(){return(process.env.LARKPAL_AGENT_SCENARIO_DIRS||``).split(`:`).map(e=>e.trim()).filter(Boolean)}function dn(e=process.env){let t=e.LARKPAL_AGENT_MCP_TIMEOUT_MS;if(t==null||t.trim()===``)return 1e4;let n=Number.parseInt(t,10);if(!Number.isFinite(n)||!/^\d+$/.test(t.trim())||n<=0)throw Error(`LARKPAL_AGENT_MCP_TIMEOUT_MS 必须是正整数毫秒值`);return n}function fn(e){let t=process.env.LARKPAL_AGENT_SCENARIO_PROVIDER_CONFIG;if(t){let e=hn(t);if(!e.type)throw Error(`LARKPAL_AGENT_SCENARIO_PROVIDER_CONFIG 缺少必填字段 type`);return pn(e)}let n=process.env.LARKPAL_AGENT_SCENARIO_PROVIDER_TYPE;if(!(!n&&e.length===0)){if(!n||n===`local`)return{type:`local`,manifestDirs:e,dirs:e};if(n===`http`){let e=process.env.LARKPAL_AGENT_SCENARIO_PROVIDER_BASE_URL||process.env.LARKPAL_AGENT_SCENARIO_PROVIDER_URL||process.env.AI_KNOWLEDGE_SCENARIO_PROVIDER_BASE_URL;if(!e)throw Error(`LARKPAL_AGENT_SCENARIO_PROVIDER_TYPE=http 时必须配置 LARKPAL_AGENT_SCENARIO_PROVIDER_BASE_URL`);let t=mn(e);return{type:n,baseURL:t,baseUrl:t,headers:gn(`LARKPAL_AGENT_SCENARIO_PROVIDER_HEADERS`)}}return n===`mcp`?{type:n,toolPrefix:process.env.LARKPAL_AGENT_SCENARIO_PROVIDER_MCP_TOOL_PREFIX}:{type:n}}}function pn(e){if(e.type!==`http`)return e;let t=typeof e.baseURL==`string`?e.baseURL:typeof e.baseUrl==`string`?e.baseUrl:void 0;if(!t)return e;let n=mn(t);return{...e,baseURL:n,baseUrl:n}}function mn(e){let t=e.trim().replace(/\/+$/,``);return t.toLowerCase().endsWith(`/api/scenario-manifests`)&&t.slice(0,-23)||t}function hn(e){try{let t=JSON.parse(e);if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`config must be a JSON object`);return t}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`LARKPAL_AGENT_SCENARIO_PROVIDER_CONFIG 不是合法 JSON 对象: ${t}`,{cause:e})}}function gn(e){let t=process.env[e];if(!t)return;let n=JSON.parse(t);if(!n||typeof n!=`object`||Array.isArray(n))throw Error(`${e} 必须是 JSON object`);let r={};for(let[e,t]of Object.entries(n))typeof t==`string`&&(r[e]=t);return r}function _n(e){if(e)return{type:e.type,baseURL:e.baseURL||e.baseUrl,manifestDirCount:Array.isArray(e.manifestDirs)?e.manifestDirs.length:void 0,hasHeaders:!!e.headers,toolPrefix:e.toolPrefix}}async function vn(){let e=ln(),t=await cn(),n=parseInt(process.env.LARKPAL_AGENT_MAX_TURNS||`25`,10),r=un(),i=fn(r),a=dn();I.info(`创建 LarkpalAgentAdapter`,{baseURL:e.baseURL,model:e.defaultModel,maxTurns:n,mcpTimeoutMs:a,scenarioProvider:_n(i)});let{LarkpalAgentAdapter:o,ToolRegistry:s}=await import(`@vibe-lark/larkpal-agent`),c=new s,l=parseInt(process.env.LARKPAL_AGENT_VISUAL_MAX_BATCH_SIZE||`3`,10),u=new o({llm:e,systemPrompt:t,tools:[],defaultMaxTurns:n,registry:c,scenarioManifestDirs:r,scenarioProviderConfig:i,artifactResolvers:[yn()],visualRuntime:{maxBatchSize:l,allowedDirs:[process.env.LARK_CLI_WORKDIR||`/tmp/ai-knowledge-lark-cli`,`/tmp`].filter(Boolean)}}),d=process.env.LARKPAL_AGENT_MCP_SERVER_URL;if(d)try{let e=await c.connectMcpServer(d,{timeoutMs:a}),t=c.getAll();u.registerTools(t),I.info(`MCP 工具注册完成`,{serverUrl:d,timeoutMs:a,toolCount:e,toolNames:t.map(e=>e.name)})}catch(e){I.error(`MCP Server 连接失败,Agent 将无法使用远程工具`,{serverUrl:d,error:e?.message})}else I.warn(`未配置 LARKPAL_AGENT_MCP_SERVER_URL,Agent 无远程工具可用`);return bn(u)}function yn(e){let t=e?.store||new Qt;return{name:`larkpal-gateway-artifact-store`,canResolve(e){return xn(e)!==void 0},async resolve(e,n){let r=xn(e),i=n.tenantKey||n.authHeaders?.[`x-tenant-key`],a=n.userId||n.authHeaders?.[`x-user-id`],o=n.authHeaders?.[`x-open-id`]||a;if(!r||!i||!a||!o)return;let s=await t.resolveBlob({sessionId:n.sessionId,artifactId:r,owner:{tenantKey:i,userId:a,openId:o}});if(!s)return;let c=d(n.cwd,`source-artifacts`,r),l=Sn(s.ref.fileName||e.fileName||r),u=d(c,l);return await h(c,{recursive:!0}),await m(s.blobPath,u),{artifactId:r,kind:`workspace-file`,path:u,fileName:l,mimeType:s.ref.mimeType??e.mimeType,size:s.ref.size??e.size,contentHash:s.ref.contentHash??e.contentHash,source:e,refs:{uri:s.ref.uri,gatewayArtifactId:s.ref.artifactId}}}}}function bn(e){return{get name(){return e.name},executePrompt(t,n){return e.executePrompt(t,n)},stopProcess(t){return e.stopProcess(t)},stopAll(){return e.stopAll()},getProcessInfo(t){return e.getProcessInfo(t)},getAllProcessInfo(){return e.getAllProcessInfo()},isSessionBusy(t){return e.isSessionBusy?.(t)??!1}}}function xn(e){let t=typeof e.artifactId==`string`?e.artifactId.trim():``;if(t.startsWith(`art_`))return t;let n=typeof e.uri==`string`?e.uri.trim():``;if(!n.startsWith(`artifact://`))return;let r=n.slice(11).split(/[/?#]/,1)[0]?.trim();return r?.startsWith(`art_`)?r:void 0}function Sn(e){return c(e).replace(/[\\/\0\r\n]/g,`_`).trim()||`artifact.bin`}const Cn=t(`runtime/factory`);async function wn(e){let t=process.env.LARKPAL_RUNTIME||e,n;n=t===`larkpal-agent`?await vn():t===`codex-app-server`?new St:new ut;let r=n.name===`codex-app-server`?process.env.LARKPAL_CODEX_MODEL||process.env.CODEX_MODEL||void 0:process.env.CLAUDE_MODEL||void 0;return Cn.info(`Runtime adapter created`,{requestedRuntime:t,adapter:n.name,model:r??`(default)`}),{adapter:n,runtimeName:t,model:r}}const Tn=`<!-- LARKPAL_RUNTIME_INSTRUCTIONS_START -->`,En=`<!-- LARKPAL_RUNTIME_INSTRUCTIONS_END -->`;function Dn(e){let t=On(e.instructions),n=kn(e.skills);if(!(t.length===0&&n.length===0))return{instructions:t.length>0?An(e.cwd,t):[],skills:n.map(t=>Mn(e.cwd,t))}}function On(e){return Array.isArray(e)?e.map(e=>{if(!e||typeof e!=`object`||Array.isArray(e))return null;let t=e,n=L(t.id),r=L(t.content);return!n||!r?null:{id:n,content:r,scope:Ln(t.scope),version:L(t.version)}}).filter(e=>e!=null):[]}function kn(e){return Array.isArray(e)?e.map(e=>{if(!e||typeof e!=`object`||Array.isArray(e))return null;let t=e,n=L(t.id),r=L(t.content)||L(t.skillMarkdown);return!n||!r?null:{id:n,content:r,scope:Ln(t.scope),version:L(t.version),name:L(t.name),description:L(t.description)}}).filter(e=>e!=null):[]}function An(e,t){let n=[Tn,`# LarkPal Runtime Instructions`,``,`The following instructions were injected by LarkPal for this agent session. Treat them as runtime context, not as user message content.`,``,...t.flatMap(e=>[`## ${e.id}`,``,e.content.trim(),``]),En,``].join(`
|
|
18
|
-
`);return jn(
|
|
15
|
+
`)).digest(`hex`)}function Tt(e){return e.match(/Your Feishu-facing name is 「([^」]+)」/)?.[1]?.trim()||e.match(/你的名字是「([^」]+)」/)?.[1]?.trim()||void 0}function Et(e){let t=e.split(`/`)[1]?.toLowerCase();if(!t)return`.png`;if(t===`jpeg`)return`.jpg`;let n=`.${t}`;return d(`x${n}`)?n:`.png`}function Dt(e){return JSON.stringify(e)}function Ot(e){return`[${e.map(Dt).join(`, `)}]`}function kt(e){return`{ ${Object.entries(e).map(([e,t])=>`${e} = ${Dt(t)}`).join(`, `)} }`}function At(){let e=u(m(import.meta.url)),t=p(e,`mcp-server.mjs`);if(i(t))return{command:`node`,args:[t]};let n=p(e,`..`,`dist`,`mcp-server.mjs`);if(i(n))return{command:`node`,args:[n]};let r=p(e,`..`,`mcp-server`,`index.ts`);return i(r)?{command:`npx`,args:[`tsx`,r]}:{command:`node`,args:[t]}}function jt(e){if(!e)return!1;if(Array.isArray(e))return e.some(e=>jt(e));if(typeof e!=`object`)return!1;let t=e;return t.type===`image`||t.type===`localImage`||t.type===`input_image`?!0:Object.values(t).some(e=>jt(e))}function Mt(e){let t=Pt(e)??e;return Nt(t)?_t([`当前 Codex 模型不支持图片输入。`,``,`这条消息包含图片,但当前模型返回了图片能力错误。请改用支持视觉输入的模型,或先用文字描述图片内容后再试。`].join(`
|
|
16
|
+
`),t):Error(t)}function Nt(e){let t=Pt(e)??e;return/does not support image inputs|image inputs|vision model/i.test(t)}function Pt(e){let t=e.trim();if(t.startsWith(`{`))try{let e=JSON.parse(t),n=P(e,[`error`,`message`])??P(e,[`message`]);return typeof n==`string`&&n.trim()?n.trim():void 0}catch{return}}function Ft(e){let t=[P(e,[`message`]),P(e,[`error`,`message`]),P(e,[`data`,`message`]),P(e,[`error`,`data`,`message`]),P(e,[`reason`]),P(e,[`error`,`reason`])];for(let e of t)if(typeof e==`string`&&e.trim())return e.trim()}function It(e){return!e||typeof e!=`object`?!1:e.willRetry===!0}function Lt(e,t){if(It(e))return!1;let n=[t,P(e,[`error`,`additionalDetails`]),P(e,[`additionalDetails`]),P(e,[`error`,`codexErrorInfo`]),P(e,[`codexErrorInfo`])].map(e=>typeof e==`string`?e:JSON.stringify(e??``)).join(`
|
|
17
|
+
`);return/responseStreamDisconnected|stream disconnected before completion|stream closed before response\.completed|max_output_tokens/i.test(n)}function Rt(e){if(!e)return;let t=Number.parseInt(e,10);return Number.isFinite(t)&&t>0?t:void 0}function zt(e){if(!e)return;let t=Number.parseFloat(e);return Number.isFinite(t)&&t>0?t:void 0}function Bt(){return Rt(process.env.LARKPAL_CODEX_COMPACT_TIMEOUT_MS)??bt}function Vt(e){let t=P(e,[`turn`,`id`]);return typeof t==`string`?t:void 0}function Ht(e){let t=P(e,[`turn`,`status`]);return typeof t==`string`&&[`completed`,`failed`,`interrupted`].includes(t)}function Ut(e,t,n){let r,i=new Promise((e,i)=>{r=setTimeout(()=>i(Error(n)),t)});return Promise.race([e,i]).finally(()=>{r&&clearTimeout(r)})}function Wt(e){return Gt(e,0)}function P(e,t){let n=e;for(let e of t){if(!n||typeof n!=`object`||!(e in n))return;n=n[e]}return n}function Gt(e,t){if(typeof e==`string`)return e.length>2e3?`${e.slice(0,2e3)}...[truncated ${e.length-2e3} chars]`:e;if(typeof e!=`object`||!e)return e;if(t>=6)return`[truncated: max depth]`;if(Array.isArray(e)){let n=e.slice(0,20).map(e=>Gt(e,t+1));return e.length>20&&n.push(`[truncated ${e.length-20} items]`),n}let n=Object.entries(e),r={};for(let[e,i]of n.slice(0,50))r[e]=Gt(i,t+1);return n.length>50&&(r.__truncatedKeys=n.length-50),r}function Kt(e){let t=new Set,n=0,r=0;for(let i of e.split(/\r?\n/)){let e=/^diff --git a\/(.+?) b\/(.+)$/.exec(i);if(e){t.add(e[2]);continue}let a=/^\+\+\+ b\/(.+)$/.exec(i);if(a&&a[1]!==`/dev/null`){t.add(a[1]);continue}let o=/^--- a\/(.+)$/.exec(i);if(o&&o[1]!==`/dev/null`){t.add(o[1]);continue}i.startsWith(`+`)&&!i.startsWith(`+++`)&&(n+=1),i.startsWith(`-`)&&!i.startsWith(`---`)&&(r+=1)}return{filesChanged:Array.from(t),insertions:n,deletions:r}}function F(e,t,n){return{ok:!1,sessionId:e,messageId:t,filesChanged:[],insertions:0,deletions:0,error:n}}function qt(e,t,n){return new Promise((r,i)=>{let a=[`apply`,`-R`];n&&a.push(`--check`);let o=ie(`git`,a,{cwd:e,stdio:[`pipe`,`pipe`,`pipe`]}),s=``;o.stderr?.on(`data`,e=>{s+=String(e)}),o.on(`error`,i),o.on(`close`,e=>{e===0?r():i(Error(s.trim()||`git ${a.join(` `)} failed with exit code ${e}`))}),o.stdin.end(t)})}let Jt=null;function Yt(e){Jt=e}function Xt(){return Jt}var Zt=class extends Error{constructor(e,t=400){super(e),this.statusCode=t,this.name=`ArtifactUploadError`}},Qt=class{rootDir;maxUploadBytes;ttlMs;constructor(e){let t=e?.workspaceRoot||E();this.rootDir=f(t,`.artifacts`),this.maxUploadBytes=e?.maxUploadBytes??$t(`LARKPAL_ARTIFACT_MAX_UPLOAD_BYTES`,52428800),this.ttlMs=e?.ttlMs??$t(`LARKPAL_ARTIFACT_TTL_MS`,2592e5)}async create(e){I(e.sessionId,`sessionId`),I(e.owner.tenantKey,`tenantKey`);let t=`art_${T().replace(/-/g,``)}`,n=Date.now(),i=new Date(n).toISOString(),a=new Date(n+this.ttlMs).toISOString(),o=this.getArtifactDir(e.owner.tenantKey,e.sessionId,t),s=f(o,`blob`),c=f(o,`.blob.${process.pid}.${Date.now()}.tmp`);await g(o,{recursive:!0});let l=ae(`sha256`),u=0,d=new ge({transform:(e,t,n)=>{if(u+=e.length,u>this.maxUploadBytes){n(new Zt(`Artifact exceeds max upload size ${this.maxUploadBytes} bytes`,413));return}l.update(e),n(null,e)}});try{await he(e.stream,d,r(c)),await y(c,s)}catch(e){throw await b(o,{recursive:!0,force:!0}).catch(()=>void 0),e}let p={artifactId:t,sessionId:e.sessionId,tenantKey:e.owner.tenantKey,userId:e.owner.userId,openId:e.owner.openId,kind:`workspace-file`,uri:`artifact://${t}`,fileName:en(e.fileName),mimeType:tn(e.mimeType),size:u,contentHash:`sha256:${l.digest(`hex`)}`,createdAt:i,expiresAt:a,metadata:e.metadata,blobPath:s};return await on(f(o,`meta.json`),p),nn(p)}async list(e){I(e.sessionId,`sessionId`),I(e.owner.tenantKey,`tenantKey`);let t=this.getSessionDir(e.owner.tenantKey,e.sessionId),n;try{n=await v(t)}catch{return[]}let r=[];for(let i of n){if(!i.startsWith(`art_`))continue;let n=await an(f(t,i,`meta.json`));n&&rn(n,e.owner,e.sessionId)&&(Date.parse(n.expiresAt)<=Date.now()||r.push(nn(n)))}return r.sort((e,t)=>e.createdAt.localeCompare(t.createdAt))}async statBlob(e,t){let n=await an(this.getMetadataPath(t.tenantKey,e.sessionId,e.artifactId));if(!n||!rn(n,t,e.sessionId))return null;let r=await ee(n.blobPath).catch(()=>null);return r?{path:n.blobPath,size:r.size}:null}async resolveBlob(e){I(e.sessionId,`sessionId`),I(e.owner.tenantKey,`tenantKey`),I(e.artifactId,`artifactId`);let t=await an(this.getMetadataPath(e.owner.tenantKey,e.sessionId,e.artifactId));return!t||!rn(t,e.owner,e.sessionId)||Date.parse(t.expiresAt)<=Date.now()||!await ee(t.blobPath).catch(()=>null)?null:{ref:nn(t),blobPath:t.blobPath}}getSessionDir(e,t){return f(this.rootDir,e,t)}getArtifactDir(e,t,n){return f(this.getSessionDir(e,t),n)}getMetadataPath(e,t,n){return f(this.getArtifactDir(e,t,n),`meta.json`)}};function $t(e,t){let n=process.env[e];if(!n)return t;let r=Number.parseInt(n,10);return Number.isFinite(r)&&r>0?r:t}function I(e,t){if(!/^[A-Za-z0-9_.:-]{1,200}$/.test(e))throw new Zt(`Invalid ${t}`,400)}function en(e){return e.replace(/[\\/\0\r\n]/g,`_`).trim()||`upload.bin`}function tn(e){return e?.trim()||`application/octet-stream`}function nn(e){let{tenantKey:t,userId:n,openId:r,blobPath:i,...a}=e;return a}function rn(e,t,n){return e.tenantKey===t.tenantKey&&e.userId===t.userId&&e.openId===t.openId&&e.sessionId===n}async function an(e){try{return JSON.parse(await _(e,`utf-8`))}catch{return null}}async function on(e,t){await g(u(e),{recursive:!0}),await S(e,JSON.stringify(t,null,2),`utf-8`)}const L=t(`runtime/larkpal-agent-factory`),sn=f(C(),`.claude`,`CLAUDE.md`);async function cn(){try{let e=await _(sn,`utf-8`);return L.info(`systemPrompt 加载成功`,{path:sn,length:e.length}),e}catch{return L.warn(`systemPrompt 文件不存在,使用默认`,{path:sn}),`你是一个 AI 助手,帮助用户完成飞书知识管理任务。`}}function ln(){let e=process.env.LARKPAL_AGENT_LLM_BASE_URL,t=process.env.LARKPAL_AGENT_LLM_API_KEY,n=process.env.LARKPAL_AGENT_LLM_MODEL;if(!e||!t||!n)throw Error(`larkpal-agent 需要配置 LLM 环境变量: LARKPAL_AGENT_LLM_BASE_URL, LARKPAL_AGENT_LLM_API_KEY, LARKPAL_AGENT_LLM_MODEL`);return{baseURL:e,apiKey:t,defaultModel:n}}function un(){return(process.env.LARKPAL_AGENT_SCENARIO_DIRS||``).split(`:`).map(e=>e.trim()).filter(Boolean)}function dn(e=process.env){let t=e.LARKPAL_AGENT_MCP_TIMEOUT_MS;if(t==null||t.trim()===``)return 1e4;let n=Number.parseInt(t,10);if(!Number.isFinite(n)||!/^\d+$/.test(t.trim())||n<=0)throw Error(`LARKPAL_AGENT_MCP_TIMEOUT_MS 必须是正整数毫秒值`);return n}function fn(e){let t=process.env.LARKPAL_AGENT_SCENARIO_PROVIDER_CONFIG;if(t){let e=hn(t);if(!e.type)throw Error(`LARKPAL_AGENT_SCENARIO_PROVIDER_CONFIG 缺少必填字段 type`);return pn(e)}let n=process.env.LARKPAL_AGENT_SCENARIO_PROVIDER_TYPE;if(!(!n&&e.length===0)){if(!n||n===`local`)return{type:`local`,manifestDirs:e,dirs:e};if(n===`http`){let e=process.env.LARKPAL_AGENT_SCENARIO_PROVIDER_BASE_URL||process.env.LARKPAL_AGENT_SCENARIO_PROVIDER_URL||process.env.AI_KNOWLEDGE_SCENARIO_PROVIDER_BASE_URL;if(!e)throw Error(`LARKPAL_AGENT_SCENARIO_PROVIDER_TYPE=http 时必须配置 LARKPAL_AGENT_SCENARIO_PROVIDER_BASE_URL`);let t=mn(e);return{type:n,baseURL:t,baseUrl:t,headers:gn(`LARKPAL_AGENT_SCENARIO_PROVIDER_HEADERS`)}}return n===`mcp`?{type:n,toolPrefix:process.env.LARKPAL_AGENT_SCENARIO_PROVIDER_MCP_TOOL_PREFIX}:{type:n}}}function pn(e){if(e.type!==`http`)return e;let t=typeof e.baseURL==`string`?e.baseURL:typeof e.baseUrl==`string`?e.baseUrl:void 0;if(!t)return e;let n=mn(t);return{...e,baseURL:n,baseUrl:n}}function mn(e){let t=e.trim().replace(/\/+$/,``);return t.toLowerCase().endsWith(`/api/scenario-manifests`)&&t.slice(0,-23)||t}function hn(e){try{let t=JSON.parse(e);if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`config must be a JSON object`);return t}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`LARKPAL_AGENT_SCENARIO_PROVIDER_CONFIG 不是合法 JSON 对象: ${t}`,{cause:e})}}function gn(e){let t=process.env[e];if(!t)return;let n=JSON.parse(t);if(!n||typeof n!=`object`||Array.isArray(n))throw Error(`${e} 必须是 JSON object`);let r={};for(let[e,t]of Object.entries(n))typeof t==`string`&&(r[e]=t);return r}function _n(e){if(e)return{type:e.type,baseURL:e.baseURL||e.baseUrl,manifestDirCount:Array.isArray(e.manifestDirs)?e.manifestDirs.length:void 0,hasHeaders:!!e.headers,toolPrefix:e.toolPrefix}}async function vn(){let e=ln(),t=await cn(),n=parseInt(process.env.LARKPAL_AGENT_MAX_TURNS||`25`,10),r=un(),i=fn(r),a=dn();L.info(`创建 LarkpalAgentAdapter`,{baseURL:e.baseURL,model:e.defaultModel,maxTurns:n,mcpTimeoutMs:a,scenarioProvider:_n(i)});let{LarkpalAgentAdapter:o,ToolRegistry:s}=await import(`@vibe-lark/larkpal-agent`),c=new s,l=parseInt(process.env.LARKPAL_AGENT_VISUAL_MAX_BATCH_SIZE||`3`,10),u=new o({llm:e,systemPrompt:t,tools:[],defaultMaxTurns:n,registry:c,scenarioManifestDirs:r,scenarioProviderConfig:i,artifactResolvers:[yn()],visualRuntime:{maxBatchSize:l,allowedDirs:[process.env.LARK_CLI_WORKDIR||`/tmp/ai-knowledge-lark-cli`,`/tmp`].filter(Boolean)}}),d=process.env.LARKPAL_AGENT_MCP_SERVER_URL;if(d)try{let e=await c.connectMcpServer(d,{timeoutMs:a}),t=c.getAll();u.registerTools(t),L.info(`MCP 工具注册完成`,{serverUrl:d,timeoutMs:a,toolCount:e,toolNames:t.map(e=>e.name)})}catch(e){L.error(`MCP Server 连接失败,Agent 将无法使用远程工具`,{serverUrl:d,error:e?.message})}else L.warn(`未配置 LARKPAL_AGENT_MCP_SERVER_URL,Agent 无远程工具可用`);return bn(u)}function yn(e){let t=e?.store||new Qt;return{name:`larkpal-gateway-artifact-store`,canResolve(e){return xn(e)!==void 0},async resolve(e,n){let r=xn(e),i=n.tenantKey||n.authHeaders?.[`x-tenant-key`],a=n.userId||n.authHeaders?.[`x-user-id`],o=n.authHeaders?.[`x-open-id`]||a;if(!r||!i||!a||!o)return;let s=await t.resolveBlob({sessionId:n.sessionId,artifactId:r,owner:{tenantKey:i,userId:a,openId:o}});if(!s)return;let c=f(n.cwd,`source-artifacts`,r),l=Sn(s.ref.fileName||e.fileName||r),u=f(c,l);return await g(c,{recursive:!0}),await h(s.blobPath,u),{artifactId:r,kind:`workspace-file`,path:u,fileName:l,mimeType:s.ref.mimeType??e.mimeType,size:s.ref.size??e.size,contentHash:s.ref.contentHash??e.contentHash,source:e,refs:{uri:s.ref.uri,gatewayArtifactId:s.ref.artifactId}}}}}function bn(e){return{get name(){return e.name},executePrompt(t,n){return e.executePrompt(t,n)},stopProcess(t){return e.stopProcess(t)},stopAll(){return e.stopAll()},getProcessInfo(t){return e.getProcessInfo(t)},getAllProcessInfo(){return e.getAllProcessInfo()},isSessionBusy(t){return e.isSessionBusy?.(t)??!1}}}function xn(e){let t=typeof e.artifactId==`string`?e.artifactId.trim():``;if(t.startsWith(`art_`))return t;let n=typeof e.uri==`string`?e.uri.trim():``;if(!n.startsWith(`artifact://`))return;let r=n.slice(11).split(/[/?#]/,1)[0]?.trim();return r?.startsWith(`art_`)?r:void 0}function Sn(e){return l(e).replace(/[\\/\0\r\n]/g,`_`).trim()||`artifact.bin`}const Cn=t(`runtime/factory`);async function wn(e){let t=n({defaultRuntime:e===`codex-app-server`||e===`larkpal-agent`||e===`claude-code`?e:`claude-code`}),r;r=t===`larkpal-agent`?await vn():t===`codex-app-server`?new St:new ut;let i=r.name===`codex-app-server`?process.env.LARKPAL_CODEX_MODEL||process.env.CODEX_MODEL||void 0:process.env.CLAUDE_MODEL||void 0;return Cn.info(`Runtime adapter created`,{requestedRuntime:t,adapter:r.name,model:i??`(default)`}),{adapter:r,runtimeName:t,model:i}}const Tn=`<!-- LARKPAL_RUNTIME_INSTRUCTIONS_START -->`,En=`<!-- LARKPAL_RUNTIME_INSTRUCTIONS_END -->`;function Dn(e){let t=On(e.instructions),n=kn(e.skills);if(!(t.length===0&&n.length===0))return{instructions:t.length>0?An(e.cwd,t):[],skills:n.map(t=>Mn(e.cwd,t))}}function On(e){return Array.isArray(e)?e.map(e=>{if(!e||typeof e!=`object`||Array.isArray(e))return null;let t=e,n=R(t.id),r=R(t.content);return!n||!r?null:{id:n,content:r,scope:Ln(t.scope),version:R(t.version)}}).filter(e=>e!=null):[]}function kn(e){return Array.isArray(e)?e.map(e=>{if(!e||typeof e!=`object`||Array.isArray(e))return null;let t=e,n=R(t.id),r=R(t.content)||R(t.skillMarkdown);return!n||!r?null:{id:n,content:r,scope:Ln(t.scope),version:R(t.version),name:R(t.name),description:R(t.description)}}).filter(e=>e!=null):[]}function An(e,t){let n=[Tn,`# LarkPal Runtime Instructions`,``,`The following instructions were injected by LarkPal for this agent session. Treat them as runtime context, not as user message content.`,``,...t.flatMap(e=>[`## ${e.id}`,``,e.content.trim(),``]),En,``].join(`
|
|
18
|
+
`);return jn(f(e,`CLAUDE.md`),n),jn(f(e,`AGENTS.md`),n.replace(Tn,`<!-- LARKPAL_RUNTIME_INSTRUCTIONS_START -->`).replace(En,`<!-- LARKPAL_RUNTIME_INSTRUCTIONS_END -->`)),t.map(e=>({id:e.id,scope:e.scope??`request`,hash:Fn(e.content),version:e.version,path:`CLAUDE.md,AGENTS.md`}))}function jn(e,t){let n=Pn(i(e)?o(e,`utf-8`):``,t);a(u(e),{recursive:!0}),s(e,n,`utf-8`)}function Mn(e,t){let n=`.claude/skills/${In(t.id)}/SKILL.md`,r=f(e,n),i=Nn(t);return a(u(r),{recursive:!0}),s(r,i,`utf-8`),{id:t.id,scope:t.scope??`request`,hash:Fn(i),version:t.version,path:n}}function Nn(e){let t=e.content.trim();if(t.startsWith(`---`))return`${t}\n`;let n=e.name||e.id,r=e.description||`Runtime skill injected by LarkPal: ${e.id}`;return[`---`,`name: ${Rn(n)}`,`description: ${Rn(r)}`,`---`,``,t,``].join(`
|
|
19
19
|
`)}function Pn(e,t){let n=e.indexOf(Tn),r=e.indexOf(En);if(n!==-1&&r!==-1&&r>n){let i=e.slice(0,n).trimEnd(),a=e.slice(r+41).trimStart();return[i,t.trimEnd(),a].filter(Boolean).join(`
|
|
20
20
|
|
|
21
21
|
`)+`
|
|
22
22
|
`}return[e.trimEnd(),t.trimEnd()].filter(Boolean).join(`
|
|
23
23
|
|
|
24
24
|
`)+`
|
|
25
|
-
`}function Fn(e){return`sha256:${ae(`sha256`).update(e).digest(`hex`)}`}function In(e){return e.replace(/[^A-Za-z0-9._-]/g,`_`).replace(/^\.+$/,`skill`)||`skill`}function L(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function Ln(e){return e===`app`||e===`session`||e===`request`?e:`request`}function Rn(e){return JSON.stringify(e)}const zn=/(authorization|cookie|token|api[-_]?key|secret|password|credential)/i,Bn=/^(file[-_]?token|drive[-_]?file[-_]?token|doc[-_]?token|sheet[-_]?token|wiki[-_]?token|node[-_]?token)$/i,Vn=new Set([`x-tenant-key`,`x-user-id`,`x-open-id`,`x-user-name`,`x-session-id`,`x-conversation-id`,`x-trace-id`,`x-request-id`]);function Hn(e){return rr(e,`x-request-id`)||w()}function Un(e,t){return rr(e,`x-trace-id`)||t}function Wn(e,t){let n=t?.scenarioId??t?.scenario_id;if(typeof e==`string`&&e.trim().length>0)return e.trim();if(typeof n==`string`&&n.trim().length>0)return n.trim()}function Gn(){return T()}function Kn(e,t){let n=t||d(Gn(),`.sessions`,e);return i(n,{recursive:!0}),n}function R(e){let t=e.requestId||w(),n=B(e.sessionId,`sessionId`),r=B(e.traceId||t,`traceId`),i=B(e.conversationId||n,`conversationId`),a=B(e.identity?.tenantKey,`tenantKey`),o=B(e.identity?.userId||e.identity?.openId,`userId`),s=Wn(e.scenarioId,e.metadata),c=Kn(n,e.cwd),l=Dn({cwd:c,instructions:e.runtimeInstructions,skills:e.runtimeSkills}),u=ir(e.metadata,{conversationId:i,traceId:r,entrypoint:e.entrypoint,scenarioId:s,runtimeContext:l}),d=er({tenantKey:a,userId:o,openId:e.identity?.openId,userName:e.identity?.userName,sessionId:n,conversationId:i,traceId:r,requestId:t,explicitHeaders:e.authHeaders}),f=tr(e.policy,{maxTurns:e.maxTurns,maxBudgetUsd:e.maxBudgetUsd,allowSignalNoReplyTool:e.allowSignalNoReplyTool}),p=nr(e.identity),m={requestId:t,sessionId:n,conversationId:i,traceId:r,entrypoint:e.entrypoint,scenarioId:s,tenantKey:a,userId:o,openId:e.identity?.openId,userName:e.identity?.userName,cwd:c,authHeaders:d,attachments:e.attachments,sourceArtifacts:e.sourceArtifacts,runtimeContext:l,llmConfig:e.llmConfig,policy:f,metadata:u};return{requestId:t,sessionId:n,cwd:c,prompt:e.prompt,maxTurns:e.maxTurns??f.maxTurns,maxBudgetUsd:e.maxBudgetUsd??f.maxBudgetUsd,model:e.model,transcriptMode:e.transcriptMode,userContext:p,tenantContext:{tenantKey:a},authHeaders:d,attachments:e.attachments,sourceArtifacts:e.sourceArtifacts,runtimeContext:l,llmConfig:e.llmConfig,policy:f,requestContext:m,runContext:{tenantKey:a,userId:o,sessionId:n,conversationId:i,traceId:r,requestId:t,entrypoint:e.entrypoint,scenarioId:s,authHeaders:d,metadata:u},metadata:u}}function qn(...e){return e.find(e=>e!==void 0)}function z(e){if(e==null)return e;if(typeof e==`string`)return or(e);if(typeof e==`number`||typeof e==`boolean`)return e;if(Array.isArray(e))return{type:`array`,length:e.length,sample:e.slice(0,5).map(e=>z(e))};if(typeof e==`object`){let t={};for(let[n,r]of Object.entries(e))zn.test(n)&&!Bn.test(n)?t[n]=`[redacted]`:t[n]=z(r);return t}return String(e)}function Jn(e,t,n){let r=ar(e,n?.metadata);return{id:w(),requestId:e.requestId,sessionId:e.sessionId,tenantKey:e.tenantKey,userId:e.userId,type:t,timestamp:new Date().toISOString(),...n,...r?{metadata:r}:{}}}function Yn(e){return{...e,inputSummary:z(e.inputSummary)}}function Xn(e){if(!e)return;let t={toolResult:z(e)};for(let n of[`ok`,`exitCode`,`isError`,`errorCode`,`reasonCode`])e[n]!==void 0&&(t[n]=e[n]);return t}function Zn(e){let t={verifierResult:z(e)};for(let n of[`ok`,`status`,`reasonCode`])e[n]!==void 0&&(t[n]=e[n]);return e.failedGates&&(t.failedGates=z(e.failedGates)),e.missingArtifacts&&(t.missingArtifacts=z(e.missingArtifacts)),t}function Qn(e){let t={};return e.attachments!==void 0&&(t.attachments=z(e.attachments)),e.sourceArtifacts!==void 0&&(t.sourceArtifacts=z(e.sourceArtifacts)),e.runtimeContext!==void 0&&(t.runtimeContext=e.runtimeContext),t}function $n(e){let t={runtimeEventType:e.type,runtimeEvent:z(e)};for(let n of[`scenarioId`,`traceId`,`phaseId`,`artifactName`,`artifactNames`,`capabilityId`,`repairActionId`,`repairAttempt`,`targetPhase`,`requiredNextPhases`,`plannerInstruction`,`reasonCode`,`verifierReasonCode`,`missingPhases`,`failedGates`,`missingArtifacts`,`status`,`finalStatus`])e[n]!==void 0&&(t[n]=z(e[n]));return t}function er(e){let t={"x-tenant-key":e.tenantKey,"x-user-id":e.userId,...e.openId?{"x-open-id":e.openId}:{},...e.userName?{"x-user-name":e.userName}:{},"x-session-id":e.sessionId,"x-conversation-id":e.conversationId,"x-trace-id":e.traceId,"x-request-id":e.requestId};for(let[n,r]of Object.entries(e.explicitHeaders||{})){let e=n.toLowerCase();e.startsWith(`x-`)&&!zn.test(e)&&!Vn.has(e)&&(t[e]=r)}return t}function tr(e,t){let n={allowedTools:e?.allowedTools??[],disallowedTools:e?.disallowedTools,allowedSkills:e?.allowedSkills??[],disallowedSkills:e?.disallowedSkills,maxTurns:t.maxTurns??e?.maxTurns,maxToolCalls:e?.maxToolCalls,maxRuntimeMs:e?.maxRuntimeMs,maxBudgetUsd:t.maxBudgetUsd??e?.maxBudgetUsd,turnPolicy:e?.turnPolicy};return t.allowSignalNoReplyTool?n:Ce(n,`signal_no_reply`)}function nr(e){if(!e?.userId&&!e?.openId)return;let t=e.userId||e.openId;if(t)return{userId:t,openId:e.openId||t,userName:e.userName||t,credentialDir:e.credentialDir||d(Gn(),`users`,t),isTenantIdentity:e.isTenantIdentity??!1}}function rr(e,t){let n=t.toLowerCase(),r=e[t]??e[n],i=Array.isArray(r)?r[0]:r;if(typeof i!=`string`)return;let a=i.trim();return a.length>0?a:void 0}function B(e,t){if(typeof e==`string`&&e.trim().length>0)return e.trim();throw Error(`Agent run context missing required field: ${t}`)}function ir(e,t){return{...e,conversationId:t.conversationId,traceId:t.traceId,entrypoint:t.entrypoint,...t.scenarioId?{scenarioId:t.scenarioId}:{},...t.runtimeContext?{runtimeContext:t.runtimeContext}:{}}}function ar(e,t){let n={...e.conversationId?{conversationId:e.conversationId}:{},...e.traceId?{traceId:e.traceId}:{},...e.entrypoint?{entrypoint:e.entrypoint}:{},...e.scenarioId?{scenarioId:e.scenarioId}:{},...t};return Object.keys(n).length>0?n:void 0}function or(e){return e.length<=200?e:{type:`string`,length:e.length,preview:e.slice(0,200)}}const sr=t(`memory/store`),cr=1e3,lr=/(api[-_ ]?key|secret|password|bearer\s+[a-z0-9._-]+|sk-[a-z0-9]|token\s*[:=])/i,ur=new Set([`fact`,`preference`,`decision`,`recurring_context`]);var dr=class e{static updateLocks=new Map;getMemoryPath(e){return d(e,`.larkpal`,`memory.json`)}async load(e){let t=this.getMemoryPath(e);if(!r(t))return fr();try{let e=await g(t,`utf-8`);return pr(JSON.parse(e))}catch(n){return sr.warn(`memory file load failed, using empty state`,{cwd:e,path:t,error:n instanceof Error?n.message:String(n)}),fr()}}async save(e,t){await this.withMemoryLock(e,()=>this.writeMemoryFile(e,t))}async writeMemoryFile(e,t){let n=this.getMemoryPath(e);await h(l(n),{recursive:!0});let r=pr(t),i=`${n}.${process.pid}.${Date.now()}.tmp`;await x(i,JSON.stringify(r,null,2),`utf-8`),await v(i,n)}async propose(e,t){let n=t.kind;if(!ur.has(n))return{accepted:!1,reasonCode:`invalid_kind`};let r=V(t.text,cr);return r?lr.test(r)?{accepted:!1,reasonCode:`sensitive`}:this.withMemoryLock(e,async()=>{let i=await this.load(e);i.longTerm=vr(i.longTerm);let a=_r(n,r),o=i.longTerm.find(e=>_r(e.kind,e.text)===a);if(o)return{accepted:!1,id:o.id,reasonCode:`duplicate`};let s=new Date().toISOString(),c=typeof t.ttlDays==`number`&&t.ttlDays>0?t.ttlDays:void 0,l={id:C(),kind:n,text:r,source:V(t.source||t.reason||`agent_proposal`,160)||`agent_proposal`,confidence:gr(t.confidence),tags:H(t.tags,48,12),sourceRefs:H(t.sourceRefs,160,12),createdAt:s,updatedAt:s,...c?{expiresAt:new Date(Date.now()+c*24*60*60*1e3).toISOString()}:{}};return i.longTerm.push(l),i.longTerm=yr(i.longTerm),await this.writeMemoryFile(e,i),{accepted:!0,id:l.id}}):{accepted:!1,reasonCode:`empty`}}async search(e,t){let n=await this.load(e),r=t.query||``,i=t.kinds?.filter(e=>ur.has(e)),a=Math.max(1,Math.min(t.limit??8,20));return xr(vr(n.longTerm),r,i).slice(0,a)}async appendTeammateSummary(e,t){return this.withMemoryLock(e,async()=>{let n=await this.load(e),r={id:C(),decision:t.decision,summary:V(t.summary,600)||`(empty)`,messageCount:Math.max(0,t.messageCount),sourceRefs:H(t.sourceRefs,160,12),createdAt:new Date().toISOString()};return n.working.teammateRecent.push(r),n.working.teammateRecent=n.working.teammateRecent.slice(-3),await this.writeMemoryFile(e,n),r})}async withMemoryLock(t,n){let r=this.getMemoryPath(t),i=e.updateLocks.get(r)??Promise.resolve(),a=()=>{},o=new Promise(e=>{a=e}),s=i.catch(()=>void 0).then(()=>o);e.updateLocks.set(r,s),await i.catch(()=>void 0);try{return await n()}finally{a(),e.updateLocks.get(r)===s&&e.updateLocks.delete(r)}}};function fr(){return{version:1,working:{teammateRecent:[]},longTerm:[]}}function pr(e){let t=fr(),n=Array.isArray(e.working?.teammateRecent)?e.working.teammateRecent.filter(e=>!!e&&typeof e.summary==`string`).map(e=>({id:String(e.id||C()),decision:e.decision===`HANDOFF_TO_MAIN`?`HANDOFF_TO_MAIN`:`NO_REPLY`,summary:V(e.summary,600)||`(empty)`,messageCount:Math.max(0,Number(e.messageCount)||0),sourceRefs:H(e.sourceRefs,160,12),createdAt:typeof e.createdAt==`string`?e.createdAt:new Date().toISOString()})).slice(-3):[],r=Array.isArray(e.longTerm)?yr(vr(br(e.longTerm.filter(mr).map(hr).filter(e=>e!==null)))):[];return{...t,working:{teammateRecent:n},longTerm:r}}function mr(e){return!!e&&typeof e==`object`&&ur.has(e.kind)&&typeof e.text==`string`}function hr(e){let t=new Date().toISOString(),n=V(e.text,cr);return!n||lr.test(n)?null:{id:String(e.id||C()),kind:e.kind,text:n,source:V(e.source||`unknown`,160)||`unknown`,confidence:gr(e.confidence),tags:H(e.tags,48,12),sourceRefs:H(e.sourceRefs,160,12),createdAt:typeof e.createdAt==`string`?e.createdAt:t,updatedAt:typeof e.updatedAt==`string`?e.updatedAt:t,...typeof e.expiresAt==`string`?{expiresAt:e.expiresAt}:{}}}function V(e,t){return typeof e==`string`?e.replace(/\s+/g,` `).trim().slice(0,t):``}function H(e,t,n){return Array.isArray(e)?e.map(e=>V(e,t)).filter(Boolean).slice(0,n):[]}function gr(e){return typeof e!=`number`||Number.isNaN(e)?.7:Math.max(0,Math.min(1,e))}function _r(e,t){return`${e}:${t.toLowerCase().replace(/\s+/g,` `).trim()}`}function vr(e){let t=Date.now();return e.filter(e=>!e.expiresAt||U(e.expiresAt)>t)}function yr(e){return e.length<=100?e:[...e].sort((e,t)=>U(e.updatedAt)-U(t.updatedAt)).slice(e.length-100)}function br(e){let t=new Map;for(let n of e){let e=_r(n.kind,n.text),r=t.get(e);(!r||U(n.updatedAt)>=U(r.updatedAt))&&t.set(e,n)}return Array.from(t.values())}function xr(e,t,n){let r=n&&n.length>0?e.filter(e=>n.includes(e.kind)):e,i=Cr(t);return i.length===0?[...r].sort((e,t)=>U(t.updatedAt)-U(e.updatedAt)):[...r].map(e=>({record:e,score:Sr(e,i)})).filter(e=>e.score>0).sort((e,t)=>t.score-e.score||U(t.record.updatedAt)-U(e.record.updatedAt)).map(e=>e.record)}function Sr(e,t){let n=`${e.kind} ${e.text} ${e.tags.join(` `)}`.toLowerCase(),r=0;for(let e of t)n.includes(e)&&(r+=e.length);return r+e.confidence}function Cr(e){return Array.from(new Set(e.toLowerCase().split(/[^\p{L}\p{N}_-]+/u).filter(e=>e.length>=2))).slice(0,24)}function U(e){let t=Date.parse(e);return Number.isFinite(t)?t:0}var wr=class{constructor(e=new dr){this.store=e}async build(e,t,n={}){let r=await this.store.load(e),i=await this.store.search(e,{query:t,kinds:n.longTermKinds,limit:n.longTermLimit??8}),a=[`<memory_context>`],o=!1,s=e=>[...a,...e,`</memory_context>`].join(`
|
|
25
|
+
`}function Fn(e){return`sha256:${ae(`sha256`).update(e).digest(`hex`)}`}function In(e){return e.replace(/[^A-Za-z0-9._-]/g,`_`).replace(/^\.+$/,`skill`)||`skill`}function R(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function Ln(e){return e===`app`||e===`session`||e===`request`?e:`request`}function Rn(e){return JSON.stringify(e)}const zn=/(authorization|cookie|token|api[-_]?key|secret|password|credential)/i,Bn=/^(file[-_]?token|drive[-_]?file[-_]?token|doc[-_]?token|sheet[-_]?token|wiki[-_]?token|node[-_]?token)$/i,Vn=new Set([`x-tenant-key`,`x-user-id`,`x-open-id`,`x-user-name`,`x-session-id`,`x-conversation-id`,`x-trace-id`,`x-request-id`]);function Hn(e){return ir(e,`x-request-id`)||T()}function Un(e,t){return ir(e,`x-trace-id`)||t}function Wn(e,t){let n=t?.scenarioId??t?.scenario_id;if(typeof e==`string`&&e.trim().length>0)return e.trim();if(typeof n==`string`&&n.trim().length>0)return n.trim()}function Gn(){return E()}function Kn(e,t){let n=t||f(Gn(),`.sessions`,e);return a(n,{recursive:!0}),n}function qn(e){let t=e.requestId||T(),n=B(e.sessionId,`sessionId`),r=B(e.traceId||t,`traceId`),i=B(e.conversationId||n,`conversationId`),a=B(e.identity?.tenantKey,`tenantKey`),o=B(e.identity?.userId||e.identity?.openId,`userId`),s=Wn(e.scenarioId,e.metadata),c=Kn(n,e.cwd),l=Dn({cwd:c,instructions:e.runtimeInstructions,skills:e.runtimeSkills}),u=ar(e.metadata,{conversationId:i,traceId:r,entrypoint:e.entrypoint,scenarioId:s,runtimeContext:l}),d=tr({tenantKey:a,userId:o,openId:e.identity?.openId,userName:e.identity?.userName,sessionId:n,conversationId:i,traceId:r,requestId:t,explicitHeaders:e.authHeaders}),f=nr(e.policy,{maxTurns:e.maxTurns,maxBudgetUsd:e.maxBudgetUsd,allowSignalNoReplyTool:e.allowSignalNoReplyTool}),p=rr(e.identity),m={requestId:t,sessionId:n,conversationId:i,traceId:r,entrypoint:e.entrypoint,scenarioId:s,tenantKey:a,userId:o,openId:e.identity?.openId,userName:e.identity?.userName,cwd:c,authHeaders:d,attachments:e.attachments,sourceArtifacts:e.sourceArtifacts,runtimeContext:l,llmConfig:e.llmConfig,policy:f,metadata:u};return{requestId:t,sessionId:n,cwd:c,prompt:e.prompt,maxTurns:e.maxTurns??f.maxTurns,maxBudgetUsd:e.maxBudgetUsd??f.maxBudgetUsd,model:e.model,transcriptMode:e.transcriptMode,userContext:p,tenantContext:{tenantKey:a},authHeaders:d,attachments:e.attachments,sourceArtifacts:e.sourceArtifacts,runtimeContext:l,llmConfig:e.llmConfig,policy:f,requestContext:m,runContext:{tenantKey:a,userId:o,sessionId:n,conversationId:i,traceId:r,requestId:t,entrypoint:e.entrypoint,scenarioId:s,authHeaders:d,metadata:u},metadata:u}}function Jn(...e){return e.find(e=>e!==void 0)}function z(e){if(e==null)return e;if(typeof e==`string`)return sr(e);if(typeof e==`number`||typeof e==`boolean`)return e;if(Array.isArray(e))return{type:`array`,length:e.length,sample:e.slice(0,5).map(e=>z(e))};if(typeof e==`object`){let t={};for(let[n,r]of Object.entries(e))zn.test(n)&&!Bn.test(n)?t[n]=`[redacted]`:t[n]=z(r);return t}return String(e)}function Yn(e,t,n){let r=or(e,n?.metadata);return{id:T(),requestId:e.requestId,sessionId:e.sessionId,tenantKey:e.tenantKey,userId:e.userId,type:t,timestamp:new Date().toISOString(),...n,...r?{metadata:r}:{}}}function Xn(e){return{...e,inputSummary:z(e.inputSummary)}}function Zn(e){if(!e)return;let t={toolResult:z(e)};for(let n of[`ok`,`exitCode`,`isError`,`errorCode`,`reasonCode`])e[n]!==void 0&&(t[n]=e[n]);return t}function Qn(e){let t={verifierResult:z(e)};for(let n of[`ok`,`status`,`reasonCode`])e[n]!==void 0&&(t[n]=e[n]);return e.failedGates&&(t.failedGates=z(e.failedGates)),e.missingArtifacts&&(t.missingArtifacts=z(e.missingArtifacts)),t}function $n(e){let t={};return e.attachments!==void 0&&(t.attachments=z(e.attachments)),e.sourceArtifacts!==void 0&&(t.sourceArtifacts=z(e.sourceArtifacts)),e.runtimeContext!==void 0&&(t.runtimeContext=e.runtimeContext),t}function er(e){let t={runtimeEventType:e.type,runtimeEvent:z(e)};for(let n of[`scenarioId`,`traceId`,`phaseId`,`artifactName`,`artifactNames`,`capabilityId`,`repairActionId`,`repairAttempt`,`targetPhase`,`requiredNextPhases`,`plannerInstruction`,`reasonCode`,`verifierReasonCode`,`missingPhases`,`failedGates`,`missingArtifacts`,`status`,`finalStatus`])e[n]!==void 0&&(t[n]=z(e[n]));return t}function tr(e){let t={"x-tenant-key":e.tenantKey,"x-user-id":e.userId,...e.openId?{"x-open-id":e.openId}:{},...e.userName?{"x-user-name":e.userName}:{},"x-session-id":e.sessionId,"x-conversation-id":e.conversationId,"x-trace-id":e.traceId,"x-request-id":e.requestId};for(let[n,r]of Object.entries(e.explicitHeaders||{})){let e=n.toLowerCase();e.startsWith(`x-`)&&!zn.test(e)&&!Vn.has(e)&&(t[e]=r)}return t}function nr(e,t){let n={allowedTools:e?.allowedTools??[],disallowedTools:e?.disallowedTools,allowedSkills:e?.allowedSkills??[],disallowedSkills:e?.disallowedSkills,maxTurns:t.maxTurns??e?.maxTurns,maxToolCalls:e?.maxToolCalls,maxRuntimeMs:e?.maxRuntimeMs,maxBudgetUsd:t.maxBudgetUsd??e?.maxBudgetUsd,turnPolicy:e?.turnPolicy};return t.allowSignalNoReplyTool?n:Ce(n,`signal_no_reply`)}function rr(e){if(!e?.userId&&!e?.openId)return;let t=e.userId||e.openId;if(t)return{userId:t,openId:e.openId||t,userName:e.userName||t,credentialDir:e.credentialDir||f(Gn(),`users`,t),isTenantIdentity:e.isTenantIdentity??!1}}function ir(e,t){let n=t.toLowerCase(),r=e[t]??e[n],i=Array.isArray(r)?r[0]:r;if(typeof i!=`string`)return;let a=i.trim();return a.length>0?a:void 0}function B(e,t){if(typeof e==`string`&&e.trim().length>0)return e.trim();throw Error(`Agent run context missing required field: ${t}`)}function ar(e,t){return{...e,conversationId:t.conversationId,traceId:t.traceId,entrypoint:t.entrypoint,...t.scenarioId?{scenarioId:t.scenarioId}:{},...t.runtimeContext?{runtimeContext:t.runtimeContext}:{}}}function or(e,t){let n={...e.conversationId?{conversationId:e.conversationId}:{},...e.traceId?{traceId:e.traceId}:{},...e.entrypoint?{entrypoint:e.entrypoint}:{},...e.scenarioId?{scenarioId:e.scenarioId}:{},...t};return Object.keys(n).length>0?n:void 0}function sr(e){return e.length<=200?e:{type:`string`,length:e.length,preview:e.slice(0,200)}}const cr=t(`memory/store`),lr=1e3,ur=/(api[-_ ]?key|secret|password|bearer\s+[a-z0-9._-]+|sk-[a-z0-9]|token\s*[:=])/i,dr=new Set([`fact`,`preference`,`decision`,`recurring_context`]);var fr=class e{static updateLocks=new Map;getMemoryPath(e){return f(e,`.larkpal`,`memory.json`)}async load(e){let t=this.getMemoryPath(e);if(!i(t))return pr();try{let e=await _(t,`utf-8`);return mr(JSON.parse(e))}catch(n){return cr.warn(`memory file load failed, using empty state`,{cwd:e,path:t,error:n instanceof Error?n.message:String(n)}),pr()}}async save(e,t){await this.withMemoryLock(e,()=>this.writeMemoryFile(e,t))}async writeMemoryFile(e,t){let n=this.getMemoryPath(e);await g(u(n),{recursive:!0});let r=mr(t),i=`${n}.${process.pid}.${Date.now()}.tmp`;await S(i,JSON.stringify(r,null,2),`utf-8`),await y(i,n)}async propose(e,t){let n=t.kind;if(!dr.has(n))return{accepted:!1,reasonCode:`invalid_kind`};let r=V(t.text,lr);return r?ur.test(r)?{accepted:!1,reasonCode:`sensitive`}:this.withMemoryLock(e,async()=>{let i=await this.load(e);i.longTerm=yr(i.longTerm);let a=vr(n,r),o=i.longTerm.find(e=>vr(e.kind,e.text)===a);if(o)return{accepted:!1,id:o.id,reasonCode:`duplicate`};let s=new Date().toISOString(),c=typeof t.ttlDays==`number`&&t.ttlDays>0?t.ttlDays:void 0,l={id:w(),kind:n,text:r,source:V(t.source||t.reason||`agent_proposal`,160)||`agent_proposal`,confidence:_r(t.confidence),tags:H(t.tags,48,12),sourceRefs:H(t.sourceRefs,160,12),createdAt:s,updatedAt:s,...c?{expiresAt:new Date(Date.now()+c*24*60*60*1e3).toISOString()}:{}};return i.longTerm.push(l),i.longTerm=br(i.longTerm),await this.writeMemoryFile(e,i),{accepted:!0,id:l.id}}):{accepted:!1,reasonCode:`empty`}}async search(e,t){let n=await this.load(e),r=t.query||``,i=t.kinds?.filter(e=>dr.has(e)),a=Math.max(1,Math.min(t.limit??8,20));return Sr(yr(n.longTerm),r,i).slice(0,a)}async appendTeammateSummary(e,t){return this.withMemoryLock(e,async()=>{let n=await this.load(e),r={id:w(),decision:t.decision,summary:V(t.summary,600)||`(empty)`,messageCount:Math.max(0,t.messageCount),sourceRefs:H(t.sourceRefs,160,12),createdAt:new Date().toISOString()};return n.working.teammateRecent.push(r),n.working.teammateRecent=n.working.teammateRecent.slice(-3),await this.writeMemoryFile(e,n),r})}async withMemoryLock(t,n){let r=this.getMemoryPath(t),i=e.updateLocks.get(r)??Promise.resolve(),a=()=>{},o=new Promise(e=>{a=e}),s=i.catch(()=>void 0).then(()=>o);e.updateLocks.set(r,s),await i.catch(()=>void 0);try{return await n()}finally{a(),e.updateLocks.get(r)===s&&e.updateLocks.delete(r)}}};function pr(){return{version:1,working:{teammateRecent:[]},longTerm:[]}}function mr(e){let t=pr(),n=Array.isArray(e.working?.teammateRecent)?e.working.teammateRecent.filter(e=>!!e&&typeof e.summary==`string`).map(e=>({id:String(e.id||w()),decision:e.decision===`HANDOFF_TO_MAIN`?`HANDOFF_TO_MAIN`:`NO_REPLY`,summary:V(e.summary,600)||`(empty)`,messageCount:Math.max(0,Number(e.messageCount)||0),sourceRefs:H(e.sourceRefs,160,12),createdAt:typeof e.createdAt==`string`?e.createdAt:new Date().toISOString()})).slice(-3):[],r=Array.isArray(e.longTerm)?br(yr(xr(e.longTerm.filter(hr).map(gr).filter(e=>e!==null)))):[];return{...t,working:{teammateRecent:n},longTerm:r}}function hr(e){return!!e&&typeof e==`object`&&dr.has(e.kind)&&typeof e.text==`string`}function gr(e){let t=new Date().toISOString(),n=V(e.text,lr);return!n||ur.test(n)?null:{id:String(e.id||w()),kind:e.kind,text:n,source:V(e.source||`unknown`,160)||`unknown`,confidence:_r(e.confidence),tags:H(e.tags,48,12),sourceRefs:H(e.sourceRefs,160,12),createdAt:typeof e.createdAt==`string`?e.createdAt:t,updatedAt:typeof e.updatedAt==`string`?e.updatedAt:t,...typeof e.expiresAt==`string`?{expiresAt:e.expiresAt}:{}}}function V(e,t){return typeof e==`string`?e.replace(/\s+/g,` `).trim().slice(0,t):``}function H(e,t,n){return Array.isArray(e)?e.map(e=>V(e,t)).filter(Boolean).slice(0,n):[]}function _r(e){return typeof e!=`number`||Number.isNaN(e)?.7:Math.max(0,Math.min(1,e))}function vr(e,t){return`${e}:${t.toLowerCase().replace(/\s+/g,` `).trim()}`}function yr(e){let t=Date.now();return e.filter(e=>!e.expiresAt||U(e.expiresAt)>t)}function br(e){return e.length<=100?e:[...e].sort((e,t)=>U(e.updatedAt)-U(t.updatedAt)).slice(e.length-100)}function xr(e){let t=new Map;for(let n of e){let e=vr(n.kind,n.text),r=t.get(e);(!r||U(n.updatedAt)>=U(r.updatedAt))&&t.set(e,n)}return Array.from(t.values())}function Sr(e,t,n){let r=n&&n.length>0?e.filter(e=>n.includes(e.kind)):e,i=wr(t);return i.length===0?[...r].sort((e,t)=>U(t.updatedAt)-U(e.updatedAt)):[...r].map(e=>({record:e,score:Cr(e,i)})).filter(e=>e.score>0).sort((e,t)=>t.score-e.score||U(t.record.updatedAt)-U(e.record.updatedAt)).map(e=>e.record)}function Cr(e,t){let n=`${e.kind} ${e.text} ${e.tags.join(` `)}`.toLowerCase(),r=0;for(let e of t)n.includes(e)&&(r+=e.length);return r+e.confidence}function wr(e){return Array.from(new Set(e.toLowerCase().split(/[^\p{L}\p{N}_-]+/u).filter(e=>e.length>=2))).slice(0,24)}function U(e){let t=Date.parse(e);return Number.isFinite(t)?t:0}var Tr=class{constructor(e=new fr){this.store=e}async build(e,t,n={}){let r=await this.store.load(e),i=await this.store.search(e,{query:t,kinds:n.longTermKinds,limit:n.longTermLimit??8}),a=[`<memory_context>`],o=!1,s=e=>[...a,...e,`</memory_context>`].join(`
|
|
26
26
|
`).length<=3e3,c=(e,t,n)=>{let r=[];for(let i of t){if(!s([e,...r,i,n]))break;r.push(i)}r.length!==0&&(a.push(e,...r,n),o=!0)};return c(`<teammate_recent>`,r.working.teammateRecent.map(e=>`- ${e.decision} (${e.messageCount} messages): ${e.summary}`),`</teammate_recent>`),i.length>0&&c(`<long_term>`,i.map(e=>{let t=e.tags.length>0?` tags=${e.tags.join(`,`)}`:``;return`- [${e.kind}]${t} ${e.text}`}),`</long_term>`),a.push(`</memory_context>`),o?a.join(`
|
|
27
|
-
`):``}async injectPrompt(e,t,n,r){let i=await this.build(e,n,r);if(!i)return t;let a=`${i}\n\n`;if(typeof t==`string`)return`${a}${t}`;let o=t[0]?.type===`text`?t[0]:void 0;return o?[{...o,text:`${a}${o.text}`},...t.slice(1)]:[{type:`text`,text:a},...t]}};let W;function Tr(){if(W)return W;try{let e=a(d(l(p(import.meta.url)),`..`,`..`,`package.json`),`utf8`);return W=JSON.parse(e).version??`unknown`,W}catch{return W=`unknown`,W}}function Er(){switch(process.platform){case`darwin`:return`mac`;case`win32`:return`windows`;default:return`linux`}}function Dr(){return`openclaw-lark/${Tr()}/${Er()}`}function Or(e){let t=K([J(1,`audio/pcm`),J(2,`s16le`),q(3,24000n)]),n=K([Y(1,K([Y(1,K([Y(1,t),Y(2,t)]))]))]);return K([J(1,`session.create`),J(2,e.eventId),q(3,0n),J(4,e.createdAt),Y(10,n)])}function kr(e){let t=K([Y(1,Buffer.from(e.delta))]);return K([J(1,`audio.upstream.append`),J(2,e.eventId),q(3,e.sessionId),J(4,e.createdAt),Y(11,t)])}function Ar(e){return K([J(1,`audio.upstream.clear`),J(2,e.eventId),q(3,e.sessionId),J(4,e.createdAt),Y(12,Buffer.alloc(0))])}function jr(e){let t=K([q(1,e.reason===`CLIENT_ERROR`?2n:1n)]);return K([J(1,`session.close`),J(2,e.eventId),q(3,e.sessionId),J(4,e.createdAt),Y(13,t)])}function Mr(e){let t=[q(1,e.seqId),q(2,e.logId),q(3,BigInt(e.service)),q(4,BigInt(e.method)),J(6,e.payloadEncoding),J(7,e.payloadType),Y(8,Buffer.from(e.payload))];return e.msgId&&t.push(J(11,e.msgId)),K(t)}function Nr(e){let t=G(e);return{seqId:t.get(1)?.varint,logId:t.get(2)?.varint,service:t.get(3)?.varint,method:t.get(4)?.varint,payloadEncoding:t.get(6)?.string,payloadType:t.get(7)?.string,payload:t.get(8)?.bytes,msgId:t.get(11)?.string,frameType:t.get(12)?.varint}}function Pr(e){let t=G(e),n={type:t.get(1)?.string,eventId:t.get(2)?.string,sessionId:t.get(3)?.varint,createdAt:t.get(4)?.string},r=t.get(10)?.bytes;r&&(n.clientEventId=G(r).get(1)?.string);let i=t.get(20)?.bytes;if(i){let e=G(i),t=e.get(3)?.bytes,r=t?G(t):void 0;n.audioDownstreamDelta={trackId:e.get(1)?.string,source:e.get(2)?.string,format:r?{type:r.get(1)?.string,encoding:r.get(2)?.string,sampleRate:r.get(3)?.varint}:void 0,ptsMs:e.get(4)?.varint,durationMs:e.get(5)?.varint,delta:e.get(6)?.bytes}}let a=t.get(90)?.bytes;if(a){let e=G(a);n.error={clientEventId:e.get(1)?.string,code:e.get(2)?.varint,message:e.get(3)?.string,retryable:e.get(4)?.varint===1n}}return n}function G(e){let t=Buffer.from(e),n=new Map,r=0;for(;r<t.byteLength;){let e=Ir(t,r);r=e.offset;let i=Number(e.value>>3n),a=Number(e.value&7n);if(a===0){let e=Ir(t,r);r=e.offset,n.set(i,{varint:e.value});continue}if(a===2){let e=Ir(t,r);r=e.offset;let a=t.subarray(r,r+Number(e.value));r+=Number(e.value),n.set(i,{bytes:a,string:a.toString(`utf8`)});continue}throw Error(`Unsupported protobuf wire type: ${a}`)}return n}function K(e){return Buffer.concat(e)}function q(e,t){return Buffer.concat([Fr(BigInt(e<<3)),Fr(t)])}function J(e,t){return Y(e,Buffer.from(t,`utf8`))}function Y(e,t){return Buffer.concat([Fr(BigInt(e<<3|2)),Fr(BigInt(t.byteLength)),t])}function Fr(e){if(e<0n)throw Error(`Negative protobuf varint is not supported`);let t=[],n=e;do{let e=Number(n&127n);n>>=7n,n>0n&&(e|=128),t.push(e)}while(n>0n);return Buffer.from(t)}function Ir(e,t){let n=0n,r=0n,i=t;for(;i<e.byteLength;){let t=e[i]??0;if(n|=BigInt(t&127)<<r,i+=1,!(t&128))return{value:n,offset:i};r+=7n}throw Error(`Unterminated protobuf varint`)}var Lr=class{constructor(e){this.opts=e}async*frames(e){if(!this.opts.socket.receiveBinary)throw Error(`Feishu realtime socket must support receiveBinary() to receive downstream audio`);let t=e?.durationMs===void 0?void 0:Date.now()+e.durationMs;for(;;){let e=t===void 0?void 0:t-Date.now();if(e!==void 0&&e<=0)return;let n=e===void 0?await this.opts.socket.receiveBinary():await Rr(this.opts.socket.receiveBinary(),e);if(!n)return;let r=Nr(n);if(!r.payload)continue;let i=Pr(r.payload);if(i.type===`session.closed`)return;if(i.type===`error`){let e=i.error?.code?.toString()??`unknown`,t=i.error?.message??`unknown realtime error`;throw Error(`Feishu realtime server error: ${e} ${t}`)}if(i.type!==`audio.downstream.delta`||!i.audioDownstreamDelta?.delta||i.sessionId!==this.opts.sessionId)continue;let a=i.audioDownstreamDelta.format;if(a?.type!==`audio/pcm`||a.encoding!==`s16le`||a.sampleRate!==24000n)throw Error(`Feishu meeting downstream audio must be 24kHz s16le PCM`);yield{meetingId:this.opts.meetingId,sessionId:i.sessionId,trackId:i.audioDownstreamDelta.trackId,source:i.audioDownstreamDelta.source,ptsMs:i.audioDownstreamDelta.ptsMs,durationMs:i.audioDownstreamDelta.durationMs===void 0?void 0:Number(i.audioDownstreamDelta.durationMs),pcm:i.audioDownstreamDelta.delta,format:{sampleRate:24e3,channels:1,encoding:`s16le`}}}}};async function Rr(e,t){let n;try{return await Promise.race([e,new Promise(e=>{n=setTimeout(()=>e(void 0),t)})])}finally{n&&clearTimeout(n)}}var zr=class{constructor(e){this.opts=e}async appendPcm(e){if(e.meetingId!==this.opts.meetingId)throw Error(`Meeting audio frame belongs to ${e.meetingId}, expected ${this.opts.meetingId}`);if(e.format.sampleRate!==24e3||e.format.channels!==1||e.format.encoding!==`s16le`)throw Error(`Feishu meeting upstream audio requires 24kHz mono s16le PCM`);await this.opts.transport.send({type:`audio.upstream.append`,meetingId:this.opts.meetingId,sessionId:this.opts.sessionId,sequence:e.sequence,payloadType:`audio/pcm`,format:e.format,audioByteLength:e.pcm.byteLength,audio:e.pcm})}async clear(){await this.opts.transport.send({type:`audio.upstream.clear`,meetingId:this.opts.meetingId,sessionId:this.opts.sessionId})}};function Br(e,t){let n={...t?.headers,"User-Agent":Dr()};return fetch(e,{...t,headers:n})}var Vr=class{fetchFn;baseUrl;constructor(e){this.opts=e,this.fetchFn=e.fetchFn??Br,this.baseUrl=e.baseUrl??`https://open.feishu.cn`}async joinBot(e){let t=this.getUserAccessTokenOrUndefined();if(!t&&this.opts.useLarkCliUserAuth)return this.joinBotWithLarkCli(e);if(!t)throw Wr();let n=await this.request(`/open-apis/vc/v1/bots/join`,{method:`POST`,token:t,body:{join_identify:{meeting_no:e.meetingNumber,...e.password?{password:e.password}:{}},join_type:1}}),r=n.data?.meeting?.id;if(!r)throw Error(`Feishu meeting bot join response missing data.meeting.id`);return{meetingId:r,raw:n.data}}async getRealtimeEndpoint(e){let t=this.getUserAccessTokenOrUndefined();if(!t&&this.opts.useLarkCliUserAuth)return this.getRealtimeEndpointWithLarkCli(e);if(!t)throw Wr();let n=await this.request(`/open-apis/vc/v1/realtime/endpoint`,{method:`GET`,token:t,query:{meeting_id:e}}),r=n.data?.websocket_url;if(!r)throw Error(`Feishu realtime endpoint response missing data.websocket_url`);return{websocketUrl:r,expiresTime:n.data?.expires_time}}async leaveBot(e){let t=this.getUserAccessTokenOrUndefined();if(!t&&this.opts.useLarkCliUserAuth){this.leaveBotWithLarkCli(e);return}if(!t)throw Wr();await this.request(`/open-apis/vc/v1/bots/leave`,{method:`POST`,token:t,body:{meeting_id:e}})}async getTenantAccessToken(){if(!this.opts.appId||!this.opts.appSecret)throw Error(`Feishu tenant token auth requires app_id and app_secret`);let e=await this.request(`/open-apis/auth/v3/tenant_access_token/internal`,{method:`POST`,body:{app_id:this.opts.appId,app_secret:this.opts.appSecret}}),t=e.data?.tenant_access_token??e.raw.tenant_access_token;if(!t)throw Error(`Feishu token response missing tenant_access_token`);return t}getUserAccessTokenOrUndefined(){return this.opts.userAccessToken?.trim()||void 0}joinBotWithLarkCli(e){let t={join_type:1,join_identify:{meeting_no:e.meetingNumber,...e.password?{password:e.password}:{}}},n=this.larkCliRequest(`/open-apis/vc/v1/bots/join`,{method:`POST`,body:t}),r=n.data?.meeting?.id;if(!r)throw Error(`Feishu meeting bot join response missing data.meeting.id`);return{meetingId:r,raw:n.data}}getRealtimeEndpointWithLarkCli(e){let t=this.larkCliRequest(`/open-apis/vc/v1/realtime/endpoint`,{method:`GET`,query:{meeting_id:e}}),n=t.data?.websocket_url;if(!n)throw Error(`Feishu realtime endpoint response missing data.websocket_url`);return{websocketUrl:n,expiresTime:t.data?.expires_time}}leaveBotWithLarkCli(e){this.larkCliRequest(`/open-apis/vc/v1/bots/leave`,{method:`POST`,body:{meeting_id:e}})}larkCliRequest(e,t){let n={method:t.method,path:e,...t.query?{query:t.query}:{},...t.body===void 0?{}:{body:Hr(t.body)},auth:{present:!0,scheme:`lark-cli-user`}};try{let r=[`api`,t.method,e,`--as`,`user`,`--format`,`json`];t.query&&r.push(`--params`,JSON.stringify(t.query)),t.body!==void 0&&r.push(`--data`,JSON.stringify(t.body));let i=(this.opts.larkCliExecFileSync??re)(`lark-cli`,r,{encoding:`utf-8`,env:process.env,stdio:[`ignore`,`pipe`,`pipe`],timeout:3e4}),a=Gr(String(i));if(n.httpStatus=200,n.code=a.code,a.msg!==void 0&&(n.msg=X(a.msg)),a.code!==void 0&&a.code!==0)throw Error(`Feishu OpenAPI error ${a.code}: ${X(a.msg??`unknown error`)}`);return{data:a.data,raw:a}}catch(e){let t=Kr(e);throw t?(n.code=t.code,n.msg=t.msg,Error(`Feishu OpenAPI error ${t.code}: ${t.msg??`unknown error`}`,{cause:e})):e}finally{this.opts.onRequestTrace?.(n)}}async request(e,t){let n=new URL(e,this.baseUrl);for(let[e,r]of Object.entries(t.query??{}))n.searchParams.set(e,r);let r={};t.token&&(r.Authorization=`Bearer ${t.token}`),t.body!==void 0&&(r[`Content-Type`]=`application/json`);let i={method:t.method,path:e,...t.query?{query:t.query}:{},...t.body===void 0?{}:{body:Hr(t.body)},auth:Jr(r.Authorization)};try{let e=await this.fetchFn(n,{method:t.method,headers:r,...t.body===void 0?{}:{body:JSON.stringify(t.body)}});i.httpStatus=e.status;let a=Yr(e.headers);Object.keys(a).length>0&&(i.responseHeaders=a);let o=await e.json();if(i.code=o.code,o.msg!==void 0&&(i.msg=X(o.msg)),o.code!==void 0&&o.code!==0)throw Error(`Feishu OpenAPI error ${o.code}: ${X(o.msg??`unknown error`)}`);return{data:o.data,raw:o}}finally{this.opts.onRequestTrace?.(i)}}};function Hr(e){if(!e||typeof e!=`object`)return e;if(Array.isArray(e))return e.map(Hr);let t={};for(let[n,r]of Object.entries(e)){if(Ur(n)){t[n]=`[redacted]`;continue}t[n]=Hr(r)}return t}function Ur(e){return[`app_secret`,`password`,`token`,`authorization`].includes(e.toLocaleLowerCase())}function Wr(){return Error(`Feishu meeting OpenAPI requires user_access_token; tenant_access_token is not supported for meeting bot realtime APIs`)}function Gr(e){return JSON.parse(qr(e))}function Kr(e){if(!e||typeof e!=`object`)return;let t=[`stdout`in e?String(e.stdout??``):``,`stderr`in e?String(e.stderr??``):``];for(let e of t)if(e.trim())try{let t=Gr(e),n=t.error?.code??t.code,r=t.error?.message??t.msg;return{code:n,msg:r===void 0?void 0:X(r)}}catch{continue}}function qr(e){let t=e.indexOf(`{`),n=e.lastIndexOf(`}`);if(t<0||n<t)throw Error(`lark-cli response missing JSON object`);return e.slice(t,n+1)}function Jr(e){if(!e)return{present:!1};let[t,n]=e.split(/\s+/,2);return n?{present:!0,scheme:t,tokenLength:n.length,tokenFingerprint:ae(`sha256`).update(n).digest(`hex`).slice(0,12)}:{present:!0,scheme:t}}function Yr(e){let t=[`x-request-id`,`x-tt-logid`,`x-tt-trace-id`,`x-log-id`,`request-id`,`x-lark-request-id`],n={};for(let r of t){let t=e.get(r);t&&(n[r]=t)}return n}function X(e){return e.replace(/\bwss:\/\/\S+/gi,`[redacted-wss-url]`).replace(/\b(token=)[^\s,;]+/gi,`$1[redacted]`).replace(/\b(access_token=)[^\s,;]+/gi,`$1[redacted]`).replace(/\b(refresh_token=)[^\s,;]+/gi,`$1[redacted]`).replace(/\b(authorization:\s*bearer\s+)[^\s,;]+/gi,`$1[redacted]`)}var Xr=class{seq=0n;log=0n;constructor(e){this.opts=e}async createSession(e){if(!this.opts.socket.receiveBinary)throw Error(`Feishu realtime socket must support receiveBinary() to create a session`);let t=this.nextEventId();await this.sendRealtimePayload(t,Or({eventId:t,createdAt:this.now()}));let n=Date.now()+(e?.timeoutMs??1e4);for(;Date.now()<n;){let e=n-Date.now(),r=await Qr(this.opts.socket.receiveBinary(),e);if(!r)break;let i=Nr(r);if(!i.payload)continue;let a=Pr(i.payload);if(a.type===`session.created`){if(a.clientEventId&&a.clientEventId!==t)continue;if(!a.sessionId)throw Error(`Feishu realtime session.created missing session_id`);return a.sessionId}if(a.type===`error`){let e=a.error?.message??`unknown realtime error`,t=a.error?.code?.toString()??`unknown`;throw Error(`Feishu realtime session.create failed: ${t} ${e}`)}}throw Error(`Timed out waiting for Feishu realtime session.created`)}async send(e){let t=e.type===`audio.upstream.append`?kr({eventId:this.nextEventId(),sessionId:Zr(e.sessionId),createdAt:this.now(),delta:e.audio}):Ar({eventId:this.nextEventId(),sessionId:Zr(e.sessionId),createdAt:this.now()});await this.sendRealtimePayload(void 0,t)}async closeSession(e,t){let n=this.nextEventId();await this.sendRealtimePayload(n,jr({eventId:n,sessionId:Zr(e),createdAt:this.now(),reason:t?.reason}))}async sendRealtimePayload(e,t){await this.opts.socket.sendBinary(Mr({seqId:this.nextSeqId(),logId:this.nextLogId(),service:33555721,method:1,payloadEncoding:`binary`,payloadType:`application/x-protobuf`,payload:t,msgId:e}))}nextSeqId(){return this.opts.nextSeqId?this.opts.nextSeqId():(this.seq+=1n,this.seq)}nextLogId(){return this.opts.nextLogId?this.opts.nextLogId():(this.log+=1n,this.log)}nextEventId(){return this.opts.nextEventId?.()??`meeting-client-event-${Date.now()}-${this.nextSeqId()}`}now(){return this.opts.now?.()??new Date().toISOString()}};function Zr(e){if(typeof e==`bigint`)return e;if(!Number.isSafeInteger(e))throw Error(`Feishu meeting realtime session id must be a safe integer or bigint`);return BigInt(e)}async function Qr(e,t){let n;try{return await Promise.race([e,new Promise(e=>{n=setTimeout(()=>e(void 0),t)})])}finally{n&&clearTimeout(n)}}async function $r(e){let t=yi(e.meetingId,`meetingId`),n=ei(e.workspaceRoot,t),r=vi(t,e.transcriptEvents);if(e.transcriptEvents.length===0)return{decision:`NO_REPLY`,spokenReplies:[],pendingSpokenSummaries:[],speechSuppressed:e.speechSuppressed??!1};let i=gi(e.transcriptEvents,e.wakePhrases),a=_i(e.transcriptEvents),o=a?`HANDOFF_TO_SPEAKER reflective silence opportunity`:i?`HANDOFF_TO_SPEAKER explicit invite: ${i}`:await ti({...e,meetingId:t,cwd:n}),s=i||a?`HANDOFF_TO_SPEAKER`:di(o);if(await new dr().appendTeammateSummary(n,{decision:s===`HANDOFF_TO_SPEAKER`?`HANDOFF_TO_MAIN`:`NO_REPLY`,summary:fi(o,s),messageCount:e.transcriptEvents.length,sourceRefs:r}),s===`NO_REPLY`)return{decision:s,spokenReplies:[],pendingSpokenSummaries:[],speechSuppressed:e.speechSuppressed??!1};if(e.speechSuppressed&&!i)return{decision:s,spokenReplies:[],pendingSpokenSummaries:[],speechSuppressed:!0};let c=(await ni({...e,meetingId:t,cwd:n,fastDecisionText:o})).trim(),l=hi(c);if(l){let r=await ri({...e,meetingId:t,cwd:n,executionRequest:l});return{decision:s,spokenReplies:[],pendingSpokenSummaries:r.trim()?[r.trim()]:[],speechSuppressed:!1}}return!c||pi(c)||mi(c)?{decision:s,spokenReplies:[],pendingSpokenSummaries:[],speechSuppressed:!1}:{decision:s,spokenReplies:[{text:c,source:`speaking_session`}],pendingSpokenSummaries:[],speechSuppressed:!1}}function ei(e,t){return d(e,`meeting`,Z(t))}async function ti(e){let t=`meeting-fast-decision:${e.meetingId}:${Date.now()}`,n=R({requestId:t,traceId:t,sessionId:`meeting_fast_decision_${Z(e.meetingId)}_${Date.now()}`,conversationId:`meeting_${Z(e.meetingId)}`,entrypoint:`event`,cwd:e.cwd,prompt:ai(e.meetingId,e.transcriptEvents,e.parentContextSummary),model:e.model,transcriptMode:`ephemeral`,maxTurns:1,allowSignalNoReplyTool:!0,policy:{disallowedTools:[{tool:`ask_user`},{tool:`request_permission`}],maxTurns:1,maxToolCalls:0,maxRuntimeMs:3e3,turnPolicy:{maxTextCharsPerTurn:300,textBudgetExceededAction:`discard_turn`}},identity:e.owner,metadata:{channel:`feishu-meeting`,eventKind:`meeting-fast-decision`,meetingId:e.meetingId,...e.parentSessionId?{parentSessionId:e.parentSessionId}:{}}});return ui(e.runtime,n)}async function ni(e){let t=`meeting-speaking:${e.meetingId}:${Date.now()}`,n=R({requestId:t,traceId:t,sessionId:`meeting_speaking_${Z(e.meetingId)}`,conversationId:`meeting_${Z(e.meetingId)}`,entrypoint:`event`,cwd:e.cwd,prompt:oi(e.meetingId,e.transcriptEvents,e.fastDecisionText,e.parentContextSummary,e.pendingSpokenSummaries),model:e.model,transcriptMode:`persistent`,maxTurns:2,policy:ii({maxTurns:2,maxRuntimeMs:1e4}),identity:e.owner,metadata:{channel:`feishu-meeting`,eventKind:`meeting-speaking-session`,meetingId:e.meetingId,...e.parentSessionId?{parentSessionId:e.parentSessionId}:{}}});return ui(e.runtime,n)}async function ri(e){let t=`meeting-execution:${e.meetingId}:${Date.now()}`,n=R({requestId:t,traceId:t,sessionId:`meeting_execution_${Z(e.meetingId)}_${Date.now()}`,conversationId:`meeting_${Z(e.meetingId)}`,entrypoint:`event`,cwd:e.cwd,prompt:ci(e.meetingId,e.executionRequest,e.parentContextSummary),model:e.model,transcriptMode:`ephemeral`,maxTurns:3,policy:ii({maxTurns:3,maxRuntimeMs:3e4}),identity:e.owner,metadata:{channel:`feishu-meeting`,eventKind:`meeting-execution-subagent`,meetingId:e.meetingId,...e.parentSessionId?{parentSessionId:e.parentSessionId}:{}}});return ui(e.runtime,n)}function ii(e){return{disallowedTools:[{tool:`ask_user`},{tool:`request_permission`}],maxTurns:e.maxTurns,maxRuntimeMs:e.maxRuntimeMs,turnPolicy:{maxTextCharsPerTurn:500,textBudgetExceededAction:`discard_turn`}}}function ai(e,t,n){let r=t.map(e=>{let t=e.speaker.name||e.speaker.openId||e.speaker.userId||e.speaker.participantId;return`[${e.timestamp}] ${t}: ${e.text}`}).join(`
|
|
28
|
-
`);return[`[会议旁听快速判定]`,`meeting_id: ${e}`,`只判断是否应该把这段会议窗口交给会议发言 session;不要回答用户,不要调用工具。`,`如果不需要参与,必须以 NO_REPLY 开头。`,`如果应该参与,必须以 HANDOFF_TO_SPEAKER 开头,并给出一句极短理由。`,``,...
|
|
29
|
-
`)}function
|
|
27
|
+
`):``}async injectPrompt(e,t,n,r){let i=await this.build(e,n,r);if(!i)return t;let a=`${i}\n\n`;if(typeof t==`string`)return`${a}${t}`;let o=t[0]?.type===`text`?t[0]:void 0;return o?[{...o,text:`${a}${o.text}`},...t.slice(1)]:[{type:`text`,text:a},...t]}};let W;function Er(){if(W)return W;try{let e=o(f(u(m(import.meta.url)),`..`,`..`,`package.json`),`utf8`);return W=JSON.parse(e).version??`unknown`,W}catch{return W=`unknown`,W}}function Dr(){switch(process.platform){case`darwin`:return`mac`;case`win32`:return`windows`;default:return`linux`}}function Or(){return`openclaw-lark/${Er()}/${Dr()}`}function kr(e){let t=K([J(1,`audio/pcm`),J(2,`s16le`),q(3,24000n)]),n=K([Y(1,K([Y(1,K([Y(1,t),Y(2,t)]))]))]);return K([J(1,`session.create`),J(2,e.eventId),q(3,0n),J(4,e.createdAt),Y(10,n)])}function Ar(e){let t=K([Y(1,Buffer.from(e.delta))]);return K([J(1,`audio.upstream.append`),J(2,e.eventId),q(3,e.sessionId),J(4,e.createdAt),Y(11,t)])}function jr(e){return K([J(1,`audio.upstream.clear`),J(2,e.eventId),q(3,e.sessionId),J(4,e.createdAt),Y(12,Buffer.alloc(0))])}function Mr(e){let t=K([q(1,e.reason===`CLIENT_ERROR`?2n:1n)]);return K([J(1,`session.close`),J(2,e.eventId),q(3,e.sessionId),J(4,e.createdAt),Y(13,t)])}function Nr(e){let t=[q(1,e.seqId),q(2,e.logId),q(3,BigInt(e.service)),q(4,BigInt(e.method)),J(6,e.payloadEncoding),J(7,e.payloadType),Y(8,Buffer.from(e.payload))];return e.msgId&&t.push(J(11,e.msgId)),K(t)}function Pr(e){let t=G(e);return{seqId:t.get(1)?.varint,logId:t.get(2)?.varint,service:t.get(3)?.varint,method:t.get(4)?.varint,payloadEncoding:t.get(6)?.string,payloadType:t.get(7)?.string,payload:t.get(8)?.bytes,msgId:t.get(11)?.string,frameType:t.get(12)?.varint}}function Fr(e){let t=G(e),n={type:t.get(1)?.string,eventId:t.get(2)?.string,sessionId:t.get(3)?.varint,createdAt:t.get(4)?.string},r=t.get(10)?.bytes;r&&(n.clientEventId=G(r).get(1)?.string);let i=t.get(20)?.bytes;if(i){let e=G(i),t=e.get(3)?.bytes,r=t?G(t):void 0;n.audioDownstreamDelta={trackId:e.get(1)?.string,source:e.get(2)?.string,format:r?{type:r.get(1)?.string,encoding:r.get(2)?.string,sampleRate:r.get(3)?.varint}:void 0,ptsMs:e.get(4)?.varint,durationMs:e.get(5)?.varint,delta:e.get(6)?.bytes}}let a=t.get(90)?.bytes;if(a){let e=G(a);n.error={clientEventId:e.get(1)?.string,code:e.get(2)?.varint,message:e.get(3)?.string,retryable:e.get(4)?.varint===1n}}return n}function G(e){let t=Buffer.from(e),n=new Map,r=0;for(;r<t.byteLength;){let e=Lr(t,r);r=e.offset;let i=Number(e.value>>3n),a=Number(e.value&7n);if(a===0){let e=Lr(t,r);r=e.offset,n.set(i,{varint:e.value});continue}if(a===2){let e=Lr(t,r);r=e.offset;let a=t.subarray(r,r+Number(e.value));r+=Number(e.value),n.set(i,{bytes:a,string:a.toString(`utf8`)});continue}throw Error(`Unsupported protobuf wire type: ${a}`)}return n}function K(e){return Buffer.concat(e)}function q(e,t){return Buffer.concat([Ir(BigInt(e<<3)),Ir(t)])}function J(e,t){return Y(e,Buffer.from(t,`utf8`))}function Y(e,t){return Buffer.concat([Ir(BigInt(e<<3|2)),Ir(BigInt(t.byteLength)),t])}function Ir(e){if(e<0n)throw Error(`Negative protobuf varint is not supported`);let t=[],n=e;do{let e=Number(n&127n);n>>=7n,n>0n&&(e|=128),t.push(e)}while(n>0n);return Buffer.from(t)}function Lr(e,t){let n=0n,r=0n,i=t;for(;i<e.byteLength;){let t=e[i]??0;if(n|=BigInt(t&127)<<r,i+=1,!(t&128))return{value:n,offset:i};r+=7n}throw Error(`Unterminated protobuf varint`)}var Rr=class{constructor(e){this.opts=e}async*frames(e){if(!this.opts.socket.receiveBinary)throw Error(`Feishu realtime socket must support receiveBinary() to receive downstream audio`);let t=e?.durationMs===void 0?void 0:Date.now()+e.durationMs;for(;;){let e=t===void 0?void 0:t-Date.now();if(e!==void 0&&e<=0)return;let n=e===void 0?await this.opts.socket.receiveBinary():await zr(this.opts.socket.receiveBinary(),e);if(!n)return;let r=Pr(n);if(!r.payload)continue;let i=Fr(r.payload);if(i.type===`session.closed`)return;if(i.type===`error`){let e=i.error?.code?.toString()??`unknown`,t=i.error?.message??`unknown realtime error`;throw Error(`Feishu realtime server error: ${e} ${t}`)}if(i.type!==`audio.downstream.delta`||!i.audioDownstreamDelta?.delta||i.sessionId!==this.opts.sessionId)continue;let a=i.audioDownstreamDelta.format;if(a?.type!==`audio/pcm`||a.encoding!==`s16le`||a.sampleRate!==24000n)throw Error(`Feishu meeting downstream audio must be 24kHz s16le PCM`);yield{meetingId:this.opts.meetingId,sessionId:i.sessionId,trackId:i.audioDownstreamDelta.trackId,source:i.audioDownstreamDelta.source,ptsMs:i.audioDownstreamDelta.ptsMs,durationMs:i.audioDownstreamDelta.durationMs===void 0?void 0:Number(i.audioDownstreamDelta.durationMs),pcm:i.audioDownstreamDelta.delta,format:{sampleRate:24e3,channels:1,encoding:`s16le`}}}}};async function zr(e,t){let n;try{return await Promise.race([e,new Promise(e=>{n=setTimeout(()=>e(void 0),t)})])}finally{n&&clearTimeout(n)}}var Br=class{constructor(e){this.opts=e}async appendPcm(e){if(e.meetingId!==this.opts.meetingId)throw Error(`Meeting audio frame belongs to ${e.meetingId}, expected ${this.opts.meetingId}`);if(e.format.sampleRate!==24e3||e.format.channels!==1||e.format.encoding!==`s16le`)throw Error(`Feishu meeting upstream audio requires 24kHz mono s16le PCM`);await this.opts.transport.send({type:`audio.upstream.append`,meetingId:this.opts.meetingId,sessionId:this.opts.sessionId,sequence:e.sequence,payloadType:`audio/pcm`,format:e.format,audioByteLength:e.pcm.byteLength,audio:e.pcm})}async clear(){await this.opts.transport.send({type:`audio.upstream.clear`,meetingId:this.opts.meetingId,sessionId:this.opts.sessionId})}};function Vr(e,t){let n={...t?.headers,"User-Agent":Or()};return fetch(e,{...t,headers:n})}var Hr=class{fetchFn;baseUrl;constructor(e){this.opts=e,this.fetchFn=e.fetchFn??Vr,this.baseUrl=e.baseUrl??`https://open.feishu.cn`}async joinBot(e){let t=this.getUserAccessTokenOrUndefined();if(!t&&this.opts.useLarkCliUserAuth)return this.joinBotWithLarkCli(e);if(!t)throw Gr();let n=await this.request(`/open-apis/vc/v1/bots/join`,{method:`POST`,token:t,body:{join_identify:{meeting_no:e.meetingNumber,...e.password?{password:e.password}:{}},join_type:1}}),r=n.data?.meeting?.id;if(!r)throw Error(`Feishu meeting bot join response missing data.meeting.id`);return{meetingId:r,raw:n.data}}async getRealtimeEndpoint(e){let t=this.getUserAccessTokenOrUndefined();if(!t&&this.opts.useLarkCliUserAuth)return this.getRealtimeEndpointWithLarkCli(e);if(!t)throw Gr();let n=await this.request(`/open-apis/vc/v1/realtime/endpoint`,{method:`GET`,token:t,query:{meeting_id:e}}),r=n.data?.websocket_url;if(!r)throw Error(`Feishu realtime endpoint response missing data.websocket_url`);return{websocketUrl:r,expiresTime:n.data?.expires_time}}async leaveBot(e){let t=this.getUserAccessTokenOrUndefined();if(!t&&this.opts.useLarkCliUserAuth){this.leaveBotWithLarkCli(e);return}if(!t)throw Gr();await this.request(`/open-apis/vc/v1/bots/leave`,{method:`POST`,token:t,body:{meeting_id:e}})}async getTenantAccessToken(){if(!this.opts.appId||!this.opts.appSecret)throw Error(`Feishu tenant token auth requires app_id and app_secret`);let e=await this.request(`/open-apis/auth/v3/tenant_access_token/internal`,{method:`POST`,body:{app_id:this.opts.appId,app_secret:this.opts.appSecret}}),t=e.data?.tenant_access_token??e.raw.tenant_access_token;if(!t)throw Error(`Feishu token response missing tenant_access_token`);return t}getUserAccessTokenOrUndefined(){return this.opts.userAccessToken?.trim()||void 0}joinBotWithLarkCli(e){let t={join_type:1,join_identify:{meeting_no:e.meetingNumber,...e.password?{password:e.password}:{}}},n=this.larkCliRequest(`/open-apis/vc/v1/bots/join`,{method:`POST`,body:t}),r=n.data?.meeting?.id;if(!r)throw Error(`Feishu meeting bot join response missing data.meeting.id`);return{meetingId:r,raw:n.data}}getRealtimeEndpointWithLarkCli(e){let t=this.larkCliRequest(`/open-apis/vc/v1/realtime/endpoint`,{method:`GET`,query:{meeting_id:e}}),n=t.data?.websocket_url;if(!n)throw Error(`Feishu realtime endpoint response missing data.websocket_url`);return{websocketUrl:n,expiresTime:t.data?.expires_time}}leaveBotWithLarkCli(e){this.larkCliRequest(`/open-apis/vc/v1/bots/leave`,{method:`POST`,body:{meeting_id:e}})}larkCliRequest(e,t){let n={method:t.method,path:e,...t.query?{query:t.query}:{},...t.body===void 0?{}:{body:Ur(t.body)},auth:{present:!0,scheme:`lark-cli-user`}};try{let r=[`api`,t.method,e,`--as`,`user`,`--format`,`json`];t.query&&r.push(`--params`,JSON.stringify(t.query)),t.body!==void 0&&r.push(`--data`,JSON.stringify(t.body));let i=(this.opts.larkCliExecFileSync??re)(`lark-cli`,r,{encoding:`utf-8`,env:process.env,stdio:[`ignore`,`pipe`,`pipe`],timeout:3e4}),a=Kr(String(i));if(n.httpStatus=200,n.code=a.code,a.msg!==void 0&&(n.msg=X(a.msg)),a.code!==void 0&&a.code!==0)throw Error(`Feishu OpenAPI error ${a.code}: ${X(a.msg??`unknown error`)}`);return{data:a.data,raw:a}}catch(e){let t=qr(e);throw t?(n.code=t.code,n.msg=t.msg,Error(`Feishu OpenAPI error ${t.code}: ${t.msg??`unknown error`}`,{cause:e})):e}finally{this.opts.onRequestTrace?.(n)}}async request(e,t){let n=new URL(e,this.baseUrl);for(let[e,r]of Object.entries(t.query??{}))n.searchParams.set(e,r);let r={};t.token&&(r.Authorization=`Bearer ${t.token}`),t.body!==void 0&&(r[`Content-Type`]=`application/json`);let i={method:t.method,path:e,...t.query?{query:t.query}:{},...t.body===void 0?{}:{body:Ur(t.body)},auth:Yr(r.Authorization)};try{let e=await this.fetchFn(n,{method:t.method,headers:r,...t.body===void 0?{}:{body:JSON.stringify(t.body)}});i.httpStatus=e.status;let a=Xr(e.headers);Object.keys(a).length>0&&(i.responseHeaders=a);let o=await e.json();if(i.code=o.code,o.msg!==void 0&&(i.msg=X(o.msg)),o.code!==void 0&&o.code!==0)throw Error(`Feishu OpenAPI error ${o.code}: ${X(o.msg??`unknown error`)}`);return{data:o.data,raw:o}}finally{this.opts.onRequestTrace?.(i)}}};function Ur(e){if(!e||typeof e!=`object`)return e;if(Array.isArray(e))return e.map(Ur);let t={};for(let[n,r]of Object.entries(e)){if(Wr(n)){t[n]=`[redacted]`;continue}t[n]=Ur(r)}return t}function Wr(e){return[`app_secret`,`password`,`token`,`authorization`].includes(e.toLocaleLowerCase())}function Gr(){return Error(`Feishu meeting OpenAPI requires user_access_token; tenant_access_token is not supported for meeting bot realtime APIs`)}function Kr(e){return JSON.parse(Jr(e))}function qr(e){if(!e||typeof e!=`object`)return;let t=[`stdout`in e?String(e.stdout??``):``,`stderr`in e?String(e.stderr??``):``];for(let e of t)if(e.trim())try{let t=Kr(e),n=t.error?.code??t.code,r=t.error?.message??t.msg;return{code:n,msg:r===void 0?void 0:X(r)}}catch{continue}}function Jr(e){let t=e.indexOf(`{`),n=e.lastIndexOf(`}`);if(t<0||n<t)throw Error(`lark-cli response missing JSON object`);return e.slice(t,n+1)}function Yr(e){if(!e)return{present:!1};let[t,n]=e.split(/\s+/,2);return n?{present:!0,scheme:t,tokenLength:n.length,tokenFingerprint:ae(`sha256`).update(n).digest(`hex`).slice(0,12)}:{present:!0,scheme:t}}function Xr(e){let t=[`x-request-id`,`x-tt-logid`,`x-tt-trace-id`,`x-log-id`,`request-id`,`x-lark-request-id`],n={};for(let r of t){let t=e.get(r);t&&(n[r]=t)}return n}function X(e){return e.replace(/\bwss:\/\/\S+/gi,`[redacted-wss-url]`).replace(/\b(token=)[^\s,;]+/gi,`$1[redacted]`).replace(/\b(access_token=)[^\s,;]+/gi,`$1[redacted]`).replace(/\b(refresh_token=)[^\s,;]+/gi,`$1[redacted]`).replace(/\b(authorization:\s*bearer\s+)[^\s,;]+/gi,`$1[redacted]`)}var Zr=class{seq=0n;log=0n;constructor(e){this.opts=e}async createSession(e){if(!this.opts.socket.receiveBinary)throw Error(`Feishu realtime socket must support receiveBinary() to create a session`);let t=this.nextEventId();await this.sendRealtimePayload(t,kr({eventId:t,createdAt:this.now()}));let n=Date.now()+(e?.timeoutMs??1e4);for(;Date.now()<n;){let e=n-Date.now(),r=await $r(this.opts.socket.receiveBinary(),e);if(!r)break;let i=Pr(r);if(!i.payload)continue;let a=Fr(i.payload);if(a.type===`session.created`){if(a.clientEventId&&a.clientEventId!==t)continue;if(!a.sessionId)throw Error(`Feishu realtime session.created missing session_id`);return a.sessionId}if(a.type===`error`){let e=a.error?.message??`unknown realtime error`,t=a.error?.code?.toString()??`unknown`;throw Error(`Feishu realtime session.create failed: ${t} ${e}`)}}throw Error(`Timed out waiting for Feishu realtime session.created`)}async send(e){let t=e.type===`audio.upstream.append`?Ar({eventId:this.nextEventId(),sessionId:Qr(e.sessionId),createdAt:this.now(),delta:e.audio}):jr({eventId:this.nextEventId(),sessionId:Qr(e.sessionId),createdAt:this.now()});await this.sendRealtimePayload(void 0,t)}async closeSession(e,t){let n=this.nextEventId();await this.sendRealtimePayload(n,Mr({eventId:n,sessionId:Qr(e),createdAt:this.now(),reason:t?.reason}))}async sendRealtimePayload(e,t){await this.opts.socket.sendBinary(Nr({seqId:this.nextSeqId(),logId:this.nextLogId(),service:33555721,method:1,payloadEncoding:`binary`,payloadType:`application/x-protobuf`,payload:t,msgId:e}))}nextSeqId(){return this.opts.nextSeqId?this.opts.nextSeqId():(this.seq+=1n,this.seq)}nextLogId(){return this.opts.nextLogId?this.opts.nextLogId():(this.log+=1n,this.log)}nextEventId(){return this.opts.nextEventId?.()??`meeting-client-event-${Date.now()}-${this.nextSeqId()}`}now(){return this.opts.now?.()??new Date().toISOString()}};function Qr(e){if(typeof e==`bigint`)return e;if(!Number.isSafeInteger(e))throw Error(`Feishu meeting realtime session id must be a safe integer or bigint`);return BigInt(e)}async function $r(e,t){let n;try{return await Promise.race([e,new Promise(e=>{n=setTimeout(()=>e(void 0),t)})])}finally{n&&clearTimeout(n)}}async function ei(e){let t=bi(e.meetingId,`meetingId`),n=ti(e.workspaceRoot,t),r=yi(t,e.transcriptEvents);if(e.transcriptEvents.length===0)return{decision:`NO_REPLY`,spokenReplies:[],pendingSpokenSummaries:[],speechSuppressed:e.speechSuppressed??!1};let i=_i(e.transcriptEvents,e.wakePhrases),a=vi(e.transcriptEvents),o=a?`HANDOFF_TO_SPEAKER reflective silence opportunity`:i?`HANDOFF_TO_SPEAKER explicit invite: ${i}`:await ni({...e,meetingId:t,cwd:n}),s=i||a?`HANDOFF_TO_SPEAKER`:fi(o);if(await new fr().appendTeammateSummary(n,{decision:s===`HANDOFF_TO_SPEAKER`?`HANDOFF_TO_MAIN`:`NO_REPLY`,summary:pi(o,s),messageCount:e.transcriptEvents.length,sourceRefs:r}),s===`NO_REPLY`)return{decision:s,spokenReplies:[],pendingSpokenSummaries:[],speechSuppressed:e.speechSuppressed??!1};if(e.speechSuppressed&&!i)return{decision:s,spokenReplies:[],pendingSpokenSummaries:[],speechSuppressed:!0};let c=(await ri({...e,meetingId:t,cwd:n,fastDecisionText:o})).trim(),l=gi(c);if(l){let r=await ii({...e,meetingId:t,cwd:n,executionRequest:l});return{decision:s,spokenReplies:[],pendingSpokenSummaries:r.trim()?[r.trim()]:[],speechSuppressed:!1}}return!c||mi(c)||hi(c)?{decision:s,spokenReplies:[],pendingSpokenSummaries:[],speechSuppressed:!1}:{decision:s,spokenReplies:[{text:c,source:`speaking_session`}],pendingSpokenSummaries:[],speechSuppressed:!1}}function ti(e,t){return f(e,`meeting`,Z(t))}async function ni(e){let t=`meeting-fast-decision:${e.meetingId}:${Date.now()}`,n=qn({requestId:t,traceId:t,sessionId:`meeting_fast_decision_${Z(e.meetingId)}_${Date.now()}`,conversationId:`meeting_${Z(e.meetingId)}`,entrypoint:`event`,cwd:e.cwd,prompt:oi(e.meetingId,e.transcriptEvents,e.parentContextSummary),model:e.model,transcriptMode:`ephemeral`,maxTurns:1,allowSignalNoReplyTool:!0,policy:{disallowedTools:[{tool:`ask_user`},{tool:`request_permission`}],maxTurns:1,maxToolCalls:0,maxRuntimeMs:3e3,turnPolicy:{maxTextCharsPerTurn:300,textBudgetExceededAction:`discard_turn`}},identity:e.owner,metadata:{channel:`feishu-meeting`,eventKind:`meeting-fast-decision`,meetingId:e.meetingId,...e.parentSessionId?{parentSessionId:e.parentSessionId}:{}}});return di(e.runtime,n)}async function ri(e){let t=`meeting-speaking:${e.meetingId}:${Date.now()}`,n=qn({requestId:t,traceId:t,sessionId:`meeting_speaking_${Z(e.meetingId)}`,conversationId:`meeting_${Z(e.meetingId)}`,entrypoint:`event`,cwd:e.cwd,prompt:si(e.meetingId,e.transcriptEvents,e.fastDecisionText,e.parentContextSummary,e.pendingSpokenSummaries),model:e.model,transcriptMode:`persistent`,maxTurns:2,policy:ai({maxTurns:2,maxRuntimeMs:1e4}),identity:e.owner,metadata:{channel:`feishu-meeting`,eventKind:`meeting-speaking-session`,meetingId:e.meetingId,...e.parentSessionId?{parentSessionId:e.parentSessionId}:{}}});return di(e.runtime,n)}async function ii(e){let t=`meeting-execution:${e.meetingId}:${Date.now()}`,n=qn({requestId:t,traceId:t,sessionId:`meeting_execution_${Z(e.meetingId)}_${Date.now()}`,conversationId:`meeting_${Z(e.meetingId)}`,entrypoint:`event`,cwd:e.cwd,prompt:li(e.meetingId,e.executionRequest,e.parentContextSummary),model:e.model,transcriptMode:`ephemeral`,maxTurns:3,policy:ai({maxTurns:3,maxRuntimeMs:3e4}),identity:e.owner,metadata:{channel:`feishu-meeting`,eventKind:`meeting-execution-subagent`,meetingId:e.meetingId,...e.parentSessionId?{parentSessionId:e.parentSessionId}:{}}});return di(e.runtime,n)}function ai(e){return{disallowedTools:[{tool:`ask_user`},{tool:`request_permission`}],maxTurns:e.maxTurns,maxRuntimeMs:e.maxRuntimeMs,turnPolicy:{maxTextCharsPerTurn:500,textBudgetExceededAction:`discard_turn`}}}function oi(e,t,n){let r=t.map(e=>{let t=e.speaker.name||e.speaker.openId||e.speaker.userId||e.speaker.participantId;return`[${e.timestamp}] ${t}: ${e.text}`}).join(`
|
|
28
|
+
`);return[`[会议旁听快速判定]`,`meeting_id: ${e}`,`只判断是否应该把这段会议窗口交给会议发言 session;不要回答用户,不要调用工具。`,`如果不需要参与,必须以 NO_REPLY 开头。`,`如果应该参与,必须以 HANDOFF_TO_SPEAKER 开头,并给出一句极短理由。`,``,...ui(n),``,`<meeting_window>`,r,`</meeting_window>`].join(`
|
|
29
|
+
`)}function si(e,t,n,r,i){return[`[会议发言任务]`,`meeting_id: ${e}`,`你是本场会议的发言 session。只输出参会者应该听到的简短自然语言,不输出 thinking、工具轨迹或内部判定。`,`如果此刻不应该说话,输出 NO_REPLY。`,`快速判定:${n.trim().slice(0,500)}`,``,...ui(r),...ci(i),``,`<meeting_window>`,t.map(e=>{let t=e.speaker.name||e.speaker.openId||e.speaker.userId||e.speaker.participantId;return`[${e.timestamp}] ${t}: ${e.text}`}).join(`
|
|
30
30
|
`),`</meeting_window>`].join(`
|
|
31
|
-
`)}function
|
|
32
|
-
`).slice(0,2e3),`</pending_execution_results>`]}function
|
|
33
|
-
`)}function li(e){let t=e?.trim();return t?[`<parent_im_context>`,t.slice(0,2e3),`</parent_im_context>`]:[]}async function ui(e,t){let n=``;return await new Promise(r=>{e.executePrompt(t,{onTextDelta:e=>{n+=e},onResult:e=>{!n&&e.result&&(n=e.result),r()},onError:()=>r()}).catch(()=>r())}),n}function di(e){return e.trim().match(/^([A-Z_]+)/i)?.[1]?.toUpperCase()===`HANDOFF_TO_SPEAKER`?`HANDOFF_TO_SPEAKER`:`NO_REPLY`}function fi(e,t){return e.trim().replace(/^(HANDOFF_TO_SPEAKER|NO_REPLY)\b[\s::-]*/i,``).trim()||t}function pi(e){return e.trim().toUpperCase().startsWith(`NO_REPLY`)}function mi(e){let t=e.trim();return/^(thinking|thought|reasoning|tool|tool_call|tool_result)\s*[::]/i.test(t)||/^<\/?(tool|thinking|reasoning|tool_call|tool_result)\b/i.test(t)}function hi(e){return e.match(/^EXECUTE_SUBAGENT\s*[::-]\s*(.+)$/is)?.[1]?.trim()||void 0}function gi(e,t){let n=(t||[]).map(e=>e.trim()).filter(Boolean);if(n.length!==0)for(let t of e){let e=t.text.toLocaleLowerCase(),r=n.find(t=>e.includes(t.toLocaleLowerCase()));if(r)return r}}function _i(e){return e.some(e=>e.text.trim()===`[reflective silence opportunity]`)}function vi(e,t){return t.map(t=>`meeting:${e}:${t.id}`)}function Z(e){return e.trim().replace(/[^a-zA-Z0-9_-]+/g,`_`)}function yi(e,t){let n=e.trim();if(!n)throw Error(`Missing ${t}`);return n}const bi={sampleRate:24e3,channels:1,encoding:`s16le`};async function xi(e){if(e.interrupted||e.interruptSignal?.aborted)return await e.sink.clear(),{spokenReplyCount:0,appendedFrameCount:0,appendedAudioDurationMs:0,cleared:!0};if(e.speechSuppressed)return{spokenReplyCount:0,appendedFrameCount:0,appendedAudioDurationMs:0,cleared:!1};let t=0,n=0,r=0,i=0,a=!1,o=e.frameDurationMs??100;for(let s of e.spokenReplies){if(e.interruptSignal?.aborted)return await e.sink.clear(),{spokenReplyCount:i,appendedFrameCount:n,appendedAudioDurationMs:r,cleared:!0};let c=s.text.trim();if(c){i+=1;for(let l of Ci(c)){if(e.interruptSignal?.aborted)return await e.sink.clear(),{spokenReplyCount:i,appendedFrameCount:n,appendedAudioDurationMs:r,cleared:!0};let c=await e.tts.synthesize({meetingId:e.meetingId,text:l,language:s.language});for await(let l of c)for(let c of Si(l,{frameDurationMs:o})){if(e.interruptSignal?.aborted)return await e.sink.clear(),{spokenReplyCount:i,appendedFrameCount:n,appendedAudioDurationMs:r,cleared:!0};a||(a=!0,e.onSpeechOutputStarted?.(s)),t+=1,await e.sink.appendPcm({meetingId:e.meetingId,sequence:t,pcm:c,format:bi,durationMs:Ti(c)}),await Promise.resolve(),n+=1,r+=Ti(c)}}}}return{spokenReplyCount:i,appendedFrameCount:n,appendedAudioDurationMs:r,cleared:!1}}function Si(e,t){let n=wi(t?.frameDurationMs??100);if(e.byteLength<=n)return e.byteLength===0?[]:[e];let r=[];for(let t=0;t<e.byteLength;t+=n)r.push(e.slice(t,Math.min(t+n,e.byteLength)));return r}function Ci(e){let t=e.replace(/\s+/g,` `).trim();if(!t)return[];let n=[],r=0;for(let e=0;e<t.length;e+=1){if(!/[。!?.!?]/u.test(t[e]))continue;let i=t.slice(r,e+1).trim();for(i&&n.push(i),r=e+1;t[r]===` `;)r+=1}let i=t.slice(r).trim();return i&&n.push(i),n}function wi(e){return Math.round(bi.sampleRate*e/1e3)*2}function Ti(e){let t=e.byteLength/2;return Math.round(t/bi.sampleRate*1e3)}async function Ei(e){let t=await $r(e);return{teammate:t,voice:await xi({meetingId:e.meetingId,spokenReplies:t.spokenReplies,speechSuppressed:t.speechSuppressed,interrupted:e.interrupted,interruptSignal:e.interruptSignal,onSpeechOutputStarted:e.onSpeechOutputStarted,tts:e.tts,sink:e.sink})}}async function Di(e){let t=e.maxWindowEvents??1,n=e.now??Date.now,r=e.echoSuppressionTailMs??800,i=e.interruptOnAudio??!0,a=e.participationCooldownMs??0,o=[],s=0,c=0,l=0,u=0,d=0,f=0,p=0,m=0,h=!1,g=[],_,v,y=async(t,i)=>{let o=n(),s=await Ei({...e,transcriptEvents:t,pendingSpokenSummaries:g,tts:e.tts,sink:e.sink,speechSuppressed:h,interruptSignal:i.abort.signal,onSpeechOutputStarted:e=>{i.speaking=!0,i.spokenText=e.text}});u+=1,f+=s.voice.spokenReplyCount;let c=g.length>0;g=[...g,...s.teammate.pendingSpokenSummaries],!c&&g.length>0&&(_=o),s.voice.spokenReplyCount>0&&(g=[],_=void 0),h=s.voice.cleared?!0:s.teammate.speechSuppressed,s.voice.spokenReplyCount>0&&s.voice.appendedAudioDurationMs>0&&(p=Math.max(p,n()+s.voice.appendedAudioDurationMs+r),m=Math.max(m,n()+a))},b=e.source.frames({durationMs:e.durationMs})[Symbol.asyncIterator]();for(;!e.abortSignal?.aborted;){let r=await Mi(b,e.abortSignal);if(!r||r.done)break;let a=r.value;s+=1,v?.speaking&&i&&!v.interrupted&&(e.voiceActivityDetector?.(a,{meetingId:e.meetingId,currentSpokenText:v.spokenText})??`ignore`)===`interrupt`&&(v.interrupted=!0,d+=1,h=!0,v.abort.abort());let u=await e.transcriber.push(a);for(let t of u){let r=Oi(t,e.wakePhrases);if(v?.speaking&&i&&!v.interrupted){if(Ni(t.text,v.spokenText)){l+=1;continue}v.interrupted||(v.interrupted=!0,d+=1,h=!0,v.abort.abort()),l+=1;continue}if(r){n()<m&&(l+=ki(o,e.wakePhrases)),m=0,h=!1,o.push(t),v||(c+=1);continue}if(n()<p){l+=1;continue}if(h){l+=1;continue}if(n()<m){l+=1;continue}o.push(t),v||(c+=1)}if(o.length>=t&&!v){let e=o.splice(0,o.length),t={abort:new AbortController,interrupted:!1,speaking:!1,spokenText:void 0,promise:Promise.resolve()};t.promise=y(e,t).finally(()=>{v===t&&(v=void 0)}),v=t;continue}if(Ai({eventCount:u.length,pendingSpokenSummaryCount:g.length,pendingSpokenSummariesSince:_,reflectiveSilenceMs:e.reflectiveSilenceMs,activeTurn:v,speechSuppressed:h,echoSuppressedUntil:p,participationCooldownUntil:m,now:n()})){let t={abort:new AbortController,interrupted:!1,speaking:!1,spokenText:void 0,promise:Promise.resolve()};t.promise=y([ji(e.meetingId,n())],t).finally(()=>{v===t&&(v=void 0)}),v=t}}e.abortSignal?.aborted&&b.return?.();let ee=await e.transcriber.flush?.()??[];for(let t of ee){if(Oi(t,e.wakePhrases)){n()<m&&(l+=ki(o,e.wakePhrases)),m=0,h=!1,o.push(t),v||(c+=1);continue}if(n()<p){l+=1;continue}if(h){l+=1;continue}if(n()<m){l+=1;continue}o.push(t),v||(c+=1)}v&&await v.promise,Ai({eventCount:0,pendingSpokenSummaryCount:g.length,pendingSpokenSummariesSince:_,reflectiveSilenceMs:e.reflectiveSilenceMs,activeTurn:v,speechSuppressed:h,echoSuppressedUntil:p,participationCooldownUntil:m,now:n()})&&await y([ji(e.meetingId,n())],{abort:new AbortController,speaking:!1});let x=o.splice(0,o.length).filter(t=>Oi(t,e.wakePhrases)?(n()<m&&(l+=ki(o,e.wakePhrases)),m=0,h=!1,!0):n()<p||h||n()<m?(l+=1,!1):!0);return c+=x.length,x.length>0&&await y(x,{abort:new AbortController,speaking:!1}),await e.transcriber.close?.(),{audioFrameCount:s,transcriptEventCount:c,suppressedTranscriptEventCount:l,voiceTurnCount:u,interruptedVoiceTurnCount:d,spokenReplyCount:f}}function Oi(e,t){let n=(t||[]).map(e=>e.trim()).filter(Boolean);if(n.length===0)return!1;let r=e.text.toLocaleLowerCase();return n.some(e=>r.includes(e.toLocaleLowerCase()))}function ki(e,t){let n=0;for(let r=e.length-1;r>=0;--r)Oi(e[r],t)||(e.splice(r,1),n+=1);return n}function Ai(e){return e.eventCount===0&&e.pendingSpokenSummaryCount>0&&e.pendingSpokenSummariesSince!=null&&e.reflectiveSilenceMs!=null&&e.reflectiveSilenceMs>=0&&!e.activeTurn&&!e.speechSuppressed&&e.now>=e.echoSuppressedUntil&&e.now>=e.participationCooldownUntil&&e.now-e.pendingSpokenSummariesSince>=e.reflectiveSilenceMs}function ji(e,t){return{id:`reflective-silence:${e}:${t}`,text:`[reflective silence opportunity]`,timestamp:new Date(t).toISOString(),speaker:{participantId:`meeting-silence`,name:`meeting silence`}}}async function Mi(e,t){if(!t)return e.next();if(t.aborted)return;let n,r=new Promise(e=>{let r=()=>{n?.(),e(void 0)};n=()=>t.removeEventListener(`abort`,r),t.addEventListener(`abort`,r,{once:!0})});return Promise.race([e.next().finally(()=>n?.()),r])}function Ni(e,t){if(!t)return!1;let n=Pi(e),r=Pi(t);return!n||!r?!1:r.includes(n)||n.includes(r)}function Pi(e){return e.toLocaleLowerCase().replace(/[^\p{L}\p{N}]+/gu,``)}async function Fi(e){let t=Hi(await g(e,`utf-8`));return{appId:Wi(t,`app_id`),accessKey:Wi(t,`ak`),secretKey:Wi(t,`sk`),apiKey:t.get(`tts_api_key`)||t.get(`ark_api_key`)||t.get(`api_key`)||process.env.VOLC_TTS_API_KEY||process.env.ARK_API_KEY,docsUrl:t.get(`接口文档`)||t.get(`docs_url`),endpoint:t.get(`endpoint`)||`wss://openspeech.bytedance.com/api/v3/tts/bidirection`,resourceId:t.get(`resource_id`)||`seed-tts-2.0`}}function Ii(e){return{appId:`[redacted]`,accessKey:`[redacted]`,secretKey:`[redacted]`,apiKey:e.apiKey?`[redacted]`:void 0,docsUrl:e.docsUrl,endpoint:e.endpoint,resourceId:e.resourceId}}function Li(e,t){return e.apiKey?{"X-Api-Key":e.apiKey,"X-Api-Resource-Id":e.resourceId,...t?.connectId?{"X-Api-Connect-Id":t.connectId}:{}}:{"X-Api-App-Id":e.appId,"X-Api-Access-Key":e.accessKey,"X-Api-Resource-Id":e.resourceId,...t?.connectId?{"X-Api-Connect-Id":t.connectId}:{}}}async function Ri(e){let t=Hi(await g(e,`utf-8`)),n=t.get(`asr_api_key`)||t.get(`realtime_asr_api_key`)||t.get(`volc_realtime_asr_api_key`)||t.get(`ark_api_key`)||t.get(`api_key`)||t.get(`bearer_token`)||process.env.VOLC_REALTIME_ASR_API_KEY||process.env.ARK_API_KEY||``;if(!n)throw Error([`Missing Volc realtime ASR API key.`,`Set asr_api_key / ark_api_key in secrets.cfg or VOLC_REALTIME_ASR_API_KEY / ARK_API_KEY in the environment.`,`The TTS app_id/ak/sk credentials are not the realtime ASR bearer API key.`,`Docs: https://www.volcengine.com/docs/6561/1594360?lang=zh`].join(` `));return{apiKey:n,endpoint:t.get(`asr_endpoint`)||`wss://ai-gateway.vei.volces.com/v1/realtime`,model:t.get(`asr_model`)||`bigmodel`}}function zi(e){return{apiKey:`[redacted]`,endpoint:e.endpoint,model:e.model}}function Bi(e){let t=new URL(e.endpoint);return t.searchParams.set(`model`,e.model),t.toString()}function Vi(e){return{Authorization:`Bearer ${e.apiKey}`}}function Hi(e){let t=new Map;for(let n of e.split(/\r?\n/)){let e=n.trim();if(!e||e.startsWith(`#`))continue;let r=Ui(e);if(r<0)continue;let i=e.slice(0,r).trim(),a=e.slice(r+1).trim();i&&a&&t.set(i,a)}return t}function Ui(e){return[e.indexOf(`:`),e.indexOf(`:`),e.indexOf(`=`)].filter(e=>e>=0).sort((e,t)=>e-t)[0]??-1}function Wi(e,t){let n=e.get(t);if(!n)throw Error(`Missing Volc TTS config entry: ${t}`);return n}var Gi=class{bufferedAudioDurationMs=0;constructor(e){this.opts=e}async push(e){return await this.opts.asr.appendFrame(e),this.bufferedAudioDurationMs+=e.durationMs??Ki(e),this.bufferedAudioDurationMs>=(this.opts.commitAudioDurationMs??800)&&(await this.opts.asr.commit(),this.bufferedAudioDurationMs=0),this.drainTranscriptEvents({frame:e,timeoutMs:this.opts.transcriptDrainTimeoutMs??5})}async flush(){return this.bufferedAudioDurationMs>0&&(await this.opts.asr.commit(),this.bufferedAudioDurationMs=0),this.drainTranscriptEvents({timeoutMs:500})}async close(){await this.opts.asr.close()}toTranscriptEvent(e,t){return{id:t.id,text:t.text,timestamp:t.timestamp,speaker:{participantId:e.source||e.trackId||`unknown`,name:e.source}}}async drainTranscriptEvents(e){let t=[];for(;;){let n=await this.opts.asr.receiveTranscript({timeoutMs:e.timeoutMs});if(!n)return t;n.isFinal&&t.push(e.frame?this.toTranscriptEvent(e.frame,n):{id:n.id,text:n.text,timestamp:n.timestamp,speaker:{participantId:`unknown`}})}}};function Ki(e){return Math.round(e.pcm.byteLength/2/e.format.sampleRate*1e3)}function qi(e,t){if(t.fromSampleRate===t.toSampleRate)return e;if(t.fromSampleRate!==24e3||t.toSampleRate!==16e3)throw Error(`Only 24kHz to 16kHz PCM16 mono downsampling is supported`);if(e.byteLength%2!=0)throw Error(`PCM16 byte length must be even`);let n=new Int16Array(e.buffer,e.byteOffset,e.byteLength/2),r=Math.floor(n.length*t.toSampleRate/t.fromSampleRate),i=new Int16Array(r);for(let e=0;e<r;e+=1)i[e]=n[Math.floor(e*t.fromSampleRate/t.toSampleRate)]??0;return new Uint8Array(i.buffer,i.byteOffset,i.byteLength)}const Ji=16e3;var Yi=class{configured=!1;nextAudioBufferId=0;constructor(e){this.opts=e}async configure(){this.configured||=(await this.opts.transport.send(JSON.stringify({type:`transcription_session.update`,session:{input_audio_format:`pcm16`,input_audio_sample_rate:this.opts.inputSampleRate??Ji}})),!0)}async appendFrame(e){await this.configure();let t=qi(e.pcm,{fromSampleRate:e.format.sampleRate,toSampleRate:this.opts.inputSampleRate??Ji});t.byteLength!==0&&await this.opts.transport.send(JSON.stringify({type:`input_audio_buffer.append`,audio:Buffer.from(t).toString(`base64`)}))}async commit(){await this.configure(),await this.opts.transport.send(JSON.stringify({type:`input_audio_buffer.commit`}))}async receiveTranscript(e){let t=e?.timeoutMs===void 0?void 0:Date.now()+e.timeoutMs;for(;;){let e=t===void 0?void 0:t-Date.now();if(e!==void 0&&e<=0)return;let n=await this.opts.transport.receive(e===void 0?void 0:{timeoutMs:e});if(!n)return;let r=JSON.parse(n);if(r.type===`error`)throw Error(`Volc realtime ASR error: ${r.error?.code??`unknown`} ${r.error?.message??`unknown error`}`);if(r.type===`conversation.item.input_audio_transcription.result`){let e=r.delta??r.transcript??``;if(!e.trim())continue;return{id:this.segmentId(r),text:e,timestamp:new Date().toISOString(),isFinal:!1}}if(r.type===`conversation.item.input_audio_transcription.completed`){let e=r.transcript??r.delta??``;if(!e.trim())continue;return{id:this.segmentId(r),text:e,timestamp:new Date().toISOString(),isFinal:!0}}}}async close(){await this.opts.transport.close()}segmentId(e){return e.item_id?`${e.item_id}:${e.content_index??0}`:(this.nextAudioBufferId+=1,`asr:${this.nextAudioBufferId}`)}};function Q(e){let t=Buffer.from(JSON.stringify(e.payload),`utf8`);return Zi({messageType:1,serializationCompression:16,event:e.event,sessionId:e.sessionId,payload:t})}function Xi(e){let t=Buffer.from(e);if(t.byteLength<12)throw Error(`Volc TTS frame too short`);if(t[0]!==17)throw Error(`Unsupported Volc TTS frame header`);let n=(t[1]??0)>>4,r=4,i=t.readUInt32BE(r);r+=4;let a=t.readUInt32BE(r);r+=4;let o;if(r+a===t.byteLength)return{event:i,messageType:n,payload:t.subarray(r,r+a)};let s=a;s>0&&(o=t.subarray(r,r+s).toString(`utf8`),r+=s);let c=t.readUInt32BE(r);r+=4;let l=t.subarray(r,r+c);return{event:i,messageType:n,sessionId:o,payload:l}}function Zi(e){let t=Buffer.from(e.sessionId??``,`utf8`),n=8+(t.byteLength>0?4+t.byteLength:0)+4+e.payload.byteLength,r=Buffer.alloc(n),i=0;return r[i]=17,i+=1,r[i]=e.messageType<<4|4,i+=1,r[i]=e.serializationCompression,i+=1,r[i]=0,i+=1,r.writeUInt32BE(e.event,i),i+=4,t.byteLength>0&&(r.writeUInt32BE(t.byteLength,i),i+=4,t.copy(r,i),i+=t.byteLength),r.writeUInt32BE(e.payload.byteLength,i),i+=4,e.payload.copy(r,i),r}var Qi=class{connected=!1;constructor(e){this.opts=e}async*synthesize(e){let t=e.meetingId;await this.ensureConnection(),await this.startSession(t),await this.sendTaskRequest(t,e.text),await this.finishSession(t);let n=!1;for(;;){let e=await $i(this.opts.transport,1e4);if(!e){if(n)return;throw Error(`Volc TTS timed out waiting for audio response`)}let t=Xi(e);if((t.event===352||t.messageType===11)&&(n=!0,yield t.payload),t.event===152||t.event===151||t.event===153)return}}async close(){this.connected&&=(await this.opts.transport.send(Q({event:2,payload:{}})),await this.opts.transport.close(),!1)}async ensureConnection(){this.connected||=(await this.opts.transport.send(Q({event:1,payload:{}})),await this.expectEvent(50),!0)}async startSession(e){await this.opts.transport.send(Q({event:100,sessionId:e,payload:{event:100,namespace:`BidirectionalTTS`,user:{uid:this.opts.uid},req_params:{text:``,speaker:this.opts.speaker,audio_params:{format:`pcm`,sample_rate:24e3}}}})),await this.expectEvent(150)}async sendTaskRequest(e,t){await this.opts.transport.send(Q({event:200,sessionId:e,payload:{event:200,namespace:`BidirectionalTTS`,req_params:{text:t}}}))}async finishSession(e){await this.opts.transport.send(Q({event:102,sessionId:e,payload:{event:102,namespace:`BidirectionalTTS`}}))}async expectEvent(e){let t=await $i(this.opts.transport,1e4);if(!t)throw Error(`Volc TTS timed out waiting for event ${e}`);let n=Xi(t);if(n.event!==e)throw Error(`Volc TTS expected event ${e}, got ${n.event??`unknown`}`)}};async function $i(e,t){let n;try{return await Promise.race([e.receive(),new Promise(e=>{n=setTimeout(()=>e(void 0),t)})])}finally{n&&clearTimeout(n)}}var ea=class e{received=[];waiters=[];closed=!1;constructor(e){this.ws=e,this.ws.on(`message`,e=>this.push(e)),this.ws.on(`close`,()=>this.finish()),this.ws.on(`error`,()=>this.finish())}static async connect(t){let n=new _e(t.url,{headers:t.headers});return await na(n,t.openTimeoutMs??1e4),new e(n)}async send(e){await this.sendBinary(e)}async sendBinary(e){if(this.ws.readyState!==_e.OPEN)throw Error(`WebSocket is not open`);await new Promise((t,n)=>{this.ws.send(e,{binary:!0},e=>{e?n(e):t()})})}async receive(){return this.receiveBinary()}async receiveBinary(){let e=this.received.shift();if(e)return e;if(!this.closed)return new Promise(e=>{this.waiters.push(e)})}async close(){this.closed||(await new Promise(e=>{this.ws.once(`close`,()=>e()),this.ws.close(),setTimeout(e,1e3).unref()}),this.finish())}push(e){let t=ra(e),n=this.waiters.shift();if(n){n(t);return}this.received.push(t)}finish(){if(!this.closed){this.closed=!0;for(let e of this.waiters.splice(0))e(void 0)}}},ta=class e{received=[];waiters=[];closed=!1;constructor(e){this.ws=e,this.ws.on(`message`,e=>this.push(e)),this.ws.on(`close`,()=>this.finish()),this.ws.on(`error`,()=>this.finish())}static async connect(t){let n=new _e(t.url,{headers:t.headers});return await na(n,t.openTimeoutMs??1e4),new e(n)}async send(e){if(this.ws.readyState!==_e.OPEN)throw Error(`WebSocket is not open`);await new Promise((t,n)=>{this.ws.send(e,e=>{e?n(e):t()})})}async receive(e){let t=this.received.shift();if(t)return t;if(!this.closed)return new Promise(t=>{let n,r=e=>{n&&clearTimeout(n),t(e)};this.waiters.push(r),e?.timeoutMs!==void 0&&(n=setTimeout(()=>{let e=this.waiters.indexOf(r);e>=0&&this.waiters.splice(e,1),t(void 0)},e.timeoutMs))})}async close(){this.closed||(await new Promise(e=>{this.ws.once(`close`,()=>e()),this.ws.close(),setTimeout(e,1e3).unref()}),this.finish())}push(e){let t=ra(e).toString(`utf8`),n=this.waiters.shift();if(n){n(t);return}this.received.push(t)}finish(){if(!this.closed){this.closed=!0;for(let e of this.waiters.splice(0))e(void 0)}}};function na(e,t){return new Promise((n,r)=>{let i=setTimeout(()=>{a(),e.close(),r(Error(`Timed out waiting for WebSocket open`))},t),a=()=>{clearTimeout(i),e.off(`open`,o),e.off(`error`,s)},o=()=>{a(),n()},s=e=>{a(),r(e)};e.once(`open`,o),e.once(`error`,s)})}function ra(e){return Buffer.isBuffer(e)?e:e instanceof ArrayBuffer?Buffer.from(e):Array.isArray(e)?Buffer.concat(e):Buffer.from(e)}var ia=e({parseMeetingLiveCheckArgs:()=>ma,parseMeetingLiveSmokeArgs:()=>fa,parseMeetingLiveTeammateArgs:()=>pa,redactMeetingLiveDiagnostic:()=>xa,runMeetingLiveCheck:()=>ua,runMeetingLiveCheckCli:()=>la,runMeetingLiveSmoke:()=>oa,runMeetingLiveSmokeCli:()=>sa,runMeetingLiveTeammate:()=>da,runMeetingLiveTeammateCli:()=>ca});const aa=`zh_female_vv_uranus_bigtts`;async function oa(e){let t=[],n={mode:`smoke`,status:`failed`,meetingNumber:e.meetingNumber,startedAt:new Date().toISOString(),feishuRequestTrace:t},r,i,a,o,s;try{let c=await Fi(e.volcSecretsPath);console.log(`Volc TTS config loaded`,Ii(c)),i=ya(t),console.log(`Joining meeting ${e.meetingNumber} as bot...`),r=(await i.joinBot({meetingNumber:e.meetingNumber,password:e.password})).meetingId,n.meetingId=r,console.log(`Joined meeting, meeting_id=${r}`);let l=await i.getRealtimeEndpoint(r);console.log(`Realtime endpoint acquired, expires_time=${l.expiresTime??`unknown`}`),a=await ea.connect({url:l.websocketUrl});let u=new Xr({socket:a,nextEventId:()=>`meeting-smoke-${C()}`});s=await u.createSession(),n.sessionId=s.toString(),console.log(`Realtime session created, session_id=${s.toString()}`);let d=e.listenMs>0?wa({meetingId:r,sessionId:s,socket:a,durationMs:e.listenMs,rawOutputPath:e.rawOutputPath}):void 0;o=await ea.connect({url:c.endpoint,headers:Li(c,{connectId:C()})});let f=new Qi({transport:o,uid:`larkpal-meeting-smoke`,speaker:e.speaker}),p=new zr({meetingId:r,sessionId:s,transport:u}),m=await xi({meetingId:r,spokenReplies:[{text:e.text,source:`speaking_session`}],tts:f,sink:p});if(n.speech=m,console.log(`Speech sent: replies=${m.spokenReplyCount}, frames=${m.appendedFrameCount}, audio_ms=${m.appendedAudioDurationMs}`),await ga(e.postSpeechWaitMs),d){let e=await d;n.downstream=e,console.log(`Downstream audio observed: frames=${e.frames}, bytes=${e.bytes}`),e.rawOutputPath&&console.log(`Downstream raw PCM written: ${e.rawOutputPath}`)}await u.closeSession(s),await f.close(),n.status=`success`}catch(e){throw n.error=$(e),ba(t),e}finally{n.finishedAt=new Date().toISOString(),await o?.close().catch(()=>void 0),await a?.close().catch(()=>void 0),r&&i&&await i.leaveBot(r).catch(e=>{console.error(`Failed to leave meeting ${r}:`,$(e))}),await Sa(e.summaryOutputPath,n)}}async function sa(e){await oa(fa(e))}async function ca(e){await da(pa(e))}async function la(e){let t=ma(e),n=await ua(t);return console.log(`Meeting live preflight`,JSON.stringify(n,void 0,2)),await Ca(t.summaryOutputPath,n,`meeting live preflight summary`),+!n.ok}async function ua(e){let t=await Fi(e.volcSecretsPath).then(e=>({ok:!0,config:Ii(e)})).catch(e=>({ok:!1,error:$(e)})),n=await Ri(e.volcSecretsPath).then(e=>({ok:!0,config:zi(e)})).catch(e=>({ok:!1,error:$(e)}));return{ok:t.ok&&n.ok,tts:t,asr:n}}async function da(e){let t=[],n={mode:`teammate`,status:`failed`,meetingNumber:e.meetingNumber,startedAt:new Date().toISOString(),feishuRequestTrace:t},r,i,a,o,s,c;try{let l=await Fi(e.volcSecretsPath);console.log(`Volc TTS config loaded`,Ii(l));let u=await Ri(e.volcSecretsPath);console.log(`Volc realtime ASR config loaded`,zi(u));let{adapter:d,model:f}=await wn(`codex-app-server`);i=ya(t),console.log(`Joining meeting ${e.meetingNumber} as bot...`),r=(await i.joinBot({meetingNumber:e.meetingNumber,password:e.password})).meetingId,n.meetingId=r,console.log(`Joined meeting, meeting_id=${r}`);let p=await i.getRealtimeEndpoint(r);a=await ea.connect({url:p.websocketUrl});let m=new Xr({socket:a,nextEventId:()=>`meeting-live-${C()}`});c=await m.createSession(),n.sessionId=c.toString(),console.log(`Realtime session created, session_id=${c.toString()}`),await e.onJoined?.(),o=await ea.connect({url:l.endpoint,headers:Li(l,{connectId:C()})});let h=new Qi({transport:o,uid:`larkpal-meeting-live`,speaker:e.speaker});s=await ta.connect({url:Bi(u),headers:Vi(u)});let g=new Yi({transport:s}),_=new Gi({meetingId:r,asr:g}),v=new Lr({meetingId:r,sessionId:c,socket:a}),y=new zr({meetingId:r,sessionId:c,transport:m}),b=await Di({meetingId:r,source:v,transcriber:_,owner:{tenantKey:e.tenantKey,userId:e.ownerUserId,openId:e.ownerOpenId,userName:e.ownerUserName},parentContextSummary:e.parentContextSummary,parentSessionId:e.parentSessionId,workspaceRoot:e.workspaceRoot,runtime:d,model:f,tts:h,sink:y,abortSignal:e.abortSignal,durationMs:e.durationMs,wakePhrases:e.wakePhrases,reflectiveSilenceMs:e.reflectiveSilenceMs,participationCooldownMs:e.participationCooldownMs});n.teammate=b,console.log(`Meeting live teammate finished`,b),await m.closeSession(c),await h.close(),await g.close(),n.status=`success`}catch(e){throw n.error=$(e),ba(t),e}finally{n.finishedAt=new Date().toISOString(),await s?.close().catch(()=>void 0),await o?.close().catch(()=>void 0),await a?.close().catch(()=>void 0),r&&i&&await i.leaveBot(r).catch(e=>{console.error(`Failed to leave meeting ${r}:`,$(e))}),await Sa(e.summaryOutputPath,n)}}function fa(e){let t=t=>{let n=e.indexOf(t);if(!(n<0))return e[n+1]},n=t(`--meeting-number`);if(!n)throw Error(`Missing --meeting-number`);return{meetingNumber:n,password:t(`--password`),text:t(`--text`)??`这是一条 LarkPal 会议语音链路验证。`,volcSecretsPath:t(`--volc-secrets`)??ha(),speaker:t(`--speaker`)??process.env.LARKPAL_MEETING_TTS_SPEAKER??aa,postSpeechWaitMs:Number(t(`--post-speech-wait-ms`)??`2000`),listenMs:Number(t(`--listen-ms`)??`0`),rawOutputPath:t(`--raw-output`),summaryOutputPath:t(`--summary-output`)}}function pa(e){let t=t=>{let n=e.indexOf(t);if(!(n<0))return e[n+1]},n=t(`--meeting-number`);if(!n)throw Error(`Missing --meeting-number`);let r=t(`--owner-user-id`)??process.env.LARKPAL_MEETING_OWNER_USER_ID;if(!r)throw Error(`Missing --owner-user-id or LARKPAL_MEETING_OWNER_USER_ID`);return{meetingNumber:n,password:t(`--password`),volcSecretsPath:t(`--volc-secrets`)??ha(),speaker:t(`--speaker`)??process.env.LARKPAL_MEETING_TTS_SPEAKER??aa,listenMs:0,rawOutputPath:void 0,summaryOutputPath:t(`--summary-output`),durationMs:Number(t(`--duration-ms`)??`60000`),workspaceRoot:t(`--workspace-root`)??process.env.LARKPAL_WORKSPACE??`/tmp/larkpal-workspace`,parentSessionId:t(`--parent-session-id`)??process.env.LARKPAL_MEETING_PARENT_SESSION_ID,tenantKey:t(`--tenant-key`)??process.env.LARKPAL_MEETING_TENANT_KEY??`meeting-live`,ownerUserId:r,ownerOpenId:t(`--owner-open-id`)??process.env.LARKPAL_MEETING_OWNER_OPEN_ID,ownerUserName:t(`--owner-user-name`)??process.env.LARKPAL_MEETING_OWNER_USER_NAME,wakePhrases:va(t(`--wake-phrases`)??process.env.LARKPAL_MEETING_WAKE_PHRASES??`LarkPal,larkpal`),reflectiveSilenceMs:_a(t(`--reflective-silence-ms`)??process.env.LARKPAL_MEETING_REFLECTIVE_SILENCE_MS),participationCooldownMs:_a(t(`--participation-cooldown-ms`)??process.env.LARKPAL_MEETING_PARTICIPATION_COOLDOWN_MS)}}function ma(e){let t=t=>{let n=e.indexOf(t);if(!(n<0))return e[n+1]};return{volcSecretsPath:t(`--volc-secrets`)??ha(),summaryOutputPath:t(`--summary-output`)}}function ha(){if(process.env.LARKPAL_MEETING_VOLC_SECRETS)return process.env.LARKPAL_MEETING_VOLC_SECRETS;let e=d(process.cwd(),`..`,`secrets.cfg`);return r(e)?e:d(process.cwd(),`secrets.cfg`)}function ga(e){return new Promise(t=>setTimeout(t,e))}function _a(e){if(!(e==null||e.trim()===``))return Number(e)}function va(e){return e.split(`,`).map(e=>e.trim()).filter(Boolean)}function ya(e){return new Vr({appId:process.env.LARK_APP_ID,appSecret:process.env.LARK_APP_SECRET,userAccessToken:process.env.LARK_USER_ACCESS_TOKEN,useLarkCliUserAuth:!0,onRequestTrace:t=>e.push(t)})}function ba(e){e.length!==0&&console.error(`Feishu OpenAPI request trace`,JSON.stringify(e,void 0,2))}function $(e){return xa(e instanceof Error?e.message:String(e))}function xa(e){return e.replace(/\bwss:\/\/\S+/gi,`[redacted-wss-url]`).replace(/\b(token=)[^\s,;]+/gi,`$1[redacted]`).replace(/\b(access_token=)[^\s,;]+/gi,`$1[redacted]`).replace(/\b(refresh_token=)[^\s,;]+/gi,`$1[redacted]`).replace(/\b(password=)[^\s,;]+/gi,`$1[redacted]`).replace(/\b(app_secret=)[^\s,;]+/gi,`$1[redacted]`).replace(/("password"\s*:\s*")[^"]+(")/gi,`$1[redacted]$2`).replace(/("app_secret"\s*:\s*")[^"]+(")/gi,`$1[redacted]$2`).replace(/\b(authorization:\s*bearer\s+)[^\s,;]+/gi,`$1[redacted]`)}async function Sa(e,t){await Ca(e,t,`meeting live summary`)}async function Ca(e,t,n){if(e)try{await h(l(e),{recursive:!0}),await x(e,`${JSON.stringify(t,void 0,2)}\n`,`utf-8`),console.log(`${n} written: ${e}`)}catch(e){console.error(`Failed to write ${n}:`,e instanceof Error?e.message:String(e))}}async function wa(e){let t=new Lr({meetingId:e.meetingId,sessionId:e.sessionId,socket:e.socket}),r;e.rawOutputPath&&(await h(l(e.rawOutputPath),{recursive:!0}),r=n(e.rawOutputPath));let i=0,a=0;try{for await(let n of t.frames({durationMs:e.durationMs}))i+=1,a+=n.pcm.byteLength,r?.write(n.pcm)}finally{await new Promise((e,t)=>{if(!r){e();return}r.end(n=>{n?t(n):e()})})}return{frames:i,bytes:a,rawOutputPath:e.rawOutputPath}}export{xe as A,Yt as C,Ye as D,Xe as E,T as M,Re as O,Xt as S,vt as T,Yn as _,dr as a,Zt as b,Qn as c,Zn as d,Hn as f,Kn as g,Wn as h,wr as i,be as j,ve as k,$n as l,qn as m,da as n,R as o,Un as p,Dr as r,Jn as s,ia as t,Xn as u,z as v,_t as w,Qt as x,wn as y};
|
|
31
|
+
`)}function ci(e){let t=(e||[]).map(e=>e.trim()).filter(Boolean);return t.length===0?[]:[``,`<pending_execution_results>`,t.map(e=>`- ${e}`).join(`
|
|
32
|
+
`).slice(0,2e3),`</pending_execution_results>`]}function li(e,t,n){return[`[会议执行任务]`,`meeting_id: ${e}`,`执行会议发言 session 委派的任务。输出简短结果摘要;不要面向参会者发言。`,``,...ui(n),``,`<execution_request>`,t,`</execution_request>`].join(`
|
|
33
|
+
`)}function ui(e){let t=e?.trim();return t?[`<parent_im_context>`,t.slice(0,2e3),`</parent_im_context>`]:[]}async function di(e,t){let n=``;return await new Promise(r=>{e.executePrompt(t,{onTextDelta:e=>{n+=e},onResult:e=>{!n&&e.result&&(n=e.result),r()},onError:()=>r()}).catch(()=>r())}),n}function fi(e){return e.trim().match(/^([A-Z_]+)/i)?.[1]?.toUpperCase()===`HANDOFF_TO_SPEAKER`?`HANDOFF_TO_SPEAKER`:`NO_REPLY`}function pi(e,t){return e.trim().replace(/^(HANDOFF_TO_SPEAKER|NO_REPLY)\b[\s::-]*/i,``).trim()||t}function mi(e){return e.trim().toUpperCase().startsWith(`NO_REPLY`)}function hi(e){let t=e.trim();return/^(thinking|thought|reasoning|tool|tool_call|tool_result)\s*[::]/i.test(t)||/^<\/?(tool|thinking|reasoning|tool_call|tool_result)\b/i.test(t)}function gi(e){return e.match(/^EXECUTE_SUBAGENT\s*[::-]\s*(.+)$/is)?.[1]?.trim()||void 0}function _i(e,t){let n=(t||[]).map(e=>e.trim()).filter(Boolean);if(n.length!==0)for(let t of e){let e=t.text.toLocaleLowerCase(),r=n.find(t=>e.includes(t.toLocaleLowerCase()));if(r)return r}}function vi(e){return e.some(e=>e.text.trim()===`[reflective silence opportunity]`)}function yi(e,t){return t.map(t=>`meeting:${e}:${t.id}`)}function Z(e){return e.trim().replace(/[^a-zA-Z0-9_-]+/g,`_`)}function bi(e,t){let n=e.trim();if(!n)throw Error(`Missing ${t}`);return n}const xi={sampleRate:24e3,channels:1,encoding:`s16le`};async function Si(e){if(e.interrupted||e.interruptSignal?.aborted)return await e.sink.clear(),{spokenReplyCount:0,appendedFrameCount:0,appendedAudioDurationMs:0,cleared:!0};if(e.speechSuppressed)return{spokenReplyCount:0,appendedFrameCount:0,appendedAudioDurationMs:0,cleared:!1};let t=0,n=0,r=0,i=0,a=!1,o=e.frameDurationMs??100;for(let s of e.spokenReplies){if(e.interruptSignal?.aborted)return await e.sink.clear(),{spokenReplyCount:i,appendedFrameCount:n,appendedAudioDurationMs:r,cleared:!0};let c=s.text.trim();if(c){i+=1;for(let l of wi(c)){if(e.interruptSignal?.aborted)return await e.sink.clear(),{spokenReplyCount:i,appendedFrameCount:n,appendedAudioDurationMs:r,cleared:!0};let c=await e.tts.synthesize({meetingId:e.meetingId,text:l,language:s.language});for await(let l of c)for(let c of Ci(l,{frameDurationMs:o})){if(e.interruptSignal?.aborted)return await e.sink.clear(),{spokenReplyCount:i,appendedFrameCount:n,appendedAudioDurationMs:r,cleared:!0};a||(a=!0,e.onSpeechOutputStarted?.(s)),t+=1,await e.sink.appendPcm({meetingId:e.meetingId,sequence:t,pcm:c,format:xi,durationMs:Ei(c)}),await Promise.resolve(),n+=1,r+=Ei(c)}}}}return{spokenReplyCount:i,appendedFrameCount:n,appendedAudioDurationMs:r,cleared:!1}}function Ci(e,t){let n=Ti(t?.frameDurationMs??100);if(e.byteLength<=n)return e.byteLength===0?[]:[e];let r=[];for(let t=0;t<e.byteLength;t+=n)r.push(e.slice(t,Math.min(t+n,e.byteLength)));return r}function wi(e){let t=e.replace(/\s+/g,` `).trim();if(!t)return[];let n=[],r=0;for(let e=0;e<t.length;e+=1){if(!/[。!?.!?]/u.test(t[e]))continue;let i=t.slice(r,e+1).trim();for(i&&n.push(i),r=e+1;t[r]===` `;)r+=1}let i=t.slice(r).trim();return i&&n.push(i),n}function Ti(e){return Math.round(xi.sampleRate*e/1e3)*2}function Ei(e){let t=e.byteLength/2;return Math.round(t/xi.sampleRate*1e3)}async function Di(e){let t=await ei(e);return{teammate:t,voice:await Si({meetingId:e.meetingId,spokenReplies:t.spokenReplies,speechSuppressed:t.speechSuppressed,interrupted:e.interrupted,interruptSignal:e.interruptSignal,onSpeechOutputStarted:e.onSpeechOutputStarted,tts:e.tts,sink:e.sink})}}async function Oi(e){let t=e.maxWindowEvents??1,n=e.now??Date.now,r=e.echoSuppressionTailMs??800,i=e.interruptOnAudio??!0,a=e.participationCooldownMs??0,o=[],s=0,c=0,l=0,u=0,d=0,f=0,p=0,m=0,h=!1,g=[],_,v,y=async(t,i)=>{let o=n(),s=await Di({...e,transcriptEvents:t,pendingSpokenSummaries:g,tts:e.tts,sink:e.sink,speechSuppressed:h,interruptSignal:i.abort.signal,onSpeechOutputStarted:e=>{i.speaking=!0,i.spokenText=e.text}});u+=1,f+=s.voice.spokenReplyCount;let c=g.length>0;g=[...g,...s.teammate.pendingSpokenSummaries],!c&&g.length>0&&(_=o),s.voice.spokenReplyCount>0&&(g=[],_=void 0),h=s.voice.cleared?!0:s.teammate.speechSuppressed,s.voice.spokenReplyCount>0&&s.voice.appendedAudioDurationMs>0&&(p=Math.max(p,n()+s.voice.appendedAudioDurationMs+r),m=Math.max(m,n()+a))},b=e.source.frames({durationMs:e.durationMs})[Symbol.asyncIterator]();for(;!e.abortSignal?.aborted;){let r=await Ni(b,e.abortSignal);if(!r||r.done)break;let a=r.value;s+=1,v?.speaking&&i&&!v.interrupted&&(e.voiceActivityDetector?.(a,{meetingId:e.meetingId,currentSpokenText:v.spokenText})??`ignore`)===`interrupt`&&(v.interrupted=!0,d+=1,h=!0,v.abort.abort());let u=await e.transcriber.push(a);for(let t of u){let r=ki(t,e.wakePhrases);if(v?.speaking&&i&&!v.interrupted){if(Pi(t.text,v.spokenText)){l+=1;continue}v.interrupted||(v.interrupted=!0,d+=1,h=!0,v.abort.abort()),l+=1;continue}if(r){n()<m&&(l+=Ai(o,e.wakePhrases)),m=0,h=!1,o.push(t),v||(c+=1);continue}if(n()<p){l+=1;continue}if(h){l+=1;continue}if(n()<m){l+=1;continue}o.push(t),v||(c+=1)}if(o.length>=t&&!v){let e=o.splice(0,o.length),t={abort:new AbortController,interrupted:!1,speaking:!1,spokenText:void 0,promise:Promise.resolve()};t.promise=y(e,t).finally(()=>{v===t&&(v=void 0)}),v=t;continue}if(ji({eventCount:u.length,pendingSpokenSummaryCount:g.length,pendingSpokenSummariesSince:_,reflectiveSilenceMs:e.reflectiveSilenceMs,activeTurn:v,speechSuppressed:h,echoSuppressedUntil:p,participationCooldownUntil:m,now:n()})){let t={abort:new AbortController,interrupted:!1,speaking:!1,spokenText:void 0,promise:Promise.resolve()};t.promise=y([Mi(e.meetingId,n())],t).finally(()=>{v===t&&(v=void 0)}),v=t}}e.abortSignal?.aborted&&b.return?.();let ee=await e.transcriber.flush?.()??[];for(let t of ee){if(ki(t,e.wakePhrases)){n()<m&&(l+=Ai(o,e.wakePhrases)),m=0,h=!1,o.push(t),v||(c+=1);continue}if(n()<p){l+=1;continue}if(h){l+=1;continue}if(n()<m){l+=1;continue}o.push(t),v||(c+=1)}v&&await v.promise,ji({eventCount:0,pendingSpokenSummaryCount:g.length,pendingSpokenSummariesSince:_,reflectiveSilenceMs:e.reflectiveSilenceMs,activeTurn:v,speechSuppressed:h,echoSuppressedUntil:p,participationCooldownUntil:m,now:n()})&&await y([Mi(e.meetingId,n())],{abort:new AbortController,speaking:!1});let x=o.splice(0,o.length).filter(t=>ki(t,e.wakePhrases)?(n()<m&&(l+=Ai(o,e.wakePhrases)),m=0,h=!1,!0):n()<p||h||n()<m?(l+=1,!1):!0);return c+=x.length,x.length>0&&await y(x,{abort:new AbortController,speaking:!1}),await e.transcriber.close?.(),{audioFrameCount:s,transcriptEventCount:c,suppressedTranscriptEventCount:l,voiceTurnCount:u,interruptedVoiceTurnCount:d,spokenReplyCount:f}}function ki(e,t){let n=(t||[]).map(e=>e.trim()).filter(Boolean);if(n.length===0)return!1;let r=e.text.toLocaleLowerCase();return n.some(e=>r.includes(e.toLocaleLowerCase()))}function Ai(e,t){let n=0;for(let r=e.length-1;r>=0;--r)ki(e[r],t)||(e.splice(r,1),n+=1);return n}function ji(e){return e.eventCount===0&&e.pendingSpokenSummaryCount>0&&e.pendingSpokenSummariesSince!=null&&e.reflectiveSilenceMs!=null&&e.reflectiveSilenceMs>=0&&!e.activeTurn&&!e.speechSuppressed&&e.now>=e.echoSuppressedUntil&&e.now>=e.participationCooldownUntil&&e.now-e.pendingSpokenSummariesSince>=e.reflectiveSilenceMs}function Mi(e,t){return{id:`reflective-silence:${e}:${t}`,text:`[reflective silence opportunity]`,timestamp:new Date(t).toISOString(),speaker:{participantId:`meeting-silence`,name:`meeting silence`}}}async function Ni(e,t){if(!t)return e.next();if(t.aborted)return;let n,r=new Promise(e=>{let r=()=>{n?.(),e(void 0)};n=()=>t.removeEventListener(`abort`,r),t.addEventListener(`abort`,r,{once:!0})});return Promise.race([e.next().finally(()=>n?.()),r])}function Pi(e,t){if(!t)return!1;let n=Fi(e),r=Fi(t);return!n||!r?!1:r.includes(n)||n.includes(r)}function Fi(e){return e.toLocaleLowerCase().replace(/[^\p{L}\p{N}]+/gu,``)}async function Ii(e){let t=Ui(await _(e,`utf-8`));return{appId:Gi(t,`app_id`),accessKey:Gi(t,`ak`),secretKey:Gi(t,`sk`),apiKey:t.get(`tts_api_key`)||t.get(`ark_api_key`)||t.get(`api_key`)||process.env.VOLC_TTS_API_KEY||process.env.ARK_API_KEY,docsUrl:t.get(`接口文档`)||t.get(`docs_url`),endpoint:t.get(`endpoint`)||`wss://openspeech.bytedance.com/api/v3/tts/bidirection`,resourceId:t.get(`resource_id`)||`seed-tts-2.0`}}function Li(e){return{appId:`[redacted]`,accessKey:`[redacted]`,secretKey:`[redacted]`,apiKey:e.apiKey?`[redacted]`:void 0,docsUrl:e.docsUrl,endpoint:e.endpoint,resourceId:e.resourceId}}function Ri(e,t){return e.apiKey?{"X-Api-Key":e.apiKey,"X-Api-Resource-Id":e.resourceId,...t?.connectId?{"X-Api-Connect-Id":t.connectId}:{}}:{"X-Api-App-Id":e.appId,"X-Api-Access-Key":e.accessKey,"X-Api-Resource-Id":e.resourceId,...t?.connectId?{"X-Api-Connect-Id":t.connectId}:{}}}async function zi(e){let t=Ui(await _(e,`utf-8`)),n=t.get(`asr_api_key`)||t.get(`realtime_asr_api_key`)||t.get(`volc_realtime_asr_api_key`)||t.get(`ark_api_key`)||t.get(`api_key`)||t.get(`bearer_token`)||process.env.VOLC_REALTIME_ASR_API_KEY||process.env.ARK_API_KEY||``;if(!n)throw Error([`Missing Volc realtime ASR API key.`,`Set asr_api_key / ark_api_key in secrets.cfg or VOLC_REALTIME_ASR_API_KEY / ARK_API_KEY in the environment.`,`The TTS app_id/ak/sk credentials are not the realtime ASR bearer API key.`,`Docs: https://www.volcengine.com/docs/6561/1594360?lang=zh`].join(` `));return{apiKey:n,endpoint:t.get(`asr_endpoint`)||`wss://ai-gateway.vei.volces.com/v1/realtime`,model:t.get(`asr_model`)||`bigmodel`}}function Bi(e){return{apiKey:`[redacted]`,endpoint:e.endpoint,model:e.model}}function Vi(e){let t=new URL(e.endpoint);return t.searchParams.set(`model`,e.model),t.toString()}function Hi(e){return{Authorization:`Bearer ${e.apiKey}`}}function Ui(e){let t=new Map;for(let n of e.split(/\r?\n/)){let e=n.trim();if(!e||e.startsWith(`#`))continue;let r=Wi(e);if(r<0)continue;let i=e.slice(0,r).trim(),a=e.slice(r+1).trim();i&&a&&t.set(i,a)}return t}function Wi(e){return[e.indexOf(`:`),e.indexOf(`:`),e.indexOf(`=`)].filter(e=>e>=0).sort((e,t)=>e-t)[0]??-1}function Gi(e,t){let n=e.get(t);if(!n)throw Error(`Missing Volc TTS config entry: ${t}`);return n}var Ki=class{bufferedAudioDurationMs=0;constructor(e){this.opts=e}async push(e){return await this.opts.asr.appendFrame(e),this.bufferedAudioDurationMs+=e.durationMs??qi(e),this.bufferedAudioDurationMs>=(this.opts.commitAudioDurationMs??800)&&(await this.opts.asr.commit(),this.bufferedAudioDurationMs=0),this.drainTranscriptEvents({frame:e,timeoutMs:this.opts.transcriptDrainTimeoutMs??5})}async flush(){return this.bufferedAudioDurationMs>0&&(await this.opts.asr.commit(),this.bufferedAudioDurationMs=0),this.drainTranscriptEvents({timeoutMs:500})}async close(){await this.opts.asr.close()}toTranscriptEvent(e,t){return{id:t.id,text:t.text,timestamp:t.timestamp,speaker:{participantId:e.source||e.trackId||`unknown`,name:e.source}}}async drainTranscriptEvents(e){let t=[];for(;;){let n=await this.opts.asr.receiveTranscript({timeoutMs:e.timeoutMs});if(!n)return t;n.isFinal&&t.push(e.frame?this.toTranscriptEvent(e.frame,n):{id:n.id,text:n.text,timestamp:n.timestamp,speaker:{participantId:`unknown`}})}}};function qi(e){return Math.round(e.pcm.byteLength/2/e.format.sampleRate*1e3)}function Ji(e,t){if(t.fromSampleRate===t.toSampleRate)return e;if(t.fromSampleRate!==24e3||t.toSampleRate!==16e3)throw Error(`Only 24kHz to 16kHz PCM16 mono downsampling is supported`);if(e.byteLength%2!=0)throw Error(`PCM16 byte length must be even`);let n=new Int16Array(e.buffer,e.byteOffset,e.byteLength/2),r=Math.floor(n.length*t.toSampleRate/t.fromSampleRate),i=new Int16Array(r);for(let e=0;e<r;e+=1)i[e]=n[Math.floor(e*t.fromSampleRate/t.toSampleRate)]??0;return new Uint8Array(i.buffer,i.byteOffset,i.byteLength)}const Yi=16e3;var Xi=class{configured=!1;nextAudioBufferId=0;constructor(e){this.opts=e}async configure(){this.configured||=(await this.opts.transport.send(JSON.stringify({type:`transcription_session.update`,session:{input_audio_format:`pcm16`,input_audio_sample_rate:this.opts.inputSampleRate??Yi}})),!0)}async appendFrame(e){await this.configure();let t=Ji(e.pcm,{fromSampleRate:e.format.sampleRate,toSampleRate:this.opts.inputSampleRate??Yi});t.byteLength!==0&&await this.opts.transport.send(JSON.stringify({type:`input_audio_buffer.append`,audio:Buffer.from(t).toString(`base64`)}))}async commit(){await this.configure(),await this.opts.transport.send(JSON.stringify({type:`input_audio_buffer.commit`}))}async receiveTranscript(e){let t=e?.timeoutMs===void 0?void 0:Date.now()+e.timeoutMs;for(;;){let e=t===void 0?void 0:t-Date.now();if(e!==void 0&&e<=0)return;let n=await this.opts.transport.receive(e===void 0?void 0:{timeoutMs:e});if(!n)return;let r=JSON.parse(n);if(r.type===`error`)throw Error(`Volc realtime ASR error: ${r.error?.code??`unknown`} ${r.error?.message??`unknown error`}`);if(r.type===`conversation.item.input_audio_transcription.result`){let e=r.delta??r.transcript??``;if(!e.trim())continue;return{id:this.segmentId(r),text:e,timestamp:new Date().toISOString(),isFinal:!1}}if(r.type===`conversation.item.input_audio_transcription.completed`){let e=r.transcript??r.delta??``;if(!e.trim())continue;return{id:this.segmentId(r),text:e,timestamp:new Date().toISOString(),isFinal:!0}}}}async close(){await this.opts.transport.close()}segmentId(e){return e.item_id?`${e.item_id}:${e.content_index??0}`:(this.nextAudioBufferId+=1,`asr:${this.nextAudioBufferId}`)}};function Q(e){let t=Buffer.from(JSON.stringify(e.payload),`utf8`);return Qi({messageType:1,serializationCompression:16,event:e.event,sessionId:e.sessionId,payload:t})}function Zi(e){let t=Buffer.from(e);if(t.byteLength<12)throw Error(`Volc TTS frame too short`);if(t[0]!==17)throw Error(`Unsupported Volc TTS frame header`);let n=(t[1]??0)>>4,r=4,i=t.readUInt32BE(r);r+=4;let a=t.readUInt32BE(r);r+=4;let o;if(r+a===t.byteLength)return{event:i,messageType:n,payload:t.subarray(r,r+a)};let s=a;s>0&&(o=t.subarray(r,r+s).toString(`utf8`),r+=s);let c=t.readUInt32BE(r);r+=4;let l=t.subarray(r,r+c);return{event:i,messageType:n,sessionId:o,payload:l}}function Qi(e){let t=Buffer.from(e.sessionId??``,`utf8`),n=8+(t.byteLength>0?4+t.byteLength:0)+4+e.payload.byteLength,r=Buffer.alloc(n),i=0;return r[i]=17,i+=1,r[i]=e.messageType<<4|4,i+=1,r[i]=e.serializationCompression,i+=1,r[i]=0,i+=1,r.writeUInt32BE(e.event,i),i+=4,t.byteLength>0&&(r.writeUInt32BE(t.byteLength,i),i+=4,t.copy(r,i),i+=t.byteLength),r.writeUInt32BE(e.payload.byteLength,i),i+=4,e.payload.copy(r,i),r}var $i=class{connected=!1;constructor(e){this.opts=e}async*synthesize(e){let t=e.meetingId;await this.ensureConnection(),await this.startSession(t),await this.sendTaskRequest(t,e.text),await this.finishSession(t);let n=!1;for(;;){let e=await ea(this.opts.transport,1e4);if(!e){if(n)return;throw Error(`Volc TTS timed out waiting for audio response`)}let t=Zi(e);if((t.event===352||t.messageType===11)&&(n=!0,yield t.payload),t.event===152||t.event===151||t.event===153)return}}async close(){this.connected&&=(await this.opts.transport.send(Q({event:2,payload:{}})),await this.opts.transport.close(),!1)}async ensureConnection(){this.connected||=(await this.opts.transport.send(Q({event:1,payload:{}})),await this.expectEvent(50),!0)}async startSession(e){await this.opts.transport.send(Q({event:100,sessionId:e,payload:{event:100,namespace:`BidirectionalTTS`,user:{uid:this.opts.uid},req_params:{text:``,speaker:this.opts.speaker,audio_params:{format:`pcm`,sample_rate:24e3}}}})),await this.expectEvent(150)}async sendTaskRequest(e,t){await this.opts.transport.send(Q({event:200,sessionId:e,payload:{event:200,namespace:`BidirectionalTTS`,req_params:{text:t}}}))}async finishSession(e){await this.opts.transport.send(Q({event:102,sessionId:e,payload:{event:102,namespace:`BidirectionalTTS`}}))}async expectEvent(e){let t=await ea(this.opts.transport,1e4);if(!t)throw Error(`Volc TTS timed out waiting for event ${e}`);let n=Zi(t);if(n.event!==e)throw Error(`Volc TTS expected event ${e}, got ${n.event??`unknown`}`)}};async function ea(e,t){let n;try{return await Promise.race([e.receive(),new Promise(e=>{n=setTimeout(()=>e(void 0),t)})])}finally{n&&clearTimeout(n)}}var ta=class e{received=[];waiters=[];closed=!1;constructor(e){this.ws=e,this.ws.on(`message`,e=>this.push(e)),this.ws.on(`close`,()=>this.finish()),this.ws.on(`error`,()=>this.finish())}static async connect(t){let n=new _e(t.url,{headers:t.headers});return await ra(n,t.openTimeoutMs??1e4),new e(n)}async send(e){await this.sendBinary(e)}async sendBinary(e){if(this.ws.readyState!==_e.OPEN)throw Error(`WebSocket is not open`);await new Promise((t,n)=>{this.ws.send(e,{binary:!0},e=>{e?n(e):t()})})}async receive(){return this.receiveBinary()}async receiveBinary(){let e=this.received.shift();if(e)return e;if(!this.closed)return new Promise(e=>{this.waiters.push(e)})}async close(){this.closed||(await new Promise(e=>{this.ws.once(`close`,()=>e()),this.ws.close(),setTimeout(e,1e3).unref()}),this.finish())}push(e){let t=ia(e),n=this.waiters.shift();if(n){n(t);return}this.received.push(t)}finish(){if(!this.closed){this.closed=!0;for(let e of this.waiters.splice(0))e(void 0)}}},na=class e{received=[];waiters=[];closed=!1;constructor(e){this.ws=e,this.ws.on(`message`,e=>this.push(e)),this.ws.on(`close`,()=>this.finish()),this.ws.on(`error`,()=>this.finish())}static async connect(t){let n=new _e(t.url,{headers:t.headers});return await ra(n,t.openTimeoutMs??1e4),new e(n)}async send(e){if(this.ws.readyState!==_e.OPEN)throw Error(`WebSocket is not open`);await new Promise((t,n)=>{this.ws.send(e,e=>{e?n(e):t()})})}async receive(e){let t=this.received.shift();if(t)return t;if(!this.closed)return new Promise(t=>{let n,r=e=>{n&&clearTimeout(n),t(e)};this.waiters.push(r),e?.timeoutMs!==void 0&&(n=setTimeout(()=>{let e=this.waiters.indexOf(r);e>=0&&this.waiters.splice(e,1),t(void 0)},e.timeoutMs))})}async close(){this.closed||(await new Promise(e=>{this.ws.once(`close`,()=>e()),this.ws.close(),setTimeout(e,1e3).unref()}),this.finish())}push(e){let t=ia(e).toString(`utf8`),n=this.waiters.shift();if(n){n(t);return}this.received.push(t)}finish(){if(!this.closed){this.closed=!0;for(let e of this.waiters.splice(0))e(void 0)}}};function ra(e,t){return new Promise((n,r)=>{let i=setTimeout(()=>{a(),e.close(),r(Error(`Timed out waiting for WebSocket open`))},t),a=()=>{clearTimeout(i),e.off(`open`,o),e.off(`error`,s)},o=()=>{a(),n()},s=e=>{a(),r(e)};e.once(`open`,o),e.once(`error`,s)})}function ia(e){return Buffer.isBuffer(e)?e:e instanceof ArrayBuffer?Buffer.from(e):Array.isArray(e)?Buffer.concat(e):Buffer.from(e)}var aa=e({parseMeetingLiveCheckArgs:()=>ha,parseMeetingLiveSmokeArgs:()=>pa,parseMeetingLiveTeammateArgs:()=>ma,redactMeetingLiveDiagnostic:()=>Sa,runMeetingLiveCheck:()=>da,runMeetingLiveCheckCli:()=>ua,runMeetingLiveSmoke:()=>sa,runMeetingLiveSmokeCli:()=>ca,runMeetingLiveTeammate:()=>fa,runMeetingLiveTeammateCli:()=>la});const oa=`zh_female_vv_uranus_bigtts`;async function sa(e){let t=[],n={mode:`smoke`,status:`failed`,meetingNumber:e.meetingNumber,startedAt:new Date().toISOString(),feishuRequestTrace:t},r,i,a,o,s;try{let c=await Ii(e.volcSecretsPath);console.log(`Volc TTS config loaded`,Li(c)),i=ba(t),console.log(`Joining meeting ${e.meetingNumber} as bot...`),r=(await i.joinBot({meetingNumber:e.meetingNumber,password:e.password})).meetingId,n.meetingId=r,console.log(`Joined meeting, meeting_id=${r}`);let l=await i.getRealtimeEndpoint(r);console.log(`Realtime endpoint acquired, expires_time=${l.expiresTime??`unknown`}`),a=await ta.connect({url:l.websocketUrl});let u=new Zr({socket:a,nextEventId:()=>`meeting-smoke-${w()}`});s=await u.createSession(),n.sessionId=s.toString(),console.log(`Realtime session created, session_id=${s.toString()}`);let d=e.listenMs>0?Ta({meetingId:r,sessionId:s,socket:a,durationMs:e.listenMs,rawOutputPath:e.rawOutputPath}):void 0;o=await ta.connect({url:c.endpoint,headers:Ri(c,{connectId:w()})});let f=new $i({transport:o,uid:`larkpal-meeting-smoke`,speaker:e.speaker}),p=new Br({meetingId:r,sessionId:s,transport:u}),m=await Si({meetingId:r,spokenReplies:[{text:e.text,source:`speaking_session`}],tts:f,sink:p});if(n.speech=m,console.log(`Speech sent: replies=${m.spokenReplyCount}, frames=${m.appendedFrameCount}, audio_ms=${m.appendedAudioDurationMs}`),await _a(e.postSpeechWaitMs),d){let e=await d;n.downstream=e,console.log(`Downstream audio observed: frames=${e.frames}, bytes=${e.bytes}`),e.rawOutputPath&&console.log(`Downstream raw PCM written: ${e.rawOutputPath}`)}await u.closeSession(s),await f.close(),n.status=`success`}catch(e){throw n.error=$(e),xa(t),e}finally{n.finishedAt=new Date().toISOString(),await o?.close().catch(()=>void 0),await a?.close().catch(()=>void 0),r&&i&&await i.leaveBot(r).catch(e=>{console.error(`Failed to leave meeting ${r}:`,$(e))}),await Ca(e.summaryOutputPath,n)}}async function ca(e){await sa(pa(e))}async function la(e){await fa(ma(e))}async function ua(e){let t=ha(e),n=await da(t);return console.log(`Meeting live preflight`,JSON.stringify(n,void 0,2)),await wa(t.summaryOutputPath,n,`meeting live preflight summary`),+!n.ok}async function da(e){let t=await Ii(e.volcSecretsPath).then(e=>({ok:!0,config:Li(e)})).catch(e=>({ok:!1,error:$(e)})),n=await zi(e.volcSecretsPath).then(e=>({ok:!0,config:Bi(e)})).catch(e=>({ok:!1,error:$(e)}));return{ok:t.ok&&n.ok,tts:t,asr:n}}async function fa(e){let t=[],n={mode:`teammate`,status:`failed`,meetingNumber:e.meetingNumber,startedAt:new Date().toISOString(),feishuRequestTrace:t},r,i,a,o,s,c;try{let l=await Ii(e.volcSecretsPath);console.log(`Volc TTS config loaded`,Li(l));let u=await zi(e.volcSecretsPath);console.log(`Volc realtime ASR config loaded`,Bi(u));let{adapter:d,model:f}=await wn(`codex-app-server`);i=ba(t),console.log(`Joining meeting ${e.meetingNumber} as bot...`),r=(await i.joinBot({meetingNumber:e.meetingNumber,password:e.password})).meetingId,n.meetingId=r,console.log(`Joined meeting, meeting_id=${r}`);let p=await i.getRealtimeEndpoint(r);a=await ta.connect({url:p.websocketUrl});let m=new Zr({socket:a,nextEventId:()=>`meeting-live-${w()}`});c=await m.createSession(),n.sessionId=c.toString(),console.log(`Realtime session created, session_id=${c.toString()}`),await e.onJoined?.(),o=await ta.connect({url:l.endpoint,headers:Ri(l,{connectId:w()})});let h=new $i({transport:o,uid:`larkpal-meeting-live`,speaker:e.speaker});s=await na.connect({url:Vi(u),headers:Hi(u)});let g=new Xi({transport:s}),_=new Ki({meetingId:r,asr:g}),v=new Rr({meetingId:r,sessionId:c,socket:a}),y=new Br({meetingId:r,sessionId:c,transport:m}),b=await Oi({meetingId:r,source:v,transcriber:_,owner:{tenantKey:e.tenantKey,userId:e.ownerUserId,openId:e.ownerOpenId,userName:e.ownerUserName},parentContextSummary:e.parentContextSummary,parentSessionId:e.parentSessionId,workspaceRoot:e.workspaceRoot,runtime:d,model:f,tts:h,sink:y,abortSignal:e.abortSignal,durationMs:e.durationMs,wakePhrases:e.wakePhrases,reflectiveSilenceMs:e.reflectiveSilenceMs,participationCooldownMs:e.participationCooldownMs});n.teammate=b,console.log(`Meeting live teammate finished`,b),await m.closeSession(c),await h.close(),await g.close(),n.status=`success`}catch(e){throw n.error=$(e),xa(t),e}finally{n.finishedAt=new Date().toISOString(),await s?.close().catch(()=>void 0),await o?.close().catch(()=>void 0),await a?.close().catch(()=>void 0),r&&i&&await i.leaveBot(r).catch(e=>{console.error(`Failed to leave meeting ${r}:`,$(e))}),await Ca(e.summaryOutputPath,n)}}function pa(e){let t=t=>{let n=e.indexOf(t);if(!(n<0))return e[n+1]},n=t(`--meeting-number`);if(!n)throw Error(`Missing --meeting-number`);return{meetingNumber:n,password:t(`--password`),text:t(`--text`)??`这是一条 LarkPal 会议语音链路验证。`,volcSecretsPath:t(`--volc-secrets`)??ga(),speaker:t(`--speaker`)??process.env.LARKPAL_MEETING_TTS_SPEAKER??oa,postSpeechWaitMs:Number(t(`--post-speech-wait-ms`)??`2000`),listenMs:Number(t(`--listen-ms`)??`0`),rawOutputPath:t(`--raw-output`),summaryOutputPath:t(`--summary-output`)}}function ma(e){let t=t=>{let n=e.indexOf(t);if(!(n<0))return e[n+1]},n=t(`--meeting-number`);if(!n)throw Error(`Missing --meeting-number`);let r=t(`--owner-user-id`)??process.env.LARKPAL_MEETING_OWNER_USER_ID;if(!r)throw Error(`Missing --owner-user-id or LARKPAL_MEETING_OWNER_USER_ID`);return{meetingNumber:n,password:t(`--password`),volcSecretsPath:t(`--volc-secrets`)??ga(),speaker:t(`--speaker`)??process.env.LARKPAL_MEETING_TTS_SPEAKER??oa,listenMs:0,rawOutputPath:void 0,summaryOutputPath:t(`--summary-output`),durationMs:Number(t(`--duration-ms`)??`60000`),workspaceRoot:t(`--workspace-root`)??process.env.LARKPAL_WORKSPACE??`/tmp/larkpal-workspace`,parentSessionId:t(`--parent-session-id`)??process.env.LARKPAL_MEETING_PARENT_SESSION_ID,tenantKey:t(`--tenant-key`)??process.env.LARKPAL_MEETING_TENANT_KEY??`meeting-live`,ownerUserId:r,ownerOpenId:t(`--owner-open-id`)??process.env.LARKPAL_MEETING_OWNER_OPEN_ID,ownerUserName:t(`--owner-user-name`)??process.env.LARKPAL_MEETING_OWNER_USER_NAME,wakePhrases:ya(t(`--wake-phrases`)??process.env.LARKPAL_MEETING_WAKE_PHRASES??`LarkPal,larkpal`),reflectiveSilenceMs:va(t(`--reflective-silence-ms`)??process.env.LARKPAL_MEETING_REFLECTIVE_SILENCE_MS),participationCooldownMs:va(t(`--participation-cooldown-ms`)??process.env.LARKPAL_MEETING_PARTICIPATION_COOLDOWN_MS)}}function ha(e){let t=t=>{let n=e.indexOf(t);if(!(n<0))return e[n+1]};return{volcSecretsPath:t(`--volc-secrets`)??ga(),summaryOutputPath:t(`--summary-output`)}}function ga(){if(process.env.LARKPAL_MEETING_VOLC_SECRETS)return process.env.LARKPAL_MEETING_VOLC_SECRETS;let e=f(process.cwd(),`..`,`secrets.cfg`);return i(e)?e:f(process.cwd(),`secrets.cfg`)}function _a(e){return new Promise(t=>setTimeout(t,e))}function va(e){if(!(e==null||e.trim()===``))return Number(e)}function ya(e){return e.split(`,`).map(e=>e.trim()).filter(Boolean)}function ba(e){return new Hr({appId:process.env.LARK_APP_ID,appSecret:process.env.LARK_APP_SECRET,userAccessToken:process.env.LARK_USER_ACCESS_TOKEN,useLarkCliUserAuth:!0,onRequestTrace:t=>e.push(t)})}function xa(e){e.length!==0&&console.error(`Feishu OpenAPI request trace`,JSON.stringify(e,void 0,2))}function $(e){return Sa(e instanceof Error?e.message:String(e))}function Sa(e){return e.replace(/\bwss:\/\/\S+/gi,`[redacted-wss-url]`).replace(/\b(token=)[^\s,;]+/gi,`$1[redacted]`).replace(/\b(access_token=)[^\s,;]+/gi,`$1[redacted]`).replace(/\b(refresh_token=)[^\s,;]+/gi,`$1[redacted]`).replace(/\b(password=)[^\s,;]+/gi,`$1[redacted]`).replace(/\b(app_secret=)[^\s,;]+/gi,`$1[redacted]`).replace(/("password"\s*:\s*")[^"]+(")/gi,`$1[redacted]$2`).replace(/("app_secret"\s*:\s*")[^"]+(")/gi,`$1[redacted]$2`).replace(/\b(authorization:\s*bearer\s+)[^\s,;]+/gi,`$1[redacted]`)}async function Ca(e,t){await wa(e,t,`meeting live summary`)}async function wa(e,t,n){if(e)try{await g(u(e),{recursive:!0}),await S(e,`${JSON.stringify(t,void 0,2)}\n`,`utf-8`),console.log(`${n} written: ${e}`)}catch(e){console.error(`Failed to write ${n}:`,e instanceof Error?e.message:String(e))}}async function Ta(e){let t=new Rr({meetingId:e.meetingId,sessionId:e.sessionId,socket:e.socket}),n;e.rawOutputPath&&(await g(u(e.rawOutputPath),{recursive:!0}),n=r(e.rawOutputPath));let i=0,a=0;try{for await(let r of t.frames({durationMs:e.durationMs}))i+=1,a+=r.pcm.byteLength,n?.write(r.pcm)}finally{await new Promise((e,t)=>{if(!n){e();return}n.end(n=>{n?t(n):e()})})}return{frames:i,bytes:a,rawOutputPath:e.rawOutputPath}}export{xe as A,Yt as C,Ye as D,Xe as E,E as M,Re as O,Xt as S,vt as T,Xn as _,fr as a,Zt as b,$n as c,Qn as d,Hn as f,Kn as g,Wn as h,Tr as i,be as j,ve as k,er as l,Jn as m,fa as n,qn as o,Un as p,Or as r,Yn as s,aa as t,Zn as u,z as v,_t as w,Qt as x,wn as y};
|