shennian 0.2.94 → 0.2.96
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/publish-build-manifest.json +44 -34
- package/dist/src/channels/wechat-channel/fingerprint.js +1 -1
- package/dist/src/channels/wechat-channel/helper-assets.d.ts +1 -0
- package/dist/src/channels/wechat-channel/helper-assets.js +1 -1
- package/dist/src/channels/wechat-channel/helper-client.d.ts +17 -0
- package/dist/src/channels/wechat-channel/helper-client.js +3 -3
- package/dist/src/channels/wechat-channel/helper-protocol.d.ts +1 -1
- package/dist/src/channels/wechat-channel/helper-protocol.js +1 -1
- package/dist/src/channels/wechat-channel/macos-helper-app-bridge.d.ts +1 -0
- package/dist/src/channels/wechat-channel/macos-helper-app-bridge.js +2 -0
- package/dist/src/channels/wechat-channel/observer.d.ts +23 -3
- package/dist/src/channels/wechat-channel/observer.js +6 -6
- package/dist/src/channels/wechat-channel/outbound-sender.d.ts +3 -1
- package/dist/src/channels/wechat-channel/outbound-sender.js +1 -1
- package/dist/src/channels/wechat-channel/preflight.js +1 -1
- package/dist/src/channels/wechat-channel/runner.js +1 -1
- package/dist/src/commands/daemon.d.ts +3 -0
- package/dist/src/commands/daemon.js +7 -7
- package/dist/src/commands/pair.js +8 -8
- package/dist/src/commands/wechat.d.ts +26 -2
- package/dist/src/commands/wechat.js +8 -3
- package/dist/src/devtools/wechat-channel-action-smoke.d.ts +18 -0
- package/dist/src/devtools/wechat-channel-action-smoke.js +8 -7
- package/dist/src/devtools/wechat-channel-markdown-report.d.ts +6 -0
- package/dist/src/devtools/wechat-channel-markdown-report.js +5 -0
- package/dist/src/devtools/wechat-channel-product-steps.d.ts +3 -2
- package/dist/src/devtools/wechat-channel-product-steps.js +8 -4
- package/dist/src/manager/registry.js +1 -1
- package/dist/src/native-fusion/parsers.js +4 -4
- package/dist/src/session/handlers/tool-detail.d.ts +1 -1
- package/dist/src/session/handlers/tool-detail.js +1 -1
- package/node_modules/@shennian/wire/dist/machine.d.ts +25 -0
- package/node_modules/@shennian/wire/dist/machine.d.ts.map +1 -1
- package/node_modules/@shennian/wire/dist/message-payload.d.ts.map +1 -1
- package/node_modules/@shennian/wire/dist/message-payload.js +10 -2
- package/node_modules/@shennian/wire/dist/message-payload.js.map +1 -1
- package/package.json +9 -10
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import j from"node:crypto";import q from"node:fs";import W from"node:path";import{SERVERS as U}from"../region.js";import{loadConfig as B,resolveShennianPath as R}from"../config/index.js";import{createWeChatRpaProductSourceConnection as z,listWeChatRpaProductRecentMessages as F,weChatChannelConversationId as J}from"../channels/wechat-rpa/product-channel.js";import{createWeChatChannelProductRunner as H}from"../channels/wechat-channel/runner.js";import{createWeChatChannelApiClient as K}from"../channels/wechat-channel/client.js";import{readExternalAttachment as V}from"./external-attachments.js";import{resolveWeChatChannelHelperAsset as Q,WECHAT_CHANNEL_HELPER_VERSION as Z}from"../channels/wechat-channel/helper-assets.js";import{WeChatChannelHelperClient as G}from"../channels/wechat-channel/helper-client.js";import{requiredWindowsWeChatChannelHelperCapabilitiesForProfile as X}from"../channels/wechat-channel/helper-protocol.js";import{ensureWeChatWindowReady as Y,fallbackWeChatMessageInputPointForWindow as ee,focusKnownWeChatWindow as ne,openConversationBySearch as te}from"../channels/wechat-channel/observer.js";import{enqueueWeChatOutboundReply as re}from"../channels/wechat-channel/outbound-ledger.js";import{sendQueuedWeChatOutboundRecords as _,WeChatChannelOutboundSender as ae}from"../channels/wechat-channel/outbound-sender.js";async function oe(e={}){const n=B(),t=he(e.serverUrl||n.serverUrl||U.cn.url),a=e.machineToken||n.machineToken,r=e.machineId||n.machineId,s=e.fetchImpl||fetch,o=[f("cli_installed","Shennian CLI is installed."),a?f("machine_paired","Machine token is configured."):v("machine_paired","machine_not_paired","Machine is not paired. Run shennian pair first.")];if(!a)return y({checks:o,serverUrl:t,machineId:r});try{const d=await s(`${t}/api/channels/wechat/runtime-policy`,{headers:{authorization:`Bearer ${a}`}}),i=await d.json().catch(()=>null);if(!d.ok||i?.ok===!1){const l=I(i?.reasonCode)||d.statusText||"request_failed";return o.push(v("server_policy",l,`WeChat runtime policy is blocked: ${l}`)),y({checks:o,serverUrl:t,machineId:r})}const c=g(i?.usagePolicy)?i.usagePolicy:{};o.push(f("server_policy","Server WeChat policy is reachable.")),o.push(f("entitlement","Account has Pro / Team external channel entitlement.")),o.push(f("credits",c.billingMode==="credits"?"Credit billing is enabled; balance is checked by server calls.":"Credits are not metered in current billing mode."));const h=g(i?.runtime)&&g(i.runtime.current)?i.runtime.current:null;o.push(h?f("runtime_registered","Local WeChat runtime is registered on the server."):me("runtime_registered","runtime_not_registered","Local WeChat runtime is not registered yet; open Shennian Desktop/daemon and enable Use WeChat."))}catch(d){o.push(v("server_policy","network_unavailable",d instanceof Error?d.message:"Unable to reach Shennian server."))}return y({checks:o,serverUrl:t,machineId:r})}async function ie(e){const n=e.text.trim();if(!n&&!e.attachment)throw new Error("Message text or attachment is required");const t=x(e),a=e.attachment?We(e.attachment):void 0;if(e.dryRun)return{ok:!0,operation:"write",conversation:t.conversationName,conversationName:t.conversationName,conversationId:t.conversationId,sessionId:t.sessionId,channelId:t.channelId,traceId:e.traceId,outDir:t.workDir,helperTracePath:null,sendStatus:"dry_run",pending:!1,attachment:a,attachments:a?[a]:[],dryRun:!0,reasonCode:null,message:"Dry run completed. No WeChat message was sent."};if(!M(e)){const c=await(e.directRuntime??b).send(t,e);return{ok:!0,operation:"write",conversation:t.conversationName,conversationName:t.conversationName,conversationId:t.conversationId,sessionId:t.sessionId,channelId:t.channelId,traceId:e.traceId,outDir:t.workDir,helperTracePath:null,sendStatus:c.sendStatus??(c.pending?"pending":"sent"),pending:c.pending===!0,attachment:a,attachments:a?[a]:[],reasonCode:null,message:c.pending?"WeChat message is queued or waiting for confirmation.":"WeChat message sent."}}const r=e.ipc??$();await N(r,t,e);const s=e.idempotencyKey||C("wechat-cli-send",`${t.channelId}
|
|
2
2
|
${t.conversationId}
|
|
3
3
|
${n}
|
|
4
|
-
${Date.now()}`)},e.fetchImpl);return{ok:!0,conversationName:t.conversationName,conversationId:t.conversationId,sessionId:t.sessionId,channelId:t.channelId,sendStatus:
|
|
4
|
+
${Date.now()}`),o=await w(r,"/external/reply",{managerSessionId:t.sessionId,channelId:t.channelId,conversationId:t.conversationId,text:n,attachment:e.attachment,idempotencyKey:s},e.fetchImpl,e.timeoutMs),d=await w(r,"/wechat-rpa/channel/sync",{managerSessionId:t.sessionId},e.fetchImpl,e.timeoutMs),i=Ie(d,s,o.pending===!0);return{ok:!0,operation:"write",conversation:t.conversationName,conversationName:t.conversationName,conversationId:t.conversationId,sessionId:t.sessionId,channelId:t.channelId,traceId:e.traceId,outDir:t.workDir,helperTracePath:null,sendStatus:i,pending:o.pending===!0&&(i==="queued"||i==="pending"),attachment:a,attachments:a?[a]:[],reasonCode:null,message:i==="confirmed_echo"?"WeChat message sent and confirmed.":i==="manual_review"?"WeChat message was submitted but needs manual review.":"WeChat message submitted to local daemon."}}async function se(e){const n=m(e.limit,10),t=x(e);if(!M(e)){const c=(await(e.directRuntime??b).readLatest(t,{...e,limit:n,recentLimit:e.recentLimit??n})).filter(l=>l.conversationId===t.conversationId||l.conversationName===t.conversationName).slice(-n),h=T(c);return{ok:!0,operation:"read",conversation:t.conversationName,conversationName:t.conversationName,conversationId:t.conversationId,sessionId:t.sessionId,channelId:t.channelId,traceId:e.traceId,outDir:t.workDir,helperTracePath:null,messages:c,attachments:h,count:c.length,reasonCode:null,message:`Read ${c.length} WeChat message(s).`}}const a=e.ipc??$();await N(a,t,{...e,recentLimit:e.recentLimit??n});const r=await w(a,"/wechat-rpa/channel/sync",{managerSessionId:t.sessionId},e.fetchImpl,e.timeoutMs),o=(Array.isArray(r.messages)?r.messages.filter(Ne):[]).filter(i=>i.conversationId===t.conversationId||i.conversationName===t.conversationName).slice(-n),d=T(o);return{ok:!0,operation:"read",conversation:t.conversationName,conversationName:t.conversationName,conversationId:t.conversationId,sessionId:t.sessionId,channelId:t.channelId,traceId:e.traceId,outDir:t.workDir,helperTracePath:null,messages:o,attachments:d,count:o.length,reasonCode:null,message:`Read ${o.length} WeChat message(s).`}}const b={async readLatest(e,n){const{config:t,secret:a}=D(e,n),r=P(t,a,n);try{return await r.runner.tick(),F({config:t,product:r,limit:n.limit??n.recentLimit??10})}finally{await r.runner.stop().catch(()=>{})}},async send(e,n){return ce(e,n)}};async function ce(e,n){const{config:t,secret:a}=D(e,n),r=P(t,a,n),s=r.runtime.bindings.find(l=>l.conversationDisplayName===e.conversationName)??r.runtime.bindings[0];if(!s)throw new Error("wechat_direct_binding_missing");const o=r.runtime.policy.platform,d=Q({platform:o});if(!d.ok)throw new Error(`${d.reasonCode}: ${d.message}`);const i=new G({helperPath:d.helperPath,expectedHelperVersion:d.version||Z,requiredCapabilities:o==="win32"?X("send"):void 0,guardUnsafeWindowsCommands:o==="win32",cleanupWindowsOverlays:o==="win32"}),c={version:1,runtimeId:r.runtime.runtimeId,records:[]},h=n.idempotencyKey||C("wechat-cli-send",`${e.channelId}
|
|
5
5
|
${e.conversationId}
|
|
6
6
|
${n.text}
|
|
7
|
-
${
|
|
7
|
+
${n.attachment?.localPath||""}
|
|
8
|
+
${Date.now()}`);re({ledger:c,replyId:`wechat-cli:${h}`,idempotencyKey:h,bindingId:s.bindingId,runtimeId:r.runtime.runtimeId,sessionId:s.sessionId,conversationName:s.conversationDisplayName,replyBaseRevision:0,text:n.text,attachmentLocalRefs:n.attachment?.localPath?[n.attachment.localPath]:[]});try{await i.start();const l=new ae({helper:i,platform:o,traceId:n.traceId,openConversation:async L=>{const O=await Y(i,n.traceId),S=await ne(i,O,n.traceId);return{...await te({helper:i,window:S,settleToBottom:!1,binding:{...s,conversationDisplayName:L},traceId:n.traceId}),inputPoint:ee(S)}}}),u=await de({ledger:c,bindingId:s.bindingId,sender:l,maxWaitMs:n.timeoutMs??9e4}),k=c.records[0];if(u.sentRecords.length>0)return{pending:!0,sendStatus:"sent_unconfirmed"};if(u.manualReviewRecords.length>0)return{pending:!1,sendStatus:"manual_review"};if(u.waitingRecords.length>0)return{pending:!0,sendStatus:"pending"};if(u.staleRecords.length>0)throw new Error(u.staleRecords[0]?.failureCode||"reply_revision_stale");if(u.failedRecords.length>0)throw new Error(u.failedRecords[0]?.failureCode||u.failedRecords[0]?.lastErrorSummary||"wechat_direct_send_failed");return{pending:k?.sendStatus==="queued",sendStatus:k?.sendStatus==="queued"?"queued":"pending"}}finally{await i.stop().catch(()=>{}),await r.runner.stop().catch(()=>{})}}async function de(e){const n=e.maxAttempts??24,t=e.maxWaitMs??9e4,a=Date.now();let r=await _({ledger:e.ledger,bindingId:e.bindingId,currentLastInboundRevision:0,sender:e.sender,maxUserActivityWaitMs:t});for(let s=2;r.waitingRecords.length>0&&s<=n&&!(Date.now()-a>=t);s+=1){const o=le(r.waitingRecords[0]?.nextAttemptAt,a,t);await ue(o),r=await _({ledger:e.ledger,bindingId:e.bindingId,currentLastInboundRevision:0,sender:e.sender,maxUserActivityWaitMs:t})}return r}function le(e,n,t){const a=Math.max(0,n+t-Date.now());if(a<=0)return 0;if(!e)return Math.min(1200,a);const r=new Date(e).getTime();return Number.isFinite(r)?Math.max(250,Math.min(r-Date.now(),a)):Math.min(1200,a)}function ue(e){return new Promise(n=>setTimeout(n,Math.max(0,e)))}function He(e){const n=e.command("wechat").description("Use WeChat through Shennian local runtime");n.option("--conversation <name>","WeChat conversation/group name"),n.command("doctor").description("Check local Shennian, pairing, entitlement, credits, and WeChat runtime readiness").option("--json","Output JSON",!1).action(async a=>{const r=await oe();if(a.json)console.log(JSON.stringify(r,null,2));else for(const s of r.checks){const o=s.ok?"\u2713":s.status==="warning"?"!":"\u2717";console.log(`${o} ${s.id}: ${s.message}`)}r.ok||(process.exitCode=1)}),n.command("write").aliases(["send"]).description("Write a message to a local WeChat conversation through Shennian").argument("[text...]","Message text").option("--conversation <name>","WeChat conversation/group name").option("--text <text>","Message text").option("--file <path>","File attachment path").option("--image <path>","Image attachment path").option("--video <path>","Video attachment path").option("--session-id <id>","Bind to an existing Shennian chat/session; omit for direct local WeChat tool mode").option("--work-dir <path>","Local tool work dir; defaults under ~/.shennian/wechat-cli").option("--idempotency-key <key>","Idempotency key").option("--dry-run","Validate the request and output the planned write without sending",!1).option("--trace-id <id>","Trace id included in JSON output").option("--timeout <ms>","Manager IPC request timeout in milliseconds").option("--format <format>","Output format: json or text","text").option("--json","Output JSON",!1).action(async(a,r,s)=>{const o=A(s,r.conversation),d=r.text??a.join(" "),i=Ce(r),c=await ie({conversation:o,text:d,attachment:i,sessionId:r.sessionId,workDir:r.workDir,idempotencyKey:r.idempotencyKey,dryRun:r.dryRun,traceId:r.traceId,timeoutMs:r.timeout?m(r.timeout,24e4):void 0});ge(c,r.json||r.format==="json")}),n.command("read").aliases(["read-latest","read_latest","latest"]).description("Read recent messages from a local WeChat conversation through Shennian").argument("[count]","Number of latest messages","10").option("--conversation <name>","WeChat conversation/group name").option("--limit <n>","Number of latest messages").option("--format <format>","Output format: markdown or json","markdown").option("--download <mode>","Attachment download mode: auto or never","auto").option("--trace-id <id>","Trace id included in JSON output").option("--timeout <ms>","Manager IPC request timeout in milliseconds").option("--session-id <id>","Bind to an existing Shennian chat/session; omit for direct local WeChat tool mode").option("--work-dir <path>","Local tool work dir; defaults under ~/.shennian/wechat-cli").option("--json","Output JSON",!1).action(async(a,r,s)=>{const o=A(s,r.conversation),d=ke(r.json?"json":r.format),i=await se({conversation:o,limit:m(r.limit??a,10),download:Se(r.download),traceId:r.traceId,timeoutMs:r.timeout?m(r.timeout,24e4):void 0,sessionId:r.sessionId,workDir:r.workDir});pe(i,d)})}function y(e){return{ok:e.checks.every(n=>n.ok||n.status==="warning"),checks:e.checks,serverUrl:e.serverUrl,machineId:e.machineId}}function f(e,n){return{id:e,ok:!0,status:"ready",message:n}}function me(e,n,t){return{id:e,ok:!1,status:"warning",reasonCode:n,message:t}}function v(e,n,t){return{id:e,ok:!1,status:"blocked",reasonCode:n,message:t}}function he(e){return e.replace(/\/+$/,"")}function $(){const e=R("runtime","manager-ipc.json");let n;try{n=JSON.parse(q.readFileSync(e,"utf-8"))}catch{throw new Error("Manager IPC is not available. Open Shennian Desktop or run `shennian start` first.")}const t=Number(n.pid);if(Number.isInteger(t)&&t>0&&!be(t))throw new Error(`Manager IPC runtime file is stale for PID ${t}. Restart Shennian Desktop or run \`shennian restart\`.`);const a=typeof n.url=="string"?n.url.replace(/\/+$/,""):"",r=typeof n.token=="string"?n.token:"";if(!a||!r)throw new Error(`Manager IPC runtime file is incomplete: ${e}`);return{url:a,token:r}}async function N(e,n,t){return w(e,"/wechat-rpa/channel/upsert",{managerSessionId:n.sessionId,id:n.channelId,name:`WeChat ${n.conversationName}`,workDir:n.workDir,enabled:!0,groups:[{name:n.conversationName}],canReply:!0,source:t.source||"wechat-channel",recentLimit:m(t.recentLimit,20),pollIntervalMs:m(t.pollIntervalMs,3e4),forceForeground:!0,downloadAttachments:t.download!=="never",privacyConsentAccepted:!0},t.fetchImpl,t.timeoutMs)}async function w(e,n,t,a=fetch,r){const s=String(t.managerSessionId||"");if(!s)throw new Error("managerSessionId is required");const o=r?new AbortController:null,d=o?setTimeout(()=>o.abort(),r):null;try{const i=await a(`${e.url}${n}`,{method:"POST",headers:{authorization:`Bearer ${e.token}`,"content-type":"application/json","x-shennian-manager-session-id":s},body:JSON.stringify(t),signal:o?.signal}),c=await i.json().catch(()=>({ok:!1,error:i.statusText}));if(!i.ok||!c.ok)throw new Error(c.error||`Manager IPC failed: ${i.status}`);return c}finally{d&&clearTimeout(d)}}function x(e){const n=e.conversation.trim();if(!n)throw new Error("--conversation is required");const t=C("wechat-cli-conversation",n),a=e.sessionId?.trim()||`wechat-cli-${t.slice(-24)}`,r=`wechat-rpa:${a}`;return{sessionId:a,channelId:r,conversationId:J(n),conversationName:n,workDir:W.resolve(e.workDir||R("wechat-cli",$e(n)))}}function M(e){return!e.directRuntime}function D(e,n){return{config:{id:e.channelId,type:"wechat-rpa",name:`WeChat ${e.conversationName}`,sessionId:e.sessionId,managerSessionId:e.sessionId,workDir:e.workDir,enabled:!0,secretRef:`wechat-cli:${e.channelId}`},secret:{groups:[{name:e.conversationName}],pollIntervalMs:m(n.pollIntervalMs,3e4),forceForeground:!0,downloadAttachments:n.download!=="never",canReply:!0}}}function P(e,n,t){const a=fe(t);return z({config:e,secret:n,createRunner:r=>H({...r,api:a})})}function fe(e){return{...K({fetchImpl:e.fetchImpl}),upsertRuntime:async()=>({ok:!0,status:"local_direct_tool"}),ingest:async()=>({ok:!0,status:"local_direct_tool"}),reportRunStatus:async()=>({ok:!0,status:"local_direct_tool"}),reportOutboundStatus:async()=>({ok:!0,status:"local_direct_tool"})}}function A(e,n){const t=e.parent?.opts()??{},a=n||t.conversation||"";if(!a.trim())throw new Error("--conversation is required");return a}function ge(e,n){if(n){console.log(JSON.stringify(e,null,2));return}console.log(e.sendStatus)}function pe(e,n){if(n==="json"){console.log(JSON.stringify(e,null,2));return}console.log(we(e).trimEnd())}function we(e){const n=[];if(n.push(`${p(e.conversationName||e.conversation)}:`),e.messages.length===0)return n.push("\u6D88\u606F: \uFF08\u6CA1\u6709\u8BFB\u5230\uFF09"),`${n.join(`
|
|
9
|
+
`)}
|
|
10
|
+
`;for(const t of e.messages)n.push(`${ve(t)}: ${ye(t)}`);return`${n.join(`
|
|
11
|
+
`)}
|
|
12
|
+
`}function Ie(e,n,t){const a=g(e.channel)?e.channel:{},s=(Array.isArray(a.wechatRpaPendingReplies)?a.wechatRpaPendingReplies:[]).filter(g).find(c=>I(c.idempotencyKey)===n),o=I(s?.status);if(o==="confirmed_echo"||o==="sent_unconfirmed"||o==="manual_review"||o==="queued")return o;const i=(Array.isArray(a.wechatRpaRecentTaskSummaries)?a.wechatRpaRecentTaskSummaries:[]).filter(g).map(c=>I(c.status)).find(Boolean);return i==="sent"?"sent":i==="confirmed_echo"?"confirmed_echo":i==="manual_review"?"manual_review":t?"pending":"ok"}function ye(e){const n=e.attachments||[],t=p(e.text);return t&&n.length===0?t:t&&n.length>0?`${t} ${n.map(E).join("\u3001")}`:n.length>0?n.map(E).join("\u3001"):"\uFF08\u6D88\u606F\uFF09"}function ve(e){return p(e.sender.name||e.sender.id||"\u5BF9\u65B9")}function E(e){const n=p(e.name||W.basename(e.localPath||"")||e.type||"\u9644\u4EF6"),t=e.localPath||e.url||"",a=e.availability&&e.availability!=="edge-local"?` (${e.availability})`:"";return t?`[${_e(n)}](${Re(t)})${a}`:`${n}${a}`}function Ce(e){const n=[e.file?{kind:"file",path:e.file}:null,e.image?{kind:"image",path:e.image}:null,e.video?{kind:"video",path:e.video}:null].filter(t=>!!t);if(n.length>1)throw new Error("Pass only one of --file, --image, or --video");if(n.length!==0)return V(n[0].path,n[0].kind)}function ke(e){const n=String(e||"markdown").trim().toLowerCase();if(n==="json")return"json";if(n==="markdown"||n==="md"||n==="text")return"markdown";throw new Error(`Unsupported --format: ${e}. Use markdown or json.`)}function Se(e){const n=String(e||"auto").trim().toLowerCase();if(n==="auto"||n==="never")return n;throw new Error(`Unsupported --download: ${e}. Use auto or never.`)}function We(e){return{kind:e.kind,name:e.name,mimeType:e.mimeType,size:e.size,localPath:e.localPath}}function T(e){return e.flatMap(n=>n.attachments??[])}function Re(e){const n=e.replace(/\\/g,"/");return/[\s()<>]/.test(n)?`<${n.replace(/[<>]/g,"")}>`:n}function _e(e){return p(e).replace(/([\\\]])/g,"\\$1")}function p(e){return String(e||"").replace(/\s+/g," ").trim()}function be(e){try{return process.kill(e,0),!0}catch{return!1}}function C(e,n){return`${e}:${j.createHash("sha256").update(n).digest("hex").slice(0,32)}`}function $e(e){return e.trim().replace(/[^a-zA-Z0-9._-]+/g,"_").replace(/^_+|_+$/g,"")||"conversation"}function m(e,n){const t=Number(e);return!Number.isFinite(t)||t<=0?n:Math.floor(t)}function Ne(e){return!!e&&typeof e=="object"&&!Array.isArray(e)&&e.type==="external.message"&&typeof e.channelId=="string"&&typeof e.conversationId=="string"&&typeof e.messageId=="string"&&typeof e.text=="string"}function g(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function I(e){return typeof e=="string"&&e?e:void 0}export{we as buildWeChatReadMarkdown,He as registerWeChatCommand,oe as runWeChatDoctor,se as runWeChatReadLatest,ie as runWeChatSend};
|
|
@@ -18,12 +18,14 @@ export type WeChatChannelActionSmokeOptions = {
|
|
|
18
18
|
imagePath?: string;
|
|
19
19
|
videoPath?: string;
|
|
20
20
|
downloadAnchorText?: string;
|
|
21
|
+
allowEmptyMedia?: boolean;
|
|
21
22
|
requireServer: boolean;
|
|
22
23
|
};
|
|
23
24
|
export type WeChatChannelActionSmokeResult = {
|
|
24
25
|
ok: boolean;
|
|
25
26
|
conversation: string;
|
|
26
27
|
outDir: string;
|
|
28
|
+
helperTracePath: string;
|
|
27
29
|
traceId: string;
|
|
28
30
|
runtimeId: string;
|
|
29
31
|
machineId: string;
|
|
@@ -40,10 +42,26 @@ export type WeChatChannelActionSmokeResult = {
|
|
|
40
42
|
details?: Record<string, unknown>;
|
|
41
43
|
}>;
|
|
42
44
|
};
|
|
45
|
+
export type WeChatChannelSmokeObservePipeline = 'edge-structure' | 'server-observe';
|
|
46
|
+
export declare function resolveWeChatSmokeObserveSessionMode(input: {
|
|
47
|
+
sessionId?: string;
|
|
48
|
+
observePipeline?: WeChatChannelSmokeObservePipeline;
|
|
49
|
+
}): 'direct-edge-structure' | 'session-bound';
|
|
43
50
|
export { buildBottomPageReport, buildDownloadVisibleMediaReport };
|
|
44
51
|
export declare function parseWeChatChannelActionSmokeArgs(argv: string[]): WeChatChannelActionSmokeOptions;
|
|
45
52
|
export declare function stepsForMode(mode: WeChatChannelActionSmokeOptions['mode']): WeChatChannelActionSmokeStep[];
|
|
46
53
|
export declare function runWeChatChannelActionSmoke(options: WeChatChannelActionSmokeOptions): Promise<WeChatChannelActionSmokeResult>;
|
|
54
|
+
export declare function buildSendStepAcceptance(input: {
|
|
55
|
+
sendAccepted: boolean;
|
|
56
|
+
text?: string | null;
|
|
57
|
+
beforeTextCount?: number | null;
|
|
58
|
+
afterTextCount?: number | null;
|
|
59
|
+
}): {
|
|
60
|
+
ok: boolean;
|
|
61
|
+
reasonCode?: string;
|
|
62
|
+
sendAccepted: boolean;
|
|
63
|
+
confirmationRequired: boolean;
|
|
64
|
+
};
|
|
47
65
|
export declare function nextSmokeDrainWaitMs(nextAttemptAt: string | undefined, startedAtMs: number, maxWaitMs: number): number;
|
|
48
66
|
export type WeChatChannelSendAndConfirmEvidenceInput = {
|
|
49
67
|
sendResults: Array<{
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import R from"node:crypto";import{spawnSync as X}from"node:child_process";import w from"node:fs";import d from"node:path";import{fileURLToPath as Y}from"node:url";import{buildBottomPageReport as k,buildDownloadVisibleMediaReport as F}from"./wechat-channel-download-report.js";import{loadConfig as ee}from"../config/index.js";import{createWeChatChannelApiClient as te}from"../channels/wechat-channel/client.js";import{resolveWeChatChannelHelperAsset as ne,WECHAT_CHANNEL_HELPER_VERSION as oe}from"../channels/wechat-channel/helper-assets.js";import{WeChatChannelHelperClient as re}from"../channels/wechat-channel/helper-client.js";import{requiredWindowsWeChatChannelHelperCapabilitiesForProfile as D}from"../channels/wechat-channel/helper-protocol.js";import{classifyWeChatOutboundEchoes as se,enqueueWeChatOutboundReply as O}from"../channels/wechat-channel/outbound-ledger.js";import{loadWeChatChannelLedger as ae,saveWeChatChannelLedger as ie,updateWeChatChannelBindingLedger as de}from"../channels/wechat-channel/ledger.js";import{WeChatChannelOutboundSender as B,sendQueuedWeChatOutboundRecords as b}from"../channels/wechat-channel/outbound-sender.js";import{captureWeChatWindow as M,ensureWeChatWindowReady as v,focusKnownWeChatWindow as y,observeWeChatChannelBindingViaHelper as ce,openConversationBySearch as C,recognizeWeChatScreenshot as P}from"../channels/wechat-channel/observer.js";import{createWeChatChannelRuntime as ue}from"../channels/wechat-channel/runtime.js";const le="ABC",me="wechat-channel-action-smoke";function he(e){const t=e.filter(u=>u!=="--"),n=Ve(t),o=Ge(t,"--step").map(ze).filter(u=>u!=null),r=ee(),s=m(t,"--trace-id")||`wechat-action-smoke-${Date.now().toString(36)}`,a=d.resolve(m(t,"--out")||m(t,"--output")||d.join(process.cwd(),".dev-runtime","wechat-channel","action-smoke",s)),i=o.length?Je(o):fe(n);return{conversation:m(t,"--conversation")||m(t,"--group")||le,mode:o.length?"custom":n,steps:i,outDir:a,workDir:d.resolve(m(t,"--work-dir")||process.cwd()),traceId:s,runtimeId:m(t,"--runtime-id")||me,machineId:m(t,"--machine-id")||process.env.SHENNIAN_MACHINE_ID||r.machineId||"local",sessionId:m(t,"--session-id")||process.env.SHENNIAN_EXTERNAL_SESSION_ID||process.env.SHENNIAN_MANAGER_SESSION_ID,serverUrl:m(t,"--server-url")||r.serverUrl,platform:Ke(m(t,"--platform")),text:m(t,"--text"),filePath:T(m(t,"--file")),imagePath:T(m(t,"--image")),videoPath:T(m(t,"--video")),downloadAnchorText:m(t,"--download-anchor-text")||m(t,"--media-anchor-text"),requireServer:t.includes("--require-server")}}function fe(e){return e==="send"?["open-read","send-text","send-file","send-image","send-video"]:e==="observe"?["structure-window"]:e==="all"?["open-read","send-text","send-file","send-image","send-video","structure-window"]:["open-read"]}async function ge(e){const t=Date.now(),n=new Date(t).toISOString();w.mkdirSync(e.outDir,{recursive:!0});const o=Be(e),r=o.bindings[0],s=Le(e);await s.start();const a={ok:!1,conversation:e.conversation,outDir:e.outDir,traceId:e.traceId,runtimeId:e.runtimeId,machineId:e.machineId,startedAt:n,finishedAt:n,durationMs:0,steps:[]};try{for(const i of e.steps)a.steps.push(await pe({step:i,options:e,runtime:o,binding:r,helper:s}))}finally{await s.stop().catch(()=>{}),a.finishedAt=new Date().toISOString(),a.durationMs=Date.now()-t,a.ok=a.steps.every(i=>i.ok||i.skipped),h(d.join(e.outDir,"summary.json"),a)}return a}async function pe(e){try{return e.step==="open-read"?await ve(e):e.step==="structure-window"?await Pe(e):e.step==="server-observe"?await Me(e):e.step==="read-bottom-page"?await Re(e):e.step==="download-visible-media"?await De(e):e.step==="send-and-confirm"?await ke(e):e.step.startsWith("human-")?await we(e):await L(e)}catch(t){const n=tt(t);return{step:e.step,ok:!1,reasonCode:n,errorSummary:t instanceof Error?t.message:String(t),userAction:nt(n)}}}async function we(e){if(e.step==="human-observe-deferred")return await be(e);const t=e.step,n=`human-${I(`${e.options.traceId}:${t}:${Date.now()}`)}`,o={version:1,runtimeId:e.runtime.runtimeId,records:[]},r=O({ledger:o,replyId:`human:${t}:${n}`,idempotencyKey:`human:${n}`,bindingId:e.binding.bindingId,runtimeId:e.runtime.runtimeId,sessionId:e.binding.sessionId,conversationName:e.binding.conversationDisplayName,replyBaseRevision:0,text:`${n} ${e.options.text||"Shennian WeChat human coordination smoke"}`}),s=K(e.helper,q(t)),a=s.actionLog,i=async N=>{a.push(`openConversation:${N}`);const Q=await v(s,e.options.traceId),Z=await y(s,Q,e.options.traceId);return C({helper:s,window:Z,binding:{...e.binding,conversationDisplayName:N},traceId:e.options.traceId})},u=new B({helper:s,platform:e.runtime.policy.platform,openConversation:i,traceId:e.options.traceId,activityGatePolicy:e.step==="human-send-user-active-timeout"?{keyDownThresholdMs:3e4,mouseMovedThresholdMs:3e4,mouseClickThresholdMs:3e4,scrollWheelThresholdMs:3e4}:void 0});let l=await b({ledger:o,bindingId:e.binding.bindingId,currentLastInboundRevision:0,sender:u,now:new Date("2026-06-15T00:00:00.000Z"),maxUserActivityWaitMs:e.step==="human-send-user-active-timeout"?1e3:void 0});e.step==="human-send-user-active-timeout"&&(l=await b({ledger:o,bindingId:e.binding.bindingId,currentLastInboundRevision:0,sender:u,now:new Date("2026-06-15T00:00:02.000Z"),maxUserActivityWaitMs:1e3})),(e.step==="human-send-preflight-busy-then-idle"||e.step==="human-send-takeover-then-idle")&&(s.setScenario(Ee()),l=await b({ledger:o,bindingId:e.binding.bindingId,currentLastInboundRevision:0,sender:u,now:new Date("2026-06-15T00:00:06.000Z")}));const f=$e(e.step,r)?await Ne({helper:s,binding:e.binding,marker:n,traceId:e.options.traceId,outDir:e.options.outDir,filePrefix:e.step}):0,g=f>0?se({ledger:o,bindingId:e.binding.bindingId,messages:[{stableMessageKey:`human-echo:${n}`,senderRole:"self",kind:"text",anchorText:r.text,normalizedText:r.text,textExcerpt:r.text,observedAt:new Date().toISOString()}]}):{confirmedRecords:[],manualReviewRecords:[],remainingMessages:[]},c=o.records[0],J=Fe(c,l,g.confirmedRecords),A={case:e.step,marker:n,runStatus:J,reasonCode:c.deferReason||c.failureCode||null,outboundStatus:c.sendStatus,attemptCount:c.attemptCount??0,nextAttemptAt:c.nextAttemptAt??null,observedMarkerCount:f,actionLog:a,clipboardRestore:a.includes("clipboard.restore")?"attempted":"not_needed",commitStage:c.commitStage??null};return h(d.join(e.options.outDir,`${e.step}-summary.json`),A),{step:e.step,ok:Oe(e.step,A),reasonCode:A.reasonCode||void 0,details:A}}async function be(e){const t=K(e.helper,q("human-observe-deferred")),n=await t.request("activity.snapshot",{},e.options.traceId),o=!!(n.ok&&n.result&&typeof n.result=="object"&&Number(n.result.keyDownSecondsAgo)<5),r={case:e.step,marker:null,runStatus:o?"observe_deferred_user_active":"baseline_or_no_change",reasonCode:o?"recent_keyboard_activity":null,outboundStatus:null,attemptCount:0,nextAttemptAt:null,observedMarkerCount:0,actionLog:t.actionLog,clipboardRestore:"not_needed"};return h(d.join(e.options.outDir,`${e.step}-summary.json`),r),{step:e.step,ok:o&&!t.actionLog.some(s=>s.startsWith("windows.")||s.startsWith("wechat.")||s.startsWith("clipboard.")),reasonCode:r.reasonCode||void 0,details:r}}async function ve(e){const t=await v(e.helper,e.options.traceId),n=await y(e.helper,t,e.options.traceId),o=await C({helper:e.helper,window:n,binding:e.binding,traceId:e.options.traceId});if(!o.opened)throw await ye({helper:e.helper,window:n,outDir:e.options.outDir,traceId:e.options.traceId,reason:o.reason||"conversation_not_opened"}),new Error(o.reason||"conversation_not_opened");const r=await M(e.helper,n.windowId,e.options.traceId),s=x(e.options.outDir,"open-read-full-window",r),a=await P(e.helper,r,e.options.traceId);return h(d.join(e.options.outDir,"open-read-ocr.json"),a),{step:"open-read",ok:!0,details:{openedReason:o.reason,windowId:n.windowId,screenshotPath:s,screenshot:{width:r.width,height:r.height,mimeType:r.mimeType},ocrBlockCount:a.blocks?.length??0,visibleConversationFingerprintCount:a.visibleConversationFingerprints?.length??0}}}async function ye(e){try{const t=await M(e.helper,e.window.windowId,e.traceId,e.window.bounds),n=x(e.outDir,"open-read-failure-window",t),o=await P(e.helper,t,e.traceId);h(d.join(e.outDir,"open-read-failure-ocr.json"),o),h(d.join(e.outDir,"open-read-failure-summary.json"),{reason:e.reason,windowId:e.window.windowId,screenshotPath:n,screenshot:{width:t.width,height:t.height,mimeType:t.mimeType},ocrBlockCount:o.blocks?.length??0,visibleConversationFingerprintCount:o.visibleConversationFingerprints?.length??0,topTexts:(o.blocks??[]).slice(0,30).map(r=>({text:r.text,bbox:r.bbox}))})}catch(t){h(d.join(e.outDir,"open-read-failure-summary.json"),{reason:e.reason,captureError:t instanceof Error?t.message:String(t)})}}async function L(e){return await Ce(e,qe(e.step,e.options))}async function Ce(e,t){if(t.skipped)return{step:e.step,ok:!0,skipped:!0,reasonCode:t.reasonCode};const n={version:1,runtimeId:e.runtime.runtimeId,records:[]},o=`${e.options.traceId}:${e.step}:${t.text}:${t.attachmentPath||""}`;O({ledger:n,replyId:`action-smoke:${e.step}:${I(o)}`,idempotencyKey:`action-smoke:${I(o)}`,bindingId:e.binding.bindingId,runtimeId:e.runtime.runtimeId,sessionId:e.binding.sessionId,conversationName:e.binding.conversationDisplayName,replyBaseRevision:0,text:t.text,attachmentLocalRefs:t.attachmentPath?[t.attachmentPath]:[]});const r=new B({helper:e.helper,platform:e.runtime.policy.platform,traceId:e.options.traceId,openConversation:async u=>{const p=await v(e.helper,e.options.traceId),l=await y(e.helper,p,e.options.traceId);return C({helper:e.helper,window:l,binding:{...e.binding,conversationDisplayName:u},traceId:e.options.traceId})}}),s=await Se({ledger:n,bindingId:e.binding.bindingId,sender:r});await _(900);const a=n.records[0],i=s.failedRecords[0]?.failureCode||s.manualReviewRecords[0]?.failureCode||s.waitingRecords[0]?.deferReason||s.staleRecords[0]?.failureCode;return{step:e.step,ok:s.sentRecords.length===1&&s.failedRecords.length===0,reasonCode:i,errorSummary:s.failedRecords[0]?.lastErrorSummary||s.manualReviewRecords[0]?.lastErrorSummary,details:{text:t.text,attachmentPath:t.attachmentPath??null,sentRecords:s.sentRecords.length,failedRecords:s.failedRecords.length,waitingRecords:s.waitingRecords.length,manualReviewRecords:s.manualReviewRecords.length,staleRecords:s.staleRecords.length,sendStatus:a?.sendStatus,failureCode:a?.failureCode??null,lastErrorSummary:a?.lastErrorSummary??null,deferReason:a?.deferReason,commitStage:a?.commitStage??null,attemptCount:a?.attemptCount??0,nextAttemptAt:a?.nextAttemptAt??null}}}async function Se(e){const t=e.maxAttempts??24,n=e.maxWaitMs??9e4,o=Date.now();let r=await b({ledger:e.ledger,bindingId:e.bindingId,currentLastInboundRevision:0,sender:e.sender,maxUserActivityWaitMs:n});for(let s=2;r.waitingRecords.length>0&&s<=t&&!(Date.now()-o>=n);s+=1){const a=Ie(r.waitingRecords[0]?.nextAttemptAt,o,n);await _(a),r=await b({ledger:e.ledger,bindingId:e.bindingId,currentLastInboundRevision:0,sender:e.sender,maxUserActivityWaitMs:n})}return r}function Ie(e,t,n){const o=Math.max(0,n-(Date.now()-t));if(o<=0)return 0;const r=e?new Date(e).getTime():Number.NaN,s=Number.isFinite(r)?r-Date.now():1e3;return Math.max(500,Math.min(Math.max(500,s),Math.min(5e3,o)))}function Ae(e){const t=e.sendResults.filter(c=>!H(c)),n=e.sendResults.filter(c=>!c.skipped).map(c=>c.details?.text&&typeof c.details.text=="string"?c.details.text:"").filter(Boolean),o=e.observedMessages.map(c=>[c.normalizedText||"",c.anchorText||"",c.textExcerpt||""].join(`
|
|
1
|
+
import D from"node:crypto";import{spawnSync as ne}from"node:child_process";import w from"node:fs";import i from"node:path";import{fileURLToPath as oe}from"node:url";import{buildBottomPageReport as M,buildDownloadVisibleMediaReport as q}from"./wechat-channel-download-report.js";import{buildWeChatMessagesMarkdown as y}from"./wechat-channel-markdown-report.js";import{loadConfig as re}from"../config/index.js";import{createWeChatChannelApiClient as se}from"../channels/wechat-channel/client.js";import{resolveWeChatChannelHelperAsset as ae,WECHAT_CHANNEL_HELPER_VERSION as ie}from"../channels/wechat-channel/helper-assets.js";import{WeChatChannelHelperClient as de}from"../channels/wechat-channel/helper-client.js";import{requiredWindowsWeChatChannelHelperCapabilitiesForProfile as j}from"../channels/wechat-channel/helper-protocol.js";import{classifyWeChatOutboundEchoes as ce,enqueueWeChatOutboundReply as K}from"../channels/wechat-channel/outbound-ledger.js";import{loadWeChatChannelLedger as le,saveWeChatChannelLedger as ue,updateWeChatChannelBindingLedger as me}from"../channels/wechat-channel/ledger.js";import{WeChatChannelOutboundSender as U,sendQueuedWeChatOutboundRecords as S}from"../channels/wechat-channel/outbound-sender.js";import{captureWeChatWindow as W,ensureWeChatWindowReady as C,fallbackWeChatMessageInputPointForWindow as he,focusKnownWeChatWindow as k,observeWeChatChannelBindingViaHelper as fe,openConversationBySearch as I,recognizeWeChatScreenshot as E}from"../channels/wechat-channel/observer.js";import{createWeChatChannelRuntime as ge}from"../channels/wechat-channel/runtime.js";function pe(e){const t=!e.sessionId&&e.observePipeline==="edge-structure";if(!e.sessionId&&!t)throw new Error("session_id_required: pass --session-id <existing Shennian session id> for server observe steps");return t?"direct-edge-structure":"session-bound"}const we="ABC",be="wechat-channel-action-smoke";function ve(e){const t=e.filter(l=>l!=="--"),n=st(t),o=it(t,"--step").map(at).filter(l=>l!=null),r=re(),s=g(t,"--trace-id")||`wechat-action-smoke-${Date.now().toString(36)}`,a=i.resolve(g(t,"--out")||g(t,"--output")||i.join(process.cwd(),".dev-runtime","wechat-channel","action-smoke",s)),d=o.length?dt(o):ye(n);return{conversation:g(t,"--conversation")||g(t,"--group")||we,mode:o.length?"custom":n,steps:d,outDir:a,workDir:i.resolve(g(t,"--work-dir")||process.cwd()),traceId:s,runtimeId:g(t,"--runtime-id")||be,machineId:g(t,"--machine-id")||process.env.SHENNIAN_MACHINE_ID||r.machineId||"local",sessionId:g(t,"--session-id")||process.env.SHENNIAN_EXTERNAL_SESSION_ID||process.env.SHENNIAN_MANAGER_SESSION_ID,serverUrl:g(t,"--server-url")||r.serverUrl,platform:nt(g(t,"--platform")),text:g(t,"--text"),filePath:F(g(t,"--file")),imagePath:F(g(t,"--image")),videoPath:F(g(t,"--video")),downloadAnchorText:g(t,"--download-anchor-text")||g(t,"--media-anchor-text"),allowEmptyMedia:t.includes("--allow-empty-media"),requireServer:t.includes("--require-server")}}function ye(e){return e==="send"?["open-read","send-text","send-file","send-image","send-video"]:e==="observe"?["structure-window"]:e==="all"?["open-read","send-text","send-file","send-image","send-video","structure-window"]:["open-read"]}async function Se(e){const t=Date.now(),n=new Date(t).toISOString();w.mkdirSync(e.outDir,{recursive:!0});const o=i.join(e.outDir,"helper-trace.jsonl");w.writeFileSync(o,"");const r=Qe(e),s=r.bindings[0],a=Ze(e,o);await a.start();const d={ok:!1,conversation:e.conversation,outDir:e.outDir,helperTracePath:o,traceId:e.traceId,runtimeId:e.runtimeId,machineId:e.machineId,startedAt:n,finishedAt:n,durationMs:0,steps:[]};try{for(const l of e.steps){if(Ce(l)&&d.steps.some(c=>c.step==="open-read"&&!c.ok&&!c.skipped)){d.steps.push({step:l,ok:!1,reasonCode:"open_read_required",errorSummary:"open-read failed; refusing to run send step against the current WeChat window"});continue}d.steps.push(await ke({step:l,options:e,runtime:r,binding:s,helper:a}))}}finally{await a.stop().catch(()=>{}),d.finishedAt=new Date().toISOString(),d.durationMs=Date.now()-t,d.ok=d.steps.every(l=>l.ok||l.skipped),f(i.join(e.outDir,"summary.json"),d)}return d}function Ce(e){return e==="send-text"||e==="send-file"||e==="send-image"||e==="send-video"||e==="send-and-confirm"}async function ke(e){try{return e.step==="open-read"?await Re(e):e.step==="structure-window"?await Le(e):e.step==="server-observe"?await Oe(e):e.step==="read-bottom-page"?await Ne(e):e.step==="download-visible-media"?await Fe(e):e.step==="send-and-confirm"?await Ee(e):e.step.startsWith("human-")?await Ae(e):await V(e)}catch(t){const n=ft(t),o=await Ie(e,n,t);return{step:e.step,ok:!1,reasonCode:n,errorSummary:t instanceof Error?t.message:String(t),userAction:gt(n),...o?{details:o}:{}}}}async function Ie(e,t,n){if(!xe(t))return;const o=i.join(e.options.outDir,`${e.step}-failure-diagnostics.json`),r={step:e.step,reasonCode:t,errorSummary:n instanceof Error?n.message:String(n),capturedAt:new Date().toISOString()};try{r.permissions=await e.helper.request("permissions.check",{},e.options.traceId)}catch(s){r.permissionsError=s instanceof Error?s.message:String(s)}try{r.windows=await e.helper.request("windows.list",{},e.options.traceId)}catch(s){r.windowsError=s instanceof Error?s.message:String(s)}return f(o,r),{failureDiagnosticsPath:o}}function xe(e){return e.startsWith("wechat_")||e.startsWith("permission_")||e.startsWith("user_active")}async function Ae(e){if(e.step==="human-observe-deferred")return await _e(e);const t=e.step,n=`human-${_(`${e.options.traceId}:${t}:${Date.now()}`)}`,o={version:1,runtimeId:e.runtime.runtimeId,records:[]},r=K({ledger:o,replyId:`human:${t}:${n}`,idempotencyKey:`human:${n}`,bindingId:e.binding.bindingId,runtimeId:e.runtime.runtimeId,sessionId:e.binding.sessionId,conversationName:e.binding.conversationDisplayName,replyBaseRevision:0,text:`${n} ${e.options.text||"Shennian WeChat human coordination smoke"}`}),s=G(e.helper,J(t)),a=s.actionLog,d=async H=>{a.push(`openConversation:${H}`);const ee=await C(s,e.options.traceId),te=await k(s,ee,e.options.traceId);return I({helper:s,window:te,settleToBottom:!1,binding:{...e.binding,conversationDisplayName:H},traceId:e.options.traceId})},l=new U({helper:s,platform:e.runtime.policy.platform,openConversation:d,traceId:e.options.traceId,activityGatePolicy:e.step==="human-send-user-active-timeout"?{keyDownThresholdMs:3e4,mouseMovedThresholdMs:3e4,mouseClickThresholdMs:3e4,scrollWheelThresholdMs:3e4}:void 0});let h=await S({ledger:o,bindingId:e.binding.bindingId,currentLastInboundRevision:0,sender:l,now:new Date("2026-06-15T00:00:00.000Z"),maxUserActivityWaitMs:e.step==="human-send-user-active-timeout"?1e3:void 0});e.step==="human-send-user-active-timeout"&&(h=await S({ledger:o,bindingId:e.binding.bindingId,currentLastInboundRevision:0,sender:l,now:new Date("2026-06-15T00:00:02.000Z"),maxUserActivityWaitMs:1e3})),(e.step==="human-send-preflight-busy-then-idle"||e.step==="human-send-takeover-then-idle")&&(s.setScenario(Ue()),h=await S({ledger:o,bindingId:e.binding.bindingId,currentLastInboundRevision:0,sender:l,now:new Date("2026-06-15T00:00:06.000Z")}));const m=Ve(e.step,r)?await N({helper:s,binding:e.binding,marker:n,traceId:e.options.traceId,outDir:e.options.outDir,filePrefix:e.step}):0,p=m>0?ce({ledger:o,bindingId:e.binding.bindingId,messages:[{stableMessageKey:`human-echo:${n}`,senderRole:"self",kind:"text",anchorText:r.text,normalizedText:r.text,textExcerpt:r.text,observedAt:new Date().toISOString()}]}):{confirmedRecords:[],manualReviewRecords:[],remainingMessages:[]},u=o.records[0],b=Ge(u,h,p.confirmedRecords),v={case:e.step,marker:n,runStatus:b,reasonCode:u.deferReason||u.failureCode||null,outboundStatus:u.sendStatus,attemptCount:u.attemptCount??0,nextAttemptAt:u.nextAttemptAt??null,observedMarkerCount:m,actionLog:a,clipboardRestore:a.includes("clipboard.restore")?"attempted":"not_needed",commitStage:u.commitStage??null};return f(i.join(e.options.outDir,`${e.step}-summary.json`),v),{step:e.step,ok:Je(e.step,v),reasonCode:v.reasonCode||void 0,details:v}}async function _e(e){const t=G(e.helper,J("human-observe-deferred")),n=await t.request("activity.snapshot",{},e.options.traceId),o=!!(n.ok&&n.result&&typeof n.result=="object"&&Number(n.result.keyDownSecondsAgo)<5),r={case:e.step,marker:null,runStatus:o?"observe_deferred_user_active":"baseline_or_no_change",reasonCode:o?"recent_keyboard_activity":null,outboundStatus:null,attemptCount:0,nextAttemptAt:null,observedMarkerCount:0,actionLog:t.actionLog,clipboardRestore:"not_needed"};return f(i.join(e.options.outDir,`${e.step}-summary.json`),r),{step:e.step,ok:o&&!t.actionLog.some(s=>s.startsWith("windows.")||s.startsWith("wechat.")||s.startsWith("clipboard.")),reasonCode:r.reasonCode||void 0,details:r}}async function Re(e){const t=await C(e.helper,e.options.traceId),n=await k(e.helper,t,e.options.traceId),o=await I({helper:e.helper,window:n,binding:e.binding,traceId:e.options.traceId});if(!o.opened)throw await De({helper:e.helper,window:n,outDir:e.options.outDir,traceId:e.options.traceId,reason:o.reason||"conversation_not_opened"}),new Error(o.reason||"conversation_not_opened");const r=await W(e.helper,n.windowId,e.options.traceId),s=T(e.options.outDir,"open-read-full-window",r),a=await E(e.helper,r,e.options.traceId);return f(i.join(e.options.outDir,"open-read-ocr.json"),a),{step:"open-read",ok:!0,details:{openedReason:o.reason,windowId:n.windowId,screenshotPath:s,screenshot:{width:r.width,height:r.height,mimeType:r.mimeType},ocrBlockCount:a.blocks?.length??0,visibleConversationFingerprintCount:a.visibleConversationFingerprints?.length??0}}}async function De(e){try{const t=await W(e.helper,e.window.windowId,e.traceId,e.window.bounds),n=T(e.outDir,"open-read-failure-window",t),o=await E(e.helper,t,e.traceId);f(i.join(e.outDir,"open-read-failure-ocr.json"),o),f(i.join(e.outDir,"open-read-failure-summary.json"),{reason:e.reason,windowId:e.window.windowId,screenshotPath:n,screenshot:{width:t.width,height:t.height,mimeType:t.mimeType},ocrBlockCount:o.blocks?.length??0,visibleConversationFingerprintCount:o.visibleConversationFingerprints?.length??0,topTexts:(o.blocks??[]).slice(0,30).map(r=>({text:r.text,bbox:r.bbox}))})}catch(t){f(i.join(e.outDir,"open-read-failure-summary.json"),{reason:e.reason,captureError:t instanceof Error?t.message:String(t)})}}async function V(e){return await Me(e,ot(e.step,e.options))}async function Me(e,t){if(t.skipped)return{step:e.step,ok:!0,skipped:!0,reasonCode:t.reasonCode};const n={version:1,runtimeId:e.runtime.runtimeId,records:[]},o=`${e.options.traceId}:${e.step}:${t.text}:${t.attachmentPath||""}`,r=t.text?await N({helper:e.helper,binding:e.binding,marker:t.text,traceId:e.options.traceId,outDir:e.options.outDir,filePrefix:`${e.step}-before-send`,settleToBottom:!1}).catch(()=>null):null;K({ledger:n,replyId:`action-smoke:${e.step}:${_(o)}`,idempotencyKey:`action-smoke:${_(o)}`,bindingId:e.binding.bindingId,runtimeId:e.runtime.runtimeId,sessionId:e.binding.sessionId,conversationName:e.binding.conversationDisplayName,replyBaseRevision:0,text:t.text,attachmentLocalRefs:t.attachmentPath?[t.attachmentPath]:[]});const s=new U({helper:e.helper,platform:e.runtime.policy.platform,traceId:e.options.traceId,openConversation:async p=>{const u=await C(e.helper,e.options.traceId),b=await k(e.helper,u,e.options.traceId);return{...await I({helper:e.helper,window:b,settleToBottom:!1,binding:{...e.binding,conversationDisplayName:p},traceId:e.options.traceId}),inputPoint:he(b)}}}),a=await Te({ledger:n,bindingId:e.binding.bindingId,sender:s});await R(900);const d=n.records[0],l=a.failedRecords[0]?.failureCode||a.manualReviewRecords[0]?.failureCode||a.waitingRecords[0]?.deferReason||a.staleRecords[0]?.failureCode,c=a.sentRecords.length===1&&a.failedRecords.length===0&&a.waitingRecords.length===0&&a.manualReviewRecords.length===0&&a.staleRecords.length===0,h=c&&t.text?await ze({helper:e.helper,binding:e.binding,marker:t.text,traceId:e.options.traceId,outDir:e.options.outDir,filePrefix:`${e.step}-after-send`,settleToBottom:!1,attempts:3,targetGreaterThan:r}):null,m=Pe({sendAccepted:c,text:t.text,beforeTextCount:r,afterTextCount:h});return{step:e.step,ok:m.ok,reasonCode:l||m.reasonCode,errorSummary:a.failedRecords[0]?.lastErrorSummary||a.manualReviewRecords[0]?.lastErrorSummary,details:{text:t.text,attachmentPath:t.attachmentPath??null,helperTracePath:i.join(e.options.outDir,"helper-trace.jsonl"),confirmationRequired:m.confirmationRequired,sendAccepted:m.sendAccepted,beforeTextCount:r,afterTextCount:h,sentRecords:a.sentRecords.length,failedRecords:a.failedRecords.length,waitingRecords:a.waitingRecords.length,manualReviewRecords:a.manualReviewRecords.length,staleRecords:a.staleRecords.length,sendStatus:d?.sendStatus,failureCode:d?.failureCode??null,lastErrorSummary:d?.lastErrorSummary??null,deferReason:d?.deferReason,commitStage:d?.commitStage??null,attemptCount:d?.attemptCount??0,nextAttemptAt:d?.nextAttemptAt??null}}}function Pe(e){const t=!!(e.text&&e.text.trim());if(!e.sendAccepted)return{ok:!1,reasonCode:void 0,sendAccepted:!1,confirmationRequired:t};if(!t)return{ok:!0,sendAccepted:!0,confirmationRequired:t};const n=typeof e.beforeTextCount=="number"&&Number.isFinite(e.beforeTextCount)?e.beforeTextCount:null,o=typeof e.afterTextCount=="number"&&Number.isFinite(e.afterTextCount)?e.afterTextCount:0,r=n==null?o>0:o>n;return{ok:r,reasonCode:r?void 0:"sent_text_not_observed",sendAccepted:!0,confirmationRequired:t}}async function Te(e){const t=e.maxAttempts??24,n=e.maxWaitMs??9e4,o=Date.now();let r=await S({ledger:e.ledger,bindingId:e.bindingId,currentLastInboundRevision:0,sender:e.sender,maxUserActivityWaitMs:n});for(let s=2;r.waitingRecords.length>0&&s<=t&&!(Date.now()-o>=n);s+=1){const a=je(r.waitingRecords[0]?.nextAttemptAt,o,n);await R(a),r=await S({ledger:e.ledger,bindingId:e.bindingId,currentLastInboundRevision:0,sender:e.sender,maxUserActivityWaitMs:n})}return r}function je(e,t,n){const o=Math.max(0,n-(Date.now()-t));if(o<=0)return 0;const r=e?new Date(e).getTime():Number.NaN,s=Number.isFinite(r)?r-Date.now():1e3;return Math.max(500,Math.min(Math.max(500,s),Math.min(5e3,o)))}function We(e){const t=e.sendResults.filter(u=>!z(u)),n=e.sendResults.filter(u=>!u.skipped).map(u=>u.details?.text&&typeof u.details.text=="string"?u.details.text:"").filter(Boolean),o=e.observedMessages.map(u=>[u.normalizedText||"",u.anchorText||"",u.textExcerpt||""].join(`
|
|
2
2
|
`)).join(`
|
|
3
|
-
`),r=n.filter(c=>o.includes(c)),s=e.sendResults.map(c=>typeof c.details?.sendStatus=="string"?c.details.sendStatus:"").filter(Boolean),a=e.sendResults.filter(H).length,i=j(t,"waitingRecords"),u=j(t,"failedRecords"),p=j(t,"manualReviewRecords"),l=t.find(c=>!c.ok||c.skipped),f=s.length===n.length&&s.every(c=>c==="sent_unconfirmed"||c==="confirmed_echo"),g=!l&&n.length>0&&r.length>0&&f&&i===0&&u===0&&p===0;return{ok:g,reasonCode:g?void 0:l?.reasonCode||(i>0?"outbound_send_waiting":void 0)||(u>0?"outbound_send_failed":void 0)||(p>0?"outbound_manual_review":void 0)||(f?void 0:"outbound_status_not_accepted")||(r.length?"partial_sent_messages_observed":"sent_messages_not_observed"),sentTexts:n,confirmedTexts:r,outboundStatuses:s,skippedFixtureCount:a,pendingOutboundCount:i,failedOutboundCount:u,manualReviewCount:p}}function H(e){return e.skipped===!0&&e.reasonCode==="ffmpeg_unavailable_for_video_fixture"}function j(e,t){return e.reduce((n,o)=>{const r=o.details?.[t];return n+(typeof r=="number"&&Number.isFinite(r)?r:0)},0)}async function ke(e){const t=["send-text","send-file","send-image","send-video"],n=[];for(const i of t)n.push(await L({...e,step:i}));await _(1200);const o=await xe(e,3),r=k(o.messages);h(d.join(e.options.outDir,"bottom-page-summary.json"),r),h(d.join(e.options.outDir,"server-observe-messages.json"),o.messages);const s=Ae({sendResults:n,observedMessages:o.messages}),a=s.ok&&o.messages.length>0;return{step:"send-and-confirm",ok:a,reasonCode:a?void 0:s.reasonCode,errorSummary:n.find(i=>!i.ok||i.skipped)?.errorSummary,details:{sent:n.map(i=>({step:i.step,ok:i.ok,skipped:i.skipped,reasonCode:i.reasonCode,errorSummary:i.errorSummary,text:i.details?.text,attachmentPath:i.details?.attachmentPath,sendStatus:i.details?.sendStatus,deferReason:i.details?.deferReason,failureCode:i.details?.failureCode,commitStage:i.details?.commitStage,attemptCount:i.details?.attemptCount,nextAttemptAt:i.details?.nextAttemptAt,waitingRecords:i.details?.waitingRecords,failedRecords:i.details?.failedRecords,manualReviewRecords:i.details?.manualReviewRecords})),sentTexts:s.sentTexts,confirmedTexts:s.confirmedTexts,outboundStatuses:s.outboundStatuses,skippedFixtureCount:s.skippedFixtureCount,pendingOutboundCount:s.pendingOutboundCount,failedOutboundCount:s.failedOutboundCount,manualReviewCount:s.manualReviewCount,observedCount:o.messages.length,byKind:r.byKind,attachmentSummary:r.attachmentSummary,attachmentsDir:o.attachmentsDir,reportPath:d.join(e.options.outDir,"bottom-page-summary.json")}}}async function xe(e,t){let n;for(let o=1;o<=t;o+=1)try{return await S(e)}catch(r){if(n=r,o>=t||!_e(r))break;try{const s=await v(e.helper,e.options.traceId),a=await y(e.helper,s,e.options.traceId);await C({helper:e.helper,window:a,binding:e.binding,traceId:e.options.traceId})}catch{}await _(1500*o)}throw n}function _e(e){const t=e instanceof Error?e.message:String(e||"");return/conversation_not_visible|wechat_window_unavailable|wechat_window_not_found|title_not_confirmed|server_observe_failed|timeout/i.test(t)}async function Re(e){const t=await S(e),n=k(t.messages);return h(d.join(e.options.outDir,"bottom-page-summary.json"),n),h(d.join(e.options.outDir,"server-observe-messages.json"),t.messages),{step:"read-bottom-page",ok:n.messageCount>0,reasonCode:n.messageCount>0?void 0:"no_observed_messages",details:{messageCount:n.messageCount,byKind:n.byKind,attachmentSummary:n.attachmentSummary,attachmentsDir:t.attachmentsDir,reportPath:d.join(e.options.outDir,"bottom-page-summary.json")}}}async function De(e){const t=await S(e,{observePipeline:"edge-structure",persistLocalLedger:!0});W(e.options.outDir,"download-visible",t.observationEvidence);const n=k(t.messages),o=F(t.messages,t.attachmentsDir,{observePipeline:t.observePipeline,downloadAnchorText:e.options.downloadAnchorText,ledgerPath:t.ledgerPath,ledgerBinding:t.ledgerBinding,traceHashes:t.traceHashes});return h(d.join(e.options.outDir,"bottom-page-summary.json"),n),h(d.join(e.options.outDir,"download-visible-summary.json"),o),h(d.join(e.options.outDir,"download-visible-messages.json"),t.messages),{step:"download-visible-media",ok:o.ok,reasonCode:o.ok?void 0:o.reasonCode,details:{mediaCandidateCount:o.mediaCandidateCount,localAttachmentCount:o.localAttachmentCount,originalLocalAttachmentCount:o.originalLocalAttachmentCount,previewAttachmentCount:o.previewAttachmentCount,missingLocalPathCount:o.missingLocalPathCount,pendingAttachmentCount:o.pendingAttachmentCount,byKind:o.byKind,byAvailability:o.byAvailability,reasonCodes:o.reasonCodes,attachmentsDir:t.attachmentsDir,reportPath:d.join(e.options.outDir,"download-visible-summary.json"),phases:o.phases,observePipeline:o.observePipeline,ledgerPath:o.ledgerPath,ledgerRevision:o.ledger?.revision,traceHashes:o.traceHashes,traceEvents:o.traceEvents}}}async function Me(e){const t=await S(e,{observePipeline:"server-observe"});W(e.options.outDir,"server-observe",t.observationEvidence),h(d.join(e.options.outDir,"server-observe-messages.json"),t.messages);const n=U(t.messages);return{step:"server-observe",ok:t.messages.length>0,reasonCode:t.messages.length>0?void 0:"no_observed_messages",details:{observedCount:t.messages.length,byKind:E(t.messages.map(o=>o.kind||"unknown")),attachmentSummary:n,attachmentsDir:t.attachmentsDir}}}async function Pe(e){const t=await S(e,{observePipeline:"edge-structure",downloadMedia:!1});W(e.options.outDir,"structure-window",t.observationEvidence),h(d.join(e.options.outDir,"structure-window-messages.json"),t.messages);const n=U(t.messages);return{step:"structure-window",ok:t.messages.length>0,reasonCode:t.messages.length>0?void 0:"no_observed_messages",details:{observedCount:t.messages.length,byKind:E(t.messages.map(o=>o.kind||"unknown")),attachmentSummary:n,attachmentsDir:t.attachmentsDir}}}async function S(e,t={}){if(!e.options.sessionId)throw new Error("session_id_required: pass --session-id <existing Shennian session id> for server observe steps");const n=te({serverUrl:e.options.serverUrl});await n.upsertRuntime(e.runtime,{...e.binding,enabled:!1,allowReply:!1});const o=d.join(e.options.outDir,"inbound-attachments"),r=t.persistLocalLedger?Qe(e.options):void 0,s=r?ae(r,e.runtime.runtimeId):void 0;let a,i,u;const p=await ce({runtime:e.runtime,binding:{...e.binding,downloadMedia:t.downloadMedia??e.binding.downloadMedia},helper:e.helper,api:n,workDir:e.options.workDir,attachmentsDir:o,traceId:e.options.traceId,mediaAnchorText:e.options.downloadAnchorText,observePipeline:t.observePipeline,localLedgerTailAnchors:s?Ze(s.bindings[e.binding.bindingId]):void 0,onObservationEvidence:({capture:g,ocr:c})=>{a=We(g),i=Te(c),u=je(g,c,{captureHash:a,ocrHash:i})}});let l,f;if(s&&r){const g=de({ledger:s,bindingId:e.binding.bindingId,observedMessages:p});l=g.binding,f=G({bindingId:e.binding.bindingId,revision:l.revision,messages:g.newMessages}),ie(r,s)}return{messages:p,attachmentsDir:o,observePipeline:t.observePipeline,...r?{ledgerPath:r}:{},...l?{ledgerBinding:l}:{},traceHashes:{...a?{captureHash:a}:{},...i?{ocrHash:i}:{},...f?{ingestPayloadHash:f}:{}},...u?{observationEvidence:u}:{}}}function je(e,t,n){return{capture:e,report:{screenshot:{width:e.width,height:e.height,mimeType:e.mimeType,...e.windowId?{windowId:e.windowId}:{}},hashes:n,ocrBlockCount:t.blocks?.length??0,visibleConversationFingerprintCount:t.visibleConversationFingerprints?.length??0,topTexts:(t.blocks??[]).slice(0,40).map(o=>({text:o.text,...o.bbox?{bbox:o.bbox}:{},...typeof o.confidence=="number"?{confidence:o.confidence}:{}}))}}}function W(e,t,n){if(!n)return;const o=x(e,`${t}-observation-window`,n.capture);h(d.join(e,`${t}-observation-evidence.json`),{...n.report,screenshotPath:o})}function We(e){return`sha256:${R.createHash("sha256").update(Buffer.from(e.dataBase64,"base64")).digest("hex")}`}function Te(e){return G({blocks:(e.blocks??[]).map(t=>({text:t.text??"",bbox:t.bbox??null,confidence:typeof t.confidence=="number"?Number(t.confidence.toFixed(4)):null})),visibleConversationFingerprints:e.visibleConversationFingerprints??[]})}function K(e,t){let n=t,o=0,r=0,s="";const a=[];return{actionLog:a,setScenario(u){n=u,o=0,r=0},async request(u,p,l){if(a.push(u),u==="activity.snapshot"){if(o+=1,o<=n.preflightBusySnapshots)return{id:`human-${o}`,ok:!0,result:{keyDownSecondsAgo:.2,mouseMovedSecondsAgo:.2,scrollWheelSecondsAgo:.2,privacy:{capturesKeyContent:!1,capturesMousePath:!1}},latencyMs:0,traceId:l};if(n.forceIdleAfterBusy)return{id:`human-${o}`,ok:!0,result:{keyDownSecondsAgo:60,mouseMovedSecondsAgo:60,leftMouseDownSecondsAgo:60,rightMouseDownSecondsAgo:60,scrollWheelSecondsAgo:60,privacy:{capturesKeyContent:!1,capturesMousePath:!1}},latencyMs:0,traceId:l}}if(u==="automation.lease.acquire"){const f=await e.request(u,p,l),g=f.result&&typeof f.result=="object"?f.result:{};return s=typeof g.leaseId=="string"?g.leaseId:"",f}return u==="automation.lease.status"?(r+=1,n.simulateInterruptionAtLeaseStatus===r?(a.push("automation.lease.simulateInterruption"),{id:`human-lease-${r}`,ok:!0,result:{active:!0,leaseId:s,interrupted:!0,interruptReason:n.interruptionReason||"recent_mouse_activity"},latencyMs:0,traceId:l}):{id:`human-lease-${r}`,ok:!0,result:{active:!0,leaseId:s,interrupted:!1},latencyMs:0,traceId:l}):e.request(u,p,l)}}}function q(e){return e==="human-send-preflight-busy"||e==="human-send-preflight-busy-then-idle"||e==="human-send-user-active-timeout"||e==="human-observe-deferred"?{preflightBusySnapshots:100}:e==="human-send-takeover-during-run"||e==="human-send-takeover-then-idle"?{preflightBusySnapshots:0,forceIdleAfterBusy:!0,simulateInterruptionAtLeaseStatus:2,interruptionReason:"recent_mouse_activity"}:{preflightBusySnapshots:0,forceIdleAfterBusy:!0}}function Ee(){return{preflightBusySnapshots:0,forceIdleAfterBusy:!0}}function $e(e,t){return t.sendStatus!=="sent_unconfirmed"?!1:e==="human-send-normal"||e==="human-send-preflight-busy-then-idle"||e==="human-send-takeover-then-idle"}async function Ne(e){const t=await v(e.helper,e.traceId),n=await y(e.helper,t,e.traceId);if(!(await C({helper:e.helper,window:n,binding:e.binding,traceId:e.traceId})).opened)return 0;const r=await M(e.helper,n.windowId,e.traceId),s=x(e.outDir,`${e.filePrefix}-observe-marker`,r),a=await P(e.helper,r,e.traceId);return h(d.join(e.outDir,`${e.filePrefix}-observe-marker-ocr.json`),{screenshotPath:s,marker:e.marker,ocr:a}),(a.blocks||[]).map(u=>u.text||"").join(`
|
|
4
|
-
`).split(e.marker).length-1}function
|
|
3
|
+
`),r=n.filter(u=>o.includes(u)),s=e.sendResults.map(u=>typeof u.details?.sendStatus=="string"?u.details.sendStatus:"").filter(Boolean),a=e.sendResults.filter(z).length,d=$(t,"waitingRecords"),l=$(t,"failedRecords"),c=$(t,"manualReviewRecords"),h=t.find(u=>!u.ok||u.skipped),m=s.length===n.length&&s.every(u=>u==="sent_unconfirmed"||u==="confirmed_echo"),p=!h&&n.length>0&&r.length>0&&m&&d===0&&l===0&&c===0;return{ok:p,reasonCode:p?void 0:h?.reasonCode||(d>0?"outbound_send_waiting":void 0)||(l>0?"outbound_send_failed":void 0)||(c>0?"outbound_manual_review":void 0)||(m?void 0:"outbound_status_not_accepted")||(r.length?"partial_sent_messages_observed":"sent_messages_not_observed"),sentTexts:n,confirmedTexts:r,outboundStatuses:s,skippedFixtureCount:a,pendingOutboundCount:d,failedOutboundCount:l,manualReviewCount:c}}function z(e){return e.skipped===!0&&e.reasonCode==="ffmpeg_unavailable_for_video_fixture"}function $(e,t){return e.reduce((n,o)=>{const r=o.details?.[t];return n+(typeof r=="number"&&Number.isFinite(r)?r:0)},0)}async function Ee(e){const t=["send-text","send-file","send-image","send-video"],n=[];for(const c of t)n.push(await V({...e,step:c}));await R(1200);const o=await $e(e,3),r=M(o.messages),s=i.join(e.options.outDir,"bottom-page.md"),a=y(o.messages,{conversation:e.options.conversation,attachmentsDirName:i.basename(o.attachmentsDir)});f(i.join(e.options.outDir,"bottom-page-summary.json"),r),f(i.join(e.options.outDir,"server-observe-messages.json"),o.messages),A(s,a);const d=We({sendResults:n,observedMessages:o.messages}),l=d.ok&&o.messages.length>0;return{step:"send-and-confirm",ok:l,reasonCode:l?void 0:d.reasonCode,errorSummary:n.find(c=>!c.ok||c.skipped)?.errorSummary,details:{sent:n.map(c=>({step:c.step,ok:c.ok,skipped:c.skipped,reasonCode:c.reasonCode,errorSummary:c.errorSummary,text:c.details?.text,attachmentPath:c.details?.attachmentPath,sendStatus:c.details?.sendStatus,deferReason:c.details?.deferReason,failureCode:c.details?.failureCode,commitStage:c.details?.commitStage,attemptCount:c.details?.attemptCount,nextAttemptAt:c.details?.nextAttemptAt,waitingRecords:c.details?.waitingRecords,failedRecords:c.details?.failedRecords,manualReviewRecords:c.details?.manualReviewRecords})),sentTexts:d.sentTexts,confirmedTexts:d.confirmedTexts,outboundStatuses:d.outboundStatuses,skippedFixtureCount:d.skippedFixtureCount,pendingOutboundCount:d.pendingOutboundCount,failedOutboundCount:d.failedOutboundCount,manualReviewCount:d.manualReviewCount,observedCount:o.messages.length,byKind:r.byKind,attachmentSummary:r.attachmentSummary,attachmentsDir:o.attachmentsDir,reportPath:i.join(e.options.outDir,"bottom-page-summary.json"),markdownPath:s,markdown:a}}}async function $e(e,t){let n;for(let o=1;o<=t;o+=1)try{return await x(e)}catch(r){if(n=r,o>=t||!Be(r))break;try{const s=await C(e.helper,e.options.traceId),a=await k(e.helper,s,e.options.traceId);await I({helper:e.helper,window:a,binding:e.binding,traceId:e.options.traceId})}catch{}await R(1500*o)}throw n}function Be(e){const t=e instanceof Error?e.message:String(e||"");return/conversation_not_visible|wechat_window_unavailable|wechat_window_not_found|title_not_confirmed|server_observe_failed|timeout/i.test(t)}async function Ne(e){const t=await x(e),n=M(t.messages),o=i.join(e.options.outDir,"bottom-page.md"),r=y(t.messages,{conversation:e.options.conversation,attachmentsDirName:i.basename(t.attachmentsDir)});return f(i.join(e.options.outDir,"bottom-page-summary.json"),n),f(i.join(e.options.outDir,"server-observe-messages.json"),t.messages),A(o,r),{step:"read-bottom-page",ok:n.messageCount>0,reasonCode:n.messageCount>0?void 0:"no_observed_messages",details:{messageCount:n.messageCount,byKind:n.byKind,attachmentSummary:n.attachmentSummary,attachmentsDir:t.attachmentsDir,reportPath:i.join(e.options.outDir,"bottom-page-summary.json"),markdownPath:o,markdown:r}}}async function Fe(e){const t=await x(e,{observePipeline:"edge-structure",persistLocalLedger:!0});B(e.options.outDir,"download-visible",t.observationEvidence);const n=M(t.messages),o=i.join(e.options.outDir,"download-visible.md"),r=y(t.messages,{conversation:e.options.conversation,attachmentsDirName:i.basename(t.attachmentsDir)}),s=q(t.messages,t.attachmentsDir,{observePipeline:t.observePipeline,downloadAnchorText:e.options.downloadAnchorText,ledgerPath:t.ledgerPath,ledgerBinding:t.ledgerBinding,traceHashes:t.traceHashes});f(i.join(e.options.outDir,"bottom-page-summary.json"),n),f(i.join(e.options.outDir,"download-visible-summary.json"),s),f(i.join(e.options.outDir,"download-visible-messages.json"),t.messages),A(o,r);const a=!!(e.options.allowEmptyMedia&&s.reasonCode==="no_visible_media_candidates"&&t.messages.length>0),d=s.ok||a;return{step:"download-visible-media",ok:d,reasonCode:d?void 0:s.reasonCode,details:{mediaCandidateCount:s.mediaCandidateCount,localAttachmentCount:s.localAttachmentCount,originalLocalAttachmentCount:s.originalLocalAttachmentCount,previewAttachmentCount:s.previewAttachmentCount,missingLocalPathCount:s.missingLocalPathCount,pendingAttachmentCount:s.pendingAttachmentCount,byKind:s.byKind,byAvailability:s.byAvailability,reasonCodes:s.reasonCodes,mediaReasonCode:s.reasonCode,allowEmptyMediaRead:a,attachmentsDir:t.attachmentsDir,reportPath:i.join(e.options.outDir,"download-visible-summary.json"),markdownPath:o,markdown:r,phases:s.phases,observePipeline:s.observePipeline,ledgerPath:s.ledgerPath,ledgerRevision:s.ledger?.revision,traceHashes:s.traceHashes,traceEvents:s.traceEvents}}}async function Oe(e){const t=await x(e,{observePipeline:"server-observe"});B(e.options.outDir,"server-observe",t.observationEvidence),f(i.join(e.options.outDir,"server-observe-messages.json"),t.messages);const n=i.join(e.options.outDir,"server-observe.md"),o=y(t.messages,{conversation:e.options.conversation,attachmentsDirName:i.basename(t.attachmentsDir)});A(n,o);const r=Q(t.messages);return{step:"server-observe",ok:t.messages.length>0,reasonCode:t.messages.length>0?void 0:"no_observed_messages",details:{observedCount:t.messages.length,byKind:O(t.messages.map(s=>s.kind||"unknown")),attachmentSummary:r,attachmentsDir:t.attachmentsDir,markdownPath:n,markdown:o}}}async function Le(e){const t=await x(e,{observePipeline:"edge-structure",downloadMedia:!1});B(e.options.outDir,"structure-window",t.observationEvidence),f(i.join(e.options.outDir,"structure-window-messages.json"),t.messages);const n=i.join(e.options.outDir,"structure-window.md"),o=y(t.messages,{conversation:e.options.conversation,attachmentsDirName:i.basename(t.attachmentsDir)});A(n,o);const r=Q(t.messages);return{step:"structure-window",ok:t.messages.length>0,reasonCode:t.messages.length>0?void 0:"no_observed_messages",details:{observedCount:t.messages.length,byKind:O(t.messages.map(s=>s.kind||"unknown")),attachmentSummary:r,attachmentsDir:t.attachmentsDir,markdownPath:n,markdown:o}}}async function x(e,t={}){const n=pe({sessionId:e.options.sessionId,observePipeline:t.observePipeline}),o=se({serverUrl:e.options.serverUrl});n==="direct-edge-structure"?await o.upsertRuntime(e.runtime):await o.upsertRuntime(e.runtime,{...e.binding,enabled:!1,allowReply:!1});const r=i.join(e.options.outDir,"inbound-attachments"),s=t.persistLocalLedger?ct(e.options):void 0,a=s?le(s,e.runtime.runtimeId):void 0;let d,l,c;const h=await fe({runtime:e.runtime,binding:{...e.binding,downloadMedia:t.downloadMedia??e.binding.downloadMedia},helper:e.helper,api:o,workDir:e.options.workDir,attachmentsDir:r,traceId:e.options.traceId,mediaAnchorText:e.options.downloadAnchorText,observePipeline:t.observePipeline,localLedgerTailAnchors:a?lt(a.bindings[e.binding.bindingId]):void 0,onObservationEvidence:({capture:u,ocr:b})=>{d=qe(u),l=Ke(b),c=He(u,b,{captureHash:d,ocrHash:l})}});let m,p;if(a&&s){const u=me({ledger:a,bindingId:e.binding.bindingId,observedMessages:h});m=u.binding,p=Y({bindingId:e.binding.bindingId,revision:m.revision,messages:u.newMessages}),ue(s,a)}return{messages:h,attachmentsDir:r,observePipeline:t.observePipeline,...s?{ledgerPath:s}:{},...m?{ledgerBinding:m}:{},traceHashes:{...d?{captureHash:d}:{},...l?{ocrHash:l}:{},...p?{ingestPayloadHash:p}:{}},...c?{observationEvidence:c}:{}}}function He(e,t,n){return{capture:e,report:{screenshot:{width:e.width,height:e.height,mimeType:e.mimeType,...e.windowId?{windowId:e.windowId}:{}},hashes:n,ocrBlockCount:t.blocks?.length??0,visibleConversationFingerprintCount:t.visibleConversationFingerprints?.length??0,topTexts:(t.blocks??[]).slice(0,40).map(o=>({text:o.text,...o.bbox?{bbox:o.bbox}:{},...typeof o.confidence=="number"?{confidence:o.confidence}:{}}))}}}function B(e,t,n){if(!n)return;const o=n.capture.dataBase64?T(e,`${t}-observation-window`,n.capture):void 0;f(i.join(e,`${t}-observation-evidence.json`),{...n.report,...o?{screenshotPath:o}:{}})}function qe(e){if(e.dataBase64)return`sha256:${D.createHash("sha256").update(Buffer.from(e.dataBase64,"base64")).digest("hex")}`}function Ke(e){return Y({blocks:(e.blocks??[]).map(t=>({text:t.text??"",bbox:t.bbox??null,confidence:typeof t.confidence=="number"?Number(t.confidence.toFixed(4)):null})),visibleConversationFingerprints:e.visibleConversationFingerprints??[]})}function G(e,t){let n=t,o=0,r=0,s="";const a=[];return{actionLog:a,setScenario(l){n=l,o=0,r=0},async request(l,c,h){if(a.push(l),l==="activity.snapshot"){if(o+=1,o<=n.preflightBusySnapshots)return{id:`human-${o}`,ok:!0,result:{keyDownSecondsAgo:.2,mouseMovedSecondsAgo:.2,scrollWheelSecondsAgo:.2,privacy:{capturesKeyContent:!1,capturesMousePath:!1}},latencyMs:0,traceId:h};if(n.forceIdleAfterBusy)return{id:`human-${o}`,ok:!0,result:{keyDownSecondsAgo:60,mouseMovedSecondsAgo:60,leftMouseDownSecondsAgo:60,rightMouseDownSecondsAgo:60,scrollWheelSecondsAgo:60,privacy:{capturesKeyContent:!1,capturesMousePath:!1}},latencyMs:0,traceId:h}}if(l==="automation.lease.acquire"){const m=await e.request(l,c,h),p=m.result&&typeof m.result=="object"?m.result:{};return s=typeof p.leaseId=="string"?p.leaseId:"",m}return l==="automation.lease.status"?(r+=1,n.simulateInterruptionAtLeaseStatus===r?(a.push("automation.lease.simulateInterruption"),{id:`human-lease-${r}`,ok:!0,result:{active:!0,leaseId:s,interrupted:!0,interruptReason:n.interruptionReason||"recent_mouse_activity"},latencyMs:0,traceId:h}):{id:`human-lease-${r}`,ok:!0,result:{active:!0,leaseId:s,interrupted:!1},latencyMs:0,traceId:h}):e.request(l,c,h)}}}function J(e){return e==="human-send-preflight-busy"||e==="human-send-preflight-busy-then-idle"||e==="human-send-user-active-timeout"||e==="human-observe-deferred"?{preflightBusySnapshots:100}:e==="human-send-takeover-during-run"||e==="human-send-takeover-then-idle"?{preflightBusySnapshots:0,forceIdleAfterBusy:!0,simulateInterruptionAtLeaseStatus:2,interruptionReason:"recent_mouse_activity"}:{preflightBusySnapshots:0,forceIdleAfterBusy:!0}}function Ue(){return{preflightBusySnapshots:0,forceIdleAfterBusy:!0}}function Ve(e,t){return t.sendStatus!=="sent_unconfirmed"?!1:e==="human-send-normal"||e==="human-send-preflight-busy-then-idle"||e==="human-send-takeover-then-idle"}async function N(e){const t=await C(e.helper,e.traceId),n=await k(e.helper,t,e.traceId);if(!(await I({helper:e.helper,window:n,binding:e.binding,traceId:e.traceId,settleToBottom:e.settleToBottom})).opened)return 0;const r=await W(e.helper,n.windowId,e.traceId),s=T(e.outDir,`${e.filePrefix}-observe-marker`,r),a=await E(e.helper,r,e.traceId);return f(i.join(e.outDir,`${e.filePrefix}-observe-marker-ocr.json`),{screenshotPath:s,marker:e.marker,ocr:a}),(a.blocks||[]).map(l=>l.text||"").join(`
|
|
4
|
+
`).split(e.marker).length-1}async function ze(e){const t=Math.max(1,e.attempts??3),n=typeof e.targetGreaterThan=="number"&&Number.isFinite(e.targetGreaterThan)?e.targetGreaterThan:null;let o=0;for(let r=0;r<t;r+=1){if(o=await N({helper:e.helper,binding:e.binding,marker:e.marker,traceId:e.traceId,outDir:e.outDir,filePrefix:`${e.filePrefix}-${r+1}`,settleToBottom:e.settleToBottom}),n==null?o>0:o>n)return o;r<t-1&&await R(800)}return o}function Ge(e,t,n){return n.length>0||e.sendStatus==="confirmed_echo"?"confirmed_echo":t.waitingRecords.length>0?"send_waiting_user_idle":t.failedRecords.length>0?e.failureCode==="user_active_timeout"?"failed:user_active_timeout":"outbound_send_failed":t.manualReviewRecords.length>0||e.sendStatus==="manual_review"?"manual_review":e.sendStatus==="sent_unconfirmed"?"sent_unconfirmed":e.sendStatus}function Je(e,t){return e==="human-send-preflight-busy"?t.outboundStatus==="queued"&&t.observedMarkerCount===0&&!t.actionLog.includes("clipboard.setText")&&!t.actionLog.includes("keyboard.shortcut"):e==="human-send-user-active-timeout"?t.outboundStatus==="failed"&&t.runStatus==="failed:user_active_timeout"&&t.observedMarkerCount===0&&!t.actionLog.includes("clipboard.setText")&&!t.actionLog.includes("keyboard.shortcut"):e==="human-send-takeover-during-run"?(t.outboundStatus==="queued"||t.outboundStatus==="manual_review")&&t.observedMarkerCount===0:e==="human-send-preflight-busy-then-idle"||e==="human-send-takeover-then-idle"||e==="human-send-normal"?t.outboundStatus==="confirmed_echo"||t.outboundStatus==="sent_unconfirmed"&&t.observedMarkerCount===1:t.runStatus==="observe_deferred_user_active"}function Qe(e){return ge({runtimeId:e.runtimeId,machineId:e.machineId,pollIntervalMs:6e4,platform:e.platform,foregroundPolicy:"work",bindings:[{bindingId:`action-smoke:${_(e.conversation)}`,sessionId:e.sessionId||`action-smoke:${_(e.runtimeId)}`,conversationDisplayName:e.conversation,enabled:!0,allowReply:!0,downloadMedia:!0}]})}function Ze(e,t){const n=ae({platform:e.platform});if(!n.ok)throw new Error(`${n.reasonCode}: ${n.message}`);return new de({helperPath:n.helperPath,expectedHelperVersion:n.version||ie,requiredCapabilities:tt(e),guardUnsafeWindowsCommands:(e.platform??process.platform)==="win32",cleanupWindowsOverlays:(e.platform??process.platform)==="win32",requestLogger:Xe(t)})}function Xe(e){return t=>{w.appendFileSync(e,`${JSON.stringify(Ye(t))}
|
|
5
|
+
`)}}function Ye(e){const t={phase:e.phase,at:e.at,id:e.id,command:e.command};return e.traceId&&(t.traceId=e.traceId),e.timeoutMs!=null&&(t.timeoutMs=e.timeoutMs),e.durationMs!=null&&(t.durationMs=e.durationMs),e.params!==void 0&&(t.params=P(e.params)),e.ok!==void 0&&(t.ok=e.ok),e.errorCode&&(t.errorCode=e.errorCode),e.errorSummary&&(t.errorSummary=e.errorSummary),e.latencyMs!=null&&(t.latencyMs=e.latencyMs),e.result!==void 0&&(t.result=P(e.result)),t}function P(e,t="",n=0){if(e==null||typeof e=="number"||typeof e=="boolean")return e;if(typeof e=="string")return et(t,e)?{type:"string",length:e.length,sha256:D.createHash("sha256").update(e).digest("hex").slice(0,16),preview:e.slice(0,120)}:e;if(Array.isArray(e)){const s=e.slice(0,10).map(a=>P(a,t,n+1));return e.length>s.length?{type:"array",length:e.length,items:s}:s}if(typeof e!="object")return String(e);if(n>=5)return{type:"object",truncated:!0};const o=e,r={};for(const[s,a]of Object.entries(o))r[s]=P(a,s,n+1);return r}function et(e,t){return t.length>240?!0:/(base64|bytes|data|image|screenshot|png|jpeg|jpg|buffer)/i.test(e)&&t.length>48}function tt(e){if((e.platform??process.platform)==="win32")return e.steps.some(t=>t.startsWith("send")||t.startsWith("human-send"))?j("send"):e.steps.some(t=>t==="download-visible-media")?j("download"):j("observe")}function nt(e){const t=String(e||"").trim().toLowerCase();if(t){if(t==="windows"||t==="win32")return"win32";if(t==="macos"||t==="darwin")return"darwin";throw new Error(`unsupported_wechat_smoke_platform:${e}`)}}function ot(e,t){const n=i.join(t.outDir,"fixtures");w.mkdirSync(n,{recursive:!0});const o=new Date().toISOString().replace(/[-:.TZ]/g,"").slice(0,14);if(e==="send-text")return{text:t.text||`codex-product-action text ${o}`};if(e==="send-file"){const r=t.filePath||i.join(n,`wechat-action-smoke-${o}.txt`);return t.filePath||w.writeFileSync(r,`Shennian WeChat product action smoke
|
|
5
6
|
${o}
|
|
6
|
-
`,"utf8"),{text:`codex-product-action file ${o}`,attachmentPath:r}}if(e==="send-image"){const r=t.imagePath||
|
|
7
|
-
`,"utf8")}function
|
|
8
|
-
`)}async function
|
|
9
|
-
`),process.exit(1)});export{
|
|
7
|
+
`,"utf8"),{text:`codex-product-action file ${o}`,attachmentPath:r}}if(e==="send-image"){const r=t.imagePath||i.join(n,`wechat-action-smoke-${o}.png`);return t.imagePath||ut(r),{text:`codex-product-action image ${o}`,attachmentPath:r}}if(e==="send-video"){const r=t.videoPath||i.join(n,`wechat-action-smoke-${o}.mp4`);return!t.videoPath&&!mt(r)?{skipped:!0,reasonCode:"ffmpeg_unavailable_for_video_fixture"}:{text:`codex-product-action video ${o}`,attachmentPath:r}}throw new Error(`step ${e} is not a send step`)}function Q(e){const t=e.flatMap(n=>rt(n.mediaMetadata));return{count:t.length,byAvailability:O(t.map(n=>Z(n,"availability")||"unknown")),localPaths:t.map(n=>Z(n,"localPath")).filter(n=>!!n)}}function rt(e){if(!e||typeof e!="object")return[];const t=e;return Array.isArray(t.attachments)?t.attachments.filter(X):X(t.attachment)?[t.attachment]:t.localPath||t.url||t.availability||t.name||t.fileName?[t]:[]}function st(e){const t=g(e,"--mode")||(e[0]?.startsWith("--")?"":e[0]);return t==="send"||t==="observe"||t==="all"||t==="open-read"?t:"open-read"}function at(e){return e==="open-read"||e==="send-text"||e==="send-file"||e==="send-image"||e==="send-video"||e==="structure-window"||e==="server-observe"||e==="read-bottom-page"||e==="download-visible-media"||e==="send-and-confirm"||e==="human-send-preflight-busy"||e==="human-send-preflight-busy-then-idle"||e==="human-send-user-active-timeout"||e==="human-send-takeover-during-run"||e==="human-send-takeover-then-idle"||e==="human-send-normal"||e==="human-observe-deferred"?e:null}function it(e,t){const n=[];for(let o=0;o<e.length;o+=1)e[o]===t&&e[o+1]&&n.push(e[o+1]);return n}function g(e,t){const n=e.indexOf(t),o=n>=0?e[n+1]:void 0;return o&&!o.startsWith("--")?o:void 0}function F(e){return e?i.resolve(e):void 0}function dt(e){return Array.from(new Set(e))}function T(e,t,n){const o=n.mimeType.includes("jpeg")?".jpg":".png",r=i.join(e,`${t}${o}`);return w.writeFileSync(r,Buffer.from(n.dataBase64,"base64")),r}function f(e,t){w.mkdirSync(i.dirname(e),{recursive:!0}),w.writeFileSync(e,`${JSON.stringify(t,null,2)}
|
|
8
|
+
`,"utf8")}function A(e,t){w.mkdirSync(i.dirname(e),{recursive:!0}),w.writeFileSync(e,t,"utf8")}function ct(e){return i.join(e.outDir,"wechat-channel-ledger.json")}function lt(e,t=3){return(e?.recent??[]).slice(-t).map(n=>({stableMessageKey:n.stableMessageKey,senderRole:n.senderRole,kind:n.kind,anchorText:n.anchorText??n.normalizedText??n.textExcerpt??null,anchorMetadata:n.anchorMetadata??null}))}function ut(e){w.writeFileSync(e,Buffer.from("iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAAVElEQVR4nO3PMQ0AMAgAMUTof2kOKWzo8mCqkmeX9waYtwOwG4DbANwG4DYAtwG4DcBtAG4DcBuA2wDcBuA2ALcBuA3AbQBuA3AbgNsA3AbgNgC3AbgNwG0AbgNwG8BPDyCqAzmh3yHRAAAAAElFTkSuQmCC","base64"))}function mt(e){return ne("ffmpeg",["-y","-f","lavfi","-i","testsrc=size=160x120:rate=5","-t","1","-pix_fmt","yuv420p",e],{encoding:"utf8",stdio:"ignore",timeout:2e4}).status===0&&w.existsSync(e)}function O(e){const t={};for(const n of e)t[n]=(t[n]??0)+1;return t}function Z(e,t){return typeof e[t]=="string"?e[t].trim():""}function X(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function _(e){return D.createHash("sha256").update(e).digest("hex").slice(0,16)}function Y(e){return`sha256:${D.createHash("sha256").update(ht(e)).digest("hex")}`}function ht(e){return JSON.stringify(L(e))}function L(e){if(Array.isArray(e))return e.map(L);if(!e||typeof e!="object")return e;const t=e;return Object.fromEntries(Object.keys(t).sort().map(n=>[n,L(t[n])]))}function ft(e){const t=e instanceof Error?e.message:String(e),n=t.split(":",1)[0]?.trim();return n&&/^[a-z0-9_/-]+$/i.test(n)?n.replace(/\//g,"_"):/permission|accessibility|screen|automation/i.test(t)?"permission_missing":/wechat.*window|window.*unavailable/i.test(t)?"wechat_window_unavailable":/observe|VLM|server|api/i.test(t)?"server_observe_failed":"action_smoke_failed"}function gt(e){if(e==="wechat_duplicate_instance")return"\u8BF7\u5173\u95ED\u91CD\u590D\u767B\u5F55\u3001\u5DF2\u767B\u5F55\u63D0\u793A\u6216\u7B2C\u4E8C\u4E2A\u5FAE\u4FE1\u4E3B\u7A97\u53E3\uFF0C\u53EA\u4FDD\u7559\u4E00\u4E2A\u5DF2\u767B\u5F55\u7684 Windows \u5FAE\u4FE1\u4E3B\u7A97\u53E3\u540E\u91CD\u8BD5\u3002"}function R(e){return new Promise(t=>setTimeout(t,e))}function pt(e){process.stdout.write(`${JSON.stringify({ok:e.ok,conversation:e.conversation,outDir:e.outDir,durationMs:e.durationMs,steps:e.steps.map(t=>({step:t.step,ok:t.ok,skipped:t.skipped,reasonCode:t.reasonCode,userAction:t.userAction,details:t.details,errorSummary:t.errorSummary}))},null,2)}
|
|
9
|
+
`)}async function wt(){const e=ve(process.argv.slice(2)),t=await Se(e);pt(t),(!t.ok||e.requireServer&&t.steps.some(n=>n.step==="server-observe"&&!n.ok))&&process.exit(1)}process.argv[1]&&i.resolve(process.argv[1])===oe(import.meta.url)&&wt().catch(e=>{process.stderr.write(`${e instanceof Error?e.stack||e.message:String(e)}
|
|
10
|
+
`),process.exit(1)});export{M as buildBottomPageReport,q as buildDownloadVisibleMediaReport,We as buildSendAndConfirmEvidence,Pe as buildSendStepAcceptance,je as nextSmokeDrainWaitMs,ve as parseWeChatChannelActionSmokeArgs,pe as resolveWeChatSmokeObserveSessionMode,Se as runWeChatChannelActionSmoke,ye as stepsForMode};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { WeChatChannelObservedMessage } from '../channels/wechat-channel/client.js';
|
|
2
|
+
export type WeChatMessagesMarkdownOptions = {
|
|
3
|
+
conversation?: string;
|
|
4
|
+
attachmentsDirName?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function buildWeChatMessagesMarkdown(messages: WeChatChannelObservedMessage[], options?: WeChatMessagesMarkdownOptions): string;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import d from"node:path";function x(n,t={}){const e=[];if(t.conversation?.trim()&&e.push(`${i(t.conversation)}:`),n.length===0)return e.push("\u6D88\u606F: \uFF08\u6CA1\u6709\u8BFB\u5230\uFF09"),`${e.join(`
|
|
2
|
+
`)}
|
|
3
|
+
`;for(const r of n)e.push(`${l(r)}: ${m(r,t)}`);return`${e.join(`
|
|
4
|
+
`)}
|
|
5
|
+
`}function l(n){return n.senderName?.trim()?i(n.senderName):n.senderRole==="self"?"\u6211":n.senderRole==="system"?"\u7CFB\u7EDF":n.senderRole==="contact"?"\u5BF9\u65B9":"\u672A\u77E5"}function m(n,t){const e=$(n);if(e.length>0)return e.map(a=>h(a,n,t)).join("\u3001");const r=n.normalizedText||n.anchorText||n.textExcerpt;return r?.trim()?i(r):`\uFF08${s(n.kind)}\uFF09`}function h(n,t,e){const r=o(n,"localPath"),a=o(n,"name")||o(n,"fileName")||f(r)||s(o(n,"type")||t.kind),u=p(r,e);return u?`[${y(a)}](${k(u)})`:i(a)}function p(n,t){if(!n)return"";const e=f(n);return e&&t.attachmentsDirName?`${t.attachmentsDirName.replace(/\\/g,"/")}/${e}`:n.replace(/\\/g,"/")}function $(n){const t=c(n.mediaMetadata)?n.mediaMetadata:{},e=[];return c(t.attachment)&&e.push(t.attachment),Array.isArray(t.attachments)&&e.push(...t.attachments.filter(c)),e}function f(n){return n?d.posix.basename(n.replace(/\\/g,"/")):""}function s(n){const t=String(n||"").toLowerCase();return t.includes("image")||t.includes("photo")?"\u56FE\u7247":t.includes("video")?"\u89C6\u9891":t.includes("file")||t.includes("document")?"\u6587\u4EF6":"\u6D88\u606F"}function k(n){return/[\s()<>]/.test(n)?`<${n.replace(/[<>]/g,"")}>`:n}function y(n){return i(n).replace(/([\\\]])/g,"\\$1")}function i(n){return String(n||"").replace(/\s+/g," ").trim()}function o(n,t){const e=n[t];return typeof e=="string"?e:""}function c(n){return!!n&&typeof n=="object"&&!Array.isArray(n)}export{x as buildWeChatMessagesMarkdown};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { type WeChatChannelActionSmokeOptions, type WeChatChannelActionSmokeStep } from './wechat-channel-action-smoke.js';
|
|
2
|
-
export type WeChatChannelProductStepName = 'open-conversation' | 'fingerprint' | 'visible-structure' | 'server-observe' | 'download-visible' | 'read-bottom-page' | 'send-message' | 'send-and-confirm' | 'send-text' | 'send-file' | 'send-image' | 'send-video' | 'observe' | 'human-coordination' | 'human-send-core' | 'human-send-preflight-busy' | 'human-send-preflight-busy-then-idle' | 'human-send-user-active-timeout' | 'human-send-takeover-during-run' | 'human-send-takeover-then-idle' | 'human-send-normal' | 'human-observe-deferred' | 'all';
|
|
1
|
+
import { runWeChatChannelActionSmoke, type WeChatChannelActionSmokeOptions, type WeChatChannelActionSmokeStep } from './wechat-channel-action-smoke.js';
|
|
2
|
+
export type WeChatChannelProductStepName = 'open-conversation' | 'fingerprint' | 'visible-structure' | 'server-observe' | 'download-visible' | 'read-visible' | 'read-bottom-page' | 'send-message' | 'send-and-confirm' | 'send-text' | 'send-file' | 'send-image' | 'send-video' | 'observe' | 'human-coordination' | 'human-send-core' | 'human-send-preflight-busy' | 'human-send-preflight-busy-then-idle' | 'human-send-user-active-timeout' | 'human-send-takeover-during-run' | 'human-send-takeover-then-idle' | 'human-send-normal' | 'human-observe-deferred' | 'all';
|
|
3
3
|
export type WeChatChannelProductStepsOptions = WeChatChannelActionSmokeOptions & {
|
|
4
4
|
productStep: WeChatChannelProductStepName;
|
|
5
5
|
};
|
|
6
6
|
export declare function parseWeChatChannelProductStepsArgs(argv: string[]): WeChatChannelProductStepsOptions;
|
|
7
7
|
export declare function stepsForProductStep(step: WeChatChannelProductStepName): WeChatChannelActionSmokeStep[];
|
|
8
|
+
export declare function collectWeChatProductStepMarkdown(result: Awaited<ReturnType<typeof runWeChatChannelActionSmoke>>): string;
|
|
8
9
|
export declare function isWeChatChannelProductStepsEntrypoint(metaUrl: string, argvPath?: string): boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import u from"node:path";import{fileURLToPath as l}from"node:url";import{parseWeChatChannelActionSmokeArgs as m,runWeChatChannelActionSmoke as c}from"./wechat-channel-action-smoke.js";const h={open:"open-conversation","open-read":"open-conversation","open-conversation":"open-conversation",fingerprint:"fingerprint","visible-structure":"visible-structure",structure:"visible-structure","structure-window":"visible-structure","server-observe":"server-observe","legacy-observe":"server-observe","download-visible":"download-visible",download:"download-visible","read-bottom-page":"read-bottom-page","bottom-page":"read-bottom-page","read-bottom":"read-bottom-page","send-message":"send-message",send:"send-message","send-and-confirm":"send-and-confirm","send-confirm":"send-and-confirm","send-text":"send-text","send-file":"send-file","send-image":"send-image","send-video":"send-video",observe:"observe","human-coordination":"human-coordination","human-send-core":"human-send-core","human-send-preflight-busy":"human-send-preflight-busy","human-send-preflight-busy-then-idle":"human-send-preflight-busy-then-idle","human-send-user-active-timeout":"human-send-user-active-timeout","human-send-takeover-during-run":"human-send-takeover-during-run","human-send-takeover-then-idle":"human-send-takeover-then-idle","human-send-normal":"human-send-normal","human-observe-deferred":"human-observe-deferred",all:"all"};function
|
|
1
|
+
import u from"node:path";import{fileURLToPath as l}from"node:url";import{parseWeChatChannelActionSmokeArgs as m,runWeChatChannelActionSmoke as c}from"./wechat-channel-action-smoke.js";const h={open:"open-conversation","open-read":"open-conversation","open-conversation":"open-conversation",fingerprint:"fingerprint","visible-structure":"visible-structure",structure:"visible-structure","structure-window":"visible-structure","server-observe":"server-observe","legacy-observe":"server-observe","download-visible":"download-visible",download:"download-visible",read:"read-visible","read-visible":"read-visible","read-messages":"read-visible",messages:"read-visible","read-bottom-page":"read-bottom-page","bottom-page":"read-bottom-page","read-bottom":"read-bottom-page","send-message":"send-message",send:"send-message","send-and-confirm":"send-and-confirm","send-confirm":"send-and-confirm","send-text":"send-text","send-file":"send-file","send-image":"send-image","send-video":"send-video",observe:"observe","human-coordination":"human-coordination","human-send-core":"human-send-core","human-send-preflight-busy":"human-send-preflight-busy","human-send-preflight-busy-then-idle":"human-send-preflight-busy-then-idle","human-send-user-active-timeout":"human-send-user-active-timeout","human-send-takeover-during-run":"human-send-takeover-during-run","human-send-takeover-then-idle":"human-send-takeover-then-idle","human-send-normal":"human-send-normal","human-observe-deferred":"human-observe-deferred",all:"all"};function p(e){const n=e.filter(o=>o!=="--"),r=v(n),t=n.filter((o,d)=>!(d===0&&!o.startsWith("--"))),s=m(["--mode",r==="all"?"all":"custom",...t,...f(r)]);return{...s,allowEmptyMedia:s.allowEmptyMedia||r==="read-visible",productStep:r,mode:r==="all"?"all":"custom",steps:i(r)}}function i(e){return e==="open-conversation"||e==="fingerprint"?["open-read"]:e==="visible-structure"||e==="observe"?["structure-window"]:e==="server-observe"?["server-observe"]:e==="download-visible"?["download-visible-media"]:e==="read-visible"?["download-visible-media"]:e==="read-bottom-page"?["read-bottom-page"]:e==="send-text"?["open-read","send-text"]:e==="send-file"?["open-read","send-file"]:e==="send-image"?["open-read","send-image"]:e==="send-video"?["open-read","send-video"]:e==="send-message"?["open-read","send-text","send-file","send-image","send-video"]:e==="send-and-confirm"?["open-read","send-and-confirm"]:e==="human-send-preflight-busy"?["human-send-preflight-busy"]:e==="human-send-preflight-busy-then-idle"?["human-send-preflight-busy-then-idle"]:e==="human-send-user-active-timeout"?["human-send-user-active-timeout"]:e==="human-send-takeover-during-run"?["human-send-takeover-during-run"]:e==="human-send-takeover-then-idle"?["human-send-takeover-then-idle"]:e==="human-send-normal"?["human-send-normal"]:e==="human-observe-deferred"?["human-observe-deferred"]:e==="human-send-core"||e==="human-coordination"?["human-send-preflight-busy","human-send-preflight-busy-then-idle","human-send-user-active-timeout","human-send-takeover-during-run","human-send-takeover-then-idle","human-send-normal","human-observe-deferred"]:["open-read","send-text","send-file","send-image","send-video","structure-window"]}function f(e){return i(e).flatMap(n=>["--step",n])}function v(e){const n=a(e,"--product-step")||a(e,"--step-name"),r=e[0]&&!e[0].startsWith("--")?e[0]:"",t=String(n||r||"open-conversation").trim(),s=t.toLowerCase().replace(/_/g,"-"),o=h[s];if(!o)throw new Error(`unknown_product_step: ${t}`);return o}function a(e,n){const r=e.indexOf(n),t=r>=0?e[r+1]:void 0;return t&&!t.startsWith("--")?t:void 0}function b(){process.stdout.write(`Usage:
|
|
2
2
|
pnpm wechat:rpa:product-steps -- <step> [options]
|
|
3
3
|
|
|
4
4
|
Product steps:
|
|
@@ -7,6 +7,7 @@ Product steps:
|
|
|
7
7
|
visible-structure Run structure-window on the full WeChat window.
|
|
8
8
|
server-observe Run the legacy /observe compatibility path for debug only.
|
|
9
9
|
download-visible Run the full visible-media edge flow and validate local attachments.
|
|
10
|
+
read-visible Default read: structure recent messages and download visible attachments when present.
|
|
10
11
|
read-bottom-page Observe the current bottom page and write bottom-page-summary.json.
|
|
11
12
|
send-message Send text, file, image and video fixtures.
|
|
12
13
|
send-and-confirm Send fixtures, observe bottom page, and confirm at least one sent text is visible.
|
|
@@ -31,6 +32,9 @@ Common options:
|
|
|
31
32
|
|
|
32
33
|
This devtool runs the product helper/runtime from the workspace. It does not enable
|
|
33
34
|
the long-running WeChat channel and does not require changing the global shennian CLI.
|
|
34
|
-
`)}async function
|
|
35
|
-
`),
|
|
36
|
-
`),process.
|
|
35
|
+
`)}async function g(){if(process.argv.includes("--help")||process.argv.includes("-h")){b();return}const e=p(process.argv.slice(2)),n=await c(e),r=w(n);r&&process.stdout.write(`${r}
|
|
36
|
+
`),process.stdout.write(`${JSON.stringify({ok:n.ok,productStep:e.productStep,conversation:n.conversation,outDir:n.outDir,helperTracePath:n.helperTracePath,durationMs:n.durationMs,steps:n.steps},null,2)}
|
|
37
|
+
`),n.ok||(process.exitCode=1)}function w(e){return e.steps.map(n=>typeof n.details?.markdown=="string"?n.details.markdown.trim():"").filter(Boolean).join(`
|
|
38
|
+
|
|
39
|
+
`)}function k(e,n=process.argv[1]){if(!n)return!1;try{return u.resolve(n)===l(e)}catch{return!1}}k(import.meta.url)&&g().catch(e=>{process.stderr.write(`${e.stack||e.message||String(e)}
|
|
40
|
+
`),process.exit(1)});export{w as collectWeChatProductStepMarkdown,k as isWeChatChannelProductStepsEntrypoint,p as parseWeChatChannelProductStepsArgs,i as stepsForProductStep};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import u from"node:fs";import h from"node:path";import{randomUUID as y}from"node:crypto";import{extractPayloadText as k,isAgentHiddenPayload as A,isToolPayload as
|
|
1
|
+
import u from"node:fs";import h from"node:path";import{randomUUID as y}from"node:crypto";import{extractPayloadText as k,isAgentHiddenPayload as A,isSystemControlPayload as T,isToolPayload as w}from"@shennian/wire";import{resolveShennianPath as v}from"../config/index.js";import{listSessionRecords as I,readMessages as M}from"../session/store.js";import{listProjectedSessions as W}from"../session/projection.js";const g=v("manager-registry.json");function l(){return new Date().toISOString()}function D(){return{managers:{},workers:{},replyTargets:{}}}class O{load(){try{const e=JSON.parse(u.readFileSync(g,"utf-8"));return{managers:e.managers??{},workers:e.workers??{},replyTargets:e.replyTargets??{}}}catch{return D()}}save(e){u.mkdirSync(h.dirname(g),{recursive:!0}),u.writeFileSync(g,JSON.stringify(e,null,2))}upsertManager(e){const t=this.load(),r=t.managers[e.sessionId],a=l(),s={sessionId:e.sessionId,agentSessionId:e.agentSessionId??r?.agentSessionId??null,workDir:e.workDir,machineId:e.machineId??r?.machineId??null,modelId:e.modelId,defaultWorkerAgentType:e.defaultWorkerAgentType??r?.defaultWorkerAgentType??null,defaultWorkerModelId:e.defaultWorkerModelId??r?.defaultWorkerModelId??null,status:e.status??r?.status??"idle",managedWorkerSessionIds:r?.managedWorkerSessionIds??[],attachedExternalChannels:r?.attachedExternalChannels??[],createdAt:r?.createdAt??a,updatedAt:a};return t.managers[e.sessionId]=s,this.save(t),s}getManager(e){return this.load().managers[e]}addWorker(e){const t=this.load(),r=t.managers[e.managerSessionId];if(!r)throw new Error("Manager runtime is not registered");const a=e.sessionId??`sess_worker_${y()}`,s=l(),o={sessionId:a,agentType:e.agentType,workDir:e.workDir,managedBy:e.managerSessionId,status:"running",createdAt:s,updatedAt:s,lastActivityAt:s,summary:e.summary??null,agentSessionId:null,runId:null};return t.workers[a]=o,r.managedWorkerSessionIds.includes(a)||r.managedWorkerSessionIds.push(a),r.updatedAt=s,this.save(t),o}updateWorker(e,t){const r=this.load(),a=r.workers[e];if(!a)return;const s={...a,...t,updatedAt:l()};return r.workers[e]=s,this.save(r),s}listWorkers(e,t={}){const r=this.load(),a=r.managers[e];if(!a)return[];const s=Object.values(r.workers).filter(n=>n.workDir===a.workDir).filter(n=>t.includeManagers||n.agentType!=="manager").map(n=>this.decorateManagedWorker(n,t.runningSessionIds)),o=new Set(s.map(n=>n.sessionId)),i=I().filter(n=>n.workDir===a.workDir).filter(n=>t.includeManagers||n.agentType!=="manager").filter(n=>!o.has(n.sessionId)).map(n=>this.sessionRecordToWorker(n,t.runningSessionIds)),c=new Set([...s,...i].map(n=>n.sessionId)),f=(t.projectedSessions??W()).filter(n=>n.workDir===a.workDir).filter(n=>t.includeManagers||n.agentType!=="manager").filter(n=>!c.has(n.id)).map(n=>this.projectedSessionToWorker(n,t.runningSessionIds));return[...s,...i,...f].sort((n,S)=>S.lastActivityAt.localeCompare(n.lastActivityAt))}getWorkerForManager(e,t){const r=this.load(),a=r.managers[e],s=r.workers[t];if(!a)return;if(s)return s.workDir!==a.workDir||s.agentType==="manager"?void 0:this.decorateManagedWorker(s);const o=I().find(i=>i.sessionId===t);if(!(!o||o.workDir!==a.workDir||o.agentType==="manager"))return this.sessionRecordToWorker(o)}decorateManagedWorker(e,t){const r=t?.has(e.sessionId)?"running":e.status,a=this.readTranscriptSummary(e.sessionId,e.summary??null),s=a.lastMessagePreview??e.lastMessagePreview??e.summary??null,o=e.userGoal??a.userGoal??null;return{...e,managedBy:e.managedBy??null,status:r,title:e.title??o??s??e.summary??e.sessionId,userGoal:o,lastMessagePreview:s,summary:e.summary??s,canResume:e.canResume??e.status!=="aborted",source:e.source??"manager_registry",role:"managed_worker"}}sessionRecordToWorker(e,t){const r=this.readTranscriptSummary(e.sessionId,e.lastMessagePreview??null),a=r.lastMessagePreview??e.lastMessagePreview??null,s=r.userGoal,o=t?.has(e.sessionId)?"running":e.status==="failed"?"error":e.status==="completed"?"final":"idle";return{sessionId:e.sessionId,agentType:e.agentType,workDir:e.workDir,managedBy:null,status:o,createdAt:e.createdAt,updatedAt:e.updatedAt,lastActivityAt:e.lastActivityAt,title:s??a??e.sessionId,userGoal:s,lastMessagePreview:a,summary:a??s??null,agentSessionId:e.agentSessionId??null,runId:null,canResume:!!e.agentSessionId,source:"local_index",role:"project_session"}}projectedSessionToWorker(e,t){const r=e.lastMessagePreview??null,a=e.title?.trim()||r,s=t?.has(e.id)?"running":e.status==="failed"?"error":e.status==="completed"?"final":"idle";return{sessionId:e.id,agentType:e.agentType,workDir:e.workDir,managedBy:null,status:s,createdAt:e.createdAt,updatedAt:e.updatedAt,lastActivityAt:e.lastActivityAt||e.updatedAt,title:a??e.id,userGoal:a??null,lastMessagePreview:r,summary:r??a??null,agentSessionId:e.agentSessionId??null,runId:e.activity?.runId??null,canResume:!0,source:"app_projection",role:"project_session"}}readTranscriptSummary(e,t){const r=M(e,{limit:200});if(!r.length)return{userGoal:null,lastMessagePreview:t};const a=[...r].sort((i,c)=>i.ts-c.ts),s=a.find(i=>i.role==="user"),o=[...a].reverse().find(i=>m(i));return{userGoal:s?p(m(s),160):null,lastMessagePreview:p(m(o),180)??t}}createReplyTarget(e){const t=this.load(),r={replyTarget:`rt_${y()}`,managerSessionId:e.managerSessionId,channelId:e.channelId,conversationId:e.conversationId,messageId:e.messageId??null,createdAt:l()};return t.replyTargets[r.replyTarget]=r,this.save(t),r}getReplyTarget(e){return this.load().replyTargets[e]}getLatestReplyTargetForManager(e){return Object.values(this.load().replyTargets).filter(t=>t.managerSessionId===e).sort((t,r)=>r.createdAt.localeCompare(t.createdAt))[0]}}function m(d){return!d||w(d.payload)||A(d.payload)||T(d.payload)?null:k(d.payload).replace(/\r\n/g,`
|
|
2
2
|
`).trim()||null}function p(d,e){return d?d.length>e?`${d.slice(0,e)}...`:d:null}export{O as ManagerRegistry};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import T from"node:fs";import j from"node:os";import x from"node:path";import{buildApprovalPendingPayload as V,buildUserMessagePayload as k,isSystemControlPayload as A,isToolPayload as F}from"@shennian/wire";import{listOpenCodeSessionFiles as jt,parseOpenCodeSessionFile as At,parseOpenCodeSessionSnapshot as Mt}from"./opencode-parser.js";import{buildImagePayload as X,buildToolPayload as Y,inferMimeType as E,makeCursor as I,makeEventKey as w,normalizeText as h,parseStructuredString as Z,readClaudeEventCwd as N,readJsonlLines as v,readTimestamp as q,safeParse as M,isClaudeSubagentTranscript as D,shouldIgnoreClaudeProjectDir as K,shouldIgnoreClaudeTranscriptPath as O,shouldIgnoreNativeScanPath as R}from"./parser-common.js";function P(e){if(typeof e=="string"){const s=e.trim();return s?{path:s,name:x.basename(s)||"image.png",mimeType:E(s),kind:"image"}:null}if(typeof e!="object"||e===null)return null;const r=e,n=typeof r.path=="string"?r.path:typeof r.file_path=="string"?r.file_path:typeof r.saved_path=="string"?r.saved_path:"";if(!n.trim())return null;const t=typeof r.name=="string"&&r.name.trim()?r.name:x.basename(n)||"image.png",o=typeof r.mimeType=="string"&&r.mimeType.trim()?r.mimeType:E(n);return{path:n,name:t,mimeType:o,kind:"image"}}function U(e){return Array.isArray(e)?e.map(n=>{if(typeof n=="string")return n;if(typeof n=="object"&&n!==null){const t=n;return typeof t.text=="string"?t.text:""}return""}).map(n=>h(n)).filter(Boolean).join(`
|
|
2
2
|
|
|
3
|
-
`):""}function B(e){const r=h(e);if(!r)return{text:"",strippedWrapper:!1};const n=r.match(/My request for Codex:\s*([\s\S]*)$/i);return n&&n[1]?{text:tt(n[1]),strippedWrapper:!0}:{text:r,strippedWrapper:!1}}function tt(e){return h(e.replace(/<image>\s*<\/image>/gi,""))}function z(e){const r=h(e);if(!r)return!1;const n=r.startsWith("# AGENTS.md instructions for ")&&r.includes("<INSTRUCTIONS>")&&r.includes("</INSTRUCTIONS>"),t=r.includes("<environment_context>")&&r.includes("</environment_context>");return n&&t}function H(e){const r=U(e.text_elements),n=Array.isArray(e.input)?U(e.input):"",t=typeof e.message=="string"?B(e.message):{text:"",strippedWrapper:!1},o=t.text,s=r||n||o,u=t.strippedWrapper?"codex_app_context_wrapper":void 0,a=Array.isArray(e.local_images)?e.local_images.map(P).filter(
|
|
3
|
+
`):""}function B(e){const r=h(e);if(!r)return{text:"",strippedWrapper:!1};const n=r.match(/My request for Codex:\s*([\s\S]*)$/i);return n&&n[1]?{text:tt(n[1]),strippedWrapper:!0}:{text:r,strippedWrapper:!1}}function tt(e){return h(e.replace(/<image>\s*<\/image>/gi,""))}function z(e){const r=h(e);if(!r)return!1;if(A(r))return!0;const n=r.startsWith("# AGENTS.md instructions for ")&&r.includes("<INSTRUCTIONS>")&&r.includes("</INSTRUCTIONS>"),t=r.includes("<environment_context>")&&r.includes("</environment_context>");return n&&t}function H(e){const r=U(e.text_elements),n=Array.isArray(e.input)?U(e.input):"",t=typeof e.message=="string"?B(e.message):{text:"",strippedWrapper:!1},o=t.text,s=r||n||o,u=t.strippedWrapper?"codex_app_context_wrapper":void 0,a=Array.isArray(e.local_images)?e.local_images.map(P).filter(f=>f!=null):[];return!s&&a.length===0||A(s)&&a.length===0||z(s)&&a.length===0?null:a.length>0?{payload:k(s,a),titleText:s,repairHint:u}:{payload:s,titleText:s,repairHint:u}}function et(e){return e==="turn_completed"||e==="turn_complete"||e==="task_complete"}function nt(e){return/approval|permission|confirm|user[_-]?input|input[_-]?required/i.test(e)}function rt(e){const r=typeof e.command=="string"?e.command:Array.isArray(e.command)?e.command.join(" "):"",n=typeof e.prompt=="string"?e.prompt:typeof e.reason=="string"?e.reason:typeof e.message=="string"?e.message:r?`Codex \u8BF7\u6C42\u6267\u884C\u547D\u4EE4\uFF1A${r}`:"Codex \u6B63\u5728\u7B49\u5F85\u7528\u6237\u786E\u8BA4\u540E\u7EE7\u7EED\u3002";return V({title:"\u9700\u8981\u7528\u6237\u786E\u8BA4",content:n,source:"codex",actionHint:"\u5F53\u524D\u795E\u5FF5\u6682\u4E0D\u652F\u6301\u8FDC\u7A0B\u786E\u8BA4\uFF0C\u8BF7\u56DE\u5230\u8FD0\u884C Codex \u7684\u7535\u8111/\u7EC8\u7AEF\u5B8C\u6210\u786E\u8BA4\u3002"})}function $(e,r){return Array.isArray(e)?h(e.map(n=>{if(typeof n=="string")return n;if(typeof n!="object"||n===null)return"";const t=n;return t.type!==r?"":typeof t.text=="string"?t.text:""}).filter(Boolean).join(`
|
|
4
4
|
|
|
5
|
-
`)):""}function ot(e){if(!Array.isArray(e))return[];const r=[];for(const n of e){if(typeof n!="object"||n===null)continue;const t=n;if(t.type!=="input_image")continue;const o=typeof t.path=="string"?t.path:typeof t.file_path=="string"?t.file_path:typeof t.saved_path=="string"?t.saved_path:typeof t.image_path=="string"?t.image_path:"";o.trim()&&r.push({path:o,name:x.basename(o)||"image.png",mimeType:E(o),kind:"image"})}return r}function L(e){if(e.type!=="message")return null;const r=e.role==="assistant"?"agent":e.role==="user"?"user":null;if(!r)return null;if(r==="agent"){const s=$(e.content,"output_text");return A(s)?null:s?{role:r,payload:s,titleText:s}:null}const n=B($(e.content,"input_text")),t=n.text,o=ot(e.content);return!t&&o.length===0||A(t)&&o.length===0||z(t)&&o.length===0?null:{role:r,payload:o.length>0?k(t,o):t,titleText:t,repairHint:n.strippedWrapper?"codex_app_context_wrapper":void 0}}function J(e){if(!e)return"";try{const r=JSON.parse(e);if(typeof r=="object"&&r!==null){const n=r;if(n.type==="user"&&typeof n.content=="string")return h(n.content)}}catch{}return h(e)}function st(e,r,n,t){return e.agentType!=="codex"||e.role!==r||F(e.payload)||Math.abs(e.ts-t)>300*1e3?!1:J(e.payload)===J(n)}function W(e,r,n,t){for(let o=e.length-1;o>=0;o-=1){const s=e[o];if(s){if(st(s,r,n,t))return o;if(s.agentType==="codex"&&Math.abs(s.ts-t)>300*1e3)break}}return-1}function b(e,r,n,t,o,s,u,a,
|
|
6
|
-
(exit ${String(
|
|
5
|
+
`)):""}function ot(e){if(!Array.isArray(e))return[];const r=[];for(const n of e){if(typeof n!="object"||n===null)continue;const t=n;if(t.type!=="input_image")continue;const o=typeof t.path=="string"?t.path:typeof t.file_path=="string"?t.file_path:typeof t.saved_path=="string"?t.saved_path:typeof t.image_path=="string"?t.image_path:"";o.trim()&&r.push({path:o,name:x.basename(o)||"image.png",mimeType:E(o),kind:"image"})}return r}function L(e){if(e.type!=="message")return null;const r=e.role==="assistant"?"agent":e.role==="user"?"user":null;if(!r)return null;if(r==="agent"){const s=$(e.content,"output_text");return A(s)?null:s?{role:r,payload:s,titleText:s}:null}const n=B($(e.content,"input_text")),t=n.text,o=ot(e.content);return!t&&o.length===0||A(t)&&o.length===0||z(t)&&o.length===0?null:{role:r,payload:o.length>0?k(t,o):t,titleText:t,repairHint:n.strippedWrapper?"codex_app_context_wrapper":void 0}}function J(e){if(!e)return"";try{const r=JSON.parse(e);if(typeof r=="object"&&r!==null){const n=r;if(n.type==="user"&&typeof n.content=="string")return h(n.content)}}catch{}return h(e)}function st(e,r,n,t){return e.agentType!=="codex"||e.role!==r||F(e.payload)||Math.abs(e.ts-t)>300*1e3?!1:J(e.payload)===J(n)}function W(e,r,n,t){for(let o=e.length-1;o>=0;o-=1){const s=e[o];if(s){if(st(s,r,n,t))return o;if(s.agentType==="codex"&&Math.abs(s.ts-t)>300*1e3)break}}return-1}function b(e,r,n,t,o,s,u,a,f,c,i="agent",l=!1,m){u&&e.push({agentType:"codex",sourceMode:"codex_rollout_import",sourceSessionKey:o,sourceEventKey:w(r,n,t),cursor:I(r,n),role:i,ts:s,payload:u,title:a,modelId:f,workDir:c,terminal:l,repairHint:m})}function C(e,r,n,t,o,s,u,a,f,c,i,l){b(e,r,n,t,o,s,Y(u,i,l),a,f,c)}function it(e,r,n,t,o,s,u,a,f){const c=typeof t.type=="string"?t.type:"";if(c){if(c==="message"){const i=L(t);if(!i||W(e,i.role,i.payload,s)>=0)return;b(e,r,n,`${c}:${i.role}`,o,s,i.payload,u,a,f,i.role,!1,i.repairHint);return}if(c==="function_call"){const i=typeof t.name=="string"?t.name:"function_call";C(e,r,n,c,o,s,i,u,a,f,Z(t.arguments));return}if(c==="function_call_output"){C(e,r,n,c,o,s,"function_call_output",u,a,f,t.call_id,t.output);return}if(c==="custom_tool_call"){const i=typeof t.name=="string"?t.name:"custom_tool_call",l=t.input!==void 0?{input:t.input}:void 0;C(e,r,n,c,o,s,i,u,a,f,l);return}if(c==="custom_tool_call_output"){const i=typeof t.name=="string"?t.name:"custom_tool_call_output",l=t.output??t.result??t.content;C(e,r,n,c,o,s,i,u,a,f,t.call_id,l);return}if(c==="web_search_call"){const i=typeof t.action=="object"&&t.action!==null?t.action:null;C(e,r,n,c,o,s,"web_search",u,a,f,i??t.query);return}}}function ct(e,r,n,t,o,s,u,a,f){const c=typeof t.type=="string"?t.type:"";if(c){if(c==="user_message"){const i=H(t);if(!i)return;b(e,r,n,c,o,s,i.payload,u,a,f,"user",!1,i.repairHint);return}if(c==="agent_message"){const i=typeof t.message=="string"?h(t.message):"";if(!i||A(i))return;b(e,r,n,c,o,s,i,u,a,f);return}if(c==="turn_aborted"||c==="error"){const i=typeof t.message=="string"?h(t.message):typeof t.error=="string"?h(t.error):"";if(!i)return;b(e,r,n,c,o,s,i,u,a,f,"agent",!0);return}if(nt(c)){b(e,r,n,c,o,s,rt(t),u,a,f,"agent");return}if(c==="exec_command_end"){const i=Array.isArray(t.command)?t.command:t.parsed_cmd??t.command,l=t.exit_code??t.exitCode,m=[typeof t.aggregated_output=="string"?t.aggregated_output:"",l!=null?`
|
|
6
|
+
(exit ${String(l)})`:""].join("");C(e,r,n,c,o,s,"command_execution",u,a,f,{command:i},m);return}if(c==="patch_apply_end"){C(e,r,n,c,o,s,"apply_patch",u,a,f,t.changes,{success:t.success,stdout:t.stdout,stderr:t.stderr});return}if(c==="mcp_tool_call_end"){const i=typeof t.invocation=="object"&&t.invocation!==null?t.invocation:null,l=typeof i?.tool=="string"?i.tool:"mcp_tool_call",m={server:i?.server,...typeof i?.arguments=="object"&&i.arguments!==null?i.arguments:{}};C(e,r,n,c,o,s,l,u,a,f,m,t.result);return}if(c==="dynamic_tool_call_request"){const i=typeof t.tool=="string"?t.tool:"dynamic_tool_call";C(e,r,n,c,o,s,i,u,a,f,t.arguments);return}if(c==="dynamic_tool_call_response"){const i=typeof t.tool=="string"?t.tool:"dynamic_tool_call";C(e,r,n,c,o,s,i,u,a,f,t.callId??t.call_id,t.result??t.output);return}if(c==="web_search_end"){const i=typeof t.action=="object"&&t.action!==null?t.action:null;C(e,r,n,c,o,s,"web_search",u,a,f,i??t.query,t.query);return}if(c==="image_generation_end"){const i=typeof t.saved_path=="string"?t.saved_path.trim():"";if(!i)return;b(e,r,n,c,o,s,X(i),u,a,f);return}c==="view_image_tool_call"&&C(e,r,n,c,o,s,"view_image",u,a,f,t.path??t.image_path??t)}}function ut(e){const r=j.homedir();return e.startsWith(r)?e.slice(r.length).replace(/^\//,"")||"~":e.replace(/\//g,"-")}function at(e){const r=T.openSync(e,"r");try{const n=[];let t=0,o="";for(;t<1024*1024;){const f=Buffer.alloc(16384),c=T.readSync(r,f,0,f.length,t);if(c<=0)break;const i=f.subarray(0,c);n.push(i),t+=c;const l=Buffer.concat(n),m=l.indexOf(10);if(m>=0){o=l.subarray(0,m).toString("utf8");break}}!o&&n.length>0&&(o=Buffer.concat(n).toString("utf8"));const s=M(o);if(!s||s.type!=="session_meta")return{sourceSessionKey:"",workDir:"",modelId:null,title:""};const u=typeof s.payload=="object"&&s.payload!==null?s.payload:null;if(!u)return{sourceSessionKey:"",workDir:"",modelId:null,title:""};const a=typeof u.id=="string"?u.id:"";return{sourceSessionKey:a,workDir:typeof u.cwd=="string"?u.cwd:"",modelId:G(u),title:Q(a)??""}}finally{T.closeSync(r)}return{sourceSessionKey:"",workDir:"",modelId:null,title:""}}function G(e){return(typeof e.model=="string"?e.model.trim():"")||null}function ft(e,r){if((typeof e.id=="string"?e.id:typeof e.thread_id=="string"?e.thread_id:typeof e.session_id=="string"?e.session_id:"")!==r)return null;const o=(typeof e.thread_name=="string"?e.thread_name:typeof e.title=="string"?e.title:"").trim();return o?o.slice(0,120):null}function Q(e){if(!e)return null;const r=x.join(j.homedir(),".codex","session_index.jsonl");if(!T.existsSync(r))return null;let n=null;return v(r,0,t=>{if(!t.trim())return;const o=M(t);if(!o)return;const s=ft(o,e);s&&(n=s)}),n}function _t(){const e=[x.join(j.homedir(),".codex","sessions"),x.join(j.homedir(),".codex","archived_sessions")],r=[],n=t=>{for(const o of T.readdirSync(t,{withFileTypes:!0})){const s=x.join(t,o.name);o.isDirectory()?n(s):o.isFile()&&o.name.endsWith(".jsonl")&&r.push(s)}};for(const t of e)T.existsSync(t)&&n(t);return[...new Set(r)].sort()}function lt(){const e=x.join(j.homedir(),".claude","projects");if(!T.existsSync(e))return[];const r=[],n=t=>{for(const o of T.readdirSync(t,{withFileTypes:!0})){const s=x.join(t,o.name);if(o.isDirectory()){if(t===e&&K(o.name))continue;n(s)}else o.isFile()&&o.name.endsWith(".jsonl")&&r.push(s)}};return n(e),r.sort()}function yt(e){if(!e)return null;const r=lt().find(t=>x.basename(t,".jsonl")===e);if(!r)return null;let n=null;return v(r,0,t=>{if(n||!t.trim())return;const o=M(t);if(!o)return;const s=N(o);s&&(n=s)}),n}function ht(e,r){const n=[];let{sourceSessionKey:t,workDir:o,modelId:s,title:u}=at(e),a=!1;return{nextOffset:v(e,r,(c,i)=>{const l=M(c);if(!l)return;const m=typeof l.type=="string"?l.type:"",p=typeof l.payload=="object"&&l.payload!==null?l.payload:null,_=q(l.timestamp);if(!(!p||!_)){if(m==="session_meta"){t=typeof p.id=="string"?p.id:t,o=typeof p.cwd=="string"?p.cwd:o,s=G(p)??s,u||(u=Q(t)??"");return}if(t){if(m==="response_item"){const y=L(p);y?.role==="user"&&y.titleText&&!u&&(u=y.titleText.slice(0,80)),it(n,e,i,p,t,_,u,s,o);return}if(m==="event_msg"){const y=typeof p.type=="string"?p.type:"";if(et(y)){for(let d=n.length-1;d>=0;d-=1){const g=n[d];if(g?.agentType==="codex"&&g.role==="agent"&&!F(g.payload)){g.terminal=!0,a=!1;break}}return}if(y==="user_message"){const d=H(p);if(d?.titleText&&!u&&(u=d.titleText.slice(0,80)),d){const g=W(n,"user",d.payload,_);g>=0&&n.splice(g,1)}}else if(y==="agent_message"){const d=typeof p.message=="string"?h(p.message):"";if(d&&!A(d)){const g=W(n,"agent",d,_);g>=0&&n.splice(g,1)}}const S=n.length;ct(n,e,i,p,t,_,u,s,o),a&&n.length>S&&(n[n.length-1].terminal=!0,a=!1)}}}}),events:n}}function Ct(e,r){const n=T.statSync(e).size;if(D(e)||O(e))return{nextOffset:n,events:[]};const t=[],o=x.basename(e,".jsonl"),s=ut(x.dirname(e).replace(x.join(j.homedir(),".claude","projects")+x.sep,""));if(R(s))return{nextOffset:n,events:[]};let u="";return{nextOffset:v(e,r,(f,c)=>{const i=M(f);if(!i)return;const l=q(i.timestamp),m=typeof i.type=="string"?i.type:"";if(!l||!m)return;const p=N(i);if(!(p&&R(p))){if(m==="user"){const _=typeof i.message=="object"&&i.message!==null?i.message:null,y=typeof _?.content=="string"?h(_.content):"";if(!y)return;u||(u=y.slice(0,80)),t.push({agentType:"claude",sourceMode:"claude_transcript_import",sourceSessionKey:o,sourceEventKey:w(e,c,"user"),cursor:I(e,c),role:"user",ts:l,payload:y,title:u,workDir:p??s})}else if(m==="assistant"){const _=typeof i.message=="object"&&i.message!==null?i.message:null,y=Array.isArray(_?.content)?_.content:[],S=h(y.map(g=>typeof g=="object"&&g!==null&&typeof g.text=="string"?g.text:"").filter(Boolean).join(`
|
|
7
7
|
|
|
8
|
-
`));if(!S)return;const d=typeof _?.model=="string"?_.model:null;t.push({agentType:"claude",sourceMode:"claude_transcript_import",sourceSessionKey:o,sourceEventKey:w(e,c,"assistant"),cursor:I(e,c),role:"agent",ts:
|
|
8
|
+
`));if(!S)return;const d=typeof _?.model=="string"?_.model:null;t.push({agentType:"claude",sourceMode:"claude_transcript_import",sourceSessionKey:o,sourceEventKey:w(e,c,"assistant"),cursor:I(e,c),role:"agent",ts:l,payload:S,title:u,modelId:d,workDir:p??s})}}}),events:t}}export{lt as listClaudeTranscriptFiles,_t as listCodexRolloutFiles,jt as listOpenCodeSessionFiles,yt as lookupClaudeTranscriptCwd,Ct as parseClaudeTranscriptChunk,ht as parseCodexRolloutChunk,At as parseOpenCodeSessionFile,Mt as parseOpenCodeSessionSnapshot};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{isSystemControlPayload as R}from"@shennian/wire";import{readMessages as E}from"../store.js";const A=2e3,_=8e3,b=/(?:token|api[-_]?key|password|passwd|pwd|secret|authorization|cookie|credential|private[-_]?key)/i,T=/\b([A-Z0-9_]*(?:TOKEN|KEY|SECRET|PASSWORD|PASSWD|PWD|AUTH)[A-Z0-9_]*)=("[^"]*"|'[^']*'|[^\s]+)/gi,x=/\bBearer\s+[A-Za-z0-9._~+/=-]+/gi,D=/\bsk-[A-Za-z0-9_-]{12,}\b/g;function m(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function d(e){if(!e)return null;if(typeof e=="string")try{return d(JSON.parse(e))}catch{return null}const t=m(e);if(!t)return null;const s=typeof t.runId=="string"?t.runId:void 0,o=typeof t.sourceSeq=="number"?t.sourceSeq:typeof t.seq=="number"?t.seq:void 0,n=typeof t.toolIndex=="number"?t.toolIndex:void 0;return{...s?{runId:s}:{},...o!=null?{sourceSeq:o}:{},...n!=null?{toolIndex:n}:{}}}function p(e){return/^agent-(.+)-\d+$/.exec(e)?.[1]??null}function I(e){const t=/^agent-.+-(\d+)$/.exec(e);return t?Number(t[1]):null}function y(e){const t=typeof e=="number"?e:Number(e);return!Number.isFinite(t)||t<=0?A:Math.min(Math.max(200,Math.floor(t)),_)}function c(e,t){if(R(e))return"[SYSTEM CONTEXT REDACTED]";const s=e.replace(T,"$1=[REDACTED]").replace(x,"Bearer [REDACTED]").replace(D,"sk-[REDACTED]");return s.length>t?`${s.slice(0,t)}\u2026`:s}function u(e,t,s=0){if(e==null)return e;if(typeof e=="string")return c(e,t);if(typeof e=="number"||typeof e=="boolean")return e;if(s>=4)return"[Truncated]";if(Array.isArray(e))return e.slice(0,20).map(o=>u(o,t,s+1));if(typeof e=="object"){const o={};for(const[n,r]of Object.entries(e).slice(0,50)){if(b.test(n)){o[n]="[REDACTED]";continue}o[n]=u(r,t,s+1)}return o}return String(e)}function h(e,t){const o=m(e)?.command;if(typeof o=="string")return c(o,t);if(Array.isArray(o)){const n=o.map(r=>String(r)).join(" ");return c(n,t)}}function C(e){const t=E(e),s=[];for(const o of t)if(!(o.role!=="agent"||!o.payload.trim().startsWith("{")))try{const n=JSON.parse(o.payload),r=n.type;if(r!=="tool"&&r!=="tool_use"&&r!=="tool_result")continue;const a=typeof n.name=="string"&&n.name.trim()?n.name.trim():"tool";s.push({id:o.id,ts:o.ts,name:a,args:n.args,result:n.result,status:r==="tool_result"||Object.prototype.hasOwnProperty.call(n,"result")?"completed":n.status==="completed"||n.status==="failed"||n.status==="running"?n.status:"running",detailRef:d(n.detailRef)})}catch{}return s}function k(e,t,s){let o=0;e.id===t.messageId&&(o+=100),t.name&&e.name===t.name&&(o+=20);const n=s?.runId??t.runId??p(t.messageId),r=s?.sourceSeq??t.sourceSeq??I(t.messageId)??void 0;return n&&(e.detailRef?.runId??p(e.id))===n&&(o+=20),r!=null&&(e.detailRef?.sourceSeq??I(e.id))===r&&(o+=80),e.args!=null&&(o+=5),o}function q(e){const t=d(e.detailRef)??d({runId:e.runId,sourceSeq:e.sourceSeq,toolIndex:e.toolIndex}),s=C(e.sessionId);return s.length===0?null:s.map(n=>({candidate:n,score:k(n,e,t)})).filter(n=>n.score>0).sort((n,r)=>r.score-n.score||r.candidate.ts-n.candidate.ts)[0]?.candidate??null}async function O(e,t){const s=t.params,o=typeof s.sessionId=="string"?s.sessionId:"",n=typeof s.messageId=="string"?s.messageId:"";if(!o||!n){e.client.sendRes({type:"res",id:t.id,ok:!1,error:"sessionId and messageId are required"});return}const r={sessionId:o,messageId:n,...typeof s.name=="string"?{name:s.name}:{},...typeof s.toolIndex=="number"?{toolIndex:s.toolIndex}:{},...typeof s.runId=="string"?{runId:s.runId}:{},...typeof s.sourceSeq=="number"?{sourceSeq:s.sourceSeq}:{},...s.detailRef!==void 0?{detailRef:s.detailRef}:{},maxChars:y(s.maxChars)},a=y(r.maxChars),i=q(r);if(!i||i.args==null){const S={detailStatus:"not_found",messageId:n,toolIndex:r.toolIndex??0,name:r.name,resultOmitted:!0,source:"unavailable",reason:"tool detail is not available on this machine"};e.client.sendRes({type:"res",id:t.id,ok:!0,payload:S});return}const l=i.args==null?void 0:u(i.args,a),f=h(i.args,a),g={detailStatus:"available",messageId:n,toolIndex:r.toolIndex??0,name:i.name,status:i.status,...l!==void 0?{argsSummary:l}:{},...f?{command:f}:{},resultOmitted:!0,source:"local-session-store"};e.client.sendRes({type:"res",id:t.id,ok:!0,payload:g})}export{O as handleSessionToolDetail};
|