shennian 0.3.27 → 0.3.28
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.
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import E from"node:crypto";import{callDaemonIpc as T}from"../daemon-ipc/client.js";import{DaemonIpcError as
|
|
2
|
-
`)}function
|
|
1
|
+
import E from"node:crypto";import{callDaemonIpc as T}from"../daemon-ipc/client.js";import{DaemonIpcError as h}from"../daemon-ipc/protocol.js";import{normalizeRoomActionParameters as z}from"../room/room-action-schema.js";import{SHENNIAN_ROOM_TOOL_NAME as N}from"../room/tool-schema.js";import{roomMcpHostToolName as O}from"./room-plugin-shared.js";const H=256*1024,_={SessionStart:"active",UserPromptSubmit:"active",PreCompact:"active",PostCompact:"active",PreToolUse:"active",Stop:"idle",SessionEnd:"idle"};async function F(t,o=process.stdin,n=process.stdout,r=T){let s="";for await(const a of o)if(s+=Buffer.isBuffer(a)?a.toString("utf8"):String(a),Buffer.byteLength(s,"utf8")>H)return"ignored";const e=j(t,s);if(!e)return"ignored";let d=!1;try{await r({method:"room-host-session.observe",params:{runtimeAdapter:e.runtimeAdapter,sourceSessionKey:e.sourceSessionKey,hostContextHash:e.hostContextHash,workspaceHash:e.workspaceHash,workspacePath:e.workspacePath,lifecycleState:e.lifecycleState,eventName:e.eventName},timeoutMs:2e3})}catch(a){if(a instanceof h&&a.code==="machine_not_authorized")d=!0;else return"unavailable"}if(e.eventName!=="PreToolUse")return"observed";if(e.toolName!==O(e.runtimeAdapter)||!e.toolInput)return"ignored";let i=null,c="";try{if(i=K(e.toolInput),c=C(e,i),i.action==="room.create"||i.action==="room.join")try{const u=await r({method:"authorized-action.status",params:{idempotencyKey:c},timeoutMs:2e3}),I=A(u);return S(n,e.runtimeAdapter,e.toolInput,I),"authorized"}catch(u){if(!(u instanceof h)||u.code!=="pending_action_not_found")throw u}if(d)return await w(e,i,c,n,r);const a=await r({method:"room-session.resolve",params:{runtimeAdapter:e.runtimeAdapter,sourceSessionKey:e.sourceSessionKey},timeoutMs:2e3}),l=x(a),P=await r({method:"room-invocation.issue",params:{registryKey:l,action:i.action,targetTool:N,actionParameters:i.actionParameters},timeoutMs:2e3}),k=v(P),b={action:e.toolInput.action,...$(i.actionParameters),_shennianRegistryKey:l,_shennianInvocationToken:k};return y(n,{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",permissionDecisionReason:"Authorized by the local Shennian daemon for this Agent conversation.",...g(e.runtimeAdapter,b)}}),"authorized"}catch(a){if(a instanceof h&&a.code==="machine_not_authorized"&&i&&(i.action==="room.create"||i.action==="room.join"))try{return await w(e,i,c,n,r)}catch{}return y(n,{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:"This Agent conversation is not connected to Shennian yet. Open it from Shennian or use the repair connection action."}}),"denied"}}async function w(t,o,n,r,s){if(o.action!=="room.create"&&o.action!=="room.join")throw new Error("authorization_requires_onboarding_action");const e=await s({method:"authorized-action.create",params:{actionType:o.action,actionSummary:M(o.action,o.actionParameters),actionPayload:U(t,o),idempotencyKey:n,returnTo:"/spaces"},timeoutMs:12e3});return S(r,t.runtimeAdapter,t.toolInput,A(e)),"authorized"}function j(t,o){if(t!=="codex"&&t!=="claude_code"&&t!=="workbuddy")return null;let n;try{n=JSON.parse(o)}catch{return null}if(!n||typeof n!="object"||Array.isArray(n))return null;const r=n,s=m(r.session_id,1024),e=D(r.hook_event_name);if(!s||!e)return null;const d=m(r.transcript_path,4096)??"",i=m(r.cwd,4096)??"",c=e==="PreToolUse"?m(r.tool_name,256):null,a=e==="PreToolUse"?B(r.tool_input):null,l=e==="PreToolUse"?m(r.tool_use_id??r.tool_call_id,512):null;return{runtimeAdapter:t,sourceSessionKey:s,hostContextHash:f(`${s}\0${d}`),workspaceHash:i?f(i):null,workspacePath:i||null,lifecycleState:_[e],eventName:e,toolName:c,toolInput:a,toolRequestId:l}}function K(t){const o=R(t.action);if(Object.keys(t).some(r=>r.startsWith("_shennian")))throw new Error("hidden_input");const n=Object.fromEntries(Object.entries(t).filter(([r])=>r!=="action"));return{action:o,actionParameters:z(o,n)}}function $(t){if(!t||Array.isArray(t)||typeof t!="object")throw new Error("invalid_action_parameters");return t}function R(t){const o={create:"room.create",join:"room.join",read:"room.read",send:"room.send",mode:"room.mode",status:"room.status"};if(typeof t!="string"||!(t in o))throw new Error("invalid_action");return o[t]}function x(t){const o=p(t,"registryKey");if(!/^[a-f0-9]{64}$/.test(o))throw new Error("invalid_registry");return o}function v(t){const o=p(t,"invocationToken");if(!/^sni_v1_[A-Za-z0-9_-]{40,80}$/.test(o))throw new Error("invalid_token");return o}function A(t){const o=p(t,"id");if(!/^[A-Za-z0-9_-]{8,128}$/.test(o))throw new Error("invalid_pending_action");return o}function C(t,o){const n=t.toolRequestId??f(JSON.stringify(o.actionParameters));return`${o.action.replace(".","-")}-auth:${f(`${t.runtimeAdapter}\0${t.sourceSessionKey}\0${n}`)}`}function U(t,o){return{schemaVersion:1,runtimeAdapter:t.runtimeAdapter,sourceSessionKey:t.sourceSessionKey,hostContextHash:t.hostContextHash,workspaceHash:t.workspaceHash,workspacePath:t.workspacePath,lifecycleState:t.lifecycleState,action:o.action,actionParameters:o.actionParameters}}function M(t,o){if(!o||Array.isArray(o)||typeof o!="object")throw new Error("invalid_authorized_action");const n=typeof o.agentAlias=="string"?o.agentAlias:"";return t==="room.create"?`\u521B\u5EFA\u7FA4\u804A\u300C${typeof o.name=="string"?o.name:""}\u300D\uFF0C\u5E76\u4EE5 Agent\u300C${n}\u300D\u52A0\u5165`:`\u4F7F\u7528\u5F53\u524D\u9080\u8BF7\u52A0\u5165\u7FA4\u804A\uFF0C\u5E76\u4EE5 Agent\u300C${n}\u300D\u53C2\u4E0E`}function S(t,o,n,r){const s={...n,_shennianAuthorizedActionId:r};y(t,{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",permissionDecisionReason:"Shennian will open a secure browser authorization and continue this action automatically.",...g(o,s)}})}function g(t,o){return t==="workbuddy"?{updatedInput:o,modifiedInput:o}:{updatedInput:o}}function p(t,o){if(!t||Array.isArray(t)||typeof t!="object")throw new Error("invalid_response");const n=t[o];if(typeof n!="string")throw new Error("invalid_response");return n}function D(t){return typeof t=="string"&&t in _?t:null}function m(t,o){if(typeof t!="string")return null;const n=t.trim();return!n||n.length>o||/[\0\r\n]/.test(n)?null:n}function B(t){return!t||typeof t!="object"||Array.isArray(t)?null:t}function y(t,o){t.write(`${JSON.stringify(o)}
|
|
2
|
+
`)}function f(t){return E.createHash("sha256").update(t,"utf8").digest("hex")}export{j as parseRoomSessionHookInput,F as runRoomSessionHook};
|