grix-connector 4.0.1 → 4.1.0

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 (62) hide show
  1. package/dist/adapter/acp/acp-adapter.js +5 -5
  2. package/dist/adapter/acp/session-activity.js +1 -1
  3. package/dist/adapter/agy/agy-adapter.js +7 -7
  4. package/dist/adapter/claude/claude-bridge-server.js +1 -0
  5. package/dist/adapter/claude/claude-tools.js +1 -0
  6. package/dist/adapter/claude/claude-worker-client.js +1 -0
  7. package/dist/adapter/claude/mcp-http-launcher.js +2 -0
  8. package/dist/adapter/claude/result-timeout.js +1 -0
  9. package/dist/adapter/deepseek/deepseek-adapter.js +6 -0
  10. package/dist/adapter/deepseek/index.js +1 -0
  11. package/dist/adapter/qwen/index.js +1 -0
  12. package/dist/adapter/qwen/qwen-adapter.js +4 -0
  13. package/dist/aibot/client.js +1 -0
  14. package/dist/aibot/index.js +1 -0
  15. package/dist/aibot/types.js +0 -0
  16. package/dist/assets/dsh-bridge/grix-dsh-bridge-4.1.0.tgz +0 -0
  17. package/dist/assets/dsh-bridge/manifest.json +5 -5
  18. package/dist/audit/adapters/agy/agy-audit-adapter.js +1 -1
  19. package/dist/audit/adapters/agy/agy-gen-metadata.js +1 -0
  20. package/dist/bridge/bridge.js +7 -7
  21. package/dist/bridge/lifecycle-barrier.js +1 -1
  22. package/dist/core/access/allowlist-gate.js +1 -0
  23. package/dist/core/access/allowlist-store.js +1 -0
  24. package/dist/core/access/index.js +1 -0
  25. package/dist/core/aibot/connection-manager.js +1 -1
  26. package/dist/core/config/agent-config-repository.js +2 -0
  27. package/dist/core/file-ops/handler.js +1 -0
  28. package/dist/core/file-ops/list-files.js +1 -0
  29. package/dist/core/file-ops/types.js +0 -0
  30. package/dist/core/installer/npm-registry.js +4 -4
  31. package/dist/core/skill-sync/skill-syncer.js +1 -1
  32. package/dist/core/upgrade/npm-upgrader.js +2 -2
  33. package/dist/core/upgrade/upgrade-checker.js +1 -1
  34. package/dist/default-skills/grix-agent-dispatch/SKILL.md +9 -9
  35. package/dist/grix.js +7 -7
  36. package/dist/log.js +3 -0
  37. package/dist/main.js +31 -0
  38. package/dist/manager.js +1 -2
  39. package/dist/mcp/stream-http/config.js +1 -0
  40. package/dist/mcp/stream-http/connection-binding.js +1 -0
  41. package/dist/mcp/stream-http/event-tool-executor.js +1 -0
  42. package/dist/mcp/stream-http/gateway.js +1 -0
  43. package/dist/mcp/stream-http/index.js +1 -0
  44. package/dist/mcp/stream-http/security.js +1 -0
  45. package/dist/mcp/stream-http/session-manager.js +1 -0
  46. package/dist/mcp/stream-http/tool-executor.js +1 -0
  47. package/dist/mcp/stream-http/tool-registry.js +1 -0
  48. package/dist/mcp/stream-http/tool-schemas.js +1 -0
  49. package/dist/service/platform-adapter.js +25 -24
  50. package/dist/service/process-control.js +1 -1
  51. package/dist/service/service-manager.js +3 -3
  52. package/dist/service/service-paths.js +2 -2
  53. package/dist/service/windows-wrapper-migration.js +1 -0
  54. package/dist/session/index.js +1 -0
  55. package/dist/session/manager.js +1 -0
  56. package/dist/transport/index.js +1 -0
  57. package/dist/transport/json-rpc.js +3 -0
  58. package/openclaw-plugin/audit-recorder-worker.js +496 -54
  59. package/package.json +2 -1
  60. package/scripts/install-guardian.mjs +35 -19
  61. package/scripts/upgrade-guardian.mjs +1270 -0
  62. package/dist/assets/dsh-bridge/grix-dsh-bridge-4.0.1.tgz +0 -0
