shennian 0.5.32 → 0.5.35
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 +50 -30
- package/dist/src/agents/codex-approvals.js +2 -0
- package/dist/src/agents/codex-conversation-settings.js +1 -0
- package/dist/src/agents/codex-runtime.js +9 -8
- package/dist/src/agents/codex-user-question.js +4 -0
- package/dist/src/agents/codex.js +3 -3
- package/dist/src/agents/command-spec.js +1 -1
- package/dist/src/agents/public-delivery-worker.js +1 -1
- package/dist/src/agents/public-turn-runner.js +3 -3
- package/dist/src/agents/public-workdir.js +1 -1
- package/dist/src/commands/agent-workspace.js +2 -2
- package/dist/src/native-fusion/codex-parser.js +3 -3
- package/dist/src/session/handlers/chat-adapter-config.js +1 -1
- package/dist/src/session/handlers/codex-settings.js +1 -0
- package/dist/src/session/handlers/title.js +1 -1
- package/dist/src/session/manager.js +1 -1
- package/dist/src/session/native-cleanup-outbox.js +2 -2
- package/dist/src/session/native-session-lifecycle.js +6 -6
- package/dist/src/session/store.js +1 -1
- package/node_modules/@shennian/wire/dist/codex-settings.js +1 -0
- package/node_modules/@shennian/wire/dist/index.js +1 -1
- package/node_modules/@shennian/wire/dist/message-payload.js +5 -5
- package/package.json +1 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import T from"node:crypto";import R from"node:fs/promises";import k from"node:path";import{DEFAULT_RESTRICTED_MANAGED_AGENT_PERMISSION_POLICY as F}from"@shennian/wire";import{getShennianDir as j}from"../config/index.js";import{callDaemonIpc as z}from"../daemon-ipc/client.js";import{DaemonIpcError as O}from"../daemon-ipc/protocol.js";import{PublicAgentClient as J,PublicAgentClientError as D}from"../agents/public-agent-client.js";const G={write:e=>process.stdout.write(e),fail:()=>{process.exitCode=1}};function ae(e,t={}){const o=t.client??new J,r=t.io??G,g=t.callDaemon??z;e.command("list").description("List Shennian Agents owned by the paired user on this computer").action(()=>s("agent.list",r,()=>o.list())),e.command("get <agent-id>").description("Read one exact Shennian Agent").action(i=>s("agent.get",r,()=>o.get(d(i,"agent_id_invalid")))),e.command("create").description("Check one local AI configuration, then create a Shennian Agent (full access unless --file-access is set)").requiredOption("--name <name>","Agent display name").requiredOption("--description <description>","Public Room introduction").requiredOption("--agent <type>","Exact type returned by agent discover").requiredOption("--workdir <path>","Absolute working directory on this computer").option("--model <id>","Exact model id returned by agent discover").option("--system-prompt <prompt>","Private system prompt","").option("--file-access <mode>","Codex restricted file access: workspace-read or workspace-write; denies network, web, browser, computer use and MCP").action(i=>s("agent.create",r,async()=>{const n=L(i);return await I(n,g),o.create(n)})),e.command("share").description("Publish an existing Agent by --agent-id, or create one and return a usable link").option("--agent-id <id>","Exact id of an existing Shennian Agent").option("--name <name>","New Agent and public display name").option("--agent <type>","New Agent type returned by agent discover").option("--workdir <path>","Working directory; otherwise create an empty private directory").option("--model <id>","Exact model id returned by agent discover").option("--description <description>","Public introduction","").option("--system-prompt <prompt>","Private system prompt","").option("--file-access <mode>","Codex restricted file access: workspace-read or workspace-write; denies network, web, browser, computer use and MCP").option("--anonymous","Allow browser-scoped visitors to chat without signing in").action(i=>s("agent.share",r,async()=>{let n="",p;if(i.agentId)(i.name||i.agent||i.workdir||i.model||i.systemPrompt||i.description||i.fileAccess)&&a("agent_share_ambiguous","Use --agent-id alone for an existing Agent; edit its settings separately."),n=d(i.agentId,"agent_id_invalid"),p=S(await o.get(n)),p.status!=="active"&&a("agent_unavailable","This Agent is not active.");else{(!i.name||!i.agent)&&a("agent_share_selection_required","Provide --agent-id for an existing Agent, or --name and --agent for a new one.");const m=i.workdir?q(i.workdir):await B();p=L({...i,name:i.name,agent:i.agent,systemPrompt:i.systemPrompt??"",description:i.description||i.name,workdir:m})}if(await I(p,g),!i.agentId){const m=S(await o.create(p));n=f(m.id,"invalid_server_response")}const u=i.agentId?(await o.getPublication(n)).publication:null;if((!u||typeof u=="object"&&!Array.isArray(u)&&u.status==="revoked")&&await o.createPublicationDraft(n,{displayName:f(p.displayName,"invalid_server_response"),description:typeof p.description=="string"?p.description:"",dailyMessageLimit:100}),i.anonymous){const m=y(u??(await o.getPublication(n)).publication,"invalid_server_response");m.allowAnonymousVisitors!==!0&&await o.setPublicationAnonymousAccess(n,!0,P(m.generation),P(m.policyVersion))}const l=y((await o.getPublication(n)).publication,"invalid_server_response");if(l.status!=="active"){const m=y((await o.getPublicationReadiness(n)).readiness,"invalid_server_response");m.activationAvailable!==!0&&a("agent_publication_not_ready",`Agent ${n} exists, but cannot be shared yet: ${JSON.stringify(m.blockers??[])}. No usable link was returned.`),y((await o.activatePublication(n,P(l.generation),P(l.policyVersion))).publication,"invalid_server_response").status!=="active"&&a("agent_publication_inactive",`Agent ${n} exists, but publication is not active.`)}const _=y((await o.getPublication(n)).publication,"invalid_server_response");return(_.status!=="active"||typeof _.shareUrl!="string")&&a("agent_publication_unconfirmed",`Agent ${n} was created, but an active share URL could not be confirmed.`),i.anonymous&&_.allowAnonymousVisitors!==!0&&a("agent_publication_guest_unconfirmed",`Agent ${n} was published, but browser guest access could not be confirmed.`),{agentId:n,status:"active",shareUrl:_.shareUrl,visitorAccess:i.anonymous?"browser_guest_allowed":"sign_in_required"}})),e.command("update <agent-id>").description("Update one exact Shennian Agent; runtime changes are checked before saving").option("--name <name>","Agent display name").option("--description <description>","Public Room introduction").option("--agent <type>","Exact type returned by agent discover").option("--workdir <path>","Absolute working directory on this computer").option("--model <id>","Exact model id returned by agent discover").option("--clear-model","Use the runtime default model").option("--system-prompt <prompt>","Private system prompt").action((i,n)=>s("agent.update",r,async()=>{const p=d(i,"agent_id_invalid"),u=H(n);Object.keys(u).length||a("agent_changes_required","Provide at least one Agent field to update.");const l=S(await o.get(p)),_={...l,...u};return M(l)!==M(_)&&await I(_,g),o.update(p,u)})),e.command("delete <agent-id>").description("Delete one exact Shennian Agent and its dedicated Room conversations").action(i=>s("agent.delete",r,()=>o.delete(d(i,"agent_id_invalid"))));const w=e.command("room").description("List, add, or remove this Agent in explicit Rooms");w.command("list <agent-id>").description("List Rooms currently linked to one exact Agent").action(i=>s("agent.room.list",r,()=>o.listRooms(d(i,"agent_id_invalid")))),w.command("add <agent-id> <room-url>").description("Create a dedicated conversation and add this Agent to one explicit Room").option("--mode <mode>","auto_follow, mention_only, or paused","auto_follow").action((i,n,p)=>s("agent.room.add",r,async()=>{const u=d(i,"agent_id_invalid"),l=N(n),_=K(p.mode),m=`cli-agent-room:${T.randomUUID()}`,A=await o.createRoomSession(u,{roomId:l,assignmentIntentId:m,activationMode:_});if(A.existing===!0)return A;const x=y(A.session,"invalid_server_response"),C=f(x.id,"invalid_server_response"),V=f(x.agentType,"invalid_server_response"),$=await g({method:"room.agent.bind-managed",params:{roomId:l,agentIdentityId:u,nianSessionId:C,assignmentIntentId:m,agentType:V,activationMode:_},timeoutMs:12e4});return{session:x,binding:$}})),w.command("remove <agent-id> <room-url>").description("Remove this Agent from one explicit Room and delete its dedicated conversation").action((i,n)=>s("agent.room.remove",r,()=>o.removeFromRoom(d(i,"agent_id_invalid"),N(n))));const v=e.command("publication").description("Manage one Agent publication by exact Agent id");v.command("get <agent-id>").description("Read publication status and versions").action(i=>s("agent.publication.get",r,()=>o.getPublication(d(i,"agent_id_invalid")))),v.command("readiness <agent-id>").description("Read the current machine and runtime checks for one exact Agent publication").action(i=>s("agent.publication.readiness",r,()=>o.getPublicationReadiness(d(i,"agent_id_invalid")))),v.command("draft <agent-id>").description("Create an inactive publication draft; this does not expose a share URL").requiredOption("--name <name>","Public display name").requiredOption("--description <description>","Public introduction").option("--daily-limit <count>","Visitor messages per day","100").action((i,n)=>s("agent.publication.draft",r,()=>o.createPublicationDraft(d(i,"agent_id_invalid"),{displayName:c(n.name,80,"publication_name_invalid",!0),description:c(n.description,1e3,"publication_description_invalid"),dailyMessageLimit:E(n.dailyLimit)}))),v.command("update <agent-id>").description("Update publication details with versions from publication get").requiredOption("--generation <number>","Expected generation").requiredOption("--policy-version <number>","Expected policy version").requiredOption("--name <name>","Public display name").requiredOption("--description <description>","Public introduction").requiredOption("--daily-limit <count>","Visitor messages per day").action((i,n)=>s("agent.publication.update",r,()=>o.updatePublication(d(i,"agent_id_invalid"),{expectedGeneration:b(n.generation,"publication_generation_invalid"),expectedPolicyVersion:b(n.policyVersion,"publication_policy_version_invalid"),displayName:c(n.name,80,"publication_name_invalid",!0),description:c(n.description,1e3,"publication_description_invalid"),dailyMessageLimit:E(n.dailyLimit)}))),v.command("anonymous <agent-id>").description("Enable or disable browser-scoped chats without sign-in on one publication").requiredOption("--generation <number>","Expected generation").requiredOption("--policy-version <number>","Expected policy version").requiredOption("--allowed <value>","true or false").action((i,n)=>s("agent.publication.anonymous",r,()=>o.setPublicationAnonymousAccess(d(i,"agent_id_invalid"),Z(n.allowed),b(n.generation,"publication_generation_invalid"),b(n.policyVersion,"publication_policy_version_invalid")))),v.command("pause <agent-id>").description("Pause an active publication using exact versions").requiredOption("--generation <number>","Expected generation").requiredOption("--policy-version <number>","Expected policy version").action((i,n)=>s("agent.publication.pause",r,()=>o.pausePublication(d(i,"agent_id_invalid"),b(n.generation,"publication_generation_invalid"),b(n.policyVersion,"publication_policy_version_invalid")))),v.command("activate <agent-id>").description("Activate a draft or resume a paused publication only after server release and runtime checks").requiredOption("--generation <number>","Expected generation").requiredOption("--policy-version <number>","Expected policy version").action((i,n)=>s("agent.publication.activate",r,()=>o.activatePublication(d(i,"agent_id_invalid"),b(n.generation,"publication_generation_invalid"),b(n.policyVersion,"publication_policy_version_invalid")))),v.command("revoke <agent-id>").description("Revoke a publication and invalidate its old share URL").requiredOption("--generation <number>","Expected generation").action((i,n)=>s("agent.publication.revoke",r,()=>o.revokePublication(d(i,"agent_id_invalid"),b(n.generation,"publication_generation_invalid")))),v.command("conversations <agent-id>").description("List this publication\u2019s conversations, one page at a time").option("--cursor <cursor>","Opaque next cursor from the previous page").action((i,n)=>s("agent.publication.conversations",r,()=>o.listPublicationConversations(d(i,"agent_id_invalid"),n.cursor)));const h=e.command("public").description("Use the same published Agent URL as a human visitor");h.command("list").description("List your own existing conversations, including history after a link is revoked").option("--cursor <cursor>","Opaque next cursor from the previous page").action(i=>s("agent.public.list",r,()=>o.listMyDirectConversations(i.cursor))),h.command("open <url>").description("Read public Agent details from an exact Shennian share URL").action(i=>s("agent.public.open",r,()=>o.openPublishedAgent(i))),h.command("read <url>").description("Read your latest messages, or page older / follow newer messages").option("--after <cursor>","Read messages after this sequence").option("--before <cursor>","Read older messages before this sequence (default: latest)").action((i,n)=>s("agent.public.read",r,()=>o.readPublishedAgent(i,n))),h.command("history <conversation-id>").description("Read your latest conversation history by stable ID after URL revocation").option("--after <cursor>","Read messages after this sequence").option("--before <cursor>","Read older messages before this sequence (default: latest)").action((i,n)=>s("agent.public.history",r,()=>o.readDirectConversation(d(i,"conversation_id_invalid"),n))),h.command("send <url> <message>").description("Send one message as the paired human user; requires an active publication").requiredOption("--client-message-id <id>","Stable ID for idempotent retries (letters, digits, _ or -)").action((i,n,p)=>s("agent.public.send",r,async()=>{const u=W(p.clientMessageId),l=await o.sendPublishedAgent(i,{text:c(n,2e4,"publication_message_invalid",!0),clientMessageId:u});return{...l,...typeof l.conversationId=="string"?{conversationRef:l.conversationId}:{},clientMessageId:u}}))}function b(e,t){/^[1-9][0-9]*$/.test(e)||a(t,"Use a positive integer.");const o=Number(e);return Number.isSafeInteger(o)||a(t,"Use a positive integer."),o}function E(e){const t=b(e,"publication_daily_limit_invalid");return t>1e3&&a("publication_daily_limit_invalid","Daily limit must be at most 1000."),t}function W(e){return/^[A-Za-z0-9_-]{1,128}$/.test(e)||a("publication_message_id_invalid","Use 1\u2013128 letters, digits, _ or - for --client-message-id."),e}function Z(e){if(e==="true")return!0;if(e==="false")return!1;a("publication_anonymous_invalid","Use true or false for --allowed.")}async function B(){const e=k.join(k.dirname(j()),"shennian-agent-workspaces");await R.mkdir(e,{recursive:!0,mode:448});const t=await R.lstat(e);return(!t.isDirectory()||t.isSymbolicLink())&&a("agent_workdir_invalid","The Agent workspace root is unavailable."),R.mkdtemp(k.join(e,"agent-"))}function P(e){return(typeof e!="number"||!Number.isSafeInteger(e)||e<1)&&a("invalid_server_response","Shennian returned an invalid publication version."),e}function L(e){const t=Y(e);return{displayName:c(e.name,191,"agent_name_invalid",!0),description:c(e.description,1e3,"agent_description_invalid",!0),runtimeAdapter:c(e.agent,64,"agent_runtime_invalid",!0),workDir:q(e.workdir),modelId:e.model?c(e.model,191,"agent_model_invalid",!0):null,systemPrompt:c(e.systemPrompt,2e4,"agent_system_prompt_invalid"),...t?{permissionPolicy:t}:{}}}function Y(e){return e.fileAccess===void 0?null:((e.agent!=="codex"||e.fileAccess!=="workspace-read"&&e.fileAccess!=="workspace-write")&&a("agent_file_access_invalid","--file-access supports only Codex workspace-read or workspace-write."),{...F,executionMode:"restricted",fileAccess:e.fileAccess,externalCapabilities:{commandNetwork:!1,webSearch:!1,browser:!1,computerUse:!1,mcp:!1}})}function H(e){return e.clearModel&&e.model!==void 0&&a("agent_model_ambiguous","Use either --model or --clear-model, not both."),{...e.name===void 0?{}:{displayName:c(e.name,191,"agent_name_invalid",!0)},...e.description===void 0?{}:{description:c(e.description,1e3,"agent_description_invalid",!0)},...e.agent===void 0?{}:{runtimeAdapter:c(e.agent,64,"agent_runtime_invalid",!0)},...e.workdir===void 0?{}:{workDir:q(e.workdir)},...e.model===void 0&&!e.clearModel?{}:{modelId:e.clearModel?null:c(e.model,191,"agent_model_invalid",!0)},...e.systemPrompt===void 0?{}:{systemPrompt:c(e.systemPrompt,2e4,"agent_system_prompt_invalid")}}}async function I(e,t){const o=f(e.runtimeAdapter,"agent_runtime_invalid"),r=f(e.workDir,"agent_workdir_invalid"),g=typeof e.modelId=="string"?e.modelId:null;if(y(await t({method:"agent.check",params:{agentType:o,workDir:r,modelId:g},timeoutMs:9e4}),"agent_check_invalid_response").ready!==!0)throw new O("agent_check_invalid_response","The daemon did not confirm a successful hello reply.")}function M(e){return JSON.stringify([e.runtimeAdapter??null,e.workDir??null,e.modelId??null,typeof e.systemPrompt=="string"?e.systemPrompt.trim():""])}function S(e){return y(e.agent,"invalid_server_response")}async function s(e,t,o){try{const r=await o();t.write(`${JSON.stringify({ok:!0,command:e,result:r})}
|
|
2
|
-
`)}catch(r){if(r instanceof D){U(
|
|
1
|
+
import T from"node:crypto";import R from"node:fs/promises";import P from"node:path";import{DEFAULT_RESTRICTED_MANAGED_AGENT_PERMISSION_POLICY as F}from"@shennian/wire";import{getShennianDir as j}from"../config/index.js";import{callDaemonIpc as z}from"../daemon-ipc/client.js";import{DaemonIpcError as O}from"../daemon-ipc/protocol.js";import{PublicAgentClient as G,PublicAgentClientError as D}from"../agents/public-agent-client.js";const J={write:e=>process.stdout.write(e),fail:()=>{process.exitCode=1}};function ae(e,n={}){const t=n.client??new G,r=n.io??J,m=n.callDaemon??z;e.command("list").description("List Shennian Agents owned by the paired user on this computer").action(()=>s("agent.list",r,()=>t.list())),e.command("get <agent-id>").description("Read one exact Shennian Agent").action(i=>s("agent.get",r,()=>t.get(u(i,"agent_id_invalid")))),e.command("create").description("Check one local AI configuration, then create a Shennian Agent (full access unless --file-access is set)").requiredOption("--name <name>","Agent display name").requiredOption("--description <description>","Public Room introduction").requiredOption("--agent <type>","Exact type returned by agent discover").requiredOption("--workdir <path>","Absolute working directory on this computer").option("--model <id>","Exact model id returned by agent discover").option("--system-prompt <prompt>","Private system prompt","").option("--file-access <mode>","Codex restricted file access: workspace-read or workspace-write; denies network, web, browser, computer use and MCP").action(i=>s("agent.create",r,async()=>{const o=L(i);return await I(o,m),t.create(o)})),e.command("share").description("Publish an existing Agent by --agent-id, or create one and return a usable link").option("--agent-id <id>","Exact id of an existing Shennian Agent").option("--name <name>","New Agent and public display name").option("--agent <type>","New Agent type returned by agent discover").option("--workdir <path>","Working directory; otherwise create an empty private directory").option("--model <id>","Exact model id returned by agent discover").option("--description <description>","Public introduction","").option("--system-prompt <prompt>","Private system prompt","").option("--file-access <mode>","Codex restricted file access: workspace-read or workspace-write; denies network, web, browser, computer use and MCP").option("--anonymous","Allow browser-scoped visitors to chat without signing in (default)").option("--require-login","Require visitors to sign in before chatting").action(i=>s("agent.share",r,async()=>{i.anonymous&&i.requireLogin&&a("agent_share_access_conflict","Use either --anonymous or --require-login, not both.");const o=!i.requireLogin;let d="",c;if(i.agentId)(i.name||i.agent||i.workdir||i.model||i.systemPrompt||i.description||i.fileAccess)&&a("agent_share_ambiguous","Use --agent-id alone for an existing Agent; edit its settings separately."),d=u(i.agentId,"agent_id_invalid"),c=q(await t.get(d)),c.status!=="active"&&a("agent_unavailable","This Agent is not active.");else{(!i.name||!i.agent)&&a("agent_share_selection_required","Provide --agent-id for an existing Agent, or --name and --agent for a new one.");const y=i.workdir?S(i.workdir):await B();c=L({...i,name:i.name,agent:i.agent,systemPrompt:i.systemPrompt??"",description:i.description||i.name,workdir:y})}if(!i.agentId){await I(c,m);const y=q(await t.create(c));d=w(y.id,"invalid_server_response")}const l=i.agentId?(await t.getPublication(d)).publication:null;(!l||typeof l=="object"&&!Array.isArray(l)&&l.status==="revoked")&&await t.createPublicationDraft(d,{displayName:w(c.displayName,"invalid_server_response"),description:typeof c.description=="string"?c.description:"",dailyMessageLimit:100});const v=f(l??(await t.getPublication(d)).publication,"invalid_server_response");v.allowAnonymousVisitors===!0!==o&&await t.setPublicationAnonymousAccess(d,o,x(v.generation),x(v.policyVersion));const h=f((await t.getPublication(d)).publication,"invalid_server_response");h.status!=="active"&&f((await t.activatePublication(d,x(h.generation),x(h.policyVersion))).publication,"invalid_server_response").status!=="active"&&a("agent_publication_inactive",`Agent ${d} exists, but publication is not active.`);const g=f((await t.getPublication(d)).publication,"invalid_server_response");return(g.status!=="active"||typeof g.shareUrl!="string")&&a("agent_publication_unconfirmed",`Agent ${d} was created, but an active share URL could not be confirmed.`),o&&g.allowAnonymousVisitors!==!0&&a("agent_publication_guest_unconfirmed",`Agent ${d} was published, but browser guest access could not be confirmed.`),!o&&g.allowAnonymousVisitors!==!1&&a("agent_publication_login_unconfirmed",`Agent ${d} was published, but sign-in requirements could not be confirmed.`),{agentId:d,status:"active",shareUrl:g.shareUrl,visitorAccess:g.allowAnonymousVisitors===!0?"browser_guest_allowed":"sign_in_required"}})),e.command("update <agent-id>").description("Update one exact Shennian Agent; runtime changes are checked before saving").option("--name <name>","Agent display name").option("--description <description>","Public Room introduction").option("--agent <type>","Exact type returned by agent discover").option("--workdir <path>","Absolute working directory on this computer").option("--model <id>","Exact model id returned by agent discover").option("--clear-model","Use the runtime default model").option("--system-prompt <prompt>","Private system prompt").action((i,o)=>s("agent.update",r,async()=>{const d=u(i,"agent_id_invalid"),c=H(o);Object.keys(c).length||a("agent_changes_required","Provide at least one Agent field to update.");const l=q(await t.get(d)),v={...l,...c};return M(l)!==M(v)&&await I(v,m),t.update(d,c)})),e.command("delete <agent-id>").description("Delete one exact Shennian Agent and its dedicated Room conversations").action(i=>s("agent.delete",r,()=>t.delete(u(i,"agent_id_invalid"))));const k=e.command("room").description("List, add, or remove this Agent in explicit Rooms");k.command("list <agent-id>").description("List Rooms currently linked to one exact Agent").action(i=>s("agent.room.list",r,()=>t.listRooms(u(i,"agent_id_invalid")))),k.command("add <agent-id> <room-url>").description("Create a dedicated conversation and add this Agent to one explicit Room").option("--mode <mode>","auto_follow, mention_only, or paused","auto_follow").action((i,o,d)=>s("agent.room.add",r,async()=>{const c=u(i,"agent_id_invalid"),l=C(o),v=K(d.mode),h=`cli-agent-room:${T.randomUUID()}`,g=await t.createRoomSession(c,{roomId:l,assignmentIntentId:h,activationMode:v});if(g.existing===!0)return g;const y=f(g.session,"invalid_server_response"),N=w(y.id,"invalid_server_response"),V=w(y.agentType,"invalid_server_response"),$=await m({method:"room.agent.bind-managed",params:{roomId:l,agentIdentityId:c,nianSessionId:N,assignmentIntentId:h,agentType:V,activationMode:v},timeoutMs:12e4});return{session:y,binding:$}})),k.command("remove <agent-id> <room-url>").description("Remove this Agent from one explicit Room and delete its dedicated conversation").action((i,o)=>s("agent.room.remove",r,()=>t.removeFromRoom(u(i,"agent_id_invalid"),C(o))));const b=e.command("publication").description("Manage one Agent publication by exact Agent id");b.command("get <agent-id>").description("Read publication status and versions").action(i=>s("agent.publication.get",r,()=>t.getPublication(u(i,"agent_id_invalid")))),b.command("readiness <agent-id>").description("Read the current machine and runtime checks for one exact Agent publication").action(i=>s("agent.publication.readiness",r,()=>t.getPublicationReadiness(u(i,"agent_id_invalid")))),b.command("draft <agent-id>").description("Create an inactive publication draft; this does not expose a share URL").requiredOption("--name <name>","Public display name").requiredOption("--description <description>","Public introduction").option("--daily-limit <count>","Visitor messages per day","100").action((i,o)=>s("agent.publication.draft",r,()=>t.createPublicationDraft(u(i,"agent_id_invalid"),{displayName:p(o.name,80,"publication_name_invalid",!0),description:p(o.description,1e3,"publication_description_invalid"),dailyMessageLimit:E(o.dailyLimit)}))),b.command("update <agent-id>").description("Update publication details with versions from publication get").requiredOption("--generation <number>","Expected generation").requiredOption("--policy-version <number>","Expected policy version").requiredOption("--name <name>","Public display name").requiredOption("--description <description>","Public introduction").requiredOption("--daily-limit <count>","Visitor messages per day").action((i,o)=>s("agent.publication.update",r,()=>t.updatePublication(u(i,"agent_id_invalid"),{expectedGeneration:_(o.generation,"publication_generation_invalid"),expectedPolicyVersion:_(o.policyVersion,"publication_policy_version_invalid"),displayName:p(o.name,80,"publication_name_invalid",!0),description:p(o.description,1e3,"publication_description_invalid"),dailyMessageLimit:E(o.dailyLimit)}))),b.command("anonymous <agent-id>").description("Enable or disable browser-scoped chats without sign-in on one publication").requiredOption("--generation <number>","Expected generation").requiredOption("--policy-version <number>","Expected policy version").requiredOption("--allowed <value>","true or false").action((i,o)=>s("agent.publication.anonymous",r,()=>t.setPublicationAnonymousAccess(u(i,"agent_id_invalid"),Z(o.allowed),_(o.generation,"publication_generation_invalid"),_(o.policyVersion,"publication_policy_version_invalid")))),b.command("pause <agent-id>").description("Pause an active publication using exact versions").requiredOption("--generation <number>","Expected generation").requiredOption("--policy-version <number>","Expected policy version").action((i,o)=>s("agent.publication.pause",r,()=>t.pausePublication(u(i,"agent_id_invalid"),_(o.generation,"publication_generation_invalid"),_(o.policyVersion,"publication_policy_version_invalid")))),b.command("activate <agent-id>").description("Activate a draft or resume a paused publication only after server release and runtime checks").requiredOption("--generation <number>","Expected generation").requiredOption("--policy-version <number>","Expected policy version").action((i,o)=>s("agent.publication.activate",r,()=>t.activatePublication(u(i,"agent_id_invalid"),_(o.generation,"publication_generation_invalid"),_(o.policyVersion,"publication_policy_version_invalid")))),b.command("revoke <agent-id>").description("Revoke a publication and invalidate its old share URL").requiredOption("--generation <number>","Expected generation").action((i,o)=>s("agent.publication.revoke",r,()=>t.revokePublication(u(i,"agent_id_invalid"),_(o.generation,"publication_generation_invalid")))),b.command("conversations <agent-id>").description("List this publication\u2019s conversations, one page at a time").option("--cursor <cursor>","Opaque next cursor from the previous page").action((i,o)=>s("agent.publication.conversations",r,()=>t.listPublicationConversations(u(i,"agent_id_invalid"),o.cursor)));const A=e.command("public").description("Use the same published Agent URL as a human visitor");A.command("list").description("List your own existing conversations, including history after a link is revoked").option("--cursor <cursor>","Opaque next cursor from the previous page").action(i=>s("agent.public.list",r,()=>t.listMyDirectConversations(i.cursor))),A.command("open <url>").description("Read public Agent details from an exact Shennian share URL").action(i=>s("agent.public.open",r,()=>t.openPublishedAgent(i))),A.command("read <url>").description("Read your latest messages, or page older / follow newer messages").option("--after <cursor>","Read messages after this sequence").option("--before <cursor>","Read older messages before this sequence (default: latest)").action((i,o)=>s("agent.public.read",r,()=>t.readPublishedAgent(i,o))),A.command("history <conversation-id>").description("Read your latest conversation history by stable ID after URL revocation").option("--after <cursor>","Read messages after this sequence").option("--before <cursor>","Read older messages before this sequence (default: latest)").action((i,o)=>s("agent.public.history",r,()=>t.readDirectConversation(u(i,"conversation_id_invalid"),o))),A.command("send <url> <message>").description("Send one message as the paired human user; requires an active publication").requiredOption("--client-message-id <id>","Stable ID for idempotent retries (letters, digits, _ or -)").action((i,o,d)=>s("agent.public.send",r,async()=>{const c=W(d.clientMessageId),l=await t.sendPublishedAgent(i,{text:p(o,2e4,"publication_message_invalid",!0),clientMessageId:c});return{...l,...typeof l.conversationId=="string"?{conversationRef:l.conversationId}:{},clientMessageId:c}}))}function _(e,n){/^[1-9][0-9]*$/.test(e)||a(n,"Use a positive integer.");const t=Number(e);return Number.isSafeInteger(t)||a(n,"Use a positive integer."),t}function E(e){const n=_(e,"publication_daily_limit_invalid");return n>1e3&&a("publication_daily_limit_invalid","Daily limit must be at most 1000."),n}function W(e){return/^[A-Za-z0-9_-]{1,128}$/.test(e)||a("publication_message_id_invalid","Use 1\u2013128 letters, digits, _ or - for --client-message-id."),e}function Z(e){if(e==="true")return!0;if(e==="false")return!1;a("publication_anonymous_invalid","Use true or false for --allowed.")}async function B(){const e=P.join(P.dirname(j()),"shennian-agent-workspaces");await R.mkdir(e,{recursive:!0,mode:448});const n=await R.lstat(e);return(!n.isDirectory()||n.isSymbolicLink())&&a("agent_workdir_invalid","The Agent workspace root is unavailable."),R.mkdtemp(P.join(e,"agent-"))}function x(e){return(typeof e!="number"||!Number.isSafeInteger(e)||e<1)&&a("invalid_server_response","Shennian returned an invalid publication version."),e}function L(e){const n=Y(e);return{displayName:p(e.name,191,"agent_name_invalid",!0),description:p(e.description,1e3,"agent_description_invalid",!0),runtimeAdapter:p(e.agent,64,"agent_runtime_invalid",!0),workDir:S(e.workdir),modelId:e.model?p(e.model,191,"agent_model_invalid",!0):null,systemPrompt:p(e.systemPrompt,2e4,"agent_system_prompt_invalid"),...n?{permissionPolicy:n}:{}}}function Y(e){return e.fileAccess===void 0?null:((e.agent!=="codex"||e.fileAccess!=="workspace-read"&&e.fileAccess!=="workspace-write")&&a("agent_file_access_invalid","--file-access supports only Codex workspace-read or workspace-write."),{...F,executionMode:"restricted",fileAccess:e.fileAccess,externalCapabilities:{commandNetwork:!1,webSearch:!1,browser:!1,computerUse:!1,mcp:!1}})}function H(e){return e.clearModel&&e.model!==void 0&&a("agent_model_ambiguous","Use either --model or --clear-model, not both."),{...e.name===void 0?{}:{displayName:p(e.name,191,"agent_name_invalid",!0)},...e.description===void 0?{}:{description:p(e.description,1e3,"agent_description_invalid",!0)},...e.agent===void 0?{}:{runtimeAdapter:p(e.agent,64,"agent_runtime_invalid",!0)},...e.workdir===void 0?{}:{workDir:S(e.workdir)},...e.model===void 0&&!e.clearModel?{}:{modelId:e.clearModel?null:p(e.model,191,"agent_model_invalid",!0)},...e.systemPrompt===void 0?{}:{systemPrompt:p(e.systemPrompt,2e4,"agent_system_prompt_invalid")}}}async function I(e,n){const t=w(e.runtimeAdapter,"agent_runtime_invalid"),r=w(e.workDir,"agent_workdir_invalid"),m=typeof e.modelId=="string"?e.modelId:null;if(f(await n({method:"agent.check",params:{agentType:t,workDir:r,modelId:m},timeoutMs:9e4}),"agent_check_invalid_response").ready!==!0)throw new O("agent_check_invalid_response","The daemon did not confirm a successful hello reply.")}function M(e){return JSON.stringify([e.runtimeAdapter??null,e.workDir??null,e.modelId??null,typeof e.systemPrompt=="string"?e.systemPrompt.trim():""])}function q(e){return f(e.agent,"invalid_server_response")}async function s(e,n,t){try{const r=await t();n.write(`${JSON.stringify({ok:!0,command:e,result:r})}
|
|
2
|
+
`)}catch(r){if(r instanceof D){U(n,r.code,r.message,r.nextAction);return}if(r instanceof O){U(n,r.code,r.message,null);return}U(n,"agent_command_failed","Shennian Agent command failed.",null)}}function u(e,n){return/^[A-Za-z0-9_.:@/-]{1,191}$/.test(e)||a(n,"Use the exact Agent id returned by Shennian."),e}function C(e){let n;try{n=new URL(e)}catch{a("invalid_room_ref","Use an official Room URL returned by Shennian.")}const t=n.pathname.match(/^\/spaces\/([A-Za-z0-9_-]{1,191})$/);return(n.protocol!=="https:"||n.hostname!=="app.shennian.net"||n.port||n.username||n.password||n.hash||n.search||!t)&&a("invalid_room_ref","Use an official Room URL returned by Shennian."),t[1]}function K(e){if(e==="auto_follow"||e==="mention_only"||e==="paused")return e;a("invalid_activation_mode","--mode must be auto_follow, mention_only, or paused.")}function S(e){const n=p(e,1024,"agent_workdir_invalid",!0);return P.isAbsolute(n)||a("agent_workdir_invalid","Use an absolute working directory."),n}function p(e,n,t,r=!1){const m=typeof e=="string"?e.trim():"";return(r&&!m||m.length>n||m.includes("\0"))&&a(t,"Agent field is invalid."),m}function w(e,n){return(typeof e!="string"||!e)&&a(n,"Shennian returned an invalid Agent response."),e}function f(e,n){return(!e||typeof e!="object"||Array.isArray(e))&&a(n,"Shennian returned an invalid Agent response."),e}function a(e,n){throw new D(e,n)}function U(e,n,t,r){e.write(`${JSON.stringify({ok:!1,error:n,message:t,nextAction:r})}
|
|
3
3
|
`),e.fail()}export{ae as registerAgentWorkspaceCommands};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import A from"node:fs";import{createHash as
|
|
1
|
+
import A from"node:fs";import{createHash as X}from"node:crypto";import{buildApprovalPendingPayload as S,buildUserMessagePayload as Y,isSystemControlPayload as E,isToolPayload as L}from"@shennian/wire";import{buildImagePayload as Z,buildToolPayload as D,findJsonlLookbackOffset as K,makeCursor as q,normalizeText as I,parseStructuredString as P,readJsonlLines as O,readJsonlLinesCooperatively as tt,readTimestamp as et,safeParse as N,shouldIgnoreNativeScanPath as U}from"./parser-common.js";import{lookupCodexThreadName as k}from"./codex-files.js";import{buildCodexUserQuestion as nt}from"../agents/codex-user-question.js";import{parseCodexDelegationInput as rt,parseCodexResponseUserInput as ot}from"./codex-user-input.js";import{listCodexRolloutFiles as At,lookupCodexThreadName as Et}from"./codex-files.js";import{isCodexInjectedContextText as ut,parseCodexLocalImageAttachment as H,parseCodexUserMessage as B}from"./codex-message-parser.js";function ct(e){return e==="turn_aborted"?"aborted":e==="turn_completed"||e==="turn_complete"||e==="task_complete"?"completed":null}function it(e){return/approval|permission|confirm|user[_-]?input|input[_-]?required/i.test(e)}function st(e){const r=typeof e.command=="string"?e.command:Array.isArray(e.command)?e.command.join(" "):"",n=typeof e.prompt=="string"?e.prompt:typeof e.reason=="string"?e.reason:typeof e.message=="string"?e.message:r?`Codex \u8BF7\u6C42\u6267\u884C\u547D\u4EE4\uFF1A${r}`:"Codex \u6B63\u5728\u7B49\u5F85\u7528\u6237\u786E\u8BA4\u540E\u7EE7\u7EED\u3002";return S({title:"\u9700\u8981\u7528\u6237\u786E\u8BA4",content:n,source:"codex",actionHint:"\u5F53\u524D\u795E\u5FF5\u6682\u4E0D\u652F\u6301\u8FDC\u7A0B\u786E\u8BA4\uFF0C\u8BF7\u56DE\u5230\u8FD0\u884C Codex \u7684\u7535\u8111/\u7EC8\u7AEF\u5B8C\u6210\u786E\u8BA4\u3002"})}function lt(e,r){return Array.isArray(e)?I(e.map(n=>{if(typeof n=="string")return n;if(typeof n!="object"||n===null)return"";const t=n;return t.type!==r?"":typeof t.text=="string"?t.text:""}).filter(Boolean).join(`
|
|
2
2
|
|
|
3
|
-
`)):""}function
|
|
4
|
-
(exit ${String(f)})`:""].join("");C(e,r,n,c,u,i,"command_execution",s,l,a,{command:o},g);return}if(c==="patch_apply_end"){C(e,r,n,c,u,i,"apply_patch",s,l,a,t.changes,{success:t.success,stdout:t.stdout,stderr:t.stderr});return}if(c==="mcp_tool_call_end"){const o=typeof t.invocation=="object"&&t.invocation!==null?t.invocation:null,f=typeof o?.tool=="string"?o.tool:"mcp_tool_call",g={server:o?.server,...typeof o?.arguments=="object"&&o.arguments!==null?o.arguments:{}};C(e,r,n,c,u,i,f,s,l,a,g,t.result);return}if(c==="dynamic_tool_call_request"){const o=typeof t.tool=="string"?t.tool:"dynamic_tool_call";C(e,r,n,c,u,i,o,s,l,a,t.arguments,void 0,{callId:t.callId??t.call_id});return}if(c==="dynamic_tool_call_response"){const o=typeof t.tool=="string"?t.tool:"dynamic_tool_call";C(e,r,n,c,u,i,o,s,l,a,void 0,t.result??t.output,{callId:t.callId??t.call_id,completed:!0});return}if(c==="web_search_end"){const o=typeof t.action=="object"&&t.action!==null?t.action:null;C(e,r,n,c,u,i,"web_search",s,l,a,o??t.query,t.query);return}if(c==="image_generation_end"){const o=typeof t.saved_path=="string"?t.saved_path.trim():"";if(!o)return;
|
|
3
|
+
`)):""}function at(e){if(!Array.isArray(e))return[];const r=[];for(const n of e){if(typeof n!="object"||n===null)continue;const t=n;if(t.type!=="input_image")continue;const u=H(t);u&&r.push(u)}return r}function J(e){if(e.type!=="message")return null;const r=e.role==="assistant"?"agent":e.role==="user"?"user":null;if(!r)return null;if(r==="agent"){const i=lt(e.content,"output_text");return E(i)?null:i?{role:r,payload:i,titleText:i}:null}const n=ot(e.content),t=n.text,u=[...at(e.content)];for(const i of n.imagePaths){const s=H(i);s&&(u.some(l=>l.path===s.path)||u.push(s))}return!t&&u.length===0||E(t)&&u.length===0||ut(t)&&u.length===0?null:{role:r,payload:u.length>0?Y(t,u):t,titleText:t,repairHint:n.strippedWrapper?"codex_app_context_wrapper":void 0}}function z(e){if(!e)return"";try{const r=JSON.parse(e);if(typeof r=="object"&&r!==null){const n=r;if(n.type==="user"&&typeof n.content=="string")return I(n.content)}}catch{}return I(e)}function ft(e,r,n,t){return e.agentType!=="codex"||e.role!==r||L(e.payload)||Math.abs(e.ts-t)>300*1e3?!1:z(e.payload)===z(n)}function R(e,r,n,t){for(let u=e.length-1;u>=0;u-=1){const i=e[u];if(i){if(ft(i,r,n,t))return u;if(i.agentType==="codex"&&Math.abs(i.ts-t)>300*1e3)break}}return-1}function v(e,r,n,t,u,i,s,l,a,c,o="agent",f=!1,g){s&&e.push({agentType:"codex",sourceMode:"codex_rollout_import",sourceSessionKey:u,sourceEventKey:w(u,n,t),cursor:q(r,n),role:o,ts:i,payload:s,title:l,modelId:a,workDir:c,terminal:f,...f?{terminalState:t==="turn_aborted"?"aborted":t==="error"?"failed":"completed"}:{},repairHint:g})}function C(e,r,n,t,u,i,s,l,a,c,o,f,g){const M=w(u,n,t),_=typeof g?.callId=="string"&&g.callId.trim()?g.callId.trim():null,x=_?X("sha256").update(`${u}\0${_}`).digest("hex").slice(0,32):null,y=x?`tool:${x}`:void 0,m=x?`native:tool:${x}`:`native:${M}`,T=g?.completed&&x?2:1,p=f!==void 0?"completed":"running";e.push({agentType:"codex",sourceMode:"codex_rollout_import",sourceSessionKey:u,sourceEventKey:M,cursor:q(r,n),role:"agent",ts:i,payload:D({name:s,toolCallId:m,detailRevision:T,status:p}),title:l,modelId:a,workDir:c,...y?{canonicalMessageKey:y,canonicalMutation:g?.completed?"upsert":"append"}:{},localToolDetail:{toolCallId:m,detailRevision:T,name:s,...o!==void 0?{args:o}:{},...f!==void 0?{result:f}:{},status:p}})}function w(e,r,n){return`codex:${e}:${r}:${n}`}function mt(e,r,n,t,u,i,s,l,a){const c=typeof t.type=="string"?t.type:"";if(c){if(c==="message"){const o=J(t);if(!o||R(e,o.role,o.payload,i)>=0)return;v(e,r,n,`${c}:${o.role}`,u,i,o.payload,s,l,a,o.role,!1,o.repairHint);return}if(c==="function_call"){const o=typeof t.name=="string"?t.name:"function_call",f=nt(o,t.arguments);f&&v(e,r,n,"user_question",u,i,S(f),s,l,a),C(e,r,n,c,u,i,o,s,l,a,P(t.arguments),void 0,{callId:t.call_id});return}if(c==="function_call_output"){const o=rt(t);if(o){v(e,r,n,"delegation:user",u,i,o,s||o.slice(0,80),l,a,"user");return}C(e,r,n,c,u,i,"function_call_output",s,l,a,void 0,t.output,{callId:t.call_id,completed:!0});return}if(c==="custom_tool_call"){const o=typeof t.name=="string"?t.name:"custom_tool_call",f=t.input!==void 0?{input:t.input}:void 0;C(e,r,n,c,u,i,o,s,l,a,f,void 0,{callId:t.call_id});return}if(c==="custom_tool_call_output"){const o=typeof t.name=="string"?t.name:"custom_tool_call_output",f=t.output??t.result??t.content;C(e,r,n,c,u,i,o,s,l,a,void 0,f,{callId:t.call_id,completed:!0});return}if(c==="web_search_call"){const o=typeof t.action=="object"&&t.action!==null?t.action:null;C(e,r,n,c,u,i,"web_search",s,l,a,o??t.query);return}}}function gt(e,r,n,t,u,i,s,l,a){const c=typeof t.type=="string"?t.type:"";if(c){if(c==="user_message"){const o=B(t);if(!o)return;v(e,r,n,c,u,i,o.payload,s,l,a,"user",!1,o.repairHint);return}if(c==="agent_message"){const o=typeof t.message=="string"?I(t.message):"";if(!o||E(o))return;v(e,r,n,c,u,i,o,s,l,a);return}if(c==="turn_aborted"||c==="error"){const o=typeof t.message=="string"?I(t.message):typeof t.error=="string"?I(t.error):"";if(!o)return;v(e,r,n,c,u,i,o,s,l,a,"agent",!0);return}if(it(c)){v(e,r,n,c,u,i,st(t),s,l,a,"agent");return}if(c==="exec_command_end"){const o=Array.isArray(t.command)?t.command:t.parsed_cmd??t.command,f=t.exit_code??t.exitCode,g=[typeof t.aggregated_output=="string"?t.aggregated_output:"",f!=null?`
|
|
4
|
+
(exit ${String(f)})`:""].join("");C(e,r,n,c,u,i,"command_execution",s,l,a,{command:o},g);return}if(c==="patch_apply_end"){C(e,r,n,c,u,i,"apply_patch",s,l,a,t.changes,{success:t.success,stdout:t.stdout,stderr:t.stderr});return}if(c==="mcp_tool_call_end"){const o=typeof t.invocation=="object"&&t.invocation!==null?t.invocation:null,f=typeof o?.tool=="string"?o.tool:"mcp_tool_call",g={server:o?.server,...typeof o?.arguments=="object"&&o.arguments!==null?o.arguments:{}};C(e,r,n,c,u,i,f,s,l,a,g,t.result);return}if(c==="dynamic_tool_call_request"){const o=typeof t.tool=="string"?t.tool:"dynamic_tool_call";C(e,r,n,c,u,i,o,s,l,a,t.arguments,void 0,{callId:t.callId??t.call_id});return}if(c==="dynamic_tool_call_response"){const o=typeof t.tool=="string"?t.tool:"dynamic_tool_call";C(e,r,n,c,u,i,o,s,l,a,void 0,t.result??t.output,{callId:t.callId??t.call_id,completed:!0});return}if(c==="web_search_end"){const o=typeof t.action=="object"&&t.action!==null?t.action:null;C(e,r,n,c,u,i,"web_search",s,l,a,o??t.query,t.query);return}if(c==="image_generation_end"){const o=typeof t.saved_path=="string"?t.saved_path.trim():"";if(!o)return;v(e,r,n,c,u,i,Z(o),s,l,a);return}c==="view_image_tool_call"&&C(e,r,n,c,u,i,"view_image",s,l,a,t.path??t.image_path??t)}}function $(e=!1){return{sourceSessionKey:"",workDir:"",modelId:null,title:"",skipImport:e}}function F(e){if((typeof e.thread_source=="string"?e.thread_source.trim().toLowerCase():"")==="subagent")return!0;const n=typeof e.source=="object"&&e.source!==null?e.source:null;if(n&&typeof n.subagent=="object"&&n.subagent!==null)return!0;const t=typeof e.parent_thread_id=="string"&&e.parent_thread_id.trim().length>0,u=typeof e.agent_nickname=="string"||typeof e.agent_role=="string"||typeof e.multi_agent_version=="string";return t&&u}function pt(e){const r=A.openSync(e,"r");try{const n=[];let t=0,u="";for(;t<1024*1024;){const a=Buffer.alloc(16384),c=A.readSync(r,a,0,a.length,t);if(c<=0)break;const o=a.subarray(0,c);n.push(o),t+=c;const f=Buffer.concat(n),g=f.indexOf(10);if(g>=0){u=f.subarray(0,g).toString("utf8");break}}!u&&n.length>0&&(u=Buffer.concat(n).toString("utf8"));const i=N(u);if(!i||i.type!=="session_meta")return $();const s=typeof i.payload=="object"&&i.payload!==null?i.payload:null;if(!s)return $();if(F(s))return $(!0);const l=typeof s.id=="string"?s.id:"";return{sourceSessionKey:l,workDir:typeof s.cwd=="string"?s.cwd:"",modelId:Q(s),title:k(l)??"",skipImport:!1}}finally{A.closeSync(r)}return $()}function Q(e){return(typeof e.model=="string"?e.model.trim():"")||null}function W(e,r){const n=[],t=pt(e);let{sourceSessionKey:u,workDir:i,modelId:s,title:l,skipImport:a}=t,c=t.title;if(a||U(i))return{nextOffset:A.statSync(e).size,events:[]};let o=null;const f=new Set,g=(M,_)=>{const x=N(M);if(!x)return;const y=typeof x.type=="string"?x.type:"",m=typeof x.payload=="object"&&x.payload!==null?x.payload:null,T=et(x.timestamp);if(!(!m||!T)){if(y==="session_meta"){if(F(m)){n.length=0,a=!0;return}if(u=typeof m.id=="string"?m.id:u,i=typeof m.cwd=="string"?m.cwd:i,U(i)){n.length=0,a=!0;return}s=Q(m)??s;const p=k(u);p&&(c=p,l=p);return}if(!a&&u){if(y==="response_item"){const p=J(m);p?.role==="user"&&p.titleText&&!l&&(l=p.titleText.slice(0,80)),mt(n,e,_,m,u,T,l,s,i);return}if(y==="event_msg"){const p=typeof m.type=="string"?m.type:"",j=ct(p);if(j){let h=!1;for(let b=n.length-1;b>=0;b-=1){const d=n[b];if(d?.agentType==="codex"&&d.role==="agent"&&!L(d.payload)){d.terminal=!0,d.terminalState=j,_>=r&&Number(d.cursor?.slice(e.length+1))<r&&f.add(d.sourceEventKey),h=!0,o=null;break}}if(!h)for(let b=n.length-1;b>=0;b-=1){const d=n[b];if(!(d?.agentType!=="codex"||d.role!=="agent")){d.terminal=!0,d.terminalState=j,_>=r&&Number(d.cursor?.slice(e.length+1))<r&&f.add(d.sourceEventKey),h=!0,o=null;break}}h||(o=j);return}if(p==="user_message"){const h=B(m);if(h?.titleText&&!l&&(l=h.titleText.slice(0,80)),h){const b=R(n,"user",h.payload,T);b>=0&&n.splice(b,1)}}else if(p==="agent_message"){const h=typeof m.message=="string"?I(m.message):"";if(h&&!E(h)){const b=R(n,"agent",h,T);b>=0&&n.splice(b,1)}}const V=n.length;gt(n,e,_,m,u,T,l,s,i),o&&n.length>V&&(n[n.length-1].terminal=!0,n[n.length-1].terminalState=o,o=null)}}}};return{readOffset:K(e,r),onLine:g,finish:M=>{for(const _ of n)_.titleSource=c&&_.title===c?"agent_native":"first_user_fallback";return{nextOffset:M,events:n.filter(_=>f.has(_.sourceEventKey)||Number(_.cursor?.slice(e.length+1))>=r)}}}}function G(e){return"nextOffset"in e}function It(e,r){const n=W(e,r);return G(n)?n:n.finish(O(e,n.readOffset,n.onLine))}async function Mt(e,r){const n=W(e,r);return G(n)?n:n.finish(await tt(e,n.readOffset,n.onLine))}export{At as listCodexRolloutFiles,Et as lookupCodexThreadName,It as parseCodexRolloutChunk,Mt as parseCodexRolloutChunkCooperatively};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{buildManagedAgentEnv as
|
|
1
|
+
import{buildManagedAgentEnv as m}from"../../agents/config-status.js";import{lookupClaudeTranscriptCwd as f}from"../../native-fusion/parsers.js";import{getManagedRoomIpcRoot as x,MANAGED_ROOM_IPC_ROOT_ENV as p}from"../../daemon-ipc/paths.js";import{listSessionRecords as s}from"../store.js";import{stewardSessionEnv as C}from"../../steward/session.js";function R(n){return m(n)}function g(n,o,e){return{}}function _(n,o,e,t,a,r,u,i){const c=e==="codex",d=e==="codex"&&!u?s().find(l=>l.sessionId===o)?.codexSettings:void 0;n.configure?.({codexSettings:d,sessionId:o,externalChannel:t??null,env:{...R(e),...g(o,t,a),...C(o),...r&&!c?{SHENNIAN_MANAGED_ROOM_CONTEXT:r,[p]:x()}:{}},...u?{managedAgentPolicy:u}:{},...c?{managedRoomContextToken:r??null,managedRoomExecutor:r?i??null:null}:{}})}function O(n,o,e){const t=o.managedRoomContextToken;t&&t!==e&&n.revokeManagedRoomContextToken?.(t),o.managedRoomContextToken=e,o.roomSendOutcome={successes:0,failureCodes:[]}}function S(n,o){const e=o?.managedRoomContextToken;!o||!e||(o.managedRoomContextToken=null,n.revokeManagedRoomContextToken?.(e))}function N(n,o,e){if(n!=="claude"||!e)return o;const t=o.trim();return!!t&&t.startsWith("-")&&!t.includes("/")?f(e)??o:o}export{_ as configureAdapterForSession,g as externalChannelEnv,R as managedProviderEnv,N as maybeResolveClaudeImportedWorkDir,O as replaceManagedRoomContextToken,S as revokeManagedRoomContextToken};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DEFAULT_CODEX_CONVERSATION_SETTINGS as g}from"@shennian/wire";import{normalizeCodexConversationSettings as m}from"../../agents/codex-conversation-settings.js";import{assertPersonalSyncIdentity as I}from"../../personal-sync/epoch.js";import{isStewardSessionId as x}from"../../steward/session.js";import{listSessionRecords as p,recordSession as f}from"../store.js";import{configureAdapterForSession as l}from"./chat-adapter-config.js";function k(i,n){I(n.params);const s=typeof n.params.sessionId=="string"?n.params.sessionId:"",o=n.params.codexSettingsSession;if(!s||!o)throw new Error("codex_settings_requires_server_upgrade");const e=p().find(t=>t.sessionId===s);if(o.agentType!=="codex"||!o.workDir||o.agentIdentityId||o.sessionMode==="manager"||o.sessionScope==="steward"||x(s)||e?.deletedAt||e?.nativeSessionVisibility==="internal"||e?.sessionScope==="steward"||e&&(e.agentType!=="codex"||e.sessionMode==="manager"))throw new Error("codex_settings_personal_only");const r=i.sessions.get(s),d=i.chatQueue?.getSnapshot(s),a=!!(r?.currentRunId||r?.journalRunId||d?.busy||d?.pending.length||i.recoveryBarrier?.isDispatchFrozen()||i.recoveryBarrier?.isRecovering(s)),c=!!(e?.agentSessionId||o.agentSessionId||r?.agentSessionId);if(n.method==="chat.codex.settings.set"){if(a)throw new Error("codex_settings_busy");const t=m(n.params.settings),S=e?.codexSettings??g;if(c&&t.codexHome!==S.codexHome)throw new Error("codex_home_locked");f({sessionId:s,agentType:"codex",workDir:e?.workDir??o.workDir,agentSessionId:e?.agentSessionId??o.agentSessionId,codexSettings:t}),r&&l(r.adapter,s,"codex")}i.client.sendRes({type:"res",id:n.id,ok:!0,payload:{settings:p().find(t=>t.sessionId===s)?.codexSettings??g,homeLocked:c,busy:a}})}export{k as handleCodexSettings};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createAgent as
|
|
1
|
+
import{createAgent as g}from"../../agents/adapter.js";import{buildManagedAgentEnv as f}from"../../agents/config-status.js";import{listSessionRecords as S,recordSession as m}from"../store.js";import{requestSessionIndexPublish as I}from"../index-publisher.js";import{assertPersonalSyncIdentity as k}from"../../personal-sync/epoch.js";function r(e){return typeof e=="string"?e.trim():""}async function h(e,i){const t=i.params;k(t);const s=r(t.sessionId),d=r(t.title),n=r(t.agentSessionId),l=r(t.agentType),c=r(t.workDir)||process.cwd(),u=r(t.titleOriginEventId),p=t.titleRevision;if(!s||!d||!l||t.titleSource!=="shennian_manual"||!Number.isSafeInteger(p)||Number(p)<1||!u){e.client.sendRes({type:"res",id:i.id,ok:!1,error:"explicit shennian_manual title authority is required"});return}if(m({sessionId:s,agentType:l,workDir:c,agentSessionId:n||null,title:d,titleSource:"shennian_manual",titleRevision:Number(p),titleLockedByUser:!0,titleOriginEventId:u}),I(e.client),l!=="codex"||!n){e.client.sendRes({type:"res",id:i.id,ok:!0,payload:{localApplied:!0,nativeWriteback:"unsupported"}});return}const o=e.sessions.get(s);if(o?.agentType==="codex"&&o.adapter.setTitle){await o.adapter.setTitle(n,d,o.workDir||c),o.agentSessionId=n,o.lastActiveAt=Date.now(),e.client.sendRes({type:"res",id:i.id,ok:!0,payload:{synced:!0}});return}const a=g("codex");if(!a?.setTitle){e.client.sendRes({type:"res",id:i.id,ok:!1,error:"Codex adapter does not support title sync"});return}a.configure?.({sessionId:s,env:f("codex"),codexSettings:S().find(y=>y.sessionId===s)?.codexSettings});try{await a.start(s,c,n),await a.setTitle(n,d,c),e.client.sendRes({type:"res",id:i.id,ok:!0,payload:{synced:!0}})}finally{await a.stop().catch(()=>{})}}export{h as handleSessionTitleSet};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import b from"node:crypto";import{getRegisteredAgents as S,unregisterAgent as k}from"../agents/adapter.js";import{resetCommandSpecCache as w}from"../agents/command-spec.js";import{loadConfig as I}from"../config/index.js";import{handleUpgradeStart as A,handleUpgradeStatus as T}from"../commands/upgrade.js";import{handleAgentsRefresh as P,handleModelsRefresh as C,refreshMachineAgents as M}from"./handlers/agents.js";import{AcpDiscoveryWatcher as x}from"../agents/acp/watcher.js";import{handleAgentCapabilitiesList as D}from"./handlers/agent-capabilities.js";import{handleAgentConfigClear as F,handleAgentConfigGet as E,handleAgentConfigTest as Q,handleAgentConfigUpsert as j}from"./handlers/agent-config.js";import{handleChatAbort as z,handleChatSend as O}from"./handlers/chat.js";import{recoverJournaledRun as B}from"./handlers/chat-recovery.js";import{handleSessionRefresh as W}from"./handlers/session-refresh.js";import{handleSessionToolDetail as _}from"./handlers/tool-detail.js";import{handleSessionTitleSet as H}from"./handlers/title.js";import{handleSessionMessageStatus as U}from"./handlers/message-status.js";import{handleAgentWorkspaceValidation as J}from"./handlers/agent-workspace-validation.js";import{handleVoiceSessionBodyWindow as $}from"./handlers/voice-window.js";import{commitStewardSay as V,commitTerminalStewardSay as L}from"./handlers/steward.js";import{handleRemoteAccessPause as N}from"./handlers/remote-access.js";import{cleanupPendingTransfers as G,handleFsLs as K,handleFsRead as X,handleFsRename as Z,handleFsWrite as Y,handleFsTransferAbort as q,handleFsTransferChunk as ee,handleFsTransferFinish as se,handleFsTransferStart as te,handleFsExportMarkdownPdf as ae,handleFsExportMarkdownPdfSetup as re,handleFsArchiveZip as ne}from"./handlers/fs.js";import{handleRegionProbe as ie,handleRegionSwitch as oe,handleUpgradeSetPolicy as ce}from"./handlers/control.js";import{ManagerRuntimeService as le,setManagerRuntimeService as h}from"../manager/runtime.js";import{ChatQueueManager as ue}from"./queue.js";import{createAuthorizedFsRoot as he,createAuthorizedFsRootAsync as de,resolveAuthorizedPath as me,resolveAuthorizedPathAsync as pe,resolveSessionWorkDir as ge}from"../fs/boundary.js";import"../agents/claude.js";import"../agents/codex.js";import"../agents/workbuddy.js";import"../agents/gemini.js";import"../agents/cursor.js";import"../agents/opencode.js";import"../agents/pi-coding-agent.js";import"../agents/manager.js";import{registerCustomAgent as fe}from"../agents/custom.js";import{listNodeAdapters as ve}from"../adapter-kit/registry.js";import{syncNodeAdapterAgents as ye}from"../agents/node-adapter.js";import{bindManagedRoom as Re,handleManagedRoomBind as be,handleManagedRoomRestart as Se,discardPreBindingSession as ke}from"./handlers/room-managed.js";import{getDaemonInstallationId as d,listSessionRecords as u,purgeCanonicalSession as we,purgeSessionRecord as Ie,recordSession as Ae,upsertMessage as Te}from"./store.js";import{requestSessionIndexPublish as m}from"./index-publisher.js";import{checkRunStalls as Pe}from"./run-stall.js";import{reportUpgradeAggregateMetric as Ce}from"../log-reporter.js";import{PersonalHistorySubscriptions as Me}from"./history-subscriptions.js";import{sweepAttachmentTransfers as xe}from"./attachment-transfer-store.js";import{NativeSourceDeletionStore as De}from"../native-fusion/native-source-deletions.js";import{collectLocalNativeSources as Fe}from"../native-fusion/session-native-sources.js";import{purgeToolDetails as Ee}from"./tool-detail-store.js";import{NativeSessionCleanupOutbox as Qe}from"./native-cleanup-outbox.js";import{assertPersonalSyncIdentity as o}from"../personal-sync/epoch.js";import{ActiveRunJournal as je}from"./run-recovery/journal.js";import{RunRecoveryBarrier as ze}from"./run-recovery/barrier.js";import{RunRecoveryCoordinator as Oe}from"./run-recovery/coordinator.js";import{ProjectFsHandleStore as Be}from"./project-fs-store.js";import{handleProjectFsRequest as We}from"./handlers/project-fs.js";import{handleAgentPermissionResponse as _e,handleAcpAgentRequest as He}from"./handlers/agent-control.js";import{SessionDeletionSynchronizer as Ue}from"./deletion-synchronizer.js";import{dispatchManagedChat as Je,dispatchQueuedChat as $e,interruptQueuedChat as Ve}from"./queued-chat-dispatch.js";const Le=50;import{resolveSessionWorkDir as qs}from"../fs/boundary.js";function Ne(){return"\u795E\u5FF5\u5347\u7EA7\u4E2D\u65AD\u4E86\u672C\u6B21\u8FD0\u884C\u3002\u5DF2\u5B8C\u6210\u7684\u56DE\u590D\u6216\u64CD\u4F5C\u4ECD\u7136\u6709\u6548\uFF0C\u672A\u5B8C\u6210\u90E8\u5206\u53EF\u91CD\u8BD5\u3002\u539F\u4F1A\u8BDD\u5DF2\u4FDD\u7559\u3002"}class Xs{client;nativeFusion;cliVersion;upgradePolicyController;managedRoomBinder;remoteAccessPauseController;managedRoomContextRevoker;managedRoomExecutor;trustedProjectFsRequestResolver;getAgentSnapshot;scheduleHandler;getScheduleQueue(){return this.chatQueue}sessions=new Map;processedReqIds=new Set;runTextAcc=new Map;pendingTransfers=new Map;managerRuntime;chatQueue;historySubscriptions;nativeCleanupOutbox;activityProbeTimer=null;attachmentCleanupTimer=null;activeRequests=0;acpDiscoveryWatcher;runJournal;recoveryBarrier=new ze;recoveryCoordinator;recoveryPass=null;prepareManagedRecovery;projectFsHandleStore=new Be;deletionSynchronizer;constructor(e,t=null,s,n=null,r=null,l=null,p=null,g=null,f=null,v=null,y=null){this.client=e,this.nativeFusion=t,this.cliVersion=s,this.upgradePolicyController=n,this.managedRoomBinder=r,this.remoteAccessPauseController=l,this.managedRoomContextRevoker=p,this.managedRoomExecutor=g,this.trustedProjectFsRequestResolver=v,this.getAgentSnapshot=y,this.runJournal=f??new je(d());for(const a of this.runJournal.loadPendingReconciliation().records)this.recoveryBarrier.begin(a.sessionId);this.recoveryCoordinator=new Oe({journal:this.runJournal,barrier:this.recoveryBarrier,recover:(a,i)=>B(this.getRuntime(),a,i),commitTerminal:(a,i)=>this.commitRecoveryTerminal(a,i),isCanonicalTerminal:a=>{const i=u().find(R=>R.sessionId===a.sessionId),c=`terminal:${b.createHash("sha256").update(`${a.runId}\0`).digest("hex")}`;return i?.lastAttentionId===c},onOutcome:a=>Ce({kind:"recovery",adapterType:a.adapterType,result:a.result,stage:a.result==="continued"?"continue":a.result==="reattached"?"reattach":a.result==="resumed"?"resume":a.result==="terminal_reconciled"?"inspect":"terminal",durationMs:a.durationMs,retries:Math.max(0,a.attempts-1),...a.reason?{errorCode:a.reason}:{}})}),this.managerRuntime=new le({getRuntime:()=>this.getRuntime(),getAgentSnapshot:this.getAgentSnapshot??void 0,dispatchReq:a=>this.handleReq(a,{propagateErrors:!0})}),this.chatQueue=new ue({getRuntime:()=>this.getRuntime(),dispatchReq:a=>this.handleReq(a),dispatchManagedReq:(a,i)=>Je(this.getRuntime(),a,i),dispatchQueuedReq:(a,i)=>$e(this.getRuntime(),a,i),interruptQueuedSession:a=>Ve(this.getRuntime(),a)}),this.deletionSynchronizer=new Ue(e,a=>this.applySessionDeletion(a)),this.historySubscriptions=new Me(this.client),this.nativeCleanupOutbox=new Qe({logger:console.info}),this.acpDiscoveryWatcher=new x(async()=>{w(),await M(this.getRuntime())}),this.nativeFusion?.setExternalTerminalHandler?.(a=>{this.handleExternalTerminal(a)}),this.nativeFusion?.setExternalClaimHandler?.((a,i)=>{this.chatQueue.noteExternalClaim(a,i)}),this.nativeCleanupOutbox.start(),h(this.managerRuntime),this.managerRuntime.start(),this.reloadCustomAgents();try{this.acpDiscoveryWatcher.start()}catch(a){console.warn(`[acp.discovery] watcher unavailable: ${a instanceof Error?a.message:String(a)}`)}this.activityProbeTimer=setInterval(()=>{Pe(this.sessions.entries(),()=>m(this.client)),this.publishManagedActivitySnapshots().catch(a=>{console.error("[session.activity] managed probe failed",a)})},15e3),this.activityProbeTimer.unref?.(),this.attachmentCleanupTimer=setInterval(()=>{const a=new Set([...u().map(i=>i.workDir),...Array.from(this.pendingTransfers.values()).map(i=>i.rootPath)]);for(const i of a)try{xe(this.resolvePath(i))}catch(c){console.error("[attachment.cleanup] failed",c instanceof Error?c.message:String(c))}},6e4),this.attachmentCleanupTimer.unref?.()}executeManagedManagerAction(e){return this.managerRuntime.executeScopedWorkerAction(e.managerSessionId,e.action,e.params,e.roomOrigin)}noteManagedRoomSendOutcome(e){for(const t of this.sessions.values()){if(t.managedRoomContextToken!==e.token)continue;const s=t.roomSendOutcome??(t.roomSendOutcome={successes:0,failureCodes:[]});e.ok?s.successes+=1:s.failureCodes.length<20&&s.failureCodes.push(e.errorCode??"managed_room_action_failed");return}}getManagedRoomActiveRunId(e,t){const s=this.sessions.get(t);if(s?.currentRunId)return s.currentRunId;for(const n of this.sessions.values())if(n.managedRoomContextToken===e)return n.currentRunId??null;return null}getRuntime(){return{client:this.client,pendingTransfers:this.pendingTransfers,processedReqIds:this.processedReqIds,reloadCustomAgents:()=>this.reloadCustomAgents(),getAgentSnapshot:this.getAgentSnapshot??void 0,resolvePath:e=>this.resolvePath(e),resolveAuthorizedPath:(e,t)=>this.resolveAuthorizedPath(e,t),resolveAuthorizedPathAsync:(e,t)=>this.resolveAuthorizedPathAsync(e,t),runTextAcc:this.runTextAcc,sessions:this.sessions,evictIdleSessions:()=>this.evictIdleSessions(),nativeFusion:this.nativeFusion,managerRuntime:this.managerRuntime,chatQueue:this.chatQueue,activityPublisher:{publish:(e,t)=>this.publishSessionActivity(e,t)},upgradePolicyController:this.upgradePolicyController,revokeManagedRoomContextToken:this.managedRoomContextRevoker,managedRoomExecutor:this.managedRoomExecutor,runJournal:this.runJournal,recoveryBarrier:this.recoveryBarrier,prepareManagedRecovery:this.prepareManagedRecovery}}async resumePendingAcpAuthentication(e){const t=[...this.sessions.values()].find(s=>s.agentType===e&&s.adapter.hasPendingAuthenticationRetry?.());return t?.adapter.resumeAfterExternalAuthentication?(await t.adapter.resumeAfterExternalAuthentication(),!0):!1}getUpgradeIdleState(){const e=[];return[...this.sessions.values()].some(t=>t.currentRunId!==null)&&e.push("active-agent-turn"),this.pendingTransfers.size>0&&e.push("file-transfer"),this.activeRequests>0&&e.push("active-daemon-request"),{idle:e.length===0,reasons:e}}bindManagedRoomFromLocal(e){return Re(this.getRuntime(),this.managedRoomBinder,e)}stewardSayFromLocal(e){const t=typeof e.sessionId=="string"?e.sessionId:"",s=typeof e.text=="string"?e.text:"";return t?V(this.getRuntime(),t,s):L(this.getRuntime(),s)}prepareForUpgrade(e){this.recoveryBarrier.freezeDispatch();const t=this.runJournal.markPlannedUpgrade(e);return this.runJournal.sync(),{activeRunCount:t}}cancelUpgradePreparation(){this.recoveryBarrier.unfreezeDispatch()}async recoverInterruptedRuns(){this.recoveryPass??=this.recoveryCoordinator.recoverAll(),await this.recoveryPass}getPendingRecoveryCount(){return this.runJournal.loadPendingReconciliation().records.length}revokeProjectFsHandles(){this.projectFsHandleStore.revokeAll()}async commitRecoveryTerminal(e,t){const s=this.sessions.get(e.sessionId);s&&(s.currentRunId=null,s.currentRunPhase=null,s.journalRunId=null,s.heartbeatTimer&&(clearInterval(s.heartbeatTimer),s.heartbeatTimer=null)),this.runTextAcc.delete(`${e.sessionId}:${e.providerRunId??e.runId}`),this.publishSessionActivity(e.sessionId,null);const n=Ne();Te(e.sessionId,{id:`upgrade-recovery-terminal-${e.runId}`,sessionId:e.sessionId,role:"agent",ts:Date.now(),payload:JSON.stringify({v:1,type:"error",content:n,error:!0,recoveryState:t.result,recoveryReason:t.reason})}),Ae({sessionId:e.sessionId,agentType:e.agentType,sessionMode:e.sessionMode,workDir:e.workDir,agentSessionId:e.agentSessionId,modelId:e.modelId,status:"failed",attentionId:`upgrade-recovery:${e.runId}`,lastActivityAt:new Date().toISOString()}),this.managerRuntime.noteAgentEvent(e.sessionId,{state:"error",runId:e.providerRunId??e.runId,seq:e.lastObservedEventSeq+1,message:n}),m(this.client);const r=e.lastObservedEventSeq+1;this.client.sendAgentEvent({type:"event",event:"agent",payload:t.result==="interrupted_by_upgrade"?{state:"interrupted_by_upgrade",sessionId:e.sessionId,runId:e.providerRunId??e.runId,seq:r,reason:t.reason}:{state:"recovery_failed",sessionId:e.sessionId,runId:e.providerRunId??e.runId,seq:r,reason:t.reason,...t.message?{message:t.message}:{}},seq:r,id:`agent-recovery-terminal-${e.runId}`}),this.chatQueue.noteTerminal(e.sessionId)}setManagedRoomTurnPreparer(e){this.chatQueue.setManagedRoomTurnPreparer(e)}setManagedAgentDirectTurnPreparer(e){this.chatQueue.setManagedAgentDirectTurnPreparer(e)}setManagedRecoveryPreparer(e){this.prepareManagedRecovery=e}async enqueueManagedRoomBatch(e){const t=e.map(s=>{const n=u().find(r=>r.sessionId===s.params.sessionId);return{context:s.context,params:{...s.params,modelId:n?.modelId??s.params.modelId,sessionMode:n?.sessionMode??s.params.sessionMode,managerConfig:n?.managerConfig??s.params.managerConfig,managerDefaultWorkerAgentType:n?.managerDefaultWorkerAgentType??s.params.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:n?.managerDefaultWorkerModelId??s.params.managerDefaultWorkerModelId}}});await this.chatQueue.enqueueManagedRoomBatch(t)}async retireManagedRoomSession(e){this.chatQueue.purgeSession(e),await ke(this.getRuntime(),e)}discardPendingManagedRoomMessages(e){return this.chatQueue.discardPendingManagedRoomMessages(e)}async synchronizeSessionDeletions(){await this.deletionSynchronizer.synchronize()}async applySessionDeletion(e){const t=new De({daemonInstallationId:d()});let s=[];try{s=Fe(e.sessionId,{records:u()})}catch(r){console.warn("[session.deletions] local native source lookup failed",{error:r instanceof Error?r.message:String(r)})}t.recordSession(e);for(const r of[...e.sources,...s]){const l=t.find(r.agentType,r.sourceSessionKey);l&&l.sessionId!==e.sessionId||t.record({...e,...r})}this.runJournal.markSessionAborted(e.sessionId),this.recoveryBarrier.end(e.sessionId);const n=this.sessions.get(e.sessionId);if(n){this.revokeManagedRoomToken(n);try{await n.adapter.stop()}catch{}this.sessions.delete(e.sessionId)}this.historySubscriptions.closeSession(e.sessionId),this.nativeFusion?.handleSessionDeleted(e.sessionId),this.chatQueue.purgeSession(e.sessionId),Ee(e.sessionId),we(e.sessionId),Ie(e.sessionId),this.runTextAcc.delete(e.sessionId),this.publishSessionActivity(e.sessionId,null),this.nativeCleanupOutbox.enqueue(e),this.nativeCleanupOutbox.kick()}publishSessionActivity(e,t){this.client.sendEvent({type:"event",event:"session.activity",payload:{sessionId:e,activity:t}})}async handleExternalTerminal(e){const t=this.sessions.get(e);t&&(t.journalRunId&&(this.recoveryCoordinator.completeFromProvider(e,t.journalRunId),t.journalRunId=null),this.sessions.delete(e),this.revokeManagedRoomToken(t),t.heartbeatTimer&&clearInterval(t.heartbeatTimer),t.adapter.removeAllListeners(),await t.adapter.stop().catch(()=>{})),this.chatQueue.noteTerminal(e)}async publishManagedActivitySnapshots(){for(const[e,t]of this.sessions.entries()){if(t.heartbeatTimer||!t.currentRunId||!t.adapter.getStatus)continue;const s=await t.adapter.getStatus().catch(()=>null);if(!s?.active||!s.runPhase)continue;const n=new Date().toISOString();this.publishSessionActivity(e,{sessionId:e,runId:s.runId||t.currentRunId,runPhase:s.runPhase,startedAt:new Date(t.lastActiveAt).toISOString(),updatedAt:n,canStop:s.canStop??!0});const r=t.heartbeatSeq++;this.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"heartbeat",sessionId:e,runId:s.runId||t.currentRunId,seq:r,runPhase:s.runPhase,canStop:s.canStop??!0},seq:r,id:`agent-status-${s.runId||t.currentRunId}-${Date.now()}`})}}reloadCustomAgents(){for(const t of S())t.startsWith("custom:")&&k(t);const e=I();for(const[t,s]of Object.entries(e.customAgents??{}))fe(t,s);ye(ve(),new Set(Object.keys(e.customAgents??{})))}async handleReq(e,t={}){const s=this.getRuntime();let n;this.activeRequests++;try{switch(e.method){case"schedule.deliver":if(!this.scheduleHandler)throw new Error("schedules_unavailable");await this.scheduleHandler(e);break;case"chat.send":if(e.params.scheduledDelivery)throw new Error("schedule_source_untrusted");o(e.params),this.recoveryBarrier.isDispatchFrozen()||this.recoveryBarrier.isRecovering(String(e.params.sessionId??""))?n={durableQueueHandoff:await this.chatQueue.handleEnqueue({...e,method:"chat.enqueue"})}:await O(s,e);break;case"chat.enqueue":o(e.params),n={durableQueueHandoff:await this.chatQueue.handleEnqueue(e)};break;case"chat.queue.get":o(e.params),await this.chatQueue.handleGet(e);break;case"chat.queue.edit":o(e.params),await this.chatQueue.handleEdit(e);break;case"chat.queue.delete":o(e.params),await this.chatQueue.handleDelete(e);break;case"chat.queue.promote":o(e.params),await this.chatQueue.handlePromote(e);break;case"chat.abort":o(e.params),await z(s,e);break;case"session.refresh":o(e.params),await W(s,e);break;case"session.history.open":this.historySubscriptions.handleOpen(e);break;case"session.history.sync":this.historySubscriptions.handleSync(e);break;case"session.history.page":this.historySubscriptions.handlePage(e);break;case"session.history.close":this.historySubscriptions.handleClose(e);break;case"session.body.replica.subscribe":this.historySubscriptions.handleReplicaSubscribe(e);break;case"session.body.replica.unsubscribe":this.historySubscriptions.handleReplicaUnsubscribe(e);break;case"session.history":this.client.sendRes({type:"res",id:e.id,ok:!1,error:"upgrade_required"});break;case"session.message.status":U(s,e);break;case"session.tool.detail":await _(s,e);break;case"voice.session.body.window":$(s,e);break;case"session.title.set":await H(s,e);break;case"room.agent.bind-managed":await be(s,this.managedRoomBinder,e);break;case"room.agent.restart-managed":await Se(s,this.managedRoomBinder,e);break;case"fs.ls":await K(s,e);break;case"project.fs.open":case"project.fs.list":case"project.fs.read":case"project.fs.close":await We(this.client,this.projectFsHandleStore,e,this.trustedProjectFsRequestResolver);break;case"fs.read":await X(s,e);break;case"fs.write":await Y(s,e);break;case"fs.export.markdown-pdf":await ae(s,e);break;case"fs.export.markdown-pdf.setup":await re(s,e);break;case"fs.archive.zip":await ne(s,e);break;case"fs.rename":await Z(s,e);break;case"fs.transfer.start":await te(s,e);break;case"fs.transfer.chunk":await ee(s,e);break;case"fs.transfer.finish":await se(s,e);break;case"fs.transfer.abort":await q(s,e);break;case"region.probe":await ie(s,e);break;case"region.switch":await oe(s,e);break;case"upgrade.start":await A(this.client,e.id,e.params.version,{currentVersion:this.cliVersion,confirmedMajor:e.params.confirmedMajor===!0,prepareForUpgrade:r=>this.prepareForUpgrade(r),cancelUpgradePreparation:()=>this.cancelUpgradePreparation(),shutdownAfterHandoff:()=>{setTimeout(()=>process.kill(process.pid,"SIGTERM"),100).unref?.()}});break;case"upgrade.status":await T(this.client,e.id,{currentVersion:this.cliVersion});break;case"upgrade.set-policy":await ce(s,e);break;case"machine.remote-access.pause":await N(this.client,this.remoteAccessPauseController,e);break;case"agents.refresh":await P(s,e);break;case"agent.permission.respond":await _e(s,e);break;case"agent.auth.start":case"agent.auth.logout":case"agent.session-options.get":case"agent.external-sessions.list":case"agent.external-sessions.import":case"agent.external-sessions.close":case"agent.external-sessions.delete":await He(s,e);break;case"models.refresh":await C(s,e);break;case"agent.config.get":await E(s,e);break;case"agent.config.upsert":await j(s,e);break;case"agent.config.clear":await F(s,e);break;case"agent.config.test":await Q(s,e);break;case"agent.workspace.validate":await J(s,e);break;case"agent.capabilities.list":await D(s,e);break;case"skill.list":case"skill.install":case"skill.doctor":case"skill.setup":case"skill.use":this.client.sendRes({type:"res",id:e.id,ok:!1,error:"feature_retired"});break;case"session.wechat-rpa.channel.get":case"session.wechat-rpa.channel.upsert":case"session.wechat-rpa.channel.sync":case"manager.wechat-rpa.channel.get":case"manager.wechat-rpa.channel.upsert":case"manager.wechat-rpa.channel.sync":this.client.sendRes({type:"res",id:e.id,ok:!1,error:"feature_retired"});break;default:this.client.sendRes({type:"res",id:e.id,ok:!1,error:`Unknown method: ${e.method}`})}}catch(r){if(t.propagateErrors)throw r;this.client.sendRes({type:"res",id:e.id,ok:!1,error:r instanceof Error?r.message:String(r)})}finally{this.activeRequests--}return n}evictIdleSessions(){if(this.sessions.size<Le)return;let e=null;for(const[t,s]of this.sessions)(!e||s.lastActiveAt<e.session.lastActiveAt)&&(e={key:t,session:s});e&&(this.revokeManagedRoomToken(e.session),e.session.heartbeatTimer&&(clearInterval(e.session.heartbeatTimer),e.session.heartbeatTimer=null),e.session.adapter.removeAllListeners(),e.session.adapter.stop().catch(()=>{}),this.sessions.delete(e.key))}resolvePath(e){return ge(e)}resolveAuthorizedPath(e,t){return me(e,he(t))}async resolveAuthorizedPathAsync(e,t){return pe(e,await de(t))}async cleanup(){this.chatQueue.stop(),this.projectFsHandleStore.revokeAll(),this.acpDiscoveryWatcher.stop(),this.nativeFusion?.setExternalTerminalHandler?.(null),this.nativeCleanupOutbox.stop(),this.historySubscriptions.closeAll(),this.activityProbeTimer&&(clearInterval(this.activityProbeTimer),this.activityProbeTimer=null),this.attachmentCleanupTimer&&(clearInterval(this.attachmentCleanupTimer),this.attachmentCleanupTimer=null);for(const[,e]of this.sessions)this.revokeManagedRoomToken(e),e.heartbeatTimer&&(clearInterval(e.heartbeatTimer),e.heartbeatTimer=null),e.adapter.removeAllListeners(),await e.adapter.stop().catch(()=>{});this.sessions.clear(),this.runTextAcc.clear(),G(this.getRuntime()),await this.managerRuntime.stop(),h(null)}revokeManagedRoomToken(e){const t=e.managedRoomContextToken;e.managedRoomContextToken=null,t&&this.managedRoomContextRevoker?.(t)}}export{Xs as SessionManager,qs as resolveSessionWorkDir,Ne as upgradeRecoveryVisibleMessage};
|
|
1
|
+
import b from"node:crypto";import{getRegisteredAgents as S,unregisterAgent as k}from"../agents/adapter.js";import{resetCommandSpecCache as w}from"../agents/command-spec.js";import{loadConfig as I}from"../config/index.js";import{handleUpgradeStart as A,handleUpgradeStatus as T}from"../commands/upgrade.js";import{handleAgentsRefresh as P,handleModelsRefresh as C,refreshMachineAgents as M}from"./handlers/agents.js";import{AcpDiscoveryWatcher as x}from"../agents/acp/watcher.js";import{handleAgentCapabilitiesList as D}from"./handlers/agent-capabilities.js";import{handleAgentConfigClear as F,handleAgentConfigGet as E,handleAgentConfigTest as Q,handleAgentConfigUpsert as j}from"./handlers/agent-config.js";import{handleCodexSettings as z}from"./handlers/codex-settings.js";import{handleChatAbort as O,handleChatSend as B}from"./handlers/chat.js";import{recoverJournaledRun as H}from"./handlers/chat-recovery.js";import{handleSessionRefresh as W}from"./handlers/session-refresh.js";import{handleSessionToolDetail as _}from"./handlers/tool-detail.js";import{handleSessionTitleSet as U}from"./handlers/title.js";import{handleSessionMessageStatus as J}from"./handlers/message-status.js";import{handleAgentWorkspaceValidation as $}from"./handlers/agent-workspace-validation.js";import{handleVoiceSessionBodyWindow as V}from"./handlers/voice-window.js";import{commitStewardSay as L,commitTerminalStewardSay as N}from"./handlers/steward.js";import{handleRemoteAccessPause as G}from"./handlers/remote-access.js";import{cleanupPendingTransfers as K,handleFsLs as X,handleFsRead as Z,handleFsRename as Y,handleFsWrite as q,handleFsTransferAbort as ee,handleFsTransferChunk as se,handleFsTransferFinish as te,handleFsTransferStart as ae,handleFsExportMarkdownPdf as ne,handleFsExportMarkdownPdfSetup as re,handleFsArchiveZip as ie}from"./handlers/fs.js";import{handleRegionProbe as oe,handleRegionSwitch as ce,handleUpgradeSetPolicy as le}from"./handlers/control.js";import{ManagerRuntimeService as ue,setManagerRuntimeService as d}from"../manager/runtime.js";import{ChatQueueManager as he}from"./queue.js";import{createAuthorizedFsRoot as de,createAuthorizedFsRootAsync as me,resolveAuthorizedPath as pe,resolveAuthorizedPathAsync as ge,resolveSessionWorkDir as fe}from"../fs/boundary.js";import"../agents/claude.js";import"../agents/codex.js";import"../agents/workbuddy.js";import"../agents/gemini.js";import"../agents/cursor.js";import"../agents/opencode.js";import"../agents/pi-coding-agent.js";import"../agents/manager.js";import{registerCustomAgent as ve}from"../agents/custom.js";import{listNodeAdapters as ye}from"../adapter-kit/registry.js";import{syncNodeAdapterAgents as Re}from"../agents/node-adapter.js";import{bindManagedRoom as be,handleManagedRoomBind as Se,handleManagedRoomRestart as ke,discardPreBindingSession as we}from"./handlers/room-managed.js";import{getDaemonInstallationId as m,listSessionRecords as u,purgeCanonicalSession as Ie,purgeSessionRecord as Ae,recordSession as Te,upsertMessage as Pe}from"./store.js";import{requestSessionIndexPublish as p}from"./index-publisher.js";import{checkRunStalls as Ce}from"./run-stall.js";import{reportUpgradeAggregateMetric as Me}from"../log-reporter.js";import{PersonalHistorySubscriptions as xe}from"./history-subscriptions.js";import{sweepAttachmentTransfers as De}from"./attachment-transfer-store.js";import{NativeSourceDeletionStore as Fe}from"../native-fusion/native-source-deletions.js";import{collectLocalNativeSources as Ee}from"../native-fusion/session-native-sources.js";import{purgeToolDetails as Qe}from"./tool-detail-store.js";import{NativeSessionCleanupOutbox as je}from"./native-cleanup-outbox.js";import{assertPersonalSyncIdentity as c}from"../personal-sync/epoch.js";import{ActiveRunJournal as ze}from"./run-recovery/journal.js";import{RunRecoveryBarrier as Oe}from"./run-recovery/barrier.js";import{RunRecoveryCoordinator as Be}from"./run-recovery/coordinator.js";import{ProjectFsHandleStore as He}from"./project-fs-store.js";import{handleProjectFsRequest as We}from"./handlers/project-fs.js";import{handleAgentPermissionResponse as _e,handleAcpAgentRequest as Ue}from"./handlers/agent-control.js";import{SessionDeletionSynchronizer as Je}from"./deletion-synchronizer.js";import{dispatchManagedChat as $e,dispatchQueuedChat as Ve,interruptQueuedChat as Le}from"./queued-chat-dispatch.js";const Ne=50;import{resolveSessionWorkDir as st}from"../fs/boundary.js";function Ge(){return"\u795E\u5FF5\u5347\u7EA7\u4E2D\u65AD\u4E86\u672C\u6B21\u8FD0\u884C\u3002\u5DF2\u5B8C\u6210\u7684\u56DE\u590D\u6216\u64CD\u4F5C\u4ECD\u7136\u6709\u6548\uFF0C\u672A\u5B8C\u6210\u90E8\u5206\u53EF\u91CD\u8BD5\u3002\u539F\u4F1A\u8BDD\u5DF2\u4FDD\u7559\u3002"}class Ys{client;nativeFusion;cliVersion;upgradePolicyController;managedRoomBinder;remoteAccessPauseController;managedRoomContextRevoker;managedRoomExecutor;trustedProjectFsRequestResolver;getAgentSnapshot;scheduleHandler;getScheduleQueue(){return this.chatQueue}sessions=new Map;processedReqIds=new Set;runTextAcc=new Map;pendingTransfers=new Map;managerRuntime;chatQueue;historySubscriptions;nativeCleanupOutbox;activityProbeTimer=null;attachmentCleanupTimer=null;activeRequests=0;acpDiscoveryWatcher;runJournal;recoveryBarrier=new Oe;recoveryCoordinator;recoveryPass=null;prepareManagedRecovery;projectFsHandleStore=new He;deletionSynchronizer;constructor(e,t=null,s,n=null,r=null,o=null,h=null,g=null,f=null,v=null,y=null){this.client=e,this.nativeFusion=t,this.cliVersion=s,this.upgradePolicyController=n,this.managedRoomBinder=r,this.remoteAccessPauseController=o,this.managedRoomContextRevoker=h,this.managedRoomExecutor=g,this.trustedProjectFsRequestResolver=v,this.getAgentSnapshot=y,this.runJournal=f??new ze(m());for(const a of this.runJournal.loadPendingReconciliation().records)this.recoveryBarrier.begin(a.sessionId);this.recoveryCoordinator=new Be({journal:this.runJournal,barrier:this.recoveryBarrier,recover:(a,i)=>H(this.getRuntime(),a,i),commitTerminal:(a,i)=>this.commitRecoveryTerminal(a,i),isCanonicalTerminal:a=>{const i=u().find(R=>R.sessionId===a.sessionId),l=`terminal:${b.createHash("sha256").update(`${a.runId}\0`).digest("hex")}`;return i?.lastAttentionId===l},onOutcome:a=>Me({kind:"recovery",adapterType:a.adapterType,result:a.result,stage:a.result==="continued"?"continue":a.result==="reattached"?"reattach":a.result==="resumed"?"resume":a.result==="terminal_reconciled"?"inspect":"terminal",durationMs:a.durationMs,retries:Math.max(0,a.attempts-1),...a.reason?{errorCode:a.reason}:{}})}),this.managerRuntime=new ue({getRuntime:()=>this.getRuntime(),getAgentSnapshot:this.getAgentSnapshot??void 0,dispatchReq:a=>this.handleReq(a,{propagateErrors:!0})}),this.chatQueue=new he({getRuntime:()=>this.getRuntime(),dispatchReq:a=>this.handleReq(a),dispatchManagedReq:(a,i)=>$e(this.getRuntime(),a,i),dispatchQueuedReq:(a,i)=>Ve(this.getRuntime(),a,i),interruptQueuedSession:a=>Le(this.getRuntime(),a)}),this.deletionSynchronizer=new Je(e,a=>this.applySessionDeletion(a)),this.historySubscriptions=new xe(this.client),this.nativeCleanupOutbox=new je({logger:console.info}),this.acpDiscoveryWatcher=new x(async()=>{w(),await M(this.getRuntime())}),this.nativeFusion?.setExternalTerminalHandler?.(a=>{this.handleExternalTerminal(a)}),this.nativeFusion?.setExternalClaimHandler?.((a,i)=>{this.chatQueue.noteExternalClaim(a,i)}),this.nativeCleanupOutbox.start(),d(this.managerRuntime),this.managerRuntime.start(),this.reloadCustomAgents();try{this.acpDiscoveryWatcher.start()}catch(a){console.warn(`[acp.discovery] watcher unavailable: ${a instanceof Error?a.message:String(a)}`)}this.activityProbeTimer=setInterval(()=>{Ce(this.sessions.entries(),()=>p(this.client)),this.publishManagedActivitySnapshots().catch(a=>{console.error("[session.activity] managed probe failed",a)})},15e3),this.activityProbeTimer.unref?.(),this.attachmentCleanupTimer=setInterval(()=>{const a=new Set([...u().map(i=>i.workDir),...Array.from(this.pendingTransfers.values()).map(i=>i.rootPath)]);for(const i of a)try{De(this.resolvePath(i))}catch(l){console.error("[attachment.cleanup] failed",l instanceof Error?l.message:String(l))}},6e4),this.attachmentCleanupTimer.unref?.()}executeManagedManagerAction(e){return this.managerRuntime.executeScopedWorkerAction(e.managerSessionId,e.action,e.params,e.roomOrigin)}noteManagedRoomSendOutcome(e){for(const t of this.sessions.values()){if(t.managedRoomContextToken!==e.token)continue;const s=t.roomSendOutcome??(t.roomSendOutcome={successes:0,failureCodes:[]});e.ok?s.successes+=1:s.failureCodes.length<20&&s.failureCodes.push(e.errorCode??"managed_room_action_failed");return}}getManagedRoomActiveRunId(e,t){const s=this.sessions.get(t);if(s?.currentRunId)return s.currentRunId;for(const n of this.sessions.values())if(n.managedRoomContextToken===e)return n.currentRunId??null;return null}getRuntime(){return{client:this.client,pendingTransfers:this.pendingTransfers,processedReqIds:this.processedReqIds,reloadCustomAgents:()=>this.reloadCustomAgents(),getAgentSnapshot:this.getAgentSnapshot??void 0,resolvePath:e=>this.resolvePath(e),resolveAuthorizedPath:(e,t)=>this.resolveAuthorizedPath(e,t),resolveAuthorizedPathAsync:(e,t)=>this.resolveAuthorizedPathAsync(e,t),runTextAcc:this.runTextAcc,sessions:this.sessions,evictIdleSessions:()=>this.evictIdleSessions(),nativeFusion:this.nativeFusion,managerRuntime:this.managerRuntime,chatQueue:this.chatQueue,activityPublisher:{publish:(e,t)=>this.publishSessionActivity(e,t)},upgradePolicyController:this.upgradePolicyController,revokeManagedRoomContextToken:this.managedRoomContextRevoker,managedRoomExecutor:this.managedRoomExecutor,runJournal:this.runJournal,recoveryBarrier:this.recoveryBarrier,prepareManagedRecovery:this.prepareManagedRecovery}}async resumePendingAcpAuthentication(e){const t=[...this.sessions.values()].find(s=>s.agentType===e&&s.adapter.hasPendingAuthenticationRetry?.());return t?.adapter.resumeAfterExternalAuthentication?(await t.adapter.resumeAfterExternalAuthentication(),!0):!1}getUpgradeIdleState(){const e=[];return[...this.sessions.values()].some(t=>t.currentRunId!==null)&&e.push("active-agent-turn"),this.pendingTransfers.size>0&&e.push("file-transfer"),this.activeRequests>0&&e.push("active-daemon-request"),{idle:e.length===0,reasons:e}}bindManagedRoomFromLocal(e){return be(this.getRuntime(),this.managedRoomBinder,e)}stewardSayFromLocal(e){const t=typeof e.sessionId=="string"?e.sessionId:"",s=typeof e.text=="string"?e.text:"";return t?L(this.getRuntime(),t,s):N(this.getRuntime(),s)}prepareForUpgrade(e){this.recoveryBarrier.freezeDispatch();const t=this.runJournal.markPlannedUpgrade(e);return this.runJournal.sync(),{activeRunCount:t}}cancelUpgradePreparation(){this.recoveryBarrier.unfreezeDispatch()}async recoverInterruptedRuns(){this.recoveryPass??=this.recoveryCoordinator.recoverAll(),await this.recoveryPass}getPendingRecoveryCount(){return this.runJournal.loadPendingReconciliation().records.length}revokeProjectFsHandles(){this.projectFsHandleStore.revokeAll()}async commitRecoveryTerminal(e,t){const s=this.sessions.get(e.sessionId);s&&(s.currentRunId=null,s.currentRunPhase=null,s.journalRunId=null,s.heartbeatTimer&&(clearInterval(s.heartbeatTimer),s.heartbeatTimer=null)),this.runTextAcc.delete(`${e.sessionId}:${e.providerRunId??e.runId}`),this.publishSessionActivity(e.sessionId,null);const n=Ge();Pe(e.sessionId,{id:`upgrade-recovery-terminal-${e.runId}`,sessionId:e.sessionId,role:"agent",ts:Date.now(),payload:JSON.stringify({v:1,type:"error",content:n,error:!0,recoveryState:t.result,recoveryReason:t.reason})}),Te({sessionId:e.sessionId,agentType:e.agentType,sessionMode:e.sessionMode,workDir:e.workDir,agentSessionId:e.agentSessionId,modelId:e.modelId,status:"failed",attentionId:`upgrade-recovery:${e.runId}`,lastActivityAt:new Date().toISOString()}),this.managerRuntime.noteAgentEvent(e.sessionId,{state:"error",runId:e.providerRunId??e.runId,seq:e.lastObservedEventSeq+1,message:n}),p(this.client);const r=e.lastObservedEventSeq+1;this.client.sendAgentEvent({type:"event",event:"agent",payload:t.result==="interrupted_by_upgrade"?{state:"interrupted_by_upgrade",sessionId:e.sessionId,runId:e.providerRunId??e.runId,seq:r,reason:t.reason}:{state:"recovery_failed",sessionId:e.sessionId,runId:e.providerRunId??e.runId,seq:r,reason:t.reason,...t.message?{message:t.message}:{}},seq:r,id:`agent-recovery-terminal-${e.runId}`}),this.chatQueue.noteTerminal(e.sessionId)}setManagedRoomTurnPreparer(e){this.chatQueue.setManagedRoomTurnPreparer(e)}setManagedAgentDirectTurnPreparer(e){this.chatQueue.setManagedAgentDirectTurnPreparer(e)}setManagedRecoveryPreparer(e){this.prepareManagedRecovery=e}async enqueueManagedRoomBatch(e){const t=e.map(s=>{const n=u().find(r=>r.sessionId===s.params.sessionId);return{context:s.context,params:{...s.params,modelId:n?.modelId??s.params.modelId,sessionMode:n?.sessionMode??s.params.sessionMode,managerConfig:n?.managerConfig??s.params.managerConfig,managerDefaultWorkerAgentType:n?.managerDefaultWorkerAgentType??s.params.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:n?.managerDefaultWorkerModelId??s.params.managerDefaultWorkerModelId}}});await this.chatQueue.enqueueManagedRoomBatch(t)}async retireManagedRoomSession(e){this.chatQueue.purgeSession(e),await we(this.getRuntime(),e)}discardPendingManagedRoomMessages(e){return this.chatQueue.discardPendingManagedRoomMessages(e)}async synchronizeSessionDeletions(){await this.deletionSynchronizer.synchronize()}async applySessionDeletion(e){const t=new Fe({daemonInstallationId:m()}),s=u().find(o=>o.sessionId===e.sessionId)?.codexSettings?.codexHome;let n=[];try{n=Ee(e.sessionId,{records:u()})}catch(o){console.warn("[session.deletions] local native source lookup failed",{error:o instanceof Error?o.message:String(o)})}t.recordSession(e);for(const o of[...e.sources,...n]){const h=t.find(o.agentType,o.sourceSessionKey);h&&h.sessionId!==e.sessionId||t.record({...e,...o})}this.runJournal.markSessionAborted(e.sessionId),this.recoveryBarrier.end(e.sessionId);const r=this.sessions.get(e.sessionId);if(r){this.revokeManagedRoomToken(r);try{await r.adapter.stop()}catch{}this.sessions.delete(e.sessionId)}this.historySubscriptions.closeSession(e.sessionId),this.nativeFusion?.handleSessionDeleted(e.sessionId),this.chatQueue.purgeSession(e.sessionId),Qe(e.sessionId),Ie(e.sessionId),Ae(e.sessionId),this.runTextAcc.delete(e.sessionId),this.publishSessionActivity(e.sessionId,null),this.nativeCleanupOutbox.enqueue(e,s),this.nativeCleanupOutbox.kick()}publishSessionActivity(e,t){this.client.sendEvent({type:"event",event:"session.activity",payload:{sessionId:e,activity:t}})}async handleExternalTerminal(e){const t=this.sessions.get(e);t&&(t.journalRunId&&(this.recoveryCoordinator.completeFromProvider(e,t.journalRunId),t.journalRunId=null),this.sessions.delete(e),this.revokeManagedRoomToken(t),t.heartbeatTimer&&clearInterval(t.heartbeatTimer),t.adapter.removeAllListeners(),await t.adapter.stop().catch(()=>{})),this.chatQueue.noteTerminal(e)}async publishManagedActivitySnapshots(){for(const[e,t]of this.sessions.entries()){if(t.heartbeatTimer||!t.currentRunId||!t.adapter.getStatus)continue;const s=await t.adapter.getStatus().catch(()=>null);if(!s?.active||!s.runPhase)continue;const n=new Date().toISOString();this.publishSessionActivity(e,{sessionId:e,runId:s.runId||t.currentRunId,runPhase:s.runPhase,startedAt:new Date(t.lastActiveAt).toISOString(),updatedAt:n,canStop:s.canStop??!0});const r=t.heartbeatSeq++;this.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"heartbeat",sessionId:e,runId:s.runId||t.currentRunId,seq:r,runPhase:s.runPhase,canStop:s.canStop??!0},seq:r,id:`agent-status-${s.runId||t.currentRunId}-${Date.now()}`})}}reloadCustomAgents(){for(const t of S())t.startsWith("custom:")&&k(t);const e=I();for(const[t,s]of Object.entries(e.customAgents??{}))ve(t,s);Re(ye(),new Set(Object.keys(e.customAgents??{})))}async handleReq(e,t={}){const s=this.getRuntime();let n;this.activeRequests++;try{switch(e.method){case"schedule.deliver":if(!this.scheduleHandler)throw new Error("schedules_unavailable");await this.scheduleHandler(e);break;case"chat.send":if(e.params.scheduledDelivery)throw new Error("schedule_source_untrusted");c(e.params),this.recoveryBarrier.isDispatchFrozen()||this.recoveryBarrier.isRecovering(String(e.params.sessionId??""))?n={durableQueueHandoff:await this.chatQueue.handleEnqueue({...e,method:"chat.enqueue"})}:await B(s,e);break;case"chat.enqueue":c(e.params),n={durableQueueHandoff:await this.chatQueue.handleEnqueue(e)};break;case"chat.codex.settings.get":case"chat.codex.settings.set":z(s,e);break;case"chat.queue.get":c(e.params),await this.chatQueue.handleGet(e);break;case"chat.queue.edit":c(e.params),await this.chatQueue.handleEdit(e);break;case"chat.queue.delete":c(e.params),await this.chatQueue.handleDelete(e);break;case"chat.queue.promote":c(e.params),await this.chatQueue.handlePromote(e);break;case"chat.abort":c(e.params),await O(s,e);break;case"session.refresh":c(e.params),await W(s,e);break;case"session.history.open":this.historySubscriptions.handleOpen(e);break;case"session.history.sync":this.historySubscriptions.handleSync(e);break;case"session.history.page":this.historySubscriptions.handlePage(e);break;case"session.history.close":this.historySubscriptions.handleClose(e);break;case"session.body.replica.subscribe":this.historySubscriptions.handleReplicaSubscribe(e);break;case"session.body.replica.unsubscribe":this.historySubscriptions.handleReplicaUnsubscribe(e);break;case"session.history":this.client.sendRes({type:"res",id:e.id,ok:!1,error:"upgrade_required"});break;case"session.message.status":J(s,e);break;case"session.tool.detail":await _(s,e);break;case"voice.session.body.window":V(s,e);break;case"session.title.set":await U(s,e);break;case"room.agent.bind-managed":await Se(s,this.managedRoomBinder,e);break;case"room.agent.restart-managed":await ke(s,this.managedRoomBinder,e);break;case"fs.ls":await X(s,e);break;case"project.fs.open":case"project.fs.list":case"project.fs.read":case"project.fs.close":await We(this.client,this.projectFsHandleStore,e,this.trustedProjectFsRequestResolver);break;case"fs.read":await Z(s,e);break;case"fs.write":await q(s,e);break;case"fs.export.markdown-pdf":await ne(s,e);break;case"fs.export.markdown-pdf.setup":await re(s,e);break;case"fs.archive.zip":await ie(s,e);break;case"fs.rename":await Y(s,e);break;case"fs.transfer.start":await ae(s,e);break;case"fs.transfer.chunk":await se(s,e);break;case"fs.transfer.finish":await te(s,e);break;case"fs.transfer.abort":await ee(s,e);break;case"region.probe":await oe(s,e);break;case"region.switch":await ce(s,e);break;case"upgrade.start":await A(this.client,e.id,e.params.version,{currentVersion:this.cliVersion,confirmedMajor:e.params.confirmedMajor===!0,prepareForUpgrade:r=>this.prepareForUpgrade(r),cancelUpgradePreparation:()=>this.cancelUpgradePreparation(),shutdownAfterHandoff:()=>{setTimeout(()=>process.kill(process.pid,"SIGTERM"),100).unref?.()}});break;case"upgrade.status":await T(this.client,e.id,{currentVersion:this.cliVersion});break;case"upgrade.set-policy":await le(s,e);break;case"machine.remote-access.pause":await G(this.client,this.remoteAccessPauseController,e);break;case"agents.refresh":await P(s,e);break;case"agent.permission.respond":await _e(s,e);break;case"agent.auth.start":case"agent.auth.logout":case"agent.session-options.get":case"agent.external-sessions.list":case"agent.external-sessions.import":case"agent.external-sessions.close":case"agent.external-sessions.delete":await Ue(s,e);break;case"models.refresh":await C(s,e);break;case"agent.config.get":await E(s,e);break;case"agent.config.upsert":await j(s,e);break;case"agent.config.clear":await F(s,e);break;case"agent.config.test":await Q(s,e);break;case"agent.workspace.validate":await $(s,e);break;case"agent.capabilities.list":await D(s,e);break;case"skill.list":case"skill.install":case"skill.doctor":case"skill.setup":case"skill.use":this.client.sendRes({type:"res",id:e.id,ok:!1,error:"feature_retired"});break;case"session.wechat-rpa.channel.get":case"session.wechat-rpa.channel.upsert":case"session.wechat-rpa.channel.sync":case"manager.wechat-rpa.channel.get":case"manager.wechat-rpa.channel.upsert":case"manager.wechat-rpa.channel.sync":this.client.sendRes({type:"res",id:e.id,ok:!1,error:"feature_retired"});break;default:this.client.sendRes({type:"res",id:e.id,ok:!1,error:`Unknown method: ${e.method}`})}}catch(r){if(t.propagateErrors)throw r;this.client.sendRes({type:"res",id:e.id,ok:!1,error:r instanceof Error?r.message:String(r)})}finally{this.activeRequests--}return n}evictIdleSessions(){if(this.sessions.size<Ne)return;let e=null;for(const[t,s]of this.sessions)(!e||s.lastActiveAt<e.session.lastActiveAt)&&(e={key:t,session:s});e&&(this.revokeManagedRoomToken(e.session),e.session.heartbeatTimer&&(clearInterval(e.session.heartbeatTimer),e.session.heartbeatTimer=null),e.session.adapter.removeAllListeners(),e.session.adapter.stop().catch(()=>{}),this.sessions.delete(e.key))}resolvePath(e){return fe(e)}resolveAuthorizedPath(e,t){return pe(e,de(t))}async resolveAuthorizedPathAsync(e,t){return ge(e,await me(t))}async cleanup(){this.chatQueue.stop(),this.projectFsHandleStore.revokeAll(),this.acpDiscoveryWatcher.stop(),this.nativeFusion?.setExternalTerminalHandler?.(null),this.nativeCleanupOutbox.stop(),this.historySubscriptions.closeAll(),this.activityProbeTimer&&(clearInterval(this.activityProbeTimer),this.activityProbeTimer=null),this.attachmentCleanupTimer&&(clearInterval(this.attachmentCleanupTimer),this.attachmentCleanupTimer=null);for(const[,e]of this.sessions)this.revokeManagedRoomToken(e),e.heartbeatTimer&&(clearInterval(e.heartbeatTimer),e.heartbeatTimer=null),e.adapter.removeAllListeners(),await e.adapter.stop().catch(()=>{});this.sessions.clear(),this.runTextAcc.clear(),K(this.getRuntime()),await this.managerRuntime.stop(),d(null)}revokeManagedRoomToken(e){const t=e.managedRoomContextToken;e.managedRoomContextToken=null,t&&this.managedRoomContextRevoker?.(t)}}export{Ys as SessionManager,st as resolveSessionWorkDir,Ge as upgradeRecoveryVisibleMessage};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
`,"utf8"),r.fsyncSync(e),r.closeSync(e),e=void 0,
|
|
1
|
+
import p from"node:crypto";import r from"node:fs";import{renameSyncWithRetry as h}from"../fs/atomic-rename.js";import u from"node:path";import{resolvePersonalSyncV1Path as y}from"../personal-sync/paths.js";import{getDaemonInstallationId as f}from"../personal-sync/identity.js";import{NativeSourceDeletionStore as I}from"../native-fusion/native-source-deletions.js";import{NativeSessionLifecycleRegistry as S}from"./native-session-lifecycle.js";const d=1,b=8,v=6e4,w=360*60*1e3,m=new Set(["succeeded_archived","succeeded_deleted","succeeded_already_absent","skipped_unsupported","skipped_invalid_identity","failed_permanent"]);class P{options;lifecycle;timer=null;drainPromise=null;constructor(t={}){this.options=t,this.lifecycle=t.lifecycle??new S}start(){this.timer||(this.drain(),this.timer=setInterval(()=>{this.drain()},this.options.drainIntervalMs??v),this.timer.unref?.())}stop(){this.timer&&clearInterval(this.timer),this.timer=null}enqueue(t,s){if((t.nativeCleanupPolicy??"none")!=="auto")return[];const i=this.read(!0),e=[];for(const o of t.sources){const n=this.jobId(t,o.agentType,o.sourceSessionKey),c=i.jobs[n];if(c){e.push(c);continue}const l={schemaVersion:d,daemonInstallationId:this.installationId(),jobId:n,sessionId:t.sessionId,deletionRevision:t.deletionRevision,agentType:o.agentType,sourceSessionKey:o.sourceSessionKey,...t.workDir?{workDir:t.workDir}:{},...o.agentType==="codex"&&s?{codexHome:s}:{},requestedAt:t.deletedAt,state:"pending",attempts:0};i.jobs[n]=l,e.push(l)}return e.some(o=>o.state==="pending")&&this.write(i),e}kick(){this.drain()}async drain(){return this.drainPromise?await this.drainPromise:(this.drainPromise=this.drainOnce().finally(()=>{this.drainPromise=null}),await this.drainPromise)}listJobs(){return Object.values(this.read(!0).jobs).sort((t,s)=>t.deletionRevision-s.deletionRevision||t.jobId.localeCompare(s.jobId))}async drainOnce(){for(;;){const t=this.read(!0),s=this.now(),i=Object.values(t.jobs).filter(o=>o.state==="pending"||o.state==="retry_wait"&&(!o.nextAttemptAt||Date.parse(o.nextAttemptAt)<=s.getTime())).sort((o,n)=>o.deletionRevision-n.deletionRevision||o.jobId.localeCompare(n.jobId))[0];if(!i)return;i.state="running",i.attempts+=1,delete i.nextAttemptAt,this.write(t);let e;if(!this.sourceGuard(i))e={outcome:"invalid_identity"};else try{e=await this.lifecycle.execute(i.agentType,i.sourceSessionKey,{workDir:i.workDir,...i.codexHome?{codexHome:i.codexHome}:{}})}catch{e={outcome:"transient",errorCode:"lifecycle_unexpected_failure"}}this.applyResult(i.jobId,e)}}applyResult(t,s){const i=this.read(!1),e=i.jobs[t];if(!e||m.has(e.state))return;const o=this.now().toISOString();switch(s.outcome){case"archived":e.state="succeeded_archived";break;case"deleted":e.state="succeeded_deleted";break;case"already_absent":e.state="succeeded_already_absent";break;case"unsupported":e.state="skipped_unsupported";break;case"invalid_identity":e.state="skipped_invalid_identity";break;case"permanent":e.state="failed_permanent",e.lastErrorCode=s.errorCode;break;case"transient":{if(e.lastErrorCode=s.errorCode,e.attempts>=(this.options.maxAttempts??b)){e.state="failed_permanent";break}e.state="retry_wait";const n=Math.min((this.options.retryBaseMs??5e3)*2**Math.max(0,e.attempts-1),w);e.nextAttemptAt=new Date(this.now().getTime()+n).toISOString(),delete e.completedAt,this.write(i),this.log(e,s.errorCode);return}}e.completedAt=o,delete e.nextAttemptAt,this.write(i),this.log(e,e.lastErrorCode??s.outcome)}sourceGuard(t){if(this.options.sourceGuard)return this.options.sourceGuard(t);const s=new I({rootDir:this.rootDir(),daemonInstallationId:this.installationId()}).find(t.agentType,t.sourceSessionKey);return!!(s&&s.sessionId===t.sessionId&&s.deletionRevision===t.deletionRevision)}log(t,s){this.options.logger?.("[native-cleanup] job state changed",{job:t.jobId.slice(0,12),provider:t.agentType,state:t.state,result:s,attempts:t.attempts})}read(t){const s=this.filePath();if(!r.existsSync(s))return this.emptyFile();const i=JSON.parse(r.readFileSync(s,"utf8"));if(i.schemaVersion!==d||i.daemonInstallationId!==this.installationId()||!i.jobs||typeof i.jobs!="object"||Array.isArray(i.jobs))throw new Error("invalid native cleanup outbox");let e=!1;for(const[o,n]of Object.entries(i.jobs)){if(o!==n.jobId||n.schemaVersion!==d||n.daemonInstallationId!==this.installationId()||!n.sessionId||!n.agentType||!n.sourceSessionKey||!Number.isSafeInteger(n.deletionRevision)||n.deletionRevision<1||!Number.isSafeInteger(n.attempts)||n.attempts<0||!m.has(n.state)&&n.state!=="pending"&&n.state!=="running"&&n.state!=="retry_wait")throw new Error("invalid native cleanup job");t&&n.state==="running"&&(n.state="pending",e=!0)}return e&&this.write(i),i}write(t){_(this.filePath(),t)}emptyFile(){return{schemaVersion:d,daemonInstallationId:this.installationId(),jobs:{}}}jobId(t,s,i){return p.createHash("sha256").update(`${this.installationId()}\0${t.deletionRevision}\0${s}\0${i}`).digest("hex")}installationId(){return this.options.daemonInstallationId??f()}rootDir(){return this.options.rootDir??y()}filePath(){return u.join(this.rootDir(),"native-session-cleanup-outbox.json")}now(){return this.options.now?.()??new Date}}function _(a,t){const s=u.dirname(a);r.mkdirSync(s,{recursive:!0,mode:448});const i=`${a}.tmp-${process.pid}-${p.randomBytes(6).toString("hex")}`;let e;try{if(e=r.openSync(i,"wx",384),r.writeFileSync(e,`${JSON.stringify(t,null,2)}
|
|
2
|
+
`,"utf8"),r.fsyncSync(e),r.closeSync(e),e=void 0,h(i,a),process.platform!=="win32"){const o=r.openSync(s,"r");try{r.fsyncSync(o)}finally{r.closeSync(o)}}}finally{e!==void 0&&r.closeSync(e);try{r.unlinkSync(i)}catch{}}}export{P as NativeSessionCleanupOutbox};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import{createInterface as
|
|
2
|
-
${
|
|
3
|
-
${t.stderr}`)}async function
|
|
4
|
-
`)})};try{
|
|
5
|
-
${
|
|
6
|
-
${e.stderr}`;return{canArchive:e.code===0&&/\barchive-chat\b/.test(t),canDelete:e.code===0&&/\bdelete-chat\b/.test(t)}},archive:async e=>
|
|
1
|
+
import{createInterface as g}from"node:readline";import x from"node:fs";import{isAvailableBuiltinAgentType as k}from"@shennian/wire";import{buildAgentProcessEnv as y}from"../agent-env.js";import{resolveBuiltinCommand as w,spawnAgentCommand as C}from"../agents/command-spec.js";import{deleteOwnedPiSession as $}from"../agents/pi-session-ownership.js";const O=64*1024,f=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,I=/^ses_[A-Za-z0-9_-]{6,191}$/;function A(o,r){return o.length>=O?o:`${o}${String(r)}`.slice(0,O)}const N=async(o,r,i=1e4,e)=>{if(!k(o))return{code:null,stdout:"",stderr:"",timedOut:!1,spawnErrorCode:"command_unavailable"};const t=w(o);return t?await new Promise(s=>{let a="",m="",p=!1,c=!1;const l=C(t,r,{stdio:["ignore","pipe","pipe"],env:y({NO_COLOR:"1"}),...e?{cwd:e}:{}}),h=n=>{p||(p=!0,d&&clearTimeout(d),s({...n,stdout:a,stderr:m,timedOut:c}))};l.stdout?.on("data",n=>{a=A(a,n)}),l.stderr?.on("data",n=>{m=A(m,n)}),l.on("error",n=>{h({code:null,spawnErrorCode:n.code??"spawn_failed"})}),l.on("close",n=>h({code:n}));const d=setTimeout(()=>{c=!0,l.kill("SIGTERM"),setTimeout(()=>l.kill("SIGKILL"),1e3).unref?.()},i);d.unref?.()}):{code:null,stdout:"",stderr:"",timedOut:!1,spawnErrorCode:"command_unavailable"}};function L(o){return`${o.stdout}
|
|
2
|
+
${o.stderr}`.toLowerCase()}function v(o,r){if(o.spawnErrorCode==="command_unavailable"||o.spawnErrorCode==="ENOENT")return{outcome:"unsupported"};if(o.timedOut)return{outcome:"transient",errorCode:"command_timeout"};const i=L(o);return/not found|does not exist|no session|unknown session|already (?:deleted|archived)/.test(i)?{outcome:"already_absent"}:/busy|locked|writer|in use|current active session|active turn|temporar|try again|timed out|timeout/.test(i)?{outcome:"transient",errorCode:"native_busy"}:/invalid.*(?:uuid|session|id)|malformed/.test(i)?{outcome:"invalid_identity"}:/permission denied|unauthenticated|authentication|forbidden/.test(i)?{outcome:"permanent",errorCode:"native_auth_required"}:o.code===0?{outcome:r}:{outcome:"transient",errorCode:"native_command_failed"}}async function b(o,r,i,e){const t=await o(r,i);return!t.timedOut&&t.code===0&&e.test(`${t.stdout}
|
|
3
|
+
${t.stderr}`)}async function E(o,r,i){return await new Promise(e=>{let t=null,s=!1,a=1,m=null;const p=new Map,c=d=>{if(!s){s=!0,m&&clearTimeout(m);for(const n of p.values())n.reject(new Error("app_server_stopped"));p.clear(),t?.kill("SIGTERM"),e(d)}},l=(d,n)=>{if(!t?.stdin)return Promise.reject(new Error("app_server_unavailable"));const u=a++;return new Promise((_,D)=>{p.set(u,{resolve:_,reject:D}),t.stdin.write(`${JSON.stringify({id:u,method:d,params:n})}
|
|
4
|
+
`)})};try{t=C(o,["app-server","--listen","stdio://"],{stdio:["pipe","pipe","ignore"],env:y({NO_COLOR:"1",...i?{CODEX_HOME:i}:{}})})}catch{c({outcome:"transient",errorCode:"app_server_start_failed"});return}g({input:t.stdout}).on("line",d=>{if(!d.trim())return;let n;try{n=JSON.parse(d)}catch{return}if(n.id==null)return;const u=p.get(n.id);if(u)if(p.delete(n.id),n.error){const _=new Error(n.error.message??"app_server_error");_.rpcCode=n.error.code,u.reject(_)}else u.resolve(n.result)}),t.on("error",()=>c({outcome:"transient",errorCode:"app_server_start_failed"})),t.on("close",()=>{s||c({outcome:"transient",errorCode:"app_server_stopped"})}),m=setTimeout(()=>c({outcome:"transient",errorCode:"app_server_timeout"}),12e3),m.unref?.(),(async()=>{try{await l("initialize",{clientInfo:{name:"shennian-native-cleanup",title:"Shennian",version:"1"},capabilities:{experimentalApi:!0}}),await l("thread/archive",{threadId:r}),c({outcome:"archived"})}catch(d){const n=d,u=n.message.toLowerCase();/not found|does not exist|already archived|no rollout/.test(u)?c({outcome:"already_absent"}):/busy|locked|writer|active turn|in use/.test(u)?c({outcome:"transient",errorCode:"native_busy"}):n.rpcCode===-32601||/method not found|unsupported/.test(u)?c({outcome:"unsupported"}):c({outcome:"transient",errorCode:"app_server_failed"})}})()})}class U{options;capabilities=new Map;constructor(r={}){this.options=r}async execute(r,i,e={}){if(r==="codex"&&e.codexHome){if(!f.test(i))return{outcome:"invalid_identity"};const a=w("codex");return a?await E(a,i,e.codexHome):{outcome:"unsupported"}}const t=this.adapter(r),s=await this.probe(r,t);if(s.canArchive&&t.archive)return await t.archive(i);if(s.canDelete&&t.delete){if(r==="gemini"&&!e.workDir)return{outcome:"invalid_identity"};if((r==="gemini"||r==="opencode")&&e.workDir)try{if(!x.statSync(e.workDir).isDirectory())return{outcome:"permanent",errorCode:"workdir_unavailable"}}catch{return{outcome:"permanent",errorCode:"workdir_unavailable"}}return await this.deleteWithContext(t,i,e)}return{outcome:"unsupported"}}async deleteWithContext(r,i,e){return r.delete?await r.delete(i,e):{outcome:"unsupported"}}clearCapabilityCache(){this.capabilities.clear()}probe(r,i){const e=this.capabilities.get(r);if(e)return e;const t=i.probe().catch(()=>({canArchive:!1,canDelete:!1}));return this.capabilities.set(r,t),t}adapter(r){const i=this.options.runner??N;return r==="codex"?{probe:async()=>({canArchive:await b(i,"codex",["--help"],/\barchive\b/),canDelete:!1}),archive:async e=>{if(!f.test(e))return{outcome:"invalid_identity"};const t=this.options.codexArchive,s=w("codex");let a={outcome:"unsupported"};return t?a=await t(e):s&&(a=await E(s,e)),a.outcome==="archived"||a.outcome==="already_absent"||a.outcome==="invalid_identity"||a.outcome==="transient"&&a.errorCode==="native_busy"?a:v(await i("codex",["archive",e],15e3),"archived")}}:r==="gemini"?{probe:async()=>({canArchive:!1,canDelete:await b(i,"gemini",["--help"],/--delete-session\b/)}),delete:async(e,t)=>{if(!f.test(e))return{outcome:"invalid_identity"};const s=await i("gemini",["--delete-session",e],15e3,t?.workDir);return/invalid session identifier/i.test(`${s.stdout}
|
|
5
|
+
${s.stderr}`)?{outcome:"already_absent"}:v(s,"deleted")}}:r==="opencode"?{probe:async()=>({canArchive:!1,canDelete:await b(i,"opencode",["session","delete","--help"],/session delete\s+<sessionID>/i)}),delete:async(e,t)=>I.test(e)?v(await i("opencode",["session","delete",e],15e3,t?.workDir),"deleted"):{outcome:"invalid_identity"}}:r==="cursor"?{probe:async()=>{const e=await i("cursor",["--help"]),t=`${e.stdout}
|
|
6
|
+
${e.stderr}`;return{canArchive:e.code===0&&/\barchive-chat\b/.test(t),canDelete:e.code===0&&/\bdelete-chat\b/.test(t)}},archive:async e=>f.test(e)?v(await i("cursor",["archive-chat",e],15e3),"archived"):{outcome:"invalid_identity"},delete:async e=>f.test(e)?v(await i("cursor",["delete-chat",e],15e3),"deleted"):{outcome:"invalid_identity"}}:r==="pi-coding-agent"?{probe:async()=>({canArchive:!1,canDelete:!0}),delete:async e=>{const t=$(e);return t==="deleted"?{outcome:"deleted"}:t==="already_absent"?{outcome:"already_absent"}:{outcome:"invalid_identity"}}}:{probe:async()=>({canArchive:!1,canDelete:!1})}}}export{U as NativeSessionLifecycleRegistry,N as runNativeLifecycleCommand};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{SESSION_SYNC_DATA_EPOCH as R,SESSION_SYNC_PROTOCOL_VERSION as M,SESSION_TITLE_SOURCE_PRIORITY as I,isInternalSession as C,isToolPayload as D,parseStewardSayPayload as q,sessionPreviewFromPayload as _,STEWARD_TERMINAL_OPEN_MESSAGE_ID_PREFIX as T}from"@shennian/wire";import k from"node:crypto";import u from"node:fs";import{renameSyncWithRetry as j}from"../fs/atomic-rename.js";import b from"node:path";import{NativeSourceDeletionStore as W}from"../native-fusion/native-source-deletions.js";import{registerInternalNativeSource as F}from"../native-fusion/source-visibility.js";import{getDaemonInstallationId as S}from"../personal-sync/identity.js";import{PERSONAL_SYNC_V1_ROOT_NAME as $,resolvePersonalSyncV1Path as Q}from"../personal-sync/paths.js";import{CanonicalSessionStore as Y}from"./canonical-store.js";const N=120;function E(t){if(t.length<=N)return t;let e=t.slice(0,N);const n=e.charCodeAt(e.length-1);return n>=55296&&n<=56319&&(e=e.slice(0,-1)),e}let P=null,V=null;function O(){return Q()}function c(){const t=b.join(O(),"canonical");return(!P||V!==t)&&(P=new Y(t,S()),V=t),P}function B(){return b.join(O(),"session-index.json")}function d(){const t=B();if(!u.existsSync(t))return{};const e=JSON.parse(u.readFileSync(t,"utf8"));if(!e||typeof e!="object"||Array.isArray(e))throw new Error(`invalid personal session index: ${t}`);const n=S();for(const s of Object.values(e))if(s.daemonInstallationId!==n)throw new Error(`personal session index belongs to another daemon installation: ${t}`);return e}function g(t){te(B(),t)}function h(t){return _(t.payload,120)}function p(t){if(new W({rootDir:O(),daemonInstallationId:S()}).hasSession(t))throw new Error(`session_deleted:${t}`)}function z(t){p(t.sessionId),S();const e=d(),n=e[t.sessionId],s=new Date().toISOString(),i=c().getManifest(t.sessionId)?.bodyRevision??n?.bodyRevision??0,o=c().getManifest(t.sessionId),a=ee(n,t),r=t.attentionId?.trim()||null,l=Array.from(new Set([...n?.seenAttentionIds??[],...n?.lastAttentionId?[n.lastAttentionId]:[]])),f=!!(r&&!l.includes(r)),v=t.lastMessagePreview===null?{preview:null,messageId:null,at:null}:t.lastMessagePreview!==void 0&&t.lastMessagePreviewMessageId&&t.lastMessagePreviewAt?{preview:t.lastMessagePreview,messageId:t.lastMessagePreviewMessageId,at:t.lastMessagePreviewAt}:{preview:n?.lastMessagePreview??null,messageId:n?.lastMessagePreviewMessageId??null,at:n?.lastMessagePreviewAt??null},A=Date.parse(t.lastVisibleEventAt??""),m=Date.parse(n?.lastVisibleEventAt??""),w=Number.isFinite(A)&&(!Number.isFinite(m)||A>=m)?t.lastVisibleEventAt:n?.lastVisibleEventAt??null,x=n?n.sessionScope==="steward"?"steward":"personal":t.sessionScope==="steward"?"steward":"personal",y={daemonInstallationId:S(),sessionId:t.sessionId,agentType:t.agentType,sessionMode:t.sessionMode??n?.sessionMode,sessionScope:x,nativeSessionVisibility:C({...n,id:t.sessionId})||C({...n,...t,id:t.sessionId,sessionMode:t.sessionMode??n?.sessionMode,sessionScope:x})?"internal":"user",managerConfig:t.managerConfig??n?.managerConfig??null,workDir:t.workDir,agentSessionId:t.agentSessionId??n?.agentSessionId??null,modelId:t.modelId??n?.modelId??null,managerDefaultWorkerAgentType:t.managerDefaultWorkerAgentType??n?.managerDefaultWorkerAgentType??null,managerDefaultWorkerModelId:t.managerDefaultWorkerModelId??n?.managerDefaultWorkerModelId??null,status:t.status??n?.status??"active",createdAt:n?.createdAt??s,updatedAt:s,lastActivityAt:t.lastActivityAt??n?.lastActivityAt??s,lastMessagePreview:v.preview,lastMessagePreviewMessageId:v.messageId,lastMessagePreviewAt:v.at,lastVisibleEventAt:w,localReady:n?.localReady===!0||t.localReady===!0,firstUserMessageId:n?.firstUserMessageId??t.firstUserMessageId??null,firstUserBodyRevision:n?.firstUserBodyRevision??t.firstUserBodyRevision??null,bodyRevision:i,indexRevision:(n?.indexRevision??0)+1,...a,firstAvailableSeq:o?.firstAvailableSeq??n?.firstAvailableSeq??null,visibleMessageCount:o?.visibleMessageCount??n?.visibleMessageCount??0,lastVisibleMessageId:o?.lastVisibleMessageId??n?.lastVisibleMessageId??null,attentionCount:(n?.attentionCount??0)+(f?1:0),lastAttentionId:f?r:n?.lastAttentionId??null,seenAttentionIds:f&&r?[...l,r]:l,lastBodyCommittedAt:o?.lastBodyCommittedAt??n?.lastBodyCommittedAt??null,deletionRevision:n?.deletionRevision??0,deletedAt:t.deletedAt??n?.deletedAt??null,syncedIndexRevision:n?.syncedIndexRevision??0,indexSyncState:"pending",indexSyncStateRevision:(n?.indexRevision??0)+1,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,indexQuarantineCode:null,titleGenerationAttemptedAt:n?.titleGenerationAttemptedAt&&n.titleGenerationNextAttemptAt!==void 0?n.titleGenerationAttemptedAt:null,titleGenerationNextAttemptAt:n?.titleGenerationNextAttemptAt??null,titleGenerationAttempts:n?.titleGenerationAttempts??0};return y.nativeSessionVisibility==="internal"&&y.agentSessionId&&F(y.sessionId,y.agentType,y.agentSessionId),e[t.sessionId]=y,g(e),y}function J(){return Object.values(d())}function Se(t){if(!t)throw new Error("sessionId is required");const e=d();e[t]&&(delete e[t],g(e))}function ge(t){c().purgeSession(t)}function H(){const t=d();let e=!1;const n=new Date().toISOString();for(const[s,i]of Object.entries(t)){const o=E(i.title);if(o===i.title)continue;const a=i.indexRevision+1;t[s]={...i,title:o,indexRevision:a,indexSyncState:"pending",indexSyncStateRevision:a,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,indexQuarantineCode:null,updatedAt:n},e=!0}e&&g(t)}function fe(){const t=S();return Z(),K(),H(),J().filter(e=>{const n=e.indexSyncStateRevision===e.indexRevision;return e.indexQuarantineCode||n&&(e.indexSyncState==="quarantined"||e.indexSyncState==="terminal")||n&&e.indexSyncNextAttemptAt&&Date.parse(e.indexSyncNextAttemptAt)>Date.now()?!1:e.indexRevision>e.syncedIndexRevision&&e.localReady&&!!e.firstUserMessageId&&e.firstUserBodyRevision!=null}).sort((e,n)=>e.indexRevision-n.indexRevision).map(e=>{const n=!!(e.lastMessagePreview&&e.lastMessagePreviewMessageId&&e.lastMessagePreviewAt);return{protocolVersion:M,dataEpoch:R,daemonInstallationId:t,session:{id:e.sessionId,agentType:e.agentType,sessionMode:e.sessionMode,nativeSessionVisibility:e.nativeSessionVisibility,...e.sessionScope==="steward"?{sessionScope:"steward"}:{},managerConfig:e.managerConfig,agentSessionId:e.agentSessionId??null,modelId:e.modelId??null,managerDefaultWorkerAgentType:e.managerDefaultWorkerAgentType??null,managerDefaultWorkerModelId:e.managerDefaultWorkerModelId??null,title:e.title,titleSource:e.titleSource,titleRevision:e.titleRevision,titleLockedByUser:e.titleLockedByUser,titleOriginEventId:e.titleOriginEventId,status:e.status??"active",workDir:e.workDir,lastMessagePreview:n?e.lastMessagePreview:null,lastMessagePreviewMessageId:n?e.lastMessagePreviewMessageId:null,lastMessagePreviewAt:n?e.lastMessagePreviewAt:null,lastVisibleEventAt:e.lastVisibleEventAt??e.lastMessagePreviewAt??null,bodyStorageMode:"machine_local",localReady:!0,firstUserBoundary:{role:"user",messageId:e.firstUserMessageId,bodyRevision:e.firstUserBodyRevision},bodyRevision:e.bodyRevision,indexRevision:e.indexRevision,firstAvailableSeq:e.firstAvailableSeq,visibleMessageCount:e.visibleMessageCount,lastVisibleMessageId:e.lastVisibleMessageId,attentionCount:e.attentionCount??0,lastAttentionId:e.lastAttentionId??null,lastBodyCommittedAt:e.lastBodyCommittedAt,deletionRevision:e.deletionRevision,lastActivityAt:e.lastActivityAt,createdAt:e.createdAt,updatedAt:e.updatedAt,deletedAt:e.deletedAt}}})}function ve(t,e){const n=d(),s=n[t];if(!(!s||e<=s.syncedIndexRevision)){if(e>s.indexRevision)throw new Error(`cannot acknowledge future index revision ${e} for ${t}`);n[t]={...s,syncedIndexRevision:e,indexSyncState:"applied",indexSyncStateRevision:e,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null},g(n)}}function me(){const t=d();let e=0;const n=new Date().toISOString();for(const[s,i]of Object.entries(t)){if(i.deletedAt||i.indexQuarantineCode||!i.localReady)continue;const o=i.indexRevision+1;t[s]={...i,indexRevision:o,indexSyncState:"pending",indexSyncStateRevision:o,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:n},e+=1}return e>0&&g(t),e}function ye(t){const e=d(),n=e[t.sessionId];if(!n||n.indexRevision!==t.indexRevision)return"terminal";const i=(n.indexSyncStateRevision===t.indexRevision?n.indexSyncAttempts??0:0)+1;let o=t.disposition;o==="retry"&&i>=(t.maxAttempts??8)&&(o="terminal");const a=t.now??Date.now(),r=Math.min(5e3*2**Math.max(0,i-1),360*60*1e3),l=Math.round(r*.2*(Math.random()*2-1));return e[t.sessionId]={...n,indexSyncState:o==="retry"?"pending":o,indexSyncStateRevision:t.indexRevision,indexSyncAttempts:i,indexSyncNextAttemptAt:o==="retry"?new Date(a+r+l).toISOString():null,indexSyncErrorCode:t.code,indexQuarantineCode:o==="quarantined"?t.code:n.indexQuarantineCode??null},g(e),o}const X=2*6e4;function Ae(t=Date.now(),e=X){const n=d(),s=[],i=new Date(t).toISOString();for(const o of Object.values(n)){if(o.titleSource!=="first_user_fallback"||o.titleLockedByUser||o.titleGenerationAttemptedAt||!o.title.trim()||o.syncedIndexRevision<o.indexRevision||o.titleGenerationNextAttemptAt&&Date.parse(o.titleGenerationNextAttemptAt)>t)continue;const a=o.status==="completed"||o.status==="failed",r=o.visibleMessageCount>=2;let l=null;if(o.agentType==="claude"&&r?l="agent_native_unavailable":a?l="terminal":r&&t-Date.parse(o.createdAt)>=e&&(l="grace_elapsed"),!l)continue;const f=_(o.title,240);if(!f)continue;const v=k.randomUUID();n[o.sessionId]={...o,titleGenerationAttemptedAt:i,titleGenerationNextAttemptAt:null,titleGenerationAttempts:(o.titleGenerationAttempts??0)+1},s.push({sessionId:o.sessionId,requestId:v,titleSeed:f,baseTitleRevision:o.titleRevision,eligibility:l})}return s.length>0&&g(n),s}function xe(t,e=Date.now()){const n=d(),s=n[t];if(!s?.titleGenerationAttemptedAt||s.titleSource!=="first_user_fallback")return null;const i=Math.max(1,s.titleGenerationAttempts??1),o=Math.min(10*6e4,3e4*2**Math.min(i-1,5)),a=new Date(e+o).toISOString();return n[t]={...s,titleGenerationAttemptedAt:null,titleGenerationNextAttemptAt:a},g(n),a}function Ie(t,e){const s=d()[t];return!s||s.titleLockedByUser||I[s.titleSource]>=I.shennian_generated||e.titleRevision<=s.titleRevision?!1:(z({sessionId:t,agentType:s.agentType,sessionMode:s.sessionMode,managerConfig:s.managerConfig,workDir:s.workDir,agentSessionId:s.agentSessionId,modelId:s.modelId,status:s.status,title:e.title,titleSource:"shennian_generated",titleRevision:e.titleRevision,titleLockedByUser:!1,titleOriginEventId:e.titleOriginEventId}),!0)}function pe(t,e,n){p(t),S();const s=c().append(t,e,n);return U(t,e,s.bodyRevision),s.bodyRevision}function we(t,e,n){p(t),S();const s=c().upsert(t,e,n);return U(t,e,s.bodyRevision),s.bodyRevision}function Re(t,e){const n=c().getMessageState(t,e);return!n||n.tombstoned||!n.message||!n.deliveryState?{protocolVersion:M,dataEpoch:R,daemonInstallationId:S(),state:"not_found",sessionId:t,clientMessageId:e}:{protocolVersion:M,dataEpoch:R,daemonInstallationId:S(),state:n.deliveryState,sessionId:t,clientMessageId:e,messageId:n.message.id,deliveryState:n.deliveryState,bodyRevision:n.lastRevision,committedAt:new Date(n.message.ts).toISOString()}}function Me(t,e){p(t),S();const n=c().tombstone(t,e),s=d(),i=s[t];if(i){const o=e===i.lastMessagePreviewMessageId?G(t):{preview:i.lastMessagePreview??null,messageId:i.lastMessagePreviewMessageId??null,at:i.lastMessagePreviewAt??null};s[t]={...i,bodyRevision:n.bodyRevision,indexRevision:i.indexRevision+1,indexSyncState:"pending",indexSyncStateRevision:i.indexRevision+1,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:new Date().toISOString(),lastMessagePreview:o.preview,lastMessagePreviewMessageId:o.messageId,lastMessagePreviewAt:o.at,lastVisibleEventAt:L(t)},g(s)}return n.bodyRevision}function U(t,e,n){const s=d(),i=s[t];if(!i)return;const o=i.sessionScope==="steward"&&e.role==="agent"&&!q(e.payload),a=e.id.startsWith(T),r=h(e),l=o||a?null:r,f=a?r:l,v=l?{lastMessagePreview:l,lastMessagePreviewMessageId:e.id,lastMessagePreviewAt:new Date(e.ts).toISOString()}:null,A=l||D(e.payload)?new Date(e.ts).toISOString():i.lastVisibleEventAt,m=c().getManifest(t),w=e.role==="user"&&f&&!i.title?{title:E(f),titleSource:"first_user_fallback",titleRevision:i.titleRevision+1,titleLockedByUser:!1,titleOriginEventId:e.id}:null,x=e.role==="user"&&!i.localReady?{localReady:!0,firstUserMessageId:e.id,firstUserBodyRevision:n}:null;s[t]={...i,...w??{},...x??{},bodyRevision:n,indexRevision:i.indexRevision+1,indexSyncState:"pending",indexSyncStateRevision:i.indexRevision+1,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:new Date().toISOString(),lastActivityAt:new Date(e.ts).toISOString(),lastVisibleEventAt:A,...v??{},firstAvailableSeq:m?.firstAvailableSeq??i.firstAvailableSeq,visibleMessageCount:m?.visibleMessageCount??i.visibleMessageCount,lastVisibleMessageId:m?.lastVisibleMessageId??i.lastVisibleMessageId,attentionCount:i.attentionCount??0,lastAttentionId:i.lastAttentionId??null,lastBodyCommittedAt:m?.lastBodyCommittedAt??i.lastBodyCommittedAt},g(s)}function G(t){let e;do{const n=c().readPage(t,{limit:500,beforeSequence:e});for(let s=n.entries.length-1;s>=0;s-=1){const i=n.entries[s];if(i.message.id.startsWith(T))continue;const o=h(i.message);if(o)return{preview:o,messageId:i.message.id,at:new Date(i.message.ts).toISOString()}}if(!n.hasOlder||n.entries.length===0)break;e=n.entries[0].sequence}while(e!==void 0);return{preview:null,messageId:null,at:null}}function L(t){let e;do{const n=c().readPage(t,{limit:500,beforeSequence:e});for(let s=n.entries.length-1;s>=0;s-=1){const i=n.entries[s].message;if(!(!h(i)&&!D(i.payload)))return new Date(i.ts).toISOString()}if(!n.hasOlder||n.entries.length===0)break;e=n.entries[0].sequence}while(e!==void 0);return null}function K(){const t=d();let e=!1;const n=new Date().toISOString();for(const[s,i]of Object.entries(t)){if(Object.prototype.hasOwnProperty.call(i,"lastVisibleEventAt"))continue;const o=i.indexRevision+1;t[s]={...i,lastVisibleEventAt:L(s)??i.lastMessagePreviewAt??null,indexRevision:o,indexSyncState:"pending",indexSyncStateRevision:o,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:n},e=!0}e&&g(t)}function Z(){const t=d();let e=!1;const n=new Date().toISOString();for(const[s,i]of Object.entries(t)){if(Object.prototype.hasOwnProperty.call(i,"lastMessagePreviewMessageId")&&Object.prototype.hasOwnProperty.call(i,"lastMessagePreviewAt"))continue;const o=G(s);t[s]={...i,lastMessagePreview:o.preview,lastMessagePreviewMessageId:o.messageId,lastMessagePreviewAt:o.at,indexRevision:i.indexRevision+1,indexSyncState:"pending",indexSyncStateRevision:i.indexRevision+1,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:n},e=!0}e&&g(t)}function ee(t,e){const n={title:t?.title??"",titleSource:t?.titleSource??"first_user_fallback",titleRevision:t?.titleRevision??0,titleLockedByUser:t?.titleLockedByUser??!1,titleOriginEventId:t?.titleOriginEventId??null},s=E(e.title?.trim()??"");if(!s)return n;if(!e.titleSource)throw new Error("titleSource is required with title");if(n.title&&n.titleSource==="first_user_fallback"&&e.titleSource==="first_user_fallback")return n;const i=e.titleSource==="shennian_manual";if(e.titleLockedByUser!==void 0&&e.titleLockedByUser!==i)throw new Error("titleLockedByUser conflicts with titleSource");const o=s===n.title&&e.titleSource===n.titleSource,a=e.titleRevision??n.titleRevision+(o?0:1);if(!Number.isSafeInteger(a)||a<0)throw new Error("invalid titleRevision");const r=I[e.titleSource],l=I[n.titleSource];return r<l||a<n.titleRevision||o&&a===n.titleRevision||a===n.titleRevision&&!o?n:{title:s,titleSource:e.titleSource,titleRevision:a,titleLockedByUser:i,titleOriginEventId:e.titleOriginEventId??n.titleOriginEventId}}function be(t,e){const n=e?.limit&&e.limit>0?Math.min(e.limit,500):500;let i=c().readRecent(t,n).messages;return e?.before!==void 0&&(i=i.filter(o=>o.ts<e.before)),[...i].sort((o,a)=>a.ts-o.ts)}function Ee(){return c().listSessionIds()}function Pe(){return c()}function te(t,e){const n=b.dirname(t);u.mkdirSync(n,{recursive:!0,mode:448});const s=`${t}.tmp-${process.pid}-${k.randomBytes(6).toString("hex")}`;let i;try{if(i=u.openSync(s,"wx",384),u.writeFileSync(i,`${JSON.stringify(e,null,2)}
|
|
1
|
+
import{SESSION_SYNC_DATA_EPOCH as R,SESSION_SYNC_PROTOCOL_VERSION as M,SESSION_TITLE_SOURCE_PRIORITY as I,isInternalSession as C,isToolPayload as D,parseStewardSayPayload as q,sessionPreviewFromPayload as _,STEWARD_TERMINAL_OPEN_MESSAGE_ID_PREFIX as T}from"@shennian/wire";import k from"node:crypto";import u from"node:fs";import{renameSyncWithRetry as j}from"../fs/atomic-rename.js";import b from"node:path";import{NativeSourceDeletionStore as W}from"../native-fusion/native-source-deletions.js";import{registerInternalNativeSource as F}from"../native-fusion/source-visibility.js";import{getDaemonInstallationId as S}from"../personal-sync/identity.js";import{PERSONAL_SYNC_V1_ROOT_NAME as $,resolvePersonalSyncV1Path as Q}from"../personal-sync/paths.js";import{CanonicalSessionStore as Y}from"./canonical-store.js";const N=120;function E(t){if(t.length<=N)return t;let e=t.slice(0,N);const n=e.charCodeAt(e.length-1);return n>=55296&&n<=56319&&(e=e.slice(0,-1)),e}let P=null,V=null;function O(){return Q()}function c(){const t=b.join(O(),"canonical");return(!P||V!==t)&&(P=new Y(t,S()),V=t),P}function B(){return b.join(O(),"session-index.json")}function d(){const t=B();if(!u.existsSync(t))return{};const e=JSON.parse(u.readFileSync(t,"utf8"));if(!e||typeof e!="object"||Array.isArray(e))throw new Error(`invalid personal session index: ${t}`);const n=S();for(const s of Object.values(e))if(s.daemonInstallationId!==n)throw new Error(`personal session index belongs to another daemon installation: ${t}`);return e}function g(t){te(B(),t)}function h(t){return _(t.payload,120)}function p(t){if(new W({rootDir:O(),daemonInstallationId:S()}).hasSession(t))throw new Error(`session_deleted:${t}`)}function z(t){p(t.sessionId),S();const e=d(),n=e[t.sessionId],s=new Date().toISOString(),i=c().getManifest(t.sessionId)?.bodyRevision??n?.bodyRevision??0,o=c().getManifest(t.sessionId),a=ee(n,t),r=t.attentionId?.trim()||null,l=Array.from(new Set([...n?.seenAttentionIds??[],...n?.lastAttentionId?[n.lastAttentionId]:[]])),f=!!(r&&!l.includes(r)),v=t.lastMessagePreview===null?{preview:null,messageId:null,at:null}:t.lastMessagePreview!==void 0&&t.lastMessagePreviewMessageId&&t.lastMessagePreviewAt?{preview:t.lastMessagePreview,messageId:t.lastMessagePreviewMessageId,at:t.lastMessagePreviewAt}:{preview:n?.lastMessagePreview??null,messageId:n?.lastMessagePreviewMessageId??null,at:n?.lastMessagePreviewAt??null},A=Date.parse(t.lastVisibleEventAt??""),m=Date.parse(n?.lastVisibleEventAt??""),w=Number.isFinite(A)&&(!Number.isFinite(m)||A>=m)?t.lastVisibleEventAt:n?.lastVisibleEventAt??null,x=n?n.sessionScope==="steward"?"steward":"personal":t.sessionScope==="steward"?"steward":"personal",y={daemonInstallationId:S(),sessionId:t.sessionId,agentType:t.agentType,sessionMode:t.sessionMode??n?.sessionMode,sessionScope:x,nativeSessionVisibility:C({...n,id:t.sessionId})||C({...n,...t,id:t.sessionId,sessionMode:t.sessionMode??n?.sessionMode,sessionScope:x})?"internal":"user",codexSettings:t.codexSettings??n?.codexSettings,managerConfig:t.managerConfig??n?.managerConfig??null,workDir:t.workDir,agentSessionId:t.agentSessionId??n?.agentSessionId??null,modelId:t.modelId??n?.modelId??null,managerDefaultWorkerAgentType:t.managerDefaultWorkerAgentType??n?.managerDefaultWorkerAgentType??null,managerDefaultWorkerModelId:t.managerDefaultWorkerModelId??n?.managerDefaultWorkerModelId??null,status:t.status??n?.status??"active",createdAt:n?.createdAt??s,updatedAt:s,lastActivityAt:t.lastActivityAt??n?.lastActivityAt??s,lastMessagePreview:v.preview,lastMessagePreviewMessageId:v.messageId,lastMessagePreviewAt:v.at,lastVisibleEventAt:w,localReady:n?.localReady===!0||t.localReady===!0,firstUserMessageId:n?.firstUserMessageId??t.firstUserMessageId??null,firstUserBodyRevision:n?.firstUserBodyRevision??t.firstUserBodyRevision??null,bodyRevision:i,indexRevision:(n?.indexRevision??0)+1,...a,firstAvailableSeq:o?.firstAvailableSeq??n?.firstAvailableSeq??null,visibleMessageCount:o?.visibleMessageCount??n?.visibleMessageCount??0,lastVisibleMessageId:o?.lastVisibleMessageId??n?.lastVisibleMessageId??null,attentionCount:(n?.attentionCount??0)+(f?1:0),lastAttentionId:f?r:n?.lastAttentionId??null,seenAttentionIds:f&&r?[...l,r]:l,lastBodyCommittedAt:o?.lastBodyCommittedAt??n?.lastBodyCommittedAt??null,deletionRevision:n?.deletionRevision??0,deletedAt:t.deletedAt??n?.deletedAt??null,syncedIndexRevision:n?.syncedIndexRevision??0,indexSyncState:"pending",indexSyncStateRevision:(n?.indexRevision??0)+1,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,indexQuarantineCode:null,titleGenerationAttemptedAt:n?.titleGenerationAttemptedAt&&n.titleGenerationNextAttemptAt!==void 0?n.titleGenerationAttemptedAt:null,titleGenerationNextAttemptAt:n?.titleGenerationNextAttemptAt??null,titleGenerationAttempts:n?.titleGenerationAttempts??0};return y.nativeSessionVisibility==="internal"&&y.agentSessionId&&F(y.sessionId,y.agentType,y.agentSessionId),e[t.sessionId]=y,g(e),y}function J(){return Object.values(d())}function Se(t){if(!t)throw new Error("sessionId is required");const e=d();e[t]&&(delete e[t],g(e))}function ge(t){c().purgeSession(t)}function H(){const t=d();let e=!1;const n=new Date().toISOString();for(const[s,i]of Object.entries(t)){const o=E(i.title);if(o===i.title)continue;const a=i.indexRevision+1;t[s]={...i,title:o,indexRevision:a,indexSyncState:"pending",indexSyncStateRevision:a,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,indexQuarantineCode:null,updatedAt:n},e=!0}e&&g(t)}function fe(){const t=S();return Z(),K(),H(),J().filter(e=>{const n=e.indexSyncStateRevision===e.indexRevision;return e.indexQuarantineCode||n&&(e.indexSyncState==="quarantined"||e.indexSyncState==="terminal")||n&&e.indexSyncNextAttemptAt&&Date.parse(e.indexSyncNextAttemptAt)>Date.now()?!1:e.indexRevision>e.syncedIndexRevision&&e.localReady&&!!e.firstUserMessageId&&e.firstUserBodyRevision!=null}).sort((e,n)=>e.indexRevision-n.indexRevision).map(e=>{const n=!!(e.lastMessagePreview&&e.lastMessagePreviewMessageId&&e.lastMessagePreviewAt);return{protocolVersion:M,dataEpoch:R,daemonInstallationId:t,session:{id:e.sessionId,agentType:e.agentType,sessionMode:e.sessionMode,nativeSessionVisibility:e.nativeSessionVisibility,...e.sessionScope==="steward"?{sessionScope:"steward"}:{},managerConfig:e.managerConfig,agentSessionId:e.agentSessionId??null,modelId:e.modelId??null,managerDefaultWorkerAgentType:e.managerDefaultWorkerAgentType??null,managerDefaultWorkerModelId:e.managerDefaultWorkerModelId??null,title:e.title,titleSource:e.titleSource,titleRevision:e.titleRevision,titleLockedByUser:e.titleLockedByUser,titleOriginEventId:e.titleOriginEventId,status:e.status??"active",workDir:e.workDir,lastMessagePreview:n?e.lastMessagePreview:null,lastMessagePreviewMessageId:n?e.lastMessagePreviewMessageId:null,lastMessagePreviewAt:n?e.lastMessagePreviewAt:null,lastVisibleEventAt:e.lastVisibleEventAt??e.lastMessagePreviewAt??null,bodyStorageMode:"machine_local",localReady:!0,firstUserBoundary:{role:"user",messageId:e.firstUserMessageId,bodyRevision:e.firstUserBodyRevision},bodyRevision:e.bodyRevision,indexRevision:e.indexRevision,firstAvailableSeq:e.firstAvailableSeq,visibleMessageCount:e.visibleMessageCount,lastVisibleMessageId:e.lastVisibleMessageId,attentionCount:e.attentionCount??0,lastAttentionId:e.lastAttentionId??null,lastBodyCommittedAt:e.lastBodyCommittedAt,deletionRevision:e.deletionRevision,lastActivityAt:e.lastActivityAt,createdAt:e.createdAt,updatedAt:e.updatedAt,deletedAt:e.deletedAt}}})}function ve(t,e){const n=d(),s=n[t];if(!(!s||e<=s.syncedIndexRevision)){if(e>s.indexRevision)throw new Error(`cannot acknowledge future index revision ${e} for ${t}`);n[t]={...s,syncedIndexRevision:e,indexSyncState:"applied",indexSyncStateRevision:e,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null},g(n)}}function me(){const t=d();let e=0;const n=new Date().toISOString();for(const[s,i]of Object.entries(t)){if(i.deletedAt||i.indexQuarantineCode||!i.localReady)continue;const o=i.indexRevision+1;t[s]={...i,indexRevision:o,indexSyncState:"pending",indexSyncStateRevision:o,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:n},e+=1}return e>0&&g(t),e}function ye(t){const e=d(),n=e[t.sessionId];if(!n||n.indexRevision!==t.indexRevision)return"terminal";const i=(n.indexSyncStateRevision===t.indexRevision?n.indexSyncAttempts??0:0)+1;let o=t.disposition;o==="retry"&&i>=(t.maxAttempts??8)&&(o="terminal");const a=t.now??Date.now(),r=Math.min(5e3*2**Math.max(0,i-1),360*60*1e3),l=Math.round(r*.2*(Math.random()*2-1));return e[t.sessionId]={...n,indexSyncState:o==="retry"?"pending":o,indexSyncStateRevision:t.indexRevision,indexSyncAttempts:i,indexSyncNextAttemptAt:o==="retry"?new Date(a+r+l).toISOString():null,indexSyncErrorCode:t.code,indexQuarantineCode:o==="quarantined"?t.code:n.indexQuarantineCode??null},g(e),o}const X=2*6e4;function Ae(t=Date.now(),e=X){const n=d(),s=[],i=new Date(t).toISOString();for(const o of Object.values(n)){if(o.titleSource!=="first_user_fallback"||o.titleLockedByUser||o.titleGenerationAttemptedAt||!o.title.trim()||o.syncedIndexRevision<o.indexRevision||o.titleGenerationNextAttemptAt&&Date.parse(o.titleGenerationNextAttemptAt)>t)continue;const a=o.status==="completed"||o.status==="failed",r=o.visibleMessageCount>=2;let l=null;if(o.agentType==="claude"&&r?l="agent_native_unavailable":a?l="terminal":r&&t-Date.parse(o.createdAt)>=e&&(l="grace_elapsed"),!l)continue;const f=_(o.title,240);if(!f)continue;const v=k.randomUUID();n[o.sessionId]={...o,titleGenerationAttemptedAt:i,titleGenerationNextAttemptAt:null,titleGenerationAttempts:(o.titleGenerationAttempts??0)+1},s.push({sessionId:o.sessionId,requestId:v,titleSeed:f,baseTitleRevision:o.titleRevision,eligibility:l})}return s.length>0&&g(n),s}function xe(t,e=Date.now()){const n=d(),s=n[t];if(!s?.titleGenerationAttemptedAt||s.titleSource!=="first_user_fallback")return null;const i=Math.max(1,s.titleGenerationAttempts??1),o=Math.min(10*6e4,3e4*2**Math.min(i-1,5)),a=new Date(e+o).toISOString();return n[t]={...s,titleGenerationAttemptedAt:null,titleGenerationNextAttemptAt:a},g(n),a}function Ie(t,e){const s=d()[t];return!s||s.titleLockedByUser||I[s.titleSource]>=I.shennian_generated||e.titleRevision<=s.titleRevision?!1:(z({sessionId:t,agentType:s.agentType,sessionMode:s.sessionMode,managerConfig:s.managerConfig,workDir:s.workDir,agentSessionId:s.agentSessionId,modelId:s.modelId,status:s.status,title:e.title,titleSource:"shennian_generated",titleRevision:e.titleRevision,titleLockedByUser:!1,titleOriginEventId:e.titleOriginEventId}),!0)}function pe(t,e,n){p(t),S();const s=c().append(t,e,n);return U(t,e,s.bodyRevision),s.bodyRevision}function we(t,e,n){p(t),S();const s=c().upsert(t,e,n);return U(t,e,s.bodyRevision),s.bodyRevision}function Re(t,e){const n=c().getMessageState(t,e);return!n||n.tombstoned||!n.message||!n.deliveryState?{protocolVersion:M,dataEpoch:R,daemonInstallationId:S(),state:"not_found",sessionId:t,clientMessageId:e}:{protocolVersion:M,dataEpoch:R,daemonInstallationId:S(),state:n.deliveryState,sessionId:t,clientMessageId:e,messageId:n.message.id,deliveryState:n.deliveryState,bodyRevision:n.lastRevision,committedAt:new Date(n.message.ts).toISOString()}}function Me(t,e){p(t),S();const n=c().tombstone(t,e),s=d(),i=s[t];if(i){const o=e===i.lastMessagePreviewMessageId?G(t):{preview:i.lastMessagePreview??null,messageId:i.lastMessagePreviewMessageId??null,at:i.lastMessagePreviewAt??null};s[t]={...i,bodyRevision:n.bodyRevision,indexRevision:i.indexRevision+1,indexSyncState:"pending",indexSyncStateRevision:i.indexRevision+1,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:new Date().toISOString(),lastMessagePreview:o.preview,lastMessagePreviewMessageId:o.messageId,lastMessagePreviewAt:o.at,lastVisibleEventAt:L(t)},g(s)}return n.bodyRevision}function U(t,e,n){const s=d(),i=s[t];if(!i)return;const o=i.sessionScope==="steward"&&e.role==="agent"&&!q(e.payload),a=e.id.startsWith(T),r=h(e),l=o||a?null:r,f=a?r:l,v=l?{lastMessagePreview:l,lastMessagePreviewMessageId:e.id,lastMessagePreviewAt:new Date(e.ts).toISOString()}:null,A=l||D(e.payload)?new Date(e.ts).toISOString():i.lastVisibleEventAt,m=c().getManifest(t),w=e.role==="user"&&f&&!i.title?{title:E(f),titleSource:"first_user_fallback",titleRevision:i.titleRevision+1,titleLockedByUser:!1,titleOriginEventId:e.id}:null,x=e.role==="user"&&!i.localReady?{localReady:!0,firstUserMessageId:e.id,firstUserBodyRevision:n}:null;s[t]={...i,...w??{},...x??{},bodyRevision:n,indexRevision:i.indexRevision+1,indexSyncState:"pending",indexSyncStateRevision:i.indexRevision+1,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:new Date().toISOString(),lastActivityAt:new Date(e.ts).toISOString(),lastVisibleEventAt:A,...v??{},firstAvailableSeq:m?.firstAvailableSeq??i.firstAvailableSeq,visibleMessageCount:m?.visibleMessageCount??i.visibleMessageCount,lastVisibleMessageId:m?.lastVisibleMessageId??i.lastVisibleMessageId,attentionCount:i.attentionCount??0,lastAttentionId:i.lastAttentionId??null,lastBodyCommittedAt:m?.lastBodyCommittedAt??i.lastBodyCommittedAt},g(s)}function G(t){let e;do{const n=c().readPage(t,{limit:500,beforeSequence:e});for(let s=n.entries.length-1;s>=0;s-=1){const i=n.entries[s];if(i.message.id.startsWith(T))continue;const o=h(i.message);if(o)return{preview:o,messageId:i.message.id,at:new Date(i.message.ts).toISOString()}}if(!n.hasOlder||n.entries.length===0)break;e=n.entries[0].sequence}while(e!==void 0);return{preview:null,messageId:null,at:null}}function L(t){let e;do{const n=c().readPage(t,{limit:500,beforeSequence:e});for(let s=n.entries.length-1;s>=0;s-=1){const i=n.entries[s].message;if(!(!h(i)&&!D(i.payload)))return new Date(i.ts).toISOString()}if(!n.hasOlder||n.entries.length===0)break;e=n.entries[0].sequence}while(e!==void 0);return null}function K(){const t=d();let e=!1;const n=new Date().toISOString();for(const[s,i]of Object.entries(t)){if(Object.prototype.hasOwnProperty.call(i,"lastVisibleEventAt"))continue;const o=i.indexRevision+1;t[s]={...i,lastVisibleEventAt:L(s)??i.lastMessagePreviewAt??null,indexRevision:o,indexSyncState:"pending",indexSyncStateRevision:o,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:n},e=!0}e&&g(t)}function Z(){const t=d();let e=!1;const n=new Date().toISOString();for(const[s,i]of Object.entries(t)){if(Object.prototype.hasOwnProperty.call(i,"lastMessagePreviewMessageId")&&Object.prototype.hasOwnProperty.call(i,"lastMessagePreviewAt"))continue;const o=G(s);t[s]={...i,lastMessagePreview:o.preview,lastMessagePreviewMessageId:o.messageId,lastMessagePreviewAt:o.at,indexRevision:i.indexRevision+1,indexSyncState:"pending",indexSyncStateRevision:i.indexRevision+1,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:n},e=!0}e&&g(t)}function ee(t,e){const n={title:t?.title??"",titleSource:t?.titleSource??"first_user_fallback",titleRevision:t?.titleRevision??0,titleLockedByUser:t?.titleLockedByUser??!1,titleOriginEventId:t?.titleOriginEventId??null},s=E(e.title?.trim()??"");if(!s)return n;if(!e.titleSource)throw new Error("titleSource is required with title");if(n.title&&n.titleSource==="first_user_fallback"&&e.titleSource==="first_user_fallback")return n;const i=e.titleSource==="shennian_manual";if(e.titleLockedByUser!==void 0&&e.titleLockedByUser!==i)throw new Error("titleLockedByUser conflicts with titleSource");const o=s===n.title&&e.titleSource===n.titleSource,a=e.titleRevision??n.titleRevision+(o?0:1);if(!Number.isSafeInteger(a)||a<0)throw new Error("invalid titleRevision");const r=I[e.titleSource],l=I[n.titleSource];return r<l||a<n.titleRevision||o&&a===n.titleRevision||a===n.titleRevision&&!o?n:{title:s,titleSource:e.titleSource,titleRevision:a,titleLockedByUser:i,titleOriginEventId:e.titleOriginEventId??n.titleOriginEventId}}function be(t,e){const n=e?.limit&&e.limit>0?Math.min(e.limit,500):500;let i=c().readRecent(t,n).messages;return e?.before!==void 0&&(i=i.filter(o=>o.ts<e.before)),[...i].sort((o,a)=>a.ts-o.ts)}function Ee(){return c().listSessionIds()}function Pe(){return c()}function te(t,e){const n=b.dirname(t);u.mkdirSync(n,{recursive:!0,mode:448});const s=`${t}.tmp-${process.pid}-${k.randomBytes(6).toString("hex")}`;let i;try{if(i=u.openSync(s,"wx",384),u.writeFileSync(i,`${JSON.stringify(e,null,2)}
|
|
2
2
|
`,"utf8"),u.fsyncSync(i),u.closeSync(i),i=void 0,j(s,t),process.platform!=="win32"){const o=u.openSync(n,"r");try{u.fsyncSync(o)}finally{u.closeSync(o)}}}finally{i!==void 0&&u.closeSync(i);try{u.unlinkSync(s)}catch{}}}export{$ as PERSONAL_SYNC_V1_ROOT_NAME,ve as acknowledgeSessionIndexUpdate,pe as appendMessage,Ie as applyGeneratedSessionTitle,Ae as claimSessionTitleGenerationCandidates,xe as deferSessionTitleGeneration,Pe as getCanonicalSessionStore,S as getDaemonInstallationId,Re as getMessageDeliveryStatus,fe as listPendingSessionIndexUpdates,J as listSessionRecords,Ee as listSessions,me as markAllSessionIndexesForRepublish,ge as purgeCanonicalSession,Se as purgeSessionRecord,be as readMessages,z as recordSession,ye as recordSessionIndexRejection,Me as tombstoneMessage,we as upsertMessage};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e={codexHome:null,sandbox:"danger-full-access",approvalPolicy:"never",networkAccess:!1};export{e as DEFAULT_CODEX_CONVERSATION_SETTINGS};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export*from"./envelope.js";export*from"./events.js";export*from"./machine.js";export*from"./methods.js";export*from"./frames.js";export*from"./fs.js";export*from"./session.js";export*from"./session-sync.js";export*from"./message-payload.js";export*from"./external-message-format.js";export*from"./native-session.js";export*from"./tool-detail.js";export*from"./voice-chief.js";export*from"./project.js";export*from"./project-fs.js";export*from"./room.js";export*from"./agent-capabilities.js";export*from"./agent-workspace.js";export*from"./relay-connectivity.js";export*from"./project-path.js";export*from"./schedule.js";export*from"./support.js";export*from"./adapter-submission.js";
|
|
1
|
+
export*from"./envelope.js";export*from"./events.js";export*from"./machine.js";export*from"./methods.js";export*from"./frames.js";export*from"./fs.js";export*from"./session.js";export*from"./session-sync.js";export*from"./message-payload.js";export*from"./external-message-format.js";export*from"./native-session.js";export*from"./tool-detail.js";export*from"./voice-chief.js";export*from"./project.js";export*from"./project-fs.js";export*from"./room.js";export*from"./agent-capabilities.js";export*from"./agent-workspace.js";export*from"./relay-connectivity.js";export*from"./project-path.js";export*from"./schedule.js";export*from"./support.js";export*from"./adapter-submission.js";export*from"./codex-settings.js";
|