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.
- package/dist/adapter/acp/acp-adapter.js +5 -5
- package/dist/adapter/acp/session-activity.js +1 -1
- package/dist/adapter/agy/agy-adapter.js +7 -7
- package/dist/adapter/claude/claude-bridge-server.js +1 -0
- package/dist/adapter/claude/claude-tools.js +1 -0
- package/dist/adapter/claude/claude-worker-client.js +1 -0
- package/dist/adapter/claude/mcp-http-launcher.js +2 -0
- package/dist/adapter/claude/result-timeout.js +1 -0
- package/dist/adapter/deepseek/deepseek-adapter.js +6 -0
- package/dist/adapter/deepseek/index.js +1 -0
- package/dist/adapter/qwen/index.js +1 -0
- package/dist/adapter/qwen/qwen-adapter.js +4 -0
- package/dist/aibot/client.js +1 -0
- package/dist/aibot/index.js +1 -0
- package/dist/aibot/types.js +0 -0
- package/dist/assets/dsh-bridge/grix-dsh-bridge-4.1.0.tgz +0 -0
- package/dist/assets/dsh-bridge/manifest.json +5 -5
- package/dist/audit/adapters/agy/agy-audit-adapter.js +1 -1
- package/dist/audit/adapters/agy/agy-gen-metadata.js +1 -0
- package/dist/bridge/bridge.js +7 -7
- package/dist/bridge/lifecycle-barrier.js +1 -1
- package/dist/core/access/allowlist-gate.js +1 -0
- package/dist/core/access/allowlist-store.js +1 -0
- package/dist/core/access/index.js +1 -0
- package/dist/core/aibot/connection-manager.js +1 -1
- package/dist/core/config/agent-config-repository.js +2 -0
- package/dist/core/file-ops/handler.js +1 -0
- package/dist/core/file-ops/list-files.js +1 -0
- package/dist/core/file-ops/types.js +0 -0
- package/dist/core/installer/npm-registry.js +4 -4
- package/dist/core/skill-sync/skill-syncer.js +1 -1
- package/dist/core/upgrade/npm-upgrader.js +2 -2
- package/dist/core/upgrade/upgrade-checker.js +1 -1
- package/dist/default-skills/grix-agent-dispatch/SKILL.md +9 -9
- package/dist/grix.js +7 -7
- package/dist/log.js +3 -0
- package/dist/main.js +31 -0
- package/dist/manager.js +1 -2
- package/dist/mcp/stream-http/config.js +1 -0
- package/dist/mcp/stream-http/connection-binding.js +1 -0
- package/dist/mcp/stream-http/event-tool-executor.js +1 -0
- package/dist/mcp/stream-http/gateway.js +1 -0
- package/dist/mcp/stream-http/index.js +1 -0
- package/dist/mcp/stream-http/security.js +1 -0
- package/dist/mcp/stream-http/session-manager.js +1 -0
- package/dist/mcp/stream-http/tool-executor.js +1 -0
- package/dist/mcp/stream-http/tool-registry.js +1 -0
- package/dist/mcp/stream-http/tool-schemas.js +1 -0
- package/dist/service/platform-adapter.js +25 -24
- package/dist/service/process-control.js +1 -1
- package/dist/service/service-manager.js +3 -3
- package/dist/service/service-paths.js +2 -2
- package/dist/service/windows-wrapper-migration.js +1 -0
- package/dist/session/index.js +1 -0
- package/dist/session/manager.js +1 -0
- package/dist/transport/index.js +1 -0
- package/dist/transport/json-rpc.js +3 -0
- package/openclaw-plugin/audit-recorder-worker.js +496 -54
- package/package.json +2 -1
- package/scripts/install-guardian.mjs +35 -19
- package/scripts/upgrade-guardian.mjs +1270 -0
- 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
|
|
Binary file
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"bridgeVersion": "4.0
|
|
4
|
-
"tarball": "grix-dsh-bridge-4.0.
|
|
5
|
-
"size":
|
|
3
|
+
"bridgeVersion": "4.1.0",
|
|
4
|
+
"tarball": "grix-dsh-bridge-4.1.0.tgz",
|
|
5
|
+
"size": 21976,
|
|
6
6
|
"unpackedSize": 87631,
|
|
7
|
-
"shasum": "
|
|
8
|
-
"integrity": "sha512-
|
|
7
|
+
"shasum": "b3ae8ae30357af60166ad38491e87cd247d95cff",
|
|
8
|
+
"integrity": "sha512-jNBmFsYy0XuBFYvFrWnn8vsMCdY8o+6ccVHL9bdptd+9rpo3u+Vex2uldd6YRboJhDz/maWKzqexarNgJKH8kA=="
|
|
9
9
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readFile as
|
|
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};
|