Class: PetriDish::Environment

Inherits:
Object
  • Object
show all
Defined in:
lib/petri_dish/environment.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ Environment

Returns a new instance of Environment.



11
12
13
# File 'lib/petri_dish/environment.rb', line 11

def initialize(name)
  @name = name
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



9
10
11
# File 'lib/petri_dish/environment.rb', line 9

def name
  @name
end

Instance Method Details

#clean!Object



62
63
64
# File 'lib/petri_dish/environment.rb', line 62

def clean!
  run("cenv remove #{name}")
end

#clear_hook_log!Object



28
29
30
31
# File 'lib/petri_dish/environment.rb', line 28

def clear_hook_log!
  path = hook_log_path
  File.write(path, "") if File.exist?(path)
end

#create!(bare: false) ⇒ Object



52
53
54
55
56
57
58
59
60
# File 'lib/petri_dish/environment.rb', line 52

def create!(bare: false)
  if exists?
    log "Environment '#{name}' already exists, skipping create"
    return
  end
  cmd = "cenv create #{name}"
  cmd += " --bare" if bare
  run!(cmd)
end

#detect_marketplace_name(source) ⇒ Object



88
89
90
91
92
93
94
# File 'lib/petri_dish/environment.rb', line 88

def detect_marketplace_name(source)
  output = `cenv run #{name.shellescape} -- plugin marketplace list 2>/dev/null`
  lines = output.lines
  source_idx = lines.index { |l| l.include?("Source:") && l.include?("(#{source})") }
  return nil unless source_idx && source_idx > 0
  lines[source_idx - 1].strip.sub(/^❯\s+/, "").strip
end

#env_pathObject



20
21
22
# File 'lib/petri_dish/environment.rb', line 20

def env_path
  `cenv path #{name} 2>/dev/null`.strip
end

#exists?Boolean

Returns:

  • (Boolean)


15
16
17
18
# File 'lib/petri_dish/environment.rb', line 15

def exists?
  path = env_path
  path && File.directory?(path)
end

#hook_log_pathObject



24
25
26
# File 'lib/petri_dish/environment.rb', line 24

def hook_log_path
  "#{env_path}/hook-events.jsonl"
end

#inject_hooks!(prompt_mode:) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/petri_dish/environment.rb', line 33

def inject_hooks!(prompt_mode:)
  hooks = {
    "hooks" => {
      "PreToolUse" => [event_logger_hook_with_matcher],
      "PostToolUse" => [event_logger_hook_with_matcher],
      "UserPromptSubmit" => [event_logger_hook_without_matcher],
      "Notification" => [event_logger_hook_without_matcher],
      "Stop" => [event_logger_hook_without_matcher],
      "SubagentStop" => [event_logger_hook_without_matcher],
      "PreCompact" => [event_logger_hook_with_matcher],
      "SessionStart" => [event_logger_hook_with_matcher],
      "SessionEnd" => [event_logger_hook_with_matcher],
      "PermissionRequest" => [permission_handler_hook(prompt_mode)],
      "PermissionDenied" => [event_logger_hook_with_matcher]
    }
  }
  merge_settings!(hooks)
end

#install_plugin!(marketplace:, plugin:) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/petri_dish/environment.rb', line 74

def install_plugin!(marketplace:, plugin:)
  # Add marketplace (idempotent, errors if already added)
  run("cenv run #{name} -- plugin marketplace add #{marketplace}")

  # cenv stores the marketplace under its canonical name (from marketplace.json),
  # which is not always the slug derived from the source URL. Detect it from the
  # list, fall back to the slug if detection fails.
  marketplace_name = detect_marketplace_name(marketplace) || marketplace.tr("/", "-")

  # Install plugin
  run!("cenv run #{name} -- plugin install #{plugin}@#{marketplace_name}")
  log "Installed #{plugin}@#{marketplace_name}"
end

#merge_settings!(settings) ⇒ Object



66
67
68
69
70
71
72
# File 'lib/petri_dish/environment.rb', line 66

def merge_settings!(settings)
  return if settings.nil? || settings.empty?

  json = JSON.generate(settings)
  run!("cenv settings merge #{name} '#{json}'")
  log "Merged settings into '#{name}'"
end

#trust!(work_dir) ⇒ Object



96
97
98
99
100
# File 'lib/petri_dish/environment.rb', line 96

def trust!(work_dir)
  path = File.realpath(File.expand_path(work_dir)) rescue File.expand_path(work_dir)
  run!("cenv trust #{name} #{path.shellescape}")
  log "Trusted #{path}"
end