brainiac-discord 0.0.11 → 0.0.13
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.
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1f2f87e89db33072e4ceb141ec472b71ce09f22d3a383da595f195f3f441b9ee
|
|
4
|
+
data.tar.gz: 69aeb6d7e6f945f0fb517c8bfd37a6d91e749137d634d5578596a462579044b2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2eab7e192cfe422009193273e88bbf8aab1b8ccecdf3d33d7643847b4799a55f44bb5c3d5f18c56eea753982491c73426942e420a1d99c418867829c9bb65fdf
|
|
7
|
+
data.tar.gz: 6f66c81ea46ac32423fb10a542730c3e2c71d6d7db71b959ef188b93effa68a12932f4e8e52cc1d203473882355d78339058320dbba9eb61eb8e88d62a479700
|
|
@@ -558,8 +558,24 @@ module Brainiac
|
|
|
558
558
|
)
|
|
559
559
|
end
|
|
560
560
|
|
|
561
|
+
# Resolve CLI overrides and work_dir BEFORE building the prompt so we can determine
|
|
562
|
+
# whether resume will actually work. This prevents sending a lean prompt when
|
|
563
|
+
# the CLI won't actually have session state.
|
|
564
|
+
work_dir = chat_mode_fallback(agent_key, agent_name, message_id, chat_mode, thread_worktree_path) ||
|
|
565
|
+
(project_config ? project_config["repo_path"] : Dir.pwd)
|
|
566
|
+
model, effort, cli_provider_override = resolve_overrides(
|
|
567
|
+
clean_content, project_config, thread_model, thread_effort, thread_cli_provider
|
|
568
|
+
)
|
|
569
|
+
resolved = resolve_project_cli_config(project_config || DEFAULT_PROJECT,
|
|
570
|
+
cli_provider_override: cli_provider_override, agent_name: agent_name)
|
|
571
|
+
|
|
572
|
+
# Convert should_resume to the actual flag/symbol. If resolve_resume returns false,
|
|
573
|
+
# we know the CLI won't actually resume, so we shouldn't send a lean prompt.
|
|
574
|
+
actual_resume = should_resume ? resolve_resume(true, resolved, work_dir) : false
|
|
575
|
+
use_lean_prompt = actual_resume && thread_worktree_path
|
|
576
|
+
|
|
561
577
|
prompt = build_prompt(
|
|
562
|
-
should_resume:
|
|
578
|
+
should_resume: use_lean_prompt, thread_worktree_path: thread_worktree_path,
|
|
563
579
|
clean_content_for_prompt: clean_content_for_prompt,
|
|
564
580
|
discord_user: discord_user, channel_name: channel_info&.dig("name") || channel_id, reply_context: reply_context,
|
|
565
581
|
channel_history: channel_history, thread_root_context: thread_root_context,
|
|
@@ -567,15 +583,9 @@ module Brainiac
|
|
|
567
583
|
brain_context: brain_context, agent_name: agent_name, supersede_key: supersede_key
|
|
568
584
|
)
|
|
569
585
|
|
|
570
|
-
work_dir = chat_mode_fallback(agent_key, agent_name, message_id, chat_mode, thread_worktree_path) ||
|
|
571
|
-
(project_config ? project_config["repo_path"] : Dir.pwd)
|
|
572
586
|
prompt_file = File.join(response_dir, "discord-prompt-#{timestamp}-#{agent_key}-#{message_id}.md")
|
|
573
587
|
File.write(prompt_file, prompt)
|
|
574
588
|
|
|
575
|
-
model, effort, cli_provider_override = resolve_overrides(
|
|
576
|
-
clean_content, project_config, thread_model, thread_effort, thread_cli_provider
|
|
577
|
-
)
|
|
578
|
-
|
|
579
589
|
persist_overrides(thread_map_key, clean_content, project_config,
|
|
580
590
|
cli_provider: cli_provider_override, model: model, effort: effort,
|
|
581
591
|
prev_cli_provider: thread_cli_provider, prev_model: thread_model, prev_effort: thread_effort)
|
|
@@ -592,8 +602,8 @@ module Brainiac
|
|
|
592
602
|
agent_key: agent_key, agent_name: agent_name, bot_token: bot_token,
|
|
593
603
|
channel_id: channel_id, message_id: message_id, discord_user: discord_user,
|
|
594
604
|
work_dir: work_dir, prompt_file: prompt_file, response_file: response_file,
|
|
595
|
-
meta_file: meta_file, model: model, effort: effort,
|
|
596
|
-
|
|
605
|
+
meta_file: meta_file, model: model, effort: effort, actual_resume: actual_resume,
|
|
606
|
+
resolved: resolved, project_config: project_config,
|
|
597
607
|
session_key: session_key, supersede_key: supersede_key,
|
|
598
608
|
attachment_paths: attachment_paths, timestamp: timestamp, response_dir: response_dir
|
|
599
609
|
)
|
|
@@ -886,17 +896,15 @@ module Brainiac
|
|
|
886
896
|
|
|
887
897
|
def spawn_agent(agent_key:, agent_name:, bot_token:, channel_id:, message_id:, discord_user:,
|
|
888
898
|
work_dir:, prompt_file:, response_file:, meta_file:, model:, effort:,
|
|
889
|
-
|
|
899
|
+
actual_resume:, resolved:, project_config:,
|
|
890
900
|
session_key:, supersede_key:, attachment_paths:, timestamp:, response_dir:)
|
|
891
901
|
agent_config_name = agent_key.downcase.gsub(/[^a-z0-9-]/, "-")
|
|
892
902
|
log_file = File.join(response_dir, "discord-agent-#{timestamp}-#{agent_key}-#{message_id}.log")
|
|
893
903
|
|
|
894
|
-
resolved = resolve_project_cli_config(project_config || DEFAULT_PROJECT,
|
|
895
|
-
cli_provider_override: cli_provider_override, agent_name: agent_name)
|
|
896
904
|
cmd = build_agent_cmd(resolved, agent_config_name: agent_config_name, model: model, effort: effort,
|
|
897
|
-
prompt_file: prompt_file, resume:
|
|
905
|
+
prompt_file: prompt_file, resume: actual_resume)
|
|
898
906
|
|
|
899
|
-
resume_note =
|
|
907
|
+
resume_note = actual_resume ? ", resuming" : ""
|
|
900
908
|
if defined?(LOG)
|
|
901
909
|
LOG.info "[Discord:#{agent_name}] Dispatching for #{discord_user} " \
|
|
902
910
|
"(model: #{model || "default"}, effort: #{effort || "default"}, cli: #{resolved["agent_cli"]}#{resume_note}), tail -f #{log_file}"
|
|
@@ -910,6 +918,17 @@ module Brainiac
|
|
|
910
918
|
LOG.info "[Discord:#{agent_name}] Injecting #{agent_env.size} env var(s): #{agent_env.keys.join(", ")}" if defined?(LOG)
|
|
911
919
|
end
|
|
912
920
|
|
|
921
|
+
# Inject a GitHub App token so `gh`/`git` run as the agent's own bot
|
|
922
|
+
# identity (e.g. galen[bot]) instead of the host machine's personal
|
|
923
|
+
# `gh auth`. Without this, `gh pr create` in the prompt would open PRs
|
|
924
|
+
# under whoever is logged in on the box. No-op if the github plugin
|
|
925
|
+
# isn't loaded or the agent has no app configured.
|
|
926
|
+
gh_env = github_agent_token_env(agent_name, project_config)
|
|
927
|
+
unless gh_env.empty?
|
|
928
|
+
spawn_env.merge!(gh_env)
|
|
929
|
+
LOG.info "[Discord:#{agent_name}] Injecting GitHub App token (GH_TOKEN) for bot identity" if defined?(LOG)
|
|
930
|
+
end
|
|
931
|
+
|
|
913
932
|
head_before, status_before = capture_brainiac_state(project_config, work_dir)
|
|
914
933
|
prompt_mode = resolved["prompt_mode"] || "stdin"
|
|
915
934
|
|
|
@@ -936,6 +955,41 @@ module Brainiac
|
|
|
936
955
|
)
|
|
937
956
|
end
|
|
938
957
|
|
|
958
|
+
# Build a { "GH_TOKEN" => ... } env hash so the spawned agent's `gh`
|
|
959
|
+
# and `git` invocations authenticate as the agent's own GitHub App bot
|
|
960
|
+
# rather than the host's personal `gh auth`. This is what makes the
|
|
961
|
+
# prompt's `gh pr create` open PRs under e.g. galen[bot].
|
|
962
|
+
#
|
|
963
|
+
# Reuses the brainiac-github plugin's AppClient. The github plugin is
|
|
964
|
+
# optional, so everything is guarded: if it isn't loaded, or no app is
|
|
965
|
+
# configured for the agent (or the shared "brainiac" app), we return an
|
|
966
|
+
# empty hash and `gh` falls back to whatever's authenticated on the box.
|
|
967
|
+
def github_agent_token_env(agent_name, project_config)
|
|
968
|
+
return {} unless agent_name && project_config
|
|
969
|
+
|
|
970
|
+
repo = project_config["github_repo"]
|
|
971
|
+
return {} unless repo && !repo.to_s.empty?
|
|
972
|
+
|
|
973
|
+
return {} unless defined?(Brainiac::Plugins::Github::AppClient)
|
|
974
|
+
|
|
975
|
+
client = Brainiac::Plugins::Github::AppClient
|
|
976
|
+
effective_agent = if client.configured?(agent_name)
|
|
977
|
+
agent_name
|
|
978
|
+
elsif client.configured?("brainiac")
|
|
979
|
+
"brainiac"
|
|
980
|
+
end
|
|
981
|
+
return {} unless effective_agent
|
|
982
|
+
|
|
983
|
+
repo_owner = repo.to_s.split("/").first
|
|
984
|
+
token = client.installation_token_for(effective_agent, repo_owner: repo_owner)
|
|
985
|
+
return {} unless token && !token.empty?
|
|
986
|
+
|
|
987
|
+
{ "GH_TOKEN" => token }
|
|
988
|
+
rescue StandardError => e
|
|
989
|
+
LOG.warn "[Discord:#{agent_name}] Could not mint GitHub App token: #{e.message}" if defined?(LOG)
|
|
990
|
+
{}
|
|
991
|
+
end
|
|
992
|
+
|
|
939
993
|
def capture_brainiac_state(project_config, work_dir)
|
|
940
994
|
return [nil, nil] unless project_config
|
|
941
995
|
|
|
@@ -48,8 +48,8 @@ module Brainiac
|
|
|
48
48
|
3. Make the changes, test if applicable
|
|
49
49
|
4. Commit with a clear message
|
|
50
50
|
5. Push the branch
|
|
51
|
-
6.
|
|
52
|
-
7.
|
|
51
|
+
6. Open a PR with `gh pr create --fill` (or with a descriptive body)
|
|
52
|
+
7. Summarize what you did in your response file, including a link to the PR
|
|
53
53
|
|
|
54
54
|
**When responding conversationally:**
|
|
55
55
|
- Answer questions about the codebase, architecture, conventions
|