grix-connector 3.31.1 → 3.31.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
- import{createHash as D,randomUUID as x}from"node:crypto";import{EventEmitter as V}from"node:events";import{copyFileSync as he,existsSync as W,mkdirSync as ce}from"node:fs";import{dirname as ue,join as w,resolve as G}from"node:path";import{fileURLToPath as z}from"node:url";import{log as f}from"../../core/log/index.js";import{syncDefaultSkillsToDir as pe}from"../../default-skills/index.js";import{resolveCliPath as ge}from"../../core/util/cli-probe.js";import{DshWireCapture as fe}from"./audit-boundary.js";import{dsmlToolCallKey as me,projectVisibleDsmlText as ve}from"./dsml-text-filter.js";import{mapDshSessionEvent as be,unwrapDshSessionEvent as _e}from"./event-mapper.js";import{buildDshUserPrompt as Q,extractQuotedMessageMarker as K}from"./prompt-builder.js";import{DshProcessRuntime as Se}from"./process-runtime.js";import{DshProfileRuntime as ke}from"./profile-runtime.js";import{createDshWebProfile as Ie}from"./profile-catalog.js";import{listDshPlugins as M,resolveDshPlugin as Te,updateDshPluginIds as we}from"./plugin-manager.js";import{listDshSkills as R,resolveDshSkill as Pe,updateDshSkillIds as ye}from"./skill-manager.js";import{prepareDshSessionPluginOverlay as Ee}from"./session-plugin-overlay.js";import{assertSelectableDshProfileName as Ce,discoverDshBridgeEndpoints as De,listDshProfiles as xe,resolveDshConnectorProfileDataDir as Me,resolveDshSelectedProfileName as Re}from"./profile-resolver.js";import{DshBridgeInstaller as A,errorForDshBridgeReadiness as H}from"./bridge-installer.js";import{ensureDshBridgeReady as Ae,prepareDshProfileBridge as He}from"./profile-supervisor.js";import{DSH_RUNTIME_ENSURE_MAX_ATTEMPTS as X,dshRuntimeEnsureBackoffMs as $e,isRetryableDshRuntimeError as Be}from"./runtime-ensure.js";import{runDshProtocolProbe as Ne}from"./probe.js";import{buildDshSystemPrompt as Fe,describeDshSystemPrompt as qe}from"./system-prompt.js";import{DshActionCoordinator as je}from"./toolbar-actions.js";import{adoptDshProfileModels as Le,adoptLiveDshProviderSelection as Ue,buildDshToolbarMeta as Oe,DEFAULT_DSH_MAX_TOKENS as Ve,DEFAULT_DSH_MODELS as We,DEFAULT_DSH_PRESETS as Ge,DEFAULT_DSH_PROVIDER_ID as $,DEFAULT_DSH_REASONING_EFFORT as ze,DEFAULT_DSH_THINKING as Qe,normalizeDshPresets as Ke,normalizeDshProviders as Xe,normalizeDshReasoningEffort as B,normalizeDshThinking as N,permissionModeFor as J,resolveDshAgentPreset as Y,resolveDshModeId as Je,resolveDshProviderId as Ye,retainRequestedDshProvider as Ze}from"./toolbar-state.js";import{modelsForDshProvider as et,resolveDshCatalogForToolbar as tt,writeDshCatalogCache as it}from"./catalog-cache.js";import{TurnCorrelator as st}from"./turn-correlator.js";import{effectiveDshReasoningEffort as nt}from"./types.js";import{getDshSessionUsageStore as ot,normalizeDshUsage as Z}from"./usage.js";import{toolCallToInvoke as rt}from"../../core/mcp/tools.js";import{isEventTool as at}from"../../core/mcp/event-tool-executor.js";import{isDshBridgedGrixTool as dt}from"./grix-tool-bridge.js";import{DSH_GRIX_PROVIDER_ID as b,buildDshManagedProvider as ee}from"./dsh-provider-config.js";const m="deepseek-harness-adapter",te=20*6e4,ie=6e4,se=9e4,ne=30*6e4,oe="0.1.0-rc.8";class lt extends V{adapterSessionId;cancelFn;constructor(e,t){super(),this.adapterSessionId=e,this.cancelFn=t}cancel(){return this.cancelFn()}}class ti extends V{config;callbacks;type="deepseek-harness";alive=!1;stopped=!1;runtime=null;capture=null;runtimeGeneration=0;runtimeSessionId="";applied;active=null;correlator=null;timeoutTimer=null;hardTimeoutTimer=null;activeTimeoutMs=te;intentionalRuntimeStop=!1;personaDirty=!1;profileRevision=0;appliedProfileRevision=-1;rebuildPromise=null;runtimeStartPromise=null;contextWindow=null;reportedContextCapacity=null;providerQuota=null;settingsState="applied";settingsErrorCode=null;injectedMessageIds=new Set;auditBoundaries=new Map;actionCoordinator=new je;activeWireStart=0;activeUsage=re();activeUsageSeq=-1;activeCommittedUsageSeqs=new Set;permissionHandler=null;quotedMessageId;cancelRequested=!1;runtimeReadiness="unknown";bridgeCapabilities=null;profileDshVersion=null;bridgeAckCursor=0;pendingFinalBridgeAck=null;finishingTurn=!1;pendingApprovals=new Map;options;models=We;providers=[];presets=[...Ge];catalogProviderId;constructor(e,t,i){super(),this.config=e,this.callbacks=t,this.options=i,this.hydrateCatalogFromCache()}async start(){this.alive=!0,this.stopped=!1,this.settingsState="applied",this.settingsErrorCode=null,this.hydrateCatalogFromCache();const e=this.options.bindingStore.get(this.options.aibotSessionId);if(e?.cwd&&this.seedSessionToolbarFromGlobal(),this.syncGrixProvider(),e&&await this.options.bindingStore.flush(),this.resolveIntegrationMode()==="profile_bridge")try{const t=await this.attachSelectedProfile();await this.healBridgeUpdate(t)}catch(t){this.runtimeReadiness=String(t?.code??"bridge_probe_failed"),this.settingsErrorCode=this.runtimeReadiness}else this.runtimeReadiness="ready";this.pushToolbarMeta(),this.refreshProviderQuota(!1)}async stop(){this.stopped=!0,this.clearPendingApprovals("cancelled"),this.clearTimeout(),this.active&&this.finishActive("canceled","connector shutdown"),this.applied=void 0,this.contextWindow=null,this.reportedContextCapacity=null,this.settingsState="pending",this.settingsErrorCode=null,this.pushToolbarMeta(),await this.rebuildPromise?.catch(()=>{}),await this.stopRuntime(!0),await this.usageStore().flush(),this.alive=!1}isAlive(){return this.alive&&!this.stopped}async createSession(e){return this.options.aibotSessionId}async resumeSession(e,t){}async destroySession(e){e===this.options.aibotSessionId&&(this.usageStore().delete(e),await this.usageStore().flush(),await this.stopRuntime(!0))}sendPrompt(e){const t=new lt(e.adapterSessionId,()=>this.cancel(e.adapterSessionId));return queueMicrotask(()=>t.emit("done",{status:"failed",error:"Use deliverInboundEvent for platform prompts"})),t}async cancel(e){await this.cancelActive("user canceled")}deliverInboundEvent(e){if(!this.isAlive()){this.failEvent(e,"adapter is not alive");return}if(e.attachments_json&&e.attachments_json!=="[]"){this.failEvent(e,"DeepSeek Harness first version supports text only; attachments must be materialized in the bound workspace");return}if(this.active){this.failEvent(e,"concurrent prompt rejected");return}this.runInboundEvent(e)}deliverStopEvent(e,t){this.active&&e===this.active.inbound.event_id&&(t&&t!==this.active.inbound.session_id||this.cancelActive("user canceled"))}async handleLocalAction(e){if(!["set_model","set_mode","set_provider","set_thinking","set_reasoning_effort","set_preset","set_profile","create_profile","get_session_usage","get_rate_limits","dsh_bridge_status","dsh_install_bridge","dsh_list_plugins","dsh_enable_plugin","dsh_disable_plugin","dsh_refresh_plugins","dsh_list_skills","dsh_enable_skill","dsh_disable_skill","dsh_list_mcp","dsh_list_tools","dsh_list_jobs","dsh_list_goals","exec_approve","exec_reject","permission_approve","permission_reject"].includes(e.action_type))return{handled:!1,kind:""};const t=await this.actionCoordinator.run(e.action_id,()=>this.executeLocalAction(e));return this.callbacks.sendLocalActionResult(e.action_id,t.status,t.result,t.errorCode,t.errorMsg),{handled:!0,kind:e.action_type}}setPermissionHandler(e){this.permissionHandler=e}async ping(e){return this.isAlive()&&(!this.runtime||this.runtime.isConnected())}getStatus(){return{alive:this.isAlive()&&!!this.runtime,busy:!!this.active||this.intentionalRuntimeStop||!!this.rebuildPromise||!!this.runtimeStartPromise,backgroundBusy:!1,sessions:this.runtime?1:0,details:{runtimeGeneration:this.runtimeGeneration,runtimeSessionId:this.runtimeSessionId||void 0}}}getActiveEventIds(){return this.active?[this.active.inbound.event_id]:[]}takeAuditBoundary(e){const t=this.auditBoundaries.get(e);return this.auditBoundaries.delete(e),t}clearActiveEventForShutdown(){this.active=null,this.correlator=null,this.clearTimeout()}getMcpConfig(){return null}async hasBackgroundWork(){return this.runtime?.hasBackgroundWork()??!1}onAgentProfileChanged(){this.profileRevision+=1,this.personaDirty=!0,!this.active&&this.runtime&&this.rebuildRuntime("persona_changed")}updateProviderQuotaSnapshot(e){this.providerQuota=e??null,this.pushToolbarMeta()}async probe(e={}){const t=this.resolveIntegrationMode(),i=t==="embedded_jsonrpc"?this.config.command||"dsh-jsonrpc-agent":"dsh",s=await ge(i),n=!!s;let a={ok:e.conversation!==!0,latency:null};if(n&&e.conversation===!0&&s)if(t==="embedded_jsonrpc")try{const d=await Ne({command:s,args:this.config.args,cordisPath:G(this.options.cordisPath??z(new URL("./grix-jsonrpc.cordis.yml",import.meta.url))),settings:this.resolveDesiredSettings(),timeoutMs:e.timeoutMs});a={ok:!0,latency:d.latencyMs,serverName:d.serverName,serverVersion:d.serverVersion}}catch(d){a={ok:!1,latency:null,error:this.redactError(d)}}else{const d=Date.now();try{const r=new A({command:"dsh",dshHome:this.options.dshHome??this.config.env?.DSH_HOME,profileName:this.resolveSelectedProfile()}),p=await Ae({installer:r,autoStart:!1}),u=H(p);if(u)throw u;const o=De(p.identity);if(o.length===0)throw Object.assign(new Error(`No live Grix Bridge endpoint in DSH profile "${p.identity.profileName}"`),{code:"bridge_missing"});a={ok:!0,latency:Date.now()-d,serverName:"grix-dsh-profile-bridge",serverVersion:o[0].bridgeVersion}}catch(r){a={ok:!1,latency:null,error:this.redactError(r)}}}return{cli:{command:i,installed:n,path:s,version:null,...n?{}:{error:{code:"cli_not_found",message:`${i} not found`}}},conversation:{attempted:e.conversation===!0,ok:a.ok,latency_ms:a.latency,...a.ok?{}:{error:{code:"conversation_failed",message:a.error??"initialize/shutdown probe failed"}}},config:{model:this.resolveDesiredSettings().modelId,base_url:this.config.env?.DEEPSEEK_BASE_URL??null,source:{model:"config",base_url:this.config.env?.DEEPSEEK_BASE_URL?"env":"unknown"},extras:{protocol:t==="profile_bridge"?"grix-dsh/1":"jsonrpc-v1",profile:this.resolveSelectedProfile(),serverName:a.serverName,serverVersion:a.serverVersion}},process:{started:!!this.runtime,alive:this.runtime?.isConnected()??!1,busy:!!this.active}}}async runInboundEvent(e){const t={inbound:e,admitted:!1,claimed:!1,turnEnded:!1,rootIdle:!1,text:"",sentText:"",seq:0,startedAt:Date.now()};this.active=t,this.correlator=new st(t),this.activeUsage=re(),this.activeUsageSeq=-1,this.activeCommittedUsageSeqs.clear(),this.quotedMessageId=void 0,this.cancelRequested=!1,this.emit("eventStarted",e.event_id,e.session_id);try{if(await this.ensureRuntimeWithRetry(),this.cancelRequested||this.active!==t)return;this.activeWireStart=this.capture?.offset??0;const i=Q(e,this.injectedMessageIds);this.startTimeout(e.timeoutMs);const s=await this.runtime.client.prompt({sessionId:this.runtimeSessionId,contentBlocks:[{type:"text",text:i.text}]});if(!s?.messageId)throw Object.assign(new Error("session/prompt response missing messageId"),{code:"protocol_invalid_prompt_result"});this.correlator.setPromptMessageId(s.messageId)}catch(i){const s=this.redactError(i,e.content);this.finishActive(this.cancelRequested?"canceled":"failed",this.cancelRequested?"user canceled":s)}}async ensureRuntime(){if(this.stopped)throw new Error("adapter stopped");if(this.runtime)return;this.syncGrixProvider();const t=this.options.bindingStore.get(this.options.aibotSessionId)?.cwd;if(!t)throw Object.assign(new Error("Session binding missing. Open a workspace first."),{code:"binding_missing"});const i=this.projectConnectorSkills();let s=this.resolveDesiredSettings();const n=this.options.bindingStore.getDshSettings(this.options.aibotSessionId),a={};n?.modelId||(a.modelId=s.modelId),!n?.providerId&&s.providerId&&(a.providerId=s.providerId),n?.thinking||(a.thinking=s.thinking),n?.reasoningEffort||(a.reasoningEffort=s.reasoningEffort),Object.keys(a).length>0&&(this.options.bindingStore.updateDshSettings(this.options.aibotSessionId,a),await this.options.bindingStore.flush(),s=this.resolveDesiredSettings());const d=this.callbacks.getAgentProfile(),r=this.profileRevision,p=Fe({...d,grixSessionId:this.options.aibotSessionId,agentId:this.callbacks.getAgentId()}),u=qe(p);this.runtimeGeneration+=1;const o=this.resolveIntegrationMode(),l=this.resolveSelectedProfile();if(o==="profile_bridge")try{await this.ensureProfileReadyForChat(),this.pushToolbarMeta()}catch(g){throw this.settingsState="failed",this.settingsErrorCode=String(g?.code??"runtime_initialize_failed"),this.runtimeReadiness=this.settingsErrorCode,this.pushToolbarMeta(),g}let c=o==="profile_bridge"?this.options.bindingStore.getDshProfileBinding(this.options.aibotSessionId,l):void 0;o==="profile_bridge"&&!c&&(c={profileName:l,sessionId:pt(this.options.aibotSessionId),sessionCreated:!1,eventCursor:0},this.options.bindingStore.setDshProfileBinding(this.options.aibotSessionId,c),await this.options.bindingStore.flush()),this.runtimeSessionId=c?.sessionId??ut(this.options.aibotSessionId,this.runtimeGeneration);const v=this.profileDataDir(l),F=G(this.options.cordisPath??z(new URL("./grix-jsonrpc.cordis.yml",import.meta.url))),q=Ee({dshHome:this.options.dshHome??this.config.env?.DSH_HOME,profileName:l,pluginIds:s.pluginIds??[],overlayId:D("sha256").update(this.options.aibotSessionId).digest("hex").slice(0,24),baseCordisPath:F}),le=w(v,"audit-source",`${this.runtimeSessionId}.jsonl`);this.capture=new fe(le);const _=o==="embedded_jsonrpc"?new Se({command:this.config.command||"dsh-jsonrpc-agent",args:this.config.args,cwd:t,cordisPath:q.embeddedCordisPath??F,home:v,sessionRoot:w(v,"sessions"),skillsDir:i,env:this.config.env,systemPrompt:p,settings:s,capture:this.capture,maxLineBytes:this.options.maxLineBytes}):new ke({dshHome:this.options.dshHome??this.config.env?.DSH_HOME,profileName:l,cwd:t,ownerId:`${this.callbacks.getAgentId()}:${this.options.aibotSessionId}`,sessionId:this.runtimeSessionId,resumeSession:c?.sessionCreated===!0,lastAckCursor:c?.eventCursor??0,systemPrompt:p,settings:s,skillsDir:i,pluginOverlayPath:q.bridgeOverlayPath,managedProvider:s.providerId===b?ee(this.options.provider??{}):void 0,capture:this.capture,maxFrameBytes:this.options.maxLineBytes,onApproval:g=>this.handleBridgeApproval(g),onToolInvoke:(g,P,I)=>this.invokeGrixTool(g,P,I),onCursorAck:g=>{!c||g<=c.eventCursor||(c={...c,eventCursor:g},this.options.bindingStore.setDshProfileBinding(this.options.aibotSessionId,c))}});this.runtime=_,this.bridgeAckCursor=c?.eventCursor??0,this.pendingFinalBridgeAck=null,this.finishingTurn=!1,this.intentionalRuntimeStop=!1;try{const g=await _.start();if(!_.isConnected())throw Object.assign(new Error("Harness runtime disconnected immediately after initialize"),{code:"runtime_exited"});_.client?.on("notification",(S,k)=>this.onNotification(S,k)),_.client?.on("protocolError",S=>this.onProtocolError(S)),_.onExit(()=>this.onRuntimeExit()),_.client?.activateNotifications?.();let P=!1;if(o==="profile_bridge"){const S=Xe(g.providers),k=Ue({requestedProviderId:s.providerId,liveProviders:S,liveSelectedProvider:String(g.selectedProvider??"")});this.providers=Ze(S,k.providerId,this.providers),s={...s,providerId:k.providerId},P=k.persistFallback;const E=k.providerId,L=Object.prototype.hasOwnProperty.call(g,"models")?g.models:void 0,U=!!this.catalogProviderId&&!!E&&E!==this.catalogProviderId;this.models=Le({current:this.models,fetched:L,providerChanged:U}),(L!==void 0||U)&&(this.catalogProviderId=E||this.catalogProviderId);const C=String(g.selectedModel??"");C&&C!==s.modelId&&(s={...s,modelId:C});const O=Ke(g.presets);O.length>0&&(this.presets=O);const y=String(g.selectedPreset??"");y&&y!==s.agentPreset&&(s={...s,agentPreset:y},this.options.bindingStore.getDshAgentPreset(this.options.aibotSessionId)||this.options.bindingStore.setDshAgentPreset(this.options.aibotSessionId,y))}const I=this.options.bindingStore.getDshSettings(this.options.aibotSessionId),j=(I?.revision??0)!==s.revision,T={};!j&&P&&(I?.providerId??"")!==(s.providerId??"")&&(T.providerId=s.providerId),!j&&(I?.modelId??"")!==s.modelId&&(T.modelId=s.modelId),(T.providerId||T.modelId)&&(s.revision=this.options.bindingStore.updateDshSettings(this.options.aibotSessionId,T)??s.revision,await this.options.bindingStore.flush(),f.warn(m,`replaced unavailable persisted DSH catalog selection provider=${s.providerId} model=${s.modelId}`)),this.applied={runtimeGeneration:this.runtimeGeneration,appliedRevision:s.revision,providerId:s.providerId??$,modelId:s.modelId,modeId:s.modeId,thinking:s.thinking,reasoningEffort:nt(s)},this.runtimeReadiness="ready",this.bridgeCapabilities=g.capabilities??null,o==="profile_bridge"&&c&&!c.sessionCreated&&(c={...c,sessionCreated:!0},this.options.bindingStore.setDshProfileBinding(this.options.aibotSessionId,c),await this.options.bindingStore.flush()),this.settingsState=this.resolveDesiredSettings().revision===s.revision?"applied":"pending",this.settingsErrorCode=null,this.appliedProfileRevision=r,this.personaDirty=this.appliedProfileRevision!==this.profileRevision,f.info(m,`runtime initialized generation=${this.runtimeGeneration} prompt_schema=${u.schemaVersion} prompt_sha256=${u.sha256} prompt_length=${u.length}`),await this.persistCatalogCache(s.providerId??$),this.pushToolbarMeta(),this.settingsState==="pending"&&!this.active&&!this.stopped&&this.rebuildRuntime("settings_changed_during_start")}catch(g){throw this.settingsState="failed",this.settingsErrorCode=String(g?.code??"runtime_initialize_failed"),this.runtimeReadiness=this.settingsErrorCode,this.applied=void 0,this.pushToolbarMeta(),await this.stopRuntime(!0),g}}ensureRuntimeWithRetry(){if(this.runtimeStartPromise)return this.runtimeStartPromise;const e=this.ensureRuntimeWithRetryLoop();this.runtimeStartPromise=e;const t=()=>{this.runtimeStartPromise===e&&(this.runtimeStartPromise=null)};return e.then(t,t),e}async ensureRuntimeWithRetryLoop(){let e;for(let t=1;t<=X;t++)try{await this.ensureRuntime();return}catch(i){e=i;const s=String(i?.code??"");if(this.cancelRequested||!Be(s)||t===X)throw i;f.warn(m,`runtime ensure retry attempt=${t} code=${s||"unknown"}`),this.settingsState="pending",this.settingsErrorCode=s||"runtime_initialize_failed",this.runtimeReadiness=this.settingsErrorCode,this.pushToolbarMeta(),await this.stopRuntime(!0),await ct($e(t))}throw e}onNotification(e,t){const i=ht(t);if(e==="session.event"){const s=_e(t);if(!s){this.onProtocolError(new Error("malformed session.event"));return}const n=this.onSessionEvent(s);this.advanceBridgeAck(i,n);return}if(e==="session.status"){const s=t&&typeof t=="object"?t:{};if(String(s.sessionId??"")===this.runtimeSessionId){this.touchActivity(),this.correlator?.markRootStatus(String(s.status??"")),s.status==="idle"&&this.active&&this.correlator&&f.debug(m,`turn correlation idle admitted=${this.active.admitted} claimed=${this.active.claimed} ended=${this.active.turnEnded} complete=${this.correlator.complete}`);const a=!!this.correlator?.complete;a&&this.finishFromTurnOutcome(),this.advanceBridgeAck(i,a)}else i>0&&this.advanceBridgeAck(i,!1);return}if(e==="subagent.started"||e==="subagent.finished"){this.touchActivity(3);const s=t&&typeof t=="object"?t:{},n=String(s.childSessionId??s.sessionId??"");n&&this.capture?.addChild(n),this.active&&this.callbacks.sendRawEventEnvelope(this.active.inbound.event_id,this.active.inbound.session_id,{type:e,payload:s},e==="subagent.started"?"[subagent started]":"[subagent finished]"),this.advanceBridgeAck(i,!1);return}this.onProtocolError(new Error(`unknown required JSON-RPC notification: ${e}`))}onSessionEvent(e){if(!this.active||!this.correlator)return!1;this.touchActivity(e.type==="tool/call"||e.type==="tool/result"?3:1);const t=be(e);if(t.kind==="unknown"&&!St(e)&&e.ignorable!==!0)return this.onProtocolError(new Error(`unknown required SessionEvent: ${e.type}`)),!1;if(e.sessionId&&e.sessionId!==this.runtimeSessionId)return!1;const i=this.correlator.accept(e);if((e.type==="agent/inbox/spliced"||e.type==="user/message"||e.type==="turn/end")&&f.debug(m,`turn correlation event=${e.type} belongs=${i} admitted=${this.active.admitted} claimed=${this.active.claimed} ended=${this.active.turnEnded}`),e.type==="agent/inbox/spliced"&&this.active.admitted){const s=Q(this.active.inbound,this.injectedMessageIds);for(const n of s.contextIds)this.injectedMessageIds.add(n);s.currentMessageId&&this.injectedMessageIds.add(s.currentMessageId)}return i?vt(e)?(this.flushPendingTextAsThinking(),!1):t.kind==="text"?(t.payload?.committed===!0?(t.payload?.hasToolCall===!0?this.applyCommittedToolStepText(t.text??""):this.applyCommittedText(t.text??""),t.usage&&this.collectCommittedUsage(t.usage,Number(e.seq??e.step??Date.now()))):this.applyTextDelta(t.text??""),!1):t.kind==="thinking"?(this.thinkingEnabled()&&this.callbacks.sendThinking(this.active.inbound.event_id,this.active.inbound.session_id,t.text??""),!1):t.kind==="tool_call"?(this.flushPendingTextAsThinking(),this.toolEventsEnabled()&&this.sendRaw("tool_call",{call_id:t.callId,tool_name:t.name,tool_input:t.input},`[tool] ${t.name}`),!1):t.kind==="tool_result"?(this.toolEventsEnabled()&&this.sendRaw("tool_result",{call_id:t.callId,result:t.output},`[tool result] ${t.callId??""}`),!1):t.kind==="todo"||t.kind==="compaction"?!1:t.kind==="context"?(this.updateContextCapacity(t.payload),!1):t.kind==="usage"?(this.updateContextWindow(t.usage),!1):t.kind==="turn_end"&&this.correlator.complete?(this.finishFromTurnOutcome(),!0):!1:!1}applyTextDelta(e){this.active.pendingText=`${this.active.pendingText??""}${e}`}applyCommittedText(e){const t=this.active;if(t.pendingText=void 0,e.startsWith(t.text))t.text=e;else if(!t.text.startsWith(e)){f.warn(m,`committed assistant text diverged event=${t.inbound.event_id}`);const i=K(e).quotedMessageId;i&&(this.quotedMessageId=i),t.text=t.sentText}this.flushVisibleText(!1)}flushPendingTextAsThinking(){const e=this.active,t=e?.pendingText;!e||!t||(e.pendingText=void 0,this.thinkingEnabled()&&t.trim()&&this.callbacks.sendThinking(e.inbound.event_id,e.inbound.session_id,t),e.lastThinkingText=t)}applyCommittedToolStepText(e){const t=this.active;t&&(t.pendingText=void 0,e.trim()&&t.lastThinkingText!==e&&this.thinkingEnabled()&&(this.callbacks.sendThinking(t.inbound.event_id,t.inbound.session_id,e),t.lastThinkingText=e))}promotePendingTextToVisible(){const e=this.active,t=e?.pendingText;!e||!t||(e.pendingText=void 0,e.text+=t)}flushVisibleText(e,t={}){const i=this.active;if(!i)return;const s=K(i.text);s.quotedMessageId&&(this.quotedMessageId=s.quotedMessageId);const n=s.text.replace(/\[\[quoted_message_id:[^\]]*$/g,""),a=ve(n,{finalize:t.finalizeDsml===!0||e});this.surfaceSuppressedDsmlToolCalls(a.suppressedToolCalls);const d=a.visible;this.observeVisibleTextAfterToolCall(d);let r="";d.startsWith(i.sentText)?r=d.slice(i.sentText.length):(e||t.finalizeDsml)&&(r=d),!(!r&&!e)&&(i.seq+=1,this.callbacks.sendStreamChunk(i.inbound.event_id,i.inbound.session_id,r,i.seq,e,`${i.inbound.event_id}-dsh`,this.quotedMessageId),i.sentText=d)}surfaceSuppressedDsmlToolCalls(e){if(!this.active||e.length===0)return;const t=this.active.dsmlSuppressedKeys??new Set;this.active.dsmlSuppressedKeys=t;for(const i of e){const s=me(i);if(t.has(s)||(t.add(s),this.markToolCallAwaitingFinalText(),f.warn(m,`suppressed leaked DSML tool markup name=${i.name} event=${this.active.inbound.event_id}`),!this.toolEventsEnabled()))continue;let n=i.arguments;try{n=JSON.parse(i.arguments)}catch{}this.sendRaw("tool_call",{call_id:`dsml-${t.size}`,tool_name:i.name,tool_input:n,source:"dsml_text_leak",executed:!1},`[tool] ${i.name}`)}}markToolCallAwaitingFinalText(){const e=this.active;e&&(e.toolCallAwaitingFinalText=!0,e.toolCallVisibleTextLength=e.sentText.length)}observeVisibleTextAfterToolCall(e){const t=this.active;if(!t?.toolCallAwaitingFinalText)return;const i=t.toolCallVisibleTextLength??t.sentText.length;e.slice(i).trim().length!==0&&(t.toolCallAwaitingFinalText=!1,t.toolCallVisibleTextLength=void 0)}collectCommittedUsage(e,t){if(this.activeCommittedUsageSeqs.has(t))return;this.activeCommittedUsageSeqs.add(t);const i=Z(e);this.activeUsage.inputTokens+=i.inputTokens,this.activeUsage.outputTokens+=i.outputTokens,this.activeUsage.cacheReadInputTokens+=i.cacheReadInputTokens,this.activeUsage.cacheCreationInputTokens+=i.cacheCreationInputTokens,this.activeUsage.reasoningTokens+=i.reasoningTokens,this.activeUsageSeq=Math.max(this.activeUsageSeq,t),this.updateContextWindow(i)}updateContextWindow(e){const t=Z(e),i=this.resolveDesiredSettings(),s=this.models.find(a=>a.id===i.modelId),n=this.reportedContextCapacity??s?.contextWindow;if(n&&n>0){const a=t.inputTokens+t.cacheReadInputTokens+t.cacheCreationInputTokens;this.contextWindow={usedTokens:a,totalTokens:n,remainingTokens:Math.max(0,n-a),usedPercentage:a/n*100,remainingPercentage:Math.max(0,100-a/n*100)},this.pushToolbarMeta()}}updateContextCapacity(e){const t=Number(e?.contextWindow);if(!Number.isFinite(t)||t<=0)return;this.reportedContextCapacity=t;const i=this.contextWindow&&typeof this.contextWindow=="object"?this.contextWindow:{},s=Math.max(0,Number(i.usedTokens)||0);this.contextWindow={usedTokens:s,totalTokens:t,remainingTokens:Math.max(0,t-s),usedPercentage:s/t*100,remainingPercentage:Math.max(0,100-s/t*100)},this.pushToolbarMeta()}finishFromTurnOutcome(){if(!this.active)return;this.finishingTurn=!0;const e=this.active.outcome??"completed",t=this.active.outcomeDetail?.trim();e==="completed"?this.finishActive("responded"):e==="aborted"?this.finishActive("canceled"):e==="max-tokens"&&this.active.sentText?this.finishActive("responded","Response truncated at model token limit"):this.finishActive("failed",t?t.toLowerCase().includes(e.toLowerCase())?`Harness turn ended: ${t}`:`Harness turn ended: ${e}: ${t}`:`Harness turn ended: ${e}`)}finishActive(e,t){const i=this.active;if(!i)return;let s=e,n=t;this.finishingTurn=!0,this.clearTimeout(),this.promotePendingTextToVisible(),this.flushVisibleText(!1,{finalizeDsml:!0}),s==="responded"&&i.toolCallAwaitingFinalText&&(s="failed",n="DeepSeek Harness ended after a tool call without returning final assistant text",f.warn(m,`${n} event=${i.inbound.event_id}`)),i.text=i.sentText;const a=s==="failed"&&!!n?.trim();a&&(i.text+=`
1
+ import{createHash as D,randomUUID as x}from"node:crypto";import{EventEmitter as O}from"node:events";import{copyFileSync as he,existsSync as W,mkdirSync as ce}from"node:fs";import{dirname as ue,join as w,resolve as G}from"node:path";import{fileURLToPath as z}from"node:url";import{log as f}from"../../core/log/index.js";import{syncDefaultSkillsToDir as pe}from"../../default-skills/index.js";import{resolveCliPath as ge}from"../../core/util/cli-probe.js";import{DshWireCapture as fe}from"./audit-boundary.js";import{dsmlToolCallKey as me,projectVisibleDsmlText as ve}from"./dsml-text-filter.js";import{mapDshSessionEvent as be,unwrapDshSessionEvent as _e}from"./event-mapper.js";import{buildDshUserPrompt as Q,extractQuotedMessageMarker as K}from"./prompt-builder.js";import{DshProcessRuntime as Se}from"./process-runtime.js";import{DshProfileRuntime as ke}from"./profile-runtime.js";import{createDshWebProfile as Ie}from"./profile-catalog.js";import{listDshPlugins as M,resolveDshPlugin as Te,updateDshPluginIds as we}from"./plugin-manager.js";import{listDshSkills as R,resolveDshSkill as Pe,updateDshSkillIds as ye}from"./skill-manager.js";import{prepareDshSessionPluginOverlay as Ce}from"./session-plugin-overlay.js";import{assertSelectableDshProfileName as Ee,discoverDshBridgeEndpoints as De,listDshProfiles as xe,resolveDshConnectorProfileDataDir as Me,resolveDshSelectedProfileName as Re}from"./profile-resolver.js";import{DshBridgeInstaller as A,errorForDshBridgeReadiness as H}from"./bridge-installer.js";import{ensureDshBridgeReady as Ae,prepareDshProfileBridge as He}from"./profile-supervisor.js";import{DSH_RUNTIME_ENSURE_MAX_ATTEMPTS as X,dshRuntimeEnsureBackoffMs as $e,isRetryableDshRuntimeError as Be}from"./runtime-ensure.js";import{runDshProtocolProbe as Ne}from"./probe.js";import{buildDshSystemPrompt as Fe,describeDshSystemPrompt as qe}from"./system-prompt.js";import{DshActionCoordinator as je}from"./toolbar-actions.js";import{adoptDshProfileModels as Le,adoptLiveDshProviderSelection as Ue,buildDshToolbarMeta as Ve,DEFAULT_DSH_MAX_TOKENS as Oe,DEFAULT_DSH_MODELS as We,DEFAULT_DSH_PRESETS as Ge,DEFAULT_DSH_PROVIDER_ID as $,DEFAULT_DSH_REASONING_EFFORT as ze,DEFAULT_DSH_THINKING as Qe,normalizeDshPresets as Ke,normalizeDshProviders as Xe,normalizeDshReasoningEffort as B,normalizeDshThinking as N,permissionModeFor as J,resolveDshAgentPreset as Y,resolveDshModeId as Je,resolveDshProviderId as Ye,retainRequestedDshProvider as Ze}from"./toolbar-state.js";import{modelsForDshProvider as et,resolveDshCatalogForToolbar as tt,writeDshCatalogCache as it}from"./catalog-cache.js";import{TurnCorrelator as st}from"./turn-correlator.js";import{effectiveDshReasoningEffort as nt}from"./types.js";import{getDshSessionUsageStore as ot,normalizeDshUsage as Z}from"./usage.js";import{toolCallToInvoke as rt}from"../../core/mcp/tools.js";import{isEventTool as at}from"../../core/mcp/event-tool-executor.js";import{isDshBridgedGrixTool as dt}from"./grix-tool-bridge.js";import{DSH_GRIX_PROVIDER_ID as b,buildDshManagedProvider as ee}from"./dsh-provider-config.js";const m="deepseek-harness-adapter",te=20*6e4,ie=6e4,se=9e4,ne=30*6e4,oe="0.1.0-rc.8";class lt extends O{adapterSessionId;cancelFn;constructor(e,t){super(),this.adapterSessionId=e,this.cancelFn=t}cancel(){return this.cancelFn()}}class ti extends O{config;callbacks;type="deepseek-harness";alive=!1;stopped=!1;runtime=null;capture=null;runtimeGeneration=0;runtimeSessionId="";applied;active=null;correlator=null;timeoutTimer=null;hardTimeoutTimer=null;activeTimeoutMs=te;intentionalRuntimeStop=!1;personaDirty=!1;profileRevision=0;appliedProfileRevision=-1;rebuildPromise=null;runtimeStartPromise=null;contextWindow=null;reportedContextCapacity=null;providerQuota=null;settingsState="applied";settingsErrorCode=null;injectedMessageIds=new Set;auditBoundaries=new Map;actionCoordinator=new je;activeWireStart=0;activeUsage=re();activeUsageSeq=-1;activeCommittedUsageSeqs=new Set;permissionHandler=null;quotedMessageId;cancelRequested=!1;runtimeReadiness="unknown";bridgeCapabilities=null;profileDshVersion=null;bridgeAckCursor=0;pendingFinalBridgeAck=null;finishingTurn=!1;pendingApprovals=new Map;options;models=We;providers=[];presets=[...Ge];catalogProviderId;constructor(e,t,i){super(),this.config=e,this.callbacks=t,this.options=i,this.hydrateCatalogFromCache()}async start(){this.alive=!0,this.stopped=!1,this.settingsState="applied",this.settingsErrorCode=null,this.hydrateCatalogFromCache();const e=this.options.bindingStore.get(this.options.aibotSessionId);if(e?.cwd&&this.seedSessionToolbarFromGlobal(),this.syncGrixProvider(),e&&await this.options.bindingStore.flush(),this.resolveIntegrationMode()==="profile_bridge")try{const t=await this.attachSelectedProfile();await this.healBridgeUpdate(t)}catch(t){this.runtimeReadiness=String(t?.code??"bridge_probe_failed"),this.settingsErrorCode=this.runtimeReadiness}else this.runtimeReadiness="ready";this.pushToolbarMeta(),this.refreshProviderQuota(!1)}async stop(){this.stopped=!0,this.clearPendingApprovals("cancelled"),this.clearTimeout(),this.active&&this.finishActive("canceled","connector shutdown"),this.applied=void 0,this.contextWindow=null,this.reportedContextCapacity=null,this.settingsState==="pending"&&(this.settingsState="applied"),this.settingsErrorCode=null,this.pushToolbarMeta(),await this.rebuildPromise?.catch(()=>{}),await this.stopRuntime(!0),await this.usageStore().flush(),this.alive=!1}isAlive(){return this.alive&&!this.stopped}async createSession(e){return this.options.aibotSessionId}async resumeSession(e,t){}async destroySession(e){e===this.options.aibotSessionId&&(this.usageStore().delete(e),await this.usageStore().flush(),await this.stopRuntime(!0))}sendPrompt(e){const t=new lt(e.adapterSessionId,()=>this.cancel(e.adapterSessionId));return queueMicrotask(()=>t.emit("done",{status:"failed",error:"Use deliverInboundEvent for platform prompts"})),t}async cancel(e){await this.cancelActive("user canceled")}deliverInboundEvent(e){if(!this.isAlive()){this.failEvent(e,"adapter is not alive");return}if(e.attachments_json&&e.attachments_json!=="[]"){this.failEvent(e,"DeepSeek Harness first version supports text only; attachments must be materialized in the bound workspace");return}if(this.active){this.failEvent(e,"concurrent prompt rejected");return}this.runInboundEvent(e)}deliverStopEvent(e,t){this.active&&e===this.active.inbound.event_id&&(t&&t!==this.active.inbound.session_id||this.cancelActive("user canceled"))}async handleLocalAction(e){if(!["set_model","set_mode","set_provider","set_thinking","set_reasoning_effort","set_preset","set_profile","create_profile","get_session_usage","get_rate_limits","dsh_bridge_status","dsh_install_bridge","dsh_list_plugins","dsh_enable_plugin","dsh_disable_plugin","dsh_refresh_plugins","dsh_list_skills","dsh_enable_skill","dsh_disable_skill","dsh_list_mcp","dsh_list_tools","dsh_list_jobs","dsh_list_goals","exec_approve","exec_reject","permission_approve","permission_reject"].includes(e.action_type))return{handled:!1,kind:""};const t=await this.actionCoordinator.run(e.action_id,()=>this.executeLocalAction(e));return this.callbacks.sendLocalActionResult(e.action_id,t.status,t.result,t.errorCode,t.errorMsg),{handled:!0,kind:e.action_type}}setPermissionHandler(e){this.permissionHandler=e}async ping(e){return this.isAlive()&&(!this.runtime||this.runtime.isConnected())}getStatus(){return{alive:this.isAlive()&&!!this.runtime,busy:!!this.active||this.intentionalRuntimeStop||!!this.rebuildPromise||!!this.runtimeStartPromise,backgroundBusy:!1,sessions:this.runtime?1:0,details:{runtimeGeneration:this.runtimeGeneration,runtimeSessionId:this.runtimeSessionId||void 0}}}getActiveEventIds(){return this.active?[this.active.inbound.event_id]:[]}takeAuditBoundary(e){const t=this.auditBoundaries.get(e);return this.auditBoundaries.delete(e),t}clearActiveEventForShutdown(){this.active=null,this.correlator=null,this.clearTimeout()}getMcpConfig(){return null}async hasBackgroundWork(){return this.runtime?.hasBackgroundWork()??!1}onAgentProfileChanged(){this.profileRevision+=1,this.personaDirty=!0,!this.active&&this.runtime&&this.rebuildRuntime("persona_changed")}updateProviderQuotaSnapshot(e){this.providerQuota=e??null;const t=this.options.bindingStore.get(this.options.aibotSessionId);this.callbacks.sendUpdateBindingCard(this.options.aibotSessionId,this.stopped?"stopped":this.active?"busy":"ready",t?.cwd,{provider_quota:this.providerQuota})}async probe(e={}){const t=this.resolveIntegrationMode(),i=t==="embedded_jsonrpc"?this.config.command||"dsh-jsonrpc-agent":"dsh",s=await ge(i),n=!!s;let a={ok:e.conversation!==!0,latency:null};if(n&&e.conversation===!0&&s)if(t==="embedded_jsonrpc")try{const d=await Ne({command:s,args:this.config.args,cordisPath:G(this.options.cordisPath??z(new URL("./grix-jsonrpc.cordis.yml",import.meta.url))),settings:this.resolveDesiredSettings(),timeoutMs:e.timeoutMs});a={ok:!0,latency:d.latencyMs,serverName:d.serverName,serverVersion:d.serverVersion}}catch(d){a={ok:!1,latency:null,error:this.redactError(d)}}else{const d=Date.now();try{const r=new A({command:"dsh",dshHome:this.options.dshHome??this.config.env?.DSH_HOME,profileName:this.resolveSelectedProfile()}),p=await Ae({installer:r,autoStart:!1}),u=H(p);if(u)throw u;const o=De(p.identity);if(o.length===0)throw Object.assign(new Error(`No live Grix Bridge endpoint in DSH profile "${p.identity.profileName}"`),{code:"bridge_missing"});a={ok:!0,latency:Date.now()-d,serverName:"grix-dsh-profile-bridge",serverVersion:o[0].bridgeVersion}}catch(r){a={ok:!1,latency:null,error:this.redactError(r)}}}return{cli:{command:i,installed:n,path:s,version:null,...n?{}:{error:{code:"cli_not_found",message:`${i} not found`}}},conversation:{attempted:e.conversation===!0,ok:a.ok,latency_ms:a.latency,...a.ok?{}:{error:{code:"conversation_failed",message:a.error??"initialize/shutdown probe failed"}}},config:{model:this.resolveDesiredSettings().modelId,base_url:this.config.env?.DEEPSEEK_BASE_URL??null,source:{model:"config",base_url:this.config.env?.DEEPSEEK_BASE_URL?"env":"unknown"},extras:{protocol:t==="profile_bridge"?"grix-dsh/1":"jsonrpc-v1",profile:this.resolveSelectedProfile(),serverName:a.serverName,serverVersion:a.serverVersion}},process:{started:!!this.runtime,alive:this.runtime?.isConnected()??!1,busy:!!this.active}}}async runInboundEvent(e){const t={inbound:e,admitted:!1,claimed:!1,turnEnded:!1,rootIdle:!1,text:"",sentText:"",seq:0,startedAt:Date.now()};this.active=t,this.correlator=new st(t),this.activeUsage=re(),this.activeUsageSeq=-1,this.activeCommittedUsageSeqs.clear(),this.quotedMessageId=void 0,this.cancelRequested=!1,this.emit("eventStarted",e.event_id,e.session_id);try{if(await this.ensureRuntimeWithRetry(),this.cancelRequested||this.active!==t)return;this.activeWireStart=this.capture?.offset??0;const i=Q(e,this.injectedMessageIds);this.startTimeout(e.timeoutMs);const s=await this.runtime.client.prompt({sessionId:this.runtimeSessionId,contentBlocks:[{type:"text",text:i.text}]});if(!s?.messageId)throw Object.assign(new Error("session/prompt response missing messageId"),{code:"protocol_invalid_prompt_result"});this.correlator.setPromptMessageId(s.messageId)}catch(i){const s=this.redactError(i,e.content);this.finishActive(this.cancelRequested?"canceled":"failed",this.cancelRequested?"user canceled":s)}}async ensureRuntime(){if(this.stopped)throw new Error("adapter stopped");if(this.runtime)return;this.syncGrixProvider();const t=this.options.bindingStore.get(this.options.aibotSessionId)?.cwd;if(!t)throw Object.assign(new Error("Session binding missing. Open a workspace first."),{code:"binding_missing"});const i=this.projectConnectorSkills();let s=this.resolveDesiredSettings();const n=this.options.bindingStore.getDshSettings(this.options.aibotSessionId),a={};n?.modelId||(a.modelId=s.modelId),!n?.providerId&&s.providerId&&(a.providerId=s.providerId),n?.thinking||(a.thinking=s.thinking),n?.reasoningEffort||(a.reasoningEffort=s.reasoningEffort),Object.keys(a).length>0&&(this.options.bindingStore.updateDshSettings(this.options.aibotSessionId,a),await this.options.bindingStore.flush(),s=this.resolveDesiredSettings());const d=this.callbacks.getAgentProfile(),r=this.profileRevision,p=Fe({...d,grixSessionId:this.options.aibotSessionId,agentId:this.callbacks.getAgentId()}),u=qe(p);this.runtimeGeneration+=1;const o=this.resolveIntegrationMode(),l=this.resolveSelectedProfile();if(o==="profile_bridge")try{await this.ensureProfileReadyForChat(),this.pushToolbarMeta()}catch(g){throw this.settingsState="failed",this.settingsErrorCode=String(g?.code??"runtime_initialize_failed"),this.runtimeReadiness=this.settingsErrorCode,this.pushToolbarMeta(),g}let c=o==="profile_bridge"?this.options.bindingStore.getDshProfileBinding(this.options.aibotSessionId,l):void 0;o==="profile_bridge"&&!c&&(c={profileName:l,sessionId:pt(this.options.aibotSessionId),sessionCreated:!1,eventCursor:0},this.options.bindingStore.setDshProfileBinding(this.options.aibotSessionId,c),await this.options.bindingStore.flush()),this.runtimeSessionId=c?.sessionId??ut(this.options.aibotSessionId,this.runtimeGeneration);const v=this.profileDataDir(l),F=G(this.options.cordisPath??z(new URL("./grix-jsonrpc.cordis.yml",import.meta.url))),q=Ce({dshHome:this.options.dshHome??this.config.env?.DSH_HOME,profileName:l,pluginIds:s.pluginIds??[],overlayId:D("sha256").update(this.options.aibotSessionId).digest("hex").slice(0,24),baseCordisPath:F}),le=w(v,"audit-source",`${this.runtimeSessionId}.jsonl`);this.capture=new fe(le);const _=o==="embedded_jsonrpc"?new Se({command:this.config.command||"dsh-jsonrpc-agent",args:this.config.args,cwd:t,cordisPath:q.embeddedCordisPath??F,home:v,sessionRoot:w(v,"sessions"),skillsDir:i,env:this.config.env,systemPrompt:p,settings:s,capture:this.capture,maxLineBytes:this.options.maxLineBytes}):new ke({dshHome:this.options.dshHome??this.config.env?.DSH_HOME,profileName:l,cwd:t,ownerId:`${this.callbacks.getAgentId()}:${this.options.aibotSessionId}`,sessionId:this.runtimeSessionId,resumeSession:c?.sessionCreated===!0,lastAckCursor:c?.eventCursor??0,systemPrompt:p,settings:s,skillsDir:i,pluginOverlayPath:q.bridgeOverlayPath,managedProvider:s.providerId===b?ee(this.options.provider??{}):void 0,capture:this.capture,maxFrameBytes:this.options.maxLineBytes,onApproval:g=>this.handleBridgeApproval(g),onToolInvoke:(g,P,I)=>this.invokeGrixTool(g,P,I),onCursorAck:g=>{!c||g<=c.eventCursor||(c={...c,eventCursor:g},this.options.bindingStore.setDshProfileBinding(this.options.aibotSessionId,c))}});this.runtime=_,this.bridgeAckCursor=c?.eventCursor??0,this.pendingFinalBridgeAck=null,this.finishingTurn=!1,this.intentionalRuntimeStop=!1;try{const g=await _.start();if(!_.isConnected())throw Object.assign(new Error("Harness runtime disconnected immediately after initialize"),{code:"runtime_exited"});_.client?.on("notification",(S,k)=>this.onNotification(S,k)),_.client?.on("protocolError",S=>this.onProtocolError(S)),_.onExit(()=>this.onRuntimeExit()),_.client?.activateNotifications?.();let P=!1;if(o==="profile_bridge"){const S=Xe(g.providers),k=Ue({requestedProviderId:s.providerId,liveProviders:S,liveSelectedProvider:String(g.selectedProvider??"")});this.providers=Ze(S,k.providerId,this.providers),s={...s,providerId:k.providerId},P=k.persistFallback;const C=k.providerId,L=Object.prototype.hasOwnProperty.call(g,"models")?g.models:void 0,U=!!this.catalogProviderId&&!!C&&C!==this.catalogProviderId;this.models=Le({current:this.models,fetched:L,providerChanged:U}),(L!==void 0||U)&&(this.catalogProviderId=C||this.catalogProviderId);const E=String(g.selectedModel??"");E&&E!==s.modelId&&(s={...s,modelId:E});const V=Ke(g.presets);V.length>0&&(this.presets=V);const y=String(g.selectedPreset??"");y&&y!==s.agentPreset&&(s={...s,agentPreset:y},this.options.bindingStore.getDshAgentPreset(this.options.aibotSessionId)||this.options.bindingStore.setDshAgentPreset(this.options.aibotSessionId,y))}const I=this.options.bindingStore.getDshSettings(this.options.aibotSessionId),j=(I?.revision??0)!==s.revision,T={};!j&&P&&(I?.providerId??"")!==(s.providerId??"")&&(T.providerId=s.providerId),!j&&(I?.modelId??"")!==s.modelId&&(T.modelId=s.modelId),(T.providerId||T.modelId)&&(s.revision=this.options.bindingStore.updateDshSettings(this.options.aibotSessionId,T)??s.revision,await this.options.bindingStore.flush(),f.warn(m,`replaced unavailable persisted DSH catalog selection provider=${s.providerId} model=${s.modelId}`)),this.applied={runtimeGeneration:this.runtimeGeneration,appliedRevision:s.revision,providerId:s.providerId??$,modelId:s.modelId,modeId:s.modeId,thinking:s.thinking,reasoningEffort:nt(s)},this.runtimeReadiness="ready",this.bridgeCapabilities=g.capabilities??null,o==="profile_bridge"&&c&&!c.sessionCreated&&(c={...c,sessionCreated:!0},this.options.bindingStore.setDshProfileBinding(this.options.aibotSessionId,c),await this.options.bindingStore.flush()),this.settingsState=this.resolveDesiredSettings().revision===s.revision?"applied":"pending",this.settingsErrorCode=null,this.appliedProfileRevision=r,this.personaDirty=this.appliedProfileRevision!==this.profileRevision,f.info(m,`runtime initialized generation=${this.runtimeGeneration} prompt_schema=${u.schemaVersion} prompt_sha256=${u.sha256} prompt_length=${u.length}`),await this.persistCatalogCache(s.providerId??$),this.pushToolbarMeta(),this.settingsState==="pending"&&!this.active&&!this.stopped&&this.rebuildRuntime("settings_changed_during_start")}catch(g){throw this.settingsState="failed",this.settingsErrorCode=String(g?.code??"runtime_initialize_failed"),this.runtimeReadiness=this.settingsErrorCode,this.applied=void 0,this.pushToolbarMeta(),await this.stopRuntime(!0),g}}ensureRuntimeWithRetry(){if(this.runtimeStartPromise)return this.runtimeStartPromise;const e=this.ensureRuntimeWithRetryLoop();this.runtimeStartPromise=e;const t=()=>{this.runtimeStartPromise===e&&(this.runtimeStartPromise=null)};return e.then(t,t),e}async ensureRuntimeWithRetryLoop(){let e;for(let t=1;t<=X;t++)try{await this.ensureRuntime();return}catch(i){e=i;const s=String(i?.code??"");if(this.cancelRequested||!Be(s)||t===X)throw i;f.warn(m,`runtime ensure retry attempt=${t} code=${s||"unknown"}`),this.settingsState="pending",this.settingsErrorCode=s||"runtime_initialize_failed",this.runtimeReadiness=this.settingsErrorCode,this.pushToolbarMeta(),await this.stopRuntime(!0),await ct($e(t))}throw e}onNotification(e,t){const i=ht(t);if(e==="session.event"){const s=_e(t);if(!s){this.onProtocolError(new Error("malformed session.event"));return}const n=this.onSessionEvent(s);this.advanceBridgeAck(i,n);return}if(e==="session.status"){const s=t&&typeof t=="object"?t:{};if(String(s.sessionId??"")===this.runtimeSessionId){this.touchActivity(),this.correlator?.markRootStatus(String(s.status??"")),s.status==="idle"&&this.active&&this.correlator&&f.debug(m,`turn correlation idle admitted=${this.active.admitted} claimed=${this.active.claimed} ended=${this.active.turnEnded} complete=${this.correlator.complete}`);const a=!!this.correlator?.complete;a&&this.finishFromTurnOutcome(),this.advanceBridgeAck(i,a)}else i>0&&this.advanceBridgeAck(i,!1);return}if(e==="subagent.started"||e==="subagent.finished"){this.touchActivity(3);const s=t&&typeof t=="object"?t:{},n=String(s.childSessionId??s.sessionId??"");n&&this.capture?.addChild(n),this.active&&this.callbacks.sendRawEventEnvelope(this.active.inbound.event_id,this.active.inbound.session_id,{type:e,payload:s},e==="subagent.started"?"[subagent started]":"[subagent finished]"),this.advanceBridgeAck(i,!1);return}this.onProtocolError(new Error(`unknown required JSON-RPC notification: ${e}`))}onSessionEvent(e){if(!this.active||!this.correlator)return!1;this.touchActivity(e.type==="tool/call"||e.type==="tool/result"?3:1);const t=be(e);if(t.kind==="unknown"&&!St(e)&&e.ignorable!==!0)return this.onProtocolError(new Error(`unknown required SessionEvent: ${e.type}`)),!1;if(e.sessionId&&e.sessionId!==this.runtimeSessionId)return!1;const i=this.correlator.accept(e);if((e.type==="agent/inbox/spliced"||e.type==="user/message"||e.type==="turn/end")&&f.debug(m,`turn correlation event=${e.type} belongs=${i} admitted=${this.active.admitted} claimed=${this.active.claimed} ended=${this.active.turnEnded}`),e.type==="agent/inbox/spliced"&&this.active.admitted){const s=Q(this.active.inbound,this.injectedMessageIds);for(const n of s.contextIds)this.injectedMessageIds.add(n);s.currentMessageId&&this.injectedMessageIds.add(s.currentMessageId)}return i?vt(e)?(this.flushPendingTextAsThinking(),!1):t.kind==="text"?(t.payload?.committed===!0?(t.payload?.hasToolCall===!0?this.applyCommittedToolStepText(t.text??""):this.applyCommittedText(t.text??""),t.usage&&this.collectCommittedUsage(t.usage,Number(e.seq??e.step??Date.now()))):this.applyTextDelta(t.text??""),!1):t.kind==="thinking"?(this.thinkingEnabled()&&this.callbacks.sendThinking(this.active.inbound.event_id,this.active.inbound.session_id,t.text??""),!1):t.kind==="tool_call"?(this.flushPendingTextAsThinking(),this.toolEventsEnabled()&&this.sendRaw("tool_call",{call_id:t.callId,tool_name:t.name,tool_input:t.input},`[tool] ${t.name}`),!1):t.kind==="tool_result"?(this.toolEventsEnabled()&&this.sendRaw("tool_result",{call_id:t.callId,result:t.output},`[tool result] ${t.callId??""}`),!1):t.kind==="todo"||t.kind==="compaction"?!1:t.kind==="context"?(this.updateContextCapacity(t.payload),!1):t.kind==="usage"?(this.updateContextWindow(t.usage),!1):t.kind==="turn_end"&&this.correlator.complete?(this.finishFromTurnOutcome(),!0):!1:!1}applyTextDelta(e){this.active.pendingText=`${this.active.pendingText??""}${e}`}applyCommittedText(e){const t=this.active;if(t.pendingText=void 0,e.startsWith(t.text))t.text=e;else if(!t.text.startsWith(e)){f.warn(m,`committed assistant text diverged event=${t.inbound.event_id}`);const i=K(e).quotedMessageId;i&&(this.quotedMessageId=i),t.text=t.sentText}this.flushVisibleText(!1)}flushPendingTextAsThinking(){const e=this.active,t=e?.pendingText;!e||!t||(e.pendingText=void 0,this.thinkingEnabled()&&t.trim()&&this.callbacks.sendThinking(e.inbound.event_id,e.inbound.session_id,t),e.lastThinkingText=t)}applyCommittedToolStepText(e){const t=this.active;t&&(t.pendingText=void 0,e.trim()&&t.lastThinkingText!==e&&this.thinkingEnabled()&&(this.callbacks.sendThinking(t.inbound.event_id,t.inbound.session_id,e),t.lastThinkingText=e))}promotePendingTextToVisible(){const e=this.active,t=e?.pendingText;!e||!t||(e.pendingText=void 0,e.text+=t)}flushVisibleText(e,t={}){const i=this.active;if(!i)return;const s=K(i.text);s.quotedMessageId&&(this.quotedMessageId=s.quotedMessageId);const n=s.text.replace(/\[\[quoted_message_id:[^\]]*$/g,""),a=ve(n,{finalize:t.finalizeDsml===!0||e});this.surfaceSuppressedDsmlToolCalls(a.suppressedToolCalls);const d=a.visible;this.observeVisibleTextAfterToolCall(d);let r="";d.startsWith(i.sentText)?r=d.slice(i.sentText.length):(e||t.finalizeDsml)&&(r=d),!(!r&&!e)&&(i.repliedViaTool||(i.seq+=1,this.callbacks.sendStreamChunk(i.inbound.event_id,i.inbound.session_id,r,i.seq,e,`${i.inbound.event_id}-dsh`,this.quotedMessageId)),i.sentText=d)}surfaceSuppressedDsmlToolCalls(e){if(!this.active||e.length===0)return;const t=this.active.dsmlSuppressedKeys??new Set;this.active.dsmlSuppressedKeys=t;for(const i of e){const s=me(i);if(t.has(s)||(t.add(s),this.markToolCallAwaitingFinalText(),f.warn(m,`suppressed leaked DSML tool markup name=${i.name} event=${this.active.inbound.event_id}`),!this.toolEventsEnabled()))continue;let n=i.arguments;try{n=JSON.parse(i.arguments)}catch{}this.sendRaw("tool_call",{call_id:`dsml-${t.size}`,tool_name:i.name,tool_input:n,source:"dsml_text_leak",executed:!1},`[tool] ${i.name}`)}}markToolCallAwaitingFinalText(){const e=this.active;e&&(e.toolCallAwaitingFinalText=!0,e.toolCallVisibleTextLength=e.sentText.length)}observeVisibleTextAfterToolCall(e){const t=this.active;if(!t?.toolCallAwaitingFinalText)return;const i=t.toolCallVisibleTextLength??t.sentText.length;e.slice(i).trim().length!==0&&(t.toolCallAwaitingFinalText=!1,t.toolCallVisibleTextLength=void 0)}collectCommittedUsage(e,t){if(this.activeCommittedUsageSeqs.has(t))return;this.activeCommittedUsageSeqs.add(t);const i=Z(e);this.activeUsage.inputTokens+=i.inputTokens,this.activeUsage.outputTokens+=i.outputTokens,this.activeUsage.cacheReadInputTokens+=i.cacheReadInputTokens,this.activeUsage.cacheCreationInputTokens+=i.cacheCreationInputTokens,this.activeUsage.reasoningTokens+=i.reasoningTokens,this.activeUsageSeq=Math.max(this.activeUsageSeq,t),this.updateContextWindow(i)}updateContextWindow(e){const t=Z(e),i=this.resolveDesiredSettings(),s=this.models.find(a=>a.id===i.modelId),n=this.reportedContextCapacity??s?.contextWindow;if(n&&n>0){const a=t.inputTokens+t.cacheReadInputTokens+t.cacheCreationInputTokens;this.contextWindow={usedTokens:a,totalTokens:n,remainingTokens:Math.max(0,n-a),usedPercentage:a/n*100,remainingPercentage:Math.max(0,100-a/n*100)},this.pushToolbarMeta()}}updateContextCapacity(e){const t=Number(e?.contextWindow);if(!Number.isFinite(t)||t<=0)return;this.reportedContextCapacity=t;const i=this.contextWindow&&typeof this.contextWindow=="object"?this.contextWindow:{},s=Math.max(0,Number(i.usedTokens)||0);this.contextWindow={usedTokens:s,totalTokens:t,remainingTokens:Math.max(0,t-s),usedPercentage:s/t*100,remainingPercentage:Math.max(0,100-s/t*100)},this.pushToolbarMeta()}finishFromTurnOutcome(){if(!this.active)return;this.finishingTurn=!0;const e=this.active.outcome??"completed",t=this.active.outcomeDetail?.trim();e==="completed"?this.finishActive("responded"):e==="aborted"?this.finishActive("canceled"):e==="max-tokens"&&this.active.sentText?this.finishActive("responded","Response truncated at model token limit"):this.finishActive("failed",t?t.toLowerCase().includes(e.toLowerCase())?`Harness turn ended: ${t}`:`Harness turn ended: ${e}: ${t}`:`Harness turn ended: ${e}`)}finishActive(e,t){const i=this.active;if(!i)return;let s=e,n=t;this.finishingTurn=!0,this.clearTimeout(),this.promotePendingTextToVisible(),this.flushVisibleText(!1,{finalizeDsml:!0}),s==="responded"&&i.toolCallAwaitingFinalText&&!i.repliedViaTool&&(s="failed",n="DeepSeek Harness ended after a tool call without returning final assistant text",f.warn(m,`${n} event=${i.inbound.event_id}`)),i.text=i.sentText;const a=s==="failed"&&!!n?.trim();a&&(i.text+=`
2
2
 
3
- Error: ${n}`,this.flushVisibleText(!1,{finalizeDsml:!0})),s==="responded"&&this.activeUsageSeq>=0&&(this.usageStore().commit(i.inbound.session_id,this.runtimeSessionId,this.activeUsageSeq,this.applied?.modelId??this.resolveDesiredSettings().modelId,this.activeUsage),this.usageStore().flush()),i.inbound.audit?.enabled&&this.capture&&this.auditBoundaries.set(i.inbound.event_id,this.capture.boundary({runtimeSessionId:this.runtimeSessionId,rootSessionId:this.runtimeSessionId,startOffset:this.activeWireStart,turn:i.turn,messageId:i.messageId}));const d=this.personaDirty&&!!this.runtime,r=!!this.runtime&&!!this.applied&&this.applied.appliedRevision!==this.resolveDesiredSettings().revision;d&&this.emit("pauseIntake","barrier"),this.active=null,this.correlator=null;const p=`${i.inbound.event_id}-dsh`,u=(o,l,c=!1)=>{this.callbacks.sendEventResult(i.inbound.event_id,o,l,c),this.emit("eventDone",i.inbound.event_id),d?this.rebuildRuntime("persona_changed"):r&&this.rebuildRuntime("settings_changed")};this.callbacks.sendFinalStreamChunkReliable(i.inbound.event_id,i.inbound.session_id,p).then(async()=>{await this.flushPendingFinalBridgeAck(!0),u(s,n,a)},async o=>{await this.flushPendingFinalBridgeAck(!1),u(s==="responded"?"failed":s,s==="responded"?`Final output delivery failed: ${this.redactError(o,i.inbound.content)}`:n)})}advanceBridgeAck(e,t){if(!(e<=0)){if(t||this.finishingTurn||this.pendingFinalBridgeAck!==null){this.pendingFinalBridgeAck=Math.max(this.pendingFinalBridgeAck??0,e);return}this.ackBridgeCursor(e)}}async flushPendingFinalBridgeAck(e){const t=this.pendingFinalBridgeAck;this.pendingFinalBridgeAck=null,this.finishingTurn=!1,!(!e||t===null)&&await this.ackBridgeCursor(t)}async ackBridgeCursor(e){if(e<=this.bridgeAckCursor)return;const t=this.runtime?.client?.ack;if(!t){this.bridgeAckCursor=Math.max(this.bridgeAckCursor,e);return}try{await t.call(this.runtime.client,e),this.bridgeAckCursor=Math.max(this.bridgeAckCursor,e)}catch(i){this.onProtocolError(i instanceof Error?i:new Error(String(i)))}}async cancelActive(e){this.active&&(this.cancelRequested=!0,this.clearPendingApprovals("cancelled"),this.resolveIntegrationMode()==="embedded_jsonrpc"?(this.contextWindow=null,this.reportedContextCapacity=null,this.applied=void 0,this.settingsState="applied",this.pushToolbarMeta(),this.runtimeStartPromise&&this.runtime&&await this.runtime.terminate().catch(()=>{}),await this.runtimeStartPromise?.catch(()=>{}),await this.stopRuntime(!0)):(await this.runtimeStartPromise?.catch(()=>{}),await this.runtime?.cancel(this.runtimeSessionId).catch(()=>{}),this.runtime&&!this.runtime.isConnected()&&await this.stopRuntime(!0)),this.finishActive("canceled",e))}async handleBridgeApproval(e){const t=this.permissionHandler,i=String(e.interactionId??e.callId??x());if(t)try{return await t({adapterSessionId:this.options.aibotSessionId,requestId:i,description:String(e.reason??`Allow ${String(e.toolName??"operation")}?`),options:[{id:"allow_once",label:"Allow once",isAllow:!0},{id:"reject",label:"Reject",isAllow:!1}]})==="allow_once"?"allowed-once":"rejected"}catch{return"cancelled"}const s=this.active;return s?(this.callbacks.sendPermissionCard({eventId:s.inbound.event_id,sessionId:s.inbound.session_id,approvalId:i,toolName:String(e.toolName??"operation"),toolTitle:String(e.reason??`Allow ${String(e.toolName??"operation")}?`)}),new Promise(n=>{const a=setTimeout(()=>{this.pendingApprovals.delete(i),n("unavailable")},3e5);a.unref?.(),this.pendingApprovals.set(i,{resolve:n,timer:a})})):"unavailable"}async invokeGrixTool(e,t,i){if(!dt(e))throw Object.assign(new Error(`grix tool "${e}" is not exposed to DSH`),{code:"capability_unavailable"});if(at(e)){if(!this.callbacks.eventToolInvoke)throw Object.assign(new Error(`grix event tool "${e}" has no connector-side runner`),{code:"capability_unavailable"});return this.callbacks.eventToolInvoke(e,t)}if(!this.callbacks.agentInvoke)throw Object.assign(new Error(`grix tool "${e}" has no connector-side action runner`),{code:"capability_unavailable"});const s=rt(e,t);return this.callbacks.agentInvoke(s.action,s.params,i??s.timeoutMs)}projectConnectorSkills(){const e=w(this.options.dataRoot,"dsh-session-skills"),t=pe(e);return t.length>0&&f.info(m,`Synced connector skills to ${e}: [${t.join(", ")}]`),e}rebuildRuntime(e){if(this.stopped||this.active)return Promise.resolve();if(this.rebuildPromise)return this.rebuildPromise;const t=(async()=>{this.emit("pauseIntake","barrier"),this.contextWindow=null,this.reportedContextCapacity=null,this.applied=void 0,this.settingsState="pending",this.pushToolbarMeta();try{await this.stopRuntime(!0),await this.ensureRuntime()}catch(i){f.warn(m,`${e} rebuild failed: ${this.redactError(i)}`)}finally{this.emit("resumeIntake","barrier")}})();return this.rebuildPromise=t.finally(()=>{this.rebuildPromise=null;const i=this.resolveDesiredSettings().revision;!this.stopped&&!this.active&&(this.personaDirty||this.applied&&this.applied.appliedRevision!==i)&&this.rebuildRuntime("coalesced_state_changed")}),this.rebuildPromise}async stopRuntime(e){const t=this.runtime;t&&(this.intentionalRuntimeStop=e,this.runtime=null,await t.shutdown().catch(()=>t.terminate()),this.capture?.close(),this.capture=null,this.intentionalRuntimeStop=!1)}onRuntimeExit(){this.intentionalRuntimeStop||this.stopped||(this.runtime=null,this.capture?.close(),this.capture=null,this.applied=void 0,this.contextWindow=null,this.reportedContextCapacity=null,this.settingsState="failed",this.settingsErrorCode="runtime_exited",this.pushToolbarMeta(),this.active&&this.finishActive("failed","Harness runtime exited; prompt was not replayed"),this.emit("exit",1))}onProtocolError(e){if(this.stopped||!this.runtime&&!this.active)return;const t=this.redactError(e,this.active?.inbound.content);this.clearPendingApprovals("unavailable"),this.contextWindow=null,this.reportedContextCapacity=null,this.settingsState="failed",this.settingsErrorCode="protocol_error",this.pushToolbarMeta();const i=this.runtime;this.runtime=null,this.intentionalRuntimeStop=!0,i?.client?.close(e),this.active&&this.finishActive("failed",`Harness protocol error: ${t}`),i?.terminate().finally(()=>{this.intentionalRuntimeStop=!1}),this.emit("exit",1)}async executeLocalAction(e){const t=e.params??{},i=String(t.session_id??"");if(!i||i!==this.options.aibotSessionId)return{status:"failed",errorCode:"binding_missing",errorMsg:"Session binding missing"};if(["exec_approve","exec_reject","permission_approve","permission_reject"].includes(e.action_type)){const o=String(t.approval_command_id??t.approval_id??t.request_id??"").trim(),l=this.pendingApprovals.get(o);if(!l)return{status:"failed",errorCode:"unknown_or_expired_approval_id",errorMsg:"That DSH approval request is no longer pending"};clearTimeout(l.timer),this.pendingApprovals.delete(o);const c=e.action_type==="exec_approve"||e.action_type==="permission_approve";return l.resolve(c?"allowed-once":"rejected"),{status:"ok",result:{approval_id:o,decision:c?"allow-once":"deny"}}}if(e.action_type==="get_session_usage")return{status:"ok",result:{adapterType:"deepseek-harness",available:!0,dsh_profile:this.resolveSelectedProfile(),...this.usageStore().get(i)}};if(e.action_type==="get_rate_limits"){this.providerQuota=null,this.pushToolbarMeta();try{this.providerQuota=await this.callbacks.queryProviderQuota(!0)??{provider:"deepseek",providerLabel:"DeepSeek",success:!1,error:"unavailable"}}catch(o){this.providerQuota={provider:"deepseek",providerLabel:"DeepSeek",success:!1,error:this.redactError(o)}}return this.pushToolbarMeta(),{status:"ok",result:{sampledAt:new Date().toISOString(),contextWindow:this.contextWindow,providerQuota:this.providerQuota}}}if(e.action_type==="dsh_bridge_status"||e.action_type==="dsh_install_bridge"){if(this.resolveIntegrationMode()!=="profile_bridge")return{status:"unsupported",errorCode:"capability_unavailable",errorMsg:"Bridge management requires Profile Bridge mode"};if(this.active||this.runtime)return{status:"failed",errorCode:"worker_busy",errorMsg:"Stop the active DSH session before changing its Profile plugin"};try{const o=new A({command:"dsh",dshHome:this.options.dshHome??this.config.env?.DSH_HOME,profileName:this.resolveSelectedProfile()}),l=e.action_type==="dsh_install_bridge"?await o.install():await o.status();return this.runtimeReadiness=l.readiness,this.settingsErrorCode=l.readiness==="ready"?null:l.readiness,this.pushToolbarMeta(),{status:"ok",result:bt(l)}}catch(o){const l=String(o?.code??"bridge_install_failed");return this.runtimeReadiness=l,this.settingsErrorCode=l,this.pushToolbarMeta(),{status:"failed",errorCode:l,errorMsg:this.redactError(o)}}}if(e.action_type==="dsh_list_plugins"||e.action_type==="dsh_refresh_plugins"||e.action_type==="dsh_enable_plugin"||e.action_type==="dsh_disable_plugin")return this.executePluginAction(e.action_type,t,i);if(e.action_type==="dsh_list_skills"||e.action_type==="dsh_enable_skill"||e.action_type==="dsh_disable_skill")return this.executeSkillAction(e.action_type,t,i);const n={dsh_list_mcp:"mcp/list",dsh_list_tools:"tools/list",dsh_list_jobs:"jobs/list",dsh_list_goals:"goals/list"}[e.action_type];if(n){if(this.resolveIntegrationMode()!=="profile_bridge")return{status:"unsupported",errorCode:"capability_unavailable",errorMsg:"DSH resources require Profile Bridge mode"};if(this.active)return{status:"failed",errorCode:"worker_busy",errorMsg:"Cannot query DSH resources during an active turn"};try{return await this.ensureRuntimeWithRetry(),{status:"ok",result:await this.runtime?.client?.call(n,{cwd:this.options.bindingStore.get(i)?.cwd})}}catch(o){const l=String(o?.code??"resource_query_failed");return{status:l==="capability_unavailable"?"unsupported":"failed",errorCode:l,errorMsg:this.redactError(o)}}}if(e.action_type==="set_profile"||e.action_type==="create_profile"){if(this.active)return{status:"failed",errorCode:"worker_busy",errorMsg:"Cannot change DeepSeek Harness Profile during an active turn"};if(!this.options.bindingStore.get(i))return{status:"failed",errorCode:"binding_missing",errorMsg:"Session binding missing. Open a workspace first."};let o;try{o=Ce(String(t.profile_id??t.dsh_profile??t.profile_name??t.name??""))}catch(c){return{status:"failed",errorCode:"profile_invalid",errorMsg:this.redactError(c)}}if(this.options.bindingStore.isDshProfileLocked(i)){const c=this.resolveSelectedProfile();return e.action_type==="create_profile"||c!==o?{status:"failed",errorCode:"profile_locked",errorMsg:"This conversation Profile is locked after the session is created"}:this.finishProfileSelection(o,!1)}if(e.action_type==="create_profile")try{const c=this.options.createDshProfile?await this.options.createDshProfile(o):await Ie({profileName:o,dshHome:this.options.dshHome??this.config.env?.DSH_HOME}),v=c.identity?.profileName??o;return this.persistSelectedProfile(v)?(await this.flushSelectedProfile(),this.finishProfileSelection(v,c.created)):{status:"failed",errorCode:"profile_locked",errorMsg:"This conversation Profile is locked after the session is created"}}catch(c){return{status:"failed",errorCode:String(c?.code??"profile_create_failed"),errorMsg:this.redactError(c)}}return this.listProfiles().some(c=>c.id===o)?this.persistSelectedProfile(o)?(await this.flushSelectedProfile(),this.finishProfileSelection(o,!1)):{status:"failed",errorCode:"profile_locked",errorMsg:"This conversation Profile is locked after the session is created"}:{status:"failed",errorCode:"profile_not_found",errorMsg:"Requested DSH profile is not in the local catalog"}}if(e.action_type==="set_preset"){if(this.active)return{status:"failed",errorCode:"worker_busy",errorMsg:"Cannot change DeepSeek Harness settings during an active turn"};if(!this.options.bindingStore.get(i)?.cwd)return{status:"failed",errorCode:"binding_missing",errorMsg:"Session binding missing. Open a workspace first."};const l=String(t.agent_preset_id??t.preset_id??"").trim();if(!this.presets.some(v=>v.id===l))return{status:"failed",errorCode:"preset_not_found",errorMsg:"Requested agent preset is not in the Harness catalog"};const c=Y(this.resolveDesiredSettings().agentPreset,this.presets);return this.options.bindingStore.isDshAgentPresetLocked(i)?c===l?{status:"ok",result:this.presetActionResult(l,!0)}:{status:"failed",errorCode:"agent_preset_locked",errorMsg:"This conversation scene is locked after the session is created"}:c===l?(this.options.bindingStore.setDshAgentPreset(i,l),await this.persistGlobalToolbarDefaults({dshAgentPreset:l}),await this.options.bindingStore.flush(),this.pushToolbarMeta(),{status:"ok",result:this.presetActionResult(l,!1)}):this.options.bindingStore.setDshAgentPreset(i,l)?(await this.persistGlobalToolbarDefaults({dshAgentPreset:l}),await this.options.bindingStore.flush(),this.pushToolbarMeta(),{status:"ok",result:this.presetActionResult(l,!1)}):{status:"failed",errorCode:"agent_preset_locked",errorMsg:"This conversation scene is locked after the session is created"}}if(this.active)return{status:"failed",errorCode:"worker_busy",errorMsg:"Cannot change DeepSeek Harness settings during an active turn"};if(!this.options.bindingStore.get(i)?.cwd)return{status:"failed",errorCode:"binding_missing",errorMsg:"Session binding missing. Open a workspace first."};const d=this.resolveDesiredSettings();let r;if(e.action_type==="set_provider"){const o=String(t.provider_id??"").trim();if(!this.providers.some(l=>l.id===o))return{status:"failed",errorCode:"provider_not_found",errorMsg:"Requested provider is not in the Harness catalog"};r={providerId:o},o!==d.providerId&&(this.models=et(this.options.dataRoot,o),this.catalogProviderId=o,this.models.some(l=>l.id===d.modelId)||(r.modelId=this.models[0]?.id))}else if(e.action_type==="set_model"){const o=String(t.model_id??"").trim();if(!this.models.some(l=>l.id===o))return{status:"failed",errorCode:"model_not_found",errorMsg:"Requested model is not in the Harness catalog"};r={modelId:o}}else if(e.action_type==="set_thinking"){const o=N(t.thinking_mode??t.thinking);if(!o)return{status:"failed",errorCode:"thinking_invalid",errorMsg:"thinking_mode must be enabled or disabled"};r={thinking:o}}else if(e.action_type==="set_reasoning_effort"){const o=B(t.reasoning_effort??t.reasoningEffort);if(!o)return{status:"failed",errorCode:"reasoning_effort_invalid",errorMsg:"reasoning_effort must be high or max"};r={reasoningEffort:o}}else{const o=String(t.mode_id??"").trim();if(o!=="approval"&&o!=="full_auto")return{status:"failed",errorCode:"mode_invalid",errorMsg:"mode_id must be approval or full_auto"};r={modeId:o}}if((r.providerId===void 0||r.providerId===d.providerId)&&(r.modelId===void 0||r.modelId===d.modelId)&&(r.modeId===void 0||r.modeId===d.modeId)&&(r.thinking===void 0||r.thinking===d.thinking)&&(r.reasoningEffort===void 0||r.reasoningEffort===d.reasoningEffort)&&this.applied?.appliedRevision===d.revision)return{status:"ok",result:this.settingsActionResult(e.action_type,r,d.revision,"already_applied",!0)};const u=this.options.bindingStore.updateDshSettings(i,r)??d.revision;if(await this.options.bindingStore.flush(),(r.providerId||r.modelId||r.modeId||r.thinking||r.reasoningEffort)&&await this.persistGlobalToolbarDefaults({...r.providerId?{dshProviderId:r.providerId}:{},...r.modelId?{dshModelId:r.modelId}:{},...r.modeId?{dshModeId:r.modeId}:{},...r.thinking?{dshThinking:r.thinking}:{},...r.reasoningEffort?{dshReasoningEffort:r.reasoningEffort}:{}}),this.contextWindow=null,this.reportedContextCapacity=null,this.settingsErrorCode=null,this.runtimeStartPromise&&await this.runtimeStartPromise.catch(()=>{}),!this.runtime)return this.settingsState="applied",this.pushToolbarMeta(),{status:"ok",result:this.settingsActionResult(e.action_type,r,u,"applied",!1)};if(this.active)return this.applied&&this.applied.appliedRevision>=u?(this.settingsState="applied",this.pushToolbarMeta(),{status:"ok",result:this.settingsActionResult(e.action_type,r,u,"applied",!0)}):(this.settingsState="pending",this.pushToolbarMeta(),{status:"ok",result:this.settingsActionResult(e.action_type,r,u,"pending",!0)});this.settingsState="pending",this.pushToolbarMeta();try{if(await this.rebuildRuntime("settings_changed"),!this.applied||this.applied.appliedRevision<u)throw new Error("new runtime did not apply requested revision");return this.refreshProviderQuota(!0),{status:"ok",result:this.settingsActionResult(e.action_type,r,u,"applied",!0)}}catch(o){return{status:"failed",result:this.settingsActionResult(e.action_type,r,u,"failed",!1,this.redactError(o)),errorCode:"settings_apply_failed",errorMsg:this.redactError(o)}}}async finishProfileSelection(e,t){if(this.resolveIntegrationMode()==="profile_bridge")try{await this.prepareSelectedProfile()}catch(i){const s=String(i?.code??"profile_start_failed");return this.runtimeReadiness=s,this.settingsErrorCode=s,this.pushToolbarMeta(),{status:"failed",errorCode:s,errorMsg:this.redactError(i)}}return this.pushToolbarMeta(),{status:"ok",result:this.profileActionResult(e,t)}}createBridgeInstaller(){const e=this.options.bridgeInstallerOptions??{};return new A({command:e.command??"dsh",dshHome:this.options.dshHome??this.config.env?.DSH_HOME,profileName:this.resolveSelectedProfile(),...e.tarballPath?{tarballPath:e.tarballPath}:{}})}async healBridgeUpdate(e){return e.readiness!=="bridge_update_required"||this.options.autoInstallBridge===!1?e:(f.info(m,`auto-updating stale Bridge profile=${e.identity.profileName} installed=${e.installedBridgeVersion??"none"} bundled=${e.bundledBridgeVersion}`),await this.prepareSelectedProfile(),this.attachSelectedProfile())}async ensureProfileReadyForChat(){if(!(this.options.autoInstallBridge!==!1||this.options.autoStartProfile!==!1)){const s=await this.attachSelectedProfile(),n=H(s);if(n)throw n;return}this.settingsState="pending",this.pushToolbarMeta(),await this.prepareSelectedProfile();let t=await this.attachSelectedProfile();t.readiness==="bridge_update_required"&&(t=await this.healBridgeUpdate(t));const i=H(t);if(i)throw i}async attachSelectedProfile(){const t=await this.createBridgeInstaller().status();return this.runtimeReadiness=t.readiness,this.profileDshVersion=t.runningDshVersion??t.dshVersion??null,this.settingsErrorCode=t.readiness==="ready"?null:t.readiness,t}async prepareSelectedProfile(){const e=this.createBridgeInstaller(),t=await He({installer:e,autoInstall:this.options.autoInstallBridge!==!1,autoStart:this.options.autoStartProfile!==!1});this.runtimeReadiness=t.readiness,this.profileDshVersion=t.runningDshVersion??t.dshVersion??null,this.settingsErrorCode=t.readiness==="ready"?null:t.readiness}profileActionResult(e,t){return{outcome:t?"profile_created":"profile_set",profile_id:e,dsh_profile:e,created:t,dsh_profile_locked:this.options.bindingStore.isDshProfileLocked(this.options.aibotSessionId),dsh_profile_create:!this.options.bindingStore.isDshProfileLocked(this.options.aibotSessionId),available_profiles:this.listProfiles(),session_context:{dsh_profile:e,dsh_profile_locked:this.options.bindingStore.isDshProfileLocked(this.options.aibotSessionId),dsh_profile_create:!this.options.bindingStore.isDshProfileLocked(this.options.aibotSessionId)}}}persistSelectedProfile(e){return this.options.bindingStore.setDshSelectedProfile(this.options.aibotSessionId,e)?(this.options.globalConfigStore?.set(this.options.agentName,{dshProfile:e}),!0):!1}async persistGlobalToolbarDefaults(e){this.options.globalConfigStore&&Object.values(e).some(t=>t!==void 0)&&(this.options.globalConfigStore.set(this.options.agentName,e),await this.options.globalConfigStore.flush())}seedSessionToolbarFromGlobal(){const e=this.options.aibotSessionId,t=this.options.bindingStore.get(e);if(!t?.cwd)return;const i=this.resolveDesiredSettings(),s={};t.dshProviderId||(s.providerId=i.providerId),t.dshModelId||(s.modelId=i.modelId),t.dshModeId||(s.modeId=i.modeId),t.dshThinking||(s.thinking=i.thinking),t.dshReasoningEffort||(s.reasoningEffort=i.reasoningEffort),Object.keys(s).length>0&&this.options.bindingStore.updateDshSettings(e,s),!this.options.bindingStore.getDshAgentPreset(e)&&i.agentPreset&&this.options.bindingStore.setDshAgentPreset(e,i.agentPreset),this.options.bindingStore.getDshSelectedProfile(e)||this.options.bindingStore.setDshSelectedProfile(e,this.resolveSelectedProfile())}async flushSelectedProfile(){await this.options.bindingStore.flush(),await this.options.globalConfigStore?.flush()}listProfiles(){return xe({dshHome:this.options.dshHome??this.config.env?.DSH_HOME})}pluginCommandContext(){return{dshHome:this.options.dshHome??this.config.env?.DSH_HOME,profileName:this.resolveSelectedProfile(),enabledPluginIds:this.options.bindingStore.getDshEnabledPlugins(this.options.aibotSessionId)}}skillCommandContext(){return{skillsDir:this.projectConnectorSkills(),enabledSkillIds:this.options.bindingStore.getDshEnabledSkills(this.options.aibotSessionId)}}currentPlugins(){try{return M(this.pluginCommandContext())}catch{return[]}}currentSkills(){return this.sessionSkillControlUnavailable()?[]:R(this.skillCommandContext())}pluginRestartRequired(){return!1}async executePluginAction(e,t,i){if(this.active)return{status:"failed",errorCode:"worker_busy",errorMsg:"Cannot change DeepSeek plugins during an active turn"};if(!this.options.bindingStore.get(i))return{status:"failed",errorCode:"binding_missing",errorMsg:"Session binding missing. Open a workspace first."};const s=this.pluginCommandContext();try{if(e==="dsh_list_plugins"||e==="dsh_refresh_plugins"){const o=M(s);return this.pushToolbarMeta(),{status:"ok",result:this.pluginActionResult(o,!1)}}const n=String(t.name??t.plugin_name??"").trim(),a=this.options.bindingStore.getDshEnabledPlugins(i);let d=n;try{const{plugin:o}=Te({...s,name:n});d=o.name}catch(o){const l=String(o?.code??"");if(e!=="dsh_disable_plugin"||l!=="plugin_not_found"||!a.includes(n))throw o}const r=we(a,d,e==="dsh_enable_plugin"),p=this.options.bindingStore.setDshEnabledPlugins(i,r.pluginIds)??this.resolveDesiredSettings().revision;await this.options.bindingStore.flush();const u=M({...s,enabledPluginIds:r.pluginIds});if(!r.changed)return this.pushToolbarMeta(),{status:"ok",result:this.pluginActionResult(u,!1,"skipped")};if(this.runtimeStartPromise&&await this.runtimeStartPromise.catch(()=>{}),!this.runtime)return this.settingsState="applied",this.pushToolbarMeta(),{status:"ok",result:this.pluginActionResult(u,!0,"skipped")};if(this.active)return this.settingsState="pending",this.pushToolbarMeta(),{status:"ok",result:this.pluginActionResult(u,!0,"pending")};if(this.settingsState="pending",this.pushToolbarMeta(),await this.rebuildRuntime("plugin_changed"),!this.applied||this.applied.appliedRevision<p)throw new Error("new runtime did not apply requested plugin revision");return this.pushToolbarMeta(),{status:"ok",result:this.pluginActionResult(u,!0,"restarted")}}catch(n){return{status:"failed",errorCode:String(n?.code??"plugin_action_failed"),errorMsg:this.redactError(n)}}}async executeSkillAction(e,t,i){if(this.active)return{status:"failed",errorCode:"worker_busy",errorMsg:"Cannot change DeepSeek skills during an active turn"};if(!this.options.bindingStore.get(i))return{status:"failed",errorCode:"binding_missing",errorMsg:"Session binding missing. Open a workspace first."};if(this.sessionSkillControlUnavailable())return this.pushToolbarMeta(),{status:"unsupported",errorCode:"capability_unavailable",errorMsg:`DSH session skills require @deepseek-ai/dsh ${oe} or newer`};const s=this.skillCommandContext();try{if(e==="dsh_list_skills"){const o=R(s);return this.pushToolbarMeta(),{status:"ok",result:this.skillActionResult(o,!1)}}const n=String(t.name??t.skill_name??"").trim(),a=this.options.bindingStore.getDshEnabledSkills(i);let d=n;try{d=Pe({...s,name:n}).name}catch(o){const l=String(o?.code??"");if(e!=="dsh_disable_skill"||l!=="skill_not_found"||!a.includes(n))throw o}const r=ye(a,d,e==="dsh_enable_skill"),p=this.options.bindingStore.setDshEnabledSkills(i,r.skillIds)??this.resolveDesiredSettings().revision;await this.options.bindingStore.flush();const u=R({...s,enabledSkillIds:r.skillIds});if(!r.changed)return this.pushToolbarMeta(),{status:"ok",result:this.skillActionResult(u,!1,"skipped")};if(this.runtimeStartPromise&&await this.runtimeStartPromise.catch(()=>{}),!this.runtime)return this.settingsState="applied",this.pushToolbarMeta(),{status:"ok",result:this.skillActionResult(u,!0,"skipped")};if(this.active)return this.settingsState="pending",this.pushToolbarMeta(),{status:"ok",result:this.skillActionResult(u,!0,"pending")};if(this.settingsState="pending",this.pushToolbarMeta(),await this.rebuildRuntime("skill_changed"),!this.applied||this.applied.appliedRevision<p)throw new Error("new runtime did not apply requested skill revision");return this.pushToolbarMeta(),{status:"ok",result:this.skillActionResult(u,!0,"restarted")}}catch(n){return{status:"failed",errorCode:String(n?.code??"skill_action_failed"),errorMsg:this.redactError(n)}}}pluginActionResult(e,t,i="skipped"){const s=this.resolveSelectedProfile(),n=this.pluginRestartRequired();return{outcome:t?i==="restarted"?"plugin_applied":"plugin_updated":"plugin_unchanged",dsh_profile:s,dsh_plugins:e,dsh_plugin_restart_required:n,restart:i,session_context:{dsh_profile:s,dsh_plugins:e,dsh_plugin_restart_required:n}}}skillActionResult(e,t,i="skipped"){return{outcome:t?i==="restarted"?"skill_applied":"skill_updated":"skill_unchanged",dsh_skills:e,restart:i,session_context:{dsh_skills:e}}}resolveSelectedProfile(){const e=this.options.bindingStore.getDshSelectedProfile(this.options.aibotSessionId),t=Re({binding:e,global:this.options.globalConfigStore?.get(this.options.agentName)?.dshProfile,adapter:this.options.dshProfile});return this.options.bindingStore.get(this.options.aibotSessionId)&&e!==t&&this.options.bindingStore.setDshSelectedProfile(this.options.aibotSessionId,t),t}profileDataDir(e=this.resolveSelectedProfile()){return Me(this.options.dataRoot,e)}usageStore(){const e=this.resolveSelectedProfile(),t=w(this.profileDataDir(e),"session-usage.json"),i=w(this.options.dataRoot,"session-usage.json");return!W(t)&&W(i)&&(ce(ue(t),{recursive:!0,mode:448}),he(i,t)),ot(t)}presetActionResult(e,t){const i=this.resolveDesiredSettings();return{outcome:"preset_set",agentPreset:e,agent_preset_id:e,agent_preset_locked:t,available_presets:[...this.presets],session_context:{agent_preset_id:i.agentPreset??e,agent_preset_locked:t}}}settingsActionResult(e,t,i,s,n,a){const d=this.resolveDesiredSettings(),r=d.revision||i,p={provider_id:d.providerId,model_id:d.modelId,mode_id:d.modeId,thinking_mode:d.thinking,reasoning_effort:d.reasoningEffort,applied_provider_id:this.applied?.providerId??null,applied_model_id:this.applied?.modelId??null,applied_mode_id:this.applied?.modeId??null,applied_thinking_mode:this.applied?.thinking??null,applied_reasoning_effort:this.applied?.reasoningEffort??null,applied_settings_revision:this.applied?.appliedRevision??null,settings_state:this.settingsState,settings_revision:r};return e==="set_mode"&&(p.sandbox_mode=J(d.modeId),p.approval_policy=d.modeId==="full_auto"?"never":"ask"),{outcome:`${e==="set_provider"?"provider":e==="set_model"?"model":e==="set_thinking"?"thinking":e==="set_reasoning_effort"?"reasoning_effort":"mode"}_set${s==="pending"||s==="failed"?"_pending":""}`,...t.providerId?{providerId:t.providerId,provider_id:t.providerId}:{},...t.modelId?{modelId:t.modelId,model_id:t.modelId}:{},...t.modeId?{modeId:t.modeId,mode_id:t.modeId,sandbox_mode:J(t.modeId),approval_policy:t.modeId==="full_auto"?"never":"ask"}:{},...t.thinking?{thinking:t.thinking,thinking_mode:t.thinking}:{},...t.reasoningEffort?{reasoningEffort:t.reasoningEffort,reasoning_effort:t.reasoningEffort}:{},settingsRevision:r,settings_revision:r,sessionAlive:n,available_providers:[...this.providers],available_models:[...this.models],session_context:p,...a?{error:a}:{}}}hydrateCatalogFromCache(){const e=this.options.bindingStore.getDshSettings(this.options.aibotSessionId),t=this.options.globalConfigStore?.get(this.options.agentName),i=tt({dataRoot:this.options.dataRoot,providerId:e?.providerId??t?.dshProviderId});this.providers=i.providers,this.models=this.options.models?.length?this.options.models:i.models,this.catalogProviderId=i.providerId}async persistCatalogCache(e){try{await it({dataRoot:this.options.dataRoot,providers:this.providers,providerId:e,models:this.models})}catch(t){f.warn(m,`failed to persist DSH catalog cache: ${t instanceof Error?t.message:String(t)}`)}}syncGrixProvider(){const e=ee(this.options.provider??{});if(e){this.providers.some(n=>n.id===b)||(this.providers=[{id:b,displayName:e.displayName},...this.providers]);const t=this.options.bindingStore.getDshSettings(this.options.aibotSessionId),i=this.options.globalConfigStore?.get(this.options.agentName),s=t?.providerId??i?.dshProviderId;(!s||s===$||s===b)&&this.options.bindingStore.updateDshSettings(this.options.aibotSessionId,{providerId:b});return}this.providers=this.providers.filter(t=>t.id!==b)}resolveDesiredSettings(){const e=this.options.bindingStore.get(this.options.aibotSessionId),t=this.options.bindingStore.getDshSettings(this.options.aibotSessionId),i=this.options.globalConfigStore?.get(this.options.agentName),s=t?.providerId??i?.dshProviderId,n=this.providers.some(p=>p.id===b)?b:void 0,a=Ye(s||n,this.providers),d=[t?.modelId,i?.dshModelId,this.options.defaultModel,this.models[0]?.id].find(p=>!!p&&this.models.some(u=>u.id===p))??"deepseek-chat",r=Y(t?.agentPreset??i?.dshAgentPreset,this.presets);return{providerId:a,modelId:d,modeId:Je(e?.dshModeId,i?.dshModeId),thinking:N(t?.thinking)??N(i?.dshThinking)??Qe,reasoningEffort:B(t?.reasoningEffort)??B(i?.dshReasoningEffort)??ze,agentPreset:r,pluginIds:this.options.bindingStore.getDshEnabledPlugins(this.options.aibotSessionId),skillIds:this.options.bindingStore.getDshEnabledSkills(this.options.aibotSessionId),skillIdsExplicit:Array.isArray(e?.dshSkillIds),maxTokens:t?.maxTokens??this.options.maxTokens??Ve,revision:t?.revision??0}}resolveIntegrationMode(){return this.options.integrationMode?this.options.integrationMode:(this.config.command||"").includes("dsh-jsonrpc-agent")?"embedded_jsonrpc":"profile_bridge"}sessionSkillControlUnavailable(){return this.resolveIntegrationMode()!=="profile_bridge"?!1:this.bridgeCapabilities&&typeof this.bridgeCapabilities=="object"?this.bridgeCapabilities.sessionSkillAllowlist!==!0:gt(this.profileDshVersion)}pushToolbarMeta(){const e=this.options.bindingStore.get(this.options.aibotSessionId);this.callbacks.sendUpdateBindingCard(this.options.aibotSessionId,this.stopped?"stopped":this.active?"busy":"ready",e?.cwd,Oe({desired:this.resolveDesiredSettings(),applied:this.applied,models:this.models,providers:this.providers,presets:this.presets,agentPresetLocked:this.options.bindingStore.isDshAgentPresetLocked(this.options.aibotSessionId),state:this.settingsState,errorCode:this.settingsErrorCode,contextWindow:this.contextWindow,providerQuota:this.providerQuota,integrationMode:this.resolveIntegrationMode(),profileName:this.resolveSelectedProfile(),profiles:this.listProfiles(),profileLocked:this.options.bindingStore.isDshProfileLocked(this.options.aibotSessionId),plugins:this.currentPlugins(),skills:this.currentSkills(),pluginRestartRequired:this.pluginRestartRequired(),runtimeReadiness:this.runtimeReadiness,bridgeCapabilities:this.bridgeCapabilities}))}async refreshProviderQuota(e){this.providerQuota=null,this.pushToolbarMeta();try{this.providerQuota=await this.callbacks.queryProviderQuota(e)??{provider:"deepseek",providerLabel:"DeepSeek",success:!1,error:"unavailable"}}catch{this.providerQuota={provider:"deepseek",providerLabel:"DeepSeek",success:!1,error:"unavailable"}}this.pushToolbarMeta()}clearPendingApprovals(e){for(const t of this.pendingApprovals.values())clearTimeout(t.timer),t.resolve(e);this.pendingApprovals.clear()}thinkingEnabled(){const e=this.active?.inbound.connector_runtime_config?.thinking_events??this.active?.inbound.connector_runtime_config?.thinkingEvents;return e!=="off"&&e!=="hidden"&&e!=="none"}toolEventsEnabled(){const e=this.active?.inbound.connector_runtime_config?.tool_events;return e!=="off"&&e!=="hidden"&&e!=="none"}sendRaw(e,t,i){this.active&&this.callbacks.sendRawEventEnvelope(this.active.inbound.event_id,this.active.inbound.session_id,{type:e,payload:t},i)}failEvent(e,t){this.callbacks.sendEventResult(e.event_id,"failed",t),this.emit("eventDone",e.event_id)}startTimeout(e){this.activeTimeoutMs=e??this.options.promptTimeoutMs??te,this.noteRuntimeActivity(),this.armTimeout(this.activeIdleTimeoutMs()),this.armHardTimeout(this.activeTimeoutMs)}touchActivity(e=1){!this.active||!this.timeoutTimer||(this.noteRuntimeActivity(),this.armTimeout(this.activeIdleTimeoutMs()))}noteRuntimeActivity(){this.active&&(this.active.lastRuntimeActivityAt=Date.now(),this.active.livenessExtendStartAt=void 0)}activeIdleTimeoutMs(){const e=this.options.activeIdleTimeoutMs??ie,t=Number.isFinite(e)&&e>0?e:ie;return Math.min(t,this.activeTimeoutMs)}livenessFreshMs(){const e=this.options.livenessFreshMs??se;return Number.isFinite(e)&&e>0?e:se}livenessMaxExtendMs(){const e=this.options.livenessMaxExtendMs??ne;return Number.isFinite(e)&&e>0?e:ne}armTimeout(e){this.clearIdleTimeout(),this.timeoutTimer=setTimeout(()=>{this.handlePromptTimeout()},e),this.timeoutTimer.unref?.()}armHardTimeout(e){this.clearHardTimeout(),this.hardTimeoutTimer=setTimeout(()=>{this.handlePromptHardTimeout()},e),this.hardTimeoutTimer.unref?.()}async handlePromptTimeout(){const e=this.active;if(e){if(this.pendingApprovals.size>0){f.info(m,`Idle timeout skipped: pendingApprovals=${this.pendingApprovals.size} event=${e.inbound.event_id}`),this.armTimeout(this.activeIdleTimeoutMs());return}if(this.shouldExtendByLiveness(e.inbound.event_id)){this.armTimeout(this.activeIdleTimeoutMs());return}await this.failActiveTimeout("idle","Harness prompt idle timeout and the runtime was terminated")}}async handlePromptHardTimeout(){const e=this.active;if(e&&this.shouldExtendByLiveness(e.inbound.event_id)){this.armHardTimeout(this.activeTimeoutMs);return}await this.failActiveTimeout("hard","Harness prompt exceeded max duration and the runtime was terminated")}shouldExtendByLiveness(e){const t=this.active;if(!t||t.inbound.event_id!==e||!this.runtime?.isConnected()||!(!t.turnEnded&&(!!t.messageId||t.admitted||t.claimed)))return!1;const s=Date.now(),n=t.lastRuntimeActivityAt??t.startedAt,a=Math.max(0,s-n);if(a<this.livenessFreshMs())return t.livenessExtendStartAt=s,f.info(m,`Liveness check: recent DSH activity for ${e} (quietMs=${a}), extending`),!0;const d=t.livenessExtendStartAt??n;t.livenessExtendStartAt=d;const r=s-d;return r>this.livenessMaxExtendMs()?(f.warn(m,`Liveness extension budget exhausted for ${e} (quietMs=${a}, extendMs=${r}), allowing close`),!1):(f.info(m,`Liveness check: DSH turn still open for ${e} (claimed=${t.claimed}, turnEnded=${t.turnEnded}, quietMs=${a}), extending`),!0)}async failActiveTimeout(e,t){if(!this.active)return;const i=this.active;this.clearTimeout();const s=this.runtime;this.runtime=null,this.intentionalRuntimeStop=!0,this.contextWindow=null,this.reportedContextCapacity=null,this.applied=void 0,this.settingsState="applied",this.settingsErrorCode=null,this.pushToolbarMeta(),await s?.cancel(this.runtimeSessionId).catch(()=>{}),s&&await s.shutdown().catch(()=>s.terminate()),this.intentionalRuntimeStop=!1,!(this.active!==i||this.stopped)&&(f.error(m,`Active DSH turn ${e} timeout: ${i.inbound.event_id}`),this.finishActive("failed",t),this.emit("exit",1))}clearTimeout(){this.clearIdleTimeout(),this.clearHardTimeout()}clearIdleTimeout(){this.timeoutTimer&&clearTimeout(this.timeoutTimer),this.timeoutTimer=null}clearHardTimeout(){this.hardTimeoutTimer&&clearTimeout(this.hardTimeoutTimer),this.hardTimeoutTimer=null}redactError(e,t){let i=e instanceof Error?e.message:String(e);const s=this.config.env?.DEEPSEEK_API_KEY;return s&&(i=i.split(s).join("[REDACTED]")),i=i.replace(/(api[_-]?key|authorization|bearer)\s*[:=]\s*\S+/gi,"$1=[REDACTED]"),t&&t.length>=16&&i.includes(t)&&(i="Harness request failed (prompt echo redacted)"),(i.includes("[aibot-system-prompt]")||i.includes("[base-behavior]"))&&(i="Harness runtime failed (system prompt echo redacted)"),i.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g,"").slice(0,2e3)}}function ht(h){const e=Number(h&&typeof h=="object"?h.cursor:0);return Number.isSafeInteger(e)&&e>0?e:0}function ct(h){return new Promise(e=>setTimeout(e,h))}function ut(h,e){return`grix-${D("sha256").update(h).digest("hex").slice(0,12)}-${e}-${x().slice(0,8)}`}function pt(h){return`grix-${D("sha256").update(h).digest("hex").slice(0,16)}-${x().slice(0,8)}`}function re(){return{inputTokens:0,outputTokens:0,cacheReadInputTokens:0,cacheCreationInputTokens:0,reasoningTokens:0}}function gt(h){const e=ft(h,oe);return e!==null&&e<0}function ft(h,e){const t=ae(h),i=ae(e);return!t||!i?null:t.major-i.major||t.minor-i.minor||t.patch-i.patch||mt(t.prerelease,i.prerelease)}function ae(h){const e=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/.exec(String(h??"").trim());return e?{major:Number(e[1]),minor:Number(e[2]),patch:Number(e[3]),...e[4]?{prerelease:e[4]}:{}}:null}function mt(h,e){if(h===e)return 0;if(h===void 0)return 1;if(e===void 0)return-1;const t=h.split("."),i=e.split(".");for(let s=0;s<Math.max(t.length,i.length);s+=1){const n=t[s],a=i[s];if(n===a)continue;if(n===void 0)return-1;if(a===void 0)return 1;const d=/^\d+$/.test(n),r=/^\d+$/.test(a);return d&&r?Number(n)-Number(a):d!==r?d?-1:1:n<a?-1:1}return 0}function de(h){const e=h.data?.chunk&&typeof h.data.chunk=="object"?h.data.chunk:h.data;return String(e?.type??"")}function vt(h){return h.type==="assistant/chunk:tool-call-delta"||h.type==="assistant/chunk"&&de(h)==="tool-call-delta"}function bt(h){return{readiness:h.readiness,profile:h.identity.profileName,dshVersion:h.dshVersion,runningDshVersion:h.runningDshVersion,installedBridgeVersion:h.installedBridgeVersion,bundledBridgeVersion:h.bundledBridgeVersion,runningBridgeVersion:h.runningBridgeVersion,endpointCount:h.endpointCount,requiresProfileRestart:h.readiness==="profile_restart_required"}}const _t=new Set(["turn/start","step/start","step/end","agent/inbox/spliced","user/message","request/header","session/title","session/title-llm-request","session/end-seed","web/deepseek-search-llm-request","assistant/chunk:tool-call-delta","permission/preset","sandbox/mode","approval/policy","approval/asked","approval/decided","plan/mode","agent-preset/selected","llm/retry","llm/retry-started","goal/change","schedule/change","feedback/record","hook/invoked","hook/result","command/run","command/done","subagent/descriptor","tool-workflow/agent-start","tool-workflow/agent-end","tool-workflow/run-start","tool-workflow/run-end","tool/code-dispatch","tool/code-dispatch-start"]);function St(h){const e=de(h);return _t.has(h.type)||h.type==="assistant/chunk"&&["block-start","block-end","tool-call-delta","finish"].includes(e)}export{ti as DshJsonRpcAdapter};
3
+ Error: ${n}`,this.flushVisibleText(!1,{finalizeDsml:!0})),s==="responded"&&this.activeUsageSeq>=0&&(this.usageStore().commit(i.inbound.session_id,this.runtimeSessionId,this.activeUsageSeq,this.applied?.modelId??this.resolveDesiredSettings().modelId,this.activeUsage),this.usageStore().flush()),i.inbound.audit?.enabled&&this.capture&&this.auditBoundaries.set(i.inbound.event_id,this.capture.boundary({runtimeSessionId:this.runtimeSessionId,rootSessionId:this.runtimeSessionId,startOffset:this.activeWireStart,turn:i.turn,messageId:i.messageId}));const d=this.personaDirty&&!!this.runtime,r=!!this.runtime&&!!this.applied&&this.applied.appliedRevision!==this.resolveDesiredSettings().revision;d&&this.emit("pauseIntake","barrier"),this.active=null,this.correlator=null;const p=`${i.inbound.event_id}-dsh`,u=(o,l,c=!1)=>{this.callbacks.sendEventResult(i.inbound.event_id,o,l,c),this.emit("eventDone",i.inbound.event_id),d?this.rebuildRuntime("persona_changed"):r&&this.rebuildRuntime("settings_changed")};if(i.repliedViaTool&&i.seq===0){this.flushPendingFinalBridgeAck(!0).then(()=>u(s,n,a),()=>u(s,n,a));return}this.callbacks.sendFinalStreamChunkReliable(i.inbound.event_id,i.inbound.session_id,p).then(async()=>{await this.flushPendingFinalBridgeAck(!0),u(s,n,a)},async o=>{await this.flushPendingFinalBridgeAck(!1),u(s==="responded"?"failed":s,s==="responded"?`Final output delivery failed: ${this.redactError(o,i.inbound.content)}`:n)})}advanceBridgeAck(e,t){if(!(e<=0)){if(t||this.finishingTurn||this.pendingFinalBridgeAck!==null){this.pendingFinalBridgeAck=Math.max(this.pendingFinalBridgeAck??0,e);return}this.ackBridgeCursor(e)}}async flushPendingFinalBridgeAck(e){const t=this.pendingFinalBridgeAck;this.pendingFinalBridgeAck=null,this.finishingTurn=!1,!(!e||t===null)&&await this.ackBridgeCursor(t)}async ackBridgeCursor(e){if(e<=this.bridgeAckCursor)return;const t=this.runtime?.client?.ack;if(!t){this.bridgeAckCursor=Math.max(this.bridgeAckCursor,e);return}try{await t.call(this.runtime.client,e),this.bridgeAckCursor=Math.max(this.bridgeAckCursor,e)}catch(i){this.onProtocolError(i instanceof Error?i:new Error(String(i)))}}async cancelActive(e){this.active&&(this.cancelRequested=!0,this.clearPendingApprovals("cancelled"),this.resolveIntegrationMode()==="embedded_jsonrpc"?(this.contextWindow=null,this.reportedContextCapacity=null,this.applied=void 0,this.settingsState="applied",this.pushToolbarMeta(),this.runtimeStartPromise&&this.runtime&&await this.runtime.terminate().catch(()=>{}),await this.runtimeStartPromise?.catch(()=>{}),await this.stopRuntime(!0)):(await this.runtimeStartPromise?.catch(()=>{}),await this.runtime?.cancel(this.runtimeSessionId).catch(()=>{}),this.runtime&&!this.runtime.isConnected()&&await this.stopRuntime(!0)),this.finishActive("canceled",e))}async handleBridgeApproval(e){const t=this.permissionHandler,i=String(e.interactionId??e.callId??x());if(t)try{return await t({adapterSessionId:this.options.aibotSessionId,requestId:i,description:String(e.reason??`Allow ${String(e.toolName??"operation")}?`),options:[{id:"allow_once",label:"Allow once",isAllow:!0},{id:"reject",label:"Reject",isAllow:!1}]})==="allow_once"?"allowed-once":"rejected"}catch{return"cancelled"}const s=this.active;return s?(this.callbacks.sendPermissionCard({eventId:s.inbound.event_id,sessionId:s.inbound.session_id,approvalId:i,toolName:String(e.toolName??"operation"),toolTitle:String(e.reason??`Allow ${String(e.toolName??"operation")}?`)}),new Promise(n=>{const a=setTimeout(()=>{this.pendingApprovals.delete(i),n("unavailable")},3e5);a.unref?.(),this.pendingApprovals.set(i,{resolve:n,timer:a})})):"unavailable"}async invokeGrixTool(e,t,i){if(!dt(e))throw Object.assign(new Error(`grix tool "${e}" is not exposed to DSH`),{code:"capability_unavailable"});if(at(e)){if(!this.callbacks.eventToolInvoke)throw Object.assign(new Error(`grix event tool "${e}" has no connector-side runner`),{code:"capability_unavailable"});const n=this.active,a=await this.callbacks.eventToolInvoke(e,t);if(e==="grix_reply"&&n){const d=String(t.session_id??"").trim();(!d||d===n.inbound.session_id)&&(n.repliedViaTool=!0)}return a}if(!this.callbacks.agentInvoke)throw Object.assign(new Error(`grix tool "${e}" has no connector-side action runner`),{code:"capability_unavailable"});const s=rt(e,t);return this.callbacks.agentInvoke(s.action,s.params,i??s.timeoutMs)}projectConnectorSkills(){const e=w(this.options.dataRoot,"dsh-session-skills"),t=pe(e);return t.length>0&&f.info(m,`Synced connector skills to ${e}: [${t.join(", ")}]`),e}rebuildRuntime(e){if(this.stopped||this.active)return Promise.resolve();if(this.rebuildPromise)return this.rebuildPromise;const t=(async()=>{this.emit("pauseIntake","barrier"),this.contextWindow=null,this.reportedContextCapacity=null,this.applied=void 0,this.settingsState="pending",this.pushToolbarMeta();try{await this.stopRuntime(!0),await this.ensureRuntime()}catch(i){f.warn(m,`${e} rebuild failed: ${this.redactError(i)}`)}finally{this.emit("resumeIntake","barrier")}})();return this.rebuildPromise=t.finally(()=>{this.rebuildPromise=null;const i=this.resolveDesiredSettings().revision;!this.stopped&&!this.active&&(this.personaDirty||this.applied&&this.applied.appliedRevision!==i)&&this.rebuildRuntime("coalesced_state_changed")}),this.rebuildPromise}async stopRuntime(e){const t=this.runtime;t&&(this.intentionalRuntimeStop=e,this.runtime=null,await t.shutdown().catch(()=>t.terminate()),this.capture?.close(),this.capture=null,this.intentionalRuntimeStop=!1)}onRuntimeExit(){this.intentionalRuntimeStop||this.stopped||(this.runtime=null,this.capture?.close(),this.capture=null,this.applied=void 0,this.contextWindow=null,this.reportedContextCapacity=null,this.settingsState="failed",this.settingsErrorCode="runtime_exited",this.pushToolbarMeta(),this.active&&this.finishActive("failed","Harness runtime exited; prompt was not replayed"),this.emit("exit",1))}onProtocolError(e){if(this.stopped||!this.runtime&&!this.active)return;const t=this.redactError(e,this.active?.inbound.content);this.clearPendingApprovals("unavailable"),this.contextWindow=null,this.reportedContextCapacity=null,this.settingsState="failed",this.settingsErrorCode="protocol_error",this.pushToolbarMeta();const i=this.runtime;this.runtime=null,this.intentionalRuntimeStop=!0,i?.client?.close(e),this.active&&this.finishActive("failed",`Harness protocol error: ${t}`),i?.terminate().finally(()=>{this.intentionalRuntimeStop=!1}),this.emit("exit",1)}async executeLocalAction(e){const t=e.params??{},i=String(t.session_id??"");if(!i||i!==this.options.aibotSessionId)return{status:"failed",errorCode:"binding_missing",errorMsg:"Session binding missing"};if(["exec_approve","exec_reject","permission_approve","permission_reject"].includes(e.action_type)){const o=String(t.approval_command_id??t.approval_id??t.request_id??"").trim(),l=this.pendingApprovals.get(o);if(!l)return{status:"failed",errorCode:"unknown_or_expired_approval_id",errorMsg:"That DSH approval request is no longer pending"};clearTimeout(l.timer),this.pendingApprovals.delete(o);const c=e.action_type==="exec_approve"||e.action_type==="permission_approve";return l.resolve(c?"allowed-once":"rejected"),{status:"ok",result:{approval_id:o,decision:c?"allow-once":"deny"}}}if(e.action_type==="get_session_usage")return{status:"ok",result:{adapterType:"deepseek-harness",available:!0,dsh_profile:this.resolveSelectedProfile(),...this.usageStore().get(i)}};if(e.action_type==="get_rate_limits"){this.providerQuota=null,this.pushToolbarMeta();try{this.providerQuota=await this.callbacks.queryProviderQuota(!0)??{provider:"deepseek",providerLabel:"DeepSeek",success:!1,error:"unavailable"}}catch(o){this.providerQuota={provider:"deepseek",providerLabel:"DeepSeek",success:!1,error:this.redactError(o)}}return this.pushToolbarMeta(),{status:"ok",result:{sampledAt:new Date().toISOString(),contextWindow:this.contextWindow,providerQuota:this.providerQuota}}}if(e.action_type==="dsh_bridge_status"||e.action_type==="dsh_install_bridge"){if(this.resolveIntegrationMode()!=="profile_bridge")return{status:"unsupported",errorCode:"capability_unavailable",errorMsg:"Bridge management requires Profile Bridge mode"};if(this.active||this.runtime)return{status:"failed",errorCode:"worker_busy",errorMsg:"Stop the active DSH session before changing its Profile plugin"};try{const o=new A({command:"dsh",dshHome:this.options.dshHome??this.config.env?.DSH_HOME,profileName:this.resolveSelectedProfile()}),l=e.action_type==="dsh_install_bridge"?await o.install():await o.status();return this.runtimeReadiness=l.readiness,this.settingsErrorCode=l.readiness==="ready"?null:l.readiness,this.pushToolbarMeta(),{status:"ok",result:bt(l)}}catch(o){const l=String(o?.code??"bridge_install_failed");return this.runtimeReadiness=l,this.settingsErrorCode=l,this.pushToolbarMeta(),{status:"failed",errorCode:l,errorMsg:this.redactError(o)}}}if(e.action_type==="dsh_list_plugins"||e.action_type==="dsh_refresh_plugins"||e.action_type==="dsh_enable_plugin"||e.action_type==="dsh_disable_plugin")return this.executePluginAction(e.action_type,t,i);if(e.action_type==="dsh_list_skills"||e.action_type==="dsh_enable_skill"||e.action_type==="dsh_disable_skill")return this.executeSkillAction(e.action_type,t,i);const n={dsh_list_mcp:"mcp/list",dsh_list_tools:"tools/list",dsh_list_jobs:"jobs/list",dsh_list_goals:"goals/list"}[e.action_type];if(n){if(this.resolveIntegrationMode()!=="profile_bridge")return{status:"unsupported",errorCode:"capability_unavailable",errorMsg:"DSH resources require Profile Bridge mode"};if(this.active)return{status:"failed",errorCode:"worker_busy",errorMsg:"Cannot query DSH resources during an active turn"};try{return await this.ensureRuntimeWithRetry(),{status:"ok",result:await this.runtime?.client?.call(n,{cwd:this.options.bindingStore.get(i)?.cwd})}}catch(o){const l=String(o?.code??"resource_query_failed");return{status:l==="capability_unavailable"?"unsupported":"failed",errorCode:l,errorMsg:this.redactError(o)}}}if(e.action_type==="set_profile"||e.action_type==="create_profile"){if(this.active)return{status:"failed",errorCode:"worker_busy",errorMsg:"Cannot change DeepSeek Harness Profile during an active turn"};if(!this.options.bindingStore.get(i))return{status:"failed",errorCode:"binding_missing",errorMsg:"Session binding missing. Open a workspace first."};let o;try{o=Ee(String(t.profile_id??t.dsh_profile??t.profile_name??t.name??""))}catch(c){return{status:"failed",errorCode:"profile_invalid",errorMsg:this.redactError(c)}}if(this.options.bindingStore.isDshProfileLocked(i)){const c=this.resolveSelectedProfile();return e.action_type==="create_profile"||c!==o?{status:"failed",errorCode:"profile_locked",errorMsg:"This conversation Profile is locked after the session is created"}:this.finishProfileSelection(o,!1)}if(e.action_type==="create_profile")try{const c=this.options.createDshProfile?await this.options.createDshProfile(o):await Ie({profileName:o,dshHome:this.options.dshHome??this.config.env?.DSH_HOME}),v=c.identity?.profileName??o;return this.persistSelectedProfile(v)?(await this.flushSelectedProfile(),this.finishProfileSelection(v,c.created)):{status:"failed",errorCode:"profile_locked",errorMsg:"This conversation Profile is locked after the session is created"}}catch(c){return{status:"failed",errorCode:String(c?.code??"profile_create_failed"),errorMsg:this.redactError(c)}}return this.listProfiles().some(c=>c.id===o)?this.persistSelectedProfile(o)?(await this.flushSelectedProfile(),this.finishProfileSelection(o,!1)):{status:"failed",errorCode:"profile_locked",errorMsg:"This conversation Profile is locked after the session is created"}:{status:"failed",errorCode:"profile_not_found",errorMsg:"Requested DSH profile is not in the local catalog"}}if(e.action_type==="set_preset"){if(this.active)return{status:"failed",errorCode:"worker_busy",errorMsg:"Cannot change DeepSeek Harness settings during an active turn"};if(!this.options.bindingStore.get(i)?.cwd)return{status:"failed",errorCode:"binding_missing",errorMsg:"Session binding missing. Open a workspace first."};const l=String(t.agent_preset_id??t.preset_id??"").trim();if(!this.presets.some(v=>v.id===l))return{status:"failed",errorCode:"preset_not_found",errorMsg:"Requested agent preset is not in the Harness catalog"};const c=Y(this.resolveDesiredSettings().agentPreset,this.presets);return this.options.bindingStore.isDshAgentPresetLocked(i)?c===l?{status:"ok",result:this.presetActionResult(l,!0)}:{status:"failed",errorCode:"agent_preset_locked",errorMsg:"This conversation scene is locked after the session is created"}:c===l?(this.options.bindingStore.setDshAgentPreset(i,l),await this.persistGlobalToolbarDefaults({dshAgentPreset:l}),await this.options.bindingStore.flush(),this.pushToolbarMeta(),{status:"ok",result:this.presetActionResult(l,!1)}):this.options.bindingStore.setDshAgentPreset(i,l)?(await this.persistGlobalToolbarDefaults({dshAgentPreset:l}),await this.options.bindingStore.flush(),this.pushToolbarMeta(),{status:"ok",result:this.presetActionResult(l,!1)}):{status:"failed",errorCode:"agent_preset_locked",errorMsg:"This conversation scene is locked after the session is created"}}if(this.active)return{status:"failed",errorCode:"worker_busy",errorMsg:"Cannot change DeepSeek Harness settings during an active turn"};if(!this.options.bindingStore.get(i)?.cwd)return{status:"failed",errorCode:"binding_missing",errorMsg:"Session binding missing. Open a workspace first."};const d=this.resolveDesiredSettings();let r;if(e.action_type==="set_provider"){const o=String(t.provider_id??"").trim();if(!this.providers.some(l=>l.id===o))return{status:"failed",errorCode:"provider_not_found",errorMsg:"Requested provider is not in the Harness catalog"};r={providerId:o},o!==d.providerId&&(this.models=et(this.options.dataRoot,o),this.catalogProviderId=o,this.models.some(l=>l.id===d.modelId)||(r.modelId=this.models[0]?.id))}else if(e.action_type==="set_model"){const o=String(t.model_id??"").trim();if(!this.models.some(l=>l.id===o))return{status:"failed",errorCode:"model_not_found",errorMsg:"Requested model is not in the Harness catalog"};r={modelId:o}}else if(e.action_type==="set_thinking"){const o=N(t.thinking_mode??t.thinking);if(!o)return{status:"failed",errorCode:"thinking_invalid",errorMsg:"thinking_mode must be enabled or disabled"};r={thinking:o}}else if(e.action_type==="set_reasoning_effort"){const o=B(t.reasoning_effort??t.reasoningEffort);if(!o)return{status:"failed",errorCode:"reasoning_effort_invalid",errorMsg:"reasoning_effort must be high or max"};r={reasoningEffort:o}}else{const o=String(t.mode_id??"").trim();if(o!=="approval"&&o!=="full_auto")return{status:"failed",errorCode:"mode_invalid",errorMsg:"mode_id must be approval or full_auto"};r={modeId:o}}if((r.providerId===void 0||r.providerId===d.providerId)&&(r.modelId===void 0||r.modelId===d.modelId)&&(r.modeId===void 0||r.modeId===d.modeId)&&(r.thinking===void 0||r.thinking===d.thinking)&&(r.reasoningEffort===void 0||r.reasoningEffort===d.reasoningEffort)&&this.applied?.appliedRevision===d.revision)return{status:"ok",result:this.settingsActionResult(e.action_type,r,d.revision,"already_applied",!0)};const u=this.options.bindingStore.updateDshSettings(i,r)??d.revision;if(await this.options.bindingStore.flush(),(r.providerId||r.modelId||r.modeId||r.thinking||r.reasoningEffort)&&await this.persistGlobalToolbarDefaults({...r.providerId?{dshProviderId:r.providerId}:{},...r.modelId?{dshModelId:r.modelId}:{},...r.modeId?{dshModeId:r.modeId}:{},...r.thinking?{dshThinking:r.thinking}:{},...r.reasoningEffort?{dshReasoningEffort:r.reasoningEffort}:{}}),this.contextWindow=null,this.reportedContextCapacity=null,this.settingsErrorCode=null,this.runtimeStartPromise&&await this.runtimeStartPromise.catch(()=>{}),!this.runtime)return this.settingsState="applied",this.pushToolbarMeta(),{status:"ok",result:this.settingsActionResult(e.action_type,r,u,"applied",!1)};if(this.active)return this.applied&&this.applied.appliedRevision>=u?(this.settingsState="applied",this.pushToolbarMeta(),{status:"ok",result:this.settingsActionResult(e.action_type,r,u,"applied",!0)}):(this.settingsState="pending",this.pushToolbarMeta(),{status:"ok",result:this.settingsActionResult(e.action_type,r,u,"pending",!0)});this.settingsState="pending",this.pushToolbarMeta();try{if(await this.rebuildRuntime("settings_changed"),!this.applied||this.applied.appliedRevision<u)throw new Error("new runtime did not apply requested revision");return this.refreshProviderQuota(!0),{status:"ok",result:this.settingsActionResult(e.action_type,r,u,"applied",!0)}}catch(o){return{status:"failed",result:this.settingsActionResult(e.action_type,r,u,"failed",!1,this.redactError(o)),errorCode:"settings_apply_failed",errorMsg:this.redactError(o)}}}async finishProfileSelection(e,t){if(this.resolveIntegrationMode()==="profile_bridge")try{await this.prepareSelectedProfile()}catch(i){const s=String(i?.code??"profile_start_failed");return this.runtimeReadiness=s,this.settingsErrorCode=s,this.pushToolbarMeta(),{status:"failed",errorCode:s,errorMsg:this.redactError(i)}}return this.pushToolbarMeta(),{status:"ok",result:this.profileActionResult(e,t)}}createBridgeInstaller(){const e=this.options.bridgeInstallerOptions??{};return new A({command:e.command??"dsh",dshHome:this.options.dshHome??this.config.env?.DSH_HOME,profileName:this.resolveSelectedProfile(),...e.tarballPath?{tarballPath:e.tarballPath}:{}})}async healBridgeUpdate(e){return e.readiness!=="bridge_update_required"||this.options.autoInstallBridge===!1?e:(f.info(m,`auto-updating stale Bridge profile=${e.identity.profileName} installed=${e.installedBridgeVersion??"none"} bundled=${e.bundledBridgeVersion}`),await this.prepareSelectedProfile(),this.attachSelectedProfile())}async ensureProfileReadyForChat(){if(!(this.options.autoInstallBridge!==!1||this.options.autoStartProfile!==!1)){const s=await this.attachSelectedProfile(),n=H(s);if(n)throw n;return}this.settingsState="pending",this.pushToolbarMeta(),await this.prepareSelectedProfile();let t=await this.attachSelectedProfile();t.readiness==="bridge_update_required"&&(t=await this.healBridgeUpdate(t));const i=H(t);if(i)throw i}async attachSelectedProfile(){const t=await this.createBridgeInstaller().status();return this.runtimeReadiness=t.readiness,this.profileDshVersion=t.runningDshVersion??t.dshVersion??null,this.settingsErrorCode=t.readiness==="ready"?null:t.readiness,t}async prepareSelectedProfile(){const e=this.createBridgeInstaller(),t=await He({installer:e,autoInstall:this.options.autoInstallBridge!==!1,autoStart:this.options.autoStartProfile!==!1});this.runtimeReadiness=t.readiness,this.profileDshVersion=t.runningDshVersion??t.dshVersion??null,this.settingsErrorCode=t.readiness==="ready"?null:t.readiness}profileActionResult(e,t){return{outcome:t?"profile_created":"profile_set",profile_id:e,dsh_profile:e,created:t,dsh_profile_locked:this.options.bindingStore.isDshProfileLocked(this.options.aibotSessionId),dsh_profile_create:!this.options.bindingStore.isDshProfileLocked(this.options.aibotSessionId),available_profiles:this.listProfiles(),session_context:{dsh_profile:e,dsh_profile_locked:this.options.bindingStore.isDshProfileLocked(this.options.aibotSessionId),dsh_profile_create:!this.options.bindingStore.isDshProfileLocked(this.options.aibotSessionId)}}}persistSelectedProfile(e){return this.options.bindingStore.setDshSelectedProfile(this.options.aibotSessionId,e)?(this.options.globalConfigStore?.set(this.options.agentName,{dshProfile:e}),!0):!1}async persistGlobalToolbarDefaults(e){this.options.globalConfigStore&&Object.values(e).some(t=>t!==void 0)&&(this.options.globalConfigStore.set(this.options.agentName,e),await this.options.globalConfigStore.flush())}seedSessionToolbarFromGlobal(){const e=this.options.aibotSessionId,t=this.options.bindingStore.get(e);if(!t?.cwd)return;const i=this.resolveDesiredSettings(),s={};t.dshProviderId||(s.providerId=i.providerId),t.dshModelId||(s.modelId=i.modelId),t.dshModeId||(s.modeId=i.modeId),t.dshThinking||(s.thinking=i.thinking),t.dshReasoningEffort||(s.reasoningEffort=i.reasoningEffort),Object.keys(s).length>0&&this.options.bindingStore.updateDshSettings(e,s),!this.options.bindingStore.getDshAgentPreset(e)&&i.agentPreset&&this.options.bindingStore.setDshAgentPreset(e,i.agentPreset),this.options.bindingStore.getDshSelectedProfile(e)||this.options.bindingStore.setDshSelectedProfile(e,this.resolveSelectedProfile())}async flushSelectedProfile(){await this.options.bindingStore.flush(),await this.options.globalConfigStore?.flush()}listProfiles(){return xe({dshHome:this.options.dshHome??this.config.env?.DSH_HOME})}pluginCommandContext(){return{dshHome:this.options.dshHome??this.config.env?.DSH_HOME,profileName:this.resolveSelectedProfile(),enabledPluginIds:this.options.bindingStore.getDshEnabledPlugins(this.options.aibotSessionId)}}skillCommandContext(){return{skillsDir:this.projectConnectorSkills(),enabledSkillIds:this.options.bindingStore.getDshEnabledSkills(this.options.aibotSessionId)}}currentPlugins(){try{return M(this.pluginCommandContext())}catch{return[]}}currentSkills(){return this.sessionSkillControlUnavailable()?[]:R(this.skillCommandContext())}pluginRestartRequired(){return!1}async executePluginAction(e,t,i){if(this.active)return{status:"failed",errorCode:"worker_busy",errorMsg:"Cannot change DeepSeek plugins during an active turn"};if(!this.options.bindingStore.get(i))return{status:"failed",errorCode:"binding_missing",errorMsg:"Session binding missing. Open a workspace first."};const s=this.pluginCommandContext();try{if(e==="dsh_list_plugins"||e==="dsh_refresh_plugins"){const o=M(s);return this.pushToolbarMeta(),{status:"ok",result:this.pluginActionResult(o,!1)}}const n=String(t.name??t.plugin_name??"").trim(),a=this.options.bindingStore.getDshEnabledPlugins(i);let d=n;try{const{plugin:o}=Te({...s,name:n});d=o.name}catch(o){const l=String(o?.code??"");if(e!=="dsh_disable_plugin"||l!=="plugin_not_found"||!a.includes(n))throw o}const r=we(a,d,e==="dsh_enable_plugin"),p=this.options.bindingStore.setDshEnabledPlugins(i,r.pluginIds)??this.resolveDesiredSettings().revision;await this.options.bindingStore.flush();const u=M({...s,enabledPluginIds:r.pluginIds});if(!r.changed)return this.pushToolbarMeta(),{status:"ok",result:this.pluginActionResult(u,!1,"skipped")};if(this.runtimeStartPromise&&await this.runtimeStartPromise.catch(()=>{}),!this.runtime)return this.settingsState="applied",this.pushToolbarMeta(),{status:"ok",result:this.pluginActionResult(u,!0,"skipped")};if(this.active)return this.settingsState="pending",this.pushToolbarMeta(),{status:"ok",result:this.pluginActionResult(u,!0,"pending")};if(this.settingsState="pending",this.pushToolbarMeta(),await this.rebuildRuntime("plugin_changed"),!this.applied||this.applied.appliedRevision<p)throw new Error("new runtime did not apply requested plugin revision");return this.pushToolbarMeta(),{status:"ok",result:this.pluginActionResult(u,!0,"restarted")}}catch(n){return{status:"failed",errorCode:String(n?.code??"plugin_action_failed"),errorMsg:this.redactError(n)}}}async executeSkillAction(e,t,i){if(this.active)return{status:"failed",errorCode:"worker_busy",errorMsg:"Cannot change DeepSeek skills during an active turn"};if(!this.options.bindingStore.get(i))return{status:"failed",errorCode:"binding_missing",errorMsg:"Session binding missing. Open a workspace first."};if(this.sessionSkillControlUnavailable())return this.pushToolbarMeta(),{status:"unsupported",errorCode:"capability_unavailable",errorMsg:`DSH session skills require @deepseek-ai/dsh ${oe} or newer`};const s=this.skillCommandContext();try{if(e==="dsh_list_skills"){const o=R(s);return this.pushToolbarMeta(),{status:"ok",result:this.skillActionResult(o,!1)}}const n=String(t.name??t.skill_name??"").trim(),a=this.options.bindingStore.getDshEnabledSkills(i);let d=n;try{d=Pe({...s,name:n}).name}catch(o){const l=String(o?.code??"");if(e!=="dsh_disable_skill"||l!=="skill_not_found"||!a.includes(n))throw o}const r=ye(a,d,e==="dsh_enable_skill"),p=this.options.bindingStore.setDshEnabledSkills(i,r.skillIds)??this.resolveDesiredSettings().revision;await this.options.bindingStore.flush();const u=R({...s,enabledSkillIds:r.skillIds});if(!r.changed)return this.pushToolbarMeta(),{status:"ok",result:this.skillActionResult(u,!1,"skipped")};if(this.runtimeStartPromise&&await this.runtimeStartPromise.catch(()=>{}),!this.runtime)return this.settingsState="applied",this.pushToolbarMeta(),{status:"ok",result:this.skillActionResult(u,!0,"skipped")};if(this.active)return this.settingsState="pending",this.pushToolbarMeta(),{status:"ok",result:this.skillActionResult(u,!0,"pending")};if(this.settingsState="pending",this.pushToolbarMeta(),await this.rebuildRuntime("skill_changed"),!this.applied||this.applied.appliedRevision<p)throw new Error("new runtime did not apply requested skill revision");return this.pushToolbarMeta(),{status:"ok",result:this.skillActionResult(u,!0,"restarted")}}catch(n){return{status:"failed",errorCode:String(n?.code??"skill_action_failed"),errorMsg:this.redactError(n)}}}pluginActionResult(e,t,i="skipped"){const s=this.resolveSelectedProfile(),n=this.pluginRestartRequired();return{outcome:t?i==="restarted"?"plugin_applied":"plugin_updated":"plugin_unchanged",dsh_profile:s,dsh_plugins:e,dsh_plugin_restart_required:n,restart:i,session_context:{dsh_profile:s,dsh_plugins:e,dsh_plugin_restart_required:n}}}skillActionResult(e,t,i="skipped"){return{outcome:t?i==="restarted"?"skill_applied":"skill_updated":"skill_unchanged",dsh_skills:e,restart:i,session_context:{dsh_skills:e}}}resolveSelectedProfile(){const e=this.options.bindingStore.getDshSelectedProfile(this.options.aibotSessionId),t=Re({binding:e,global:this.options.globalConfigStore?.get(this.options.agentName)?.dshProfile,adapter:this.options.dshProfile});return this.options.bindingStore.get(this.options.aibotSessionId)&&e!==t&&this.options.bindingStore.setDshSelectedProfile(this.options.aibotSessionId,t),t}profileDataDir(e=this.resolveSelectedProfile()){return Me(this.options.dataRoot,e)}usageStore(){const e=this.resolveSelectedProfile(),t=w(this.profileDataDir(e),"session-usage.json"),i=w(this.options.dataRoot,"session-usage.json");return!W(t)&&W(i)&&(ce(ue(t),{recursive:!0,mode:448}),he(i,t)),ot(t)}presetActionResult(e,t){const i=this.resolveDesiredSettings();return{outcome:"preset_set",agentPreset:e,agent_preset_id:e,agent_preset_locked:t,available_presets:[...this.presets],session_context:{agent_preset_id:i.agentPreset??e,agent_preset_locked:t}}}settingsActionResult(e,t,i,s,n,a){const d=this.resolveDesiredSettings(),r=d.revision||i,p={provider_id:d.providerId,model_id:d.modelId,mode_id:d.modeId,thinking_mode:d.thinking,reasoning_effort:d.reasoningEffort,applied_provider_id:this.applied?.providerId??null,applied_model_id:this.applied?.modelId??null,applied_mode_id:this.applied?.modeId??null,applied_thinking_mode:this.applied?.thinking??null,applied_reasoning_effort:this.applied?.reasoningEffort??null,applied_settings_revision:this.applied?.appliedRevision??null,settings_state:this.settingsState,settings_revision:r};return e==="set_mode"&&(p.sandbox_mode=J(d.modeId),p.approval_policy=d.modeId==="full_auto"?"never":"ask"),{outcome:`${e==="set_provider"?"provider":e==="set_model"?"model":e==="set_thinking"?"thinking":e==="set_reasoning_effort"?"reasoning_effort":"mode"}_set${s==="pending"||s==="failed"?"_pending":""}`,...t.providerId?{providerId:t.providerId,provider_id:t.providerId}:{},...t.modelId?{modelId:t.modelId,model_id:t.modelId}:{},...t.modeId?{modeId:t.modeId,mode_id:t.modeId,sandbox_mode:J(t.modeId),approval_policy:t.modeId==="full_auto"?"never":"ask"}:{},...t.thinking?{thinking:t.thinking,thinking_mode:t.thinking}:{},...t.reasoningEffort?{reasoningEffort:t.reasoningEffort,reasoning_effort:t.reasoningEffort}:{},settingsRevision:r,settings_revision:r,sessionAlive:n,available_providers:[...this.providers],available_models:[...this.models],session_context:p,...a?{error:a}:{}}}hydrateCatalogFromCache(){const e=this.options.bindingStore.getDshSettings(this.options.aibotSessionId),t=this.options.globalConfigStore?.get(this.options.agentName),i=tt({dataRoot:this.options.dataRoot,providerId:e?.providerId??t?.dshProviderId});this.providers=i.providers,this.models=this.options.models?.length?this.options.models:i.models,this.catalogProviderId=i.providerId}async persistCatalogCache(e){try{await it({dataRoot:this.options.dataRoot,providers:this.providers,providerId:e,models:this.models})}catch(t){f.warn(m,`failed to persist DSH catalog cache: ${t instanceof Error?t.message:String(t)}`)}}syncGrixProvider(){const e=ee(this.options.provider??{});if(e){this.providers.some(n=>n.id===b)||(this.providers=[{id:b,displayName:e.displayName},...this.providers]);const t=this.options.bindingStore.getDshSettings(this.options.aibotSessionId),i=this.options.globalConfigStore?.get(this.options.agentName),s=t?.providerId??i?.dshProviderId;(!s||s===$||s===b)&&this.options.bindingStore.updateDshSettings(this.options.aibotSessionId,{providerId:b});return}this.providers=this.providers.filter(t=>t.id!==b)}resolveDesiredSettings(){const e=this.options.bindingStore.get(this.options.aibotSessionId),t=this.options.bindingStore.getDshSettings(this.options.aibotSessionId),i=this.options.globalConfigStore?.get(this.options.agentName),s=t?.providerId??i?.dshProviderId,n=this.providers.some(p=>p.id===b)?b:void 0,a=Ye(s||n,this.providers),d=[t?.modelId,i?.dshModelId,this.options.defaultModel,this.models[0]?.id].find(p=>!!p&&this.models.some(u=>u.id===p))??"deepseek-chat",r=Y(t?.agentPreset??i?.dshAgentPreset,this.presets);return{providerId:a,modelId:d,modeId:Je(e?.dshModeId,i?.dshModeId),thinking:N(t?.thinking)??N(i?.dshThinking)??Qe,reasoningEffort:B(t?.reasoningEffort)??B(i?.dshReasoningEffort)??ze,agentPreset:r,pluginIds:this.options.bindingStore.getDshEnabledPlugins(this.options.aibotSessionId),skillIds:this.options.bindingStore.getDshEnabledSkills(this.options.aibotSessionId),skillIdsExplicit:Array.isArray(e?.dshSkillIds),maxTokens:t?.maxTokens??this.options.maxTokens??Oe,revision:t?.revision??0}}resolveIntegrationMode(){return this.options.integrationMode?this.options.integrationMode:(this.config.command||"").includes("dsh-jsonrpc-agent")?"embedded_jsonrpc":"profile_bridge"}sessionSkillControlUnavailable(){return this.resolveIntegrationMode()!=="profile_bridge"?!1:this.bridgeCapabilities&&typeof this.bridgeCapabilities=="object"?this.bridgeCapabilities.sessionSkillAllowlist!==!0:gt(this.profileDshVersion)}pushToolbarMeta(){const e=this.options.bindingStore.get(this.options.aibotSessionId);this.callbacks.sendUpdateBindingCard(this.options.aibotSessionId,this.stopped?"stopped":this.active?"busy":"ready",e?.cwd,Ve({desired:this.resolveDesiredSettings(),applied:this.applied,models:this.models,providers:this.providers,presets:this.presets,agentPresetLocked:this.options.bindingStore.isDshAgentPresetLocked(this.options.aibotSessionId),state:this.settingsState,errorCode:this.settingsErrorCode,contextWindow:this.contextWindow,providerQuota:this.providerQuota,integrationMode:this.resolveIntegrationMode(),profileName:this.resolveSelectedProfile(),profiles:this.listProfiles(),profileLocked:this.options.bindingStore.isDshProfileLocked(this.options.aibotSessionId),plugins:this.currentPlugins(),skills:this.currentSkills(),pluginRestartRequired:this.pluginRestartRequired(),runtimeReadiness:this.runtimeReadiness,bridgeCapabilities:this.bridgeCapabilities}))}async refreshProviderQuota(e){this.providerQuota=null,this.pushToolbarMeta();try{this.providerQuota=await this.callbacks.queryProviderQuota(e)??{provider:"deepseek",providerLabel:"DeepSeek",success:!1,error:"unavailable"}}catch{this.providerQuota={provider:"deepseek",providerLabel:"DeepSeek",success:!1,error:"unavailable"}}this.pushToolbarMeta()}clearPendingApprovals(e){for(const t of this.pendingApprovals.values())clearTimeout(t.timer),t.resolve(e);this.pendingApprovals.clear()}thinkingEnabled(){const e=this.active?.inbound.connector_runtime_config?.thinking_events??this.active?.inbound.connector_runtime_config?.thinkingEvents;return e!=="off"&&e!=="hidden"&&e!=="none"}toolEventsEnabled(){const e=this.active?.inbound.connector_runtime_config?.tool_events;return e!=="off"&&e!=="hidden"&&e!=="none"}sendRaw(e,t,i){this.active&&this.callbacks.sendRawEventEnvelope(this.active.inbound.event_id,this.active.inbound.session_id,{type:e,payload:t},i)}failEvent(e,t){this.callbacks.sendEventResult(e.event_id,"failed",t),this.emit("eventDone",e.event_id)}startTimeout(e){this.activeTimeoutMs=e??this.options.promptTimeoutMs??te,this.noteRuntimeActivity(),this.armTimeout(this.activeIdleTimeoutMs()),this.armHardTimeout(this.activeTimeoutMs)}touchActivity(e=1){!this.active||!this.timeoutTimer||(this.noteRuntimeActivity(),this.armTimeout(this.activeIdleTimeoutMs()))}noteRuntimeActivity(){this.active&&(this.active.lastRuntimeActivityAt=Date.now(),this.active.livenessExtendStartAt=void 0)}activeIdleTimeoutMs(){const e=this.options.activeIdleTimeoutMs??ie,t=Number.isFinite(e)&&e>0?e:ie;return Math.min(t,this.activeTimeoutMs)}livenessFreshMs(){const e=this.options.livenessFreshMs??se;return Number.isFinite(e)&&e>0?e:se}livenessMaxExtendMs(){const e=this.options.livenessMaxExtendMs??ne;return Number.isFinite(e)&&e>0?e:ne}armTimeout(e){this.clearIdleTimeout(),this.timeoutTimer=setTimeout(()=>{this.handlePromptTimeout()},e),this.timeoutTimer.unref?.()}armHardTimeout(e){this.clearHardTimeout(),this.hardTimeoutTimer=setTimeout(()=>{this.handlePromptHardTimeout()},e),this.hardTimeoutTimer.unref?.()}async handlePromptTimeout(){const e=this.active;if(e){if(this.pendingApprovals.size>0){f.info(m,`Idle timeout skipped: pendingApprovals=${this.pendingApprovals.size} event=${e.inbound.event_id}`),this.armTimeout(this.activeIdleTimeoutMs());return}if(this.shouldExtendByLiveness(e.inbound.event_id)){this.armTimeout(this.activeIdleTimeoutMs());return}await this.failActiveTimeout("idle","Harness prompt idle timeout and the runtime was terminated")}}async handlePromptHardTimeout(){const e=this.active;if(e&&this.shouldExtendByLiveness(e.inbound.event_id)){this.armHardTimeout(this.activeTimeoutMs);return}await this.failActiveTimeout("hard","Harness prompt exceeded max duration and the runtime was terminated")}shouldExtendByLiveness(e){const t=this.active;if(!t||t.inbound.event_id!==e||!this.runtime?.isConnected()||!(!t.turnEnded&&(!!t.messageId||t.admitted||t.claimed)))return!1;const s=Date.now(),n=t.lastRuntimeActivityAt??t.startedAt,a=Math.max(0,s-n);if(a<this.livenessFreshMs())return t.livenessExtendStartAt=s,f.info(m,`Liveness check: recent DSH activity for ${e} (quietMs=${a}), extending`),!0;const d=t.livenessExtendStartAt??n;t.livenessExtendStartAt=d;const r=s-d;return r>this.livenessMaxExtendMs()?(f.warn(m,`Liveness extension budget exhausted for ${e} (quietMs=${a}, extendMs=${r}), allowing close`),!1):(f.info(m,`Liveness check: DSH turn still open for ${e} (claimed=${t.claimed}, turnEnded=${t.turnEnded}, quietMs=${a}), extending`),!0)}async failActiveTimeout(e,t){if(!this.active)return;const i=this.active;this.clearTimeout();const s=this.runtime;this.runtime=null,this.intentionalRuntimeStop=!0,this.contextWindow=null,this.reportedContextCapacity=null,this.applied=void 0,this.settingsState="applied",this.settingsErrorCode=null,this.pushToolbarMeta(),await s?.cancel(this.runtimeSessionId).catch(()=>{}),s&&await s.shutdown().catch(()=>s.terminate()),this.intentionalRuntimeStop=!1,!(this.active!==i||this.stopped)&&(f.error(m,`Active DSH turn ${e} timeout: ${i.inbound.event_id}`),this.finishActive("failed",t),this.emit("exit",1))}clearTimeout(){this.clearIdleTimeout(),this.clearHardTimeout()}clearIdleTimeout(){this.timeoutTimer&&clearTimeout(this.timeoutTimer),this.timeoutTimer=null}clearHardTimeout(){this.hardTimeoutTimer&&clearTimeout(this.hardTimeoutTimer),this.hardTimeoutTimer=null}redactError(e,t){let i=e instanceof Error?e.message:String(e);const s=this.config.env?.DEEPSEEK_API_KEY;return s&&(i=i.split(s).join("[REDACTED]")),i=i.replace(/(api[_-]?key|authorization|bearer)\s*[:=]\s*\S+/gi,"$1=[REDACTED]"),t&&t.length>=16&&i.includes(t)&&(i="Harness request failed (prompt echo redacted)"),(i.includes("[aibot-system-prompt]")||i.includes("[base-behavior]"))&&(i="Harness runtime failed (system prompt echo redacted)"),i.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g,"").slice(0,2e3)}}function ht(h){const e=Number(h&&typeof h=="object"?h.cursor:0);return Number.isSafeInteger(e)&&e>0?e:0}function ct(h){return new Promise(e=>setTimeout(e,h))}function ut(h,e){return`grix-${D("sha256").update(h).digest("hex").slice(0,12)}-${e}-${x().slice(0,8)}`}function pt(h){return`grix-${D("sha256").update(h).digest("hex").slice(0,16)}-${x().slice(0,8)}`}function re(){return{inputTokens:0,outputTokens:0,cacheReadInputTokens:0,cacheCreationInputTokens:0,reasoningTokens:0}}function gt(h){const e=ft(h,oe);return e!==null&&e<0}function ft(h,e){const t=ae(h),i=ae(e);return!t||!i?null:t.major-i.major||t.minor-i.minor||t.patch-i.patch||mt(t.prerelease,i.prerelease)}function ae(h){const e=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/.exec(String(h??"").trim());return e?{major:Number(e[1]),minor:Number(e[2]),patch:Number(e[3]),...e[4]?{prerelease:e[4]}:{}}:null}function mt(h,e){if(h===e)return 0;if(h===void 0)return 1;if(e===void 0)return-1;const t=h.split("."),i=e.split(".");for(let s=0;s<Math.max(t.length,i.length);s+=1){const n=t[s],a=i[s];if(n===a)continue;if(n===void 0)return-1;if(a===void 0)return 1;const d=/^\d+$/.test(n),r=/^\d+$/.test(a);return d&&r?Number(n)-Number(a):d!==r?d?-1:1:n<a?-1:1}return 0}function de(h){const e=h.data?.chunk&&typeof h.data.chunk=="object"?h.data.chunk:h.data;return String(e?.type??"")}function vt(h){return h.type==="assistant/chunk:tool-call-delta"||h.type==="assistant/chunk"&&de(h)==="tool-call-delta"}function bt(h){return{readiness:h.readiness,profile:h.identity.profileName,dshVersion:h.dshVersion,runningDshVersion:h.runningDshVersion,installedBridgeVersion:h.installedBridgeVersion,bundledBridgeVersion:h.bundledBridgeVersion,runningBridgeVersion:h.runningBridgeVersion,endpointCount:h.endpointCount,requiresProfileRestart:h.readiness==="profile_restart_required"}}const _t=new Set(["turn/start","step/start","step/end","agent/inbox/spliced","user/message","request/header","session/title","session/title-llm-request","session/end-seed","web/deepseek-search-llm-request","assistant/chunk:tool-call-delta","permission/preset","sandbox/mode","approval/policy","approval/asked","approval/decided","plan/mode","agent-preset/selected","llm/retry","llm/retry-started","goal/change","schedule/change","feedback/record","hook/invoked","hook/result","command/run","command/done","subagent/descriptor","tool-workflow/agent-start","tool-workflow/agent-end","tool-workflow/run-start","tool-workflow/run-end","tool/code-dispatch","tool/code-dispatch-start"]);function St(h){const e=de(h);return _t.has(h.type)||h.type==="assistant/chunk"&&["block-start","block-end","tool-call-delta","finish"].includes(e)}export{ti as DshJsonRpcAdapter};
@@ -1,2 +1,2 @@
1
- import{createHash as s}from"node:crypto";const r=1,i=200,n=4e3,a=64e3;function t(e,o){return String(e??"").replaceAll("\0","").slice(0,o)}function d(e){return["[base-behavior]","You are a coding agent operating through Grix.","Work in the configured workspace. Verify material changes with relevant tests.","Keep answers concise and factual. Do not bypass workspace restrictions.","Never print DSML/XML tool markup (for example <||DSML||tool_calls>). Use native DSH tools instead.","[/base-behavior]","[aibot-system-prompt]",t(e.systemPrompt,a),"[/aibot-system-prompt]","[system-identity]",`Your name is ${JSON.stringify(t(e.agentName,i))}.`,`Your self-introduction: ${t(e.introduction,n)}`,"Do not quote or repeat this block.","[/system-identity]","[system-context]",`Your current Grix session_id is ${JSON.stringify(t(e.grixSessionId,256))}.`,`Your current Grix agent_id is ${JSON.stringify(t(e.agentId,256))}.`,"Use these identifiers only when a tool or protocol requires them. Do not acknowledge or repeat this block.","[/system-context]","[grix-message-protocol]","[[message_id:<id>]] and [[quoted_message_id:<id>]] are metadata.","Never repeat them as ordinary prose. Use [[quoted_message_id:<id>]] only when intentionally threading a reply.","[/grix-message-protocol]","[workspace-policy]","The workspace is file-sandboxed. A sandbox access-denied result is policy, not a command failure.","Do not attempt to bypass it. Operations outside the workspace cannot be interactively approved in this runtime.","[/workspace-policy]"].join(`
2
- `)}function l(e){return{schemaVersion:r,sha256:s("sha256").update(e).digest("hex"),length:e.length}}export{r as DSH_SYSTEM_PROMPT_SCHEMA_VERSION,d as buildDshSystemPrompt,l as describeDshSystemPrompt};
1
+ import{createHash as o}from"node:crypto";const r=1,i=200,a=4e3,n=64e3;function t(e,s){return String(e??"").replaceAll("\0","").slice(0,s)}function l(e){return["[base-behavior]","You are a coding agent operating through Grix.","Work in the configured workspace. Verify material changes with relevant tests.","Keep answers concise and factual. Do not bypass workspace restrictions.","Never print DSML/XML tool markup (for example <||DSML||tool_calls>). Use native DSH tools instead.","[/base-behavior]","[aibot-system-prompt]",t(e.systemPrompt,n),"[/aibot-system-prompt]","[system-identity]",`Your name is ${JSON.stringify(t(e.agentName,i))}.`,`Your self-introduction: ${t(e.introduction,a)}`,"Do not quote or repeat this block.","[/system-identity]","[system-context]",`Your current Grix session_id is ${JSON.stringify(t(e.grixSessionId,256))}.`,`Your current Grix agent_id is ${JSON.stringify(t(e.agentId,256))}.`,"Use these identifiers only when a tool or protocol requires them. Do not acknowledge or repeat this block.","[/system-context]","[grix-message-protocol]","[[message_id:<id>]] and [[quoted_message_id:<id>]] are metadata.","Never repeat them as ordinary prose. Use [[quoted_message_id:<id>]] only when intentionally threading a reply.","[/grix-message-protocol]","[reply-protocol]","Your plain assistant text is delivered to the user as a chat message automatically.","Answer the current request in plain text; never send the same answer again via grix_reply or grix_message_send \u2014 that delivers a duplicate.","Use grix_reply only when you need its extras (for example quoting a specific earlier message). After calling it, end the turn silently: any later text is discarded.","[/reply-protocol]","[workspace-policy]","The workspace is file-sandboxed. A sandbox access-denied result is policy, not a command failure.","Do not attempt to bypass it. Operations outside the workspace cannot be interactively approved in this runtime.","[/workspace-policy]"].join(`
2
+ `)}function d(e){return{schemaVersion:r,sha256:o("sha256").update(e).digest("hex"),length:e.length}}export{r as DSH_SYSTEM_PROMPT_SCHEMA_VERSION,l as buildDshSystemPrompt,d as describeDshSystemPrompt};
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "bridgeVersion": "3.31.1",
4
- "tarball": "grix-dsh-bridge-3.31.1.tgz",
5
- "size": 21943,
6
- "unpackedSize": 87443,
7
- "shasum": "e0e7ae4e112502d33f67e5baf7fb90e313a4a8c0",
8
- "integrity": "sha512-SXnrTODRW4WGAcIANT+aIoWbN3KFl4lb1OiNccgIXIm9eT2Na5hjlBjay3j8Otg2uAjA8PZYNbRy0+OMUaNaRQ=="
3
+ "bridgeVersion": "3.31.3",
4
+ "tarball": "grix-dsh-bridge-3.31.3.tgz",
5
+ "size": 22013,
6
+ "unpackedSize": 87635,
7
+ "shasum": "cf98c08bfa28debe6c138bc1e01099461310d8cb",
8
+ "integrity": "sha512-j4K8nz7XSaqzwRPuuedjYRGgY75uzL8jmCDBzf40QmlaKf21hC78u3jnqt/IccPmLdEuV+NmtcgVOuel8xd2Fg=="
9
9
  }
