shennian 0.2.109 → 0.2.111
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 +35 -40
- package/dist/src/channels/runtime.d.ts +1 -0
- package/dist/src/channels/runtime.js +2 -2
- package/dist/src/channels/wechat-channel/automation-lane.d.ts +12 -0
- package/dist/src/channels/wechat-channel/automation-lane.js +2 -1
- package/dist/src/channels/wechat-channel/client.d.ts +16 -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/observer.d.ts +9 -1
- package/dist/src/channels/wechat-channel/observer.js +7 -6
- package/dist/src/channels/wechat-channel/outbound-ledger.js +2 -2
- package/dist/src/channels/wechat-channel/outbound-sender.d.ts +8 -0
- package/dist/src/channels/wechat-channel/outbound-sender.js +1 -1
- package/dist/src/channels/wechat-channel/runner.js +1 -1
- package/dist/src/channels/wechat-rpa.js +1 -1
- package/dist/src/commands/runtime.d.ts +1 -0
- package/dist/src/commands/runtime.js +1 -1
- package/dist/src/commands/wechat/command.d.ts +1 -0
- package/dist/src/commands/wechat/command.js +1 -1
- package/dist/src/commands/wechat.d.ts +1 -1
- package/dist/src/commands/wechat.js +1 -1
- package/dist/src/devtools/wechat-channel-action-smoke.d.ts +3 -1
- package/dist/src/devtools/wechat-channel-action-smoke.js +9 -9
- package/dist/src/index.js +2 -2
- package/dist/src/native-fusion/service.d.ts +0 -10
- package/dist/src/native-fusion/service.js +2 -2
- package/dist/src/session/handlers/chat.js +2 -2
- package/dist/src/session/handlers/session-refresh.js +1 -1
- package/dist/src/session/manager.d.ts +1 -1
- package/dist/src/session/manager.js +1 -1
- package/package.json +1 -1
- package/dist/src/agents/codex-control.d.ts +0 -35
- package/dist/src/agents/codex-control.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
import f from"node:fs";import I from"node:os";import o from"node:path";import v from"chalk";import{getDefaultWeChatHelperRuntimeRoot as y,readWeChatChannelHelperRuntimePackageManifest as S,resolveWeChatChannelHelperAsset as D,SHENNIAN_HELPER_RUNTIME_DIR_ENV as A,WECHAT_CHANNEL_HELPER_DIR_ENV as $}from"../channels/wechat-channel/helper-assets.js";import{downloadOfficialHelperRuntimePackage as O}from"./helper-runtime-official-download.js";import{compareVersions as U,getCurrentVersion as C}from"../upgrade/engine.js";const u="helper-runtime-package.json";function re(e){const r=e.command("runtime").description("Install, repair, and inspect Shennian local runtimes");r.command("status").description("Print local Shennian runtime status").option("--json","Output JSON",!1).option("--platform <platform>","Platform override: darwin or win32").action(i=>{const n=V({platform:i.platform});P(n,!!i.json),n.ok||(process.exitCode=1)}),r.command("install").description("Install a Shennian runtime component").argument("<component>","Runtime component, currently only: helper").option("--source <path>","Helper runtime package/source directory").option("--channel <channel>","Official Helper runtime channel: stable or next").option("--manifest-url <url>","Official Helper runtime manifest URL override").option("--no-official-download","Do not fall back to Shennian official Helper runtime download").option("--json","Output JSON",!1).option("--platform <platform>","Platform override: darwin or win32").action(async(i,n)=>{const a=i==="helper"?await H({source:n.source,platform:n.platform,officialDownload:n.officialDownload===!1?!1:{channel:n.channel,manifestUrl:n.manifestUrl}}):R(i);P(a,!!n.json),a.ok||(process.exitCode=1)}),r.command("repair").description("Repair a Shennian runtime component").argument("[component]","Runtime component, currently only: helper","helper").option("--source <path>","Helper runtime package/source directory").option("--channel <channel>","Official Helper runtime channel: stable or next").option("--manifest-url <url>","Official Helper runtime manifest URL override").option("--no-official-download","Do not fall back to Shennian official Helper runtime download").option("--json","Output JSON",!1).option("--platform <platform>","Platform override: darwin or win32").action(async(i,n)=>{const a=i==="helper"?await H({source:n.source,platform:n.platform,force:!0,officialDownload:n.officialDownload===!1?!1:{channel:n.channel,manifestUrl:n.manifestUrl}}):R(i);P(a,!!n.json),a.ok||(process.exitCode=1)})}function V(e={}){const r=w(e.platform);if(!r)return{ok:!1,installed:!1,repairable:!1,reasonCode:"unsupported_platform",message:"Shennian Helper runtime is only available on macOS and Windows.",repairSuggestion:l("unsupported_platform")};const i=e.env??process.env,n=e.homedir,a=D({platform:r,env:i,homedir:n,includeInstalledDesktop:!1}),t=y({platform:r,env:i,homedir:n});if(!a.ok)return{ok:!1,platform:r,targetPlatform:r,installed:!1,repairable:T(a.reasonCode),reasonCode:a.reasonCode,message:a.message,runtimeRoot:t,repairSuggestion:l(a.reasonCode),checkedSources:k({platform:r,env:i,homedir:n})};const s=S({platform:r,helperDir:a.helperDir});if(!s.ok)return{ok:!1,platform:r,targetPlatform:r,installed:!1,repairable:!0,reasonCode:s.reasonCode,message:s.message,helperDir:a.helperDir,helperPath:a.helperPath,helperVersion:a.version,runtimeVersion:a.version,protocolVersion:a.manifest.protocolVersion,runtimeRoot:t,repairSuggestion:l(s.reasonCode),checkedSources:k({platform:r,env:i,homedir:n})};const c=b({platform:r,packageManifest:s.manifest,currentCliVersion:C(),helperVersion:a.version,protocolVersion:a.manifest.protocolVersion});return c.ok?{ok:!0,platform:r,targetPlatform:r,installed:!0,repairable:!1,message:`Shennian Helper runtime is installed: ${a.helperDir}`,helperDir:a.helperDir,helperPath:a.helperPath,helperVersion:a.version,runtimeVersion:a.version,protocolVersion:a.manifest.protocolVersion,minCliVersion:s.manifest.minCliVersion,sha256:s.manifest.sha256,packageManifestPath:s.manifestPath,packageKind:s.manifest.packageKind,installTarget:s.manifest.installTarget,signature:s.manifest.signature,runtimeRoot:t}:{ok:!1,platform:r,targetPlatform:r,installed:!0,repairable:c.repairable,reasonCode:c.reasonCode,message:c.message,helperDir:a.helperDir,helperPath:a.helperPath,helperVersion:a.version,runtimeVersion:a.version,protocolVersion:a.manifest.protocolVersion,minCliVersion:s.manifest.minCliVersion,sha256:s.manifest.sha256,packageManifestPath:s.manifestPath,packageKind:s.manifest.packageKind,installTarget:s.manifest.installTarget,signature:s.manifest.signature,runtimeRoot:t,repairSuggestion:l(c.reasonCode,s.manifest.minCliVersion),checkedSources:k({platform:r,env:i,homedir:n})}}function j(e={}){const r=w(e.platform);if(!r)return{ok:!1,reasonCode:"unsupported_platform",message:"Shennian Helper runtime is only available on macOS and Windows.",repairable:!1,repairSuggestion:l("unsupported_platform")};const i=e.env??process.env,n=E(e.io),a=e.homedir??n.homedir(),t=V({platform:r,env:i,homedir:a});if(t.ok&&!e.force&&t.helperDir&&t.helperPath&&t.helperVersion&&t.protocolVersion)return{ok:!0,action:"already_installed",platform:r,targetPlatform:r,installed:!0,repairable:!1,targetDir:W(r,t.helperDir),helperDir:t.helperDir,helperPath:t.helperPath,helperVersion:t.helperVersion,runtimeVersion:t.helperVersion,protocolVersion:t.protocolVersion,minCliVersion:t.minCliVersion,sha256:t.sha256,packageManifestPath:t.packageManifestPath,packageKind:t.packageKind,installTarget:t.installTarget,signature:t.signature,message:`Shennian Helper runtime is already installed: ${t.helperDir}`};const s=e.source?[o.resolve(e.source)]:k({platform:r,env:i,homedir:a}),c=s.map(_=>L({candidate:_,platform:r,io:n})).find(_=>_!=null);if(!c)return{ok:!1,platform:r,targetPlatform:r,installed:!1,repairable:!0,reasonCode:"helper_runtime_source_missing",message:"No installable Shennian Helper runtime package was found. Open Shennian Desktop, pass --source, or download the official helper package.",repairSuggestion:l("helper_runtime_source_missing"),checkedSources:s};const h=S({platform:r,manifestPath:c.packageManifestPath});if(!h.ok)return{ok:!1,platform:r,targetPlatform:r,installed:!1,repairable:!0,reasonCode:h.reasonCode,message:h.message,repairSuggestion:l(h.reasonCode),checkedSources:s};const g=b({platform:r,packageManifest:h.manifest,currentCliVersion:C()});if(!g.ok)return{ok:!1,platform:r,targetPlatform:r,installed:!1,repairable:g.repairable,reasonCode:g.reasonCode,message:g.message,repairSuggestion:l(g.reasonCode,h.manifest.minCliVersion),checkedSources:s};const d=F({platform:r,env:i,homedir:a,packageKind:c.packageKind});if(!d)return{ok:!1,platform:r,targetPlatform:r,installed:!1,repairable:!1,reasonCode:"helper_runtime_target_unavailable",message:"Unable to determine Helper runtime install target for this platform.",repairSuggestion:l("helper_runtime_target_unavailable"),checkedSources:s};z({sourceDir:c.sourceDir,targetDir:d,io:n}),B({sourceManifestPath:c.packageManifestPath,targetManifestPath:c.packageManifestPathInTarget(d),io:n});const p=D({platform:r,baseDir:c.manifestDirInTarget(d),verifyIntegrity:!0});if(!p.ok)return{ok:!1,platform:r,targetPlatform:r,installed:!1,repairable:!0,reasonCode:p.reasonCode,message:`Installed Helper runtime could not be verified: ${p.message}`,repairSuggestion:l(p.reasonCode),checkedSources:s};G(r,p.helperPath,n);const m=S({platform:r,helperDir:p.helperDir});return m.ok?{ok:!0,action:"installed",platform:r,targetPlatform:r,installed:!0,repairable:!1,targetDir:d,helperDir:p.helperDir,helperPath:p.helperPath,helperVersion:p.version,runtimeVersion:p.version,protocolVersion:p.manifest.protocolVersion,minCliVersion:m.manifest.minCliVersion,sha256:m.manifest.sha256,packageManifestPath:m.manifestPath,packageKind:m.manifest.packageKind,installTarget:m.manifest.installTarget,signature:m.manifest.signature,message:`Installed Shennian Helper runtime to ${d}`}:{ok:!1,platform:r,targetPlatform:r,installed:!1,repairable:!0,reasonCode:m.reasonCode,message:`Installed Helper runtime package manifest could not be verified: ${m.message}`,repairSuggestion:l(m.reasonCode),checkedSources:s}}async function H(e={}){const r=j(e);if(r.ok||e.source||e.officialDownload===!1||!x(r.reasonCode))return r.ok?{...r,source:r.source??"local"}:r;const i=w(e.platform);if(!i)return r;const n=await O({...e.officialDownload,platform:i,env:e.env??process.env});if(!n.ok)return{ok:!1,platform:i,targetPlatform:i,installed:!1,repairable:!0,reasonCode:n.reasonCode,message:n.message,repairSuggestion:l(n.reasonCode),checkedSources:r.checkedSources,officialDownload:{manifestUrl:n.manifestUrl,artifactUrl:n.artifactUrl}};try{const a=j({...e,source:n.sourceDir,platform:i});return a.ok?{...a,source:"official-download",officialDownload:{channel:n.channel,manifestUrl:n.manifestUrl,artifactUrl:n.artifactUrl,artifactSha256:n.artifactSha256,artifactSizeBytes:n.artifactSizeBytes,arch:n.arch}}:{...a,reasonCode:a.reasonCode==="helper_runtime_source_missing"?"helper_runtime_artifact_invalid":a.reasonCode,message:a.reasonCode==="helper_runtime_source_missing"?"Official Helper runtime artifact did not contain an installable runtime package.":a.message,repairSuggestion:l(a.reasonCode==="helper_runtime_source_missing"?"helper_runtime_artifact_invalid":a.reasonCode),officialDownload:{manifestUrl:n.manifestUrl,artifactUrl:n.artifactUrl}}}finally{n.cleanup()}}function x(e){return e==="helper_runtime_source_missing"||e==="helper_runtime_package_manifest_missing"||e==="helper_runtime_package_manifest_invalid"}function w(e){const r=e??process.platform;return r==="darwin"||r==="win32"?r:null}function b(e){return e.packageManifest.platform!==e.platform?{ok:!1,reasonCode:"helper_runtime_platform_mismatch",message:`Helper runtime package platform ${e.packageManifest.platform} does not match ${e.platform}.`,repairable:!0}:e.helperVersion&&e.packageManifest.helperVersion!==e.helperVersion?{ok:!1,reasonCode:"helper_runtime_version_mismatch",message:`Helper runtime package version ${e.packageManifest.helperVersion} does not match installed helper ${e.helperVersion}.`,repairable:!0}:e.protocolVersion&&e.packageManifest.protocolVersion!==e.protocolVersion?{ok:!1,reasonCode:"helper_runtime_protocol_mismatch",message:`Helper runtime package protocol ${e.packageManifest.protocolVersion} does not match installed helper protocol ${e.protocolVersion}.`,repairable:!0}:U(e.currentCliVersion,e.packageManifest.minCliVersion)!=="none"?{ok:!1,reasonCode:"helper_runtime_cli_too_old",message:`Shennian CLI ${e.currentCliVersion} is older than required ${e.packageManifest.minCliVersion}.`,repairable:!1}:{ok:!0}}function T(e){return e!=="unsupported_platform"&&e!=="helper_runtime_cli_too_old"}function l(e,r){if(e==="unsupported_platform")return"Use Shennian Helper runtime on macOS or Windows.";if(e==="unsupported_runtime_component")return"Use `shennian runtime install helper` or `shennian runtime repair helper`.";if(e==="helper_runtime_cli_too_old")return`Upgrade Shennian CLI${r?` to ${r} or newer`:""}, then retry.`;if(e==="helper_runtime_target_unavailable")return"Set the current user home/LOCALAPPDATA correctly, then retry.";if(e==="helper_runtime_required")return"Open Shennian Desktop or use the \u4F7F\u7528\u5FAE\u4FE1 page to install Helper.";if(e==="helper_runtime_source_missing")return"Open Shennian Desktop, retry from the \u4F7F\u7528\u5FAE\u4FE1 page, or pass `--source <path>`.";if(e==="helper_runtime_manifest_unavailable")return"Check network access to Shennian official downloads, then retry from the \u4F7F\u7528\u5FAE\u4FE1 page.";if(e==="helper_runtime_artifact_unavailable")return"Upgrade Shennian CLI or wait for this platform Helper runtime to be published.";if(e==="helper_runtime_download_failed")return"Check network access to Shennian official downloads, then retry.";if(e==="helper_runtime_artifact_integrity_mismatch")return"Retry the official Helper runtime download; the downloaded package did not match the published hash.";if(e==="helper_runtime_artifact_invalid")return"Retry after Shennian republishes a valid Helper runtime package for this platform.";if(e==="helper_runtime_package_manifest_missing"||e==="helper_runtime_package_manifest_invalid")return"Reinstall or repair the official Shennian Helper runtime package.";if(e==="helper_runtime_platform_mismatch")return"Install the Helper runtime package for this platform.";if(e==="helper_runtime_version_mismatch"||e==="helper_runtime_protocol_mismatch")return"Run `shennian runtime repair helper` with the matching official Helper runtime package.";if(e==="manifest_missing"||e==="helper_missing"||e==="integrity_mismatch"||e==="helper_not_executable")return"Run `shennian runtime repair helper` or reinstall Shennian Desktop."}function R(e){return{ok:!1,repairable:!1,reasonCode:"unsupported_runtime_component",message:`Unsupported runtime component: ${e}. Supported component: helper.`,repairSuggestion:l("unsupported_runtime_component")}}function E(e){return{existsSync:e?.existsSync??f.existsSync,readFileSync:e?.readFileSync??f.readFileSync,mkdirSync:e?.mkdirSync??f.mkdirSync,rmSync:e?.rmSync??f.rmSync,cpSync:e?.cpSync??f.cpSync,renameSync:e?.renameSync??f.renameSync,chmodSync:e?.chmodSync??f.chmodSync,homedir:e?.homedir??I.homedir}}function L(e){const r=o.resolve(e.candidate);return e.io.existsSync(r)?e.platform==="darwin"?K(r,e.io):N(r,e.io):null}function K(e,r){const i=e.endsWith(".app")?e:o.join(e,"Shennian Helper.app");if(r.existsSync(o.join(i,"Contents","Resources","wechat-channel","macos","manifest.json")))return{sourceDir:i,packageKind:"macos-app",packageManifestPath:M(r,[o.join(i,"Contents","Resources","helper-runtime-package.json"),o.join(e,u)]),packageManifestPathInTarget:a=>o.join(a,"Contents","Resources",u),manifestDirInTarget:a=>o.join(a,"Contents","Resources","wechat-channel","macos")};const n=r.existsSync(o.join(e,"manifest.json"))?e:o.join(e,"wechat-channel","macos");return r.existsSync(o.join(n,"manifest.json"))?{sourceDir:n,packageKind:"asset-dir",packageManifestPath:o.join(n,"helper-runtime-package.json"),packageManifestPathInTarget:a=>o.join(a,u),manifestDirInTarget:a=>a}:null}function N(e,r){const i=o.basename(e).toLowerCase()==="shennian helper"?e:o.join(e,"Shennian Helper");if(r.existsSync(o.join(i,"resources","wechat-channel","windows","manifest.json")))return{sourceDir:i,packageKind:"windows-runtime",packageManifestPath:M(r,[o.join(i,"resources",u),o.join(e,u)]),packageManifestPathInTarget:a=>o.join(a,"resources",u),manifestDirInTarget:a=>o.join(a,"resources","wechat-channel","windows")};const n=r.existsSync(o.join(e,"manifest.json"))?e:o.join(e,"wechat-channel","windows");return r.existsSync(o.join(n,"manifest.json"))?{sourceDir:n,packageKind:"asset-dir",packageManifestPath:o.join(n,"helper-runtime-package.json"),packageManifestPathInTarget:a=>o.join(a,u),manifestDirInTarget:a=>a}:null}function F(e){const r=y(e);if(!r)return null;if(e.platform==="darwin")return e.packageKind==="macos-app"?o.join(r,"Shennian Helper.app"):o.join(r,"wechat-channel","macos");if(e.packageKind==="windows-runtime"){const i=e.env.LOCALAPPDATA||(e.homedir?o.join(e.homedir,"AppData","Local"):"");return i?o.join(i,"Programs","Shennian Helper"):null}return o.join(r,"wechat-channel","windows")}function W(e,r){const i=o.resolve(r);if(e==="darwin"){const a=`${o.sep}Contents${o.sep}Resources${o.sep}wechat-channel${o.sep}macos`;return i.endsWith(a)?i.slice(0,-a.length):i}const n=`${o.sep}resources${o.sep}wechat-channel${o.sep}windows`;return i.endsWith(n)?i.slice(0,-n.length):i}function z(e){const r=o.resolve(e.sourceDir),i=o.resolve(e.targetDir);if(r===i)return;const n=`${i}.tmp-${process.pid}-${Date.now()}`;e.io.rmSync(n,{recursive:!0,force:!0}),e.io.mkdirSync(o.dirname(i),{recursive:!0}),e.io.cpSync(r,n,{recursive:!0}),e.io.rmSync(i,{recursive:!0,force:!0}),e.io.renameSync(n,i)}function B(e){const r=o.resolve(e.sourceManifestPath),i=o.resolve(e.targetManifestPath);!e.io.existsSync(r)||r===i||(e.io.mkdirSync(o.dirname(i),{recursive:!0}),e.io.cpSync(r,i))}function M(e,r){return r.find(i=>e.existsSync(i))??r[0]}function G(e,r,i){if(e==="darwin")try{const n=f.statSync(r);(n.mode&73)===0&&i.chmodSync(r,n.mode|493)}catch{}}function k(e){const r=e.homedir||(e.platform==="win32"?e.env.USERPROFILE:e.env.HOME),i=[],n=a=>{if(!a)return;const t=o.resolve(a);i.includes(t)||i.push(t)};if(n(e.env.SHENNIAN_HELPER_PACKAGE_DIR),n(e.env[$]),n(e.env[A]),e.platform==="darwin")r&&(n(o.join(r,"Applications","Shennian.app","Contents","Resources")),n(o.join(r,"Applications","Shennian Helper.app"))),n(o.join("/Applications","Shennian.app","Contents","Resources")),n(o.join("/Applications","Shennian Helper.app"));else{const a=e.env.LOCALAPPDATA||(r?o.join(r,"AppData","Local"):""),t=e.env.ProgramFiles||e.env.PROGRAMFILES,s=e.env["ProgramFiles(x86)"]||e.env["PROGRAMFILES(X86)"];a&&(n(o.join(a,"Programs","Shennian","resources")),n(o.join(a,"Programs","Shennian Helper"))),t&&(n(o.join(t,"Shennian","resources")),n(o.join(t,"Shennian Helper"))),s&&(n(o.join(s,"Shennian","resources")),n(o.join(s,"Shennian Helper")))}return n(o.resolve(process.cwd(),"packages/helper-runtime/dist",e.platform==="darwin"?"macos":"windows")),n(o.resolve(process.cwd(),"packages/helper-runtime/wechat-channel",e.platform==="darwin"?"macos":"windows")),i}function P(e,r){if(r){console.log(JSON.stringify(e,null,2));return}if(e.ok){console.log(v.green(`\u2713 ${e.message}`)),"helperVersion"in e&&console.log(`version=${e.helperVersion} protocol=${e.protocolVersion}`),"helperPath"in e&&console.log(e.helperPath);return}console.error(v.red(`\u2717 ${e.reasonCode}`)),console.error(e.message)}export{V as getHelperRuntimeStatus,j as installHelperRuntime,H as installHelperRuntimeWithOfficialDownload,re as registerRuntimeCommand};
|
|
1
|
+
import f from"node:fs";import y from"node:os";import i from"node:path";import{spawnSync as A}from"node:child_process";import v from"chalk";import{getDefaultWeChatHelperRuntimeRoot as D,readWeChatChannelHelperRuntimePackageManifest as w,resolveWeChatChannelHelperAsset as C,SHENNIAN_HELPER_RUNTIME_DIR_ENV as E,WECHAT_CHANNEL_HELPER_DIR_ENV as O}from"../channels/wechat-channel/helper-assets.js";import{downloadOfficialHelperRuntimePackage as $}from"./helper-runtime-official-download.js";import{compareVersions as x,getCurrentVersion as H}from"../upgrade/engine.js";import{SerialWeChatAutomationLane as U}from"../channels/wechat-channel/automation-lane.js";const u="helper-runtime-package.json";function ce(e){const r=e.command("runtime").description("Install, repair, and inspect Shennian local runtimes");r.command("status").description("Print local Shennian runtime status").option("--json","Output JSON",!1).option("--platform <platform>","Platform override: darwin or win32").action(o=>{const n=V({platform:o.platform});P(n,!!o.json),n.ok||(process.exitCode=1)}),r.command("install").description("Install a Shennian runtime component").argument("<component>","Runtime component, currently only: helper").option("--source <path>","Helper runtime package/source directory").option("--channel <channel>","Official Helper runtime channel: stable or next").option("--manifest-url <url>","Official Helper runtime manifest URL override").option("--no-official-download","Do not fall back to Shennian official Helper runtime download").option("--json","Output JSON",!1).option("--platform <platform>","Platform override: darwin or win32").action(async(o,n)=>{const a=o==="helper"?await b({source:n.source,platform:n.platform,officialDownload:n.officialDownload===!1?!1:{channel:n.channel,manifestUrl:n.manifestUrl}}):M(o);P(a,!!n.json),a.ok||(process.exitCode=1)}),r.command("repair").description("Repair a Shennian runtime component").argument("[component]","Runtime component, currently only: helper","helper").option("--source <path>","Helper runtime package/source directory").option("--channel <channel>","Official Helper runtime channel: stable or next").option("--manifest-url <url>","Official Helper runtime manifest URL override").option("--no-official-download","Do not fall back to Shennian official Helper runtime download").option("--json","Output JSON",!1).option("--platform <platform>","Platform override: darwin or win32").action(async(o,n)=>{const a=o==="helper"?await b({source:n.source,platform:n.platform,force:!0,officialDownload:n.officialDownload===!1?!1:{channel:n.channel,manifestUrl:n.manifestUrl}}):M(o);P(a,!!n.json),a.ok||(process.exitCode=1)})}function V(e={}){const r=k(e.platform);if(!r)return{ok:!1,installed:!1,repairable:!1,reasonCode:"unsupported_platform",message:"Shennian Helper runtime is only available on macOS and Windows.",repairSuggestion:l("unsupported_platform")};const o=e.env??process.env,n=e.homedir,a=C({platform:r,env:o,homedir:n,includeInstalledDesktop:!1}),t=D({platform:r,env:o,homedir:n});if(!a.ok)return{ok:!1,platform:r,targetPlatform:r,installed:!1,repairable:K(a.reasonCode),reasonCode:a.reasonCode,message:a.message,runtimeRoot:t,repairSuggestion:l(a.reasonCode),checkedSources:_({platform:r,env:o,homedir:n})};const s=w({platform:r,helperDir:a.helperDir});if(!s.ok)return{ok:!1,platform:r,targetPlatform:r,installed:!1,repairable:!0,reasonCode:s.reasonCode,message:s.message,helperDir:a.helperDir,helperPath:a.helperPath,helperVersion:a.version,runtimeVersion:a.version,protocolVersion:a.manifest.protocolVersion,runtimeRoot:t,repairSuggestion:l(s.reasonCode),checkedSources:_({platform:r,env:o,homedir:n})};const c=R({platform:r,packageManifest:s.manifest,currentCliVersion:H(),helperVersion:a.version,protocolVersion:a.manifest.protocolVersion});return c.ok?{ok:!0,platform:r,targetPlatform:r,installed:!0,repairable:!1,message:`Shennian Helper runtime is installed: ${a.helperDir}`,helperDir:a.helperDir,helperPath:a.helperPath,helperVersion:a.version,runtimeVersion:a.version,protocolVersion:a.manifest.protocolVersion,minCliVersion:s.manifest.minCliVersion,sha256:s.manifest.sha256,packageManifestPath:s.manifestPath,packageKind:s.manifest.packageKind,installTarget:s.manifest.installTarget,signature:s.manifest.signature,runtimeRoot:t}:{ok:!1,platform:r,targetPlatform:r,installed:!0,repairable:c.repairable,reasonCode:c.reasonCode,message:c.message,helperDir:a.helperDir,helperPath:a.helperPath,helperVersion:a.version,runtimeVersion:a.version,protocolVersion:a.manifest.protocolVersion,minCliVersion:s.manifest.minCliVersion,sha256:s.manifest.sha256,packageManifestPath:s.manifestPath,packageKind:s.manifest.packageKind,installTarget:s.manifest.installTarget,signature:s.manifest.signature,runtimeRoot:t,repairSuggestion:l(c.reasonCode,s.manifest.minCliVersion),checkedSources:_({platform:r,env:o,homedir:n})}}function j(e={}){const r=k(e.platform);if(!r)return{ok:!1,reasonCode:"unsupported_platform",message:"Shennian Helper runtime is only available on macOS and Windows.",repairable:!1,repairSuggestion:l("unsupported_platform")};const o=e.env??process.env,n=F(e.io),a=e.homedir??n.homedir(),t=V({platform:r,env:o,homedir:a});if(t.ok&&!e.force&&t.helperDir&&t.helperPath&&t.helperVersion&&t.protocolVersion)return{ok:!0,action:"already_installed",platform:r,targetPlatform:r,installed:!0,repairable:!1,targetDir:q(r,t.helperDir),helperDir:t.helperDir,helperPath:t.helperPath,helperVersion:t.helperVersion,runtimeVersion:t.helperVersion,protocolVersion:t.protocolVersion,minCliVersion:t.minCliVersion,sha256:t.sha256,packageManifestPath:t.packageManifestPath,packageKind:t.packageKind,installTarget:t.installTarget,signature:t.signature,message:`Shennian Helper runtime is already installed: ${t.helperDir}`};const s=e.source?[i.resolve(e.source)]:_({platform:r,env:o,homedir:a}),c=s.map(S=>z({candidate:S,platform:r,io:n})).find(S=>S!=null);if(!c)return{ok:!1,platform:r,targetPlatform:r,installed:!1,repairable:!0,reasonCode:"helper_runtime_source_missing",message:"No installable Shennian Helper runtime package was found. Open Shennian Desktop, pass --source, or download the official helper package.",repairSuggestion:l("helper_runtime_source_missing"),checkedSources:s};const h=w({platform:r,manifestPath:c.packageManifestPath});if(!h.ok)return{ok:!1,platform:r,targetPlatform:r,installed:!1,repairable:!0,reasonCode:h.reasonCode,message:h.message,repairSuggestion:l(h.reasonCode),checkedSources:s};const g=R({platform:r,packageManifest:h.manifest,currentCliVersion:H()});if(!g.ok)return{ok:!1,platform:r,targetPlatform:r,installed:!1,repairable:g.repairable,reasonCode:g.reasonCode,message:g.message,repairSuggestion:l(g.reasonCode,h.manifest.minCliVersion),checkedSources:s};const d=J({platform:r,env:o,homedir:a,packageKind:c.packageKind});if(!d)return{ok:!1,platform:r,targetPlatform:r,installed:!1,repairable:!1,reasonCode:"helper_runtime_target_unavailable",message:"Unable to determine Helper runtime install target for this platform.",repairSuggestion:l("helper_runtime_target_unavailable"),checkedSources:s};X({platform:r,sourceDir:c.sourceDir,targetDir:d,io:n}),Y({sourceManifestPath:c.packageManifestPath,targetManifestPath:c.packageManifestPathInTarget(d),io:n});const m=C({platform:r,baseDir:c.manifestDirInTarget(d),verifyIntegrity:!0});if(!m.ok)return{ok:!1,platform:r,targetPlatform:r,installed:!1,repairable:!0,reasonCode:m.reasonCode,message:`Installed Helper runtime could not be verified: ${m.message}`,repairSuggestion:l(m.reasonCode),checkedSources:s};Z(r,m.helperPath,n);const p=w({platform:r,helperDir:m.helperDir});return p.ok?{ok:!0,action:"installed",platform:r,targetPlatform:r,installed:!0,repairable:!1,targetDir:d,helperDir:m.helperDir,helperPath:m.helperPath,helperVersion:m.version,runtimeVersion:m.version,protocolVersion:m.manifest.protocolVersion,minCliVersion:p.manifest.minCliVersion,sha256:p.manifest.sha256,packageManifestPath:p.manifestPath,packageKind:p.manifest.packageKind,installTarget:p.manifest.installTarget,signature:p.manifest.signature,message:`Installed Shennian Helper runtime to ${d}`}:{ok:!1,platform:r,targetPlatform:r,installed:!1,repairable:!0,reasonCode:p.reasonCode,message:`Installed Helper runtime package manifest could not be verified: ${p.message}`,repairSuggestion:l(p.reasonCode),checkedSources:s}}async function b(e={}){const r=new U({lockPath:T(e),owner:"helper-runtime-install"});try{return await r.run("helper-runtime-install",()=>N(e))}catch(o){if(L(o)){const n=k(e.platform)??void 0;return{ok:!1,platform:n,targetPlatform:n,installed:!1,repairable:!0,reasonCode:"wechat_automation_busy",message:o instanceof Error?o.message:String(o),repairSuggestion:"Wait for the current WeChat automation run to finish, then retry Helper install or repair."}}throw o}}function T(e){const r=e.env?.SHENNIAN_HOME?.trim()||process.env.SHENNIAN_HOME?.trim(),o=r?i.resolve(r):i.join(e.homedir??y.homedir(),".shennian");return i.join(o,"runtime","wechat-automation.lock")}function L(e){return e instanceof Error?e.message.includes("wechat_automation_busy"):String(e).includes("wechat_automation_busy")}async function N(e={}){const r=j(e);if(r.ok||e.source||e.officialDownload===!1||!W(r.reasonCode))return r.ok?{...r,source:r.source??"local"}:r;const o=k(e.platform);if(!o)return r;const n=await $({...e.officialDownload,platform:o,env:e.env??process.env});if(!n.ok)return{ok:!1,platform:o,targetPlatform:o,installed:!1,repairable:!0,reasonCode:n.reasonCode,message:n.message,repairSuggestion:l(n.reasonCode),checkedSources:r.checkedSources,officialDownload:{manifestUrl:n.manifestUrl,artifactUrl:n.artifactUrl}};try{const a=j({...e,source:n.sourceDir,platform:o});return a.ok?{...a,source:"official-download",officialDownload:{channel:n.channel,manifestUrl:n.manifestUrl,artifactUrl:n.artifactUrl,artifactSha256:n.artifactSha256,artifactSizeBytes:n.artifactSizeBytes,arch:n.arch}}:{...a,reasonCode:a.reasonCode==="helper_runtime_source_missing"?"helper_runtime_artifact_invalid":a.reasonCode,message:a.reasonCode==="helper_runtime_source_missing"?"Official Helper runtime artifact did not contain an installable runtime package.":a.message,repairSuggestion:l(a.reasonCode==="helper_runtime_source_missing"?"helper_runtime_artifact_invalid":a.reasonCode),officialDownload:{manifestUrl:n.manifestUrl,artifactUrl:n.artifactUrl}}}finally{n.cleanup()}}function W(e){return e==="helper_runtime_source_missing"||e==="helper_runtime_package_manifest_missing"||e==="helper_runtime_package_manifest_invalid"}function k(e){const r=e??process.platform;return r==="darwin"||r==="win32"?r:null}function R(e){return e.packageManifest.platform!==e.platform?{ok:!1,reasonCode:"helper_runtime_platform_mismatch",message:`Helper runtime package platform ${e.packageManifest.platform} does not match ${e.platform}.`,repairable:!0}:e.helperVersion&&e.packageManifest.helperVersion!==e.helperVersion?{ok:!1,reasonCode:"helper_runtime_version_mismatch",message:`Helper runtime package version ${e.packageManifest.helperVersion} does not match installed helper ${e.helperVersion}.`,repairable:!0}:e.protocolVersion&&e.packageManifest.protocolVersion!==e.protocolVersion?{ok:!1,reasonCode:"helper_runtime_protocol_mismatch",message:`Helper runtime package protocol ${e.packageManifest.protocolVersion} does not match installed helper protocol ${e.protocolVersion}.`,repairable:!0}:x(e.currentCliVersion,e.packageManifest.minCliVersion)!=="none"?{ok:!1,reasonCode:"helper_runtime_cli_too_old",message:`Shennian CLI ${e.currentCliVersion} is older than required ${e.packageManifest.minCliVersion}.`,repairable:!1}:{ok:!0}}function K(e){return e!=="unsupported_platform"&&e!=="helper_runtime_cli_too_old"}function l(e,r){if(e==="unsupported_platform")return"Use Shennian Helper runtime on macOS or Windows.";if(e==="unsupported_runtime_component")return"Use `shennian runtime install helper` or `shennian runtime repair helper`.";if(e==="helper_runtime_cli_too_old")return`Upgrade Shennian CLI${r?` to ${r} or newer`:""}, then retry.`;if(e==="helper_runtime_target_unavailable")return"Set the current user home/LOCALAPPDATA correctly, then retry.";if(e==="helper_runtime_required")return"Open Shennian Desktop or use the \u4F7F\u7528\u5FAE\u4FE1 page to install Helper.";if(e==="helper_runtime_source_missing")return"Open Shennian Desktop, retry from the \u4F7F\u7528\u5FAE\u4FE1 page, or pass `--source <path>`.";if(e==="helper_runtime_manifest_unavailable")return"Check network access to Shennian official downloads, then retry from the \u4F7F\u7528\u5FAE\u4FE1 page.";if(e==="helper_runtime_artifact_unavailable")return"Upgrade Shennian CLI or wait for this platform Helper runtime to be published.";if(e==="helper_runtime_download_failed")return"Check network access to Shennian official downloads, then retry.";if(e==="helper_runtime_artifact_integrity_mismatch")return"Retry the official Helper runtime download; the downloaded package did not match the published hash.";if(e==="helper_runtime_artifact_invalid")return"Retry after Shennian republishes a valid Helper runtime package for this platform.";if(e==="helper_runtime_package_manifest_missing"||e==="helper_runtime_package_manifest_invalid")return"Reinstall or repair the official Shennian Helper runtime package.";if(e==="helper_runtime_platform_mismatch")return"Install the Helper runtime package for this platform.";if(e==="helper_runtime_version_mismatch"||e==="helper_runtime_protocol_mismatch")return"Run `shennian runtime repair helper` with the matching official Helper runtime package.";if(e==="manifest_missing"||e==="helper_missing"||e==="integrity_mismatch"||e==="helper_not_executable")return"Run `shennian runtime repair helper` or reinstall Shennian Desktop."}function M(e){return{ok:!1,repairable:!1,reasonCode:"unsupported_runtime_component",message:`Unsupported runtime component: ${e}. Supported component: helper.`,repairSuggestion:l("unsupported_runtime_component")}}function F(e){return{existsSync:e?.existsSync??f.existsSync,readFileSync:e?.readFileSync??f.readFileSync,mkdirSync:e?.mkdirSync??f.mkdirSync,rmSync:e?.rmSync??f.rmSync,cpSync:e?.cpSync??f.cpSync,renameSync:e?.renameSync??f.renameSync,chmodSync:e?.chmodSync??f.chmodSync,homedir:e?.homedir??y.homedir,stopWindowsHelperProcesses:e?.stopWindowsHelperProcesses??Q}}function z(e){const r=i.resolve(e.candidate);return e.io.existsSync(r)?e.platform==="darwin"?B(r,e.io):G(r,e.io):null}function B(e,r){const o=e.endsWith(".app")?e:i.join(e,"Shennian Helper.app");if(r.existsSync(i.join(o,"Contents","Resources","wechat-channel","macos","manifest.json")))return{sourceDir:o,packageKind:"macos-app",packageManifestPath:I(r,[i.join(o,"Contents","Resources","helper-runtime-package.json"),i.join(e,u)]),packageManifestPathInTarget:a=>i.join(a,"Contents","Resources",u),manifestDirInTarget:a=>i.join(a,"Contents","Resources","wechat-channel","macos")};const n=r.existsSync(i.join(e,"manifest.json"))?e:i.join(e,"wechat-channel","macos");return r.existsSync(i.join(n,"manifest.json"))?{sourceDir:n,packageKind:"asset-dir",packageManifestPath:i.join(n,"helper-runtime-package.json"),packageManifestPathInTarget:a=>i.join(a,u),manifestDirInTarget:a=>a}:null}function G(e,r){const o=i.basename(e).toLowerCase()==="shennian helper"?e:i.join(e,"Shennian Helper");if(r.existsSync(i.join(o,"resources","wechat-channel","windows","manifest.json")))return{sourceDir:o,packageKind:"windows-runtime",packageManifestPath:I(r,[i.join(o,"resources",u),i.join(e,u)]),packageManifestPathInTarget:a=>i.join(a,"resources",u),manifestDirInTarget:a=>i.join(a,"resources","wechat-channel","windows")};const n=r.existsSync(i.join(e,"manifest.json"))?e:i.join(e,"wechat-channel","windows");return r.existsSync(i.join(n,"manifest.json"))?{sourceDir:n,packageKind:"asset-dir",packageManifestPath:i.join(n,"helper-runtime-package.json"),packageManifestPathInTarget:a=>i.join(a,u),manifestDirInTarget:a=>a}:null}function J(e){const r=D(e);if(!r)return null;if(e.platform==="darwin")return e.packageKind==="macos-app"?i.join(r,"Shennian Helper.app"):i.join(r,"wechat-channel","macos");if(e.packageKind==="windows-runtime"){const o=e.env.LOCALAPPDATA||(e.homedir?i.join(e.homedir,"AppData","Local"):"");return o?i.join(o,"Programs","Shennian Helper"):null}return i.join(r,"wechat-channel","windows")}function q(e,r){const o=i.resolve(r);if(e==="darwin"){const a=`${i.sep}Contents${i.sep}Resources${i.sep}wechat-channel${i.sep}macos`;return o.endsWith(a)?o.slice(0,-a.length):o}const n=`${i.sep}resources${i.sep}wechat-channel${i.sep}windows`;return o.endsWith(n)?o.slice(0,-n.length):o}function X(e){const r=i.resolve(e.sourceDir),o=i.resolve(e.targetDir);if(r===o)return;const n=`${o}.tmp-${process.pid}-${Date.now()}`;e.io.rmSync(n,{recursive:!0,force:!0}),e.io.mkdirSync(i.dirname(o),{recursive:!0}),e.io.cpSync(r,n,{recursive:!0}),e.platform==="win32"&&e.io.stopWindowsHelperProcesses(),e.io.rmSync(o,{recursive:!0,force:!0}),e.io.renameSync(n,o)}function Q(){if(process.platform!=="win32")return;const e=A("taskkill",["/IM","shennian-wechat-channel-helper.exe","/T","/F"],{stdio:"ignore",windowsHide:!0});if(e.status!==0&&e.status!==128)throw new Error(`taskkill shennian-wechat-channel-helper.exe exited ${e.status}`)}function Y(e){const r=i.resolve(e.sourceManifestPath),o=i.resolve(e.targetManifestPath);!e.io.existsSync(r)||r===o||(e.io.mkdirSync(i.dirname(o),{recursive:!0}),e.io.cpSync(r,o))}function I(e,r){return r.find(o=>e.existsSync(o))??r[0]}function Z(e,r,o){if(e==="darwin")try{const n=f.statSync(r);(n.mode&73)===0&&o.chmodSync(r,n.mode|493)}catch{}}function _(e){const r=e.homedir||(e.platform==="win32"?e.env.USERPROFILE:e.env.HOME),o=[],n=a=>{if(!a)return;const t=i.resolve(a);o.includes(t)||o.push(t)};if(n(e.env.SHENNIAN_HELPER_PACKAGE_DIR),n(e.env[O]),n(e.env[E]),e.platform==="darwin")r&&(n(i.join(r,"Applications","Shennian.app","Contents","Resources")),n(i.join(r,"Applications","Shennian Helper.app"))),n(i.join("/Applications","Shennian.app","Contents","Resources")),n(i.join("/Applications","Shennian Helper.app"));else{const a=e.env.LOCALAPPDATA||(r?i.join(r,"AppData","Local"):""),t=e.env.ProgramFiles||e.env.PROGRAMFILES,s=e.env["ProgramFiles(x86)"]||e.env["PROGRAMFILES(X86)"];a&&(n(i.join(a,"Programs","Shennian","resources")),n(i.join(a,"Programs","Shennian Helper"))),t&&(n(i.join(t,"Shennian","resources")),n(i.join(t,"Shennian Helper"))),s&&(n(i.join(s,"Shennian","resources")),n(i.join(s,"Shennian Helper")))}return n(i.resolve(process.cwd(),"packages/helper-runtime/dist",e.platform==="darwin"?"macos":"windows")),n(i.resolve(process.cwd(),"packages/helper-runtime/wechat-channel",e.platform==="darwin"?"macos":"windows")),o}function P(e,r){if(r){console.log(JSON.stringify(e,null,2));return}if(e.ok){console.log(v.green(`\u2713 ${e.message}`)),"helperVersion"in e&&console.log(`version=${e.helperVersion} protocol=${e.protocolVersion}`),"helperPath"in e&&console.log(e.helperPath);return}console.error(v.red(`\u2717 ${e.reasonCode}`)),console.error(e.message)}export{V as getHelperRuntimeStatus,j as installHelperRuntime,b as installHelperRuntimeWithOfficialDownload,ce as registerRuntimeCommand};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readExternalAttachment as
|
|
1
|
+
import{readExternalAttachment as w}from"../external-attachments.js";import{runWeChatDoctor as g}from"./doctor.js";import{runWeChatReadLatest as C,runWeChatSend as k}from"./operations.js";import{printReadLatestResult as v,printToolError as m,printToolResult as y}from"./output.js";import{clampPositiveInteger as u}from"./utils.js";const c=5*6e4,j=10*6e4;function _(e){const o=e.command("wechat").description("Use WeChat through Shennian local runtime");o.option("--conversation <name>","WeChat conversation/group name"),o.command("doctor").description("Check local Shennian, pairing, entitlement, credits, and WeChat runtime readiness").option("--json","Output JSON",!1).action(async r=>{const t=await g();if(r.json)console.log(JSON.stringify(t,null,2));else for(const a of t.checks){const n=a.ok?"\u2713":a.status==="warning"?"!":"\u2717";console.log(`${n} ${a.id}: ${a.message}`)}t.ok||(process.exitCode=1)}),o.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. Default: ${c}`).option("--transport <mode>","Execution transport: auto, daemon, or direct","auto").option("--format <format>","Output format: json or text","text").option("--json","Output JSON",!1).action(async(r,t,a)=>{let n;try{n=l(a,t.conversation);const i=t.text??r.join(" "),s=x(t),f=await k({conversation:n,text:i,attachment:s,sessionId:t.sessionId,workDir:t.workDir,idempotencyKey:t.idempotencyKey,dryRun:t.dryRun,traceId:t.traceId,timeoutMs:p(t.timeout),transport:h(t.transport)});y(f,t.json||t.format==="json")}catch(i){m("write",n||t.conversation,i,t.json||t.format==="json")}}),o.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. Default: ${c}`).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("--transport <mode>","Execution transport: auto, daemon, or direct","auto").option("--json","Output JSON",!1).action(async(r,t,a)=>{let n,i="markdown";try{n=l(a,t.conversation),i=S(t.json?"json":t.format);const s=await C({conversation:n,limit:u(t.limit??r,10),download:W(t.download),traceId:t.traceId,timeoutMs:p(t.timeout),sessionId:t.sessionId,workDir:t.workDir,transport:h(t.transport)});v(s,i)}catch(s){m("read",n||t.conversation,s,t.json||i==="json")}})}function l(e,o){const d=e.parent?.opts()??{},r=o||d.conversation||"";if(!r.trim())throw new Error("--conversation is required");return r}function x(e){const o=[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(d=>!!d);if(o.length>1)throw new Error("Pass only one of --file, --image, or --video");if(o.length!==0)return w(o[0].path,o[0].kind)}function S(e){const o=String(e||"markdown").trim().toLowerCase();if(o==="json")return"json";if(o==="markdown"||o==="md"||o==="text")return"markdown";throw new Error(`Unsupported --format: ${e}. Use markdown or json.`)}function W(e){const o=String(e||"auto").trim().toLowerCase();if(o==="auto"||o==="never")return o;throw new Error(`Unsupported --download: ${e}. Use auto or never.`)}function h(e){const o=String(e||"auto").trim().toLowerCase();if(o==="auto"||o==="daemon"||o==="direct")return o;throw new Error(`Unsupported --transport: ${e}. Use auto, daemon, or direct.`)}function p(e){return e?u(e,j):c}export{_ as registerWeChatCommand,p as resolveWeChatCommandTimeout};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{registerWeChatCommand as e}from"./wechat/command.js";export*from"./wechat/direct.js";export*from"./wechat/doctor.js";export*from"./wechat/operations.js";export*from"./wechat/output.js";export*from"./wechat/types.js";export{e as registerWeChatCommand};
|
|
1
|
+
import{registerWeChatCommand as e,resolveWeChatCommandTimeout as m}from"./wechat/command.js";export*from"./wechat/direct.js";export*from"./wechat/doctor.js";export*from"./wechat/operations.js";export*from"./wechat/output.js";export*from"./wechat/types.js";export{e as registerWeChatCommand,m as resolveWeChatCommandTimeout};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { buildBottomPageReport, buildDownloadVisibleMediaReport } from './wechat-channel-download-report.js';
|
|
2
|
-
import { type WeChatChannelObserveActivityGuardOptions } from '../channels/wechat-channel/observer.js';
|
|
2
|
+
import { type WeChatChannelObserveActivityGuardOptions, type WeChatChannelOcrBlock } from '../channels/wechat-channel/observer.js';
|
|
3
3
|
import { type WeChatChannelRuntimePlatform } from '../channels/wechat-channel/runtime.js';
|
|
4
4
|
export type WeChatChannelActionSmokeStep = 'open-read' | 'send-text' | 'send-file' | 'send-image' | 'send-video' | 'structure-window' | 'server-observe' | 'read-bottom-page' | 'download-visible-media' | 'send-and-confirm' | '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';
|
|
5
5
|
export type WeChatChannelActionSmokeOptions = {
|
|
@@ -57,6 +57,7 @@ export declare function runWeChatChannelActionSmoke(options: WeChatChannelAction
|
|
|
57
57
|
export declare function buildSendStepAcceptance(input: {
|
|
58
58
|
sendAccepted: boolean;
|
|
59
59
|
text?: string | null;
|
|
60
|
+
attachmentPath?: string | null;
|
|
60
61
|
beforeTextCount?: number | null;
|
|
61
62
|
afterTextCount?: number | null;
|
|
62
63
|
}): {
|
|
@@ -100,3 +101,4 @@ export declare function buildSendAndConfirmEvidence(input: WeChatChannelSendAndC
|
|
|
100
101
|
export declare function countMarkerOccurrencesInOcrBlocks(blocks: Array<{
|
|
101
102
|
text?: string | null;
|
|
102
103
|
}>, marker: string): number;
|
|
104
|
+
export declare function countMarkerOccurrencesInChatContentBlocks(blocks: Array<WeChatChannelOcrBlock>, marker: string): number;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import _ from"node:crypto";import{spawnSync as ae}from"node:child_process";import w from"node:fs";import i from"node:path";import{fileURLToPath as ie}from"node:url";import{buildBottomPageReport as D,buildDownloadVisibleMediaReport as q}from"./wechat-channel-download-report.js";import{buildWeChatMessagesMarkdown as y}from"./wechat-channel-markdown-report.js";import{loadConfig as de}from"../config/index.js";import{createWeChatChannelApiClient as ce}from"../channels/wechat-channel/client.js";import{resolveWeChatChannelHelperAsset as ue,WECHAT_CHANNEL_HELPER_VERSION as le}from"../channels/wechat-channel/helper-assets.js";import{WeChatChannelHelperClient as me}from"../channels/wechat-channel/helper-client.js";import{requiredWindowsWeChatChannelHelperCapabilitiesForProfile as T}from"../channels/wechat-channel/helper-protocol.js";import{classifyWeChatOutboundEchoes as he,enqueueWeChatOutboundReply as K}from"../channels/wechat-channel/outbound-ledger.js";import{loadWeChatChannelLedger as fe,saveWeChatChannelLedger as ge,updateWeChatChannelBindingLedger as pe}from"../channels/wechat-channel/ledger.js";import{waitForWeChatChannelPacing as U}from"../channels/wechat-channel/pacing.js";import{WeChatChannelOutboundSender as G,sendQueuedWeChatOutboundRecords as S}from"../channels/wechat-channel/outbound-sender.js";import{captureWeChatWindow as j,ensureWeChatWindowReady as C,fallbackWeChatMessageInputPointForWindow as we,focusKnownWeChatWindow as k,observeWeChatChannelBindingViaHelper as be,openConversationBySearch as I,recognizeWeChatScreenshot as E}from"../channels/wechat-channel/observer.js";import{createWeChatChannelRuntime as ve}from"../channels/wechat-channel/runtime.js";function ye(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 Se="ABC",Ce="wechat-channel-action-smoke";function ke(e){const t=e.filter(u=>u!=="--"),n=ct(t),o=lt(t,"--step").map(ut).filter(u=>u!=null),r=de(),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?mt(o):Ie(n);return{conversation:g(t,"--conversation")||g(t,"--group")||Se,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")||Ce,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:at(g(t,"--platform")),text:g(t,"--text"),filePath:B(g(t,"--file")),imagePath:B(g(t,"--image")),videoPath:B(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 Ie(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 xe(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=et(e),s=r.bindings[0],a=tt(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 u of e.steps){if(Ae(u)&&d.steps.some(c=>c.step==="open-read"&&!c.ok&&!c.skipped)){d.steps.push({step:u,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 _e({step:u,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(u=>u.ok||u.skipped),m(i.join(e.outDir,"summary.json"),d)}return d}function Ae(e){return e==="send-text"||e==="send-file"||e==="send-image"||e==="send-video"||e==="send-and-confirm"}async function _e(e){try{return e.step==="open-read"?await Te(e):e.step==="structure-window"?await Ke(e):e.step==="server-observe"?await qe(e):e.step==="read-bottom-page"?await Le(e):e.step==="download-visible-media"?await He(e):e.step==="send-and-confirm"?await Fe(e):e.step.startsWith("human-")?await Me(e):await z(e)}catch(t){const n=bt(t),o=await De(e,n,t);return{step:e.step,ok:!1,reasonCode:n,errorSummary:t instanceof Error?t.message:String(t),userAction:vt(n),...o?{details:o}:{}}}}async function De(e,t,n){if(!Re(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 m(o,r),{failureDiagnosticsPath:o}}function Re(e){return e.startsWith("wechat_")||e.startsWith("permission_")||e.startsWith("user_active")}async function Me(e){if(e.step==="human-observe-deferred")return await Pe(e);const t=e.step,n=`human-${A(`${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=Q(e.helper,Z(t)),a=s.actionLog,d=async H=>{a.push(`openConversation:${H}`);const re=await C(s,e.options.traceId),se=await k(s,re,e.options.traceId);return I({helper:s,window:se,settleToBottom:!1,binding:{...e.binding,conversationDisplayName:H},traceId:e.options.traceId})},u=new G({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 f=await S({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"&&(f=await S({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(Ve()),f=await S({ledger:o,bindingId:e.binding.bindingId,currentLastInboundRevision:0,sender:u,now:new Date("2026-06-15T00:00:06.000Z")}));const h=Je(e.step,r)?await O({helper:s,binding:e.binding,marker:n,traceId:e.options.traceId,outDir:e.options.outDir,filePrefix:e.step}):0,p=h>0?he({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:[]},l=o.records[0],b=Xe(l,f,p.confirmedRecords),v={case:e.step,marker:n,runStatus:b,reasonCode:l.deferReason||l.failureCode||null,outboundStatus:l.sendStatus,attemptCount:l.attemptCount??0,nextAttemptAt:l.nextAttemptAt??null,observedMarkerCount:h,actionLog:a,clipboardRestore:a.includes("clipboard.restore")?"attempted":"not_needed",commitStage:l.commitStage??null};return m(i.join(e.options.outDir,`${e.step}-summary.json`),v),{step:e.step,ok:Ye(e.step,v),reasonCode:v.reasonCode||void 0,details:v}}async function Pe(e){const t=Q(e.helper,Z("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 m(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 Te(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 je({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 j(e.helper,n.windowId,e.options.traceId),s=P(e.options.outDir,"open-read-full-window",r),a=await E(e.helper,r,e.options.traceId);return m(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 je(e){try{const t=await j(e.helper,e.window.windowId,e.traceId,e.window.bounds),n=P(e.outDir,"open-read-failure-window",t),o=await E(e.helper,t,e.traceId);m(i.join(e.outDir,"open-read-failure-ocr.json"),o),m(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){m(i.join(e.outDir,"open-read-failure-summary.json"),{reason:e.reason,captureError:t instanceof Error?t.message:String(t)})}}async function z(e){return await Ee(e,it(e.step,e.options))}async function Ee(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 O({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}:${A(o)}`,idempotencyKey:`action-smoke:${A(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 G({helper:e.helper,platform:e.runtime.policy.platform,traceId:e.options.traceId,openConversation:async p=>{const l=await C(e.helper,e.options.traceId),b=await k(e.helper,l,e.options.traceId);return{...await I({helper:e.helper,window:b,settleToBottom:!1,binding:{...e.binding,conversationDisplayName:p},traceId:e.options.traceId}),inputPoint:we(b)}}}),a=await $e({ledger:n,bindingId:e.binding.bindingId,sender:s});await U("send-after-submit",`${e.options.traceId}:${e.step}:after-submit`);const d=n.records[0],u=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,f=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,h=We({sendAccepted:c,text:t.text,beforeTextCount:r,afterTextCount:f});return{step:e.step,ok:h.ok,reasonCode:u||h.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:h.confirmationRequired,sendAccepted:h.sendAccepted,beforeTextCount:r,afterTextCount:f,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 We(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 $e(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=Oe(r.waitingRecords[0]?.nextAttemptAt,o,n);await L(a),r=await S({ledger:e.ledger,bindingId:e.bindingId,currentLastInboundRevision:0,sender:e.sender,maxUserActivityWaitMs:n})}return r}function Oe(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 Be(e){const t=e.sendResults.filter(l=>!V(l)),n=e.sendResults.filter(l=>!l.skipped).map(l=>l.details?.text&&typeof l.details.text=="string"?l.details.text:"").filter(Boolean),o=e.observedMessages.map(l=>[l.normalizedText||"",l.anchorText||"",l.textExcerpt||""].join(`
|
|
1
|
+
import M from"node:crypto";import{spawnSync as de}from"node:child_process";import p from"node:fs";import i from"node:path";import{fileURLToPath as ce}from"node:url";import{buildBottomPageReport as T,buildDownloadVisibleMediaReport as K}from"./wechat-channel-download-report.js";import{buildWeChatMessagesMarkdown as S}from"./wechat-channel-markdown-report.js";import{loadConfig as le}from"../config/index.js";import{createWeChatChannelApiClient as k}from"../channels/wechat-channel/client.js";import{resolveWeChatChannelHelperAsset as ue,WECHAT_CHANNEL_HELPER_VERSION as me}from"../channels/wechat-channel/helper-assets.js";import{WeChatChannelHelperClient as he}from"../channels/wechat-channel/helper-client.js";import{requiredWindowsWeChatChannelHelperCapabilitiesForProfile as B}from"../channels/wechat-channel/helper-protocol.js";import{classifyWeChatOutboundEchoes as fe,enqueueWeChatOutboundReply as G}from"../channels/wechat-channel/outbound-ledger.js";import{loadWeChatChannelLedger as ge,saveWeChatChannelLedger as we,updateWeChatChannelBindingLedger as pe}from"../channels/wechat-channel/ledger.js";import{waitForWeChatChannelPacing as V}from"../channels/wechat-channel/pacing.js";import{WeChatChannelOutboundSender as z,sendQueuedWeChatOutboundRecords as C}from"../channels/wechat-channel/outbound-sender.js";import{captureWeChatWindow as j,detectWeChatMessageInputPointByServerVision as be,ensureWeChatWindowReady as y,focusKnownWeChatWindow as I,observeWeChatChannelBindingViaHelper as ve,openConversationBySearch as x,recognizeWeChatScreenshot as E}from"../channels/wechat-channel/observer.js";import{createWeChatChannelRuntime as ye}from"../channels/wechat-channel/runtime.js";function Se(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 ke="ABC",Ce="wechat-channel-action-smoke";function Ie(e){const t=e.filter(l=>l!=="--"),n=ht(t),r=gt(t,"--step").map(ft).filter(l=>l!=null),o=le(),s=f(t,"--trace-id")||`wechat-action-smoke-${Date.now().toString(36)}`,d=i.resolve(f(t,"--out")||f(t,"--output")||i.join(process.cwd(),".dev-runtime","wechat-channel","action-smoke",s)),a=r.length?wt(r):xe(n);return{conversation:f(t,"--conversation")||f(t,"--group")||ke,mode:r.length?"custom":n,steps:a,outDir:d,workDir:i.resolve(f(t,"--work-dir")||process.cwd()),traceId:s,runtimeId:f(t,"--runtime-id")||Ce,machineId:f(t,"--machine-id")||process.env.SHENNIAN_MACHINE_ID||o.machineId||"local",sessionId:f(t,"--session-id")||process.env.SHENNIAN_EXTERNAL_SESSION_ID||process.env.SHENNIAN_MANAGER_SESSION_ID,serverUrl:f(t,"--server-url")||o.serverUrl,platform:lt(f(t,"--platform")),text:f(t,"--text"),filePath:L(f(t,"--file")),imagePath:L(f(t,"--image")),videoPath:L(f(t,"--video")),downloadAnchorText:f(t,"--download-anchor-text")||f(t,"--media-anchor-text"),allowEmptyMedia:t.includes("--allow-empty-media"),requireServer:t.includes("--require-server")}}function xe(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 De(e){const t=Date.now(),n=new Date(t).toISOString();p.mkdirSync(e.outDir,{recursive:!0});const r=i.join(e.outDir,"helper-trace.jsonl");p.writeFileSync(r,"");const o=ot(e),s=o.bindings[0],d=st(e,r);await d.start();const a={ok:!1,conversation:e.conversation,outDir:e.outDir,helperTracePath:r,traceId:e.traceId,runtimeId:e.runtimeId,machineId:e.machineId,startedAt:n,finishedAt:n,durationMs:0,steps:[]};try{for(const l of e.steps){if(Ae(l)&&a.steps.some(c=>c.step==="open-read"&&!c.ok&&!c.skipped)){a.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}a.steps.push(await _e({step:l,options:e,runtime:o,binding:s,helper:d}))}}finally{await d.stop().catch(()=>{}),a.finishedAt=new Date().toISOString(),a.durationMs=Date.now()-t,a.ok=a.steps.every(l=>l.ok||l.skipped),m(i.join(e.outDir,"summary.json"),a)}return a}function Ae(e){return e==="send-text"||e==="send-file"||e==="send-image"||e==="send-video"||e==="send-and-confirm"}async function _e(e){try{return e.step==="open-read"?await je(e):e.step==="structure-window"?await Ke(e):e.step==="server-observe"?await qe(e):e.step==="read-bottom-page"?await He(e):e.step==="download-visible-media"?await Ue(e):e.step==="send-and-confirm"?await Fe(e):e.step.startsWith("human-")?await Me(e):await J(e)}catch(t){const n=kt(t),r=await Re(e,n,t);return{step:e.step,ok:!1,reasonCode:n,errorSummary:t instanceof Error?t.message:String(t),userAction:Ct(n),...r?{details:r}:{}}}}async function Re(e,t,n){if(!Pe(t))return;const r=i.join(e.options.outDir,`${e.step}-failure-diagnostics.json`),o={step:e.step,reasonCode:t,errorSummary:n instanceof Error?n.message:String(n),capturedAt:new Date().toISOString()};try{o.permissions=await e.helper.request("permissions.check",{},e.options.traceId)}catch(s){o.permissionsError=s instanceof Error?s.message:String(s)}try{o.windows=await e.helper.request("windows.list",{},e.options.traceId)}catch(s){o.windowsError=s instanceof Error?s.message:String(s)}return m(r,o),{failureDiagnosticsPath:r}}function Pe(e){return e.startsWith("wechat_")||e.startsWith("permission_")||e.startsWith("user_active")}async function Me(e){if(e.step==="human-observe-deferred")return await Te(e);const t=e.step,n=`human-${_(`${e.options.traceId}:${t}:${Date.now()}`)}`,r={version:1,runtimeId:e.runtime.runtimeId,records:[]},o=G({ledger:r,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=Z(e.helper,Y(t)),d=s.actionLog,a=k({serverUrl:e.options.serverUrl}),l=async P=>{d.push(`openConversation:${P}`);const ae=await y(s,e.options.traceId),ie=await I(s,ae,e.options.traceId);return x({helper:s,window:ie,settleToBottom:!1,binding:{...e.binding,conversationDisplayName:P},runtime:e.runtime,api:a,workDir:e.options.workDir,traceId:e.options.traceId})},c=new z({helper:s,platform:e.runtime.policy.platform,openConversation:l,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 C({ledger:r,bindingId:e.binding.bindingId,currentLastInboundRevision:0,sender:c,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 C({ledger:r,bindingId:e.binding.bindingId,currentLastInboundRevision:0,sender:c,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(Je()),h=await C({ledger:r,bindingId:e.binding.bindingId,currentLastInboundRevision:0,sender:c,now:new Date("2026-06-15T00:00:06.000Z")}));const g=Qe(e.step,o)?await F({helper:s,runtime:e.runtime,binding:e.binding,api:a,workDir:e.options.workDir,marker:n,traceId:e.options.traceId,outDir:e.options.outDir,filePrefix:e.step}):0,u=g>0?fe({ledger:r,bindingId:e.binding.bindingId,messages:[{stableMessageKey:`human-echo:${n}`,senderRole:"self",kind:"text",anchorText:o.text,normalizedText:o.text,textExcerpt:o.text,observedAt:new Date().toISOString()}]}):{confirmedRecords:[],manualReviewRecords:[],remainingMessages:[]},b=r.records[0],R=nt(b,h,u.confirmedRecords),v={case:e.step,marker:n,runStatus:R,reasonCode:b.deferReason||b.failureCode||null,outboundStatus:b.sendStatus,attemptCount:b.attemptCount??0,nextAttemptAt:b.nextAttemptAt??null,observedMarkerCount:g,actionLog:d,clipboardRestore:d.includes("clipboard.restore")?"attempted":"not_needed",commitStage:b.commitStage??null};return m(i.join(e.options.outDir,`${e.step}-summary.json`),v),{step:e.step,ok:rt(e.step,v),reasonCode:v.reasonCode||void 0,details:v}}async function Te(e){const t=Z(e.helper,Y("human-observe-deferred")),n=await t.request("activity.snapshot",{},e.options.traceId),r=!!(n.ok&&n.result&&typeof n.result=="object"&&Number(n.result.keyDownSecondsAgo)<5),o={case:e.step,marker:null,runStatus:r?"observe_deferred_user_active":"baseline_or_no_change",reasonCode:r?"recent_keyboard_activity":null,outboundStatus:null,attemptCount:0,nextAttemptAt:null,observedMarkerCount:0,actionLog:t.actionLog,clipboardRestore:"not_needed"};return m(i.join(e.options.outDir,`${e.step}-summary.json`),o),{step:e.step,ok:r&&!t.actionLog.some(s=>s.startsWith("windows.")||s.startsWith("wechat.")||s.startsWith("clipboard.")),reasonCode:o.reasonCode||void 0,details:o}}async function je(e){const t=await y(e.helper,e.options.traceId),n=await I(e.helper,t,e.options.traceId),r=k({serverUrl:e.options.serverUrl}),o=await x({helper:e.helper,window:n,binding:e.binding,runtime:e.runtime,api:r,workDir:e.options.workDir,traceId:e.options.traceId});if(!o.opened)throw await Ee({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 s=await j(e.helper,n.windowId,e.options.traceId),d=D(e.options.outDir,"open-read-full-window",s),a=await E(e.helper,s,e.options.traceId);return m(i.join(e.options.outDir,"open-read-ocr.json"),a),{step:"open-read",ok:!0,details:{openedReason:o.reason,windowId:n.windowId,screenshotPath:d,screenshot:{width:s.width,height:s.height,mimeType:s.mimeType},ocrBlockCount:a.blocks?.length??0,visibleConversationFingerprintCount:a.visibleConversationFingerprints?.length??0}}}async function Ee(e){try{const t=await j(e.helper,e.window.windowId,e.traceId,e.window.bounds),n=D(e.outDir,"open-read-failure-window",t),r=await E(e.helper,t,e.traceId);m(i.join(e.outDir,"open-read-failure-ocr.json"),r),m(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:r.blocks?.length??0,visibleConversationFingerprintCount:r.visibleConversationFingerprints?.length??0,topTexts:(r.blocks??[]).slice(0,30).map(o=>({text:o.text,bbox:o.bbox}))})}catch(t){m(i.join(e.outDir,"open-read-failure-summary.json"),{reason:e.reason,captureError:t instanceof Error?t.message:String(t)})}}async function J(e){return await We(e,ut(e.step,e.options))}async function We(e,t){if(t.skipped)return{step:e.step,ok:!0,skipped:!0,reasonCode:t.reasonCode};const n=k({serverUrl:e.options.serverUrl}),r={version:1,runtimeId:e.runtime.runtimeId,records:[]},o=`${e.options.traceId}:${e.step}:${t.text}:${t.attachmentPath||""}`,s=t.text?await F({helper:e.helper,runtime:e.runtime,binding:e.binding,api:n,workDir:e.options.workDir,marker:t.text,traceId:e.options.traceId,outDir:e.options.outDir,filePrefix:`${e.step}-before-send`,settleToBottom:!1}).catch(()=>null):null;G({ledger:r,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 d=new z({helper:e.helper,platform:e.runtime.policy.platform,traceId:e.options.traceId,activityGatePolicy:e.runtime.foregroundPolicy==="work"?{mouseMovedThresholdMs:0,mouseClickThresholdMs:0,scrollWheelThresholdMs:0,keyDownThresholdMs:0}:void 0,takeoverCheck:e.runtime.foregroundPolicy!=="work",onAfterPaste:async({kind:u})=>{await Xe({helper:e.helper,traceId:e.options.traceId,outDir:e.options.outDir,filePrefix:`${e.step}-after-paste-${u}`})},openConversation:async u=>{const b=await y(e.helper,e.options.traceId),R=await I(e.helper,b,e.options.traceId),v=await x({helper:e.helper,window:R,settleToBottom:!1,binding:{...e.binding,conversationDisplayName:u},runtime:e.runtime,api:n,workDir:e.options.workDir,traceId:e.options.traceId});if(!v.opened)return{...v,inputPoint:null};const P=await be({runtime:e.runtime,binding:{...e.binding,conversationDisplayName:u},helper:e.helper,api:n,workDir:e.options.workDir,traceId:e.options.traceId,window:R});return{...v,inputPoint:P}}}),a=await Be({ledger:r,bindingId:e.binding.bindingId,sender:d});await V("send-after-submit",`${e.options.traceId}:${e.step}:after-submit`);const l=r.records[0],c=a.failedRecords[0]?.failureCode||a.manualReviewRecords[0]?.failureCode||a.waitingRecords[0]?.deferReason||a.staleRecords[0]?.failureCode,w=a.sentRecords.length===1&&a.failedRecords.length===0&&a.waitingRecords.length===0&&a.manualReviewRecords.length===0&&a.staleRecords.length===0,h=w&&t.text?await tt({helper:e.helper,runtime:e.runtime,binding:e.binding,api:n,workDir:e.options.workDir,marker:t.text,traceId:e.options.traceId,outDir:e.options.outDir,filePrefix:`${e.step}-after-send`,settleToBottom:!1,attempts:3,targetGreaterThan:s}):null,g=$e({sendAccepted:w,text:t.text,attachmentPath:t.attachmentPath,beforeTextCount:s,afterTextCount:h});return{step:e.step,ok:g.ok,reasonCode:c||g.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:g.confirmationRequired,sendAccepted:g.sendAccepted,beforeTextCount:s,afterTextCount:h,sentRecords:a.sentRecords.length,failedRecords:a.failedRecords.length,waitingRecords:a.waitingRecords.length,manualReviewRecords:a.manualReviewRecords.length,staleRecords:a.staleRecords.length,sendStatus:l?.sendStatus,failureCode:l?.failureCode??null,lastErrorSummary:l?.lastErrorSummary??null,deferReason:l?.deferReason,commitStage:l?.commitStage??null,attemptCount:l?.attemptCount??0,nextAttemptAt:l?.nextAttemptAt??null}}}function $e(e){const t=!!(e.text&&e.text.trim()&&!e.attachmentPath);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,r=typeof e.afterTextCount=="number"&&Number.isFinite(e.afterTextCount)?e.afterTextCount:0,o=n==null?r>0:r>n;return{ok:o,reasonCode:o?void 0:"sent_text_not_observed",sendAccepted:!0,confirmationRequired:t}}async function Be(e){const t=e.maxAttempts??24,n=e.maxWaitMs??9e4,r=Date.now();let o=await C({ledger:e.ledger,bindingId:e.bindingId,currentLastInboundRevision:0,sender:e.sender,maxUserActivityWaitMs:n});for(let s=2;o.waitingRecords.length>0&&s<=t&&!(Date.now()-r>=n);s+=1){const d=Ne(o.waitingRecords[0]?.nextAttemptAt,r,n);await q(d),o=await C({ledger:e.ledger,bindingId:e.bindingId,currentLastInboundRevision:0,sender:e.sender,maxUserActivityWaitMs:n})}return o}function Ne(e,t,n){const r=Math.max(0,n-(Date.now()-t));if(r<=0)return 0;const o=e?new Date(e).getTime():Number.NaN,s=Number.isFinite(o)?o-Date.now():1e3;return Math.max(500,Math.min(Math.max(500,s),Math.min(5e3,r)))}function Oe(e){const t=e.sendResults.filter(u=>!Q(u)),n=e.sendResults.filter(u=>!u.skipped).map(u=>u.details?.text&&typeof u.details.text=="string"?u.details.text:"").filter(Boolean),r=e.observedMessages.map(u=>[u.normalizedText||"",u.anchorText||"",u.textExcerpt||""].join(`
|
|
2
2
|
`)).join(`
|
|
3
|
-
`),r=n.filter(l=>o.includes(l)),s=e.sendResults.map(l=>typeof l.details?.sendStatus=="string"?l.details.sendStatus:"").filter(Boolean),a=e.sendResults.filter(V).length,d=W(t,"waitingRecords"),u=W(t,"failedRecords"),c=W(t,"manualReviewRecords"),f=t.find(l=>!l.ok||l.skipped),h=s.length===n.length&&s.every(l=>l==="sent_unconfirmed"||l==="confirmed_echo"),p=!f&&n.length>0&&r.length>0&&h&&d===0&&u===0&&c===0;return{ok:p,reasonCode:p?void 0:f?.reasonCode||(d>0?"outbound_send_waiting":void 0)||(u>0?"outbound_send_failed":void 0)||(c>0?"outbound_manual_review":void 0)||(h?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:u,manualReviewCount:c}}function V(e){return e.skipped===!0&&e.reasonCode==="ffmpeg_unavailable_for_video_fixture"}function W(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 Fe(e){const t=["send-text"],n=[];for(const c of t)n.push(await z({...e,step:c}));await L(1200);const o=await R(e,3,{observePipeline:"edge-structure"}),r=D(o.messages),s=i.join(e.options.outDir,"bottom-page.md"),a=y(o.messages,{conversation:e.options.conversation,attachmentsDirName:i.basename(o.attachmentsDir)});m(i.join(e.options.outDir,"bottom-page-summary.json"),r),m(i.join(e.options.outDir,"server-observe-messages.json"),o.messages),x(s,a);const d=Be({sendResults:n,observedMessages:o.messages}),u=d.ok&&o.messages.length>0;return{step:"send-and-confirm",ok:u,reasonCode:u?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 R(e,t,n={}){let o;const r=[];for(let s=1;s<=t;s+=1)try{const a=await J(e,n);return r.length&&(r.push({phase:"observe",attempt:s,ok:!0,observedCount:a.messages.length,at:new Date().toISOString()}),m(i.join(e.options.outDir,"observe-retry-events.json"),r)),a}catch(a){if(o=a,r.push({phase:"observe",attempt:s,ok:!1,errorSummary:a instanceof Error?a.message:String(a||""),at:new Date().toISOString()}),s>=t||!Ne(a))break;try{const d=await C(e.helper,e.options.traceId),u=await k(e.helper,d,e.options.traceId),c=await I({helper:e.helper,window:u,binding:e.binding,traceId:e.options.traceId});r.push({phase:"recover",attempt:s,ok:c.opened,reason:c.reason,windowId:u.windowId,at:new Date().toISOString()})}catch(d){r.push({phase:"recover",attempt:s,ok:!1,errorSummary:d instanceof Error?d.message:String(d||""),at:new Date().toISOString()})}m(i.join(e.options.outDir,"observe-retry-events.json"),r),await U("observe-retry",`${e.options.traceId}:observe-retry:${s}`,1500*s)}throw r.length&&m(i.join(e.options.outDir,"observe-retry-events.json"),r),o}function Ne(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 Le(e){const t=await R(e,3),n=D(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 m(i.join(e.options.outDir,"bottom-page-summary.json"),n),m(i.join(e.options.outDir,"server-observe-messages.json"),t.messages),x(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 He(e){const t=await R(e,3,{observePipeline:"edge-structure",persistLocalLedger:!0});$(e.options.outDir,"download-visible",t.observationEvidence);const n=D(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});m(i.join(e.options.outDir,"bottom-page-summary.json"),n),m(i.join(e.options.outDir,"download-visible-summary.json"),s),m(i.join(e.options.outDir,"download-visible-messages.json"),t.messages),x(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 qe(e){const t=await R(e,3,{observePipeline:"server-observe"});$(e.options.outDir,"server-observe",t.observationEvidence),m(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)});x(n,o);const r=ee(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:F(t.messages.map(s=>s.kind||"unknown")),attachmentSummary:r,attachmentsDir:t.attachmentsDir,markdownPath:n,markdown:o}}}async function Ke(e){const t=await J(e,{observePipeline:"edge-structure",downloadMedia:!1});$(e.options.outDir,"structure-window",t.observationEvidence),m(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)});x(n,o);const r=ee(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:F(t.messages.map(s=>s.kind||"unknown")),attachmentSummary:r,attachmentsDir:t.attachmentsDir,markdownPath:n,markdown:o}}}async function J(e,t={}){const n=ye({sessionId:e.options.sessionId,observePipeline:t.observePipeline}),o=ce({serverUrl:e.options.serverUrl});e.options.skipRuntimeUpsert||(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");w.mkdirSync(r,{recursive:!0});const s=t.persistLocalLedger?ht(e.options):void 0,a=s?fe(s,e.runtime.runtimeId):void 0;let d,u,c;const f=await be({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,activityGuard:e.options.activityGuard,observePipeline:t.observePipeline,localLedgerTailAnchors:a?ft(a.bindings[e.binding.bindingId]):void 0,onObservationEvidence:({capture:l,ocr:b})=>{d=Ge(l),u=ze(b),c=Ue(l,b,{captureHash:d,ocrHash:u})}});let h,p;if(a&&s){const l=pe({ledger:a,bindingId:e.binding.bindingId,observedMessages:f});h=l.binding,p=oe({bindingId:e.binding.bindingId,revision:h.revision,messages:l.newMessages}),ge(s,a)}return{messages:f,attachmentsDir:r,observePipeline:t.observePipeline,...s?{ledgerPath:s}:{},...h?{ledgerBinding:h}:{},traceHashes:{...d?{captureHash:d}:{},...u?{ocrHash:u}:{},...p?{ingestPayloadHash:p}:{}},...c?{observationEvidence:c}:{}}}function Ue(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 $(e,t,n){if(!n)return;const o=n.capture.dataBase64?P(e,`${t}-observation-window`,n.capture):void 0;m(i.join(e,`${t}-observation-evidence.json`),{...n.report,...o?{screenshotPath:o}:{}})}function Ge(e){if(e.dataBase64)return`sha256:${_.createHash("sha256").update(Buffer.from(e.dataBase64,"base64")).digest("hex")}`}function ze(e){return oe({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 Q(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,c,f){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:f};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:f}}if(u==="automation.lease.acquire"){const h=await e.request(u,c,f),p=h.result&&typeof h.result=="object"?h.result:{};return s=typeof p.leaseId=="string"?p.leaseId:"",h}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:f}):{id:`human-lease-${r}`,ok:!0,result:{active:!0,leaseId:s,interrupted:!1},latencyMs:0,traceId:f}):e.request(u,c,f)}}}function Z(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 Ve(){return{preflightBusySnapshots:0,forceIdleAfterBusy:!0}}function Je(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 O(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 j(e.helper,n.windowId,e.traceId),s=P(e.outDir,`${e.filePrefix}-observe-marker`,r),a=await E(e.helper,r,e.traceId);return m(i.join(e.outDir,`${e.filePrefix}-observe-marker-ocr.json`),{screenshotPath:s,marker:e.marker,ocr:a}),Qe(a.blocks||[],e.marker)}function Qe(e,t){const n=t.trim();if(!n)return 0;const o=e.map(a=>a.text||"").join(`
|
|
4
|
-
`),
|
|
5
|
-
`)}}function
|
|
6
|
-
${
|
|
7
|
-
`,"utf8"),{text:`codex-product-action file ${
|
|
8
|
-
`,"utf8")}function
|
|
9
|
-
`)}async function
|
|
10
|
-
`),process.exit(1)});export{
|
|
3
|
+
`),o=n.filter(u=>r.includes(u)),s=e.sendResults.map(u=>typeof u.details?.sendStatus=="string"?u.details.sendStatus:"").filter(Boolean),d=e.sendResults.filter(Q).length,a=N(t,"waitingRecords"),l=N(t,"failedRecords"),c=N(t,"manualReviewRecords"),w=t.find(u=>!u.ok||u.skipped),h=s.length===n.length&&s.every(u=>u==="sent_unconfirmed"||u==="confirmed_echo"),g=!w&&n.length>0&&o.length>0&&h&&a===0&&l===0&&c===0;return{ok:g,reasonCode:g?void 0:w?.reasonCode||(a>0?"outbound_send_waiting":void 0)||(l>0?"outbound_send_failed":void 0)||(c>0?"outbound_manual_review":void 0)||(h?void 0:"outbound_status_not_accepted")||(o.length?"partial_sent_messages_observed":"sent_messages_not_observed"),sentTexts:n,confirmedTexts:o,outboundStatuses:s,skippedFixtureCount:d,pendingOutboundCount:a,failedOutboundCount:l,manualReviewCount:c}}function Q(e){return e.skipped===!0&&e.reasonCode==="ffmpeg_unavailable_for_video_fixture"}function N(e,t){return e.reduce((n,r)=>{const o=r.details?.[t];return n+(typeof o=="number"&&Number.isFinite(o)?o:0)},0)}async function Fe(e){const t=["send-text"],n=[];for(const c of t)n.push(await J({...e,step:c}));await q(1200);const r=await W(e,3,{observePipeline:"edge-structure"}),o=T(r.messages),s=i.join(e.options.outDir,"bottom-page.md"),d=S(r.messages,{conversation:e.options.conversation,attachmentsDirName:i.basename(r.attachmentsDir)});m(i.join(e.options.outDir,"bottom-page-summary.json"),o),m(i.join(e.options.outDir,"server-observe-messages.json"),r.messages),A(s,d);const a=Oe({sendResults:n,observedMessages:r.messages}),l=a.ok&&r.messages.length>0;return{step:"send-and-confirm",ok:l,reasonCode:l?void 0:a.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:a.sentTexts,confirmedTexts:a.confirmedTexts,outboundStatuses:a.outboundStatuses,skippedFixtureCount:a.skippedFixtureCount,pendingOutboundCount:a.pendingOutboundCount,failedOutboundCount:a.failedOutboundCount,manualReviewCount:a.manualReviewCount,observedCount:r.messages.length,byKind:o.byKind,attachmentSummary:o.attachmentSummary,attachmentsDir:r.attachmentsDir,reportPath:i.join(e.options.outDir,"bottom-page-summary.json"),markdownPath:s,markdown:d}}}async function W(e,t,n={}){let r;const o=[];for(let s=1;s<=t;s+=1)try{const d=await X(e,n);return o.length&&(o.push({phase:"observe",attempt:s,ok:!0,observedCount:d.messages.length,at:new Date().toISOString()}),m(i.join(e.options.outDir,"observe-retry-events.json"),o)),d}catch(d){if(r=d,o.push({phase:"observe",attempt:s,ok:!1,errorSummary:d instanceof Error?d.message:String(d||""),at:new Date().toISOString()}),s>=t||!Le(d))break;try{const a=await y(e.helper,e.options.traceId),l=await I(e.helper,a,e.options.traceId),c=await x({helper:e.helper,window:l,binding:e.binding,runtime:e.runtime,api:k({serverUrl:e.options.serverUrl}),workDir:e.options.workDir,traceId:e.options.traceId});o.push({phase:"recover",attempt:s,ok:c.opened,reason:c.reason,windowId:l.windowId,at:new Date().toISOString()})}catch(a){o.push({phase:"recover",attempt:s,ok:!1,errorSummary:a instanceof Error?a.message:String(a||""),at:new Date().toISOString()})}m(i.join(e.options.outDir,"observe-retry-events.json"),o),await V("observe-retry",`${e.options.traceId}:observe-retry:${s}`,1500*s)}throw o.length&&m(i.join(e.options.outDir,"observe-retry-events.json"),o),r}function Le(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 He(e){const t=await W(e,3),n=T(t.messages),r=i.join(e.options.outDir,"bottom-page.md"),o=S(t.messages,{conversation:e.options.conversation,attachmentsDirName:i.basename(t.attachmentsDir)});return m(i.join(e.options.outDir,"bottom-page-summary.json"),n),m(i.join(e.options.outDir,"server-observe-messages.json"),t.messages),A(r,o),{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:r,markdown:o}}}async function Ue(e){const t=await W(e,3,{observePipeline:"edge-structure",persistLocalLedger:!0});O(e.options.outDir,"download-visible",t.observationEvidence);const n=T(t.messages),r=i.join(e.options.outDir,"download-visible.md"),o=S(t.messages,{conversation:e.options.conversation,attachmentsDirName:i.basename(t.attachmentsDir)}),s=K(t.messages,t.attachmentsDir,{observePipeline:t.observePipeline,downloadAnchorText:e.options.downloadAnchorText,ledgerPath:t.ledgerPath,ledgerBinding:t.ledgerBinding,traceHashes:t.traceHashes});m(i.join(e.options.outDir,"bottom-page-summary.json"),n),m(i.join(e.options.outDir,"download-visible-summary.json"),s),m(i.join(e.options.outDir,"download-visible-messages.json"),t.messages),A(r,o);const d=!!(e.options.allowEmptyMedia&&s.reasonCode==="no_visible_media_candidates"&&t.messages.length>0),a=s.ok||d;return{step:"download-visible-media",ok:a,reasonCode:a?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:d,attachmentsDir:t.attachmentsDir,reportPath:i.join(e.options.outDir,"download-visible-summary.json"),markdownPath:r,markdown:o,phases:s.phases,observePipeline:s.observePipeline,ledgerPath:s.ledgerPath,ledgerRevision:s.ledger?.revision,traceHashes:s.traceHashes,traceEvents:s.traceEvents}}}async function qe(e){const t=await W(e,3,{observePipeline:"server-observe"});O(e.options.outDir,"server-observe",t.observationEvidence),m(i.join(e.options.outDir,"server-observe-messages.json"),t.messages);const n=i.join(e.options.outDir,"server-observe.md"),r=S(t.messages,{conversation:e.options.conversation,attachmentsDirName:i.basename(t.attachmentsDir)});A(n,r);const o=ne(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:H(t.messages.map(s=>s.kind||"unknown")),attachmentSummary:o,attachmentsDir:t.attachmentsDir,markdownPath:n,markdown:r}}}async function Ke(e){const t=await X(e,{observePipeline:"edge-structure",downloadMedia:!1});O(e.options.outDir,"structure-window",t.observationEvidence),m(i.join(e.options.outDir,"structure-window-messages.json"),t.messages);const n=i.join(e.options.outDir,"structure-window.md"),r=S(t.messages,{conversation:e.options.conversation,attachmentsDirName:i.basename(t.attachmentsDir)});A(n,r);const o=ne(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:H(t.messages.map(s=>s.kind||"unknown")),attachmentSummary:o,attachmentsDir:t.attachmentsDir,markdownPath:n,markdown:r}}}async function X(e,t={}){const n=Se({sessionId:e.options.sessionId,observePipeline:t.observePipeline}),r=k({serverUrl:e.options.serverUrl});e.options.skipRuntimeUpsert||(n==="direct-edge-structure"?await r.upsertRuntime(e.runtime):await r.upsertRuntime(e.runtime,{...e.binding,enabled:!1,allowReply:!1}));const o=i.join(e.options.outDir,"inbound-attachments");p.mkdirSync(o,{recursive:!0});const s=t.persistLocalLedger?pt(e.options):void 0,d=s?ge(s,e.runtime.runtimeId):void 0;let a,l,c;const w=await ve({runtime:e.runtime,binding:{...e.binding,downloadMedia:t.downloadMedia??e.binding.downloadMedia},helper:e.helper,api:r,workDir:e.options.workDir,attachmentsDir:o,traceId:e.options.traceId,mediaAnchorText:e.options.downloadAnchorText,activityGuard:e.options.activityGuard,observePipeline:t.observePipeline,localLedgerTailAnchors:d?bt(d.bindings[e.binding.bindingId]):void 0,onObservationEvidence:({capture:u,ocr:b})=>{a=Ve(u),l=ze(b),c=Ge(u,b,{captureHash:a,ocrHash:l})}});let h,g;if(d&&s){const u=pe({ledger:d,bindingId:e.binding.bindingId,observedMessages:w});h=u.binding,g=se({bindingId:e.binding.bindingId,revision:h.revision,messages:u.newMessages}),we(s,d)}return{messages:w,attachmentsDir:o,observePipeline:t.observePipeline,...s?{ledgerPath:s}:{},...h?{ledgerBinding:h}:{},traceHashes:{...a?{captureHash:a}:{},...l?{ocrHash:l}:{},...g?{ingestPayloadHash:g}:{}},...c?{observationEvidence:c}:{}}}function Ge(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(r=>({text:r.text,...r.bbox?{bbox:r.bbox}:{},...typeof r.confidence=="number"?{confidence:r.confidence}:{}}))}}}function O(e,t,n){if(!n)return;const r=n.capture.dataBase64?D(e,`${t}-observation-window`,n.capture):void 0;m(i.join(e,`${t}-observation-evidence.json`),{...n.report,...r?{screenshotPath:r}:{}})}function Ve(e){if(e.dataBase64)return`sha256:${M.createHash("sha256").update(Buffer.from(e.dataBase64,"base64")).digest("hex")}`}function ze(e){return se({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 Z(e,t){let n=t,r=0,o=0,s="";const d=[];return{actionLog:d,setScenario(l){n=l,r=0,o=0},async request(l,c,w){if(d.push(l),l==="activity.snapshot"){if(r+=1,r<=n.preflightBusySnapshots)return{id:`human-${r}`,ok:!0,result:{keyDownSecondsAgo:.2,mouseMovedSecondsAgo:.2,scrollWheelSecondsAgo:.2,privacy:{capturesKeyContent:!1,capturesMousePath:!1}},latencyMs:0,traceId:w};if(n.forceIdleAfterBusy)return{id:`human-${r}`,ok:!0,result:{keyDownSecondsAgo:60,mouseMovedSecondsAgo:60,leftMouseDownSecondsAgo:60,rightMouseDownSecondsAgo:60,scrollWheelSecondsAgo:60,privacy:{capturesKeyContent:!1,capturesMousePath:!1}},latencyMs:0,traceId:w}}if(l==="automation.lease.acquire"){const h=await e.request(l,c,w),g=h.result&&typeof h.result=="object"?h.result:{};return s=typeof g.leaseId=="string"?g.leaseId:"",h}return l==="automation.lease.status"?(o+=1,n.simulateInterruptionAtLeaseStatus===o?(d.push("automation.lease.simulateInterruption"),{id:`human-lease-${o}`,ok:!0,result:{active:!0,leaseId:s,interrupted:!0,interruptReason:n.interruptionReason||"recent_mouse_activity"},latencyMs:0,traceId:w}):{id:`human-lease-${o}`,ok:!0,result:{active:!0,leaseId:s,interrupted:!1},latencyMs:0,traceId:w}):e.request(l,c,w)}}}function Y(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 Je(){return{preflightBusySnapshots:0,forceIdleAfterBusy:!0}}function Qe(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 Xe(e){try{const t=await y(e.helper,e.traceId),n=await j(e.helper,t.windowId,e.traceId,t.bounds),r=D(e.outDir,e.filePrefix,n),o=await E(e.helper,n,e.traceId);m(i.join(e.outDir,`${e.filePrefix}-ocr.json`),{screenshotPath:r,ocr:o})}catch(t){m(i.join(e.outDir,`${e.filePrefix}-error.json`),{errorSummary:t instanceof Error?t.message:String(t||"after paste evidence failed")})}}async function F(e){const t=await y(e.helper,e.traceId),n=await I(e.helper,t,e.traceId);if(!(await x({helper:e.helper,window:n,binding:e.binding,runtime:e.runtime,api:e.api,workDir:e.workDir,traceId:e.traceId,settleToBottom:e.settleToBottom})).opened)return 0;const o=await j(e.helper,n.windowId,e.traceId),s=D(e.outDir,`${e.filePrefix}-observe-marker`,o),d=await E(e.helper,o,e.traceId);return m(i.join(e.outDir,`${e.filePrefix}-observe-marker-ocr.json`),{screenshotPath:s,marker:e.marker,ocr:d}),Ye(d.blocks||[],e.marker)}function Ze(e,t){const n=t.trim();if(!n)return 0;const r=e.map(d=>d.text||"").join(`
|
|
4
|
+
`),o=te(r,n);if(o>0)return o;const s=ee(n);return s.length<8?0:te(ee(r),s)}function Ye(e,t){const n=e.filter(et);return Ze(n,t)}function et(e){const t=e.bbox;if(!t)return!0;const n=Number(t.x),r=Number(t.y),o=Number(t.width);return[n,r,o].every(Number.isFinite)?n+o/2>=560&&r>=100:!0}function ee(e){return e.normalize("NFKC").replace(/[\s\u200B-\u200D\uFEFF]+/g,"")}function te(e,t){if(!t)return 0;let n=0,r=0;for(;;){const o=e.indexOf(t,r);if(o<0)break;n+=1,r=o+t.length}return n}async function tt(e){const t=Math.max(1,e.attempts??3),n=typeof e.targetGreaterThan=="number"&&Number.isFinite(e.targetGreaterThan)?e.targetGreaterThan:null;let r=0;for(let o=0;o<t;o+=1){if(r=await F({helper:e.helper,runtime:e.runtime,binding:e.binding,api:e.api,workDir:e.workDir,marker:e.marker,traceId:e.traceId,outDir:e.outDir,filePrefix:`${e.filePrefix}-${o+1}`,settleToBottom:e.settleToBottom}),n==null?r>0:r>n)return r;o<t-1&&await q(800)}return r}function nt(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 rt(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 ot(e){return ye({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 st(e,t){const n=ue({platform:e.platform});if(!n.ok)throw new Error(`${n.reasonCode}: ${n.message}`);return new he({helperPath:n.helperPath,expectedHelperVersion:n.version||me,requiredCapabilities:ct(e),guardUnsafeWindowsCommands:(e.platform??process.platform)==="win32",skipUserActivityGuard:!0,cleanupWindowsOverlays:(e.platform??process.platform)==="win32",requestLogger:at(t)})}function at(e){return t=>{p.appendFileSync(e,`${JSON.stringify(it(t))}
|
|
5
|
+
`)}}function it(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=$(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=$(e.result)),t}function $(e,t="",n=0){if(e==null||typeof e=="number"||typeof e=="boolean")return e;if(typeof e=="string")return dt(t,e)?{type:"string",length:e.length,sha256:M.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(d=>$(d,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 r=e,o={};for(const[s,d]of Object.entries(r))o[s]=$(d,s,n+1);return o}function dt(e,t){return t.length>240?!0:/(base64|bytes|data|image|screenshot|png|jpeg|jpg|buffer)/i.test(e)&&t.length>48}function ct(e){if((e.platform??process.platform)==="win32")return e.steps.some(t=>t.startsWith("send")||t.startsWith("human-send"))?B("send"):e.steps.some(t=>t==="download-visible-media")?B("download"):B("observe")}function lt(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 ut(e,t){const n=i.join(t.outDir,"fixtures");p.mkdirSync(n,{recursive:!0});const r=new Date().toISOString().replace(/[-:.TZ]/g,"").slice(0,14);if(e==="send-text")return{text:t.text||`codex-product-action text ${r}`};if(e==="send-file"){const o=t.filePath||i.join(n,`wechat-action-smoke-${r}.txt`);return t.filePath||p.writeFileSync(o,`Shennian WeChat product action smoke
|
|
6
|
+
${r}
|
|
7
|
+
`,"utf8"),{text:`codex-product-action file ${r}`,attachmentPath:o}}if(e==="send-image"){const o=t.imagePath||i.join(n,`wechat-action-smoke-${r}.png`);return t.imagePath||vt(o),{text:`codex-product-action image ${r}`,attachmentPath:o}}if(e==="send-video"){const o=t.videoPath||i.join(n,`wechat-action-smoke-${r}.mp4`);return!t.videoPath&&!yt(o)?{skipped:!0,reasonCode:"ffmpeg_unavailable_for_video_fixture"}:{text:`codex-product-action video ${r}`,attachmentPath:o}}throw new Error(`step ${e} is not a send step`)}function ne(e){const t=e.flatMap(n=>mt(n.mediaMetadata));return{count:t.length,byAvailability:H(t.map(n=>re(n,"availability")||"unknown")),localPaths:t.map(n=>re(n,"localPath")).filter(n=>!!n)}}function mt(e){if(!e||typeof e!="object")return[];const t=e;return Array.isArray(t.attachments)?t.attachments.filter(oe):oe(t.attachment)?[t.attachment]:t.localPath||t.url||t.availability||t.name||t.fileName?[t]:[]}function ht(e){const t=f(e,"--mode")||(e[0]?.startsWith("--")?"":e[0]);return t==="send"||t==="observe"||t==="all"||t==="open-read"?t:"open-read"}function ft(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 gt(e,t){const n=[];for(let r=0;r<e.length;r+=1)e[r]===t&&e[r+1]&&n.push(e[r+1]);return n}function f(e,t){const n=e.indexOf(t),r=n>=0?e[n+1]:void 0;return r&&!r.startsWith("--")?r:void 0}function L(e){return e?i.resolve(e):void 0}function wt(e){return Array.from(new Set(e))}function D(e,t,n){const r=n.mimeType.includes("jpeg")?".jpg":".png",o=i.join(e,`${t}${r}`);return p.writeFileSync(o,Buffer.from(n.dataBase64,"base64")),o}function m(e,t){p.mkdirSync(i.dirname(e),{recursive:!0}),p.writeFileSync(e,`${JSON.stringify(t,null,2)}
|
|
8
|
+
`,"utf8")}function A(e,t){p.mkdirSync(i.dirname(e),{recursive:!0}),p.writeFileSync(e,t,"utf8")}function pt(e){return i.join(e.outDir,"wechat-channel-ledger.json")}function bt(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 vt(e){p.writeFileSync(e,Buffer.from("iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAAVElEQVR4nO3PMQ0AMAgAMUTof2kOKWzo8mCqkmeX9waYtwOwG4DbANwG4DYAtwG4DcBtAG4DcBuA2wDcBuA2ALcBuA3AbQBuA3AbgNsA3AbgNgC3AbgNwG0AbgNwG8BPDyCqAzmh3yHRAAAAAElFTkSuQmCC","base64"))}function yt(e){return de("ffmpeg",["-y","-f","lavfi","-i","testsrc=size=160x120:rate=5","-t","1","-pix_fmt","yuv420p",e],{encoding:"utf8",stdio:"ignore",timeout:2e4}).status===0&&p.existsSync(e)}function H(e){const t={};for(const n of e)t[n]=(t[n]??0)+1;return t}function re(e,t){return typeof e[t]=="string"?e[t].trim():""}function oe(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function _(e){return M.createHash("sha256").update(e).digest("hex").slice(0,16)}function se(e){return`sha256:${M.createHash("sha256").update(St(e)).digest("hex")}`}function St(e){return JSON.stringify(U(e))}function U(e){if(Array.isArray(e))return e.map(U);if(!e||typeof e!="object")return e;const t=e;return Object.fromEntries(Object.keys(t).sort().map(n=>[n,U(t[n])]))}function kt(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 Ct(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 q(e){return new Promise(t=>setTimeout(t,e))}function It(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 xt(){const e=Ie(process.argv.slice(2)),t=await De(e);It(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])===ce(import.meta.url)&&xt().catch(e=>{process.stderr.write(`${e instanceof Error?e.stack||e.message:String(e)}
|
|
10
|
+
`),process.exit(1)});export{T as buildBottomPageReport,K as buildDownloadVisibleMediaReport,Oe as buildSendAndConfirmEvidence,$e as buildSendStepAcceptance,Ye as countMarkerOccurrencesInChatContentBlocks,Ze as countMarkerOccurrencesInOcrBlocks,Ne as nextSmokeDrainWaitMs,Ie as parseWeChatChannelActionSmokeArgs,Se as resolveWeChatSmokeObserveSessionMode,De as runWeChatChannelActionSmoke,xe as stepsForMode};
|
package/dist/src/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Command as
|
|
2
|
-
Disconnecting...`)),v({level:"info",wsEvent:"daemon.stop"}),clearInterval(o)
|
|
1
|
+
import{Command as M}from"commander";import u from"chalk";import G from"node:os";import R from"node:fs";import{loadConfig as I,saveConfig as J,getConfigPath as j,getShennianDir as H,resolveShennianPath as N}from"./config/index.js";import{CliRelayClient as K}from"./relay/client.js";import{registerPairCommand as B,runSmartStart as W}from"./commands/pair.js";import{clearDaemonPidIfOwner as O,createDaemonInstanceId as Y,clearDaemonLauncher as T,findRunningDaemonProcessIds as q,isRemoteAccessDisabled as z,registerDaemonCommand as Q,writeDaemonPid as _,writeDaemonLauncher as P}from"./commands/daemon.js";import{registerAgentCommand as X}from"./commands/agent.js";import{registerManagerCommand as Z}from"./commands/manager.js";import{registerExternalCommand as ee}from"./commands/external.js";import{registerWeChatCommand as ne}from"./commands/wechat.js";import{registerRuntimeCommand as te}from"./commands/runtime.js";import{registerUpgradeCommand as oe}from"./commands/upgrade.js";import{registerToolsCommand as re}from"./commands/tools.js";import{SessionManager as se}from"./session/manager.js";import{SERVERS as k,regionToUrl as ae,urlToRegion as ie}from"./region.js";import{getCurrentVersion as L,handleStartupCrashCheck as ce,checkForUpdate as le,isUpgradeVersionInCooldown as me,recordUpgradeFailure as pe}from"./upgrade/engine.js";import{detectAgents as de}from"./agents/detect.js";import{augmentProcessPath as b}from"./env-path.js";b();const x=L(),ge=3e4,ue=5*6e4;import{getCachedAgentInfos as fe,resolveAgentInfos as he}from"./agents/model-registry.js";import{initCliLogReporter as ve,reportLog as v}from"./log-reporter.js";import{isNativeFusionEnabled as Se}from"./native-fusion/config.js";import{NativeSessionFusionService as we}from"./native-fusion/service.js";import{startDaemonLogRetention as Ie}from"./daemon-log.js";const ye=H(),De=N("daemon.pid");function $e(){try{const n=R.readFileSync(De,"utf-8").trim();if(n.startsWith("{")){const o=JSON.parse(n),r=Number(o.pid);return Number.isInteger(r)&&r>0?r:null}const t=parseInt(n,10);return Number.isInteger(t)&&t>0?t:null}catch{return null}}function Re(n){return n.replace(/^https:\/\//,"wss://").replace(/^http:\/\//,"ws://")}function ke(n){const t=[`trigger=${n.trigger??"unknown"}`,`phase=${n.phase}`,`code=${n.code??"unknown"}`,`attempt=${n.reconnectAttempt}`];return n.reason&&t.push(`reason=${n.reason}`),n.error&&t.push(`error=${n.error}`),t.join(" ")}async function F(n,t=5e3){const o=Date.now();for(;Date.now()-o<t;){try{process.kill(n,0)}catch{return!0}await new Promise(r=>setTimeout(r,100))}try{return process.kill(n,0),!1}catch{return!0}}const a=new M;a.name("shennian").description("Shennian \u2014 AI Agent Control Plane").version(x),a.option("--api <url>","Server URL override").option("--name <name>","Machine name",G.hostname()).action(async n=>{const t=I(),o=n.api??process.env.SHENNIAN_DESKTOP_SERVER_URL??t.serverUrl??void 0;await W(o,n.name)}),a.command("run-service",{hidden:!0}).description("(internal) Connect to relay server, called by the background service").option("--api <url>","Server URL override").action(async n=>{const t=N("env.json");try{const e=JSON.parse(R.readFileSync(t,"utf-8"));for(const[g,m]of Object.entries(e))process.env[g]||(process.env[g]=m);b()}catch{}const o=Ie();z()&&(console.log(`[${new Date().toISOString()}] remote access disabled, service start skipped`),clearInterval(o),process.exit(0));const r=!!(process.env.INVOCATION_ID||process.env.JOURNAL_STREAM||process.env.SHENNIAN_DESKTOP_SERVER_URL),f=async(e,g)=>{console.log(`[${new Date().toISOString()}] ${g} (PID ${e})`),process.kill(e,"SIGTERM"),await F(e)||(process.kill(e,"SIGKILL"),await F(e,2e3))};try{const e=$e();if(e&&e!==process.pid)try{process.kill(e,0),r?await f(e,"managed start taking over from existing daemon"):(console.log(`[${new Date().toISOString()}] daemon already running (PID ${e}), skipping duplicate start`),process.exit(0))}catch{}}catch{}const p=q(process.pid);if(p.length>0)if(r)for(const e of p)try{await f(e,"managed start taking over from orphan daemon")}catch{}else console.log(`[${new Date().toISOString()}] daemon already running (PID ${p[0]}), skipping duplicate start`),process.exit(0);const i=Y();_(process.pid,i,{version:x}),P(process.pid,void 0,i),process.on("exit",()=>{O(process.pid,i),T(i)}),await ce()&&(console.log(`[${new Date().toISOString()}] Rolled back to previous version, restarting...`),process.exit(0));const s=I();s.machineToken||(console.error(u.red("\u2717 Not paired yet. Run: shennian")),process.exit(1));const c=n.api??process.env.SHENNIAN_DESKTOP_SERVER_URL??s.serverUrl??k.cn.url,S=`${Re(c)}/relay/machine`,d=L(),D=de(),h=D.map(e=>e.type),$=fe(D);s.machineId&&ve(c,s.machineId),console.log(`[${new Date().toISOString()}] Connecting to ${S}... (v${d}) agents: ${h.join(",")}`),v({level:"info",wsEvent:"daemon.start",metadata:{version:d,agents:h}});let w=null;const l=new K({serverUrl:S,machineToken:s.machineToken,cliVersion:d,agentList:h,onConnected:()=>{console.log(`[${new Date().toISOString()}] \u2713 Connected`),v({level:"info",wsEvent:"daemon.connected"}),$.some(e=>e.models.length>0)&&l.sendEvent({type:"event",event:"machine.agents",payload:{agentList:h,agents:$}}),he(D,{serverUrl:s.serverUrl??c,authToken:s.machineToken??s.accessToken}).then(e=>{JSON.stringify(e)!==JSON.stringify($)&&l.sendEvent({type:"event",event:"machine.agents",payload:{agentList:h,agents:e}})}).catch(()=>{}),import("./upgrade/engine.js").then(({readUpgradeAttempt:e,clearUpgradeAttempt:g})=>{const m=e();g(),m&&(console.log(`[${new Date().toISOString()}] [upgrade] Reporting success: ${m.from} \u2192 ${m.to}`),l.sendEvent({type:"event",event:"upgrade",payload:{state:"success",machineId:"self",from:m.from,to:m.to}}))}).catch(()=>{}),Ee(l,s.autoUpgrade??"patch",d),w?.handleConnected()},onDisconnected:e=>{console.log(`[${new Date().toISOString()}] \u26A0 Disconnected, reconnecting... ${ke(e)}`),v({level:"warn",wsEvent:"daemon.disconnected",metadata:{code:e.code,reason:e.reason,error:e.error,phase:e.phase,trigger:e.trigger,reconnectAttempt:e.reconnectAttempt}})},onReq:e=>{console.log(`[${new Date().toISOString()}] [req] ${e.method}`),v({level:"info",type:"ws",wsEvent:e.method,wsDirection:"in",traceId:e.traceId}),C.handleReq(e)}});w=Se()?new we(l):null;const C=new se(l,w,d);R.mkdirSync(ye,{recursive:!0}),_(process.pid,i,{version:d}),P(process.pid,void 0,i),l.connect(),process.stdin.resume();let U=!1;const A=async()=>{if(!U){U=!0,console.log(u.gray(`
|
|
2
|
+
Disconnecting...`)),v({level:"info",wsEvent:"daemon.stop"}),clearInterval(o);try{await C.cleanup(),w?.stop(),l.disconnect(),O(process.pid,i),T(i)}finally{process.exit(0)}}};process.on("SIGINT",()=>{A()}),process.on("SIGTERM",()=>{A()})});const V=a.command("config").description("View or modify configuration");V.command("show",{isDefault:!0}).description("Show current configuration").action(()=>{console.log(`Config file: ${j()}`);const t={...I()};if(t.machineToken&&(t.machineToken=t.machineToken.slice(0,12)+"..."),t.serverUrl){const o=ie(t.serverUrl);console.log(`Region: ${o} (${k[o].label})`)}console.log(JSON.stringify(t,null,2))}),V.command("set").description("Update a config value").argument("<key>",'Config key (e.g. "server")').argument("<value>",'Config value (e.g. "cn" or "global")').action((n,t)=>{const o=I();if(n==="server"){t!=="cn"&&t!=="global"&&(console.error(u.red('\u2717 Value must be "cn" or "global"')),process.exit(1));const r=t;o.serverUrl=ae(r),J(o),console.log(u.green(`\u2713 Server set to ${k[r].label}`)),console.log(u.yellow(" Restart the background service for this to take effect: shennian stop && shennian start"));return}console.error(u.red(`\u2717 Unknown config key: ${n}. Supported: server`)),process.exit(1)}),B(a),Q(a),X(a),Z(a),ee(a),ne(a),te(a),oe(a),re(a),a.parse();async function Ee(n,t,o){if(t==="none")return;let r=!1;const f=async()=>{if(r)return;let p;try{p=await le(o)}catch{return}if(!p.hasUpdate)return;const{changeType:i,current:E,latest:s}=p;if(!(t==="patch"&&i!=="patch")&&!(t==="minor"&&i==="major")&&!me(s)){console.log(`[${new Date().toISOString()}] [upgrade] ${E} \u2192 ${s} (${i}), auto-upgrading...`),r=!0;try{const{handleUpgradeStart:c}=await import("./commands/upgrade.js");await c(n,"auto-upgrade",s,{currentVersion:o})}catch(c){const y=c instanceof Error?c.message:String(c),S=pe(s,y);console.log(`[${new Date().toISOString()}] [upgrade] ${s} failed, retry after ${new Date(S.nextRetryAt).toISOString()}: ${y}`)}finally{r=!1}}};setTimeout(()=>{f()},ge),setInterval(()=>{f()},ue)}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { CliRelayClient } from '../relay/client.js';
|
|
2
|
-
import type { SessionActivitySnapshot } from '@shennian/wire';
|
|
3
2
|
export declare class NativeSessionFusionService {
|
|
4
3
|
private client;
|
|
5
4
|
private timer;
|
|
@@ -21,15 +20,6 @@ export declare class NativeSessionFusionService {
|
|
|
21
20
|
noteManagedSourceSession(sessionId: string, agentType: string, sourceSessionKey: string | null): void;
|
|
22
21
|
private pruneState;
|
|
23
22
|
scanNow(): Promise<void>;
|
|
24
|
-
getCodexThreadActivity(params: {
|
|
25
|
-
sessionId: string;
|
|
26
|
-
threadId: string;
|
|
27
|
-
workDir?: string;
|
|
28
|
-
}): Promise<SessionActivitySnapshot | null | undefined>;
|
|
29
|
-
interruptCodexThread(params: {
|
|
30
|
-
threadId: string;
|
|
31
|
-
workDir?: string;
|
|
32
|
-
}): Promise<boolean>;
|
|
33
23
|
private runScan;
|
|
34
24
|
private tryClaimManagedEcho;
|
|
35
25
|
private isSuppressed;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{randomUUID as
|
|
2
|
-
`).trim()}function
|
|
1
|
+
import{randomUUID as y}from"node:crypto";import M from"node:fs";import{listClaudeTranscriptFiles as C,listCodexRolloutFiles as w,listOpenCodeSessionFiles as A,parseClaudeTranscriptChunk as T,parseCodexRolloutChunk as x,parseOpenCodeSessionFile as I}from"./parsers.js";import{loadNativeScannerState as _,saveNativeScannerState as N}from"./state.js";const h=6e4,m=h*2,P=30*6e4,S=20;function g(c){return c.replace(/\r\n/g,`
|
|
2
|
+
`).trim()}function K(c){return c.split(/[\\/]+/).includes(".codex")}class F{client;timer=null;scanPromise=null;pendingClaims=new Map;suppressionWindows=new Map;constructor(e){this.client=e}start(){this.timer||(this.timer=setInterval(()=>{this.scanNow().catch(e=>{console.error("[native-fusion] periodic scan failed",e)})},h))}stop(){this.timer&&clearInterval(this.timer),this.timer=null}handleConnected(){this.start(),this.scanNow().catch(e=>{console.error("[native-fusion] initial scan failed",e)})}registerManagedSend(e){if(!e.canonicalMessageId)return;const s=e.sourceAgentType??e.agentType;s!=="codex"&&s!=="claude"&&s!=="opencode"||this.pendingClaims.set(e.sessionId,{sessionId:e.sessionId,agentType:e.agentType,sourceAgentType:s,canonicalMessageId:e.canonicalMessageId,text:g(e.text),createdAt:Date.now(),expiresAt:Date.now()+m,sourceSessionKey:e.sourceSessionKey??null})}noteManagedSourceSession(e,s,t){if(!t)return;const i=this.pendingClaims.get(e);i&&i.sourceAgentType===s&&(i.sourceSessionKey=t)}pruneState(){const e=Date.now();for(const[s,t]of this.pendingClaims.entries())t.expiresAt<=e&&this.pendingClaims.delete(s);for(const[s,t]of this.suppressionWindows.entries())t.endsAt<=e&&this.suppressionWindows.delete(s)}async scanNow(){if(this.client.getState()==="connected")return this.scanPromise?this.scanPromise:(this.scanPromise=this.runScan().finally(()=>{this.scanPromise=null}),this.scanPromise)}async runScan(){this.pruneState();const e=_(),s={...e.files},t=[],i=[...w(),...C(),...A()];for(const n of i){const o=M.statSync(n),r=e.files[n];if(!r){s[n]={offset:o.size,mtimeMs:o.mtimeMs};continue}const d=K(n),a=n.endsWith(".opencode-session.json"),l=a&&r?.mtimeMs!==o.mtimeMs?r.offset:r?.offset??0,f=a?I(n,l):d?x(n,l):T(n,l);s[n]={offset:f.nextOffset,mtimeMs:o.mtimeMs};for(const u of f.events){const p=this.tryClaimManagedEcho(u);if(p){t.push(p);continue}this.isSuppressed(u)||t.push(u)}}for(let n=0;n<t.length;n+=S){const o=t.slice(n,n+S);if(o.length===0)continue;const r=o.map(({repairHint:d,...a})=>a);await this.client.sendBufferedEvent({type:"event",event:"native.session.events",id:`native-fusion-${y()}`,payload:{events:r}},6e4)}e.files=s,N(e)}tryClaimManagedEcho(e){const s=Date.now();for(const[t,i]of this.pendingClaims.entries())if(i.sourceAgentType===e.agentType&&!(i.expiresAt<=s)&&e.role==="user"&&i.sourceSessionKey&&i.sourceSessionKey===e.sourceSessionKey&&!(Math.abs(e.ts-i.createdAt)>m)&&g(e.payload)===i.text)return this.pendingClaims.delete(t),this.suppressionWindows.set(`${e.agentType}:${e.sourceSessionKey}`,{sessionId:t,agentType:e.agentType,sourceSessionKey:e.sourceSessionKey,startedAt:e.ts,endsAt:Math.max(s,e.ts)+P}),{...e,sourceMode:"managed_echo_claim",claimCanonicalMessageId:i.canonicalMessageId};return null}isSuppressed(e){const s=`${e.agentType}:${e.sourceSessionKey}`,t=this.suppressionWindows.get(s);return!t||e.ts<t.startedAt?!1:e.ts>t.endsAt?(this.suppressionWindows.delete(s),!1):e.role==="user"?(this.suppressionWindows.delete(s),!1):!0}}export{F as NativeSessionFusionService};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import F from"node:os";import{createAgent as H}from"../../agents/adapter.js";import{buildApprovalPendingPayload as O,buildUserMessagePayload as G}from"@shennian/wire";import{reportLog as x}from"../../log-reporter.js";import{lookupClaudeTranscriptCwd as U}from"../../native-fusion/parsers.js";import{appendMessage as A,recordSession as
|
|
2
|
-
`),a=e>0?Math.min(e,80):Math.min(t.length,80);return t.slice(0,a)}function Z(t,e,a={}){if(t.state==="tool-call"||t.state==="tool-result"){const s={runId:t.runId,sourceSeq:t.seq};return{state:t.state,runId:t.runId,seq:t.seq,sessionId:e,detailRef:s,...t.name?{name:t.name}:{},...t.source?{source:t.source}:{},...t.agentSessionId?{agentSessionId:t.agentSessionId}:{},...a}}return{...t,sessionId:e,...a}}const ee=3e4;function te(t){return t.state==="heartbeat"?t.runPhase??null:t.state==="tool-call"||t.state==="tool-result"?"tool_running":t.state==="approval-pending"?"waiting_approval":t.state==="delta"?t.thinking?"thinking":"streaming_text":t.state==="init"||t.state==="start"?"thinking":null}function ne(t,e){const a=e instanceof Error?e.message:String(e);return t==="pi"&&(a.includes("429")||a.includes("daily_quota_exceeded")||a.includes("nian_quota_exceeded"))?a.includes("too quickly")||a.includes("per minute")?"Nian \u8BF7\u6C42\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5\u3002":"Nian \u4ECA\u65E5\u989D\u5EA6\u5DF2\u7528\u5B8C\uFF0C\u6B21\u65E5\u81EA\u52A8\u6062\u590D\u3002":`Agent send failed: ${a}`}function L(t,e){return t!=="manager"?t:e==="claude"?"claude":"codex"}function z(t,e,a){t.client.sendEvent({type:"event",event:"session.message",payload:{sessionId:e.sessionId,message:e,session:{id:e.sessionId,agentType:a.agentType,agentSessionId:a.agentSessionId??null,modelId:a.modelId??null,workDir:a.workDir,status:"active",externalChannel:j(t,e.sessionId,a.agentType)}}})}function ae(t,e){v({sessionId:e.sessionId,agentType:e.agentType,workDir:e.workDir,agentSessionId:e.agentSessionId??null,modelId:e.modelId??null}),t.client.sendEvent({type:"event",event:"session.update",payload:{session:{id:e.sessionId,agentType:e.agentType,agentSessionId:e.agentSessionId??null,modelId:e.modelId??null,workDir:e.workDir,status:"active",externalChannel:j(t,e.sessionId,e.agentType)}}})}function re(t){if(!t||typeof t!="object")return null;const e=t;return{configured:e.configured===void 0?void 0:!!e.configured,connected:!!e.connected,type:typeof e.type=="string"?e.type:null,channelId:typeof e.channelId=="string"?e.channelId:null,name:typeof e.name=="string"?e.name:null,canReply:e.canReply===void 0||e.canReply===null?null:!!e.canReply,systemPrompt:typeof e.systemPrompt=="string"?e.systemPrompt:null,wechatRpaSource:typeof e.wechatRpaSource=="string"?e.wechatRpaSource:null,wechatRpaGroups:Array.isArray(e.wechatRpaGroups)?e.wechatRpaGroups.map(a=>({name:String(a?.name||"").trim()})).filter(a=>a.name):null,pollIntervalMs:Number.isFinite(e.pollIntervalMs)?Number(e.pollIntervalMs):null,recentLimit:Number.isFinite(e.recentLimit)?Number(e.recentLimit):null,idleSeconds:Number.isFinite(e.idleSeconds)?Number(e.idleSeconds):null,forceForeground:e.forceForeground===void 0||e.forceForeground===null?null:!!e.forceForeground,noRestore:e.noRestore===void 0||e.noRestore===null?null:!!e.noRestore,downloadAttachments:e.downloadAttachments===void 0||e.downloadAttachments===null?null:!!e.downloadAttachments,downloadAttachmentsDir:typeof e.downloadAttachmentsDir=="string"?e.downloadAttachmentsDir:null}}function se(t){return!!(t?.configured??t?.connected)}function B(t){return K(t)}function W(t,e,a){return se(e)?{...Q()?.getInjectedEnv(t,null,process.cwd(),"external")??{},SHENNIAN_EXTERNAL_SESSION_ID:t,SHENNIAN_MANAGER_SESSION_ID:t,...a?.trim()?{SHENNIAN_EXTERNAL_REPLY_TARGET:a.trim()}:{}}:{}}function oe(t,e,a,s,i){t.configure?.({sessionId:e,externalChannel:s??null,env:{...B(a),...W(e,s,i)}})}function j(t,e,a){const s=t.sessions.get(e);return s?.externalChannel?s.externalChannel:a==="manager"?t.managerRuntime?.getExternalChannelStatus(e)??null:null}function ie(t,e,a){if(t!=="claude"||!a)return e;const s=e.trim();return!!s&&s.startsWith("-")&&!s.includes("/")?U(a)??e:e}function le(t,e,a,s){let i=null;function f(n,r={}){t.client.sendAgentEvent({type:"event",event:"agent",payload:Z(n,e,r),seq:n.seq,id:`agent-evt-${n.runId}-${n.seq}`})}function l(n){n?.heartbeatTimer&&(clearInterval(n.heartbeatTimer),n.heartbeatTimer=null)}function d(n){if(!n.currentRunId||!n.currentRunPhase)return;const r=n.heartbeatSeq++;t.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"heartbeat",sessionId:e,runId:n.currentRunId,seq:r,runPhase:n.currentRunPhase},seq:r,id:`agent-heartbeat-${n.currentRunId}-${r}-${Date.now()}`})}function I(n){!n||n.heartbeatTimer||(n.heartbeatTimer=setInterval(()=>{d(n)},ee),n.heartbeatTimer.unref?.())}function S(n){const r=n?.pendingTextEvent;!n||!r||!r.text||(f({state:"delta",runId:r.runId,seq:r.seq,text:r.text,thinking:r.thinking||void 0}),n.pendingTextEvent=null)}s.on("agentEvent",n=>{const r=t.sessions.get(e),R=te(n),T=n.state==="final"||n.state==="error"||n.state==="aborted";r&&(r.nextEventSeq=n.seq+1,T||(r.currentRunId=n.runId),!T&&R&&(r.currentRunPhase=R,I(r)),n.agentSessionId&&(r.agentSessionId=n.agentSessionId)),t.managerRuntime?.noteAgentEvent(e,n),n.state!=="delta"&&x({level:"info",sessionId:e,wsEvent:`agent.${n.state}`,wsDirection:"out",metadata:{runId:n.runId,seq:n.seq,agentType:a}}),n.state==="delta"&&n.text&&!n.thinking?A(e,{id:`agent-${n.runId}-${n.seq}`,sessionId:e,role:"agent",ts:Date.now(),payload:n.text}):n.state==="tool-call"||n.state==="tool-result"?A(e,{id:`agent-${n.runId}-${n.seq}`,sessionId:e,role:"agent",ts:Date.now(),payload:JSON.stringify({v:1,type:n.state==="tool-call"?"tool_use":"tool_result",name:n.name,status:n.state==="tool-call"?"running":"completed",detailRef:{runId:n.runId,sourceSeq:n.seq},args:n.args,result:n.result})}):n.state==="approval-pending"?A(e,{id:`agent-${n.runId||"run"}-${n.seq}`,sessionId:e,role:"agent",ts:Date.now(),payload:O(n.approval)}):(n.state==="error"||n.state==="aborted")&&n.message&&A(e,{id:`agent-${n.runId||"run"}-${n.seq}`,sessionId:e,role:"agent",ts:Date.now(),payload:n.message});const m=`${e}:${n.runId}`;if(n.state==="delta"&&!n.thinking&&n.text&&t.runTextAcc.set(m,(t.runTextAcc.get(m)??"")+n.text),n.agentSessionId&&n.agentSessionId!==i&&(i=n.agentSessionId,t.nativeFusion?.noteManagedSourceSession(e,L(a,n.source),n.agentSessionId),r&&v({sessionId:e,agentType:a,workDir:r.workDir,agentSessionId:n.agentSessionId}),t.client.sendEvent({type:"event",event:"session.update",payload:{session:{id:e,agentType:a,agentSessionId:n.agentSessionId}}})),n.state==="delta"){const h=n.text??"";if(!h)return;const k=!!n.thinking;r?.pendingTextEvent&&(r.pendingTextEvent.runId!==n.runId||r.pendingTextEvent.thinking!==k)&&S(r),r&&!r.pendingTextEvent&&(r.pendingTextEvent={runId:n.runId,seq:n.seq,text:"",thinking:k}),r?.pendingTextEvent&&(r.pendingTextEvent.text+=h,r.pendingTextEvent.seq=n.seq);return}let p={};if(n.state==="final"){S(r);const h=t.runTextAcc.get(m)??"";h&&(p={messageSummary:Y(h)}),t.runTextAcc.delete(m)}else n.state==="error"||n.state==="aborted"?(S(r),t.runTextAcc.delete(m)):(n.state==="tool-call"||n.state==="tool-result"||n.state==="approval-pending")&&S(r);T&&r?.currentRunId===n.runId&&(r.currentRunId=null,r.currentRunPhase=null,r.nextEventSeq=0,l(r),t.chatQueue?.noteTerminal(e)),f(n,p)}),s.on("error",n=>{console.error(`[chat.send] adapter error sessionId=${e} agentType=${a}: ${n.message}`),t.sessions.delete(e),t.chatQueue?.noteTerminal(e),t.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:e,message:n.message,runId:"",seq:0}})})}function de(t,e){if(t.processedReqIds.add(e),t.processedReqIds.size>1e3){const a=t.processedReqIds.values().next().value;t.processedReqIds.delete(a)}}async function q(t){t.heartbeatTimer&&(clearInterval(t.heartbeatTimer),t.heartbeatTimer=null),t.adapter.removeAllListeners(),await t.adapter.stop().catch(()=>{})}async function ce(t,e,a,s,i,f,l){t.evictIdleSessions();const d=H(a);if(!d)throw new Error(`Unsupported agent: ${a}`);oe(d,e,a,f,l),await d.start(e,s,i);const I={adapter:d,workDir:s,agentType:a,agentSessionId:i??null,lastActiveAt:Date.now(),currentRunId:null,currentRunPhase:null,nextEventSeq:0,heartbeatSeq:0,heartbeatTimer:null,pendingTextEvent:null,externalChannel:f??null,externalReplyTarget:l??null,externalChannelEnv:{...B(a),...W(e,f,l)}};return t.sessions.set(e,I),le(t,e,a,d),I}function ue(t,e){const a=t.sessions.get(e),s=a?.currentRunId;if(!a||!s)return;const i=a.nextEventSeq;t.runTextAcc.delete(`${e}:${s}`),a.pendingTextEvent=null,a.currentRunId=null,a.currentRunPhase=null,a.nextEventSeq=0,a.heartbeatTimer&&(clearInterval(a.heartbeatTimer),a.heartbeatTimer=null),t.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"aborted",sessionId:e,runId:s,seq:i},seq:i,id:`agent-evt-${s}-${i}`}),t.chatQueue?.noteTerminal(e)}async function Ae(t,e){if(t.processedReqIds.has(e.id)){t.client.sendRes({type:"res",id:e.id,ok:!0});return}de(t,e.id);const{sessionId:a,text:s,agentType:i,workDir:f,agentSessionId:l,modelId:d,managerDefaultWorkerAgentType:I,managerDefaultWorkerModelId:S,reasoningEffort:n,clientMessageId:r,sessionListProjection:R,waitForDispatch:T,responseId:m}=e.params,p=m||e.id;J(R);const h=re(e.params.externalChannel),k=typeof e.params.replyTarget=="string"?e.params.replyTarget.trim():"";if(!a||!s){t.processedReqIds.delete(e.id),t.client.sendRes({type:"res",id:p,ok:!1,error:"sessionId and text are required"});return}const u=i;u==="manager"&&t.managerRuntime?.setManagerWorkerDefaults(a,I??null,S??null);const y=(u==="claude"||u==="codex")&&typeof n=="string"&&n.trim()?n.trim():void 0,E=t.resolvePath(ie(u,f||F.homedir(),l)||F.homedir()),D=E,$=X(e.params.attachments),g=$?.length?await V({text:s,attachments:$,workDir:E}):{text:s,attachments:$,localized:!1};let o=t.sessions.get(a);if(o){if(o.lastActiveAt=Date.now(),o.agentType!==u||o.workDir!==E||JSON.stringify(o.externalChannel??null)!==JSON.stringify(h??null)){t.sessions.delete(a);try{await q(o)}catch{t.processedReqIds.delete(e.id)}o=void 0}else if(l&&o.agentSessionId!==l)try{await o.adapter.resume(l),o.agentSessionId=l}catch{t.sessions.delete(a);try{await q(o)}catch{t.processedReqIds.delete(e.id)}o=void 0}}if(!o)try{o=await ce(t,a,u,E,l,h,k)}catch(c){const w=c instanceof Error&&c.message.startsWith("Unsupported agent:")?c.message:`Failed to start ${i}: ${c instanceof Error?c.message:String(c)}`;console.error(`[chat.send] start failed reqId=${e.id} sessionId=${a} agentType=${i} workDir=${E} agentSessionId=${l??""}: ${w}`),t.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:a,message:w,runId:"",seq:0}}),t.processedReqIds.delete(e.id),t.client.sendRes({type:"res",id:p,ok:!1,error:w});return}const N={id:r??`user-${e.id}`,sessionId:a,role:"user",ts:Date.now(),payload:G(g.text,g.attachments)};x({level:"info",sessionId:a,wsEvent:"chat.send.start",metadata:{reqId:e.id,agentType:u,modelId:d,reasoningEffort:y}});const P=()=>{ae(t,{sessionId:a,agentType:u,workDir:D,agentSessionId:o.agentSessionId??l??null,modelId:d}),o.currentRunId||(o.nextEventSeq=0),t.nativeFusion?.registerManagedSend({sessionId:a,agentType:u,sourceAgentType:L(u,d),canonicalMessageId:r??null,sourceSessionKey:o.agentSessionId??l??null,text:g.text}),A(a,N),z(t,N,{agentType:u,workDir:D,agentSessionId:o.agentSessionId??l??null,modelId:d})},_=async(c,w)=>{const b=ne(u,c);console.error(`[chat.send] send failed reqId=${e.id} sessionId=${a} agentType=${i} workDir=${E} agentSessionId=${o.agentSessionId??l??""}: ${b}`),t.sessions.delete(a);try{await q(o)}catch{}if(t.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:a,message:b,runId:"",seq:0}}),!w){const M={id:`agent-error-${e.id}-${Date.now()}`,sessionId:a,role:"agent",ts:Date.now(),payload:b};A(a,M),z(t,M,{agentType:u,workDir:D,agentSessionId:o.agentSessionId??l??null,modelId:d})}w&&(t.processedReqIds.delete(e.id),t.client.sendRes({type:"res",id:p,ok:!1,error:b}))};if(T){try{const c=g.attachments;c?.length?await o.adapter.send(g.text,d,y,c):y?await o.adapter.send(g.text,d,y):await o.adapter.send(g.text,d),x({level:"info",sessionId:a,wsEvent:"chat.send.done",metadata:{reqId:e.id}})}catch(c){await _(c,!0);return}P(),t.client.sendRes({type:"res",id:p,ok:!0,...g.localized?{payload:{localizedAttachments:!0}}:{}}),x({level:"info",sessionId:a,wsEvent:"chat.send.res",metadata:{reqId:e.id,ok:!0}});return}P(),t.client.sendRes({type:"res",id:p,ok:!0,...g.localized?{payload:{localizedAttachments:!0}}:{}}),x({level:"info",sessionId:a,wsEvent:"chat.send.res",metadata:{reqId:e.id,ok:!0}});const C=g.attachments;(C?.length?o.adapter.send(g.text,d,y,C):y?o.adapter.send(g.text,d,y):o.adapter.send(g.text,d)).then(()=>{x({level:"info",sessionId:a,wsEvent:"chat.send.done",metadata:{reqId:e.id}})}).catch(c=>{_(c,!1)})}async function Te(t,e){const{sessionId:a}=e.params,s=t.sessions.get(a);if(s){try{await s.adapter.stop()}catch{}ue(t,a),t.activityPublisher?.publish(a,null)}else{const i=e.params;i.agentType==="codex"&&i.agentSessionId&&t.nativeFusion&&await t.nativeFusion.interruptCodexThread({threadId:i.agentSessionId,workDir:i.workDir})&&t.activityPublisher?.publish(a,null)}t.client.sendRes({type:"res",id:e.id,ok:!0})}export{Te as handleChatAbort,Ae as handleChatSend};
|
|
1
|
+
import F from"node:os";import{createAgent as H}from"../../agents/adapter.js";import{buildApprovalPendingPayload as O,buildUserMessagePayload as G}from"@shennian/wire";import{reportLog as x}from"../../log-reporter.js";import{lookupClaudeTranscriptCwd as U}from"../../native-fusion/parsers.js";import{appendMessage as A,recordSession as L}from"../store.js";import{mergeProjectedSessions as J}from"../projection.js";import{getManagerRuntimeService as Q}from"../../manager/runtime.js";import{buildManagedAgentEnv as K}from"../../agents/config-status.js";import{materializeRemoteChatAttachments as V}from"../remote-attachments.js";function X(t){if(!Array.isArray(t))return;const e=t.map(a=>{if(!a||typeof a!="object")return null;const s=a,d=typeof s.path=="string"?s.path:"",f=typeof s.name=="string"?s.name:"",l=typeof s.mimeType=="string"?s.mimeType:"";if(!d||!f||!l)return null;const i=typeof s.previewData=="string"&&s.previewData.trim()?s.previewData.trim():void 0;return{path:d,name:f,mimeType:l,kind:l.startsWith("image/")?"image":"file",...i?{previewData:i}:{}}}).filter(a=>a!=null);return e.length?e:void 0}function Y(t){const e=t.indexOf(`
|
|
2
|
+
`),a=e>0?Math.min(e,80):Math.min(t.length,80);return t.slice(0,a)}function Z(t,e,a={}){if(t.state==="tool-call"||t.state==="tool-result"){const s={runId:t.runId,sourceSeq:t.seq};return{state:t.state,runId:t.runId,seq:t.seq,sessionId:e,detailRef:s,...t.name?{name:t.name}:{},...t.source?{source:t.source}:{},...t.agentSessionId?{agentSessionId:t.agentSessionId}:{},...a}}return{...t,sessionId:e,...a}}const ee=3e4;function te(t){return t.state==="heartbeat"?t.runPhase??null:t.state==="tool-call"||t.state==="tool-result"?"tool_running":t.state==="approval-pending"?"waiting_approval":t.state==="delta"?t.thinking?"thinking":"streaming_text":t.state==="init"||t.state==="start"?"thinking":null}function ne(t,e){const a=e instanceof Error?e.message:String(e);return t==="pi"&&(a.includes("429")||a.includes("daily_quota_exceeded")||a.includes("nian_quota_exceeded"))?a.includes("too quickly")||a.includes("per minute")?"Nian \u8BF7\u6C42\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5\u3002":"Nian \u4ECA\u65E5\u989D\u5EA6\u5DF2\u7528\u5B8C\uFF0C\u6B21\u65E5\u81EA\u52A8\u6062\u590D\u3002":`Agent send failed: ${a}`}function v(t,e){return t!=="manager"?t:e==="claude"?"claude":"codex"}function z(t,e,a){t.client.sendEvent({type:"event",event:"session.message",payload:{sessionId:e.sessionId,message:e,session:{id:e.sessionId,agentType:a.agentType,agentSessionId:a.agentSessionId??null,modelId:a.modelId??null,workDir:a.workDir,status:"active",externalChannel:j(t,e.sessionId,a.agentType)}}})}function ae(t,e){L({sessionId:e.sessionId,agentType:e.agentType,workDir:e.workDir,agentSessionId:e.agentSessionId??null,modelId:e.modelId??null}),t.client.sendEvent({type:"event",event:"session.update",payload:{session:{id:e.sessionId,agentType:e.agentType,agentSessionId:e.agentSessionId??null,modelId:e.modelId??null,workDir:e.workDir,status:"active",externalChannel:j(t,e.sessionId,e.agentType)}}})}function re(t){if(!t||typeof t!="object")return null;const e=t;return{configured:e.configured===void 0?void 0:!!e.configured,connected:!!e.connected,type:typeof e.type=="string"?e.type:null,channelId:typeof e.channelId=="string"?e.channelId:null,name:typeof e.name=="string"?e.name:null,canReply:e.canReply===void 0||e.canReply===null?null:!!e.canReply,systemPrompt:typeof e.systemPrompt=="string"?e.systemPrompt:null,wechatRpaSource:typeof e.wechatRpaSource=="string"?e.wechatRpaSource:null,wechatRpaGroups:Array.isArray(e.wechatRpaGroups)?e.wechatRpaGroups.map(a=>({name:String(a?.name||"").trim()})).filter(a=>a.name):null,pollIntervalMs:Number.isFinite(e.pollIntervalMs)?Number(e.pollIntervalMs):null,recentLimit:Number.isFinite(e.recentLimit)?Number(e.recentLimit):null,idleSeconds:Number.isFinite(e.idleSeconds)?Number(e.idleSeconds):null,forceForeground:e.forceForeground===void 0||e.forceForeground===null?null:!!e.forceForeground,noRestore:e.noRestore===void 0||e.noRestore===null?null:!!e.noRestore,downloadAttachments:e.downloadAttachments===void 0||e.downloadAttachments===null?null:!!e.downloadAttachments,downloadAttachmentsDir:typeof e.downloadAttachmentsDir=="string"?e.downloadAttachmentsDir:null}}function se(t){return!!(t?.configured??t?.connected)}function B(t){return K(t)}function W(t,e,a){return se(e)?{...Q()?.getInjectedEnv(t,null,process.cwd(),"external")??{},SHENNIAN_EXTERNAL_SESSION_ID:t,SHENNIAN_MANAGER_SESSION_ID:t,...a?.trim()?{SHENNIAN_EXTERNAL_REPLY_TARGET:a.trim()}:{}}:{}}function oe(t,e,a,s,d){t.configure?.({sessionId:e,externalChannel:s??null,env:{...B(a),...W(e,s,d)}})}function j(t,e,a){const s=t.sessions.get(e);return s?.externalChannel?s.externalChannel:a==="manager"?t.managerRuntime?.getExternalChannelStatus(e)??null:null}function le(t,e,a){if(t!=="claude"||!a)return e;const s=e.trim();return!!s&&s.startsWith("-")&&!s.includes("/")?U(a)??e:e}function ie(t,e,a,s){let d=null;function f(n,r={}){t.client.sendAgentEvent({type:"event",event:"agent",payload:Z(n,e,r),seq:n.seq,id:`agent-evt-${n.runId}-${n.seq}`})}function l(n){n?.heartbeatTimer&&(clearInterval(n.heartbeatTimer),n.heartbeatTimer=null)}function i(n){if(!n.currentRunId||!n.currentRunPhase)return;const r=n.heartbeatSeq++;t.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"heartbeat",sessionId:e,runId:n.currentRunId,seq:r,runPhase:n.currentRunPhase},seq:r,id:`agent-heartbeat-${n.currentRunId}-${r}-${Date.now()}`})}function I(n){!n||n.heartbeatTimer||(n.heartbeatTimer=setInterval(()=>{i(n)},ee),n.heartbeatTimer.unref?.())}function S(n){const r=n?.pendingTextEvent;!n||!r||!r.text||(f({state:"delta",runId:r.runId,seq:r.seq,text:r.text,thinking:r.thinking||void 0}),n.pendingTextEvent=null)}s.on("agentEvent",n=>{const r=t.sessions.get(e),T=te(n),R=n.state==="final"||n.state==="error"||n.state==="aborted";r&&(r.nextEventSeq=n.seq+1,R||(r.currentRunId=n.runId),!R&&T&&(r.currentRunPhase=T,I(r)),n.agentSessionId&&(r.agentSessionId=n.agentSessionId)),t.managerRuntime?.noteAgentEvent(e,n),n.state!=="delta"&&x({level:"info",sessionId:e,wsEvent:`agent.${n.state}`,wsDirection:"out",metadata:{runId:n.runId,seq:n.seq,agentType:a}}),n.state==="delta"&&n.text&&!n.thinking?A(e,{id:`agent-${n.runId}-${n.seq}`,sessionId:e,role:"agent",ts:Date.now(),payload:n.text}):n.state==="tool-call"||n.state==="tool-result"?A(e,{id:`agent-${n.runId}-${n.seq}`,sessionId:e,role:"agent",ts:Date.now(),payload:JSON.stringify({v:1,type:n.state==="tool-call"?"tool_use":"tool_result",name:n.name,status:n.state==="tool-call"?"running":"completed",detailRef:{runId:n.runId,sourceSeq:n.seq},args:n.args,result:n.result})}):n.state==="approval-pending"?A(e,{id:`agent-${n.runId||"run"}-${n.seq}`,sessionId:e,role:"agent",ts:Date.now(),payload:O(n.approval)}):(n.state==="error"||n.state==="aborted")&&n.message&&A(e,{id:`agent-${n.runId||"run"}-${n.seq}`,sessionId:e,role:"agent",ts:Date.now(),payload:n.message});const h=`${e}:${n.runId}`;if(n.state==="delta"&&!n.thinking&&n.text&&t.runTextAcc.set(h,(t.runTextAcc.get(h)??"")+n.text),n.agentSessionId&&n.agentSessionId!==d&&(d=n.agentSessionId,t.nativeFusion?.noteManagedSourceSession(e,v(a,n.source),n.agentSessionId),r&&L({sessionId:e,agentType:a,workDir:r.workDir,agentSessionId:n.agentSessionId}),t.client.sendEvent({type:"event",event:"session.update",payload:{session:{id:e,agentType:a,agentSessionId:n.agentSessionId}}})),n.state==="delta"){const m=n.text??"";if(!m)return;const b=!!n.thinking;r?.pendingTextEvent&&(r.pendingTextEvent.runId!==n.runId||r.pendingTextEvent.thinking!==b)&&S(r),r&&!r.pendingTextEvent&&(r.pendingTextEvent={runId:n.runId,seq:n.seq,text:"",thinking:b}),r?.pendingTextEvent&&(r.pendingTextEvent.text+=m,r.pendingTextEvent.seq=n.seq);return}let p={};if(n.state==="final"){S(r);const m=t.runTextAcc.get(h)??"";m&&(p={messageSummary:Y(m)}),t.runTextAcc.delete(h)}else n.state==="error"||n.state==="aborted"?(S(r),t.runTextAcc.delete(h)):(n.state==="tool-call"||n.state==="tool-result"||n.state==="approval-pending")&&S(r);R&&r?.currentRunId===n.runId&&(r.currentRunId=null,r.currentRunPhase=null,r.nextEventSeq=0,l(r),t.chatQueue?.noteTerminal(e)),f(n,p)}),s.on("error",n=>{console.error(`[chat.send] adapter error sessionId=${e} agentType=${a}: ${n.message}`),t.sessions.delete(e),t.chatQueue?.noteTerminal(e),t.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:e,message:n.message,runId:"",seq:0}})})}function de(t,e){if(t.processedReqIds.add(e),t.processedReqIds.size>1e3){const a=t.processedReqIds.values().next().value;t.processedReqIds.delete(a)}}async function q(t){t.heartbeatTimer&&(clearInterval(t.heartbeatTimer),t.heartbeatTimer=null),t.adapter.removeAllListeners(),await t.adapter.stop().catch(()=>{})}async function ce(t,e,a,s,d,f,l){t.evictIdleSessions();const i=H(a);if(!i)throw new Error(`Unsupported agent: ${a}`);oe(i,e,a,f,l),await i.start(e,s,d);const I={adapter:i,workDir:s,agentType:a,agentSessionId:d??null,lastActiveAt:Date.now(),currentRunId:null,currentRunPhase:null,nextEventSeq:0,heartbeatSeq:0,heartbeatTimer:null,pendingTextEvent:null,externalChannel:f??null,externalReplyTarget:l??null,externalChannelEnv:{...B(a),...W(e,f,l)}};return t.sessions.set(e,I),ie(t,e,a,i),I}function ue(t,e){const a=t.sessions.get(e),s=a?.currentRunId;if(!a||!s)return;const d=a.nextEventSeq;t.runTextAcc.delete(`${e}:${s}`),a.pendingTextEvent=null,a.currentRunId=null,a.currentRunPhase=null,a.nextEventSeq=0,a.heartbeatTimer&&(clearInterval(a.heartbeatTimer),a.heartbeatTimer=null),t.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"aborted",sessionId:e,runId:s,seq:d},seq:d,id:`agent-evt-${s}-${d}`}),t.chatQueue?.noteTerminal(e)}async function Ae(t,e){if(t.processedReqIds.has(e.id)){t.client.sendRes({type:"res",id:e.id,ok:!0});return}de(t,e.id);const{sessionId:a,text:s,agentType:d,workDir:f,agentSessionId:l,modelId:i,managerDefaultWorkerAgentType:I,managerDefaultWorkerModelId:S,reasoningEffort:n,clientMessageId:r,sessionListProjection:T,waitForDispatch:R,responseId:h}=e.params,p=h||e.id;J(T);const m=re(e.params.externalChannel),b=typeof e.params.replyTarget=="string"?e.params.replyTarget.trim():"";if(!a||!s){t.processedReqIds.delete(e.id),t.client.sendRes({type:"res",id:p,ok:!1,error:"sessionId and text are required"});return}const u=d;u==="manager"&&t.managerRuntime?.setManagerWorkerDefaults(a,I??null,S??null);const y=(u==="claude"||u==="codex")&&typeof n=="string"&&n.trim()?n.trim():void 0,E=t.resolvePath(le(u,f||F.homedir(),l)||F.homedir()),$=E,D=X(e.params.attachments),g=D?.length?await V({text:s,attachments:D,workDir:E}):{text:s,attachments:D,localized:!1};let o=t.sessions.get(a);if(o){if(o.lastActiveAt=Date.now(),o.agentType!==u||o.workDir!==E||JSON.stringify(o.externalChannel??null)!==JSON.stringify(m??null)){t.sessions.delete(a);try{await q(o)}catch{t.processedReqIds.delete(e.id)}o=void 0}else if(l&&o.agentSessionId!==l)try{await o.adapter.resume(l),o.agentSessionId=l}catch{t.sessions.delete(a);try{await q(o)}catch{t.processedReqIds.delete(e.id)}o=void 0}}if(!o)try{o=await ce(t,a,u,E,l,m,b)}catch(c){const w=c instanceof Error&&c.message.startsWith("Unsupported agent:")?c.message:`Failed to start ${d}: ${c instanceof Error?c.message:String(c)}`;console.error(`[chat.send] start failed reqId=${e.id} sessionId=${a} agentType=${d} workDir=${E} agentSessionId=${l??""}: ${w}`),t.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:a,message:w,runId:"",seq:0}}),t.processedReqIds.delete(e.id),t.client.sendRes({type:"res",id:p,ok:!1,error:w});return}const N={id:r??`user-${e.id}`,sessionId:a,role:"user",ts:Date.now(),payload:G(g.text,g.attachments)};x({level:"info",sessionId:a,wsEvent:"chat.send.start",metadata:{reqId:e.id,agentType:u,modelId:i,reasoningEffort:y}});const P=()=>{ae(t,{sessionId:a,agentType:u,workDir:$,agentSessionId:o.agentSessionId??l??null,modelId:i}),o.currentRunId||(o.nextEventSeq=0),t.nativeFusion?.registerManagedSend({sessionId:a,agentType:u,sourceAgentType:v(u,i),canonicalMessageId:r??null,sourceSessionKey:o.agentSessionId??l??null,text:g.text}),A(a,N),z(t,N,{agentType:u,workDir:$,agentSessionId:o.agentSessionId??l??null,modelId:i})},_=async(c,w)=>{const k=ne(u,c);console.error(`[chat.send] send failed reqId=${e.id} sessionId=${a} agentType=${d} workDir=${E} agentSessionId=${o.agentSessionId??l??""}: ${k}`),t.sessions.delete(a);try{await q(o)}catch{}if(t.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:a,message:k,runId:"",seq:0}}),!w){const M={id:`agent-error-${e.id}-${Date.now()}`,sessionId:a,role:"agent",ts:Date.now(),payload:k};A(a,M),z(t,M,{agentType:u,workDir:$,agentSessionId:o.agentSessionId??l??null,modelId:i})}w&&(t.processedReqIds.delete(e.id),t.client.sendRes({type:"res",id:p,ok:!1,error:k}))};if(R){try{const c=g.attachments;c?.length?await o.adapter.send(g.text,i,y,c):y?await o.adapter.send(g.text,i,y):await o.adapter.send(g.text,i),x({level:"info",sessionId:a,wsEvent:"chat.send.done",metadata:{reqId:e.id}})}catch(c){await _(c,!0);return}P(),t.client.sendRes({type:"res",id:p,ok:!0,...g.localized?{payload:{localizedAttachments:!0}}:{}}),x({level:"info",sessionId:a,wsEvent:"chat.send.res",metadata:{reqId:e.id,ok:!0}});return}P(),t.client.sendRes({type:"res",id:p,ok:!0,...g.localized?{payload:{localizedAttachments:!0}}:{}}),x({level:"info",sessionId:a,wsEvent:"chat.send.res",metadata:{reqId:e.id,ok:!0}});const C=g.attachments;(C?.length?o.adapter.send(g.text,i,y,C):y?o.adapter.send(g.text,i,y):o.adapter.send(g.text,i)).then(()=>{x({level:"info",sessionId:a,wsEvent:"chat.send.done",metadata:{reqId:e.id}})}).catch(c=>{_(c,!1)})}async function Re(t,e){const{sessionId:a}=e.params,s=t.sessions.get(a);if(s){try{await s.adapter.stop()}catch{}ue(t,a),t.activityPublisher?.publish(a,null)}t.client.sendRes({type:"res",id:e.id,ok:!0})}export{Re as handleChatAbort,Ae as handleChatSend};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
async function a(s,
|
|
1
|
+
async function a(s,e){const n=e.params;if(!n.sessionId){s.client.sendRes({type:"res",id:e.id,ok:!1,error:"sessionId is required"});return}if(!s.nativeFusion){s.client.sendRes({type:"res",id:e.id,ok:!0,payload:{scanned:!1}});return}await s.nativeFusion.scanNow(),s.client.sendRes({type:"res",id:e.id,ok:!0,payload:{scanned:!0,sessionId:n.sessionId,agentType:n.agentType??null,agentSessionId:n.agentSessionId??null}})}export{a as handleSessionRefresh};
|