@@ -0,0 +1,4 @@
1
+ import l from"node:path";import{fileURLToPath as m}from"node:url";import{EventEmitter as h}from"node:events";import{AgentProcess as f}from"../../agent/process.js";import{AcpClient as v,AcpAuthRequiredError as g}from"../../protocol/acp-client.js";import{AgentEventType as a}from"../../types/events.js";import{QuotedMessageStream as R}from"../../core/util/quoted-message-stream.js";import{InternalApiServer as A}from"../../core/mcp/internal-api-server.js";import{EventResultsStore as b}from"../../core/persistence/event-results-store.js";import{log as r}from"../../core/log/index.js";const d=l.dirname(m(import.meta.url)),w=300*1e3,u=60*1e3,I=200;class T extends h{type="qwen";config;callbacks;agentProcess=null;acpClient=null;internalApi=null;activeRun=null;pendingApprovals=new Map;bindingStore;eventResults=null;currentAibotSessionId;stopped=!1;cwd;model;promptTimeoutMs;clientMsgSeq=0;deferredEvents=new Map;sessionBindings=new Map;constructor(e,t,s,i){super(),this.config=e,this.callbacks=t,this.bindingStore=s,this.cwd=e.cwd??process.cwd(),this.model=e.options?.model,this.promptTimeoutMs=e.options?.promptTimeoutMs??w,i&&(this.eventResults=new b(i))}async start(){const e=[...this.config.args??[],"--acp"];this.model&&e.push("--model",this.model);const t={command:this.config.command||"qwen",args:e,cwd:this.cwd,env:this.config.env},s=await this.startInternalApiAndMcp();this.agentProcess=new f;const i=await this.agentProcess.start(t);r.info("qwen-adapter","Qwen process started"),this.agentProcess.on("exit",n=>{this.stopped||(r.error("qwen-adapter",`Process exited unexpectedly (code=${n})`),this.activeRun&&this.finishRun("failed",`qwen process exited (code=${n})`),this.emit("exit",n))}),this.acpClient=new v,this.acpClient.on("event",n=>this.handleAcpEvent(n));const o=this.currentAibotSessionId?this.bindingStore.getAcpSessionId(this.currentAibotSessionId):void 0;try{await this.acpClient.connect({transport:i,initialMode:"bypass",mcpServers:s,sessionId:o,cwd:this.cwd}),r.info("qwen-adapter",`ACP session ready: ${this.acpClient.sessionId}`),this.currentAibotSessionId&&this.bindingStore.setAcpSessionId(this.currentAibotSessionId,this.acpClient.sessionId);for(const[n,c]of this.sessionBindings)this.callbacks.sendUpdateBindingCard(n,"ready",c)}catch(n){if(n instanceof g){await this.handleAuthRequired(n);return}throw n}}async stop(){this.stopped=!0,this.deferredEvents.clear(),this.activeRun&&(this.activeRun.flushTimer&&(clearTimeout(this.activeRun.flushTimer),this.activeRun.flushTimer=null),this.activeRun.timeoutTimer&&(clearTimeout(this.activeRun.timeoutTimer),this.activeRun.timeoutTimer=null),this.activeRun.firstResponseTimer&&(clearTimeout(this.activeRun.firstResponseTimer),this.activeRun.firstResponseTimer=null),this.activeRun=null),this.acpClient&&(this.acpClient.removeAllListeners(),this.acpClient=null),this.agentProcess&&(await this.agentProcess.close(),this.agentProcess=null),this.internalApi&&(await this.internalApi.stop(),this.internalApi=null)}isAlive(){return this.acpClient?.isAlive??!1}async createSession(e){return this.acpClient?.sessionId??""}async resumeSession(e,t){}async destroySession(e){}sendPrompt(e){const t=new S(e.adapterSessionId);return this.acpClient?.isAlive&&this.acpClient.send(e.text).catch(s=>{t.emitError(s instanceof Error?s:new Error(String(s)))}),t}async cancel(e){this.activeRun&&this.acpClient&&(await this.acpClient.cancel(),this.flushStream(),this.finishRun("canceled","stopped by user"))}setPermissionHandler(e){}async ping(e){return this.acpClient?.ping(e)??!1}getStatus(){return{alive:this.acpClient?.isAlive??!1,busy:this.activeRun!==null,sessions:this.acpClient?1:0}}getMcpConfig(){if(!this.internalApi)return null;const e=l.resolve(d,"../../mcp/acp-mcp-server.js");return{name:"grix-connector-tools",command:process.execPath,args:[e,"--api-url",this.internalApi.url]}}get pendingApprovalEntries(){return this.pendingApprovals}get acpSessionOptions(){return this.acpClient?.sessionOptions??null}async handleLocalAction(e){const t=e.action_type??"",s=e.params??{};if(t==="exec_approve"||t==="exec_reject"){const i=String(s.tool_call_id??""),o=t==="exec_approve";if(!i)return this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"tool_call_id_required","tool_call_id is required"),{handled:!0,kind:"approval"};const n=this.pendingApprovals.get(i);return n?(this.pendingApprovals.delete(i),this.acpClient&&this.acpClient.respondPermission(n,{behavior:o?"allow":"deny"}).catch(c=>{r.error("qwen-adapter",`Failed to respond to permission: ${c}`)}),this.callbacks.sendLocalActionResult(e.action_id,"ok"),{handled:!0,kind:"approval"}):(this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"approval_not_found",`no pending approval for tool_call_id: ${i}`),{handled:!0,kind:"approval"})}return{handled:!1,kind:""}}async startInternalApiAndMcp(){try{this.internalApi=new A,this.internalApi.setInvokeHandler(async(t,s)=>this.callbacks.agentInvoke(t,s)),await this.internalApi.start(0),r.info("qwen-adapter",`Internal API started at ${this.internalApi.url}`);const e=l.resolve(d,"../../mcp/acp-mcp-server.js");return[{name:"grix-connector-tools",command:process.execPath,args:[e,"--api-url",this.internalApi.url],env:{GRIX_CONNECTOR_INTERNAL_API:this.internalApi.url}}]}catch(e){r.error("qwen-adapter",`Failed to start MCP tools: ${e}`);return}}bindSession(e,t){return this.sessionBindings.get(e)?!1:(this.sessionBindings.set(e,t),this.bindingStore.set(e,t),this.acpClient?.sessionId&&this.bindingStore.setAcpSessionId(e,this.acpClient.sessionId),this.acpClient?.isAlive&&this.callbacks.sendUpdateBindingCard(e,"connected",t),!0)}getSessionCwd(e){return this.sessionBindings.get(e)}getSessionBindings(){return this.sessionBindings}deliverInboundEvent(e){if(this.callbacks.sendEventAck(e.event_id,e.session_id),this.eventResults?.has(e.session_id,e.event_id)){const t=this.eventResults.get(e.session_id,e.event_id);r.info("qwen-adapter",`Deduplicating event ${e.event_id} (cached: ${t.status})`),this.callbacks.sendEventResult(e.event_id,t.status,t.msg);return}if(this.activeRun){r.info("qwen-adapter",`Event ${e.event_id} rejected: busy`),this.callbacks.sendEventResult(e.event_id,"failed","agent busy");return}if(!this.acpClient?.isAlive){this.callbacks.sendEventResult(e.event_id,"failed","qwen agent not alive");return}if(e.session_id&&e.session_id!==this.currentAibotSessionId&&(this.currentAibotSessionId=e.session_id),!this.sessionBindings.has(e.session_id)){this.deferEvent(e),this.callbacks.sendStreamChunk(e.event_id,e.session_id,"Qwen needs a workspace before it can reply. Use /grix open <directory> to bind.",1,!1),this.callbacks.sendStreamChunk(e.event_id,e.session_id,"",2,!0),this.callbacks.sendEventResult(e.event_id,"responded");return}this.startRun(e,!1)}deliverStopEvent(e){this.activeRun?.eventId===e&&(this.flushStream(),this.finishRun("canceled","stopped by user"))}deferEvent(e){const t=this.deferredEvents.get(e.session_id)??[];t.some(s=>s.event.event_id===e.event_id)||(t.push({event:e,queuedAt:Date.now()}),this.deferredEvents.set(e.session_id,t),r.info("qwen-adapter",`Deferred event ${e.event_id} for session ${e.session_id} (queue: ${t.length})`))}replayDeferredEvents(e){const t=this.deferredEvents.get(e);if(!(!t||t.length===0)){this.deferredEvents.delete(e),r.info("qwen-adapter",`Replaying ${t.length} deferred events for session ${e}`);for(const{event:s}of t){if(this.activeRun){r.info("qwen-adapter",`Cannot replay ${s.event_id}: agent busy, dropping`);continue}this.startRun(s,!0)}}}startRun(e,t){this.activeRun={eventId:e.event_id,sessionId:e.session_id,threadId:e.thread_id,clientMsgId:`qwen_${++this.clientMsgSeq}_${Date.now()}`,chunkSeq:0,buffer:"",quotedStream:new R,responded:!1,silent:t,flushTimer:null,timeoutTimer:null,firstResponseTimer:null};const s=this.activeRun;s.firstResponseTimer=setTimeout(()=>{this.activeRun?.eventId===e.event_id&&!s.responded&&(r.error("qwen-adapter",`No response from agent within ${u}ms for ${e.event_id}`),this.finishRun("failed","agent not responding"))},u),s.timeoutTimer=setTimeout(()=>{this.activeRun?.eventId===e.event_id&&(r.error("qwen-adapter",`Prompt timed out for ${e.event_id}`),this.finishRun("failed","agent response timed out"))},this.promptTimeoutMs),this.callbacks.sendSessionComposing(e.session_id,!0),this.acpClient.send(e.content).catch(i=>{r.error("qwen-adapter",`Prompt failed: ${i}`),this.finishRun("failed",i instanceof Error?i.message:String(i))})}handleAcpEvent(e){if(e.type===a.PermissionRequest){this.handlePermissionRequest(e);return}const t=this.activeRun;if(t)switch(t.responded||(t.responded=!0,t.firstResponseTimer&&(clearTimeout(t.firstResponseTimer),t.firstResponseTimer=null)),e.type){case a.Text:{e.content&&this.appendToStream(t,e.content);break}case a.ToolUse:{e.toolName&&this.callbacks.sendToolUse(t.eventId,t.sessionId,e.toolName,e.toolInput??"");break}case a.ToolResult:{e.content&&this.callbacks.sendToolResult(t.eventId,t.sessionId,e.content);break}case a.Thinking:{e.content&&this.callbacks.sendThinking(t.eventId,t.sessionId,e.content);break}case a.Error:{r.error("qwen-adapter",`ACP error: ${e.error}`);break}case a.Result:{this.flushStream(),this.finishRun("responded");break}}}handlePermissionRequest(e){const t=e.permissionRequest;if(!t||!e.requestId||!this.acpClient)return;const s=t.toolCallId;this.pendingApprovals.set(s,e.requestId);const i=this.activeRun;i?this.callbacks.sendPermissionCard({eventId:i.eventId,sessionId:i.sessionId,toolCallId:s,toolName:t.toolName,toolTitle:t.toolTitle,options:t.options}):(r.info("qwen-adapter",`Permission request without active run, auto-approving: ${t.toolName}`),this.acpClient.respondPermission(e.requestId,{behavior:"allow"}),this.pendingApprovals.delete(s))}async handleAuthRequired(e){r.info("qwen-adapter",`Auth required, methods: ${e.authMethods.map(o=>o.id).join(", ")}`);const t=e.authMethods.find(o=>/oauth|browser/i.test(o.id))??e.authMethods[0];if(!t)throw e;const s=this.currentAibotSessionId??"";this.callbacks.sendAuthNotification(s,`Qwen authentication required (${t.id}). Initiating auth flow...`);for(const[o,n]of this.sessionBindings)this.callbacks.sendUpdateBindingCard(o,"failed",n);const i=await this.captureAuthUrl();i&&this.callbacks.sendAuthNotification(s,`Please open this URL to authenticate:
2
+ ${i}
3
+
4
+ Waiting for authentication to complete...`);try{await this.acpClient.authenticate(t.id),r.info("qwen-adapter","Authentication successful"),this.callbacks.sendAuthNotification(s,"Authentication successful. Resuming..."),await this.acpClient.connect({transport:this.agentProcess.transport,initialMode:"bypass",mcpServers:this.internalApi?[{name:"grix-connector-tools",command:process.execPath,args:[l.resolve(d,"../../mcp/acp-mcp-server.js"),"--api-url",this.internalApi.url],env:{GRIX_CONNECTOR_INTERNAL_API:this.internalApi.url}}]:void 0}),r.info("qwen-adapter",`ACP session ready after auth: ${this.acpClient.sessionId}`);for(const[o,n]of this.sessionBindings)this.callbacks.sendUpdateBindingCard(o,"ready",n)}catch(o){throw r.error("qwen-adapter",`Auth retry failed: ${o}`),o}}captureAuthUrl(){return new Promise(e=>{if(!this.agentProcess){e(null);return}const t=/https?:\/\/[^\s"')\]]+/;let s=!1;const i=o=>{if(s)return;const n=o.toString().replace(/\x1b\[[0-9;]*m/g,"").match(t);n&&(s=!0,this.agentProcess.removeListener("stderr",i),e(n[0]))};this.agentProcess.on("stderr",i),setTimeout(()=>{s||(s=!0,this.agentProcess.removeListener("stderr",i),e(null))},3e4)})}appendToStream(e,t){const s=e.quotedStream.consume(t);s.deltaContent&&(e.buffer+=s.deltaContent,e.flushTimer||(e.flushTimer=setTimeout(()=>this.flushStream(),I)))}flushStream(){const e=this.activeRun;if(!e||!e.buffer)return;e.flushTimer&&(clearTimeout(e.flushTimer),e.flushTimer=null);const t=e.buffer;e.buffer="",this.callbacks.sendStreamChunk(e.eventId,e.sessionId,t,++e.chunkSeq,!1)}finishRun(e,t){const s=this.activeRun;if(!s)return;this.activeRun=null,this.callbacks.sendSessionComposing(s.sessionId,!1),s.flushTimer&&(clearTimeout(s.flushTimer),s.flushTimer=null),s.timeoutTimer&&(clearTimeout(s.timeoutTimer),s.timeoutTimer=null),s.firstResponseTimer&&(clearTimeout(s.firstResponseTimer),s.firstResponseTimer=null);const i=s.quotedStream.flush();i.deltaContent&&(s.buffer+=i.deltaContent),s.buffer&&(this.callbacks.sendStreamChunk(s.eventId,s.sessionId,s.buffer,++s.chunkSeq,!1),s.buffer=""),t&&this.callbacks.sendRunError(s.eventId,s.sessionId,t),this.callbacks.sendStreamChunk(s.eventId,s.sessionId,"",++s.chunkSeq,!0),s.silent||this.callbacks.sendEventResult(s.eventId,e,t),this.eventResults&&!s.silent&&this.eventResults.set({sessionId:s.sessionId,eventId:s.eventId,status:e,msg:t,updatedAt:Date.now()})}}class S extends h{adapterSessionId;constructor(e){super(),this.adapterSessionId=e}emitDone(e){this.emit("done",e)}emitError(e){this.emit("error",e)}async cancel(){}}export{T as QwenAdapter};
@@ -0,0 +1 @@
1
+ import{EventEmitter as o}from"node:events";import c from"ws";const r="aibot-agent-api-v1",h=1;class l extends o{ws=null;seq=0;heartbeatTimer=null;heartbeatSec=30;connected=!1;config;constructor(e){super(),this.config={url:e.url,agentId:e.agentId,apiKey:e.apiKey,clientType:e.clientType,capabilities:e.capabilities??["stream_chunk","local_action_v1"],localActions:e.localActions??["exec_approve","exec_reject"]}}get isConnected(){return this.connected}async connect(){return new Promise((e,a)=>{const s=new c(this.config.url);this.ws=s;const i=setTimeout(()=>{a(new Error("Auth timeout: no auth_ack received within 15s")),s.close()},15e3);s.on("open",()=>{this.sendPacket("auth",{agent_id:this.config.agentId,api_key:this.config.apiKey,client_type:this.config.clientType,protocol_version:r,contract_version:h,capabilities:this.config.capabilities,local_actions:this.config.localActions})}),s.on("message",t=>{let n;try{n=JSON.parse(t.toString())}catch{return}this.handlePacket(n,i,e,a)}),s.on("close",(t,n)=>{this.connected=!1,this.stopHeartbeat(),clearTimeout(i),this.emit("close",t,n.toString())}),s.on("error",t=>{clearTimeout(i),this.emit("error",t),this.connected||a(t)})})}handlePacket(e,a,s,i){switch(e.cmd){case"auth_ack":{clearTimeout(a);const t=e.payload;t.code===0?(this.connected=!0,t.heartbeat_sec&&(this.heartbeatSec=t.heartbeat_sec),this.startHeartbeat(),this.emit("auth",t),s(t)):i(new Error(`Auth failed: code=${t.code} msg=${t.msg}`));break}case"ping":{this.sendPacket("pong",e.payload??{});break}case"event_msg":{this.emit("event",e.payload);break}case"local_action":{this.emit("localAction",e.payload);break}case"event_stop":{this.emit("stop",e.payload);break}case"kicked":{this.emit("kicked",e.payload),this.disconnect();break}case"error":{const t=e.payload;this.emit("error",new Error(`Server error: code=${t.code} msg=${t.msg}`));break}case"send_ack":case"send_nack":case"local_action_ack":break;default:break}}sendEventAck(e){this.sendPacket("event_ack",e)}sendStreamChunk(e){this.sendPacket("client_stream_chunk",e)}sendMsg(e){this.sendPacket("send_msg",e)}sendEventResult(e){this.sendPacket("event_result",e)}sendLocalActionResult(e){this.sendPacket("local_action_result",e)}sendEventStopAck(e){this.sendPacket("event_stop_ack",e)}sendEventStopResult(e){this.sendPacket("event_stop_result",e)}sendPing(){this.sendPacket("ping",{})}disconnect(){this.connected=!1,this.stopHeartbeat(),this.ws&&(this.ws.close(),this.ws=null)}sendPacket(e,a){if(!this.ws||this.ws.readyState!==c.OPEN)return;const s={cmd:e,seq:++this.seq,payload:a};this.ws.send(JSON.stringify(s))}startHeartbeat(){this.stopHeartbeat(),this.heartbeatTimer=setInterval(()=>{this.connected&&this.sendPing()},this.heartbeatSec*1e3)}stopHeartbeat(){this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=null)}}export{l as AibotClient};
@@ -0,0 +1 @@
1
+ export*from"./types.js";import{AibotClient as o}from"./client.js";export{o as AibotClient};
File without changes
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "bridgeVersion": "4.0.1",
4
- "tarball": "grix-dsh-bridge-4.0.1.tgz",
5
- "size": 22008,
3
+ "bridgeVersion": "4.1.0",
4
+ "tarball": "grix-dsh-bridge-4.1.0.tgz",
5
+ "size": 21976,
6
6
  "unpackedSize": 87631,
7
- "shasum": "2b87cc453a861de9e491e5fe37d96bbf782b544a",
8
- "integrity": "sha512-48Kx3cTARnuY5+o8/f1me/f122v91dmhuOyurHi9hORe/jGncPtBvQy3ZDpTjBpccLch1YcI9WXxG+PIi1jErA=="
7
+ "shasum": "b3ae8ae30357af60166ad38491e87cd247d95cff",
8
+ "integrity": "sha512-jNBmFsYy0XuBFYvFrWnn8vsMCdY8o+6ccVHL9bdptd+9rpo3u+Vex2uldd6YRboJhDz/maWKzqexarNgJKH8kA=="
9
9
  }
@@ -1 +1 @@
1
- import{readFile as E}from"node:fs/promises";import{referenceCaptureContent as q}from"../../core/content-reference.js";const C=Object.freeze({inputOutput:!0,tools:!0,subagents:!1,thinking:!0,rawProviderBody:!1}),h=256e3;function O(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function m(e){return typeof e=="string"&&e.length>0?e:void 0}function x(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function b(e){return e.options?.enabled===!0?e.options.capture:C}function y(e,n,o){const t=[o.role,o.value??""].join("\0");if(n.has(t))return n.get(t);const s=q(o);return n.set(t,s),e.push(o),s}function g(e,n){n&&!e.some(o=>o.contentId===n.contentId)&&e.push(n)}function S(e,n){return typeof e=="string"&&Number.isFinite(Date.parse(e))?e:n}function I(e){const n=e.startedAt??e.job.startedAt,o=e.endedAt??e.job.endedAt,t=Date.parse(n),s=Date.parse(o);return{spanId:e.spanId,traceId:e.job.traceId,turnId:e.job.turnId,sessionId:e.job.sessionId,...e.parentSpanId?{parentSpanId:e.parentSpanId}:{},kind:e.kind,name:e.name,sequence:e.sequence,status:e.status??"completed",startedAt:n,endedAt:o,...Number.isFinite(t)&&Number.isFinite(s)?{durationMs:Math.max(0,s-t)}:{},inputRefs:[],outputRefs:[],provider:{provider:"agy",nativeEventType:e.nativeEventType,nativeIds:Object.fromEntries(Object.entries(e.nativeIds??{}).filter(p=>typeof p[1]=="string")),...e.rawAttributes?{rawAttributes:e.rawAttributes}:{}},provenance:{source:"connector",accuracy:"runtime_exact"}}}function w(e){if(!(!O(e)||typeof e.sequence!="number"||typeof e.observedAt!="string"||typeof e.action!="string"))return{sequence:e.sequence,observedAt:e.observedAt,action:e.action,...e.params===void 0?{}:{params:e.params},...e.result===void 0?{}:{result:e.result},...typeof e.error=="string"?{error:e.error}:{},...typeof e.completedAt=="string"?{completedAt:e.completedAt}:{}}}class k{provider="agy";async collect(n){const o={toolInvocations:[],anomalies:[],gaps:[]},t=O(n.boundary.agyEvidence)?n.boundary.agyEvidence:void 0;if(!t)o.gaps.push({category:"agy_evidence",reason:"source_log_missing",detail:"boundary.agyEvidence is missing"});else{const r=m(t.prompt);r!==void 0&&(o.prompt=r);const c=m(t.stdout);c!==void 0&&(o.stdout=c);const l=m(t.stderr);l!==void 0&&(o.stderr=l),(typeof t.exitCode=="number"||t.exitCode===null)&&(o.exitCode=t.exitCode);const d=m(t.response);if(d!==void 0&&(o.response=d),Array.isArray(t.toolInvocations)){for(const f of t.toolInvocations){const a=w(f);if(!a){o.anomalies.push({code:"agy_tool_invocation_malformed",message:"agy tool invocation row is malformed"}),o.gaps.push({category:"agy_tool_invocation",reason:"correlation_failed"});continue}o.toolInvocations.push(a)}o.toolInvocations.sort((f,a)=>f.sequence-a.sequence)}}const s=m(n.boundary.transcriptPath),p=x(n.boundary.transcriptStartOffset),i=x(n.boundary.transcriptEndOffset);if(s){o.logPath=s;try{const r=await E(s),c=p!==void 0&&p<=r.length?p:0,l=i!==void 0&&i>=c&&i<=r.length?i:r.length;o.logStartOffset=c,o.logEndOffset=l;const d=r.subarray(c,l).toString("utf-8");o.logExcerpt=d.length>h?d.slice(0,h):d}catch(r){o.anomalies.push({code:"agy_log_unreadable",message:r instanceof Error?r.message:String(r)}),o.gaps.push({category:"agy_log",reason:"source_log_missing",detail:s})}}return o}async normalize(n,o){const t=o,s=b(n),p=[],i=[],r=new Map;let c=0;const l=`agy:${n.turnId}:turn`,d=I({job:n,spanId:l,kind:"turn",name:"agy audited turn",sequence:c++,status:n.outcome==="completed"?"completed":n.outcome==="cancelled"?"cancelled":"failed",nativeEventType:"print_turn",nativeIds:{providerSessionId:m(n.boundary.providerSessionId)}});p.push(d);const f=s.inputOutput&&n.input?y(i,r,{...n.input,captureLevel:n.input.captureLevel??"runtime_exact"}):void 0;g(d.inputRefs,f),s.inputOutput&&n.finalOutput&&g(d.outputRefs,y(i,r,{...n.finalOutput,captureLevel:n.finalOutput.captureLevel??"runtime_exact"}));const a=I({job:n,spanId:`agy:${n.sessionId}:request:${n.turnId}`,parentSpanId:l,kind:"llm_request",name:"agy print request",sequence:c++,status:n.outcome==="completed"?"completed":"failed",nativeEventType:"print_process",nativeIds:{providerSessionId:m(n.boundary.providerSessionId)},rawAttributes:{...t.exitCode===void 0?{}:{exitCode:t.exitCode},...t.logPath?{logPath:t.logPath}:{},...t.logStartOffset===void 0?{}:{logStartOffset:t.logStartOffset},...t.logEndOffset===void 0?{}:{logEndOffset:t.logEndOffset},...t.stderr?{stderr:t.stderr.slice(0,2e3)}:{}}});g(a.inputRefs,f),s.inputOutput&&t.prompt&&g(a.inputRefs,y(i,r,{role:"model_request",format:"text",value:t.prompt,captureLevel:"provider_exact"}));const A=t.response??t.stdout;if(s.inputOutput&&A&&g(a.outputRefs,y(i,r,{role:"assistant_text",format:"text",value:A,captureLevel:"provider_exact"})),s.rawProviderBody&&t.logExcerpt&&g(a.outputRefs,y(i,r,{role:"model_response",format:"text",value:t.logExcerpt,sourcePath:t.logPath,sourceOffset:t.logStartOffset,captureLevel:"provider_exact"})),p.push(a),s.tools)for(const u of t.toolInvocations){const _=I({job:n,spanId:`agy:${n.sessionId}:tool:${u.sequence}`,parentSpanId:a.spanId,kind:"tool_call",name:u.action,sequence:c++,status:u.error?"failed":u.completedAt?"completed":"running",startedAt:S(u.observedAt,n.startedAt),endedAt:S(u.completedAt,n.endedAt),nativeEventType:"grix_tool_invoke",nativeIds:{toolSequence:String(u.sequence)},rawAttributes:{toolInvocation:u}});u.params!==void 0&&g(_.inputRefs,y(i,r,{role:"tool_arguments",format:"json",value:typeof u.params=="string"?u.params:JSON.stringify(u.params),captureLevel:"runtime_exact"}));const v=u.result??u.error;v!==void 0&&g(_.outputRefs,y(i,r,{role:"tool_result",format:typeof v=="string"?"text":"json",value:typeof v=="string"?v:JSON.stringify(v),captureLevel:"runtime_exact"})),p.push(_)}return t.gaps.push({category:"provider_usage",reason:"provider_usage_missing",detail:"agy print mode does not report token usage"}),{spans:p,contents:i,anomalies:t.anomalies,collection:t,capture:s}}async correlate(n,o){return o}validate(n,o){const t=o,s=t.spans.filter(a=>a.kind==="llm_request"),p=t.spans.filter(a=>a.kind==="tool_call"),i=!t.capture.inputOutput||n.input!==void 0||t.collection.prompt!==void 0,r=!t.capture.inputOutput||n.finalOutput!==void 0||s.some(a=>a.outputRefs.length>0),c=!t.capture.tools||p.every(a=>a.status!=="running"),l=!1,d=[...t.collection.gaps];t.capture.rawProviderBody&&d.push({category:"raw_provider_body",reason:"raw_capture_disabled",detail:"agy print mode exposes prompt/stdout and the CLI log, not raw model HTTP bodies"});const f=i&&r&&c&&l&&d.length===0;return{status:s.length===0?"failed":f?"complete":"partial",inputComplete:i,outputComplete:r,toolCallsComplete:c,subagentsComplete:!0,usageComplete:l,rawRequestsComplete:!1,gaps:d}}}export{k as AgyAuditAdapter};
1
+ import{readFile as S}from"node:fs/promises";import{referenceCaptureContent as q}from"../../core/content-reference.js";import{extractAgyResponseIds as R,readAgyTurnUsage as b}from"./agy-gen-metadata.js";const k=Object.freeze({inputOutput:!0,tools:!0,subagents:!1,thinking:!0,rawProviderBody:!1}),A=256e3;function E(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function g(e){return typeof e=="string"&&e.length>0?e:void 0}function O(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function w(e){return e.options?.enabled===!0?e.options.capture:k}function v(e,n,o){const t=[o.role,o.value??""].join("\0");if(n.has(t))return n.get(t);const s=q(o);return n.set(t,s),e.push(o),s}function m(e,n){n&&!e.some(o=>o.contentId===n.contentId)&&e.push(n)}function C(e,n){return typeof e=="string"&&Number.isFinite(Date.parse(e))?e:n}function x(e){const n=e.startedAt??e.job.startedAt,o=e.endedAt??e.job.endedAt,t=Date.parse(n),s=Date.parse(o);return{spanId:e.spanId,traceId:e.job.traceId,turnId:e.job.turnId,sessionId:e.job.sessionId,...e.parentSpanId?{parentSpanId:e.parentSpanId}:{},kind:e.kind,name:e.name,sequence:e.sequence,status:e.status??"completed",startedAt:n,endedAt:o,...Number.isFinite(t)&&Number.isFinite(s)?{durationMs:Math.max(0,s-t)}:{},inputRefs:[],outputRefs:[],provider:{provider:"agy",nativeEventType:e.nativeEventType,nativeIds:Object.fromEntries(Object.entries(e.nativeIds??{}).filter(u=>typeof u[1]=="string")),...e.rawAttributes?{rawAttributes:e.rawAttributes}:{}},provenance:{source:"connector",accuracy:"runtime_exact"}}}function T(e){if(!(!E(e)||typeof e.sequence!="number"||typeof e.observedAt!="string"||typeof e.action!="string"))return{sequence:e.sequence,observedAt:e.observedAt,action:e.action,...e.params===void 0?{}:{params:e.params},...e.result===void 0?{}:{result:e.result},...typeof e.error=="string"?{error:e.error}:{},...typeof e.completedAt=="string"?{completedAt:e.completedAt}:{}}}function P(e){const n=e.usageRecords;if(!n||n.length===0)return;let o=0,t=0;for(const a of n)o+=a.inputTokens??0,t+=a.outputTokens??0;const s=n.some(a=>a.inputTokens===null&&a.outputTokens===null),u=e.usageExpectedCount!==void 0&&n.length===e.usageExpectedCount&&!s;return{input:{total:o,uncached:null,cacheRead:null,cacheWrite:null,other:null},output:{total:t,reasoning:null,visible:null},totalProcessed:o+t,requestCount:n.length,accuracy:"provider_reported",completeness:u?"complete":"partial",provider:"agy",providerUsageRaw:n,normalization:{adapter:"agy-gen-metadata",version:1,formula:"sum of per-generation input_tokens/output_tokens from the agy conversation sqlite gen_metadata table, matched to this turn by streamGenerateContent ResponseID"}}}function L(e){return e.usageExpectedCount===void 0?"agy gen_metadata extraction skipped: conversation id or streamGenerateContent log excerpt unavailable":`agy gen_metadata extraction found no matching rows for ${e.usageExpectedCount} ResponseID(s)`}class F{provider="agy";async collect(n){const o={toolInvocations:[],anomalies:[],gaps:[]},t=E(n.boundary.agyEvidence)?n.boundary.agyEvidence:void 0;if(!t)o.gaps.push({category:"agy_evidence",reason:"source_log_missing",detail:"boundary.agyEvidence is missing"});else{const i=g(t.prompt);i!==void 0&&(o.prompt=i);const d=g(t.stdout);d!==void 0&&(o.stdout=d);const f=g(t.stderr);f!==void 0&&(o.stderr=f),(typeof t.exitCode=="number"||t.exitCode===null)&&(o.exitCode=t.exitCode);const r=g(t.response);if(r!==void 0&&(o.response=r),Array.isArray(t.toolInvocations)){for(const _ of t.toolInvocations){const y=T(_);if(!y){o.anomalies.push({code:"agy_tool_invocation_malformed",message:"agy tool invocation row is malformed"}),o.gaps.push({category:"agy_tool_invocation",reason:"correlation_failed"});continue}o.toolInvocations.push(y)}o.toolInvocations.sort((_,y)=>_.sequence-y.sequence)}}const s=g(n.boundary.transcriptPath),u=O(n.boundary.transcriptStartOffset),a=O(n.boundary.transcriptEndOffset);if(s){o.logPath=s;try{const i=await S(s),d=u!==void 0&&u<=i.length?u:0,f=a!==void 0&&a>=d&&a<=i.length?a:i.length;o.logStartOffset=d,o.logEndOffset=f;const r=i.subarray(d,f).toString("utf-8");o.logExcerpt=r.length>A?r.slice(0,A):r}catch(i){o.anomalies.push({code:"agy_log_unreadable",message:i instanceof Error?i.message:String(i)}),o.gaps.push({category:"agy_log",reason:"source_log_missing",detail:s})}}const p=g(n.boundary.providerSessionId),l=o.logExcerpt?R(o.logExcerpt):[];if(p&&l.length>0){o.usageExpectedCount=l.length;const i=b(p,l);i&&(o.usageRecords=i.records,i.model&&(o.usageModel=i.model))}return o}async normalize(n,o){const t=o,s=w(n),u=[],a=[],p=new Map;let l=0;const i=`agy:${n.turnId}:turn`,d=x({job:n,spanId:i,kind:"turn",name:"agy audited turn",sequence:l++,status:n.outcome==="completed"?"completed":n.outcome==="cancelled"?"cancelled":"failed",nativeEventType:"print_turn",nativeIds:{providerSessionId:g(n.boundary.providerSessionId)}});u.push(d);const f=s.inputOutput&&n.input?v(a,p,{...n.input,captureLevel:n.input.captureLevel??"runtime_exact"}):void 0;m(d.inputRefs,f),s.inputOutput&&n.finalOutput&&m(d.outputRefs,v(a,p,{...n.finalOutput,captureLevel:n.finalOutput.captureLevel??"runtime_exact"}));const r=x({job:n,spanId:`agy:${n.sessionId}:request:${n.turnId}`,parentSpanId:i,kind:"llm_request",name:"agy print request",sequence:l++,status:n.outcome==="completed"?"completed":"failed",nativeEventType:"print_process",nativeIds:{providerSessionId:g(n.boundary.providerSessionId)},rawAttributes:{...t.exitCode===void 0?{}:{exitCode:t.exitCode},...t.logPath?{logPath:t.logPath}:{},...t.logStartOffset===void 0?{}:{logStartOffset:t.logStartOffset},...t.logEndOffset===void 0?{}:{logEndOffset:t.logEndOffset},...t.stderr?{stderr:t.stderr.slice(0,2e3)}:{}}});m(r.inputRefs,f),s.inputOutput&&t.prompt&&m(r.inputRefs,v(a,p,{role:"model_request",format:"text",value:t.prompt,captureLevel:"provider_exact"}));const _=t.response??t.stdout;if(s.inputOutput&&_&&m(r.outputRefs,v(a,p,{role:"assistant_text",format:"text",value:_,captureLevel:"provider_exact"})),s.rawProviderBody&&t.logExcerpt&&m(r.outputRefs,v(a,p,{role:"model_response",format:"text",value:t.logExcerpt,sourcePath:t.logPath,sourceOffset:t.logStartOffset,captureLevel:"provider_exact"})),u.push(r),s.tools)for(const c of t.toolInvocations){const h=x({job:n,spanId:`agy:${n.sessionId}:tool:${c.sequence}`,parentSpanId:r.spanId,kind:"tool_call",name:c.action,sequence:l++,status:c.error?"failed":c.completedAt?"completed":"running",startedAt:C(c.observedAt,n.startedAt),endedAt:C(c.completedAt,n.endedAt),nativeEventType:"grix_tool_invoke",nativeIds:{toolSequence:String(c.sequence)},rawAttributes:{toolInvocation:c}});c.params!==void 0&&m(h.inputRefs,v(a,p,{role:"tool_arguments",format:"json",value:typeof c.params=="string"?c.params:JSON.stringify(c.params),captureLevel:"runtime_exact"}));const I=c.result??c.error;I!==void 0&&m(h.outputRefs,v(a,p,{role:"tool_result",format:typeof I=="string"?"text":"json",value:typeof I=="string"?I:JSON.stringify(I),captureLevel:"runtime_exact"})),u.push(h)}const y=P(t);return y?(r.usage=y,t.usageModel&&(r.modelId=t.usageModel)):t.gaps.push({category:"provider_usage",reason:"provider_usage_missing",detail:L(t)}),{spans:u,contents:a,anomalies:t.anomalies,collection:t,capture:s}}async correlate(n,o){return o}validate(n,o){const t=o,s=t.spans.filter(r=>r.kind==="llm_request"),u=t.spans.filter(r=>r.kind==="tool_call"),a=!t.capture.inputOutput||n.input!==void 0||t.collection.prompt!==void 0,p=!t.capture.inputOutput||n.finalOutput!==void 0||s.some(r=>r.outputRefs.length>0),l=!t.capture.tools||u.every(r=>r.status!=="running"),i=s.length>0&&s.every(r=>r.usage?.completeness==="complete"),d=[...t.collection.gaps];t.capture.rawProviderBody&&d.push({category:"raw_provider_body",reason:"raw_capture_disabled",detail:"agy print mode exposes prompt/stdout and the CLI log, not raw model HTTP bodies"});const f=a&&p&&l&&i&&d.length===0;return{status:s.length===0?"failed":f?"complete":"partial",inputComplete:a,outputComplete:p,toolCallsComplete:l,subagentsComplete:!0,usageComplete:i,rawRequestsComplete:!1,gaps:d}}}export{F as AgyAuditAdapter};
@@ -0,0 +1 @@
1
+ import{homedir as y}from"node:os";import{join as l}from"node:path";import{openReadOnlyDatabase as g}from"../../../core/util/sqlite-reader.js";function m(){return process.env.GRIX_AGY_ANTIGRAVITY_HOME??l(y(),".gemini","antigravity-cli")}function S(t){const i=[],e=new Set;for(const n of t.split(/\r?\n/)){if(!n.includes("streamGenerateContent"))continue;const r=/ResponseID: (\S+)/.exec(n);if(!r)continue;const o=r[1];e.has(o)||(e.add(o),i.push(o))}return i}function c(t,i){let e=0n,n=0n,r=i;for(;;){if(r>=t.length||n>63n)throw new Error("bad varint");const o=t[r];if(e|=BigInt(o&127)<<n,r+=1,(o&128)===0)return{value:e,next:r};n+=7n}}function p(t){const i=[];let e=0;for(;e<t.length;){const n=c(t,e);e=n.next;const r=Number(n.value>>3n),o=Number(n.value&0x7n);if(r<=0)throw new Error("bad field number");if(o===0){const s=c(t,e);e=s.next,i.push({field:r,wire:o,varint:s.value})}else if(o===2){const s=c(t,e);e=s.next;const u=e+Number(s.value);if(u>t.length)throw new Error("bad length");i.push({field:r,wire:o,bytes:t.subarray(e,u)}),e=u}else if(o===5){if(e+=4,e>t.length)throw new Error("bad fixed32")}else if(o===1){if(e+=8,e>t.length)throw new Error("bad fixed64")}else throw new Error(`unsupported wire type ${o}`)}return i}function h(t,i){const e=t.find(n=>n.field===i&&n.wire===2);if(e?.bytes)try{return p(e.bytes)}catch{return}}function x(t,i){const e=t.find(n=>n.field===i&&n.wire===0);if(e?.varint!==void 0&&!(e.varint<0n||e.varint>0xffffffffn))return Number(e.varint)}const v=/^[\x21-\x7e]{8,64}$/;function b(t){try{return new TextDecoder("utf-8",{fatal:!0}).decode(t)}catch{return}}function w(t,i,e){const n=t.find(o=>o.field===i&&o.wire===2);if(!n?.bytes)return;const r=b(n.bytes);if(r!==void 0&&!(e&&!e.test(r)))return r}function A(t){try{const i=p(t),e=h(i,1);if(!e)return;const n=h(e,4);if(!n)return;const r=w(n,11,v);return r?{responseId:r,inputTokens:x(n,2),outputTokens:x(n,3),model:w(e,19)}:void 0}catch{return}}const E=/^[a-zA-Z0-9._-]+$/;function _(t,i){if(!E.test(t)||i.length===0)return null;const e=l(m(),"conversations",`${t}.db`),n=g(e);if(!n)return null;try{const r=new Set(i),o=n.all("SELECT idx, data FROM gen_metadata"),s=new Map;let u;for(const f of o){if(!(f.data instanceof Uint8Array))continue;const d=A(f.data);if(!d||!r.has(d.responseId))continue;const a=s.get(d.responseId);a&&a.idx>=f.idx||(s.set(d.responseId,{idx:f.idx,responseId:d.responseId,inputTokens:d.inputTokens??null,outputTokens:d.outputTokens??null}),u??=d.model)}return s.size===0?null:{records:Array.from(s.values()).sort((f,d)=>f.idx-d.idx),...u?{model:u}:{}}}catch{return null}finally{n.close()}}export{A as decodeAgyGenMetadata,S as extractAgyResponseIds,_ as readAgyTurnUsage,m as resolveAgyAntigravityHome};