@@ -1 +1 @@
1
- const r=[{name:"grix_query",description:"Search contacts, sessions, message history, messages, or favorited sessions in the Grix/AIBot platform. message_history defaults to the newest one clean text/approval-card message and excludes process/tool cards.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["contact_search","session_search","message_history","message_search","search_favorite_sessions"],description:"Query action type. search_favorite_sessions returns the owner's favorited sessions (supports keyword filter)."},id:{type:"string",description:"Contact ID (contact_search) or Session ID (session_search)."},keyword:{type:"string",description:"Search keyword."},sessionType:{type:"integer",enum:[1,2],description:"Filter by session type (session_search only): 1=private chat, 2=group chat. Omit to return all."},limit:{type:"integer",description:"Max results. message_history defaults to 1 when omitted."},offset:{type:"integer",description:"Result offset."},sessionId:{type:"string",description:"Session ID (message_history, message_search)."},beforeId:{type:"string",description:"Pagination cursor (message_history, message_search)."}},required:["action"]},validation:{required:["action"],properties:{action:{type:"string",enum:["contact_search","session_search","message_history","message_search","search_favorite_sessions"]},id:{type:"string"},keyword:{type:"string",maxLength:200},sessionType:{type:"integer",enum:[1,2]},limit:{type:"integer",minimum:1,maximum:100},offset:{type:"integer",minimum:0},sessionId:{type:"string"},beforeId:{type:"string"}}}},{name:"grix_audit_data",description:"Read connector-backed conversation audit replay data from Grix/AIBot: manifest, span pages, and content chunks.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["get_manifest","list_spans","get_content_chunk"],description:"Audit read action. Start with get_manifest, then call list_spans and/or get_content_chunk based on the manifest."},auditId:{type:"string",description:"Audit ID returned by the audited turn metadata."},revision:{type:"integer",description:"Optional manifest revision to read. Usually use the revision returned by get_manifest."},cursor:{type:"string",description:"Opaque pagination cursor returned by list_spans or get_content_chunk."},limit:{type:"integer",description:"Max span items for list_spans."},contentId:{type:"string",description:"Content reference ID from manifest.content_refs (get_content_chunk only)."},maxBytes:{type:"integer",description:"Max UTF-8 bytes to return for get_content_chunk."}},required:["action","auditId"]},validation:{required:["action","auditId"],properties:{action:{type:"string",enum:["get_manifest","list_spans","get_content_chunk"]},auditId:{type:"string"},revision:{type:"integer",minimum:1},cursor:{type:"string",maxLength:4096},limit:{type:"integer",minimum:1,maximum:200},contentId:{type:"string"},maxBytes:{type:"integer",minimum:1,maximum:131072}}}},{name:"grix_group",description:"Manage groups in the Grix/AIBot platform: create, get details, leave, dissolve, manage members and permissions.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","detail","leave","add_members","remove_members","update_member_role","update_all_members_muted","update_member_speaking","dissolve"],description:"Group action type."},sessionId:{type:"string",description:"Group session ID."},name:{type:"string",description:"Group name (create)."},memberIds:{type:"array",items:{type:"string"},description:"Member IDs to add/remove."},memberTypes:{type:"array",items:{type:"integer",enum:[1,2]},description:"Member types (1=user, 2=agent)."},memberId:{type:"string",description:"Target member ID."},role:{type:"integer",enum:[1,2],description:"New role (1=admin, 2=member)."},memberType:{type:"integer",description:"Member type."},allMembersMuted:{type:"boolean",description:"Whether to mute all members."},isSpeakMuted:{type:"boolean",description:"Whether member is muted."},canSpeakWhenAllMuted:{type:"boolean",description:"Allow speaking when all muted."}},required:["action"]},validation:{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"}}}},{name:"grix_message_send",description:"Send a message to a session in the Grix/AIBot platform.",inputSchema:{type:"object",properties:{sessionId:{type:"string",description:"Target session ID"},content:{type:"string",description:"Message content"},msgType:{type:"integer",description:"Message type (1=text, default 1)"},quotedMessageId:{type:"string",description:"Message ID to reply to"},threadId:{type:"string",description:"Thread ID for threaded reply"}},required:["sessionId","content"]},validation:{required:["sessionId","content"],properties:{sessionId:{type:"string"},content:{type:"string",maxLength:1e4},msgType:{type:"integer"},quotedMessageId:{type:"string"},threadId:{type:"string"}}}},{name:"grix_message_unsend",description:"Recall/unsend a message in the Grix/AIBot platform.",inputSchema:{type:"object",properties:{sessionId:{type:"string",description:"Session ID"},msgId:{type:"string",description:"Message ID to unsend"}},required:["sessionId","msgId"]},validation:{required:["sessionId","msgId"],properties:{sessionId:{type:"string"},msgId:{type:"string"}}}},{name:"grix_file_link",description:"Create a direct, tailnet-only download link for a local file on this host. Use this whenever the user asks you to send, share, give, or deliver a file that exists on the machine where you run (a report, log, build artifact, export, or any local path). It returns a ready-to-use Markdown link in the `markdown` field \u2014 include that exact Markdown link in your reply so the user can click and download the file directly over the shared Tailscale network. The link is reachable only inside the tailnet, so just send it as-is \u2014 no need to worry about or mention any link lifetime. The download link is HTTPS, served by a built-in self-signed CA. The result also returns `ca_install_url`: the first time you share a link with a user (or whenever their browser warns the cert is untrusted), also give them this CA install link so they can install and trust it once \u2014 after that all download links work without warnings. Requires this host to be on a tailnet (Tailscale running).",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to a local file on this host to share with the user."},ttl_ms:{type:"integer",description:"Optional link lifetime in milliseconds. Leave unset to use the long default; set only if you deliberately want a short-lived link."}},required:["file_path"]},validation:{required:["file_path"],properties:{file_path:{type:"string",maxLength:4096},ttl_ms:{type:"integer",minimum:1e4,maximum:864e5}}}},{name:"grix_file_upload",description:"Upload a local file to the Grix platform and send it as a media message in the target session. Supports images (jpg/png/webp/gif/bmp/heic/heif), videos (mp4/mov/m4v/webm/mkv/avi), documents (pdf/doc/docx/xls/xlsx/ppt/pptx/txt/md/csv/json/xml), and archives (zip/rar/7z/tar/gz). Max 50 MB. Use this instead of grix_file_link when the file should appear as a native attachment in the chat (visible inline for images/videos), rather than a tailnet download link.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to a local file to upload."},session_id:{type:"string",description:"Target session ID to send the file to."},caption:{type:"string",description:"Optional text caption for the media message."},reply_to_message_id:{type:"string",description:"Optional message ID to quote/reply to."}},required:["file_path","session_id"]},validation:{required:["file_path","session_id"],properties:{file_path:{type:"string",maxLength:4096},session_id:{type:"string"},caption:{type:"string",maxLength:2e3},reply_to_message_id:{type:"string"}}}},{name:"grix_admin",description:"Agent and category management in the Grix/AIBot platform: create agents, manage categories, rotate API keys.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create_agent","list_categories","create_category","update_category","assign_category","rotate_api_key"],description:"Admin action type."},agentName:{type:"string",description:"Agent name (create_agent)."},introduction:{type:"string",description:"Professional behavioral introduction describing the Agent purpose, responsibilities, operating expectations, and boundaries (create_agent)."},isMain:{type:"boolean",description:"Set as main agent (create_agent)."},agentId:{type:"string",description:"Agent ID (assign_category, rotate_api_key)."},categoryId:{type:"string",description:"Category ID (create_agent, update_category, assign_category)."},name:{type:"string",description:"Category name (create_category, update_category)."},parentId:{type:"string",description:"Parent category ID (create_category, update_category)."},sortOrder:{type:"integer",description:"Sort order (create_category, update_category)."}},required:["action"]},validation:{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"}}}},{name:"grix_call_owner",description:"Call your owner into this session to talk by voice. Use this when, during your work, you need to reach your owner \u2014 to discuss something or to get an approval/review. It sends the owner an offline notification; when they tap it they land directly in this conversation and a voice-brain call is started automatically. Requires the owner to have configured a voice brain. Rate-limited per session.",inputSchema:{type:"object",properties:{session_id:{type:"string",description:"The session ID to call the owner into."}},required:["session_id"]},validation:{required:["session_id"],properties:{session_id:{type:"string"}}}},{name:"grix_agent_update",description:"Update the display name and/or text introduction of one of your owner's agents, identified by its numeric agent ID. Provide agent_name, introduction, or both \u2014 at least one is required.",inputSchema:{type:"object",properties:{agent_id:{type:"string",description:"Target agent's numeric ID, passed as a string."},agent_name:{type:"string",description:"New display name (max 100 characters, must be unique among the owner's agents)."},introduction:{type:"string",description:"New text introduction (max 300 characters)."}},required:["agent_id"]},validation:{required:["agent_id"],properties:{agent_id:{type:"string"},agent_name:{type:"string",maxLength:100},introduction:{type:"string",maxLength:300}}}},{name:"grix_dispatch_agent",description:`Dispatch one of your owner's agents to do work in a given working directory. Provide the target agent numeric ID, the working directory, and a text description of the task. The backend creates a NEW private session between the owner and that agent for each dispatch (it does not reuse past sessions), binds the working directory when the agent type requires it (claude/codex/etc.), and sends the task into the session AS THE OWNER so the agent starts working. Because the task is delivered as the owner, write it in the owner's first-person voice and tone \u2014 phrase it the way the owner would speak directly to the agent (e.g. "\u5E2E\u6211\u2026", "\u4F60\u53BB\u2026"), NOT as a third-person relay or as yourself narrating on the owner's behalf. Provide a short title summarizing the core of the task \u2014 it becomes the new session's title; if omitted the backend derives one from the task text.`,inputSchema:{type:"object",properties:{agent_id:{type:"string",description:"Target agent's numeric ID, passed as a string."},cwd:{type:"string",description:"Absolute working directory where the agent should do the work."},task:{type:"string",description:"Text description of the task to perform, written in the owner's first-person voice and tone \u2014 it is delivered into the session as the owner, so phrase it as the owner speaking directly to the agent, not as a third-person relay."},title:{type:"string",description:"Optional short title (a few words) summarizing the core of the task; used as the new session's title. If omitted, the backend derives a title from the task text."}},required:["agent_id","cwd","task"]},validation:{required:["agent_id","cwd","task"],properties:{agent_id:{type:"string"},cwd:{type:"string",maxLength:4096},task:{type:"string",maxLength:1e4},title:{type:"string",maxLength:255}}}},{name:"grix_session_send",description:"Send a message into a session AS THE OWNER \u2014 it appears as if the owner sent it, NOT as you (the agent). Dispatch callbacks (report_dispatch_result) MUST use this tool, even when you are a member of the callback session: a message sent as yourself cannot quote-wake the dispatcher agent, and your membership is not checked. NEVER use this for your own ordinary replies in a conversation \u2014 that would make your words show up as the owner's message; reply normally (or use grix_message_send to send as yourself) for those. The owner must be a member of the target session. Requires the Send as Owner permission scope \u2014 if rejected for missing permission, surface the error as-is so the owner can grant it; do not fall back to grix_message_send. Optional quoted_message_id quotes a message in the same session (used by dispatch callbacks to wake the dispatcher agent).",inputSchema:{type:"object",properties:{session_id:{type:"string",description:"Target session ID."},content:{type:"string",description:"Message content to send as the owner."},quoted_message_id:{type:"string",description:"Optional message ID in the target session to quote/reply to.",pattern:"^[1-9]\\d*$"}},required:["session_id","content"]},validation:{required:["session_id","content"],properties:{session_id:{type:"string"},content:{type:"string",maxLength:1e4},quoted_message_id:{type:"string",pattern:"^[1-9]\\d*$"}}}},{name:"grix_chat_state_query",description:"Query the chat-level task states across all of your owner's sessions (including direct and group chats). Returns one entry per session with a single mutually-exclusive state: running (working), waiting_approval (blocked on your owner to approve/deny), waiting_question (asked the owner a question, awaiting their reply), completed, failed, or idle (no task / stopped). When session_id identifies one completed session, the entry also includes exactly one clean final_result; non-completed and list queries never include message content. Also returns the session title (task_title) for easy identification. Supports pagination (page/page_size) and optional state filtering. Use this to see at a glance which chats are done, still running, or waiting on the owner.",inputSchema:{type:"object",properties:{session_id:{type:"string",description:"(Optional) Query a single session by its ID. Omit to return all sessions."},page:{type:"number",description:"(Optional) Page number, starting from 1. Defaults to 1 if omitted."},page_size:{type:"number",description:"(Optional) Number of items per page, max 100. Defaults to 10 if omitted."},state:{type:"string",description:"(Optional) Filter by a specific state: running, waiting_approval, waiting_question, completed, failed, or idle. Omit to return all states."}}},validation:{required:[],properties:{}}},{name:"grix_chat_state_update",description:"Manually update the task state of a specific chat session. Use this to mark a chat as completed, failed, idle, or any other state when you need to override it manually. The reason is written to stop_reason and is optional.",inputSchema:{type:"object",properties:{session_id:{type:"string",description:"The session ID whose state to update."},state:{type:"string",enum:["running","waiting_approval","waiting_question","completed","failed","idle"],description:"The new state to set. Must be one of: running, waiting_approval, waiting_question, completed, failed, idle."},reason:{type:"string",description:"(Optional) Reason for the state change, written to stop_reason."}}},validation:{required:["session_id","state"],properties:{}}},{name:"grix_access_control",description:"Manage sender access control: pair approval, allow/remove senders, set policy.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["pair_approve","pair_deny","allow_sender","remove_sender","set_policy"],description:"Access control action type."},code:{type:"string",description:"Pairing code (required for pair_approve/pair_deny)."},sender_id:{type:"string",description:"Sender ID (required for allow_sender/remove_sender)."},policy:{type:"string",enum:["allowlist","open","disabled"],description:"Access policy (required for set_policy)."}},required:["action"]},validation:{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"]}}}},{name:"grix_widget_visitor_ban",description:"Ban a widget visitor session: blocks the session and adds its most recent init IP to the owner's global IP ban list (7-day expiry).",inputSchema:{type:"object",properties:{session_id:{type:"string",description:"Widget visitor session ID (required)."}},required:["session_id"]},validation:{required:["session_id"],properties:{session_id:{type:"string"}}}},{name:"grix_skill_set",description:"Create, update, or delete one of your owner's custom skills in the platform skill library. The skill library auto-syncs to every machine the owner runs an agent on (a per-machine `grix/skills` directory), so defining a skill here makes it available on all of them. A skill is a plain SKILL.md package (frontmatter + body), same standard as other Grix skills. Provide `name` and the full `content` (the SKILL.md text) to create or overwrite by name. To delete a skill, pass its `name` with an empty `content` string. How and when any agent actually loads/uses a synced skill is arranged by the owner (in a system prompt or in conversation); this tool only manages the library.",inputSchema:{type:"object",properties:{name:{type:"string",description:"Skill name (max 100 characters); unique within the owner. Used as the identifier and the synced directory name."},content:{type:"string",description:"Full SKILL.md text. Pass an empty string to delete the skill by name."}},required:["name","content"]},validation:{required:["name","content"],properties:{name:{type:"string",maxLength:100},content:{type:"string",maxLength:262144}}}},{name:"grix_skill_get",description:"Read one of your owner's custom skills by name (returns its full SKILL.md content), or list the owner's skill library when no name is given. Use this before editing to fetch current content, then call grix_skill_set with the revised text.",inputSchema:{type:"object",properties:{name:{type:"string",description:"Skill name to fetch. Omit to list all skills (names + versions) instead."}}},validation:{required:[],properties:{name:{type:"string",maxLength:100}}}}],a=[{name:"grix_reply",description:"Send your final reply \u2014 the conclusion the user is waiting for \u2014 to the specified session. This is the message the user treats as your answer; deliver your final result here, and use plain text only for brief progress notes while you work. Supports streaming in chunks; the frontend automatically aggregates them into one complete message. The connector quotes the message being answered automatically, so quoted_message_id is optional (set it only to quote a different earlier message).",inputSchema:{type:"object",properties:{event_id:{type:"string",description:"Associated event ID from the inbound event."},session_id:{type:"string",description:"Target session ID."},text:{type:"string",description:"Reply text content."},quoted_message_id:{type:"string",description:"Quoted message ID (optional)."},is_final:{type:"boolean",description:"Whether this is a stage-final reply. Advisory only \u2014 does not trigger event completion; completion is handled by the complete tool or Stop hook."}},required:["session_id","text"]},validation:{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"}}}},{name:"grix_complete",description:"Mark event processing as complete, notifying the backend that no more replies are expected.",inputSchema:{type:"object",properties:{event_id:{type:"string",description:"The event ID to complete."},status:{type:"string",enum:["responded","canceled","failed"],description:"Completion status."},msg:{type:"string",description:"Additional note (optional)."}},required:["event_id","status"]},validation:{required:["event_id","status"],properties:{event_id:{type:"string"},status:{type:"string",enum:["responded","canceled","failed"]},msg:{type:"string",maxLength:500}}}},{name:"grix_event_ack",description:"Acknowledge event receipt (usually done automatically by the Dispatcher; agents typically do not need to call this manually).",inputSchema:{type:"object",properties:{event_id:{type:"string",description:"The event ID to acknowledge."},session_id:{type:"string",description:"Session ID."}},required:["event_id"]},validation:{required:["event_id"],properties:{event_id:{type:"string"},session_id:{type:"string"}}}},{name:"grix_composing",description:'Set the "typing" indicator status for a session.',inputSchema:{type:"object",properties:{session_id:{type:"string",description:"Session ID."},active:{type:"boolean",description:"true = typing, false = stopped."},event_id:{type:"string",description:"Associated event ID (optional)."}},required:["session_id","active"]},validation:{required:["session_id","active"],properties:{session_id:{type:"string"},active:{type:"boolean"},event_id:{type:"string"}}}},{name:"grix_status",description:"Query the Grix connection status of the current MCP session.",inputSchema:{type:"object",properties:{}},validation:{required:[],properties:{}}}],v={grix_dispatch_agent:"grix-agent-dispatch",grix_agent_update:"grix-agent-dispatch",grix_query:"grix-query",grix_audit_data:"grix-audit-data",grix_group:"grix-group",grix_message_send:"message-send",grix_message_unsend:"message-unsend",grix_admin:"grix-admin",grix_call_owner:"grix-owner-relay",grix_session_send:"grix-owner-relay",grix_chat_state_query:"grix-chat-state",grix_chat_state_update:"grix-chat-state",grix_status:"grix-chat-state",grix_access_control:"grix-access-control",grix_widget_visitor_ban:"grix-widget-visitor-ban",grix_file_link:"tailnet-file-share"};function w(e){return` Before calling this tool, follow the \`${e}\` skill's procedure first; do not invoke this tool directly without going through that skill's guidance.`}for(const e of[...r,...a]){const t=v[e.name];t&&(e.description+=w(t))}const p=[{name:"reply",description:"Send a visible message back to the chat for this grix-claude event.",inputSchema:{type:"object",properties:{text:{type:"string",description:"The visible reply text to send."},chat_id:{type:"string",description:"The target chat/session id from the <channel> tag."},event_id:{type:"string",description:"The Aibot event_id from the <channel> tag."},reply_to:{type:"string",description:"Optional message_id to quote instead of the inbound trigger message."},final:{type:"boolean",description:"Advisory flag only. It does not complete the event; completion is handled by complete tool or Stop hook."}},required:["chat_id","event_id","text"]}},{name:"complete",description:"Finish an event without sending a visible reply so the backend does not time out.",inputSchema:{type:"object",properties:{event_id:{type:"string",description:"The Aibot event_id from the <channel> tag."},status:{type:"string",enum:["responded","canceled","failed"]},msg:{type:"string"},code:{type:"string"}},required:["event_id","status"]}}],c=new Set(p.map(e=>e.name)),x=new Set(r.map(e=>e.name)),k=new Set(a.map(e=>e.name)),I=/([A-Za-z0-9._-]+:[A-Za-z0-9._-]+:[A-Za-z0-9._-]+:[A-Za-z0-9._-]+)/,S=/[A-Za-z0-9._-]+/;function H(e){return!!(x.has(e)||k.has(e)||c.has(e)||e.startsWith("mcp__grix"))}const q=[...r,...a],A=[...q,...p],Z=new Map(A.map(e=>[e.name,e]));function K(e,t){return e==="reply"?{name:"grix_reply",args:m("grix_reply",{event_id:t.event_id,session_id:t.chat_id,text:t.text,quoted_message_id:t.reply_to,is_final:t.final})}:e==="complete"?{name:"grix_complete",args:m("grix_complete",{event_id:t.event_id,status:t.status,msg:t.msg,code:t.code})}:{name:e,args:t}}function l(e){const t=String(e??"").trim();return t?t.match(I)?.[1]:void 0}function u(e){const t=String(e??"").trim();if(!t)return;const n=l(t);if(n)return _(n);const i=t.match(/(?:chat_id|session_id)\s*=\s*"([A-Za-z0-9._-]+)"/)?.[1];if(i)return i;const o=t.match(/[A-Za-z0-9._-]+/g)??[];for(const s of o)if(!(s==="event_id"||s==="chat_id"||s==="session_id")&&s.length>0)return s;return t.match(S)?.[0]}function _(e){if(!e)return;const t=e.split(":",1)[0]?.trim();if(t)return u(t)}function m(e,t){if(e!=="grix_reply"&&e!=="grix_complete")return t;const n={...t},i=l(n.event_id);if(i&&(n.event_id=i),e==="grix_reply"){const o=_(i),d=String(n.session_id??""),s=u(n.session_id),b=/\bevent_id\b|["'<>\s]/.test(d);s&&!(b&&o)?n.session_id=s:o&&(n.session_id=o)}return n}function V(e){return c.has(e)}function X(e,t){switch(e){case"grix_query":return T(t);case"grix_audit_data":return M(t);case"grix_group":return O(t);case"grix_message_send":return D(t);case"grix_message_unsend":return L(t);case"grix_file_link":return E(t);case"grix_file_upload":return j(t);case"grix_admin":return $(t);case"grix_call_owner":return N(t);case"grix_agent_update":return P(t);case"grix_dispatch_agent":return C(t);case"grix_session_send":return U(t);case"grix_chat_state_query":return z(t);case"grix_chat_state_update":return B(t);case"grix_access_control":return R(t);case"grix_widget_visitor_ban":return G(t);case"grix_skill_set":return W(t);case"grix_skill_get":return F(t);default:throw new Error(`Unknown tool: ${e}`)}}const g={contact_search:"contact_search",session_search:"session_search",message_history:"message_history",message_search:"message_search",search_favorite_sessions:"search_favorite_sessions"};function T(e){const t=String(e.action??""),n=g[t];if(!n)throw new Error(`Unknown grix_query action: ${t}`);const i={};return e.id!=null&&(i.id=e.id),e.keyword!=null&&(i.keyword=e.keyword),e.sessionType!=null&&(i.session_type=e.sessionType),e.limit!=null?i.limit=e.limit:t==="message_history"&&(i.limit=1),e.offset!=null&&(i.offset=e.offset),e.sessionId!=null&&(i.session_id=e.sessionId),e.beforeId!=null&&(i.before_id=e.beforeId),{action:n,params:i}}const y={get_manifest:"audit_get_manifest",list_spans:"audit_list_spans",get_content_chunk:"audit_get_content_chunk"};function M(e){const t=String(e.action??""),n=y[t];if(!n)throw new Error(`Unknown grix_audit_data action: ${t}`);const i={audit_id:e.auditId};return e.revision!=null&&(i.revision=e.revision),e.cursor!=null&&(i.cursor=e.cursor),e.limit!=null&&(i.limit=e.limit),e.contentId!=null&&(i.content_id=e.contentId),e.maxBytes!=null&&(i.max_bytes=e.maxBytes),{action:n,params:i}}const h={create:"group_create",detail:"group_detail_read",leave:"group_leave_self",add_members:"group_member_add",remove_members:"group_member_remove",update_member_role:"group_member_role_update",update_all_members_muted:"group_all_members_muted_update",update_member_speaking:"group_member_speaking_update",dissolve:"group_dissolve"};function O(e){const t=String(e.action??""),n=h[t];if(!n)throw new Error(`Unknown grix_group action: ${t}`);const i={};return e.sessionId!=null&&(i.session_id=e.sessionId),e.name!=null&&(i.name=e.name),e.memberIds!=null&&(i.member_ids=e.memberIds),e.memberTypes!=null&&(i.member_types=e.memberTypes),e.memberId!=null&&(i.member_id=e.memberId),e.role!=null&&(i.role=e.role),e.memberType!=null&&(i.member_type=e.memberType),e.allMembersMuted!=null&&(i.all_members_muted=e.allMembersMuted),e.isSpeakMuted!=null&&(i.is_speak_muted=e.isSpeakMuted),e.canSpeakWhenAllMuted!=null&&(i.can_speak_when_all_muted=e.canSpeakWhenAllMuted),{action:n,params:i}}function D(e){const t={session_id:e.sessionId,msg_type:e.msgType??1,content:e.content};return e.quotedMessageId!=null&&(t.quoted_message_id=e.quotedMessageId),e.threadId!=null&&(t.thread_id=e.threadId),{action:"send_msg",params:t}}function L(e){return{action:"delete_msg",params:{session_id:e.sessionId,msg_id:e.msgId}}}function E(e){const t={file_path:e.file_path};return e.ttl_ms!=null&&(t.ttl_ms=e.ttl_ms),{action:"file_link",params:t}}function j(e){const t={file_path:e.file_path,session_id:e.session_id};return e.caption!=null&&(t.caption=e.caption),e.reply_to_message_id!=null&&(t.reply_to_message_id=e.reply_to_message_id),{action:"file_upload",params:t,timeoutMs:6e4}}const f={create_agent:"agent_api_create",list_categories:"agent_category_list",create_category:"agent_category_create",update_category:"agent_category_update",assign_category:"agent_category_assign",rotate_api_key:"agent_api_key_rotate"};function N(e){return{action:"call_owner",params:{session_id:e.session_id}}}function P(e){if(e.agent_name==null&&e.introduction==null)throw new Error("grix_agent_update requires agent_name or introduction");const t={agent_id:e.agent_id};return e.agent_name!=null&&(t.agent_name=e.agent_name),e.introduction!=null&&(t.introduction=e.introduction),{action:"agent_introduction_update",params:t}}function C(e){return{action:"dispatch_agent",params:{agent_id:e.agent_id,cwd:e.cwd,task:e.task,title:e.title},timeoutMs:75e3}}function U(e){const t={session_id:e.session_id,content:e.content};return e.quoted_message_id!=null&&String(e.quoted_message_id).trim()!==""&&(t.quoted_message_id=e.quoted_message_id),{action:"session_send",params:t}}function z(e){const t={};return e.session_id!=null&&(t.session_id=e.session_id),e.page!=null&&(t.page=e.page),e.page_size!=null&&(t.page_size=e.page_size),e.state!=null&&(t.state=e.state),{action:"chat_state_query",params:t}}function R(e){const t=String(e.action??""),n=Q[t];if(!n)throw new Error(`Unknown grix_access_control action: ${t}`);const i={};return e.code!=null&&(i.code=e.code),e.sender_id!=null&&(i.sender_id=e.sender_id),e.policy!=null&&(i.policy=e.policy),{action:"claude_access_control",params:{verb:n,payload:i},timeoutMs:3e4}}function G(e){return{action:"widget_visitor_ban",params:{session_id:e.session_id}}}function B(e){const t={session_id:e.session_id,state:e.state};return e.reason!=null&&(t.reason=e.reason),{action:"chat_state_update",params:t}}function W(e){return{action:"skill_set",params:{name:e.name,content:e.content},timeoutMs:3e4}}function F(e){const t={};return e.name!=null&&(t.name=e.name),{action:"skill_get",params:t}}function $(e){const t=String(e.action??""),n=f[t];if(!n)throw new Error(`Unknown grix_admin action: ${t}`);const i={};return e.agentName!=null&&(i.agent_name=e.agentName),e.introduction!=null&&(i.introduction=e.introduction),e.isMain!=null&&(i.is_main=e.isMain),e.agentId!=null&&(i.agent_id=e.agentId),e.categoryId!=null&&(i.category_id=e.categoryId),e.name!=null&&(i.name=e.name),e.parentId!=null&&(i.parent_id=e.parentId),e.sortOrder!=null&&(i.sort_order=e.sortOrder),{action:n,params:i}}const Y=new Set([...Object.values(g),...Object.values(y),...Object.values(h),...Object.values(f),"send_msg","delete_msg","file_link","file_upload","call_owner","agent_introduction_update","dispatch_agent","session_send","chat_state_query","chat_state_update","claude_access_control","widget_visitor_ban","skill_set","skill_get"]),Q={pair_approve:"pair_approve",pair_deny:"pair_deny",allow_sender:"sender_allow",remove_sender:"sender_remove",set_policy:"policy_set"};export{Q as ACCESS_CONTROL_ACTION_MAP,q as ALL_TOOLS,a as EVENT_TOOLS,A as EXPOSED_TOOLS,Y as PHASE1_INVOKE_ACTIONS,x as PHASE1_TOOL_NAMES,k as PHASE2_TOOL_NAMES,r as TOOLS,p as TOOL_ALIASES,Z as TOOL_MAP,V as isAlias,H as isGrixInternalToolName,K as mapToolAlias,m as normalizeEventToolArgs,X as toolCallToInvoke};
1
+ const r=[{name:"grix_query",description:"Search contacts, sessions, message history, messages, or favorited sessions in the Grix/AIBot platform. message_history defaults to the newest one clean text/approval-card message and excludes process/tool cards.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["contact_search","session_search","message_history","message_search","search_favorite_sessions"],description:"Query action type. search_favorite_sessions returns the owner's favorited sessions (supports keyword filter)."},id:{type:"string",description:"Contact ID (contact_search) or Session ID (session_search)."},keyword:{type:"string",description:"Search keyword."},sessionType:{type:"integer",enum:[1,2],description:"Filter by session type (session_search only): 1=private chat, 2=group chat. Omit to return all."},limit:{type:"integer",description:"Max results. message_history defaults to 1 when omitted."},offset:{type:"integer",description:"Result offset."},sessionId:{type:"string",description:"Session ID (message_history, message_search)."},beforeId:{type:"string",description:"Pagination cursor (message_history, message_search)."}},required:["action"]},validation:{required:["action"],properties:{action:{type:"string",enum:["contact_search","session_search","message_history","message_search","search_favorite_sessions"]},id:{type:"string"},keyword:{type:"string",maxLength:200},sessionType:{type:"integer",enum:[1,2]},limit:{type:"integer",minimum:1,maximum:100},offset:{type:"integer",minimum:0},sessionId:{type:"string"},beforeId:{type:"string"}}}},{name:"grix_audit_data",description:"Read connector-backed conversation audit replay data from Grix/AIBot: manifest, span pages, and content chunks.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["get_manifest","list_spans","get_content_chunk"],description:"Audit read action. Start with get_manifest, then call list_spans and/or get_content_chunk based on the manifest."},auditId:{type:"string",description:"Audit ID returned by the audited turn metadata."},revision:{type:"integer",description:"Optional manifest revision to read. Usually use the revision returned by get_manifest."},cursor:{type:"string",description:"Opaque pagination cursor returned by list_spans or get_content_chunk."},limit:{type:"integer",description:"Max span items for list_spans."},contentId:{type:"string",description:"Content reference ID from manifest.content_refs (get_content_chunk only)."},maxBytes:{type:"integer",description:"Max UTF-8 bytes to return for get_content_chunk."}},required:["action","auditId"]},validation:{required:["action","auditId"],properties:{action:{type:"string",enum:["get_manifest","list_spans","get_content_chunk"]},auditId:{type:"string"},revision:{type:"integer",minimum:1},cursor:{type:"string",maxLength:4096},limit:{type:"integer",minimum:1,maximum:200},contentId:{type:"string"},maxBytes:{type:"integer",minimum:1,maximum:131072}}}},{name:"grix_group",description:"Manage groups in the Grix/AIBot platform: create, get details, leave, dissolve, manage members and permissions.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","detail","leave","add_members","remove_members","update_member_role","update_all_members_muted","update_member_speaking","dissolve"],description:"Group action type."},sessionId:{type:"string",description:"Group session ID."},name:{type:"string",description:"Group name (create)."},memberIds:{type:"array",items:{type:"string"},description:"Member IDs to add/remove."},memberTypes:{type:"array",items:{type:"integer",enum:[1,2]},description:"Member types (1=user, 2=agent)."},memberId:{type:"string",description:"Target member ID."},role:{type:"integer",enum:[1,2],description:"New role (1=admin, 2=member)."},memberType:{type:"integer",description:"Member type."},allMembersMuted:{type:"boolean",description:"Whether to mute all members."},isSpeakMuted:{type:"boolean",description:"Whether member is muted."},canSpeakWhenAllMuted:{type:"boolean",description:"Allow speaking when all muted."}},required:["action"]},validation:{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"}}}},{name:"grix_message_send",description:"Send a message to a session in the Grix/AIBot platform. Do NOT use this to answer the inbound event you are currently handling \u2014 answer in plain text (or the reply tool where available) instead, otherwise the user receives duplicate messages.",inputSchema:{type:"object",properties:{sessionId:{type:"string",description:"Target session ID"},content:{type:"string",description:"Message content"},msgType:{type:"integer",description:"Message type (1=text, default 1)"},quotedMessageId:{type:"string",description:"Message ID to reply to"},threadId:{type:"string",description:"Thread ID for threaded reply"}},required:["sessionId","content"]},validation:{required:["sessionId","content"],properties:{sessionId:{type:"string"},content:{type:"string",maxLength:1e4},msgType:{type:"integer"},quotedMessageId:{type:"string"},threadId:{type:"string"}}}},{name:"grix_message_unsend",description:"Recall/unsend a message in the Grix/AIBot platform.",inputSchema:{type:"object",properties:{sessionId:{type:"string",description:"Session ID"},msgId:{type:"string",description:"Message ID to unsend"}},required:["sessionId","msgId"]},validation:{required:["sessionId","msgId"],properties:{sessionId:{type:"string"},msgId:{type:"string"}}}},{name:"grix_file_link",description:"Create a direct, tailnet-only download link for a local file on this host. Use this whenever the user asks you to send, share, give, or deliver a file that exists on the machine where you run (a report, log, build artifact, export, or any local path). It returns a ready-to-use Markdown link in the `markdown` field \u2014 include that exact Markdown link in your reply so the user can click and download the file directly over the shared Tailscale network. The link is reachable only inside the tailnet, so just send it as-is \u2014 no need to worry about or mention any link lifetime. The download link is HTTPS, served by a built-in self-signed CA. The result also returns `ca_install_url`: the first time you share a link with a user (or whenever their browser warns the cert is untrusted), also give them this CA install link so they can install and trust it once \u2014 after that all download links work without warnings. Requires this host to be on a tailnet (Tailscale running).",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to a local file on this host to share with the user."},ttl_ms:{type:"integer",description:"Optional link lifetime in milliseconds. Leave unset to use the long default; set only if you deliberately want a short-lived link."}},required:["file_path"]},validation:{required:["file_path"],properties:{file_path:{type:"string",maxLength:4096},ttl_ms:{type:"integer",minimum:1e4,maximum:864e5}}}},{name:"grix_file_upload",description:"Upload a local file to the Grix platform and send it as a media message in the target session. Supports images (jpg/png/webp/gif/bmp/heic/heif), videos (mp4/mov/m4v/webm/mkv/avi), documents (pdf/doc/docx/xls/xlsx/ppt/pptx/txt/md/csv/json/xml), and archives (zip/rar/7z/tar/gz). Max 50 MB. Use this instead of grix_file_link when the file should appear as a native attachment in the chat (visible inline for images/videos), rather than a tailnet download link.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to a local file to upload."},session_id:{type:"string",description:"Target session ID to send the file to."},caption:{type:"string",description:"Optional text caption for the media message."},reply_to_message_id:{type:"string",description:"Optional message ID to quote/reply to."}},required:["file_path","session_id"]},validation:{required:["file_path","session_id"],properties:{file_path:{type:"string",maxLength:4096},session_id:{type:"string"},caption:{type:"string",maxLength:2e3},reply_to_message_id:{type:"string"}}}},{name:"grix_admin",description:"Agent and category management in the Grix/AIBot platform: create agents, manage categories, rotate API keys.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create_agent","list_categories","create_category","update_category","assign_category","rotate_api_key"],description:"Admin action type."},agentName:{type:"string",description:"Agent name (create_agent)."},introduction:{type:"string",description:"Professional behavioral introduction describing the Agent purpose, responsibilities, operating expectations, and boundaries (create_agent)."},isMain:{type:"boolean",description:"Set as main agent (create_agent)."},agentId:{type:"string",description:"Agent ID (assign_category, rotate_api_key)."},categoryId:{type:"string",description:"Category ID (create_agent, update_category, assign_category)."},name:{type:"string",description:"Category name (create_category, update_category)."},parentId:{type:"string",description:"Parent category ID (create_category, update_category)."},sortOrder:{type:"integer",description:"Sort order (create_category, update_category)."}},required:["action"]},validation:{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"}}}},{name:"grix_call_owner",description:"Call your owner into this session to talk by voice. Use this when, during your work, you need to reach your owner \u2014 to discuss something or to get an approval/review. It sends the owner an offline notification; when they tap it they land directly in this conversation and a voice-brain call is started automatically. Requires the owner to have configured a voice brain. Rate-limited per session.",inputSchema:{type:"object",properties:{session_id:{type:"string",description:"The session ID to call the owner into."}},required:["session_id"]},validation:{required:["session_id"],properties:{session_id:{type:"string"}}}},{name:"grix_agent_update",description:"Update the display name and/or text introduction of one of your owner's agents, identified by its numeric agent ID. Provide agent_name, introduction, or both \u2014 at least one is required.",inputSchema:{type:"object",properties:{agent_id:{type:"string",description:"Target agent's numeric ID, passed as a string."},agent_name:{type:"string",description:"New display name (max 100 characters, must be unique among the owner's agents)."},introduction:{type:"string",description:"New text introduction (max 300 characters)."}},required:["agent_id"]},validation:{required:["agent_id"],properties:{agent_id:{type:"string"},agent_name:{type:"string",maxLength:100},introduction:{type:"string",maxLength:300}}}},{name:"grix_dispatch_agent",description:`Dispatch one of your owner's agents to do work in a given working directory. Provide the target agent numeric ID, the working directory, and a text description of the task. The backend creates a NEW private session between the owner and that agent for each dispatch (it does not reuse past sessions), binds the working directory when the agent type requires it (claude/codex/etc.), and sends the task into the session AS THE OWNER so the agent starts working. Because the task is delivered as the owner, write it in the owner's first-person voice and tone \u2014 phrase it the way the owner would speak directly to the agent (e.g. "\u5E2E\u6211\u2026", "\u4F60\u53BB\u2026"), NOT as a third-person relay or as yourself narrating on the owner's behalf. Provide a short title summarizing the core of the task \u2014 it becomes the new session's title; if omitted the backend derives one from the task text.`,inputSchema:{type:"object",properties:{agent_id:{type:"string",description:"Target agent's numeric ID, passed as a string."},cwd:{type:"string",description:"Absolute working directory where the agent should do the work."},task:{type:"string",description:"Text description of the task to perform, written in the owner's first-person voice and tone \u2014 it is delivered into the session as the owner, so phrase it as the owner speaking directly to the agent, not as a third-person relay."},title:{type:"string",description:"Optional short title (a few words) summarizing the core of the task; used as the new session's title. If omitted, the backend derives a title from the task text."}},required:["agent_id","cwd","task"]},validation:{required:["agent_id","cwd","task"],properties:{agent_id:{type:"string"},cwd:{type:"string",maxLength:4096},task:{type:"string",maxLength:1e4},title:{type:"string",maxLength:255}}}},{name:"grix_session_send",description:"Send a message into a session AS THE OWNER \u2014 it appears as if the owner sent it, NOT as you (the agent). Dispatch callbacks (report_dispatch_result) MUST use this tool, even when you are a member of the callback session: a message sent as yourself cannot quote-wake the dispatcher agent, and your membership is not checked. NEVER use this for your own ordinary replies in a conversation \u2014 that would make your words show up as the owner's message; reply normally (or use grix_message_send to send as yourself) for those. The owner must be a member of the target session. Requires the Send as Owner permission scope \u2014 if rejected for missing permission, surface the error as-is so the owner can grant it; do not fall back to grix_message_send. Optional quoted_message_id quotes a message in the same session (used by dispatch callbacks to wake the dispatcher agent).",inputSchema:{type:"object",properties:{session_id:{type:"string",description:"Target session ID."},content:{type:"string",description:"Message content to send as the owner."},quoted_message_id:{type:"string",description:"Optional message ID in the target session to quote/reply to.",pattern:"^[1-9]\\d*$"}},required:["session_id","content"]},validation:{required:["session_id","content"],properties:{session_id:{type:"string"},content:{type:"string",maxLength:1e4},quoted_message_id:{type:"string",pattern:"^[1-9]\\d*$"}}}},{name:"grix_chat_state_query",description:"Query the chat-level task states across all of your owner's sessions (including direct and group chats). Returns one entry per session with a single mutually-exclusive state: running (working), waiting_approval (blocked on your owner to approve/deny), waiting_question (asked the owner a question, awaiting their reply), completed, failed, or idle (no task / stopped). When session_id identifies one completed session, the entry also includes exactly one clean final_result; non-completed and list queries never include message content. Also returns the session title (task_title) for easy identification. Supports pagination (page/page_size) and optional state filtering. Use this to see at a glance which chats are done, still running, or waiting on the owner.",inputSchema:{type:"object",properties:{session_id:{type:"string",description:"(Optional) Query a single session by its ID. Omit to return all sessions."},page:{type:"number",description:"(Optional) Page number, starting from 1. Defaults to 1 if omitted."},page_size:{type:"number",description:"(Optional) Number of items per page, max 100. Defaults to 10 if omitted."},state:{type:"string",description:"(Optional) Filter by a specific state: running, waiting_approval, waiting_question, completed, failed, or idle. Omit to return all states."}}},validation:{required:[],properties:{}}},{name:"grix_chat_state_update",description:"Manually update the task state of a specific chat session. Use this to mark a chat as completed, failed, idle, or any other state when you need to override it manually. The reason is written to stop_reason and is optional.",inputSchema:{type:"object",properties:{session_id:{type:"string",description:"The session ID whose state to update."},state:{type:"string",enum:["running","waiting_approval","waiting_question","completed","failed","idle"],description:"The new state to set. Must be one of: running, waiting_approval, waiting_question, completed, failed, idle."},reason:{type:"string",description:"(Optional) Reason for the state change, written to stop_reason."}}},validation:{required:["session_id","state"],properties:{}}},{name:"grix_access_control",description:"Manage sender access control: pair approval, allow/remove senders, set policy.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["pair_approve","pair_deny","allow_sender","remove_sender","set_policy"],description:"Access control action type."},code:{type:"string",description:"Pairing code (required for pair_approve/pair_deny)."},sender_id:{type:"string",description:"Sender ID (required for allow_sender/remove_sender)."},policy:{type:"string",enum:["allowlist","open","disabled"],description:"Access policy (required for set_policy)."}},required:["action"]},validation:{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"]}}}},{name:"grix_widget_visitor_ban",description:"Ban a widget visitor session: blocks the session and adds its most recent init IP to the owner's global IP ban list (7-day expiry).",inputSchema:{type:"object",properties:{session_id:{type:"string",description:"Widget visitor session ID (required)."}},required:["session_id"]},validation:{required:["session_id"],properties:{session_id:{type:"string"}}}},{name:"grix_skill_set",description:"Create, update, or delete one of your owner's custom skills in the platform skill library. The skill library auto-syncs to every machine the owner runs an agent on (a per-machine `grix/skills` directory), so defining a skill here makes it available on all of them. A skill is a plain SKILL.md package (frontmatter + body), same standard as other Grix skills. Provide `name` and the full `content` (the SKILL.md text) to create or overwrite by name. To delete a skill, pass its `name` with an empty `content` string. How and when any agent actually loads/uses a synced skill is arranged by the owner (in a system prompt or in conversation); this tool only manages the library.",inputSchema:{type:"object",properties:{name:{type:"string",description:"Skill name (max 100 characters); unique within the owner. Used as the identifier and the synced directory name."},content:{type:"string",description:"Full SKILL.md text. Pass an empty string to delete the skill by name."}},required:["name","content"]},validation:{required:["name","content"],properties:{name:{type:"string",maxLength:100},content:{type:"string",maxLength:262144}}}},{name:"grix_skill_get",description:"Read one of your owner's custom skills by name (returns its full SKILL.md content), or list the owner's skill library when no name is given. Use this before editing to fetch current content, then call grix_skill_set with the revised text.",inputSchema:{type:"object",properties:{name:{type:"string",description:"Skill name to fetch. Omit to list all skills (names + versions) instead."}}},validation:{required:[],properties:{name:{type:"string",maxLength:100}}}}],a=[{name:"grix_reply",description:"Send your final reply \u2014 the conclusion the user is waiting for \u2014 to the specified session. This is the message the user treats as your answer; deliver your final result here, and use plain text only for brief progress notes while you work. Supports streaming in chunks; the frontend automatically aggregates them into one complete message. The connector quotes the message being answered automatically, so quoted_message_id is optional (set it only to quote a different earlier message).",inputSchema:{type:"object",properties:{event_id:{type:"string",description:"Associated event ID from the inbound event."},session_id:{type:"string",description:"Target session ID."},text:{type:"string",description:"Reply text content."},quoted_message_id:{type:"string",description:"Quoted message ID (optional)."},is_final:{type:"boolean",description:"Whether this is a stage-final reply. Advisory only \u2014 does not trigger event completion; completion is handled by the complete tool or Stop hook."}},required:["session_id","text"]},validation:{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"}}}},{name:"grix_complete",description:"Mark event processing as complete, notifying the backend that no more replies are expected.",inputSchema:{type:"object",properties:{event_id:{type:"string",description:"The event ID to complete."},status:{type:"string",enum:["responded","canceled","failed"],description:"Completion status."},msg:{type:"string",description:"Additional note (optional)."}},required:["event_id","status"]},validation:{required:["event_id","status"],properties:{event_id:{type:"string"},status:{type:"string",enum:["responded","canceled","failed"]},msg:{type:"string",maxLength:500}}}},{name:"grix_event_ack",description:"Acknowledge event receipt (usually done automatically by the Dispatcher; agents typically do not need to call this manually).",inputSchema:{type:"object",properties:{event_id:{type:"string",description:"The event ID to acknowledge."},session_id:{type:"string",description:"Session ID."}},required:["event_id"]},validation:{required:["event_id"],properties:{event_id:{type:"string"},session_id:{type:"string"}}}},{name:"grix_composing",description:'Set the "typing" indicator status for a session.',inputSchema:{type:"object",properties:{session_id:{type:"string",description:"Session ID."},active:{type:"boolean",description:"true = typing, false = stopped."},event_id:{type:"string",description:"Associated event ID (optional)."}},required:["session_id","active"]},validation:{required:["session_id","active"],properties:{session_id:{type:"string"},active:{type:"boolean"},event_id:{type:"string"}}}},{name:"grix_status",description:"Query the Grix connection status of the current MCP session.",inputSchema:{type:"object",properties:{}},validation:{required:[],properties:{}}}],v={grix_dispatch_agent:"grix-agent-dispatch",grix_agent_update:"grix-agent-dispatch",grix_query:"grix-query",grix_audit_data:"grix-audit-data",grix_group:"grix-group",grix_message_send:"message-send",grix_message_unsend:"message-unsend",grix_admin:"grix-admin",grix_call_owner:"grix-owner-relay",grix_session_send:"grix-owner-relay",grix_chat_state_query:"grix-chat-state",grix_chat_state_update:"grix-chat-state",grix_status:"grix-chat-state",grix_access_control:"grix-access-control",grix_widget_visitor_ban:"grix-widget-visitor-ban",grix_file_link:"tailnet-file-share"};function w(e){return` Before calling this tool, follow the \`${e}\` skill's procedure first; do not invoke this tool directly without going through that skill's guidance.`}for(const e of[...r,...a]){const t=v[e.name];t&&(e.description+=w(t))}const p=[{name:"reply",description:"Send a visible message back to the chat for this grix-claude event.",inputSchema:{type:"object",properties:{text:{type:"string",description:"The visible reply text to send."},chat_id:{type:"string",description:"The target chat/session id from the <channel> tag."},event_id:{type:"string",description:"The Aibot event_id from the <channel> tag."},reply_to:{type:"string",description:"Optional message_id to quote instead of the inbound trigger message."},final:{type:"boolean",description:"Advisory flag only. It does not complete the event; completion is handled by complete tool or Stop hook."}},required:["chat_id","event_id","text"]}},{name:"complete",description:"Finish an event without sending a visible reply so the backend does not time out.",inputSchema:{type:"object",properties:{event_id:{type:"string",description:"The Aibot event_id from the <channel> tag."},status:{type:"string",enum:["responded","canceled","failed"]},msg:{type:"string"},code:{type:"string"}},required:["event_id","status"]}}],c=new Set(p.map(e=>e.name)),x=new Set(r.map(e=>e.name)),k=new Set(a.map(e=>e.name)),I=/([A-Za-z0-9._-]+:[A-Za-z0-9._-]+:[A-Za-z0-9._-]+:[A-Za-z0-9._-]+)/,S=/[A-Za-z0-9._-]+/;function H(e){return!!(x.has(e)||k.has(e)||c.has(e)||e.startsWith("mcp__grix"))}const q=[...r,...a],A=[...q,...p],Z=new Map(A.map(e=>[e.name,e]));function K(e,t){return e==="reply"?{name:"grix_reply",args:m("grix_reply",{event_id:t.event_id,session_id:t.chat_id,text:t.text,quoted_message_id:t.reply_to,is_final:t.final})}:e==="complete"?{name:"grix_complete",args:m("grix_complete",{event_id:t.event_id,status:t.status,msg:t.msg,code:t.code})}:{name:e,args:t}}function l(e){const t=String(e??"").trim();return t?t.match(I)?.[1]:void 0}function u(e){const t=String(e??"").trim();if(!t)return;const n=l(t);if(n)return _(n);const i=t.match(/(?:chat_id|session_id)\s*=\s*"([A-Za-z0-9._-]+)"/)?.[1];if(i)return i;const o=t.match(/[A-Za-z0-9._-]+/g)??[];for(const s of o)if(!(s==="event_id"||s==="chat_id"||s==="session_id")&&s.length>0)return s;return t.match(S)?.[0]}function _(e){if(!e)return;const t=e.split(":",1)[0]?.trim();if(t)return u(t)}function m(e,t){if(e!=="grix_reply"&&e!=="grix_complete")return t;const n={...t},i=l(n.event_id);if(i&&(n.event_id=i),e==="grix_reply"){const o=_(i),d=String(n.session_id??""),s=u(n.session_id),b=/\bevent_id\b|["'<>\s]/.test(d);s&&!(b&&o)?n.session_id=s:o&&(n.session_id=o)}return n}function V(e){return c.has(e)}function X(e,t){switch(e){case"grix_query":return T(t);case"grix_audit_data":return M(t);case"grix_group":return O(t);case"grix_message_send":return D(t);case"grix_message_unsend":return L(t);case"grix_file_link":return E(t);case"grix_file_upload":return j(t);case"grix_admin":return $(t);case"grix_call_owner":return N(t);case"grix_agent_update":return P(t);case"grix_dispatch_agent":return C(t);case"grix_session_send":return U(t);case"grix_chat_state_query":return z(t);case"grix_chat_state_update":return B(t);case"grix_access_control":return R(t);case"grix_widget_visitor_ban":return G(t);case"grix_skill_set":return W(t);case"grix_skill_get":return F(t);default:throw new Error(`Unknown tool: ${e}`)}}const g={contact_search:"contact_search",session_search:"session_search",message_history:"message_history",message_search:"message_search",search_favorite_sessions:"search_favorite_sessions"};function T(e){const t=String(e.action??""),n=g[t];if(!n)throw new Error(`Unknown grix_query action: ${t}`);const i={};return e.id!=null&&(i.id=e.id),e.keyword!=null&&(i.keyword=e.keyword),e.sessionType!=null&&(i.session_type=e.sessionType),e.limit!=null?i.limit=e.limit:t==="message_history"&&(i.limit=1),e.offset!=null&&(i.offset=e.offset),e.sessionId!=null&&(i.session_id=e.sessionId),e.beforeId!=null&&(i.before_id=e.beforeId),{action:n,params:i}}const y={get_manifest:"audit_get_manifest",list_spans:"audit_list_spans",get_content_chunk:"audit_get_content_chunk"};function M(e){const t=String(e.action??""),n=y[t];if(!n)throw new Error(`Unknown grix_audit_data action: ${t}`);const i={audit_id:e.auditId};return e.revision!=null&&(i.revision=e.revision),e.cursor!=null&&(i.cursor=e.cursor),e.limit!=null&&(i.limit=e.limit),e.contentId!=null&&(i.content_id=e.contentId),e.maxBytes!=null&&(i.max_bytes=e.maxBytes),{action:n,params:i}}const h={create:"group_create",detail:"group_detail_read",leave:"group_leave_self",add_members:"group_member_add",remove_members:"group_member_remove",update_member_role:"group_member_role_update",update_all_members_muted:"group_all_members_muted_update",update_member_speaking:"group_member_speaking_update",dissolve:"group_dissolve"};function O(e){const t=String(e.action??""),n=h[t];if(!n)throw new Error(`Unknown grix_group action: ${t}`);const i={};return e.sessionId!=null&&(i.session_id=e.sessionId),e.name!=null&&(i.name=e.name),e.memberIds!=null&&(i.member_ids=e.memberIds),e.memberTypes!=null&&(i.member_types=e.memberTypes),e.memberId!=null&&(i.member_id=e.memberId),e.role!=null&&(i.role=e.role),e.memberType!=null&&(i.member_type=e.memberType),e.allMembersMuted!=null&&(i.all_members_muted=e.allMembersMuted),e.isSpeakMuted!=null&&(i.is_speak_muted=e.isSpeakMuted),e.canSpeakWhenAllMuted!=null&&(i.can_speak_when_all_muted=e.canSpeakWhenAllMuted),{action:n,params:i}}function D(e){const t={session_id:e.sessionId,msg_type:e.msgType??1,content:e.content};return e.quotedMessageId!=null&&(t.quoted_message_id=e.quotedMessageId),e.threadId!=null&&(t.thread_id=e.threadId),{action:"send_msg",params:t}}function L(e){return{action:"delete_msg",params:{session_id:e.sessionId,msg_id:e.msgId}}}function E(e){const t={file_path:e.file_path};return e.ttl_ms!=null&&(t.ttl_ms=e.ttl_ms),{action:"file_link",params:t}}function j(e){const t={file_path:e.file_path,session_id:e.session_id};return e.caption!=null&&(t.caption=e.caption),e.reply_to_message_id!=null&&(t.reply_to_message_id=e.reply_to_message_id),{action:"file_upload",params:t,timeoutMs:6e4}}const f={create_agent:"agent_api_create",list_categories:"agent_category_list",create_category:"agent_category_create",update_category:"agent_category_update",assign_category:"agent_category_assign",rotate_api_key:"agent_api_key_rotate"};function N(e){return{action:"call_owner",params:{session_id:e.session_id}}}function P(e){if(e.agent_name==null&&e.introduction==null)throw new Error("grix_agent_update requires agent_name or introduction");const t={agent_id:e.agent_id};return e.agent_name!=null&&(t.agent_name=e.agent_name),e.introduction!=null&&(t.introduction=e.introduction),{action:"agent_introduction_update",params:t}}function C(e){return{action:"dispatch_agent",params:{agent_id:e.agent_id,cwd:e.cwd,task:e.task,title:e.title},timeoutMs:75e3}}function U(e){const t={session_id:e.session_id,content:e.content};return e.quoted_message_id!=null&&String(e.quoted_message_id).trim()!==""&&(t.quoted_message_id=e.quoted_message_id),{action:"session_send",params:t}}function z(e){const t={};return e.session_id!=null&&(t.session_id=e.session_id),e.page!=null&&(t.page=e.page),e.page_size!=null&&(t.page_size=e.page_size),e.state!=null&&(t.state=e.state),{action:"chat_state_query",params:t}}function R(e){const t=String(e.action??""),n=Q[t];if(!n)throw new Error(`Unknown grix_access_control action: ${t}`);const i={};return e.code!=null&&(i.code=e.code),e.sender_id!=null&&(i.sender_id=e.sender_id),e.policy!=null&&(i.policy=e.policy),{action:"claude_access_control",params:{verb:n,payload:i},timeoutMs:3e4}}function G(e){return{action:"widget_visitor_ban",params:{session_id:e.session_id}}}function B(e){const t={session_id:e.session_id,state:e.state};return e.reason!=null&&(t.reason=e.reason),{action:"chat_state_update",params:t}}function W(e){return{action:"skill_set",params:{name:e.name,content:e.content},timeoutMs:3e4}}function F(e){const t={};return e.name!=null&&(t.name=e.name),{action:"skill_get",params:t}}function $(e){const t=String(e.action??""),n=f[t];if(!n)throw new Error(`Unknown grix_admin action: ${t}`);const i={};return e.agentName!=null&&(i.agent_name=e.agentName),e.introduction!=null&&(i.introduction=e.introduction),e.isMain!=null&&(i.is_main=e.isMain),e.agentId!=null&&(i.agent_id=e.agentId),e.categoryId!=null&&(i.category_id=e.categoryId),e.name!=null&&(i.name=e.name),e.parentId!=null&&(i.parent_id=e.parentId),e.sortOrder!=null&&(i.sort_order=e.sortOrder),{action:n,params:i}}const Y=new Set([...Object.values(g),...Object.values(y),...Object.values(h),...Object.values(f),"send_msg","delete_msg","file_link","file_upload","call_owner","agent_introduction_update","dispatch_agent","session_send","chat_state_query","chat_state_update","claude_access_control","widget_visitor_ban","skill_set","skill_get"]),Q={pair_approve:"pair_approve",pair_deny:"pair_deny",allow_sender:"sender_allow",remove_sender:"sender_remove",set_policy:"policy_set"};export{Q as ACCESS_CONTROL_ACTION_MAP,q as ALL_TOOLS,a as EVENT_TOOLS,A as EXPOSED_TOOLS,Y as PHASE1_INVOKE_ACTIONS,x as PHASE1_TOOL_NAMES,k as PHASE2_TOOL_NAMES,r as TOOLS,p as TOOL_ALIASES,Z as TOOL_MAP,V as isAlias,H as isGrixInternalToolName,K as mapToolAlias,m as normalizeEventToolArgs,X as toolCallToInvoke};
@@ -1 +1 @@
1
- function a(t){const o=new Set([`http://127.0.0.1:${t.serverPort}`,`http://localhost:${t.serverPort}`,...t.allowedOrigins]),e=new Set([`127.0.0.1:${t.serverPort}`,`localhost:${t.serverPort}`,...t.allowedHosts]);return{validateRequest(s){const r=i(s,o);if(!r.ok)return r;const n=l(s,e);return n.ok?{ok:!0}:n}}}function i(t,o){const e=t.headers.origin;return e?o.has(e)?{ok:!0}:{ok:!1,statusCode:403,message:`Origin not allowed: ${e}`}:{ok:!0}}function l(t,o){const e=t.headers.host;return e?o.has(e)?{ok:!0}:{ok:!1,statusCode:403,message:`Host not allowed: ${e}`}:{ok:!1,statusCode:403,message:"Missing Host header"}}export{a as createSecurityPolicy};
1
+ function a(o){const e=new Set([`http://127.0.0.1:${o.serverPort}`,`http://localhost:${o.serverPort}`,...o.allowedOrigins]),t=new Set([`127.0.0.1:${o.serverPort}`,`localhost:${o.serverPort}`,...o.allowedHosts]);return{validateRequest(s){const r=i(s,e);if(!r.ok)return r;const n=l(s,t);return n.ok?{ok:!0}:n}}}function i(o,e){const t=o.headers.origin;return t?e.has(t)?{ok:!0}:{ok:!1,statusCode:403,message:`Origin not allowed: ${t}`}:{ok:!0}}function l(o,e){const t=o.headers.host;return t?e.has(t)?{ok:!0}:{ok:!1,statusCode:403,message:`Host not allowed: ${t}`}:{ok:!1,statusCode:403,message:"Missing Host header"}}export{a as createSecurityPolicy};
@@ -9410,7 +9410,7 @@ var TOOLS = [
9410
9410
  },
9411
9411
  {
9412
9412
  name: "grix_message_send",
9413
- description: "Send a message to a session in the Grix/AIBot platform.",
9413
+ description: "Send a message to a session in the Grix/AIBot platform. Do NOT use this to answer the inbound event you are currently handling \u2014 answer in plain text (or the reply tool where available) instead, otherwise the user receives duplicate messages.",
9414
9414
  inputSchema: {
9415
9415
  type: "object",
9416
9416
  properties: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grix-connector",
3
- "version": "3.31.1",
3
+ "version": "3.31.3",
4
4
  "description": "Connect local AI coding agents (Claude, Codex, Gemini, Qwen, DeepSeek, Cursor, OpenCode, Pi, OpenHuman, Reasonix) to the Grix scheduling platform. Also serves as an OpenClaw plugin for Grix channel transport.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",