vibora 9.7.2 → 9.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/vibora.js CHANGED
@@ -45126,7 +45126,7 @@ function installUv() {
45126
45126
  var package_default = {
45127
45127
  name: "vibora",
45128
45128
  private: true,
45129
- version: "9.7.2",
45129
+ version: "9.8.1",
45130
45130
  description: "Harness Attention. Orchestrate Agents. Ship.",
45131
45131
  license: "PolyForm-Perimeter-1.0.0",
45132
45132
  type: "module",
@@ -45659,7 +45659,7 @@ import { join as join4 } from "path";
45659
45659
  // plugins/vibora-opencode/index.ts
45660
45660
  var vibora_opencode_default = `import type { Plugin } from "@opencode-ai/plugin"
45661
45661
  import { appendFileSync } from "node:fs"
45662
- import { execFile } from "node:child_process"
45662
+ import { spawn } from "node:child_process"
45663
45663
  import { tmpdir } from "node:os"
45664
45664
  import { join } from "node:path"
45665
45665
 
@@ -45681,20 +45681,72 @@ const log = (msg: string) => {
45681
45681
  }
45682
45682
 
45683
45683
  /**
45684
- * Execute vibora command using execFile with shell option for proper PATH resolution.
45685
- * Using execFile with explicit args array prevents shell injection while shell:true
45684
+ * Execute vibora command using spawn with shell option for proper PATH resolution.
45685
+ * Using spawn with explicit args array prevents shell injection while shell:true
45686
45686
  * ensures PATH is properly resolved (for NVM, fnm, etc. managed node installations).
45687
+ * Includes 10 second timeout protection to prevent hanging.
45687
45688
  */
45688
45689
  async function runViboraCommand(args: string[]): Promise<{ exitCode: number; stdout: string; stderr: string }> {
45689
45690
  return new Promise((resolve) => {
45690
- execFile(VIBORA_CMD, args, { shell: true }, (error, stdout, stderr) => {
45691
- if (error) {
45692
- const execError = error as NodeJS.ErrnoException
45693
- resolve({ exitCode: execError.code ? 1 : 1, stdout: stdout || '', stderr: stderr || execError.message || '' })
45694
- } else {
45695
- resolve({ exitCode: 0, stdout: stdout || '', stderr: stderr || '' })
45691
+ let stdout = ''
45692
+ let stderr = ''
45693
+ let resolved = false
45694
+ let processExited = false
45695
+ let killTimeoutId: ReturnType<typeof setTimeout> | null = null
45696
+
45697
+ const child = spawn(VIBORA_CMD, args, { shell: true })
45698
+
45699
+ const cleanup = () => {
45700
+ processExited = true
45701
+ if (killTimeoutId) {
45702
+ clearTimeout(killTimeoutId)
45703
+ killTimeoutId = null
45704
+ }
45705
+ }
45706
+
45707
+ child.stdout?.on('data', (data) => {
45708
+ stdout += data.toString()
45709
+ })
45710
+
45711
+ child.stderr?.on('data', (data) => {
45712
+ stderr += data.toString()
45713
+ })
45714
+
45715
+ child.on('close', (code) => {
45716
+ cleanup()
45717
+ if (!resolved) {
45718
+ resolved = true
45719
+ resolve({ exitCode: code || 0, stdout, stderr })
45696
45720
  }
45697
45721
  })
45722
+
45723
+ child.on('error', (err) => {
45724
+ cleanup()
45725
+ if (!resolved) {
45726
+ resolved = true
45727
+ resolve({ exitCode: 1, stdout, stderr: err.message || '' })
45728
+ }
45729
+ })
45730
+
45731
+ // Add timeout protection to prevent hanging
45732
+ const timeoutId = setTimeout(() => {
45733
+ if (!resolved) {
45734
+ resolved = true
45735
+ log(\`Command timeout: \${VIBORA_CMD} \${args.join(' ')}\`)
45736
+ child.kill('SIGTERM')
45737
+ // Schedule SIGKILL if process doesn't exit after SIGTERM
45738
+ killTimeoutId = setTimeout(() => {
45739
+ if (!processExited) {
45740
+ log(\`Process didn't exit after SIGTERM, sending SIGKILL\`)
45741
+ child.kill('SIGKILL')
45742
+ }
45743
+ }, 2000)
45744
+ resolve({ exitCode: -1, stdout, stderr: \`Command timed out after \${VIBORA_COMMAND_TIMEOUT_MS}ms\` })
45745
+ }
45746
+ }, VIBORA_COMMAND_TIMEOUT_MS)
45747
+
45748
+ // Clear timeout if command completes
45749
+ child.on('exit', () => clearTimeout(timeoutId))
45698
45750
  })
45699
45751
  }
45700
45752
 
@@ -45706,9 +45758,12 @@ let lastStatus: "in-progress" | "review" | "" = ""
45706
45758
 
45707
45759
  const VIBORA_CMD = "vibora"
45708
45760
  const IDLE_CONFIRMATION_DELAY_MS = 1500
45761
+ const VIBORA_COMMAND_TIMEOUT_MS = 10000
45762
+ const STATUS_CHANGE_DEBOUNCE_MS = 500
45709
45763
 
45710
45764
  let deferredContextCheck: Promise<boolean> | null = null
45711
45765
  let isViboraContext: boolean | null = null
45766
+ let pendingStatusCommand: Promise<{ exitCode: number; stdout: string; stderr: string }> | null = null
45712
45767
 
45713
45768
  export const ViboraPlugin: Plugin = async ({ $, directory }) => {
45714
45769
  log("Plugin initializing...")
@@ -45760,16 +45815,28 @@ export const ViboraPlugin: Plugin = async ({ $, directory }) => {
45760
45815
  if (status === lastStatus) return
45761
45816
 
45762
45817
  cancelPendingIdle()
45818
+
45819
+ if (pendingStatusCommand) {
45820
+ log(\`Status change already in progress, will retry after \${STATUS_CHANGE_DEBOUNCE_MS}ms\`)
45821
+ setTimeout(() => setStatus(status), STATUS_CHANGE_DEBOUNCE_MS)
45822
+ return
45823
+ }
45824
+
45763
45825
  lastStatus = status
45826
+
45764
45827
  ;(async () => {
45765
45828
  try {
45766
45829
  log(\`Setting status: \${status}\`)
45767
- const res = await runViboraCommand(['current-task', status, '--path', directory])
45830
+ pendingStatusCommand = runViboraCommand(['current-task', status, '--path', directory])
45831
+ const res = await pendingStatusCommand
45832
+ pendingStatusCommand = null
45833
+
45768
45834
  if (res.exitCode !== 0) {
45769
45835
  log(\`Status update failed: exitCode=\${res.exitCode}, stderr=\${res.stderr}\`)
45770
45836
  }
45771
45837
  } catch (e) {
45772
45838
  log(\`Status update error: \${e}\`)
45839
+ pendingStatusCommand = null
45773
45840
  }
45774
45841
  })()
45775
45842
  }