grix-connector 1.0.2

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.
Files changed (211) hide show
  1. package/README.md +149 -0
  2. package/dist/adapter/acp/acp-adapter.js +13 -0
  3. package/dist/adapter/acp/index.js +1 -0
  4. package/dist/adapter/acp/usage-parser.js +1 -0
  5. package/dist/adapter/claude/activity-status-manager.js +1 -0
  6. package/dist/adapter/claude/channel-notification.js +1 -0
  7. package/dist/adapter/claude/claude-adapter.js +15 -0
  8. package/dist/adapter/claude/claude-bridge-server.js +1 -0
  9. package/dist/adapter/claude/claude-tools.js +1 -0
  10. package/dist/adapter/claude/claude-worker-client.js +1 -0
  11. package/dist/adapter/claude/index.js +1 -0
  12. package/dist/adapter/claude/interaction-protocol.js +1 -0
  13. package/dist/adapter/claude/mcp-http-launcher.js +2 -0
  14. package/dist/adapter/claude/model-list.js +1 -0
  15. package/dist/adapter/claude/protocol-contract.js +1 -0
  16. package/dist/adapter/claude/result-timeout.js +1 -0
  17. package/dist/adapter/claude/skill-scanner.js +2 -0
  18. package/dist/adapter/claude/usage-parser.js +3 -0
  19. package/dist/adapter/codewhale/codewhale-adapter.js +6 -0
  20. package/dist/adapter/codewhale/index.js +1 -0
  21. package/dist/adapter/codex/codex-bridge.js +10 -0
  22. package/dist/adapter/codex/codex-trust.js +8 -0
  23. package/dist/adapter/codex/index.js +1 -0
  24. package/dist/adapter/codex/usage-parser.js +1 -0
  25. package/dist/adapter/cursor/cursor-adapter.js +8 -0
  26. package/dist/adapter/cursor/index.js +1 -0
  27. package/dist/adapter/deepseek/deepseek-adapter.js +6 -0
  28. package/dist/adapter/deepseek/index.js +1 -0
  29. package/dist/adapter/index.js +1 -0
  30. package/dist/adapter/opencode/index.js +1 -0
  31. package/dist/adapter/opencode/opencode-adapter.js +8 -0
  32. package/dist/adapter/opencode/opencode-transport.js +5 -0
  33. package/dist/adapter/opencode/opencode-types.js +0 -0
  34. package/dist/adapter/openhuman/index.js +1 -0
  35. package/dist/adapter/openhuman/openhuman-adapter.js +7 -0
  36. package/dist/adapter/openhuman/openhuman-transport.js +1 -0
  37. package/dist/adapter/openhuman/openhuman-types.js +0 -0
  38. package/dist/adapter/pi/index.js +1 -0
  39. package/dist/adapter/pi/pi-adapter.js +10 -0
  40. package/dist/adapter/pi/pi-transport.js +4 -0
  41. package/dist/adapter/pi/pi-types.js +0 -0
  42. package/dist/adapter/pi/usage-parser.js +1 -0
  43. package/dist/adapter/qwen/index.js +1 -0
  44. package/dist/adapter/qwen/qwen-adapter.js +4 -0
  45. package/dist/adapter/types.js +1 -0
  46. package/dist/agent/index.js +1 -0
  47. package/dist/agent/process.js +2 -0
  48. package/dist/aibot/client.js +1 -0
  49. package/dist/aibot/index.js +1 -0
  50. package/dist/aibot/types.js +0 -0
  51. package/dist/bridge/adapter-pool.js +1 -0
  52. package/dist/bridge/bridge.js +10 -0
  53. package/dist/bridge/deferred-events.js +1 -0
  54. package/dist/bridge/event-queue.js +1 -0
  55. package/dist/bridge/index.js +1 -0
  56. package/dist/bridge/respawn-manager.js +1 -0
  57. package/dist/bridge/revoke-handler.js +1 -0
  58. package/dist/bridge/runtime-config.js +1 -0
  59. package/dist/bridge/send-controller.js +1 -0
  60. package/dist/bridge/session-controller.js +9 -0
  61. package/dist/bridge/tool-card-utils.js +1 -0
  62. package/dist/core/access/allowlist-gate.js +1 -0
  63. package/dist/core/access/allowlist-store.js +1 -0
  64. package/dist/core/access/index.js +1 -0
  65. package/dist/core/aibot/client.js +1 -0
  66. package/dist/core/aibot/connection-handle.js +1 -0
  67. package/dist/core/aibot/connection-manager.js +1 -0
  68. package/dist/core/aibot/event-lifecycle-types.js +0 -0
  69. package/dist/core/aibot/index.js +1 -0
  70. package/dist/core/aibot/types.js +0 -0
  71. package/dist/core/config/index.js +1 -0
  72. package/dist/core/config/paths.js +1 -0
  73. package/dist/core/context/channel-context-resolution.js +1 -0
  74. package/dist/core/context/channel-context-store.js +1 -0
  75. package/dist/core/context/index.js +1 -0
  76. package/dist/core/context/transcript-channel-context.js +1 -0
  77. package/dist/core/file-ops/handler.js +1 -0
  78. package/dist/core/file-ops/list-files.js +1 -0
  79. package/dist/core/file-ops/types.js +0 -0
  80. package/dist/core/files/create-folder.js +1 -0
  81. package/dist/core/files/index.js +1 -0
  82. package/dist/core/files/list-files.js +1 -0
  83. package/dist/core/files/list-handler.js +1 -0
  84. package/dist/core/files/types.js +0 -0
  85. package/dist/core/files/utils.js +1 -0
  86. package/dist/core/hooks/hook-signal-store.js +2 -0
  87. package/dist/core/hooks/index.js +1 -0
  88. package/dist/core/log/bridge-event-log.js +2 -0
  89. package/dist/core/log/conversation-log.js +3 -0
  90. package/dist/core/log/index.js +1 -0
  91. package/dist/core/log/logger.js +6 -0
  92. package/dist/core/log/packet-log.js +2 -0
  93. package/dist/core/log/rotation.js +2 -0
  94. package/dist/core/mcp/event-tool-executor.js +1 -0
  95. package/dist/core/mcp/index.js +1 -0
  96. package/dist/core/mcp/internal-api-server.js +1 -0
  97. package/dist/core/mcp/tool-schemas.js +1 -0
  98. package/dist/core/mcp/tools.js +1 -0
  99. package/dist/core/persistence/active-event-store.js +1 -0
  100. package/dist/core/persistence/agent-global-config-store.js +1 -0
  101. package/dist/core/persistence/elicitation-store.js +1 -0
  102. package/dist/core/persistence/event-results-store.js +1 -0
  103. package/dist/core/persistence/permission-store.js +1 -0
  104. package/dist/core/persistence/question-store.js +1 -0
  105. package/dist/core/persistence/session-binding-store.js +1 -0
  106. package/dist/core/protocol/agent-api-media.js +1 -0
  107. package/dist/core/protocol/attachment-file.js +1 -0
  108. package/dist/core/protocol/index.js +1 -0
  109. package/dist/core/protocol/interaction-parser.js +1 -0
  110. package/dist/core/protocol/message-metadata.js +2 -0
  111. package/dist/core/protocol/message-reference.js +2 -0
  112. package/dist/core/protocol/payload-parser.js +11 -0
  113. package/dist/core/protocol/protocol-descriptor.js +1 -0
  114. package/dist/core/protocol/protocol-text.js +1 -0
  115. package/dist/core/provider-quota/index.js +1 -0
  116. package/dist/core/provider-quota/kiro.js +1 -0
  117. package/dist/core/provider-quota/providers.js +1 -0
  118. package/dist/core/provider-quota/types.js +0 -0
  119. package/dist/core/runtime/health.js +1 -0
  120. package/dist/core/runtime/index.js +1 -0
  121. package/dist/core/runtime/pidfile.js +2 -0
  122. package/dist/core/runtime/spawn.js +1 -0
  123. package/dist/core/text-segmentation/index.js +1 -0
  124. package/dist/core/text-segmentation/safe-markdown-stream-segmenter.js +6 -0
  125. package/dist/core/transport/index.js +1 -0
  126. package/dist/core/transport/json-rpc.js +3 -0
  127. package/dist/core/upgrade/npm-upgrader.js +2 -0
  128. package/dist/core/upgrade/upgrade-checker.js +1 -0
  129. package/dist/core/util/client-version.js +1 -0
  130. package/dist/core/util/codex-output-policy.js +1 -0
  131. package/dist/core/util/event-buffer.js +1 -0
  132. package/dist/core/util/index.js +1 -0
  133. package/dist/core/util/json-file.js +2 -0
  134. package/dist/core/util/normalize-string.js +1 -0
  135. package/dist/core/util/quoted-message-stream.js +3 -0
  136. package/dist/grix.js +28 -0
  137. package/dist/index.js +1 -0
  138. package/dist/log.js +3 -0
  139. package/dist/main.js +31 -0
  140. package/dist/manager.js +1 -0
  141. package/dist/mcp/acp-mcp-server.js +5 -0
  142. package/dist/mcp/stdio/server.js +10 -0
  143. package/dist/mcp/stream-http/config.js +1 -0
  144. package/dist/mcp/stream-http/connection-binding.js +1 -0
  145. package/dist/mcp/stream-http/event-tool-executor.js +1 -0
  146. package/dist/mcp/stream-http/gateway.js +1 -0
  147. package/dist/mcp/stream-http/index.js +1 -0
  148. package/dist/mcp/stream-http/security.js +1 -0
  149. package/dist/mcp/stream-http/session-manager.js +1 -0
  150. package/dist/mcp/stream-http/tool-executor.js +1 -0
  151. package/dist/mcp/stream-http/tool-registry.js +1 -0
  152. package/dist/mcp/stream-http/tool-schemas.js +1 -0
  153. package/dist/protocol/acp-client.js +1 -0
  154. package/dist/protocol/event-mapper.js +5 -0
  155. package/dist/protocol/index.js +1 -0
  156. package/dist/runtime/daemon-lock.js +2 -0
  157. package/dist/runtime/service-state.js +2 -0
  158. package/dist/scripts/approve-plan-hook.js +2 -0
  159. package/dist/scripts/elicitation-hook.js +6 -0
  160. package/dist/scripts/lib/read-stdin.js +1 -0
  161. package/dist/scripts/lifecycle-hook.js +2 -0
  162. package/dist/scripts/notification-hook.js +4 -0
  163. package/dist/scripts/permission-hook.js +5 -0
  164. package/dist/scripts/status-line-forwarder.js +2 -0
  165. package/dist/scripts/user-prompt-submit-hook.js +2 -0
  166. package/dist/service/platform-adapter.js +45 -0
  167. package/dist/service/process-control.js +1 -0
  168. package/dist/service/service-install-store.js +1 -0
  169. package/dist/service/service-manager.js +1 -0
  170. package/dist/service/service-paths.js +1 -0
  171. package/dist/session/index.js +1 -0
  172. package/dist/session/manager.js +1 -0
  173. package/dist/transport/index.js +1 -0
  174. package/dist/transport/json-rpc.js +3 -0
  175. package/dist/types/events.js +1 -0
  176. package/dist/types/index.js +1 -0
  177. package/dist/types/protocol.js +0 -0
  178. package/dist/types/session-state.js +0 -0
  179. package/dist/types/usage.js +0 -0
  180. package/openclaw-plugin/index.js +11271 -0
  181. package/openclaw-plugin/skills/grix-admin/SKILL.md +202 -0
  182. package/openclaw-plugin/skills/grix-admin/references/api-contract.md +210 -0
  183. package/openclaw-plugin/skills/grix-egg/SKILL.md +81 -0
  184. package/openclaw-plugin/skills/grix-egg/references/api-contract.md +40 -0
  185. package/openclaw-plugin/skills/grix-group/SKILL.md +164 -0
  186. package/openclaw-plugin/skills/grix-group/references/api-contract.md +97 -0
  187. package/openclaw-plugin/skills/grix-query/SKILL.md +247 -0
  188. package/openclaw-plugin/skills/grix-register/SKILL.md +86 -0
  189. package/openclaw-plugin/skills/grix-register/references/api-contract.md +76 -0
  190. package/openclaw-plugin/skills/grix-register/references/grix-concepts.md +26 -0
  191. package/openclaw-plugin/skills/grix-register/references/handoff-contract.md +24 -0
  192. package/openclaw-plugin/skills/grix-register/references/openclaw-setup.md +6 -0
  193. package/openclaw-plugin/skills/grix-register/references/user-replies.md +25 -0
  194. package/openclaw-plugin/skills/grix-register/scripts/grix_auth.ts +599 -0
  195. package/openclaw-plugin/skills/grix-update/SKILL.md +310 -0
  196. package/openclaw-plugin/skills/grix-update/references/cron-setup.md +56 -0
  197. package/openclaw-plugin/skills/grix-update/references/update-contract.md +149 -0
  198. package/openclaw-plugin/skills/message-send/SKILL.md +197 -0
  199. package/openclaw-plugin/skills/message-unsend/SKILL.md +186 -0
  200. package/openclaw-plugin/skills/message-unsend/flowchart.mermaid +27 -0
  201. package/openclaw-plugin/skills/openclaw-memory-setup/SKILL.md +282 -0
  202. package/openclaw-plugin/skills/openclaw-memory-setup/references/case-study-macpro.md +52 -0
  203. package/openclaw-plugin/skills/openclaw-memory-setup/references/host-readiness.md +147 -0
  204. package/openclaw-plugin/skills/openclaw-memory-setup/scripts/bench_ollama_embeddings.ts +326 -0
  205. package/openclaw-plugin/skills/openclaw-memory-setup/scripts/set_openclaw_memory_model.ts +385 -0
  206. package/openclaw-plugin/skills/openclaw-memory-setup/scripts/survey_host_readiness.ts +294 -0
  207. package/openclaw.plugin.json +24 -0
  208. package/package.json +114 -0
  209. package/scripts/install-guardian.mjs +30 -0
  210. package/scripts/install-guardian.sh +30 -0
  211. package/scripts/upgrade-guardian.sh +98 -0
