shennian 0.5.16 → 0.5.18
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 +20 -15
- package/dist/src/commands/contact.js +3 -0
- package/dist/src/index.js +3 -3
- package/dist/src/room/public-room-client.js +1 -1
- package/dist/src/session/handlers/chat-events.js +2 -2
- package/dist/src/session/handlers/steward.js +1 -1
- package/dist/src/skill/hosts.js +1 -1
- package/dist/src/skill/updater.js +1 -1
- package/dist/src/steward/failover.js +1 -1
- package/node_modules/@shennian/wire/dist/message-payload.js +3 -3
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"jsMinified": true,
|
|
4
4
|
"minifier": "esbuild",
|
|
5
|
-
"fileCount":
|
|
5
|
+
"fileCount": 280,
|
|
6
6
|
"files": [
|
|
7
7
|
{
|
|
8
8
|
"file": "bin/shennian-adapter-host.js",
|
|
@@ -434,6 +434,11 @@
|
|
|
434
434
|
"beforeBytes": 963,
|
|
435
435
|
"afterBytes": 465
|
|
436
436
|
},
|
|
437
|
+
{
|
|
438
|
+
"file": "src/commands/contact.js",
|
|
439
|
+
"beforeBytes": 2049,
|
|
440
|
+
"afterBytes": 1217
|
|
441
|
+
},
|
|
437
442
|
{
|
|
438
443
|
"file": "src/commands/daemon-instance-lock.js",
|
|
439
444
|
"beforeBytes": 4507,
|
|
@@ -661,8 +666,8 @@
|
|
|
661
666
|
},
|
|
662
667
|
{
|
|
663
668
|
"file": "src/index.js",
|
|
664
|
-
"beforeBytes":
|
|
665
|
-
"afterBytes":
|
|
669
|
+
"beforeBytes": 46996,
|
|
670
|
+
"afterBytes": 23133
|
|
666
671
|
},
|
|
667
672
|
{
|
|
668
673
|
"file": "src/log-redaction.js",
|
|
@@ -931,8 +936,8 @@
|
|
|
931
936
|
},
|
|
932
937
|
{
|
|
933
938
|
"file": "src/room/public-room-client.js",
|
|
934
|
-
"beforeBytes":
|
|
935
|
-
"afterBytes":
|
|
939
|
+
"beforeBytes": 7119,
|
|
940
|
+
"afterBytes": 4117
|
|
936
941
|
},
|
|
937
942
|
{
|
|
938
943
|
"file": "src/room/registration-authority.js",
|
|
@@ -1091,8 +1096,8 @@
|
|
|
1091
1096
|
},
|
|
1092
1097
|
{
|
|
1093
1098
|
"file": "src/session/handlers/chat-events.js",
|
|
1094
|
-
"beforeBytes":
|
|
1095
|
-
"afterBytes":
|
|
1099
|
+
"beforeBytes": 20267,
|
|
1100
|
+
"afterBytes": 8130
|
|
1096
1101
|
},
|
|
1097
1102
|
{
|
|
1098
1103
|
"file": "src/session/handlers/chat-recovery.js",
|
|
@@ -1146,8 +1151,8 @@
|
|
|
1146
1151
|
},
|
|
1147
1152
|
{
|
|
1148
1153
|
"file": "src/session/handlers/steward.js",
|
|
1149
|
-
"beforeBytes":
|
|
1150
|
-
"afterBytes":
|
|
1154
|
+
"beforeBytes": 8421,
|
|
1155
|
+
"afterBytes": 3939
|
|
1151
1156
|
},
|
|
1152
1157
|
{
|
|
1153
1158
|
"file": "src/session/handlers/title.js",
|
|
@@ -1306,18 +1311,18 @@
|
|
|
1306
1311
|
},
|
|
1307
1312
|
{
|
|
1308
1313
|
"file": "src/skill/hosts.js",
|
|
1309
|
-
"beforeBytes":
|
|
1310
|
-
"afterBytes":
|
|
1314
|
+
"beforeBytes": 4285,
|
|
1315
|
+
"afterBytes": 1940
|
|
1311
1316
|
},
|
|
1312
1317
|
{
|
|
1313
1318
|
"file": "src/skill/updater.js",
|
|
1314
|
-
"beforeBytes":
|
|
1315
|
-
"afterBytes":
|
|
1319
|
+
"beforeBytes": 19384,
|
|
1320
|
+
"afterBytes": 9616
|
|
1316
1321
|
},
|
|
1317
1322
|
{
|
|
1318
1323
|
"file": "src/steward/failover.js",
|
|
1319
|
-
"beforeBytes":
|
|
1320
|
-
"afterBytes":
|
|
1324
|
+
"beforeBytes": 4394,
|
|
1325
|
+
"afterBytes": 2607
|
|
1321
1326
|
},
|
|
1322
1327
|
{
|
|
1323
1328
|
"file": "src/steward/session.js",
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{PublicRoomClient as s,PublicRoomClientError as n}from"../room/public-room-client.js";import{MANAGED_ROOM_CONTEXT_ENV as m}from"../room/managed-context.js";function f(i,c={}){const r=c.client??new s,o=c.io??{write:a=>process.stdout.write(a),fail:()=>{process.exitCode=1}};i.command("contact").description("Read the paired user's saved contacts").command("list").description("List saved contacts and owned Agents; not inferred from Room chats").option("--query <name>","Filter by display name (up to 80 characters)").action(async a=>{try{if(process.env[m]?.trim())throw new n("managed_room_action_forbidden","Contacts are not available in managed Room context.",{type:"ask_user",message:"A managed Agent cannot use the paired human identity."});const t=a.query?.trim();if(t&&t.length>80)throw new n("invalid_contact_query","--query must be at most 80 characters.");const e=await r.listContacts(t);o.write(`${JSON.stringify({ok:!0,command:"contact.list",result:e})}
|
|
2
|
+
`)}catch(t){const e=t instanceof n?t:new n("contact_command_failed","Shennian contact command failed.");o.write(`${JSON.stringify({ok:!1,error:e.code,message:e.message,nextAction:e.nextAction})}
|
|
3
|
+
`),o.fail()}})}export{f as registerContactCommand};
|
package/dist/src/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{registerScheduleCommand as be}from"./commands/schedule.js";import{resolvePersonalScheduleContext as
|
|
2
|
-
`),process.exitCode=1}function dn(i){const c=[`trigger=${i.trigger??"unknown"}`,`phase=${i.phase}`,`code=${i.code??"unknown"}`,`attempt=${i.reconnectAttempt}`];return i.reason&&c.push(`reason=${i.reason}`),i.error&&c.push(`error=${i.error}`),c.join(" ")}const a=new Pe;a.name("shennian").description("Shennian \u2014 AI Agent Control Plane").version(U),a.enablePositionalOptions(),so(a),co(a),lo(a),be(a),a.option("--api <url>","Server URL override").option("--name <name>","Machine name",Ee.hostname()).action(async i=>{const c=p(),g=i.api??process.env.SHENNIAN_DESKTOP_SERVER_URL??c.serverUrl??void 0;await Le(g,i.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 i=>{const c=J("env.json");try{const e=JSON.parse(z.readFileSync(c,"utf-8"));for(const[n,o]of Object.entries(e))process.env[n]||(process.env[n]=o);ue()}catch{}xe(ae(process.env,p()));const g=To();ce()&&(console.log(`[${new Date().toISOString()}] remote access disabled, service start skipped`),clearInterval(g),process.exit(0));const d=je(),C=Ro({lockPath:an,instanceId:d});C.acquired||(console.log(`[${new Date().toISOString()}] daemon already running`+(C.ownerPid?` (PID ${C.ownerPid})`:"")+", skipping duplicate start"),clearInterval(g),process.exit(0));try{const e=sn();if(e&&e!==process.pid)try{process.kill(e,0),console.log(`[${new Date().toISOString()}] daemon already running (PID ${e}), skipping duplicate start`),C.release(),process.exit(0)}catch{}}catch{}const Y=We(process.env,ye)?[]:He(process.pid);Y.length>0&&(console.log(`[${new Date().toISOString()}] daemon already running (PID ${Y[0]}), skipping duplicate start`),C.release(),process.exit(0)),le(process.pid,d,{version:U}),me(process.pid,void 0,d),process.on("exit",()=>{ie(process.pid,d),se(d)}),process.on("exit",C.release);let j=null;try{j=So()}catch(e){console.error(`[upgrade] updater bootstrap unavailable: ${e instanceof Error?e.message:String(e)}`)}const M=await ho();if(M){j||(console.error("[upgrade] Crash-loop rollback blocked: updater bootstrap unavailable"),process.exit(1));try{yo({fromVersion:U,targetVersion:M.from,oldDaemonPid:process.pid,operation:"rollback",rollbackJobId:M.jobId},{readiness:j}),console.error(`[upgrade] New version crashed ${M.attemptCount} times; external rollback scheduled.`),process.stdin.resume();return}catch(e){console.error(`[upgrade] Crash-loop rollback could not start: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}}try{on()}catch(e){console.error(`[personal-sync] data epoch initialization failed: ${e instanceof Error?e.message:String(e)}`),process.exitCode=1;return}const m=p(),u=i.api??process.env.SHENNIAN_DESKTOP_SERVER_URL??m.serverUrl??K.cn.url,h=pe(),l=await ge({serverUrl:u,authToken:m.machineToken??m.accessToken}),S=l.map(e=>e.type);let H=V(l);const f=new Oo,_=new Vo,b=new Qo(f),y=new $o(u),Ce=new Jo({actionClient:y}),Re=new Ko({actionClient:y});let w=null,r;const Z=Yo({authority:b,actionClient:y,attachmentCache:Ce,attachmentUploader:Re,observations:_,getMachineCredentials:()=>({machineToken:p().machineToken}),managerExecutor:e=>r.executeManagedManagerAction(e),onSendOutcome:e=>r.noteManagedRoomSendOutcome(e),getActiveRunId:(e,n)=>r.getManagedRoomActiveRunId(e,n),scheduleExecutor:(e,n,o)=>re({serverUrl:u,machineToken:p().machineToken,sessionId:e,action:n,args:o}),onPaused:({registryKey:e,sessionId:n})=>{const t=f.getByRegistryKey(e)?.binding;t&&f.setBinding({registryKey:e,bindingId:t.bindingId,roomId:t.roomId,agentIdentityId:t.agentIdentityId,agentMembershipId:t.agentMembershipId,status:"paused",activationMode:"paused"}),b.revokeSession(e),r?.discardPendingManagedRoomMessages(n)}});let F=null,B=null,W=null,G=null,X=!1;const k=await fe({paths:Uo(),handlers:{...Mo({daemonVersion:h,protocolVersion:xo,getStatus:()=>de(),getAgents:()=>l,requestShutdown:()=>{G?G():X=!0},completeAgentAuthentication:e=>r.resumePendingAcpAuthentication(e),bindManagedRoom:e=>r.bindManagedRoomFromLocal(e),stewardSay:e=>r.stewardSayFromLocal(e),startUpgrade:async e=>{if(!F)throw new Error("upgrade_unavailable");return F(e)},prepareExternalUpgrade:e=>{if(!B)throw new Error("external_upgrade_unavailable");return B(e)},cancelExternalUpgrade:()=>{if(!W)throw new Error("external_upgrade_unavailable");return W()}}),..._o({getStatus:()=>de(),getSnapshot:()=>V(l).map(e=>{const n=l.find(o=>o.type===e.type);return{...e,runtimePlatform:n?.runtimePlatform,runtimeIsWsl:n?.runtimeIsWsl}}),getUnavailable:ao,discover:async e=>{if(!r)throw new Error("daemon_starting");const n=await he(!0,e);if(e){const t=l.filter(I=>I.type!==e);l.splice(0,l.length,...t,...n.detectedAgents)}else l.splice(0,l.length,...n.detectedAgents);const o=V(l);return s.sendEvent({type:"event",event:"machine.agents",payload:{agentList:l.map(t=>t.type),agents:o}}),n.agents.map(t=>{const I=n.detectedAgents.find(q=>q.type===t.type);return{...t,runtimePlatform:I?.runtimePlatform,runtimeIsWsl:I?.runtimeIsWsl}})},validate:async e=>{if(!r)throw new Error("daemon_starting");return No(e,{ignoreNativeSession:(n,o)=>P?.ignoreNativeSource(n,o)})}})}});let A;try{A=await fe({paths:Do(),handlers:{"managed-room.execute":e=>Z(e),"schedule.personal":async e=>{const n=e,o=ke(n?.context);if(f.getByNianSessionId(o)?.binding)throw new Error("schedule_personal_context_required");return await re({serverUrl:u,machineToken:p().machineToken,sessionId:o,action:n.operation,args:n})}}})}catch(e){throw await k.close(),e}let ee=!1;const N=()=>{ee||(ee=!0,Promise.allSettled([k.close(),A.close()]).finally(()=>process.exit(0)))};if(process.once("SIGINT",N),process.once("SIGTERM",N),!m.machineToken){console.error('Shennian CLI is not paired. Run "shennian pair --browser" or "shennian pair --token" first.'),await Promise.allSettled([k.close(),A.close()]),process.exitCode=1;return}process.removeListener("SIGINT",N),process.removeListener("SIGTERM",N);const oe=`${cn(u)}/relay/machine`,x=m.machineToken;if(!x)return;try{await en({serverUrl:u,machineToken:x,machineId:m.machineId})}catch(e){console.error(`[personal-sync] machine authority verification failed: ${e instanceof Error?e.message:String(e)}`),await Promise.allSettled([k.close(),A.close()]),process.exit(1)}m.machineId&&ko(u,m.machineId),console.log(`[${new Date().toISOString()}] Connecting to ${oe}... (v${h}) agents: ${S.join(",")}`),D({level:"info",wsEvent:"daemon.start",metadata:{version:h,agents:S}});let P=null,E=null,R=0,v=vo();const ne=_e(m.autoUpgrade),O=m.machineId?new Co({serverUrl:u,machineId:m.machineId,getMachineToken:()=>p().machineToken,getDetectedAgents:()=>ge({serverUrl:u,authToken:p().machineToken}),onRuntimeChanged:async()=>{const e=R,n=await he(!0);if(l.splice(0,l.length,...n.detectedAgents),S.splice(0,S.length,...n.agentList),H=n.agents,!(await s.sendReq({type:"req",id:Te(),method:"machine.agents.report",params:{agents:n.agents}},2e4)).ok)throw new Error("machine_capability_report_rejected");e===R&&s.getState()==="connected"&&O?.start()},onError:()=>console.warn("[public-agent] delivery attempt failed")}):null,s=new Ne({serverUrl:oe,machineToken:x,cliVersion:h,agentList:S,autoUpgradePolicy:ne,sessionSyncProtocolVersion:ve,sessionSyncCapabilities:Ie,daemonInstallationId:Zo(),dataEpoch:Se,updaterProtocolVersion:1,onConnected:()=>{console.log(`[${new Date().toISOString()}] \u2713 Connected`),D({level:"info",wsEvent:"daemon.connected"}),s.sendEvent({type:"event",event:"machine.agents",payload:{agentList:S,agents:H}}),bo(l,{serverUrl:m.serverUrl??u,authToken:m.machineToken??m.accessToken}).then(o=>{JSON.stringify(o)!==JSON.stringify(H)&&s.sendEvent({type:"event",event:"machine.agents",payload:{agentList:S,agents:o}})}).catch(()=>{}),v&&s.sendEvent({type:"event",event:"upgrade",payload:{state:"recovering",machineId:"self",from:v.from,to:v.to,...v.jobId?{jobId:v.jobId}:{},activeRunCount:r.getPendingRecoveryCount()}}),$.start(),E?.start();const e=++R,n=async()=>{try{if(await r.synchronizeSessionDeletions(),await r.recoverInterruptedRuns(),v){const o=v;v=null,o.jobId&&wo(o.jobId,o.to),fo(),console.log(`[${new Date().toISOString()}] [upgrade] ${o.operation==="rollback"?"Rolled back":"Healthy"}: ${o.from} \u2192 ${o.to}`),Ao({kind:"upgrade",result:o.operation==="rollback"?"rolled_back":"healthy",stage:"terminal"}),s.sendEvent({type:"event",event:"upgrade",payload:{state:o.operation==="rollback"?"rolled_back":"healthy",machineId:"self",from:o.from,to:o.to,...o.jobId?{jobId:o.jobId}:{}}}),o.operation!=="rollback"&&s.sendEvent({type:"event",event:"upgrade",payload:{state:"success",machineId:"self",from:o.from,to:o.to}})}e===R&&s.getState()==="connected"&&(P?.handleConnected(),O?.start())}catch(o){if(console.error("[session.deletions] startup catch-up failed",o),e===R&&s.getState()==="connected"){if(o instanceof tn)return;const t=o instanceof nn?Math.max(1e3,o.retryAfterMs):5e3;setTimeout(()=>{n()},t).unref?.()}}};n()},onDisconnected:e=>{R+=1,r?.revokeProjectFsHandles(),O?.stop(),E?.stop(),console.log(`[${new Date().toISOString()}] \u26A0 Disconnected, reconnecting... ${dn(e)}`),D({level:"warn",wsEvent:"daemon.disconnected",metadata:{code:e.code,reason:e.reason,error:e.error,phase:e.phase,trigger:e.trigger,reconnectAttempt:e.reconnectAttempt}})},onProjectFsCapabilityChanged:e=>{e||r?.revokeProjectFsHandles()},onReq:e=>{if(console.log(`[${new Date().toISOString()}] [req] ${e.method}`),D({level:"info",type:"ws",wsEvent:e.method,wsDirection:"in",traceId:e.traceId}),e.method==="room.message.deliver"){Ho(s,E,e);return}r.handleReq(e)}});P=Po()?new Eo(s):null,E=new jo({registry:f,observations:_,actionClient:y,getMachineCredentials:()=>({machineToken:p().machineToken}),isSessionDeleted:e=>new Fo().hasSession(e),onMessages:async(e,n,o,t)=>{await w?.processMessages(e,n,o,t)},onBindingPaused:e=>{e.lifecycleState==="closed"?(b.revokeSession(e.registryKey),r?.retireManagedRoomSession(e.nianSessionId).catch(()=>{console.warn("[room.sync] retired session cleanup failed")})):r?.discardPendingManagedRoomMessages(e.nianSessionId)}});const $=new Io({currentVersion:h,machineId:m.machineId??"unknown-machine",serverUrl:m.serverUrl??u,getIdleState:()=>r.getUpgradeIdleState(),sessionSyncProtocolVersion:ve,dataEpoch:Se,advertisedCapabilities:Ie,updaterProtocolVersion:1,startUpgrade:async(e,n)=>{const{handleUpgradeStart:o}=await import("./commands/upgrade.js");await o(s,"auto-upgrade",e,{currentVersion:h,prepareForUpgrade:t=>r.prepareForUpgrade(t),cancelUpgradePreparation:()=>r.cancelUpgradePreparation(),shutdownAfterHandoff:()=>{setTimeout(()=>process.kill(process.pid,"SIGTERM"),100).unref?.()},suppressResponse:!0,waitForCompletion:!0,canHandoff:n?void 0:()=>r.getUpgradeIdleState().idle})}});$.setPolicy(ne),r=new mo(s,P,h,$,new Lo({registry:f,observations:_,bindingClient:y,getMachineCredentials:()=>{const e=p();return{machineId:e.machineId,machineToken:e.machineToken}},hostProcessIdentity:()=>`daemon:${d}`}),{prepare:()=>Fe(),isDisabled:()=>ce(),shutdownAfterResponse:()=>{setTimeout(()=>{Be(),process.kill(process.pid,"SIGTERM")},100).unref?.()}},e=>b.revokeToken(e),Z,null,po(x),()=>V(l)),F=async e=>{const n=e&&typeof e=="object"&&!Array.isArray(e)?e:{},o=typeof n.targetVersion=="string"?n.targetVersion:void 0,t=n.confirmedMajor===!0;return await Xe(s,`local-upgrade-${Date.now()}`,o,{currentVersion:h,confirmedMajor:t,prepareForUpgrade:q=>r.prepareForUpgrade(q),cancelUpgradePreparation:()=>r.cancelUpgradePreparation(),shutdownAfterHandoff:()=>{setTimeout(()=>process.kill(process.pid,"SIGTERM"),100).unref?.()},suppressResponse:!0})},B=e=>{const n=e&&typeof e=="object"&&!Array.isArray(e)?e:{},t=`desktop-${(typeof n.targetVersion=="string"?n.targetVersion:"unknown").replace(/[^A-Za-z0-9._-]/g,"_")}-${Date.now()}`;return{jobId:t,...r.prepareForUpgrade(t)}},W=()=>(r.cancelUpgradePreparation(),{cancelled:!0}),w=new Go({registry:f,observations:_,enqueueConversationBatch:e=>r.enqueueManagedRoomBatch(e),loadContext:async e=>{const n=p().machineToken?.trim(),o=e.binding;if(!n||!o)throw new Error("managed_room_context_unavailable");const t=await y.status({machineToken:n,roomId:o.roomId,bindingId:o.bindingId});if(!Wo(f,e)||!Bo(e,t))throw new Error("managed_room_binding_unavailable");return{roomName:t.room.name,memberCount:t.room.memberCount,members:t.room.members,agentsByIdentityId:t.agent?{[t.agentIdentityId]:t.agent}:{},effectiveModelsBySessionId:t.effectiveModelId!==void 0?{[e.nianSessionId]:t.effectiveModelId}:void 0,agentSystemPromptsByIdentityId:t.agent?{[t.agentIdentityId]:t.agent.systemPrompt??""}:{}}},issueManagedRoomContext:(e,n,o,t)=>{const I=p().machineToken;if(!I)throw new Error("machine_not_authorized");return b.issue({registryKey:e,machineCredential:I,activationCauseMessageId:n,allowedActions:o,propagateWorkerRoomOrigin:t})},audit:new zo,resolveManagedAgentPolicy:e=>qo({...e,runtime:l.find(n=>n.type===e.registration.runtimeAdapter)})}),r.scheduleHandler=e=>Ae({serverUrl:u,machineToken:p().machineToken,req:e,client:s,queue:r.getScheduleQueue(),registry:f}),r.getScheduleQueue().validateScheduledTarget=async e=>{if(!e.bindingId||!e.roomId)return"ready";if(f.getByNianSessionId(e.sessionId)?.binding?.bindingId!==e.bindingId)return"ended";const o=await y.status({machineToken:p().machineToken,roomId:e.roomId,bindingId:e.bindingId});return o.status==="active"&&o.room.status==="active"?"ready":"ended"},r.setManagedRoomTurnPreparer(e=>w.prepareConversationTurn(e)),r.setManagedAgentDirectTurnPreparer((e,n)=>w.prepareDirectConversationTurn(e,n)),r.setManagedRecoveryPreparer(async e=>e.source==="managed_direct"?w.prepareDirectConversationTurn(e.sessionId,Xo):e.source==="manager_event"?w.prepareDirectConversationTurn(e.sessionId,{allowedRoomActions:[],managerEvent:!0}):e.source!=="managed_room"||!e.roomContextRegistryKey||!e.activationCauseMessageId||!e.rootCauseMessageId||!e.activationSequence||e.activationHopCount===null?null:w.prepareConversationTurn([{registryKey:e.roomContextRegistryKey,causeMessageId:e.activationCauseMessageId,rootCauseMessageId:e.rootCauseMessageId,sequence:e.activationSequence,hopCount:e.activationHopCount}])),z.mkdirSync(ye,{recursive:!0}),le(process.pid,d,{version:h}),me(process.pid,void 0,d),s.connect(),process.stdin.resume();let te=!1;const L=async()=>{if(!te){te=!0,console.log(T.gray(`
|
|
3
|
-
Disconnecting...`)),D({level:"info",wsEvent:"daemon.stop"}),clearInterval(g),O?.stop();try{await r.cleanup(),$.stop(),P?.stop(),E?.stop(),s.disconnect(),await Promise.allSettled([
|
|
1
|
+
import{registerScheduleCommand as be}from"./commands/schedule.js";import{resolvePersonalScheduleContext as Ae}from"./schedules/personal-context.js";import{executeServerSchedule as ae,deliverServerSchedule as Pe}from"./schedules/server-client.js";import{Command as Ee}from"commander";import T from"chalk";import Te from"node:os";import{randomUUID as Ue}from"node:crypto";import J from"node:fs";import{loadConfig as p,saveConfig as De,getConfigPath as Me,getShennianDir as _e,resolveShennianPath as K,normalizeAutoUpgradePolicy as Ne}from"./config/index.js";import{CliRelayClient as xe}from"./relay/client.js";import{collectKnownLogSecrets as ie,installCliLogRedaction as Oe,sanitizeCliLogValue as $e}from"./log-redaction.js";import{registerPairCommand as Le,runSmartStart as Ve}from"./commands/pair.js";import{registerLogoutCommand as je}from"./commands/logout.js";import{clearDaemonPidIfOwner as se,createDaemonInstanceId as Fe,clearDaemonLauncher as ce,findRunningDaemonProcessIds as He,isRemoteAccessDisabled as de,prepareRemoteAccessPause as Be,stopPreparedRemoteAccessService as We,isIsolatedDaemonE2eInstance as Ge,getDaemonStatus as le,registerDaemonCommand as qe,writeDaemonPid as me,writeDaemonLauncher as pe}from"./commands/daemon.js";import{registerRuntimeCommand as ze}from"./commands/runtime.js";import{registerAdapterCommand as Je}from"./commands/adapter.js";import{registerAgentCommand as Ke}from"./commands/agent.js";import{registerManagerCommand as Qe}from"./commands/manager.js";import{registerWorkerCommand as Ye}from"./commands/worker.js";import{registerProjectCommand as Ze}from"./commands/project.js";import{registerStewardCommand as Xe}from"./commands/steward.js";import{handleUpgradeStart as eo,registerUpgradeCommand as oo}from"./commands/upgrade.js";import{registerToolsCommand as no}from"./commands/tools.js";import{registerQueueCommand as to}from"./commands/queue.js";import{registerSkillCommand as ro}from"./commands/skill.js";import{refreshExistingSkillForHosts as ao}from"./skill/hosts.js";import{registerSetupCommand as io}from"./commands/setup.js";import{getUnavailableAcpAgents as so}from"./agents/acp/discovery.js";import{registerCommandReference as co}from"./commands/command-reference.js";import{registerIntegrationCommand as lo}from"./commands/integration.js";import{registerRoomCommand as mo}from"./commands/room.js";import{registerContactCommand as po}from"./commands/contact.js";import{registerSupportCommand as go}from"./commands/support.js";import{SessionManager as uo}from"./session/manager.js";import{createTrustedProjectFsRequestResolver as fo}from"./session/handlers/project-fs.js";import{SERVERS as Q,regionToUrl as ho,urlToRegion as vo}from"./region.js";import{clearUpgradeAttempt as Io,getCurrentVersion as ge,handleStartupCrashCheck as So,readUpgradeAttempt as yo}from"./upgrade/engine.js";import{AutoUpgradeScheduler as wo}from"./upgrade/scheduler.js";import{ensureUpdaterInstalled as Co}from"./upgrade/updater-bootstrap.js";import{launchUpdater as ko,markUpdaterHealthy as Ro}from"./upgrade/updater-launcher.js";import{detectAgents as ue}from"./agents/detect.js";import{PublicAgentDeliveryWorker as bo}from"./agents/public-delivery-worker.js";import{augmentProcessPath as fe}from"./env-path.js";import{acquireDaemonInstanceLock as Ao}from"./commands/daemon-instance-lock.js";fe();const U=ge();import{getCachedAgentInfos as V,resolveAgentInfos as Po}from"./agents/model-registry.js";import{initCliLogReporter as Eo,reportLog as D,reportUpgradeAggregateMetric as To}from"./log-reporter.js";import{isNativeFusionEnabled as Uo}from"./native-fusion/config.js";import{NativeSessionFusionService as Do}from"./native-fusion/service.js";import{startDaemonLogRetention as Mo}from"./daemon-log.js";import{startDaemonIpcServer as he}from"./daemon-ipc/server.js";import{resolveDaemonIpcPaths as _o,resolveManagedRoomIpcPaths as No}from"./daemon-ipc/paths.js";import{createDaemonControlHandlers as xo}from"./daemon-ipc/control.js";import{createAgentReadinessHandlers as Oo}from"./daemon-ipc/agent-readiness.js";import{scanMachineAgents as ve}from"./session/handlers/agents.js";import{validateAgentWorkspaceConfiguration as $o}from"./session/handlers/agent-workspace-validation.js";import{DAEMON_IPC_VERSION as Lo}from"./daemon-ipc/protocol.js";import{RoomSessionRegistry as Vo}from"./room/session-registry.js";import{HttpRoomBindingClient as jo}from"./room/room-binding-client.js";import{TrustedManagedRoomBinder as Fo}from"./room/managed-room-binding.js";import{RoomHostSessionObservationStore as Ho}from"./room/host-session-observations.js";import{RoomMirrorSyncService as Bo}from"./room/mirror-sync-service.js";import{handleLiveRoomDelivery as Wo}from"./room/live-delivery.js";import{NativeSourceDeletionStore as Go}from"./native-fusion/native-source-deletions.js";import{matchesRoomOwner as qo,isCurrentRegistration as zo}from"./room/registration-authority.js";import{RoomActivationService as Jo,resolveManagedAgentPolicy as Ko}from"./room/activation-service.js";import{RoomActivationAudit as Qo}from"./room/activation-audit.js";import{RoomAttachmentCache as Yo}from"./room/attachment-cache.js";import{RoomAttachmentUploader as Zo}from"./room/attachment-upload.js";import{ManagedRoomContextAuthority as Xo}from"./room/managed-context.js";import{createManagedRoomExecutor as en}from"./room/managed-room-ipc.js";import{SESSION_SYNC_PROTOCOL_VERSION as Ie,SESSION_SYNC_ADVERTISED_CAPABILITIES as Se}from"@shennian/wire";import{getDaemonInstallationId as on}from"./session/store.js";import{OWNER_DIRECT_TURN_OPTIONS as nn}from"./session/queue-helpers.js";import{synchronizeMachinePersonalAuthority as tn}from"./personal-sync/machine-authority.js";import{CLI_SESSION_SYNC_DATA_EPOCH as ye,ensurePersonalDataEpoch as rn}from"./personal-sync/epoch.js";import{DeletionSyncRetryWaitError as an,DeletionSyncTerminalError as sn}from"./session/deletion-sync-state.js";const we=_e(),cn=K("daemon.pid"),dn=K("daemon.instance.lock");function ln(){try{const i=J.readFileSync(cn,"utf-8").trim();if(i.startsWith("{")){const g=JSON.parse(i),d=Number(g.pid);return Number.isInteger(d)&&d>0?d:null}const c=parseInt(i,10);return Number.isInteger(c)&&c>0?c:null}catch{return null}}function mn(i){return i.replace(/^https:\/\//,"wss://").replace(/^http:\/\//,"ws://")}function Y(){process.stdout.write(`${JSON.stringify({ok:!1,error:"integration_command_retired",message:"Room MCP and Hooks were retired. Use the Shennian Skill and CLI.",nextAction:{type:"open_install_guide",url:"https://shennian.net/install.md"}})}
|
|
2
|
+
`),process.exitCode=1}function pn(i){const c=[`trigger=${i.trigger??"unknown"}`,`phase=${i.phase}`,`code=${i.code??"unknown"}`,`attempt=${i.reconnectAttempt}`];return i.reason&&c.push(`reason=${i.reason}`),i.error&&c.push(`error=${i.error}`),c.join(" ")}const a=new Ee;a.name("shennian").description("Shennian \u2014 AI Agent Control Plane").version(U),a.enablePositionalOptions(),lo(a),mo(a),po(a),go(a),be(a),a.option("--api <url>","Server URL override").option("--name <name>","Machine name",Te.hostname()).action(async i=>{const c=p(),g=i.api??process.env.SHENNIAN_DESKTOP_SERVER_URL??c.serverUrl??void 0;await Ve(g,i.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 i=>{const c=K("env.json");try{const e=JSON.parse(J.readFileSync(c,"utf-8"));for(const[n,o]of Object.entries(e))process.env[n]||(process.env[n]=o);fe()}catch{}Oe(ie(process.env,p()));const g=Mo();de()&&(console.log(`[${new Date().toISOString()}] remote access disabled, service start skipped`),clearInterval(g),process.exit(0));const d=Fe(),C=Ao({lockPath:dn,instanceId:d});C.acquired||(console.log(`[${new Date().toISOString()}] daemon already running`+(C.ownerPid?` (PID ${C.ownerPid})`:"")+", skipping duplicate start"),clearInterval(g),process.exit(0));try{const e=ln();if(e&&e!==process.pid)try{process.kill(e,0),console.log(`[${new Date().toISOString()}] daemon already running (PID ${e}), skipping duplicate start`),C.release(),process.exit(0)}catch{}}catch{}const Z=Ge(process.env,we)?[]:He(process.pid);Z.length>0&&(console.log(`[${new Date().toISOString()}] daemon already running (PID ${Z[0]}), skipping duplicate start`),C.release(),process.exit(0)),me(process.pid,d,{version:U}),pe(process.pid,void 0,d),process.on("exit",()=>{se(process.pid,d),ce(d)}),process.on("exit",C.release);let j=null;try{j=Co()}catch(e){console.error(`[upgrade] updater bootstrap unavailable: ${e instanceof Error?e.message:String(e)}`)}const M=await So();if(M){j||(console.error("[upgrade] Crash-loop rollback blocked: updater bootstrap unavailable"),process.exit(1));try{ko({fromVersion:U,targetVersion:M.from,oldDaemonPid:process.pid,operation:"rollback",rollbackJobId:M.jobId},{readiness:j}),console.error(`[upgrade] New version crashed ${M.attemptCount} times; external rollback scheduled.`),process.stdin.resume();return}catch(e){console.error(`[upgrade] Crash-loop rollback could not start: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}}try{rn()}catch(e){console.error(`[personal-sync] data epoch initialization failed: ${e instanceof Error?e.message:String(e)}`),process.exitCode=1;return}const m=p(),u=i.api??process.env.SHENNIAN_DESKTOP_SERVER_URL??m.serverUrl??Q.cn.url,h=ge(),l=await ue({serverUrl:u,authToken:m.machineToken??m.accessToken}),S=l.map(e=>e.type);let F=V(l);const v=new Vo,_=new Ho,R=new Xo(v),y=new jo(u),ke=new Yo({actionClient:y}),Re=new Zo({actionClient:y});let w=null,r;const X=en({authority:R,actionClient:y,attachmentCache:ke,attachmentUploader:Re,observations:_,getMachineCredentials:()=>({machineToken:p().machineToken}),managerExecutor:e=>r.executeManagedManagerAction(e),onSendOutcome:e=>r.noteManagedRoomSendOutcome(e),getActiveRunId:(e,n)=>r.getManagedRoomActiveRunId(e,n),scheduleExecutor:(e,n,o)=>ae({serverUrl:u,machineToken:p().machineToken,sessionId:e,action:n,args:o}),onPaused:({registryKey:e,sessionId:n})=>{const t=v.getByRegistryKey(e)?.binding;t&&v.setBinding({registryKey:e,bindingId:t.bindingId,roomId:t.roomId,agentIdentityId:t.agentIdentityId,agentMembershipId:t.agentMembershipId,status:"paused",activationMode:"paused"}),R.revokeSession(e),r?.discardPendingManagedRoomMessages(n)}});let H=null,B=null,W=null,G=null,ee=!1;const b=await he({paths:_o(),handlers:{...xo({daemonVersion:h,protocolVersion:Lo,getStatus:()=>le(),getAgents:()=>l,requestShutdown:()=>{G?G():ee=!0},completeAgentAuthentication:e=>r.resumePendingAcpAuthentication(e),bindManagedRoom:e=>r.bindManagedRoomFromLocal(e),stewardSay:e=>r.stewardSayFromLocal(e),startUpgrade:async e=>{if(!H)throw new Error("upgrade_unavailable");return H(e)},prepareExternalUpgrade:e=>{if(!B)throw new Error("external_upgrade_unavailable");return B(e)},cancelExternalUpgrade:()=>{if(!W)throw new Error("external_upgrade_unavailable");return W()}}),...Oo({getStatus:()=>le(),getSnapshot:()=>V(l).map(e=>{const n=l.find(o=>o.type===e.type);return{...e,runtimePlatform:n?.runtimePlatform,runtimeIsWsl:n?.runtimeIsWsl}}),getUnavailable:so,discover:async e=>{if(!r)throw new Error("daemon_starting");const n=await ve(!0,e);if(e){const t=l.filter(f=>f.type!==e);l.splice(0,l.length,...t,...n.detectedAgents)}else l.splice(0,l.length,...n.detectedAgents);const o=V(l);return s.sendEvent({type:"event",event:"machine.agents",payload:{agentList:l.map(t=>t.type),agents:o}}),n.agents.map(t=>{const f=n.detectedAgents.find(z=>z.type===t.type);return{...t,runtimePlatform:f?.runtimePlatform,runtimeIsWsl:f?.runtimeIsWsl}})},validate:async e=>{if(!r)throw new Error("daemon_starting");return $o(e,{ignoreNativeSession:(n,o)=>P?.ignoreNativeSource(n,o)})}})}});let A;try{A=await he({paths:No(),handlers:{"managed-room.execute":e=>X(e),"schedule.personal":async e=>{const n=e,o=Ae(n?.context);if(v.getByNianSessionId(o)?.binding)throw new Error("schedule_personal_context_required");return await ae({serverUrl:u,machineToken:p().machineToken,sessionId:o,action:n.operation,args:n})}}})}catch(e){throw await b.close(),e}let oe=!1;const N=()=>{oe||(oe=!0,Promise.allSettled([b.close(),A.close()]).finally(()=>process.exit(0)))};if(process.once("SIGINT",N),process.once("SIGTERM",N),!m.machineToken){console.error('Shennian CLI is not paired. Run "shennian pair --browser" or "shennian pair --token" first.'),await Promise.allSettled([b.close(),A.close()]),process.exitCode=1;return}process.removeListener("SIGINT",N),process.removeListener("SIGTERM",N);const ne=`${mn(u)}/relay/machine`,x=m.machineToken;if(!x)return;try{await tn({serverUrl:u,machineToken:x,machineId:m.machineId})}catch(e){console.error(`[personal-sync] machine authority verification failed: ${e instanceof Error?e.message:String(e)}`),await Promise.allSettled([b.close(),A.close()]),process.exit(1)}m.machineId&&Eo(u,m.machineId),console.log(`[${new Date().toISOString()}] Connecting to ${ne}... (v${h}) agents: ${S.join(",")}`),D({level:"info",wsEvent:"daemon.start",metadata:{version:h,agents:S}});let P=null,E=null,k=0,q=!1,I=yo();const te=Ne(m.autoUpgrade),O=m.machineId?new bo({serverUrl:u,machineId:m.machineId,getMachineToken:()=>p().machineToken,getDetectedAgents:()=>ue({serverUrl:u,authToken:p().machineToken}),onRuntimeChanged:async()=>{const e=k,n=await ve(!0);if(l.splice(0,l.length,...n.detectedAgents),S.splice(0,S.length,...n.agentList),F=n.agents,!(await s.sendReq({type:"req",id:Ue(),method:"machine.agents.report",params:{agents:n.agents}},2e4)).ok)throw new Error("machine_capability_report_rejected");e===k&&s.getState()==="connected"&&O?.start()},onError:()=>console.warn("[public-agent] delivery attempt failed")}):null,s=new xe({serverUrl:ne,machineToken:x,cliVersion:h,agentList:S,autoUpgradePolicy:te,sessionSyncProtocolVersion:Ie,sessionSyncCapabilities:Se,daemonInstallationId:on(),dataEpoch:ye,updaterProtocolVersion:1,onConnected:()=>{console.log(`[${new Date().toISOString()}] \u2713 Connected`),D({level:"info",wsEvent:"daemon.connected"}),s.sendEvent({type:"event",event:"machine.agents",payload:{agentList:S,agents:F}}),Po(l,{serverUrl:m.serverUrl??u,authToken:m.machineToken??m.accessToken}).then(o=>{JSON.stringify(o)!==JSON.stringify(F)&&s.sendEvent({type:"event",event:"machine.agents",payload:{agentList:S,agents:o}})}).catch(()=>{}),I&&s.sendEvent({type:"event",event:"upgrade",payload:{state:"recovering",machineId:"self",from:I.from,to:I.to,...I.jobId?{jobId:I.jobId}:{},activeRunCount:r.getPendingRecoveryCount()}}),$.start(),E?.start();const e=++k,n=async()=>{try{if(await r.synchronizeSessionDeletions(),await r.recoverInterruptedRuns(),I){const o=I;I=null,o.jobId&&Ro(o.jobId,o.to),Io(),console.log(`[${new Date().toISOString()}] [upgrade] ${o.operation==="rollback"?"Rolled back":"Healthy"}: ${o.from} \u2192 ${o.to}`),To({kind:"upgrade",result:o.operation==="rollback"?"rolled_back":"healthy",stage:"terminal"}),s.sendEvent({type:"event",event:"upgrade",payload:{state:o.operation==="rollback"?"rolled_back":"healthy",machineId:"self",from:o.from,to:o.to,...o.jobId?{jobId:o.jobId}:{}}}),o.operation!=="rollback"&&s.sendEvent({type:"event",event:"upgrade",payload:{state:"success",machineId:"self",from:o.from,to:o.to}})}q||(q=!0,ao({clientVersion:h}).then(o=>{const t=o.filter(f=>!f.ok||!["current","registered","updated"].includes(f.result.status));t.length>0&&console.warn(`[skill] ${t.length} installed Skill copies need attention; run shennian setup for details`)}).catch(()=>console.warn("[skill] Official Skill refresh failed; Client remains available")).finally(()=>{q=!1})),e===k&&s.getState()==="connected"&&(P?.handleConnected(),O?.start())}catch(o){if(console.error("[session.deletions] startup catch-up failed",o),e===k&&s.getState()==="connected"){if(o instanceof sn)return;const t=o instanceof an?Math.max(1e3,o.retryAfterMs):5e3;setTimeout(()=>{n()},t).unref?.()}}};n()},onDisconnected:e=>{k+=1,r?.revokeProjectFsHandles(),O?.stop(),E?.stop(),console.log(`[${new Date().toISOString()}] \u26A0 Disconnected, reconnecting... ${pn(e)}`),D({level:"warn",wsEvent:"daemon.disconnected",metadata:{code:e.code,reason:e.reason,error:e.error,phase:e.phase,trigger:e.trigger,reconnectAttempt:e.reconnectAttempt}})},onProjectFsCapabilityChanged:e=>{e||r?.revokeProjectFsHandles()},onReq:e=>{if(console.log(`[${new Date().toISOString()}] [req] ${e.method}`),D({level:"info",type:"ws",wsEvent:e.method,wsDirection:"in",traceId:e.traceId}),e.method==="room.message.deliver"){Wo(s,E,e);return}r.handleReq(e)}});P=Uo()?new Do(s):null,E=new Bo({registry:v,observations:_,actionClient:y,getMachineCredentials:()=>({machineToken:p().machineToken}),isSessionDeleted:e=>new Go().hasSession(e),onMessages:async(e,n,o,t)=>{await w?.processMessages(e,n,o,t)},onBindingPaused:e=>{e.lifecycleState==="closed"?(R.revokeSession(e.registryKey),r?.retireManagedRoomSession(e.nianSessionId).catch(()=>{console.warn("[room.sync] retired session cleanup failed")})):r?.discardPendingManagedRoomMessages(e.nianSessionId)}});const $=new wo({currentVersion:h,machineId:m.machineId??"unknown-machine",serverUrl:m.serverUrl??u,getIdleState:()=>r.getUpgradeIdleState(),sessionSyncProtocolVersion:Ie,dataEpoch:ye,advertisedCapabilities:Se,updaterProtocolVersion:1,startUpgrade:async(e,n)=>{const{handleUpgradeStart:o}=await import("./commands/upgrade.js");await o(s,"auto-upgrade",e,{currentVersion:h,prepareForUpgrade:t=>r.prepareForUpgrade(t),cancelUpgradePreparation:()=>r.cancelUpgradePreparation(),shutdownAfterHandoff:()=>{setTimeout(()=>process.kill(process.pid,"SIGTERM"),100).unref?.()},suppressResponse:!0,waitForCompletion:!0,canHandoff:n?void 0:()=>r.getUpgradeIdleState().idle})}});$.setPolicy(te),r=new uo(s,P,h,$,new Fo({registry:v,observations:_,bindingClient:y,getMachineCredentials:()=>{const e=p();return{machineId:e.machineId,machineToken:e.machineToken}},hostProcessIdentity:()=>`daemon:${d}`}),{prepare:()=>Be(),isDisabled:()=>de(),shutdownAfterResponse:()=>{setTimeout(()=>{We(),process.kill(process.pid,"SIGTERM")},100).unref?.()}},e=>R.revokeToken(e),X,null,fo(x),()=>V(l)),H=async e=>{const n=e&&typeof e=="object"&&!Array.isArray(e)?e:{},o=typeof n.targetVersion=="string"?n.targetVersion:void 0,t=n.confirmedMajor===!0;return await eo(s,`local-upgrade-${Date.now()}`,o,{currentVersion:h,confirmedMajor:t,prepareForUpgrade:z=>r.prepareForUpgrade(z),cancelUpgradePreparation:()=>r.cancelUpgradePreparation(),shutdownAfterHandoff:()=>{setTimeout(()=>process.kill(process.pid,"SIGTERM"),100).unref?.()},suppressResponse:!0})},B=e=>{const n=e&&typeof e=="object"&&!Array.isArray(e)?e:{},t=`desktop-${(typeof n.targetVersion=="string"?n.targetVersion:"unknown").replace(/[^A-Za-z0-9._-]/g,"_")}-${Date.now()}`;return{jobId:t,...r.prepareForUpgrade(t)}},W=()=>(r.cancelUpgradePreparation(),{cancelled:!0}),w=new Jo({registry:v,observations:_,enqueueConversationBatch:e=>r.enqueueManagedRoomBatch(e),loadContext:async e=>{const n=p().machineToken?.trim(),o=e.binding;if(!n||!o)throw new Error("managed_room_context_unavailable");const t=await y.status({machineToken:n,roomId:o.roomId,bindingId:o.bindingId});if(!zo(v,e)||!qo(e,t))throw new Error("managed_room_binding_unavailable");return{roomName:t.room.name,memberCount:t.room.memberCount,members:t.room.members,agentsByIdentityId:t.agent?{[t.agentIdentityId]:t.agent}:{},effectiveModelsBySessionId:t.effectiveModelId!==void 0?{[e.nianSessionId]:t.effectiveModelId}:void 0,agentSystemPromptsByIdentityId:t.agent?{[t.agentIdentityId]:t.agent.systemPrompt??""}:{}}},issueManagedRoomContext:(e,n,o,t)=>{const f=p().machineToken;if(!f)throw new Error("machine_not_authorized");return R.issue({registryKey:e,machineCredential:f,activationCauseMessageId:n,allowedActions:o,propagateWorkerRoomOrigin:t})},audit:new Qo,resolveManagedAgentPolicy:e=>Ko({...e,runtime:l.find(n=>n.type===e.registration.runtimeAdapter)})}),r.scheduleHandler=e=>Pe({serverUrl:u,machineToken:p().machineToken,req:e,client:s,queue:r.getScheduleQueue(),registry:v}),r.getScheduleQueue().validateScheduledTarget=async e=>{if(!e.bindingId||!e.roomId)return"ready";if(v.getByNianSessionId(e.sessionId)?.binding?.bindingId!==e.bindingId)return"ended";const o=await y.status({machineToken:p().machineToken,roomId:e.roomId,bindingId:e.bindingId});return o.status==="active"&&o.room.status==="active"?"ready":"ended"},r.setManagedRoomTurnPreparer(e=>w.prepareConversationTurn(e)),r.setManagedAgentDirectTurnPreparer((e,n)=>w.prepareDirectConversationTurn(e,n)),r.setManagedRecoveryPreparer(async e=>e.source==="managed_direct"?w.prepareDirectConversationTurn(e.sessionId,nn):e.source==="manager_event"?w.prepareDirectConversationTurn(e.sessionId,{allowedRoomActions:[],managerEvent:!0}):e.source!=="managed_room"||!e.roomContextRegistryKey||!e.activationCauseMessageId||!e.rootCauseMessageId||!e.activationSequence||e.activationHopCount===null?null:w.prepareConversationTurn([{registryKey:e.roomContextRegistryKey,causeMessageId:e.activationCauseMessageId,rootCauseMessageId:e.rootCauseMessageId,sequence:e.activationSequence,hopCount:e.activationHopCount}])),J.mkdirSync(we,{recursive:!0}),me(process.pid,d,{version:h}),pe(process.pid,void 0,d),s.connect(),process.stdin.resume();let re=!1;const L=async()=>{if(!re){re=!0,console.log(T.gray(`
|
|
3
|
+
Disconnecting...`)),D({level:"info",wsEvent:"daemon.stop"}),clearInterval(g),O?.stop();try{await r.cleanup(),$.stop(),P?.stop(),E?.stop(),s.disconnect(),await Promise.allSettled([b.close(),A.close()]),se(process.pid,d),ce(d)}finally{process.exit(0)}}};G=L,ee&&L(),process.on("SIGINT",()=>{L()}),process.on("SIGTERM",()=>{L()})}),a.command("workbuddy-session-hook",{hidden:!0}).description("(retired) WorkBuddy Room Hook").allowUnknownOption(!0).action(()=>Y()),a.command("room-session-hook",{hidden:!0}).description("(internal) Authorize the official Room tool for one trusted Agent Session").argument("<runtime>","Trusted runtime adapter").allowUnknownOption(!0).action(()=>Y()),a.command("room-tool-server",{hidden:!0}).description("(internal) Run the official Shennian Room MCP tool").allowUnknownOption(!0).action(()=>Y());const Ce=a.command("config").description("View or modify configuration");Ce.command("show",{isDefault:!0}).description("Show current configuration").action(()=>{console.log(`Config file: ${Me()}`);const i=p(),c=$e(i,ie(process.env,i));if(i.serverUrl){const g=vo(i.serverUrl);console.log(`Region: ${g} (${Q[g].label})`)}console.log(JSON.stringify(c,null,2))}),Ce.command("set").description("Update a config value").argument("<key>",'Config key (e.g. "server")').argument("<value>",'Config value (e.g. "cn" or "global")').action((i,c)=>{const g=p();if(i==="server"){c!=="cn"&&c!=="global"&&(console.error(T.red('\u2717 Value must be "cn" or "global"')),process.exit(1));const d=c;g.serverUrl=ho(d),De(g),console.log(T.green(`\u2713 Server set to ${Q[d].label}`)),console.log(T.yellow(" Restart the background service for this to take effect: shennian stop && shennian start"));return}console.error(T.red(`\u2717 Unknown config key: ${i}. Supported: server`)),process.exit(1)}),io(a),Le(a),je(a),qe(a),ze(a),Je(a,{clientVersion:U}),Ke(a),Qe(a),Ye(a),Ze(a),Xe(a),oo(a),no(a),to(a),ro(a),co(a,U),a.parse();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{loadConfig as w}from"../config/index.js";import{SERVERS as R}from"../region.js";class
|
|
1
|
+
import{loadConfig as w}from"../config/index.js";import{SERVERS as R}from"../region.js";class r extends Error{code;nextAction;constructor(e,t,o=null){super(t),this.code=e,this.nextAction=o}}class C{fetchImpl;constructor(e=fetch){this.fetchImpl=e}create(e,t){return this.request("POST","/api/room-cli/create",{name:e,operationId:t},{retryNetworkOnce:!0})}list(){return this.request("GET","/api/room-cli/rooms")}listContacts(e){const t=e?`?q=${encodeURIComponent(e)}`:"";return this.request("GET",`/api/room-cli/contacts${t}`)}get(e){return this.request("GET",`/api/room-cli/${encodeURIComponent(e)}`)}update(e,t){return this.request("POST",`/api/room-cli/${encodeURIComponent(e)}/update`,t)}deleteRecord(e,t){return this.request("POST",`/api/room-cli/${encodeURIComponent(e)}/delete`,{version:t})}getInvite(e){return this.request("GET",`/api/room-cli/${encodeURIComponent(e)}/invite`)}resetInvite(e,t){return this.request("POST",`/api/room-cli/${encodeURIComponent(e)}/invite/reset`,{version:t})}listMembers(e){return this.request("GET",`/api/room-cli/${encodeURIComponent(e)}/members`)}removeMember(e,t,o){return this.request("POST",`/api/room-cli/${encodeURIComponent(e)}/members/remove`,{memberRef:t,version:o})}join(e,t,o){return this.request("POST","/api/room-cli/join",{roomId:e,inviteToken:t,...o?{message:o}:{}})}open(e){return this.request("POST",`/api/room-cli/${encodeURIComponent(e)}/open`,{})}status(e){return this.request("GET",`/api/room-cli/${encodeURIComponent(e)}/status`)}read(e,t){const o=new URLSearchParams({limit:String(t.limit)});return t.before&&o.set("before",t.before),t.after&&o.set("after",t.after),this.request("GET",`/api/room-cli/${encodeURIComponent(e)}/messages?${o}`)}send(e,t){return this.request("POST",`/api/room-cli/${encodeURIComponent(e)}/messages`,t,{retryNetworkOnce:!0})}initializeAttachment(e,t){return this.request("POST",`/api/room-cli/${encodeURIComponent(e)}/attachments/init`,t)}completeAttachment(e,t){return this.request("POST",`/api/room-cli/${encodeURIComponent(e)}/attachments/${encodeURIComponent(t)}/complete`,{})}getAttachmentDownload(e,t){return this.request("GET",`/api/room-cli/${encodeURIComponent(e)}/attachments/${encodeURIComponent(t)}/download`)}leave(e){return this.request("POST",`/api/room-cli/${encodeURIComponent(e)}/leave`,{})}async upload(e,t,o){let s;try{s=await this.fetchImpl(e,{method:"PUT",headers:t,body:o,redirect:"error",signal:AbortSignal.timeout(12e4)})}catch{throw new r("attachment_upload_failed","Attachment upload failed.")}if(!s.ok)throw new r("attachment_upload_failed","Attachment upload failed.")}async download(e){try{const t=await this.fetchImpl(e,{redirect:"error",signal:AbortSignal.timeout(6e4)});if(!t.ok||!t.body)throw new r("attachment_download_failed","Attachment download failed.");return t}catch(t){throw t instanceof r?t:new r("attachment_download_failed","Attachment download failed.")}}async request(e,t,o,s={}){const l=w();if(!l.machineToken)throw new r("not_paired","Shennian CLI is not paired.",{type:"run_command",command:"shennian pair --browser"});const d=(l.serverUrl??R.cn.url).replace(/\/+$/,""),u=()=>this.fetchImpl(`${d}${t}`,{method:e,headers:{authorization:`Bearer ${l.machineToken}`,...o==null?{}:{"content-type":"application/json"}},...o==null?{}:{body:JSON.stringify(o)},signal:AbortSignal.timeout(2e4)});let a;try{a=await u()}catch{if(!s.retryNetworkOnce)throw new r("server_unavailable","Shennian service is unavailable.");try{a=await u()}catch{throw new r("server_unavailable","Shennian service is unavailable.")}}const c=await $(a);if(!a.ok){const i=m(c)?c:{},h=typeof i.error=="string"?i.error:`http_${a.status}`,p=typeof i.message=="string"?i.message:"Room request failed.",f=I(i.nextAction)?i.nextAction:null;throw new r(h,p,f)}if(!m(c))throw new r("invalid_server_response","Shennian returned an invalid Room response.");return c}}function I(n){return m(n)&&Object.values(n).every(e=>typeof e=="string")}async function $(n){try{return await n.json()}catch{return null}}function m(n){return!!n&&typeof n=="object"&&!Array.isArray(n)}export{C as PublicRoomClient,r as PublicRoomClientError};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{buildApprovalPendingPayload as M}from"@shennian/wire";import{createHash as
|
|
2
|
-
`),o=r>0?Math.min(r,80):Math.min(a.length,80);return a.slice(0,o)}function
|
|
1
|
+
import{buildApprovalPendingPayload as M}from"@shennian/wire";import{createHash as w}from"node:crypto";import{AgentEventTerminalGate as D}from"../../agents/event-terminal-gate.js";import{recordAcpAgentModels as k}from"../../agents/model-registry.js";import{reportLog as _}from"../../log-reporter.js";import{registerInternalNativeSource as P}from"../../native-fusion/source-visibility.js";import{requestSessionIndexPublish as c}from"../index-publisher.js";import{noteRunActivity as j}from"../run-stall.js";import{appendMessage as s,recordSession as I,upsertMessage as O}from"../store.js";import{writeToolDetail as C}from"../tool-detail-store.js";import{refreshMachineAgents as F}from"./agents.js";import{roomReplyFailureNotice as N}from"../room-reply-notice.js";import{commitStewardFallback as S,tryStewardFailover as B}from"./steward.js";import{clearStewardSwitched as H,resetStewardChain as J}from"../../steward/failover.js";function L(a){const r=a.indexOf(`
|
|
2
|
+
`),o=r>0?Math.min(r,80):Math.min(a.length,80);return a.slice(0,o)}function R(a,r,o){return`${a}:${w("sha256").update(`${r}\0${o??""}`).digest("hex")}`}function V(a,r,o={}){if(a.state==="tool-call"||a.state==="tool-result"){const l={runId:a.runId,sourceSeq:a.seq};return{state:a.state,runId:a.runId,seq:a.seq,sessionId:r,detailRef:l,status:a.state==="tool-call"?"running":"completed",detailAvailable:!0,...a.durationMs!==void 0?{durationMs:a.durationMs}:{},...a.name?{name:a.name}:{},...a.source?{source:a.source}:{},...a.agentSessionId?{agentSessionId:a.agentSessionId}:{},...o}}return{...a,sessionId:r,...o}}const Q=3e4;function G(a){return a.state==="heartbeat"?a.runPhase??null:a.state==="tool-call"||a.state==="tool-result"?"tool_running":a.state==="approval-pending"?"waiting_approval":a.state==="delta"?a.thinking?"thinking":"streaming_text":a.state==="init"||a.state==="start"?"thinking":null}function A(a,r){return a!=="manager"?a:r==="claude"?"claude":"codex"}function y(a,r,o,l){if(l.state!=="error"){S(a,r,o,l);return}B(a,r,o,l).catch(()=>!1).then(g=>{g||S(a,r,o,l)})}function lt(a,r,o,l){let g=null;const E=new D;function x(t,n={}){a.client.sendAgentEvent({type:"event",event:"agent",payload:V(t,r,n),seq:t.seq,id:`agent-evt-${t.runId}-${t.seq}`})}o.startsWith("acp:")&&l.on("sessionOptions",()=>{try{const t=l.getSessionOptions?.().models??[];if(!k(o,t))return;const n=a.getAgentSnapshot?.();if(!n)return;a.client.sendEvent({type:"event",event:"machine.agents",payload:{agentList:n.map(e=>e.type),agents:n}})}catch{}});function $(t){t?.heartbeatTimer&&(clearInterval(t.heartbeatTimer),t.heartbeatTimer=null)}function b(t){if(!t.currentRunId||!t.currentRunPhase)return;const n=t.heartbeatSeq++;a.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"heartbeat",sessionId:r,runId:t.currentRunId,seq:n,runPhase:t.currentRunPhase},seq:n,id:`agent-heartbeat-${t.currentRunId}-${n}-${Date.now()}`})}function T(t){!t||t.heartbeatTimer||(t.heartbeatTimer=setInterval(()=>{b(t)},Q),t.heartbeatTimer.unref?.())}function f(t){const n=t?.pendingTextEvent;!t||!n||!n.text||(s(r,{id:`agent-${n.runId}-${n.seq}`,sessionId:r,role:"agent",ts:Date.now(),payload:n.text}),c(a.client),x({state:"delta",runId:n.runId,seq:n.seq,text:n.text,thinking:n.thinking||void 0}),t.sessionScope==="steward"&&(t.stewardLastText=n.text),t.pendingTextEvent=null)}l.on("agentEvent",t=>{if(!E.accept(t))return;let n=!1;t.errorCode==="acp_auth_required"&&F(a).catch(()=>{});const e=a.sessions.get(r),h=G(t),u=t.state==="final"||t.state==="error"||t.state==="aborted";if(e&&j(r,e,u),e&&(e.nextEventSeq=t.seq+1,!u&&e.currentRunId!==t.runId&&e.sessionScope==="steward"&&(e.stewardSay={count:0},e.stewardLastText="",H(r)),u||(e.currentRunId=t.runId),!u&&h&&(e.currentRunPhase=h,T(e)),t.agentSessionId&&(e.agentSessionId=t.agentSessionId),e.journalRunId)){const i={agentSessionId:t.agentSessionId??e.agentSessionId,providerRunId:t.runId||null,lastObservedEventSeq:t.seq,...u?{}:{phase:h==="waiting_approval"?"waiting_approval":"running"}};a.runJournal?.update(r,e.journalRunId,i)}if(a.managerRuntime?.noteAgentEvent(r,t),t.state==="delta"&&t.thinking)return;t.state!=="delta"&&_({level:"info",sessionId:r,wsEvent:`agent.${t.state}`,wsDirection:"out",metadata:{runId:t.runId,seq:t.seq,agentType:o}});let p=!1;if(t.state==="tool-call"||t.state==="tool-result"){const i=t.toolCallId?`agent-tool-${w("sha256").update(`${t.runId}\0${t.toolCallId}`).digest("hex")}`:`agent-${t.runId}-${t.seq}`;C({sessionId:r,toolCallId:i,detailRevision:t.seq,ts:Date.now(),name:t.name??"tool",...t.args!==void 0?{args:t.args}:{},...t.result!==void 0?{result:t.result}:{},status:t.toolStatus??(t.state==="tool-call"?"running":"completed"),...t.durationMs!==void 0?{durationMs:t.durationMs}:{},detailRef:{runId:t.runId,sourceSeq:t.seq}}),(t.toolCallId?O:s)(r,{id:i,sessionId:r,role:"agent",ts:Date.now(),payload:JSON.stringify({v:1,type:t.state==="tool-call"?"tool_use":"tool_result",name:t.name,toolCallId:i,status:t.toolStatus??(t.state==="tool-call"?"running":"completed"),...t.durationMs!==void 0?{durationMs:t.durationMs}:{},detailRef:{runId:t.runId,sourceSeq:t.seq},detailRevision:t.seq,detailAvailable:!0,resultOmitted:t.state==="tool-result"})}),p=!0}else t.state==="approval-pending"?(s(r,{id:`agent-${t.runId||"run"}-${t.seq}`,sessionId:r,role:"agent",ts:Date.now(),payload:M({...t.approval,permission:t.permission})}),p=!0,e&&I({sessionId:r,agentType:o,workDir:e.workDir,agentSessionId:e.agentSessionId,attentionId:R("approval",t.runId,t.seq)})):(t.state==="error"||t.state==="aborted")&&t.message&&(s(r,{id:`agent-${t.runId||"run"}-${t.seq}`,sessionId:r,role:"agent",ts:Date.now(),payload:t.message}),p=!0);p&&c(a.client);const d=`${r}:${t.runId}`;if(t.state==="delta"&&!t.thinking&&t.text&&a.runTextAcc.set(d,(a.runTextAcc.get(d)??"")+t.text),t.agentSessionId&&t.agentSessionId!==g&&(e?.nativeSessionVisibility==="internal"&&P(r,A(o,t.source)??o,t.agentSessionId),g=t.agentSessionId,a.nativeFusion?.noteManagedSourceSession(r,A(o,t.source),t.agentSessionId),e&&I({sessionId:r,agentType:o,workDir:e.workDir,agentSessionId:t.agentSessionId}),a.client.sendEvent({type:"event",event:"session.update",payload:{session:{id:r,agentType:o,agentSessionId:t.agentSessionId}}})),t.state==="delta"){const i=t.text??"";if(!i)return;e?.pendingTextEvent&&e.pendingTextEvent.runId!==t.runId&&f(e),e&&!e.pendingTextEvent&&(e.pendingTextEvent={runId:t.runId,seq:t.seq,text:"",thinking:!1}),e?.pendingTextEvent&&(e.pendingTextEvent.text+=i,e.pendingTextEvent.seq=t.seq);return}let q={};if(t.state==="final"){f(e),e&&(S(a,r,e,t),J(r));const i=e?N(e):null;i&&(n=!0,s(r,{id:`room-reply-notice-${t.runId}`,sessionId:r,role:"agent",ts:Date.now(),payload:i}),c(a.client));const m=a.runTextAcc.get(d)??"";m&&(q={messageSummary:L(m)}),a.runTextAcc.delete(d)}else t.state==="error"||t.state==="aborted"?(f(e),e&&y(a,r,e,t),a.runTextAcc.delete(d)):(t.state==="tool-call"||t.state==="tool-result"||t.state==="approval-pending")&&f(e);u&&e?.currentRunId===t.runId&&(e.currentRunId=null,e.currentRunPhase=null,e.nextEventSeq=0,$(e),a.chatQueue?.noteTerminal(r),I({sessionId:r,agentType:o,workDir:e.workDir,agentSessionId:e.agentSessionId,status:t.state==="final"&&!n?"completed":"failed",attentionId:R("terminal",t.runId),lastActivityAt:new Date().toISOString()}),c(a.client),e.journalRunId&&(a.runJournal?.remove(r,e.journalRunId),a.recoveryBarrier?.end(r),e.journalRunId=null)),x(t,q)}),l.on("error",t=>{console.error(`[chat.send] adapter error sessionId=${r} agentType=${o}: ${t.message}`);const n=a.sessions.get(r);n&&y(a,r,n,{state:"error",runId:n.currentRunId??"",message:t.message}),n?.journalRunId&&(a.runJournal?.update(r,n.journalRunId,{phase:"terminal"}),a.runJournal?.remove(r,n.journalRunId),a.recoveryBarrier?.end(r),n.journalRunId=null),a.sessions.delete(r),a.chatQueue?.noteTerminal(r),a.chatQueue?.isDispatching?.(r)||(s(r,{id:`agent-error-${r}-${Date.now()}`,sessionId:r,role:"agent",ts:Date.now(),payload:t.message}),c(a.client)),a.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:r,message:t.message,runId:"",seq:0}})})}export{lt as bindAdapterEvents,A as getNativeSourceAgentType};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash as T,randomUUID as m}from"node:crypto";import{buildStewardSayPayload as x,STEWARD_TERMINAL_OPEN_MESSAGE_ID_PREFIX as
|
|
1
|
+
import{createHash as T,randomUUID as m}from"node:crypto";import{buildStewardSayPayload as x,parseStewardSayPayload as E,STEWARD_FAILOVER_USER_MESSAGE_ID_PREFIX as A,STEWARD_TERMINAL_OPEN_MESSAGE_ID_PREFIX as $}from"@shennian/wire";import{DaemonIpcError as D}from"../../daemon-ipc/protocol.js";import{STEWARD_SAY_MAX_CHARS as l,isStewardSessionId as S}from"../../steward/session.js";import{requestSessionIndexPublish as R}from"../index-publisher.js";import{appendMessage as y,getDaemonInstallationId as I,listSessionRecords as M,readMessages as L,recordSession as g}from"../store.js";import{pinStewardWorkDir as h}from"../../steward/session.js";import{buildHandoverNote as b,carryStewardChain as N,classifyStewardFailure as k,clearStewardSwitched as _,lastStewardUserText as F,markStewardSwitched as C,pickFailoverAgent as P,setStewardHandover as U,wasStewardJustSwitched as W,stewardFailureLabel as q,stewardTriedAgents as H}from"../../steward/failover.js";class c extends D{}function w(t,e,a,r="say",d){if(!S(e))throw new c("steward_session_required","This session is not a Shennian steward session.");const s=typeof a=="string"?a.trim():"";if(!s)throw new c("steward_say_empty","There is nothing to say.");if(s.length>l)throw new c("steward_say_too_long",`A message may hold at most ${l} characters.`);const n=d??`steward-say-${m()}`;y(e,{id:n,sessionId:e,role:"agent",ts:Date.now(),payload:x(s,r)});const o=t.sessions.get(e);return o&&r==="say"&&(o.stewardSay={count:(o.stewardSay?.count??0)+1}),R(t.client),{messageId:n}}function O(t){for(const e of L(t,{limit:40})){if(e.role==="user")return!1;if(e.role==="agent"&&E(String(e.payload))?.source==="say")return!0}return!1}function te(t,e,a,r){if(!S(e)||(a.stewardSay?.count??0)>0||W(e)||O(e))return;const s=(a.stewardLastText?.trim()??"")||(r.state==="final"?"\u5DF2\u5904\u7406\uFF0C\u4F46\u6CA1\u6709\u53EF\u663E\u793A\u7684\u56DE\u590D\u3002":r.message?.trim()||"\u8FD9\u6B21\u5904\u7406\u6CA1\u6709\u5B8C\u6210\u3002");try{w(t,e,s.slice(0,l),"fallback",`steward-fallback-${r.runId||"run"}`)}catch{}}const G="\u6765\u81EA\u7EC8\u7AEF",X=new Set(["manager","pi"]);function v(t){const e=T("sha256").update(`${t}\0steward-terminal`).digest("hex"),a=(Number.parseInt(e[16],16)&3|8).toString(16);return`sess_${e.slice(0,8)}-${e.slice(8,12)}-4${e.slice(13,16)}-${a}${e.slice(17,20)}-${e.slice(20,32)}`}function ae(t,e){const a=v(I()),r=M().find(d=>d.sessionId===a);if(r&&r.sessionScope!=="steward")throw new c("steward_scope_conflict","The terminal conversation id is already in use.");if(!r){const s=(t.getAgentSnapshot?.()??[]).find(n=>n.supportsStandardSession!==!1&&!X.has(n.type))?.type??"codex";g({sessionId:a,agentType:s,workDir:h(),sessionScope:"steward",sessionMode:"standard"}),y(a,{id:`${$}${a}`,sessionId:a,role:"user",ts:Date.now(),payload:G})}return{...w(t,a,e),sessionId:a}}const Q={codex:"Codex",claude:"Claude Code",opencode:"OpenCode"},p=t=>Q[t]??t.replace(/^acp:/,"");async function re(t,e,a,r,d){if(r.state!=="error"||!S(e)||(a.stewardSay?.count??0)>0||!t.chatQueue)return!1;const s=d||F(e);if(!s)return!1;const n=H(e,a.agentType),o=P(t.getAgentSnapshot?.()??[],n);if(!o)return!1;const u=k(r.message);C(e);const i=`sess_${m()}`,f=h();g({sessionId:i,agentType:o,workDir:f,sessionScope:"steward",sessionMode:"standard"}),N(e,i,[...n,o]),U(i,b(p(a.agentType),u));try{if(!await t.chatQueue.handleEnqueue({type:"req",id:`steward-failover-${i}`,method:"chat.enqueue",params:{sessionId:i,text:s,agentType:o,workDir:f,sessionMode:"standard",sessionScope:"steward",clientMessageId:`${A}${i}`}}))return _(e),!1}catch{return _(e),!1}return w(t,i,`\u5DF2\u81EA\u52A8\u5207\u6362\u5230 ${p(o)}\uFF08\u539F\u56E0\uFF1A${p(a.agentType)}${q(u)}\uFF09`,"say",`steward-failover-note-${i}`),!0}export{G as STEWARD_TERMINAL_TITLE,c as StewardSayError,te as commitStewardFallback,w as commitStewardSay,ae as commitTerminalStewardSay,v as stewardTerminalSessionId,re as tryStewardFailover};
|
package/dist/src/skill/hosts.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import l from"node:fs";import f from"node:os";import i from"node:path";import{installOfficialSkill as h,updateOfficialSkill as d}from"./updater.js";const m=[{id:"claude",names:["Claude Code"],markers:[".claude"],skillsDir:[".claude","skills"]},{id:"agents",names:["Codex","Cursor","OpenCode","Gemini CLI"],markers:[".codex",".cursor",i.join(".config","opencode"),".gemini"],skillsDir:[".agents","skills"]},{id:"qwen",names:["Qwen Code"],markers:[".qwen"],skillsDir:[".qwen","skills"]}];function u(t=f.homedir()){const s=[];for(const e of m){const r=e.markers.filter(n=>p(i.join(t,n)));if(r.length===0)continue;const c=e.id==="agents"?e.names.filter((n,o)=>r.includes(e.markers[o])):[...e.names];e.id==="claude"&&k(t)||s.push({id:e.id,names:c,path:i.join(t,...e.skillsDir,"shennian","SKILL.md")})}return s}async function w(t){const s=[];for(const e of u(t.home))try{const r=await h(e.path,{clientVersion:t.clientVersion,fetchImpl:t.fetchImpl,registryPath:t.registryPath});s.push({...e,ok:!0,result:r})}catch(r){s.push({...e,ok:!1,error:r instanceof Error?r.message:String(r)})}return s}async function C(t){const s=[];for(const e of u(t.home))if(l.existsSync(e.path))try{const r=await d(e.path,{clientVersion:t.clientVersion,fetchImpl:t.fetchImpl,registryPath:t.registryPath});s.push({...e,ok:!0,result:r})}catch(r){s.push({...e,ok:!1,error:r instanceof Error?r.message:String(r)})}return s}function p(t){try{return l.statSync(t).isDirectory()}catch{return!1}}function k(t){const e=[{dir:i.join(t,".claude","plugins"),depth:0}];for(;e.length>0;){const{dir:r,depth:c}=e.pop();let n;try{n=l.readdirSync(r,{withFileTypes:!0})}catch{continue}for(const o of n){if(!o.isDirectory())continue;const a=i.join(r,o.name);if(o.name==="skills"&&l.existsSync(i.join(a,"shennian","SKILL.md")))return!0;c<5&&e.push({dir:a,depth:c+1})}}return!1}export{m as SKILL_HOSTS,u as detectSkillHostTargets,w as installSkillForHosts,C as refreshExistingSkillForHosts};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import y from"node:crypto";import a from"node:fs";import d from"node:path";import{resolveShennianPath as V}from"../config/index.js";const F="https://shennian.net/skill-manifest.json",k="https://shennian.net/skill.md",u=1440*6e4;async function $(r,t){const e=C(r),i=j(e),s=t.registryPath??V("skill-updates.json"),l=L(s),n=l.targets[e],h=l.checks[e],o=t.now??Date.now(),f=R(e);if(n&&i.sha256!==n.sha256&&!t.replace)return v("local_modified",e,i.version,f);if(h&&h.sha256===i.sha256&&h.clientVersion===t.clientVersion&&!t.forceCheck&&!t.replace&&o-h.lastCheckedAt<u)return{status:h.lastStatus,path:e,localVersion:i.version,remoteVersion:h.remoteVersion,checked:!1,nextCheckAt:h.lastCheckedAt+u,message:"The previous official Skill check is still fresh; the local file was not changed.",...h.lastStatus==="current"||h.lastStatus==="registered"?{}:{officialUrl:k,manualCommand:f}};if(n&&n.clientVersion===t.clientVersion&&!t.forceCheck&&!t.replace&&o-n.lastCheckedAt<u)return{status:n.lastStatus==="updated"?"current":n.lastStatus,path:e,localVersion:i.version,checked:!1,nextCheckAt:n.lastCheckedAt+u,message:n.lastStatus==="check_failed"?"The previous official Skill check failed; continuing with the registered local copy.":"Official Skill check is still fresh; using the registered local copy."};let c;try{c=await x(t.fetchImpl??fetch)}catch{return n?(n.lastCheckedAt=o,n.lastStatus="check_failed",n.clientVersion=t.clientVersion):S(l,e,i,o,"check_failed",t.clientVersion),m(s,l),{status:"check_failed",path:e,localVersion:i.version,checked:!0,nextCheckAt:o+u,message:"Could not verify the official Skill manifest; continuing with the local copy.",officialUrl:k}}if(!I(t.clientVersion,c.skill))return S(l,e,i,o,"client_incompatible",t.clientVersion,c.skill.version),m(s,l),{status:"client_incompatible",path:e,localVersion:i.version,remoteVersion:c.skill.version,checked:!0,nextCheckAt:o+u,message:"The official Skill is not compatible with this Shennian Client version.",officialUrl:k,manualCommand:f};if(g(i.version,c.skill.version)>0)return n?(n.lastCheckedAt=o,n.lastStatus="remote_older",n.clientVersion=t.clientVersion):S(l,e,i,o,"remote_older",t.clientVersion,c.skill.version),m(s,l),{status:"remote_older",path:e,localVersion:i.version,remoteVersion:c.skill.version,checked:!0,nextCheckAt:o+u,message:"The public official Skill is older than this local copy; it was not replaced."};if(!n&&i.sha256===c.skill.sha256)return l.targets[e]={path:e,version:i.version,sha256:i.sha256,lastCheckedAt:o,lastStatus:"registered",clientVersion:t.clientVersion},m(s,l),{status:"registered",path:e,localVersion:i.version,remoteVersion:c.skill.version,checked:!0,nextCheckAt:o+u,message:"Registered this exact official Skill copy for future safe updates."};const U=c.previousSkills?.some(w=>w.version===i.version&&w.sha256===i.sha256)??!1;if(!n&&!U&&!t.replace)return S(l,e,i,o,"manual_update_required",t.clientVersion,c.skill.version),m(s,l),v("manual_update_required",e,i.version,f,c.skill.version);if(n&&i.sha256!==n.sha256&&!t.replace)return v("local_modified",e,i.version,f,c.skill.version);if(i.sha256===c.skill.sha256)return l.targets[e]={path:e,version:i.version,sha256:i.sha256,lastCheckedAt:o,lastStatus:"current",clientVersion:t.clientVersion},m(s,l),{status:"current",path:e,localVersion:i.version,remoteVersion:c.skill.version,checked:!0,nextCheckAt:o+u,message:"The registered official Skill is current."};if(!K(e))return{...v("not_writable",e,i.version,f,c.skill.version),message:"The Skill file is read-only or not a regular file; use the host update mechanism."};let _;try{_=await b(t.fetchImpl??fetch,c)}catch{return n?(n.lastCheckedAt=o,n.lastStatus="check_failed",n.clientVersion=t.clientVersion):S(l,e,i,o,"check_failed",t.clientVersion,c.skill.version),m(s,l),{status:"check_failed",path:e,localVersion:i.version,remoteVersion:c.skill.version,checked:!0,nextCheckAt:o+u,message:"Could not verify the official Skill file; continuing with the local copy.",officialUrl:k}}return O(e,_),l.targets[e]={path:e,version:c.skill.version,sha256:c.skill.sha256,lastCheckedAt:o,lastStatus:"updated",clientVersion:t.clientVersion},m(s,l),{status:"updated",path:e,localVersion:c.skill.version,remoteVersion:c.skill.version,checked:!0,nextCheckAt:o+u,message:"Updated the verified official Skill atomically. Re-read this file now; start a new AI host session if it caches Skills."}}async function W(r,t){const e=C(r);if(T(e))return $(e,{...t,forceCheck:!0});const i=t.fetchImpl??fetch,s=await x(i);if(!I(t.clientVersion,s.skill))return{status:"client_incompatible",path:e,localVersion:s.skill.version,remoteVersion:s.skill.version,checked:!0,message:"The official Skill is not compatible with this Shennian Client version.",officialUrl:k};const l=await b(i,s),n=d.dirname(e);a.mkdirSync(n,{recursive:!0});const h=d.join(n,`.SKILL.md.shennian-${process.pid}-${y.randomUUID()}.tmp`);try{a.writeFileSync(h,l,{flag:"wx",mode:420}),a.renameSync(h,e)}finally{try{a.unlinkSync(h)}catch{}}const o=t.now??Date.now(),f=t.registryPath??V("skill-updates.json"),c=L(f);return c.targets[e]={path:e,version:s.skill.version,sha256:s.skill.sha256,lastCheckedAt:o,lastStatus:"registered",clientVersion:t.clientVersion},delete c.checks[e],m(f,c),{status:"installed",path:e,localVersion:s.skill.version,remoteVersion:s.skill.version,checked:!0,nextCheckAt:o+u,message:"Installed the verified official Skill."}}function T(r){try{return a.lstatSync(r),!0}catch{return!1}}function C(r){if(!d.isAbsolute(r))throw new Error("skill_path_must_be_absolute");const t=d.resolve(r);if(d.basename(t)!=="SKILL.md")throw new Error("skill_path_must_name_SKILL.md");return t}function j(r){const t=a.lstatSync(r);if(!t.isFile()||t.isSymbolicLink())throw new Error("skill_path_must_be_regular_file");const e=a.readFileSync(r);return{version:A(e.toString("utf8")).version,sha256:E(e)}}function A(r){const t=/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(r)?.[1];if(!t||!/^name:\s*shennian\s*$/m.test(t))throw new Error("not_official_shennian_skill");const e=/^version:\s*([^\s]+)\s*$/m.exec(t)?.[1];if(!e||!p(e))throw new Error("invalid_skill_version");return{version:e}}async function x(r){const t=await r(F,{redirect:"error",headers:{Accept:"application/json"},signal:AbortSignal.timeout(1e4)});if(!t.ok)throw new Error("skill_manifest_unavailable");const e=await t.json(),i=e.skill;if(e.schemaVersion!==1||e.product!=="shennian"||!i||i.name!=="shennian"||i.url!==k||!p(i.version)||!p(i.minimumClientVersion)||i.maximumClientVersion!==null&&!p(i.maximumClientVersion)||!/^[a-f0-9]{64}$/.test(i.sha256??"")||e.previousSkills!==void 0&&(!Array.isArray(e.previousSkills)||e.previousSkills.length>32||e.previousSkills.some(s=>!s||!p(s.version)||!/^[a-f0-9]{64}$/.test(s.sha256))))throw new Error("invalid_skill_manifest");return e}async function b(r,t){const e=await r(k,{redirect:"error",headers:{Accept:"text/markdown"},signal:AbortSignal.timeout(1e4)});if(!e.ok)throw new Error("skill_download_unavailable");const i=Number(e.headers.get("content-length"));if(Number.isFinite(i)&&i>512e3)throw new Error("skill_too_large");const s=Buffer.from(await e.arrayBuffer());if(s.length===0||s.length>512e3)throw new Error("skill_too_large");if(E(s)!==t.skill.sha256)throw new Error("skill_integrity_mismatch");if(A(s.toString("utf8")).version!==t.skill.version)throw new Error("skill_version_mismatch");return s}function I(r,t){return!p(r)||g(r,t.minimumClientVersion)<0?!1:t.maximumClientVersion===null||g(r,t.maximumClientVersion)<=0}function K(r){try{const t=a.lstatSync(r);return!t.isFile()||t.isSymbolicLink()?!1:(a.accessSync(r,a.constants.W_OK),a.accessSync(d.dirname(r),a.constants.W_OK),!0)}catch{return!1}}function O(r,t){const e=d.dirname(r),i=a.statSync(r).mode&511,s=d.join(e,`.SKILL.md.shennian-${process.pid}-${y.randomUUID()}.tmp`);let l=null;try{l=a.openSync(s,"wx",i),a.writeFileSync(l,t),a.fsyncSync(l),a.closeSync(l),l=null,a.renameSync(s,r);try{const n=a.openSync(e,"r");a.fsyncSync(n),a.closeSync(n)}catch{}}finally{l!==null&&a.closeSync(l);try{a.unlinkSync(s)}catch{}}}function L(r){try{const t=JSON.parse(a.readFileSync(r,"utf8"));if(t.schemaVersion===1&&t.targets&&typeof t.targets=="object")return{schemaVersion:1,targets:t.targets,checks:t.checks&&typeof t.checks=="object"?t.checks:{}}}catch{}return{schemaVersion:1,targets:{},checks:{}}}function m(r,t){a.mkdirSync(d.dirname(r),{recursive:!0,mode:448});const e=`${r}.${process.pid}.${y.randomUUID()}.tmp`;a.writeFileSync(e,JSON.stringify(t,null,2),{mode:384}),a.renameSync(e,r);try{a.chmodSync(r,384)}catch{}}function v(r,t,e,i,s){return{status:r,path:t,localVersion:e,remoteVersion:s,checked:!0,message:r==="local_modified"?"The local Skill differs from its registered official copy; it was not overwritten.":"This local Skill copy is not registered as the current official file; it was not overwritten.",officialUrl:k,manualCommand:i}}function S(r,t,e,i,s,l,n){r.checks[t]={sha256:e.sha256,version:e.version,lastCheckedAt:i,lastStatus:s,clientVersion:l,remoteVersion:n}}function R(r){return process.platform==="win32"?`shennian skill update --path ${JSON.stringify(r)} --replace --json`:`shennian skill update --path '${r.replaceAll("'","'\\''")}' --replace --json`}function E(r){return y.createHash("sha256").update(r).digest("hex")}function p(r){return typeof r=="string"&&/^\d+\.\d+\.\d+$/.test(r)}function g(r,t){const e=r.split(".").map(Number),i=t.split(".").map(Number);for(let s=0;s<3;s+=1)if(e[s]!==i[s])return e[s]-i[s];return 0}export{F as OFFICIAL_SKILL_MANIFEST_URL,k as OFFICIAL_SKILL_URL,u as SKILL_CHECK_INTERVAL_MS,W as installOfficialSkill,$ as updateOfficialSkill};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const d={not_installed:"\u6CA1\u6709\u5B89\u88C5\u6216\u627E\u4E0D\u5230\u7A0B\u5E8F",not_logged_in:"\u6CA1\u6709\u767B\u5F55\u6216\u6388\u6743\u5931\u6548",quota:"\u989D\u5EA6\u7528\u5B8C\u6216\u88AB\u9650\u6D41",crashed:"\u542F\u52A8\u5931\u8D25\u6216\u8FD0\u884C\u4E2D\u65AD"};function p(e){return d[e]}function S(e){const t=(e??"").toLowerCase();return/enoent|command not found|not installed|command_unavailable|runtime_unavailable|no such file|未找到|未安装/.test(t)?"not_installed":/log ?in|logged in|sign in|unauthori[sz]ed|\b401\b|\b403\b|auth(?:entication|_required)?\b|api key|credential|未登录|登录/.test(t)?"not_logged_in":/quota|usage limit|rate limit|too many requests|\b429\b|insufficient|credit|billing|exceeded|额度|用完|限流/.test(t)?"quota":"crashed"}const c=new Set(["manager","pi","pi-coding-agent"]);function x(e,t){const n=new Set(t);return e.find(r=>r.supportsStandardSession!==!1&&!c.has(r.type)&&r.authState!=="required"&&r.authState!=="error"&&!n.has(r.type))?.type??null}function h(e,t){return[`\u8FD9\u6BB5\u5BF9\u8BDD\u662F\u4ECE\u300C${e}\u300D\u81EA\u52A8\u5207\u6362\u8FC7\u6765\u7684\uFF08\u539F\u56E0\uFF1A${d[t]}\uFF09\u3002`,"\u4E0A\u4E00\u4E2A AI \u53EF\u80FD\u5DF2\u7ECF\u505A\u4E86\u4E00\u90E8\u5206\u64CD\u4F5C\uFF1A\u52A8\u624B\u524D\u5148\u6838\u5BF9\u73B0\u72B6\uFF08\u4F8B\u5982 shennian project task list \u770B\u5DF2\u5EFA\u7684\u4EFB\u52A1\uFF09\uFF0C","\u4E0D\u8981\u91CD\u590D\u6267\u884C\u6709\u526F\u4F5C\u7528\u7684\u64CD\u4F5C\uFF0C\u4E5F\u4E0D\u8981\u91CD\u590D\u521B\u5EFA\u5DF2\u5B58\u5728\u7684\u4EFB\u52A1\uFF1B\u6838\u5BF9\u540E\u518D\u7EE7\u7EED\u56DE\u5E94\u7528\u6237\u7684\u8FD9\u6761\u6D88\u606F\u3002"].join("")}const u=new Map,o=new Map,a=new Map,l=200;function i(e){for(;e.size>l;)e.delete(e.keys().next().value);return e}function _(e,t){i(u).set(e,t)}function g(e){return u.get(e)??""}function b(e,t){const n=o.get(e)??[];return n.includes(t)?n:[...n,t]}function A(e,t,n){i(o).set(t,[...n]),o.delete(e)}function T(e,t){i(a).set(e,t)}function m(e){const t=a.get(e)??"";return a.delete(e),t}function y(e){o.delete(e)}const s=new Map,w=6e4;function v(e){i(s).set(e,Date.now())}function k(e){const t=s.get(e);return t!==void 0&&Date.now()-t<w}function E(e){s.delete(e)}export{h as buildHandoverNote,A as carryStewardChain,S as classifyStewardFailure,E as clearStewardSwitched,g as lastStewardUserText,v as markStewardSwitched,x as pickFailoverAgent,_ as rememberStewardTurn,y as resetStewardChain,T as setStewardHandover,p as stewardFailureLabel,b as stewardTriedAgents,m as takeStewardHandover,k as wasStewardJustSwitched};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const E=/^\s*::git-[a-z-]+\{[^\n]*\}\s*$/gm,g=/^\s*\{\s*"v"\s*:\s*1\s*,\s*"type"\s*:\s*"(tool|tool_use|tool_result)"/,
|
|
1
|
+
const E=/^\s*::git-[a-z-]+\{[^\n]*\}\s*$/gm,g=/^\s*\{\s*"v"\s*:\s*1\s*,\s*"type"\s*:\s*"(tool|tool_use|tool_result)"/,R=/^\s*<environment_context>\s*[^]*?<\/environment_context>\s*$/i,S=/<(cwd|shell|current_date|timezone)>[^<]*<\/\1>/gi,x=/^\s*<recommended_plugins>[^]*?<\/recommended_plugins>\s*/i,P=/^\s*<turn_aborted>[^]*?<\/turn_aborted>\s*$/i,b=/^\s*<codex_internal_context\b[^>]*>[^]*?<\/codex_internal_context>\s*$/i,T=/^\s*# AGENTS\.md instructions for [^\n]+\n+\s*<INSTRUCTIONS>\s*[^]*?<\/INSTRUCTIONS>\s*(?:<environment_context>[^]*?<\/environment_context>)?\s*$/i,A=/^\s*\{\s*"v"\s*:\s*1\s*,\s*"type"\s*:\s*"approval_pending"/,I=/(?:<\/?(?:environment_context|instructions|system|developer|codex_internal_context|recommended_plugins)\b|#\s*AGENTS\.md instructions\b)/i,h=/\bdata:[a-z0-9.+-]+\/[a-z0-9.+-]+;base64,[a-z0-9+/=\s]+/i,N=/(?:^|\s)(?=[A-Za-z0-9+/]{80,}={0,2}(?=\s|$))(?=[A-Za-z0-9+/]*[A-Z])(?=[A-Za-z0-9+/]*[a-z])(?=[A-Za-z0-9+/]*[0-9])[A-Za-z0-9+/]{80,}={0,2}(?=\s|$)/,v=new Set(["tool","tool_use","tool_result","thinking","system","developer","context","environment_context","channel_delivery_status"]),L="steward-terminal-open-",G="steward-failover-user-";function O(e){return e.replace(/[[\]\\]/g,"\\$&")}function C(e){const t=O(e.name);return e.kind==="image"?``:`[${t}](<${e.path}>)`}function w(e,t){if(!t?.length)return e;const n=new Set(t.map(C));return e.split(`
|
|
2
2
|
`).filter(s=>!n.has(s.trim())).join(`
|
|
3
3
|
`).replace(/\n{3,}/g,`
|
|
4
4
|
|
|
5
|
-
`).trim()}function u(e){if(!e||e[0]!=="{")return null;try{const t=JSON.parse(e);if(typeof t=="object"&&t!==null)return t}catch{}return null}function D(e){if(typeof e!="object"||e===null)return null;const t=e,n=typeof t.path=="string"?t.path:"",r=typeof t.name=="string"?t.name:"",s=typeof t.mimeType=="string"?t.mimeType:"",l=t.kind==="image"||t.kind==="file"||t.kind==="folder"?t.kind:null;if(!n||!r||!s||!l)return null;const f=typeof t.previewData=="string"&&t.previewData.trim()?t.previewData.trim():void 0,p=typeof t.byteSize=="number"&&Number.isSafeInteger(t.byteSize)&&t.byteSize>=0?t.byteSize:void 0,d=typeof t.sha256=="string"&&/^[a-f0-9]{64}$/i.test(t.sha256)?t.sha256.toLowerCase():void 0;return{path:n,name:r,mimeType:s,kind:l,...p!==void 0?{byteSize:p}:{},...d?{sha256:d}:{},...f?{previewData:f}:{}}}function o(e){const t=u(e);if(!t||t.v!==1)return null;if(t.type==="user"&&typeof t.content=="string"){const n=Array.isArray(t.attachments)?t.attachments.map(D).filter(r=>r!=null):void 0;return{v:1,type:"user",content:t.content,...n?.length?{attachments:n}:{}}}return t}function z(e){const t=o(e);return t?.type==="user"?t:null}function
|
|
5
|
+
`).trim()}function u(e){if(!e||e[0]!=="{")return null;try{const t=JSON.parse(e);if(typeof t=="object"&&t!==null)return t}catch{}return null}function D(e){if(typeof e!="object"||e===null)return null;const t=e,n=typeof t.path=="string"?t.path:"",r=typeof t.name=="string"?t.name:"",s=typeof t.mimeType=="string"?t.mimeType:"",l=t.kind==="image"||t.kind==="file"||t.kind==="folder"?t.kind:null;if(!n||!r||!s||!l)return null;const f=typeof t.previewData=="string"&&t.previewData.trim()?t.previewData.trim():void 0,p=typeof t.byteSize=="number"&&Number.isSafeInteger(t.byteSize)&&t.byteSize>=0?t.byteSize:void 0,d=typeof t.sha256=="string"&&/^[a-f0-9]{64}$/i.test(t.sha256)?t.sha256.toLowerCase():void 0;return{path:n,name:r,mimeType:s,kind:l,...p!==void 0?{byteSize:p}:{},...d?{sha256:d}:{},...f?{previewData:f}:{}}}function o(e){const t=u(e);if(!t||t.v!==1)return null;if(t.type==="user"&&typeof t.content=="string"){const n=Array.isArray(t.attachments)?t.attachments.map(D).filter(r=>r!=null):void 0;return{v:1,type:"user",content:t.content,...n?.length?{attachments:n}:{}}}return t}function z(e){const t=o(e);return t?.type==="user"?t:null}function F(e,t){return t?.length?JSON.stringify({v:1,type:"user",content:e,attachments:t}):e}function $(e){if(g.test(e))return!0;const t=o(e);return!t||typeof t!="object"?!1:t.type==="tool"||t.type==="tool_use"||t.type==="tool_result"}function k(e){return A.test(e)?!0:o(e)?.type==="approval_pending"}function j(e,t="say"){return JSON.stringify({v:1,type:"steward_say",content:e,source:t})}function J(e){const t=o(e);if(!t||t.type!=="steward_say")return null;const n=t;return typeof n.content!="string"||!n.content.trim()?null:{v:1,type:"steward_say",content:n.content,source:n.source==="fallback"?"fallback":"say"}}function W(e){return V(e)?.agentVisible===!1}function V(e){const t=o(e);if(!t||t.type!=="channel_delivery_status")return null;const n=t;if(n.v!==1||n.channel!=="wechat"||n.agentVisible!==!1)return null;const r=typeof n.status=="string"&&n.status.trim()?n.status.trim():"";if(!r)return null;const s=typeof n.content=="string"&&n.content.trim()?n.content:r==="manual_review"?"\u53D1\u9001\u72B6\u6001\u4E0D\u786E\u5B9A\uFF0C\u8BF7\u68C0\u67E5\u5FAE\u4FE1":"\u672A\u80FD\u81EA\u52A8\u53D1\u9001\u5230\u5FAE\u4FE1";return{v:1,type:"channel_delivery_status",channel:"wechat",status:r,agentVisible:!1,content:s,replyId:i(n.replyId),idempotencyKey:i(n.idempotencyKey),bindingId:i(n.bindingId),reasonCode:i(n.reasonCode),copyText:i(n.copyText),copyableContentRef:i(n.copyableContentRef),errorSummary:i(n.errorSummary)}}function X(e){const t=e?.trim();return`${!t||t==="codex"?"Codex":t==="workbuddy"?"WorkBuddy":t} \u6B63\u5728\u7B49\u5F85\u7528\u6237\u786E\u8BA4\u540E\u7EE7\u7EED\u3002`}function Z(e){return JSON.stringify({v:1,type:"approval_pending",title:e?.title?.trim()||"\u9700\u8981\u7528\u6237\u786E\u8BA4",content:e?.content?.trim()||X(e?.source),source:e?.source?.trim()||"codex",actionHint:e?.permission?e?.actionHint?.trim():e?.actionHint?.trim()||"\u5F53\u524D\u795E\u5FF5\u6682\u4E0D\u652F\u6301\u8FDC\u7A0B\u786E\u8BA4\uFF0C\u8BF7\u56DE\u5230\u8FD0\u884C Codex \u7684\u7535\u8111/\u7EC8\u7AEF\u5B8C\u6210\u786E\u8BA4\u3002",...e?.permission?{permission:e.permission}:{}})}function _(e){if(!R.test(e))return!1;const t=new Set;for(const n of e.matchAll(S))n[1]&&t.add(n[1].toLowerCase());return t.has("current_date")&&t.has("timezone")&&e.includes("<workspace_roots>")?!0:t.has("cwd")&&t.has("shell")&&t.has("current_date")&&t.has("timezone")}function M(e){return P.test(e)}function y(e){return T.test(e)}function U(e){const t=e.match(x);if(t){const n=e.slice(t[0].length).trim();return!n||_(n)||y(n)}return _(e)||M(e)||b.test(e)||y(e)}function c(e){if(!e)return"";const t=e.replace(/\r\n/g,`
|
|
6
6
|
`);if(!/(^|\n)\s*::git-[a-z-]+\{[^\n]*\}\s*(?=\n|$)/.test(t))return t;const r=t.replace(E,"");return r.trim()?r.replace(/[ \t]+\n/g,`
|
|
7
7
|
`).replace(/\n+$/g,""):""}function m(e){if(!e)return"";const t=z(e);if(t)return w(t.content,t.attachments);const n=o(e);if(n){if(typeof n.content=="string")return c(n.content);if("text"in n&&typeof n.text=="string")return c(n.text)}try{const r=JSON.parse(e);if(typeof r=="string")return r;if(typeof r=="object"&&r!==null){const s=r;if(typeof s.content=="string")return c(s.content);if(typeof s.text=="string")return c(s.text)}}catch{}return c(e)}function a(e,t=160){if(typeof e!="string"||!Number.isSafeInteger(t)||t<1)return null;const n=e.replace(/\r\n/g,`
|
|
8
|
-
`).trim();if(!n||
|
|
8
|
+
`).trim();if(!n||I.test(n)||h.test(n)||N.test(n)||u(n))return null;const r=n.replace(/\s+/g," ");return r.length>t?`${r.slice(0,t)}\u2026`:r}function B(e,t=160){if(!e||$(e)||U(e))return null;if(k(e))return a("\u9700\u8981\u7528\u6237\u786E\u8BA4",t);const n=o(e);if(n){const r=typeof n.type=="string"?n.type.toLowerCase():"";return!r||v.has(r)?null:a(m(e),t)}return u(e)?null:a(m(e),t)}function i(e){return typeof e=="string"&&e.trim()?e:void 0}export{G as STEWARD_FAILOVER_USER_MESSAGE_ID_PREFIX,L as STEWARD_TERMINAL_OPEN_MESSAGE_ID_PREFIX,Z as buildApprovalPendingPayload,j as buildStewardSayPayload,F as buildUserMessagePayload,m as extractPayloadText,W as isAgentHiddenPayload,k as isApprovalPendingPayload,y as isCodexProjectInstructionsPayload,M as isCodexTurnAbortedPayload,U as isSystemControlPayload,_ as isSystemEnvironmentContextPayload,$ as isToolPayload,V as parseChannelDeliveryStatusPayload,J as parseStewardSayPayload,o as parseStructuredMessagePayload,z as parseUserMessagePayload,a as sanitizeSessionPreview,B as sessionPreviewFromPayload,c as stripGitDirectiveArtifacts};
|