@@ -0,0 +1 @@
1
+ function a(e){const t=new Set([`http://127.0.0.1:${e.serverPort}`,`http://localhost:${e.serverPort}`,...e.allowedOrigins]),o=new Set([`127.0.0.1:${e.serverPort}`,`localhost:${e.serverPort}`,...e.allowedHosts]);return{validateRequest(s){const r=i(s,t);if(!r.ok)return r;const n=l(s,o);return n.ok?{ok:!0}:n}}}function i(e,t){const o=e.headers.origin;return o?t.has(o)?{ok:!0}:{ok:!1,statusCode:403,message:`Origin not allowed: ${o}`}:{ok:!0}}function l(e,t){const o=e.headers.host;return o?t.has(o)?{ok:!0}:{ok:!1,statusCode:403,message:`Host not allowed: ${o}`}:{ok:!1,statusCode:403,message:"Missing Host header"}}export{a as createSecurityPolicy};
@@ -0,0 +1 @@
1
+ import{randomUUID as n}from"node:crypto";const i={initializing:0,ready:1,closing:2,closed:3},o=6e4;class a{sessions=new Map;config;scanTimer=null;constructor(s){this.config=s,this.startScanTimer()}createSession(){if(this.getActiveCount()>=this.config.maxSessions)throw new Error(`Session limit exceeded: max ${this.config.maxSessions} active sessions`);const s=Date.now(),t={sessionId:n(),createdAt:s,lastActivityAt:s,state:"initializing"};return this.sessions.set(t.sessionId,t),t}getSession(s){return this.sessions.get(s)}markReady(s){const t=this.sessions.get(s);if(!t)throw new Error(`Session not found: ${s}`);this.transitionState(t,"ready")}async closeSession(s){const t=this.sessions.get(s);if(!t)throw new Error(`Session not found: ${s}`);t.state!=="closed"&&(t.state!=="closing"&&this.transitionState(t,"closing"),this.transitionState(t,"closed"))}touchActivity(s){const t=this.sessions.get(s);t&&(t.lastActivityAt=Date.now())}getActiveCount(){let s=0;for(const t of this.sessions.values())t.state!=="closed"&&s++;return s}async closeAll(){const s=[];for(const t of this.sessions.values())t.state!=="closed"&&s.push(this.closeSession(t.sessionId));await Promise.all(s)}dispose(){this.scanTimer!==null&&(clearInterval(this.scanTimer),this.scanTimer=null)}startScanTimer(){this.scanTimer=setInterval(()=>{this.scanExpiredSessions()},o)}scanExpiredSessions(){const s=Date.now();for(const t of this.sessions.values())t.state==="closed"||t.state==="closing"||s-t.lastActivityAt>this.config.sessionTimeoutMs&&this.expireSession(t.sessionId)}async expireSession(s){await this.closeSession(s),await this.config.onSessionExpired?.(s)}transitionState(s,t){const e=i[s.state];if(i[t]<=e)throw new Error(`Invalid state transition: cannot transition from '${s.state}' to '${t}'`);s.state=t}}export{a as SessionManagerImpl};
@@ -0,0 +1 @@
1
+ import{toolCallToInvoke as i}from"../../core/mcp/tools.js";import{ToolRegistryImpl as l}from"./tool-registry.js";import{validateToolArgs as a}from"./tool-schemas.js";import{isEventTool as p,executeEventTool as d}from"./event-tool-executor.js";class y{registry;constructor(){this.registry=new l}async execute(r,e,t,n){if(!this.registry.hasTool(e))return this.errorResult(`\u672A\u77E5\u5DE5\u5177: ${e}`);const s=a(e,t);if(!s.valid)return this.errorResult(`\u53C2\u6570\u6821\u9A8C\u5931\u8D25: ${s.error}`);if(r.status!=="ready")return this.errorResult(`\u8FDE\u63A5\u4E0D\u53EF\u7528: \u5F53\u524D\u72B6\u6001\u4E3A ${r.status}`);if(p(e))return this.executeEventTool(r,e,t);const o=i(e,t);try{const u=await r.agentInvoke(o.action,o.params,n);return this.normalizeResult(u)}catch(u){const c=u instanceof Error?u.message:String(u);return c.toLowerCase().includes("timeout")?this.errorResult(`\u8C03\u7528\u8D85\u65F6: ${c}`):this.errorResult(`\u8C03\u7528\u5931\u8D25: ${c}`)}}normalizeResult(r){if(r==null||typeof r!="object")return this.successResult(r??null);const e=r,t=typeof e.code=="number"?e.code:0;if(t===0){const s="data"in e?e.data:null;return this.successResult(s??null)}const n=typeof e.msg=="string"?e.msg:"\u672A\u77E5\u9519\u8BEF";return this.errorResult(`\u4E0A\u6E38\u9519\u8BEF [code=${t}]: ${n}`)}successResult(r){return{content:[{type:"text",text:JSON.stringify(r)}],isError:!1}}errorResult(r){return{content:[{type:"text",text:r}],isError:!0}}async executeEventTool(r,e,t){return e==="grix_access_control"?this.executeAccessControl(r,t):d(r,e,t)}async executeAccessControl(r,e){const t=String(e.action??""),n={pair_approve:"pair_approve",pair_deny:"pair_deny",allow_sender:"sender_allow",remove_sender:"sender_remove",set_policy:"policy_set"}[t];if(!n)return this.errorResult(`\u672A\u77E5 access_control action: ${t}`);const s={};e.code!=null&&(s.code=e.code),e.sender_id!=null&&(s.sender_id=e.sender_id),e.policy!=null&&(s.policy=e.policy);try{const o=await r.agentInvoke("claude_access_control",{verb:n,payload:s},3e4);return this.successResult(o)}catch(o){const u=o instanceof Error?o.message:String(o);return this.errorResult(`access_control \u8C03\u7528\u5931\u8D25: ${u}`)}}}export{y as ToolExecutorImpl};
@@ -0,0 +1 @@
1
+ import{TOOLS as o,EVENT_TOOLS as s}from"../../core/mcp/tools.js";const e=new Set(["grix_query","grix_group","grix_message_send","grix_message_unsend","grix_admin"]),r=new Set(["grix_reply","grix_complete","grix_event_ack","grix_composing","grix_access_control","grix_status"]);class a{tools;toolMap;constructor(){this.tools=[...o.filter(t=>e.has(t.name)),...s.filter(t=>r.has(t.name))],this.toolMap=new Map(this.tools.map(t=>[t.name,t]))}getTools(){return this.tools}getTool(t){return this.toolMap.get(t)}hasTool(t){return this.toolMap.has(t)}}export{a as ToolRegistryImpl};
@@ -0,0 +1 @@
1
+ const o={required:["action"],properties:{action:{type:"string",enum:["contact_search","session_search","message_history","message_search"]},id:{type:"string"},keyword:{type:"string",maxLength:200},limit:{type:"integer",minimum:1,maximum:100},offset:{type:"integer",minimum:0},sessionId:{type:"string"},beforeId:{type:"string"}}},a={required:["action"],properties:{action:{type:"string",enum:["create","detail","leave","add_members","remove_members","update_member_role","update_all_members_muted","update_member_speaking","dissolve"]},sessionId:{type:"string"},name:{type:"string",maxLength:128},memberIds:{type:"array",items:{type:"string"},maxItems:100},memberTypes:{type:"array",items:{type:"integer",enum:[1,2]}},memberId:{type:"string"},role:{type:"integer",enum:[1,2]},memberType:{type:"integer"},allMembersMuted:{type:"boolean"},isSpeakMuted:{type:"boolean"},canSpeakWhenAllMuted:{type:"boolean"}}},p={required:["sessionId","content"],properties:{sessionId:{type:"string"},content:{type:"string",maxLength:1e4},msgType:{type:"integer"},quotedMessageId:{type:"string"},threadId:{type:"string"}}},m={required:["sessionId","msgId"],properties:{sessionId:{type:"string"},msgId:{type:"string"}}},g={required:["action"],properties:{action:{type:"string",enum:["create_agent","list_categories","create_category","update_category","assign_category","rotate_api_key"]},agentName:{type:"string"},introduction:{type:"string"},isMain:{type:"boolean"},agentId:{type:"string"},categoryId:{type:"string"},name:{type:"string"},parentId:{type:"string"},sortOrder:{type:"integer"}}},y={required:["session_id","text"],properties:{event_id:{type:"string"},session_id:{type:"string"},text:{type:"string",maxLength:5e4},quoted_message_id:{type:"string"},is_final:{type:"boolean"}}},d={required:["event_id","status"],properties:{event_id:{type:"string"},status:{type:"string",enum:["responded","canceled","failed"]},msg:{type:"string",maxLength:500}}},c={required:["event_id"],properties:{event_id:{type:"string"},session_id:{type:"string"}}},_={required:["session_id","active"],properties:{session_id:{type:"string"},active:{type:"boolean"},event_id:{type:"string"}}},l={required:["action"],properties:{action:{type:"string",enum:["pair_approve","pair_deny","allow_sender","remove_sender","set_policy"]},code:{type:"string"},sender_id:{type:"string"},policy:{type:"string",enum:["allowlist","open","disabled"]}}},f={required:[],properties:{}},C={grix_query:o,grix_group:a,grix_message_send:p,grix_message_unsend:m,grix_admin:g,grix_reply:y,grix_complete:d,grix_event_ack:c,grix_composing:_,grix_access_control:l,grix_status:f};function B(r,t){const e=C[r];if(!e)return{valid:!1,error:`\u672A\u77E5\u5DE5\u5177: ${r}`};for(const u of e.required)if(t[u]===void 0||t[u]===null)return{valid:!1,error:`\u7F3A\u5C11\u5FC5\u586B\u53C2\u6570: ${u}`};for(const[u,n]of Object.entries(t)){if(n==null)continue;const i=e.properties[u];if(!i)continue;const s=$(u,n,i);if(s)return{valid:!1,error:s}}return{valid:!0}}function $(r,t,e){switch(e.type){case"string":if(typeof t!="string")return`\u53C2\u6570 ${r} \u7C7B\u578B\u9519\u8BEF: \u671F\u671B string\uFF0C\u5B9E\u9645 ${typeof t}`;if(e.maxLength!==void 0&&t.length>e.maxLength)return`\u53C2\u6570 ${r} \u8D85\u8FC7\u6700\u5927\u957F\u5EA6 ${e.maxLength}\uFF0C\u5B9E\u9645 ${t.length}`;if(e.enum&&!e.enum.includes(t))return`\u53C2\u6570 ${r} \u503C "${t}" \u4E0D\u5728\u5141\u8BB8\u8303\u56F4 [${e.enum.join(", ")}]`;break;case"integer":if(typeof t!="number"||!Number.isInteger(t))return`\u53C2\u6570 ${r} \u7C7B\u578B\u9519\u8BEF: \u671F\u671B integer\uFF0C\u5B9E\u9645 ${typeof t=="number"?"\u6D6E\u70B9\u6570":typeof t}`;if(e.minimum!==void 0&&t<e.minimum)return`\u53C2\u6570 ${r} \u503C ${t} \u5C0F\u4E8E\u6700\u5C0F\u503C ${e.minimum}`;if(e.maximum!==void 0&&t>e.maximum)return`\u53C2\u6570 ${r} \u503C ${t} \u5927\u4E8E\u6700\u5927\u503C ${e.maximum}`;if(e.enum&&!e.enum.includes(t))return`\u53C2\u6570 ${r} \u503C ${t} \u4E0D\u5728\u5141\u8BB8\u8303\u56F4 [${e.enum.join(", ")}]`;break;case"boolean":if(typeof t!="boolean")return`\u53C2\u6570 ${r} \u7C7B\u578B\u9519\u8BEF: \u671F\u671B boolean\uFF0C\u5B9E\u9645 ${typeof t}`;break;case"array":if(!Array.isArray(t))return`\u53C2\u6570 ${r} \u7C7B\u578B\u9519\u8BEF: \u671F\u671B array\uFF0C\u5B9E\u9645 ${typeof t}`;if(e.maxItems!==void 0&&t.length>e.maxItems)return`\u53C2\u6570 ${r} \u8D85\u8FC7\u6700\u5927\u5143\u7D20\u6570 ${e.maxItems}\uFF0C\u5B9E\u9645 ${t.length}`;if(e.items)for(let u=0;u<t.length;u++){const n=t[u];if(e.items.type==="string"&&typeof n!="string")return`\u53C2\u6570 ${r}[${u}] \u7C7B\u578B\u9519\u8BEF: \u671F\u671B string\uFF0C\u5B9E\u9645 ${typeof n}`;if(e.items.type==="integer"){if(typeof n!="number"||!Number.isInteger(n))return`\u53C2\u6570 ${r}[${u}] \u7C7B\u578B\u9519\u8BEF: \u671F\u671B integer\uFF0C\u5B9E\u9645 ${typeof n}`;if(e.items.enum&&!e.items.enum.includes(n))return`\u53C2\u6570 ${r}[${u}] \u503C ${n} \u4E0D\u5728\u5141\u8BB8\u8303\u56F4 [${e.items.enum.join(", ")}]`}}break}}export{B as validateToolArgs};
@@ -0,0 +1 @@
1
+ import{EventEmitter as w}from"events";import{log as a}from"../core/log/index.js";import{AgentEventType as m}from"../types/events.js";import{mapSessionUpdate as M}from"./event-mapper.js";class c extends Error{authMethods;constructor(e){super("ACP authentication required"),this.name="AcpAuthRequiredError",this.authMethods=e}}function u(n){if(!n||typeof n!="object")return!1;const e=n;return e.code===-32e3?!0:e.code===-32603&&e.data?.details?/\b(401|token\s*expired|access\s*token)\b/i.test(e.data.details):!1}function h(n){return!n||typeof n!="object"?[{id:"oauth"}]:n.data?.authMethods??[{id:"oauth"}]}class S extends w{acpSessionId="";alive=!1;pendingPermissions=new Map;availableModes=[];availableModels=[];currentMode="";currentModel="";listSupported=!1;loadSupported=!1;transport;constructor(){super(),this.transport=null}get sessionId(){return this.acpSessionId}get isAlive(){return this.alive}get modes(){return[...this.availableModes]}get mode(){return this.currentMode}get models(){return[...this.availableModels]}get model(){return this.currentModel}get sessionOptions(){return{modes:[...this.availableModes],currentModeId:this.currentMode,models:[...this.availableModels],currentModelId:this.currentModel}}async connect(e){this.transport=e.transport,this.transport.on("close",()=>{this.alive&&(this.alive=!1,this.emit("session-lost"))}),this.transport.setHandlers((t,i)=>{t==="session/update"&&this.handleSessionUpdate(i)},(t,i,r)=>{t==="session/request_permission"?this.handlePermissionRequest(i,r):t.startsWith("cursor/")?this.transport.respondSuccess(i,{}).catch(()=>{}):this.transport.respondError(i,-32601,"method not implemented").catch(()=>{})});const s=await this.initialize();if(this.listSupported=!!s.agentCapabilities?.sessionCapabilities?.list,this.loadSupported=!!s.agentCapabilities?.loadSession,e.authMethod)try{await this.transport.call("authenticate",{methodId:e.authMethod})}catch(t){throw u(t)?new c(h(t)):t}if(e.sessionId&&e.sessionId!=="__continue__"){if(!this.loadSupported)throw new Error(`session/load not supported by agent, cannot resume session ${e.sessionId}`);try{if(await this.loadSession(e.sessionId,e)){this.alive=!0;return}}catch(t){throw u(t)?new c(h(t)):t}throw new Error(`session/load failed for session ${e.sessionId}`)}try{await this.newSession(e)}catch(t){throw u(t)?new c(h(t)):t}e.initialMode&&this.setLiveMode(e.initialMode).catch(()=>{}),this.alive=!0}async initialize(){return await this.transport.call("initialize",{protocolVersion:1,clientCapabilities:{fs:{readTextFile:!1,writeTextFile:!1},terminal:!1},clientInfo:{name:"grix-connector-acp",version:"0.2.0"}})}async newSession(e){const s=(e.mcpServers??[]).map(i=>{const r={name:i.name,command:i.command};return i.args&&(r.args=i.args),i.env&&Object.keys(i.env).length>0&&(r.env=Object.entries(i.env).map(([l,d])=>({name:l,value:d}))),r}),o={cwd:e.cwd||process.cwd(),mcpServers:s};e.additionalDirectories&&e.additionalDirectories.length>0&&(o.additionalDirectories=e.additionalDirectories);const t=await this.transport.call("session/new",o);if(!t?.sessionId)throw new Error("session/new returned empty sessionId");this.acpSessionId=t.sessionId,this.absorbModes(t.modes),this.absorbModels(t.models)}async loadSession(e,s){const o=(s.mcpServers??[]).map(r=>({name:r.name,command:r.command,...r.args?{args:r.args}:{},...r.env?{env:r.env}:{}})),t={sessionId:e,cwd:s.cwd||process.cwd(),mcpServers:o};s.additionalDirectories&&s.additionalDirectories.length>0&&(t.additionalDirectories=s.additionalDirectories);const i=await this.transport.call("session/load",t);return i?.sessionId?(this.acpSessionId=i.sessionId,this.absorbModes(i.modes),this.absorbModels(i.models),!0):i&&(i.modes||i.models)?(this.acpSessionId=e,this.absorbModes(i.modes),this.absorbModels(i.models),!0):!1}absorbModes(e){e?.availableModes?.length&&(this.availableModes=[...e.availableModes],e.currentModeId&&(this.currentMode=e.currentModeId))}absorbModels(e){e?.availableModels?.length&&(this.availableModels=[...e.availableModels],e.currentModelId&&(this.currentModel=e.currentModelId))}async send(e,s,o){if(!this.alive)throw new Error("session not active");if(!this.acpSessionId)throw new Error("no agent session id");const t=[{type:"text",text:e}];if(s)for(const i of s)t.push({type:"image",data:i.data.toString("base64"),mimeType:i.mimeType});await this.transport.call("session/prompt",{sessionId:this.acpSessionId,prompt:t,...this.currentModel?{modelId:this.currentModel}:{}}),this.emit("event",{type:m.Result,sessionId:this.acpSessionId,done:!0})}async cancel(){if(this.acpSessionId)try{await this.transport.notify("session/cancel",{sessionId:this.acpSessionId})}catch{}}async authenticate(e){await this.transport.call("authenticate",{methodId:e})}async respondPermission(e,s){const o=this.pendingPermissions.get(e);if(!o)throw new Error(`unknown permission request: ${e}`);this.pendingPermissions.delete(e);const t=this.pickPermissionOptionId(s.behavior,o.options),i=this.buildPermissionResult(s.behavior,t);await this.transport.respondSuccess(o.rpcId,i)}async ping(e=1e4){if(!this.alive)return!1;try{const s=new AbortController,o=setTimeout(()=>s.abort(),e);return await this.transport.call("session/list",{},s.signal),clearTimeout(o),!0}catch(s){return s?.code===-32601}}async setLiveMode(e){if(!this.acpSessionId)return a.warn("acp-client",`setLiveMode("${e}") skipped: no active session`),!1;const s=this.matchAvailableMode(e);if(!s)return a.warn("acp-client",`setLiveMode("${e}") failed: mode not found in available [${this.availableModes.map(o=>o.id).join(",")}]`),!1;try{const o=new AbortController,t=setTimeout(()=>o.abort(),8e3);return await this.transport.call("session/set_mode",{sessionId:this.acpSessionId,modeId:s},o.signal),clearTimeout(t),this.currentMode=s,!0}catch(o){return a.warn("acp-client",`setLiveMode("${s}") RPC failed: ${o instanceof Error?o.message:o}`),!1}}async setModel(e){if(!this.acpSessionId)return a.warn("acp-client",`setModel("${e}") skipped: no active session`),!1;try{const s=new AbortController,o=setTimeout(()=>s.abort(),8e3);return await this.transport.call("session/set_model",{sessionId:this.acpSessionId,modelId:e},s.signal),clearTimeout(o),this.currentModel=e,!0}catch(s){return a.warn("acp-client",`setModel("${e}") RPC failed: ${s instanceof Error?s.message:s}`),!1}}handleSessionUpdate(e){const s=M(this.acpSessionId,e);for(const o of s)o.sessionId||(o.sessionId=this.acpSessionId),this.emit("event",o)}handlePermissionRequest(e,s){const o=s,t=o?.toolCall??{},i=String(e),r=Array.isArray(o?.options)?o.options:[];this.pendingPermissions.set(i,{rpcId:e,options:r});const l=t.title||t.kind||"permission",d=t.toolCallId||i,p=t.title||"",f={type:m.PermissionRequest,requestId:i,toolName:l,toolInput:p||d,sessionId:this.acpSessionId,permissionRequest:{requestId:i,toolCallId:d,toolName:l,toolTitle:p,options:r,rawParams:s}};this.emit("event",f)}matchAvailableMode(e){const s=e.toLowerCase();for(const o of this.availableModes)if(o.id.toLowerCase()===s||o.name.toLowerCase()===s)return o.id;return""}pickPermissionOptionId(e,s){if(s.length===0)return"";if(e==="deny"){for(const t of s)if(t.kind==="reject_once"||t.kind==="reject_always")return t.optionId;for(const t of s)if(t.kind.toLowerCase().includes("reject")||t.kind.toLowerCase().includes("deny"))return t.optionId;for(const t of s)if(t.name.toLowerCase().includes("reject")||t.name.toLowerCase().includes("deny"))return t.optionId;return s[s.length-1].optionId}const o=e==="allow-always"?"allow_always":e==="allow-once"?"allow_once":null;if(o){for(const t of s)if(t.kind===o)return t.optionId}for(const t of s)if(t.kind.toLowerCase().includes("allow"))return t.optionId;for(const t of s)if(t.name.toLowerCase().includes("allow"))return t.optionId;return s[0].optionId}buildPermissionResult(e,s){return e==="deny"?s?{outcome:{outcome:"selected",optionId:s}}:{outcome:{outcome:"cancelled"}}:s?{outcome:{outcome:"selected",optionId:s}}:{outcome:{outcome:"cancelled"}}}}export{c as AcpAuthRequiredError,S as AcpClient,u as isAuthRequiredError};
@@ -0,0 +1,5 @@
1
+ import{AgentEventType as i}from"../types/events.js";function y(r,t){if(!t||typeof t!="object")return[];const n=t,e=n.update;if(!e||typeof e!="object")return[];const o=e.sessionUpdate,s=n.sessionId||r;switch(o){case"agent_message_chunk":return l(s,e);case"tool_call":return u(s,e);case"tool_call_update":return a(s,e);case"plan":return f(s,e);case"user_message_chunk":return[];default:return p(s,o,e)}}function l(r,t){const n=t?.content?.text;return n?[{type:i.Text,content:n,sessionId:r}]:[]}function u(r,t){const n=t?.title||t?.kind||"tool",e=m(t?.kind,t?.rawInput)||n;return[{type:i.ToolUse,toolName:n,toolInput:e,sessionId:r}]}function a(r,t){const n=t?.title||t?.toolCallId||"tool",e=d(t?.content),o=(t?.status??"").toLowerCase().trim();return o==="completed"||o==="failed"?o==="completed"&&!e?[]:[{type:i.ToolResult,toolName:n,content:o==="failed"&&!e?"(failed)":c(e,800),sessionId:r}]:e?[{type:i.ToolResult,toolName:n,content:c(e,800),sessionId:r}]:[]}function f(r,t){const n=t?.entries;if(!Array.isArray(n)||n.length===0)return[];const e=n.map(o=>{const s=o.content??"";return o.status?`[${o.status}] ${s}`:s}).join(`
2
+ `);return[{type:i.Thinking,content:e,sessionId:r}]}function p(r,t,n){const e=(t??"").toLowerCase();if(e==="reasoning"||e==="reasoning_chunk"||e==="thinking"||e==="agent_thinking_chunk"){const o=n?.content?.text||n?.text;return o?[{type:i.Thinking,content:o,sessionId:r}]:[]}return[]}function d(r){return Array.isArray(r)?r.map(t=>t?.content?.text??"").filter(Boolean).join(`
3
+ `):""}function m(r,t){if(!t||typeof t!="object")return"";const n=t;if(Object.keys(n).length===0)return"";const e=(r??"").toLowerCase();if(["bash","shell","terminal","execute"].includes(e)){const o=n.command,s=n.description;if(typeof o=="string")return typeof s=="string"&&s?`# ${s}
4
+ ${o}`:o}if(["read","write","edit"].includes(e))return n.file_path??n.path??"";if(typeof n.command=="string"){const o=n.description;return typeof o=="string"&&o?`# ${o}
5
+ ${n.command}`:n.command}return JSON.stringify(n,null,2)}function c(r,t){return t<=0||r.length<=t?r:r.slice(0,t)+"..."}export{y as mapSessionUpdate,m as summarizeToolInput};
@@ -0,0 +1 @@
1
+ import{AcpClient as p}from"./acp-client.js";import{mapSessionUpdate as t}from"./event-mapper.js";export{p as AcpClient,t as mapSessionUpdate};
@@ -0,0 +1,2 @@
1
+ import{openSync as w,closeSync as S,existsSync as D,readFileSync as f,unlinkSync as s,writeSync as k}from"node:fs";import{mkdir as h}from"node:fs/promises";import d from"node:path";import o from"node:process";import{isProcessRunning as i}from"../service/process-control.js";function l(r){try{const n=JSON.parse(r);if(typeof n?.pid=="number"&&typeof n.acquired_at=="number")return n}catch{}return null}function p(r){if(!D(r))return null;try{return l(f(r,"utf8"))}catch{return null}}function $(r){const n=p(r);return n!==null&&i(n.pid)}function y(r){const n=new Int32Array(new SharedArrayBuffer(4));Atomics.wait(n,0,0,r)}function x(r){if(r<=0||r===o.pid)return!0;try{o.kill(r,"SIGTERM")}catch{return!0}const n=Date.now()+3e3;for(;Date.now()<n;){if(!i(r))return!0;y(100)}try{o.kill(r,"SIGKILL")}catch{}const c=Date.now()+1e3;for(;Date.now()<c;){if(!i(r))return!0;y(50)}return!i(r)}async function b(r,n,c=2){await h(d.dirname(r),{recursive:!0});const a={pid:o.pid,acquired_at:Date.now(),root_dir:d.resolve(n)},m=`${JSON.stringify(a,null,2)}
2
+ `;for(let u=0;u<=c;u+=1)try{const e=w(r,"wx");try{k(e,m)}finally{S(e)}return a}catch(e){if(!(e instanceof Error)||e.code!=="EEXIST")throw e;const t=l(f(r,"utf8"));if(t&&i(t.pid)){if(t.pid===o.pid)throw new Error(`daemon already running (pid ${t.pid}, acquired at ${new Date(t.acquired_at).toISOString()})`);if(!x(t.pid))throw new Error(`\u65E0\u6CD5\u7EC8\u6B62\u8001\u8FDB\u7A0B (pid ${t.pid})\uFF0C\u8BF7\u624B\u52A8\u5904\u7406`)}try{s(r)}catch{}}throw new Error("failed to acquire daemon lock after retries")}async function A(r){const n=p(r);if(n&&n.pid===o.pid)try{s(r)}catch{}}export{b as acquireDaemonLock,$ as isDaemonLocked,p as readDaemonLock,A as releaseDaemonLock};
@@ -0,0 +1,2 @@
1
+ import{rename as r,rm as i,writeFile as a}from"node:fs/promises";import{existsSync as o,readFileSync as s}from"node:fs";import{randomBytes as p}from"node:crypto";import{isProcessRunning as u}from"../service/process-control.js";async function S(n,t){const e=`${n}.${p(4).toString("hex")}.tmp`;await a(e,`${JSON.stringify({...t,updated_at:Date.now()},null,2)}
2
+ `,"utf8"),await r(e,n)}function c(n){if(!o(n))return null;try{return JSON.parse(s(n,"utf8"))}catch{return null}}async function g(n){await i(n,{force:!0})}function y(n){const t=c(n);if(!t)return{running:!1,state:"stopped",pid:0};const e=t.pid>0&&u(t.pid);return{running:e&&(t.state==="running"||t.state==="starting"),state:e?t.state:"stopped",pid:t.pid,connection_state:t.connection_state,updated_at:t.updated_at}}export{y as inspectDaemonState,c as readDaemonStatus,g as removeDaemonStatus,S as writeDaemonStatus};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{readStdinJSON as o}from"./lib/read-stdin.js";async function i(){await o(2e3),process.stdout.write(JSON.stringify({hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",permissionDecisionReason:"ExitPlanMode auto-approved by grix-connector"}})),process.exit(0)}i().catch(()=>process.exit(0));
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import{HookSignalStore as f}from"../core/hooks/hook-signal-store.js";import{ChannelContextStore as g}from"../core/context/channel-context-store.js";import{resolveHookChannelContext as w}from"../core/context/channel-context-resolution.js";import{resolveRuntimePaths as _}from"../core/config/paths.js";import{resolveLogRotationOptions as h}from"../core/log/rotation.js";import{ElicitationStore as I}from"../core/persistence/elicitation-store.js";import{readStdinJSON as k}from"./lib/read-stdin.js";function e(t,n){const r={hookSpecificOutput:{hookEventName:"Elicitation",action:t,content:n}};process.stdout.write(JSON.stringify(r)+`
3
+ `)}const v=1e3,x=600*1e3;async function O(){const t=await k();if(t.hook_event_name!=="Elicitation"){process.stdout.write(`{}
4
+ `);return}const n=_(),r=h(),m=process.env.GRIX_HOOK_SIGNALS_PATH||n.hookSignalsPath;await new f(m,n.hookSignalsLogPath,void 0,r).recordHookEvent(t);const s=String(t.mode??"");if(s!=="form"&&s!=="url"){process.stdout.write(`{}
5
+ `);return}if(s==="form"&&!t.requested_schema){e("cancel");return}if(s==="url"&&!t.url){e("cancel");return}const l=String(t.session_id??""),d=String(t.agent_id??""),u=new g(n.contextsDir);await u.init();const a=await w({sessionContextStore:u,sessionID:l,agentID:d||void 0,transcriptPath:String(t.transcript_path??""),workingDir:String(t.cwd??process.cwd()),maxAgeMs:1800*1e3});if(a.status!=="resolved"||!a.context){process.stderr.write(`elicitation-hook: no channel context for session ${l}
6
+ `),e("cancel");return}const c=`elicit-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,i=new I(n.elicitationRequestsDir);await i.init(),await i.createRequest({request_id:c,status:"pending",fields:{mcp_server_name:String(t.mcp_server_name??""),message:String(t.message??""),mode:s,url:String(t.url??""),requested_schema:t.requested_schema??{}},channel_context:a.context});const p=Date.now()+x;for(;Date.now()<p;){await new Promise(S=>setTimeout(S,v));const o=await i.getRequest(c);if(!o||o.status==="expired"){e("cancel");return}if(o.status==="resolved"){o.response_action==="cancel"||!o.response_content?e("cancel"):e("accept",o.response_content);return}}await i.markExpired(c),e("cancel")}O().catch(()=>{e("cancel")});
@@ -0,0 +1 @@
1
+ async function i(e){return new Promise(r=>{let n="";const t=e?setTimeout(()=>{process.stdin.destroy(),r({})},e):null;process.stdin.setEncoding("utf8"),process.stdin.on("data",s=>{if(n+=s,t)try{const c=JSON.parse(n);clearTimeout(t),r(c);return}catch{}}),process.stdin.on("end",()=>{t&&clearTimeout(t);try{r(JSON.parse(n))}catch{r({})}}),process.stdin.on("error",()=>{t&&clearTimeout(t),r({})})})}export{i as readStdinJSON};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{HookSignalStore as i}from"../core/hooks/hook-signal-store.js";import{resolveRuntimePaths as a}from"../core/config/paths.js";import{resolveLogRotationOptions as r}from"../core/log/rotation.js";import{readStdinJSON as c}from"./lib/read-stdin.js";const m=new Set(["SessionStart","PermissionRequest","PreToolUse","PostToolUse","PostToolUseFailure","PermissionDenied","ElicitationResult","Stop","StopFailure","PreCompact","PostCompact","ConfigChange"]);async function S(){const o=await c(2e3),e=String(o.hook_event_name??"");m.has(e)||process.exit(0);const t=a(),n=r(),s=process.env.GRIX_HOOK_SIGNALS_PATH||t.hookSignalsPath;await new i(s,t.hookSignalsLogPath,void 0,n).recordHookEvent(o)}S().catch(()=>process.exit(0));
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import{HookSignalStore as r}from"../core/hooks/hook-signal-store.js";import{resolveRuntimePaths as e}from"../core/config/paths.js";import{resolveLogRotationOptions as i}from"../core/log/rotation.js";import{readStdinJSON as a}from"./lib/read-stdin.js";async function c(){const t=await a(),o=e(),n=i(),s=process.env.GRIX_HOOK_SIGNALS_PATH||o.hookSignalsPath;await new r(s,o.hookSignalsLogPath,void 0,n).recordHookEvent(t),process.stdout.write(`{}
3
+ `)}c().catch(()=>process.stdout.write(`{}
4
+ `));
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import{HookSignalStore as S}from"../core/hooks/hook-signal-store.js";import{resolveRuntimePaths as g}from"../core/config/paths.js";import{resolveLogRotationOptions as y}from"../core/log/rotation.js";import{PermissionStore as v}from"../core/persistence/permission-store.js";import{QuestionStore as k}from"../core/persistence/question-store.js";import{readStdinJSON as A}from"./lib/read-stdin.js";const h=1e3,q=300*1e3;function p(t){const e={hookSpecificOutput:{hookEventName:"PermissionRequest",permissionDecision:t}};process.stdout.write(JSON.stringify(e)+`
3
+ `)}function O(t){const e={hookSpecificOutput:{hookEventName:"PermissionRequest",decision:{behavior:"allow",updatedInput:t}}};process.stdout.write(JSON.stringify(e)+`
4
+ `)}function _(t){if(t&&typeof t=="object"&&!Array.isArray(t))return t;if(typeof t=="string")try{const e=JSON.parse(t);if(e&&typeof e=="object"&&!Array.isArray(e))return e}catch{return{}}return{}}function R(t,e,o){if(e&&String(e.type??"")==="map"){const d=Array.isArray(e.entries)?e.entries:[],n={};for(const i of d){if(!i||typeof i!="object")continue;const l=i,w=String(l.key??"").trim(),f=String(l.value??"").trim();w&&f&&(n[w]=f)}if(Object.keys(n).length>0)return{...t,answers:n}}const s=(e&&String(e.type??"")==="text"?String(e.value??"").trim():o.trim())||o.trim(),r=Array.isArray(t.questions)?t.questions:[],u={},a=r[0],m=a&&typeof a=="object"?String(a.question??a.header??"question"):"question";return u[m]=s,{...t,answers:u}}async function D(t){const e=g(),o=_(t.tool_input),c=`question-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,s=new k(e.questionRequestsDir),r=Array.isArray(o.questions)?o.questions:[];await s.writeRequest({request_id:c,questions:r,created_at:Date.now(),session_id:String(t.session_id??"").trim(),event_id:String(t.event_id??"").trim()});const u=y(),a=process.env.GRIX_HOOK_SIGNALS_PATH||e.hookSignalsPath;await new S(a,e.hookSignalsLogPath,void 0,u).recordHookEvent(t);const d=Date.now()+q;for(;Date.now()<d;){await new Promise(i=>setTimeout(i,h));const n=await s.getRequest(c);if(n?.resolved){n.resolution==="answer"&&(typeof n.answer=="string"||n.resolution_payload)?O(R(o,n.resolution_payload,String(n.answer??"").trim())):p("deny"),await s.cleanResolved();return}}await s.resolveRequest(c,"cancel"),p("deny")}async function P(){const t=await A(2e3);if(t.hook_event_name!=="PermissionRequest"){process.stdout.write(`{}
5
+ `);return}const e=String(t.tool_name??"");if(e==="AskUserQuestion"){await D(t);return}const o=g(),c=_(t.tool_input),s=`perm-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,r=new v(o.permissionRequestsDir);await r.writeRequest({request_id:s,tool_name:e,tool_input:JSON.stringify(c),created_at:Date.now()});const u=y(),a=process.env.GRIX_HOOK_SIGNALS_PATH||o.hookSignalsPath;await new S(a,o.hookSignalsLogPath,void 0,u).recordHookEvent(t);const d=Date.now()+q;for(;Date.now()<d;){await new Promise(l=>setTimeout(l,h));const i=(await r.listPending()).find(l=>l.request_id===s);if(!i||i.resolved){p(i?.resolution==="allow"?"allow":"deny"),await r.cleanResolved();return}}await r.resolveRequest(s,"deny"),p("deny")}P().catch(()=>{p("deny")});
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{readStdinJSON as p}from"./lib/read-stdin.js";async function u(){const c=process.env.GRIX_CLAUDE_INTERNAL_API_URL,i=process.env.GRIX_CLAUDE_INTERNAL_API_TOKEN;(!c||!i)&&process.exit(0);const o=await p(2e3);try{const t=new AbortController,d=setTimeout(()=>t.abort(),2e3);await fetch(`${c}/api/status-line?token=${i}`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(o),signal:t.signal}),clearTimeout(d)}catch{}const r=o.context_window,a=o.cost,l=o.model,n=r?.used_percentage,s=a?.total_cost_usd,e=l?.id;if(n!=null||s!=null||e){const t=[];n!=null&&t.push(`ctx: ${n}%`),s!=null&&t.push(`$${Number(s).toFixed(2)}`),e&&t.push(String(e)),process.stdout.write(t.join(" | "))}}u().catch(()=>process.exit(0));
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{HookSignalStore as p}from"../core/hooks/hook-signal-store.js";import{ChannelContextStore as m}from"../core/context/channel-context-store.js";import{extractLatestGrixChannelTag as d,extractChannelContextFromJson as S}from"../core/context/transcript-channel-context.js";import{resolveRuntimePaths as g}from"../core/config/paths.js";import{resolveLogRotationOptions as h}from"../core/log/rotation.js";import{readStdinJSON as x}from"./lib/read-stdin.js";async function f(){const t=await x();t.hook_event_name!=="UserPromptSubmit"&&process.exit(0);const o=g(),r=h(),a=process.env.GRIX_HOOK_SIGNALS_PATH||o.hookSignalsPath;await new p(a,o.hookSignalsLogPath,void 0,r).recordHookEvent(t);const n=String(t.prompt??""),e=d(n)??S(n);e?.chat_id||process.exit(0);const i=String(t.session_id??""),c=String(t.agent_id??"");i||process.exit(0);const s=new m(o.contextsDir);await s.init(),await s.put({session_id:i,agent_id:c||void 0,cwd:String(t.cwd??process.cwd()),context:e})}f().catch(()=>process.exit(0));
@@ -0,0 +1,45 @@
1
+ import{mkdir as f,readdir as b,readFile as y,rm as g,stat as L,writeFile as $}from"node:fs/promises";import m from"node:os";import l from"node:path";import{runCommand as u}from"./process-control.js";import{getServicePrefix as k,parseConfigDirFromPlistXML as N,parseConfigDirFromSystemdUnit as D,resolveLinuxUserUnitPath as T,resolveMacOSLaunchAgentPath as A}from"./service-paths.js";function p(t){return String(t??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function E(t){return`'${String(t??"").replace(/'/g,"'\\''")}'`}function v(t){return[t.nodePath,t.cliPath,...t.configDir?["--config-dir",t.configDir]:[]]}function W(t){const e=v(t);return`<?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>Label</key>
6
+ <string>${p(t.serviceID)}</string>
7
+ <key>ProgramArguments</key>
8
+ <array>
9
+ ${e.map(r=>` <string>${p(r)}</string>`).join(`
10
+ `)}
11
+ </array>
12
+ <key>RunAtLoad</key>
13
+ <true/>
14
+ <key>KeepAlive</key>
15
+ <true/>
16
+ <key>WorkingDirectory</key>
17
+ <string>${p(l.dirname(t.cliPath))}</string>
18
+ ${t.environmentPath?` <key>EnvironmentVariables</key>
19
+ <dict>
20
+ <key>PATH</key>
21
+ <string>${p(t.environmentPath)}</string>
22
+ </dict>
23
+ `:""} <key>StandardOutPath</key>
24
+ <string>${p(t.stdoutPath)}</string>
25
+ <key>StandardErrorPath</key>
26
+ <string>${p(t.stderrPath)}</string>
27
+ </dict>
28
+ </plist>
29
+ `}function R(t){const e=v(t).map(r=>E(r)).join(" ");return`[Unit]
30
+ Description=grix-connector daemon (${t.serviceID})
31
+ After=network.target
32
+
33
+ [Service]
34
+ Type=simple
35
+ ExecStart=${e}
36
+ WorkingDirectory=${l.dirname(t.cliPath)}
37
+ Restart=always
38
+ RestartSec=2
39
+ StandardOutput=append:${t.stdoutPath}
40
+ StandardError=append:${t.stderrPath}
41
+
42
+ [Install]
43
+ WantedBy=default.target
44
+ `}function C(t,e){const r=t.replace(/[^a-zA-Z0-9._-]/g,"_");return l.join(e,".grix",`${r}-wrapper.vbs`)}function w(t){return String(t??"").replace(/"/g,'""')}function O(t){const e=[`"${w(t.nodePath)}"`,`"${w(t.cliPath)}"`,...t.configDir?["--config-dir",`"${w(t.configDir)}"`]:[]].join(" ");return["Option Explicit","Dim shell, command, delayMs, rapidCount",`command = "${w(e)}"`,'Set shell = CreateObject("WScript.Shell")',"delayMs = 5000","rapidCount = 0","Do"," shell.Run command, 0, True"," rapidCount = rapidCount + 1"," If rapidCount >= 10 Then"," WScript.Sleep 300000"," rapidCount = 0"," Else"," WScript.Sleep delayMs"," End If","Loop",""].join(`\r
45
+ `)}function h(t){return`gui/${t??0}`}function S(t){const e=String(t?.stdout??"").trim();return String(t?.stderr??"").trim()||e||`exit=${Number(t?.exitCode??-1)}`}function x(t,e){if(Number(t?.exitCode??0)!==0)throw new Error(`${e}: ${S(t)}`)}function j(){return{platform:"darwin",kind:"launchd",async install({serviceID:t,nodePath:e,cliPath:r,configDir:i,stdoutPath:n,stderrPath:a,environmentPath:s="",homeDir:c=m.homedir()}){const o=A(t,c);return await f(l.dirname(o),{recursive:!0}),await $(o,W({serviceID:t,nodePath:e,cliPath:r,configDir:i,stdoutPath:n,stderrPath:a,environmentPath:s}),{encoding:"utf8",mode:384}),{definitionPath:o}},async start({serviceID:t,definitionPath:e,runCommand:r=u,uid:i=process.getuid?.()??0}){const n=h(i),a=await r("launchctl",["bootstrap",n,e],{allowFailure:!0}),s=await r("launchctl",["kickstart","-k",`${n}/${t}`],{allowFailure:!0});if(Number(s?.exitCode??0)!==0){const c=Number(a?.exitCode??0)===0?"":`, bootstrap=${S(a)}`;throw new Error(`launchctl start failed for ${n}/${t}: ${S(s)}${c}`)}},async stop({serviceID:t,runCommand:e=u,uid:r=process.getuid?.()??0}){const i=h(r);await e("launchctl",["bootout",`${i}/${t}`],{allowFailure:!0})},async restart({serviceID:t,definitionPath:e,runCommand:r=u,uid:i=process.getuid?.()??0}){const n=h(i);await r("launchctl",["bootout",`${n}/${t}`],{allowFailure:!0});for(let c=0;c<20&&(await r("launchctl",["print",`${n}/${t}`],{allowFailure:!0})).exitCode===0;c+=1)await new Promise(d=>setTimeout(d,250));try{await L(e)}catch{throw new Error(`launchd plist missing: ${e}`)}const a=await r("launchctl",["bootstrap",n,e],{allowFailure:!0});x(a,`launchctl bootstrap ${n}`);const s=await r("launchctl",["kickstart","-k",`${n}/${t}`],{allowFailure:!0});x(s,`launchctl kickstart ${n}/${t}`)},async uninstall({serviceID:t,definitionPath:e,runCommand:r=u,uid:i=process.getuid?.()??0}){const n=h(i);await r("launchctl",["bootout",`${n}/${t}`],{allowFailure:!0}),await g(e,{force:!0})},async discoverServices({homeDir:t=m.homedir()}={}){const e=l.join(t,"Library","LaunchAgents"),r=await b(e).catch(()=>[]),i=k("darwin"),n=[];for(const a of r){if(!a.startsWith(i)||!a.endsWith(".plist"))continue;const s=a.slice(0,-6),c=l.join(e,a);let o=null;try{const d=await y(c,"utf8");o=N(d)}catch{}n.push({serviceID:s,definitionPath:c,configDir:o})}return n},async isServiceLoaded({serviceID:t,runCommand:e=u,uid:r=process.getuid?.()??0}){const i=h(r),n=await e("launchctl",["print",`${i}/${t}`],{allowFailure:!0});return Number(n?.exitCode??1)===0}}}function M(){return{platform:"win32",kind:"task-scheduler",async install({serviceID:t,nodePath:e,cliPath:r,configDir:i,runCommand:n=u,homeDir:a=m.homedir()}){const s=C(t,a);return await f(l.dirname(s),{recursive:!0}),await $(s,O({nodePath:e,cliPath:r,configDir:i}),"utf8"),await n("schtasks",["/Create","/TN",t,"/SC","ONLOGON","/RL","LIMITED","/F","/TR",`wscript.exe //B //NoLogo "${s}"`]),{definitionPath:`task:${t}`}},async start({serviceID:t,runCommand:e=u}){await e("schtasks",["/Run","/TN",t])},async stop({serviceID:t,runCommand:e=u}){await e("schtasks",["/End","/TN",t],{allowFailure:!0})},async restart({serviceID:t,runCommand:e=u}){await e("schtasks",["/End","/TN",t],{allowFailure:!0}),await e("schtasks",["/Run","/TN",t])},async uninstall({serviceID:t,runCommand:e=u,homeDir:r=m.homedir()}){await e("schtasks",["/Delete","/TN",t,"/F"],{allowFailure:!0});const i=C(t,r);await g(i,{force:!0})},async discoverServices({homeDir:t=m.homedir(),runCommand:e=u}={}){const r=k("win32"),i=await e("schtasks",["/Query","/FO","CSV","/NH"],{allowFailure:!0});if(Number(i?.exitCode??-1)!==0)return[];const n=String(i.stdout??"").split(/\r?\n/),a=[];for(const s of n){const c=s.match(/^"([^"]+)"/);if(!c)continue;const o=c[1];if(!o.startsWith(r))continue;let d=null;try{const F=C(o,t),P=(await y(F,"utf8")).match(/--config-dir\s+""([^""]+)""/);P&&(d=P[1])}catch{}a.push({serviceID:o,definitionPath:`task:${o}`,configDir:d})}return a},async isServiceLoaded({serviceID:t,runCommand:e=u}){const r=await e("schtasks",["/Query","/TN",t,"/NH"],{allowFailure:!0});return Number(r?.exitCode??1)===0}}}function U(){return{platform:"linux",kind:"systemd-user",async install({serviceID:t,nodePath:e,cliPath:r,configDir:i,stdoutPath:n,stderrPath:a,homeDir:s=m.homedir(),runCommand:c=u}){const o=T(t,s);return await f(l.dirname(o),{recursive:!0}),await $(o,R({serviceID:t,nodePath:e,cliPath:r,configDir:i,stdoutPath:n,stderrPath:a}),{encoding:"utf8",mode:384}),await c("systemctl",["--user","daemon-reload"]),await c("systemctl",["--user","enable",`${t}.service`]),{definitionPath:o}},async start({serviceID:t,runCommand:e=u}){await e("systemctl",["--user","start",`${t}.service`])},async stop({serviceID:t,runCommand:e=u}){await e("systemctl",["--user","stop",`${t}.service`],{allowFailure:!0})},async restart({serviceID:t,runCommand:e=u}){await e("systemctl",["--user","restart",`${t}.service`])},async uninstall({serviceID:t,definitionPath:e,runCommand:r=u}){await r("systemctl",["--user","stop",`${t}.service`],{allowFailure:!0}),await r("systemctl",["--user","disable",`${t}.service`],{allowFailure:!0}),await g(e,{force:!0}),await r("systemctl",["--user","daemon-reload"])},async discoverServices({homeDir:t=m.homedir()}={}){const e=l.join(t,".config","systemd","user"),r=await b(e).catch(()=>[]),i=k("linux"),n=[];for(const a of r){if(!a.startsWith(i)||!a.endsWith(".service"))continue;const s=a.slice(0,-8),c=l.join(e,a);let o=null;try{const d=await y(c,"utf8");o=D(d)}catch{}n.push({serviceID:s,definitionPath:c,configDir:o})}return n},async isServiceLoaded({serviceID:t,runCommand:e=u}){const r=await e("systemctl",["--user","is-active",`${t}.service`],{allowFailure:!0});return String(r?.stdout??"").trim()==="active"}}}function q(t=process.platform){return t==="darwin"?j():t==="win32"?M():U()}export{q as getPlatformServiceAdapter};
@@ -0,0 +1 @@
1
+ import{spawn as k}from"node:child_process";import i from"node:process";import{setTimeout as x}from"node:timers/promises";function C(t,r,n={}){const{cwd:o,env:u=i.env,allowFailure:p=!1}=n;return new Promise((h,c)=>{const e=k(t,r,{cwd:o||void 0,env:u,stdio:["ignore","pipe","pipe"],windowsHide:!0}),f=[],l=[];e.stdout&&e.stdout.on("data",s=>f.push(s)),e.stderr&&e.stderr.on("data",s=>l.push(s)),e.on("error",c),e.on("close",s=>{const a=s??0,d=Buffer.concat(f).toString("utf8"),m=Buffer.concat(l).toString("utf8");if(a!==0&&!p){const E=m.trim()||d.trim()||`${t} exited with code ${a}`;c(new Error(E));return}h({exitCode:a,stdout:d,stderr:m})})})}function w(t){if(t<=0)return!1;try{return i.kill(t,0),!0}catch(r){if(r instanceof Error&&"code"in r){if(r.code==="ESRCH")return!1;if(r.code==="EPERM")return!0}return!1}}async function y(t,r={}){const{platform:n=i.platform,runCommandImpl:o=C}=r;if(t<=0)return!1;if(n==="win32")return await o("taskkill",["/PID",String(t),"/T","/F"],{allowFailure:!0}),!0;try{return i.kill(-t,"SIGTERM"),!0}catch{}try{return i.kill(t,"SIGTERM"),!0}catch{return!1}}async function M(t,r={}){const{timeoutMs:n=5e3,intervalMs:o=100}=r;if(t<=0)return!0;const u=Date.now()+n;for(;Date.now()<=u;){if(!w(t))return!0;await x(o)}return!w(t)}export{w as isProcessRunning,C as runCommand,y as terminateProcessTree,M as waitForProcessExit};
@@ -0,0 +1 @@
1
+ import o from"node:path";import{mkdir as c,rm as l}from"node:fs/promises";import{readJSONFile as n,writeJSONFileAtomic as s}from"../core/util/json-file.js";function r(t){return String(t??"").trim()}function a(t={}){return{schema_version:1,platform:r(t.platform),service_id:r(t.service_id),node_path:r(t.node_path),cli_path:r(t.cli_path),cli_hash:r(t.cli_hash),definition_path:r(t.definition_path),config_dir:r(t.config_dir),installed_at:Number(t.installed_at??0),updated_at:Number(t.updated_at??0)}}class m{filePath;constructor(e){this.filePath=e}async load(){const e=n(this.filePath);return!e||typeof e!="object"?null:a(e)}async save(e){const i=a(e);return await c(o.dirname(this.filePath),{recursive:!0}),await s(this.filePath,i),i}async clear(){await l(this.filePath,{force:!0})}}export{m as ServiceInstallStore};
@@ -0,0 +1 @@
1
+ import{createHash as P}from"node:crypto";import w from"node:fs";import _ from"node:os";import p from"node:path";import c from"node:process";import{mkdir as f}from"node:fs/promises";import{setTimeout as S}from"node:timers/promises";import{resolveRuntimePaths as h}from"../core/config/paths.js";import{inspectDaemonState as d}from"../runtime/service-state.js";import{isProcessRunning as g,runCommand as o,terminateProcessTree as y,waitForProcessExit as v}from"./process-control.js";import{readDaemonLock as z}from"../runtime/daemon-lock.js";import{ServiceInstallStore as I}from"./service-install-store.js";import{getPlatformServiceAdapter as R}from"./platform-adapter.js";import{buildServiceID as D,resolveServiceInstallRecordPath as F,resolveServiceStderrPath as l,resolveServiceStdoutPath as m}from"./service-paths.js";class G{adapter;platform;homeDir;uid;nodePath;cliPath;constructor(i){this.platform=i.platform??c.platform,this.homeDir=i.homeDir??_.homedir(),this.uid=i.uid??c.getuid?.()??0,this.nodePath=i.nodePath??c.execPath,this.cliPath=i.cliPath,this.adapter=R(this.platform)}normalizeRootDir(i){return p.resolve(String(i??"").trim())}buildDescriptor(i,t,r=""){const e=this.normalizeRootDir(i);return{schema_version:1,platform:this.platform,service_id:D(e,this.platform),node_path:this.nodePath,cli_path:this.cliPath,cli_hash:this.computeFileHash(this.cliPath)??"",definition_path:r,config_dir:t??"",installed_at:0,updated_at:0}}createStore(i){return new I(F(this.normalizeRootDir(i)))}toAdapterPayload(i){return{serviceID:i.service_id,nodePath:i.node_path,cliPath:i.cli_path,configDir:i.config_dir||void 0,environmentPath:(c.env.PATH??"").trim()}}toStartParams(i){return{serviceID:i.service_id,definitionPath:i.definition_path,uid:this.uid,homeDir:this.homeDir,runCommand:o}}toStopParams(i){return{serviceID:i.service_id,uid:this.uid,homeDir:this.homeDir,runCommand:o}}toRestartParams(i){return{serviceID:i.service_id,definitionPath:i.definition_path,uid:this.uid,homeDir:this.homeDir,runCommand:o}}toUninstallParams(i){return{serviceID:i.service_id,definitionPath:i.definition_path,uid:this.uid,homeDir:this.homeDir,runCommand:o}}async loadDescriptor(i){const t=this.createStore(i),r=await t.load();if(!r)throw new Error("\u540E\u53F0\u670D\u52A1\u8FD8\u6CA1\u6709\u5B89\u88C5\uFF0C\u8BF7\u5148\u6267\u884C service install\u3002");return{store:t,descriptor:r}}isDescriptorCurrent(i){if(i.node_path!==this.nodePath||i.cli_path!==this.cliPath||!i.cli_hash)return!1;const t=this.computeFileHash(i.cli_path);return t!==null&&t===i.cli_hash}computeFileHash(i){try{const t=w.readFileSync(i);return P("sha256").update(t).digest("hex")}catch{return null}}async refreshDescriptor(i,t){const r=this.normalizeRootDir(i);await f(p.join(r,"service"),{recursive:!0});const e={...t,platform:this.platform,service_id:t.service_id||D(r,this.platform),node_path:this.nodePath,cli_path:this.cliPath,cli_hash:this.computeFileHash(this.cliPath)??"",config_dir:t.config_dir},s=await this.adapter.install({...this.toAdapterPayload(e),stdoutPath:m(r),stderrPath:l(r),homeDir:this.homeDir,uid:this.uid,runCommand:o}),a={...e,installed_at:t.installed_at,definition_path:s?.definitionPath||e.definition_path,updated_at:Date.now()};return await this.createStore(r).save(a),a}async resolveActiveDescriptor(i){const{descriptor:t}=await this.loadDescriptor(i);return this.isDescriptorCurrent(t)?t:this.refreshDescriptor(i,t)}async discoverConflictingServices(i){const t=this.normalizeRootDir(i),r=D(t,this.platform);return(await this.adapter.discoverServices({homeDir:this.homeDir,runCommand:o})).filter(s=>s.serviceID!==r)}async cleanupConflictingServices(i){const t=await this.discoverConflictingServices(i);if(t.length>0){const e=t.map(s=>s.serviceID).join(", ");console.log(`\u53D1\u73B0 ${t.length} \u4E2A\u6B8B\u7559\u670D\u52A1\uFF0C\u6B63\u5728\u68C0\u67E5: ${e}`)}let r=0;for(const e of t){if(await this.adapter.isServiceLoaded({serviceID:e.serviceID,uid:this.uid,runCommand:o})){console.log(`\u8DF3\u8FC7\u6B63\u5728\u8FD0\u884C\u7684\u670D\u52A1: ${e.serviceID}`);continue}try{await this.adapter.stop({serviceID:e.serviceID,uid:this.uid,runCommand:o})}catch{}try{await this.adapter.uninstall({serviceID:e.serviceID,definitionPath:e.definitionPath,uid:this.uid,runCommand:o}),r++}catch{}}return r}async waitForDaemonStarted(i,t={}){const{oldPid:r=0,timeoutMs:e=5e3}=t,s=Date.now();for(;Date.now()-s<e;){const a=z(i.daemonLockFile);if(a&&a.pid>0&&g(a.pid)&&a.pid!==r)return;await S(100)}throw new Error(`daemon start timeout (${e}ms)`)}async install(i){const t=this.normalizeRootDir(i.rootDir);await this.cleanupConflictingServices(t),await f(p.join(t,"service"),{recursive:!0});const r=this.buildDescriptor(t,i.configDir),e=await this.adapter.install({...this.toAdapterPayload(r),stdoutPath:m(t),stderrPath:l(t),homeDir:this.homeDir,uid:this.uid,runCommand:o}),s={...r,definition_path:e?.definitionPath??"",installed_at:Date.now(),updated_at:Date.now()};await this.createStore(t).save(s),await this.adapter.start(this.toStartParams(s));const a=h(t);return await this.waitForDaemonStarted(a),this.status({rootDir:t})}async start(i){const t=this.normalizeRootDir(i.rootDir);await this.cleanupConflictingServices(t);const r=h(t),e=d(r.daemonStatusFile),a=await this.createStore(t).load();if(e.running&&a&&this.isDescriptorCurrent(a))return this.status({rootDir:t});const n=a?this.isDescriptorCurrent(a)?a:await this.refreshDescriptor(t,a):await this.resolveActiveDescriptor(t);try{e.running?await this.adapter.restart(this.toRestartParams(n)):await this.adapter.start(this.toStartParams(n))}catch(u){if(u instanceof Error&&u.message.includes("plist missing"))await this.adapter.install({...this.toAdapterPayload(n),stdoutPath:m(t),stderrPath:l(t),homeDir:this.homeDir,uid:this.uid,runCommand:o}),await this.adapter.start(this.toStartParams(n));else throw u}return await this.waitForDaemonStarted(r,{oldPid:e.pid}),this.status({rootDir:t})}async stop(i){const{descriptor:t}=await this.loadDescriptor(i.rootDir),r=h(t.config_dir||this.normalizeRootDir(i.rootDir)),e=d(r.daemonStatusFile);return await this.adapter.stop(this.toStopParams(t)),e.running&&e.pid&&(await v(e.pid,{timeoutMs:5e3})||(await y(e.pid,{platform:this.platform,runCommandImpl:o}),await v(e.pid,{timeoutMs:5e3}))),this.status({rootDir:i.rootDir})}async restart(i){const t=this.normalizeRootDir(i.rootDir);await this.cleanupConflictingServices(t);const r=await this.resolveActiveDescriptor(t),e=h(t),s=d(e.daemonStatusFile);try{await this.adapter.restart(this.toRestartParams(r))}catch(a){if(a instanceof Error&&a.message.includes("plist missing"))await this.adapter.install({...this.toAdapterPayload(r),stdoutPath:m(t),stderrPath:l(t),homeDir:this.homeDir,uid:this.uid,runCommand:o}),await this.adapter.start(this.toStartParams(r));else throw a}return await this.waitForDaemonStarted(e,{oldPid:s.pid}),this.status({rootDir:t})}async uninstall(i){const t=this.normalizeRootDir(i.rootDir),r=this.createStore(t),e=await r.load();return e&&(await this.adapter.uninstall(this.toUninstallParams(e)),await r.clear()),this.status({rootDir:t})}async status(i){const t=this.normalizeRootDir(i.rootDir),e=await this.createStore(t).load(),s=h(t),a=d(s.daemonStatusFile);return e?{installed:!0,install_state:this.isDescriptorCurrent(e)?"current":"stale",service_kind:this.adapter.kind,service_id:e.service_id,definition_path:e.definition_path,root_dir:t,daemon_state:a.running?"running":a.state,pid:a.pid,connection_state:a.connection_state,updated_at:a.updated_at}:{installed:!1,install_state:"missing",service_kind:this.adapter.kind,root_dir:t,daemon_state:a.running?"running":a.state,pid:a.pid}}}export{G as ServiceManager};
@@ -0,0 +1 @@
1
+ import{createHash as u}from"node:crypto";import o from"node:os";import t from"node:path";import{normalizeString as a}from"../core/util/normalize-string.js";const i="com.dhfpub.grix-connector.daemon.",c="grix-connector-daemon-",s="GrixConnectorDaemon-";function f(r){return u("sha1").update(a(r)||"default").digest("hex").slice(0,12)}function x(r,e=process.platform){const n=f(r);return e==="win32"?`${s}${n}`:e==="darwin"?`${i}${n}`:`${c}${n}`}function h(r=process.platform){return r==="win32"?s:r==="darwin"?i:c}function l(r){return r.replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"')}function v(r){const e=[...r.matchAll(/<string>([^<]+)<\/string>/g)].map(n=>l(n[1]));for(let n=0;n<e.length-1;n+=1)if(e[n]==="--config-dir")return e[n+1];return null}function S(r){const e=r.match(/--config-dir\s+(?:'([^']*)'|"([^"]*)"|(\S+))/);return e?e[1]??e[2]??e[3]??null:null}function I(r){return t.join(r,"daemon-service.json")}function P(r){return t.join(r,"service","daemon.out.log")}function E(r){return t.join(r,"service","daemon.err.log")}function R(r,e){return t.join(e??o.homedir(),"Library","LaunchAgents",`${r}.plist`)}function $(r,e){return t.join(e??o.homedir(),".config","systemd","user",`${r}.service`)}export{i as SERVICE_PREFIX_DARWIN,c as SERVICE_PREFIX_LINUX,s as SERVICE_PREFIX_WIN32,x as buildServiceID,h as getServicePrefix,v as parseConfigDirFromPlistXML,S as parseConfigDirFromSystemdUnit,$ as resolveLinuxUserUnitPath,R as resolveMacOSLaunchAgentPath,I as resolveServiceInstallRecordPath,E as resolveServiceStderrPath,P as resolveServiceStdoutPath};
@@ -0,0 +1 @@
1
+ import{SessionManager as a}from"./manager.js";export{a as SessionManager};
@@ -0,0 +1 @@
1
+ import{EventEmitter as r}from"events";import{AgentProcess as c}from"../agent/process.js";import{AcpClient as l}from"../protocol/acp-client.js";class h extends r{sessions=new Map;async create(s){const e=new c,n=await e.start(s.agent),i=new l;i.on("event",a=>{this.emit("event",a)}),await i.connect({transport:n,sessionId:s.sessionId,authMethod:s.authMethod,initialMode:s.initialMode});const t=i.sessionId,o={id:t,process:e,client:i};return this.sessions.set(t,o),n.on("close",()=>{this.sessions.delete(t),this.emit("sessionClosed",t)}),this.emit("sessionCreated",t),o}get(s){return this.sessions.get(s)}list(){return[...this.sessions.values()]}async close(s){const e=this.sessions.get(s);e&&(this.sessions.delete(s),await e.process.close(),this.emit("sessionClosed",s))}async closeAll(){const s=[...this.sessions.keys()];await Promise.all(s.map(e=>this.close(e)))}get size(){return this.sessions.size}}export{h as SessionManager};
@@ -0,0 +1 @@
1
+ import{JsonRpcTransport as o}from"./json-rpc.js";export{o as JsonRpcTransport};
@@ -0,0 +1,3 @@
1
+ import{EventEmitter as p}from"events";class w extends p{nextId=1;pending=new Map;writeLock=Promise.resolve();closed=!1;_readable;_writable;_onNotify;_onRequest;constructor(t,e,r,o){super(),this._readable=t,this._writable=e,this._onNotify=r,this._onRequest=o,this.startReadLoop()}setHandlers(t,e){t&&(this._onNotify=t),e&&(this._onRequest=e)}async call(t,e,r){if(this.closed)throw new Error("transport closed");const o=this.nextId++,s=String(o),a=await new Promise((i,d)=>{if(this.pending.set(s,{resolve:i}),r){const n=()=>{this.pending.delete(s),d(new Error(`aborted: ${r.reason??"request cancelled"}`))};if(r.aborted){n();return}r.addEventListener("abort",n,{once:!0});const c=i,h=l=>{r.removeEventListener("abort",n),c(l)};this.pending.set(s,{resolve:h})}this.write({jsonrpc:"2.0",id:o,method:t,params:e??null}).catch(n=>{this.pending.delete(s),d(n)})});if(a.error){const i=new Error(a.error.message);throw i.code=a.error.code,i}return a.result}async notify(t,e){if(this.closed)throw new Error("transport closed");await this.write({jsonrpc:"2.0",method:t,params:e??null})}async respondSuccess(t,e){await this.write({jsonrpc:"2.0",id:t,result:e})}async respondError(t,e,r){await this.write({jsonrpc:"2.0",id:t,error:{code:e,message:r}})}close(){if(!this.closed){this.closed=!0;for(const[t,{resolve:e}]of this.pending)e({error:{code:-32e3,message:"transport closed"}});this.pending.clear(),this._readable.destroy(),this.emit("close")}}startReadLoop(){let t="";this._readable.on("data",e=>{t+=e.toString();const r=t.split(`
2
+ `);t=r.pop()??"";for(const o of r){const s=o.trim();s.length!==0&&this.dispatch(s)}}),this._readable.on("end",()=>{t.trim()&&this.dispatch(t.trim()),this.close()}),this._readable.on("error",e=>{this.emit("error",e),this.close()})}dispatch(t){let e;try{e=JSON.parse(t)}catch{return}if(e.id!=null&&!e.method){this.completePending(e.id,e.result,e.error);return}if(e.method&&(e.id==null||e.id===null)){this._onNotify?.(e.method,e.params);return}e.method&&e.id!=null&&this._onRequest?.(e.method,e.id,e.params)}completePending(t,e,r){const o=String(t),s=this.pending.get(o);s&&(this.pending.delete(o),s.resolve({result:e,error:r}))}async write(t){const e=this.writeLock;return this.writeLock=e.then(async()=>new Promise((r,o)=>{const s=JSON.stringify(t)+`
3
+ `;this._writable.write(s,"utf-8")?r():(this._writable.once("drain",r),this._writable.once("error",o))})),this.writeLock}}export{w as JsonRpcTransport};
@@ -0,0 +1 @@
1
+ var r;(function(o){o.Text="text",o.ToolUse="tool_use",o.ToolResult="tool_result",o.Thinking="thinking",o.PermissionRequest="permission_request",o.Error="error",o.Result="result"})(r||(r={}));export{r as AgentEventType};
@@ -0,0 +1 @@
1
+ import{AgentEventType as n}from"./events.js";export{n as AgentEventType};
File without changes
File without changes
File without changes