pwn 0.5.642 → 0.5.647
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 +4 -4
- data/Gemfile +1 -1
- data/README.md +1 -1
- data/documentation/Cron.md +3 -2
- data/documentation/Home.md +1 -1
- data/documentation/Mistakes.md +13 -0
- data/documentation/Reinforcement-Learning.md +37 -3
- data/documentation/Skills-Memory-Learning.md +5 -3
- data/documentation/diagrams/dot/pwn-ai-feedback-learning-loop.dot +3 -3
- data/documentation/diagrams/dot/reinforcement-learning.dot +8 -8
- data/documentation/diagrams/pwn-ai-feedback-learning-loop.svg +318 -319
- data/documentation/diagrams/reinforcement-learning.svg +188 -187
- data/documentation/pwn-ai-Agent.md +5 -4
- data/lib/pwn/ai/agent/curriculum.rb +368 -32
- data/lib/pwn/ai/agent/learning.rb +159 -13
- data/lib/pwn/ai/agent/loop.rb +75 -4
- data/lib/pwn/ai/agent/metrics.rb +140 -10
- data/lib/pwn/ai/agent/mistakes.rb +26 -8
- data/lib/pwn/ai/agent/registry.rb +5 -2
- data/lib/pwn/ai/agent/reward.rb +279 -5
- data/lib/pwn/ai/agent/tools/reward.rb +66 -0
- data/lib/pwn/ai/anthropic.rb +265 -4
- data/lib/pwn/ai/open_ai.rb +307 -4
- data/lib/pwn/config.rb +50 -9
- data/lib/pwn/cron.rb +14 -2
- data/lib/pwn/version.rb +1 -1
- data/spec/integration/reinforced_feedback_loop_spec.rb +507 -12
- data/spec/lib/pwn/ai/agent/reward_spec.rb +64 -1
- data/third_party/pwn_rdoc.jsonl +35 -2
- metadata +3 -3
data/lib/pwn/config.rb
CHANGED
|
@@ -49,7 +49,22 @@ module PWN
|
|
|
49
49
|
system_role_content: 'You are an ethically hacking OpenAI agent.',
|
|
50
50
|
temp: 'optional - OpenAI temperature',
|
|
51
51
|
max_tokens: 'optional - Max output tokens per response (default 16384). Mapped to OpenAI wire param max_completion_tokens.',
|
|
52
|
-
max_prompt_length: 128_000
|
|
52
|
+
max_prompt_length: 128_000,
|
|
53
|
+
# OAuth support for ChatGPT / Codex subscriptions (in addition to API key)
|
|
54
|
+
# Populate via pwn-vault (values stored encrypted in ~/.pwn/pwn.yaml)
|
|
55
|
+
oauth: {
|
|
56
|
+
# OpenAI OAuth uses the PUBLIC Codex client (app_EMoamEEZ73f0CkXaXp7hrann) --
|
|
57
|
+
# NO client_secret. Run PWN::AI::OpenAI.obtain_oauth_bearer_token once
|
|
58
|
+
# (Codex device-code flow) then store refresh_token here; PWN refreshes
|
|
59
|
+
# the short-lived access_token automatically on every run.
|
|
60
|
+
refresh_token: 'optional - ChatGPT/Codex OAuth Refresh Token (durable; enables silent re-auth)',
|
|
61
|
+
bearer_token: 'optional - ChatGPT/Codex OAuth Access Token (short-lived JWT; auto-refreshed if refresh_token set)',
|
|
62
|
+
client_id: 'optional - override public Codex client_id (default: app_EMoamEEZ73f0CkXaXp7hrann)',
|
|
63
|
+
account_id: 'optional - ChatGPT account/workspace id (sent as ChatGPT-Account-Id when set)',
|
|
64
|
+
issuer: 'optional - override OAuth issuer (default: https://auth.openai.com)',
|
|
65
|
+
token_uri: 'optional - override OAuth token endpoint (default: https://auth.openai.com/oauth/token)',
|
|
66
|
+
enroll: 'optional - set true to force device-flow enrollment even when an API key is present'
|
|
67
|
+
}
|
|
53
68
|
},
|
|
54
69
|
ollama: {
|
|
55
70
|
base_uri: 'required - Base URI for Open WebUI - e.g. https://ollama.local',
|
|
@@ -77,7 +92,25 @@ module PWN
|
|
|
77
92
|
system_role_content: 'You are an ethically hacking Anthropic agent.',
|
|
78
93
|
temp: 'optional - Anthropic temperature',
|
|
79
94
|
max_tokens: 'optional - Max output tokens per response (default 8192). Raise if tool calls truncate.',
|
|
80
|
-
max_prompt_length: 200_000
|
|
95
|
+
max_prompt_length: 200_000,
|
|
96
|
+
# OAuth support for Claude Pro/Max subscriptions (in addition to API key)
|
|
97
|
+
# Populate via pwn-vault (values stored encrypted in ~/.pwn/pwn.yaml)
|
|
98
|
+
oauth: {
|
|
99
|
+
# Anthropic OAuth uses the PUBLIC Claude Code client
|
|
100
|
+
# (9d1c250a-e61b-44d9-88ed-5944d1962f5e) -- NO client_secret.
|
|
101
|
+
# Run PWN::AI::Anthropic.obtain_oauth_bearer_token once (PKCE paste
|
|
102
|
+
# flow) then store refresh_token here; PWN refreshes the short-lived
|
|
103
|
+
# access_token automatically on every run.
|
|
104
|
+
refresh_token: 'optional - Claude Pro/Max OAuth Refresh Token (durable; enables silent re-auth)',
|
|
105
|
+
bearer_token: 'optional - Claude Pro/Max OAuth Access Token (short-lived; auto-refreshed if refresh_token set)',
|
|
106
|
+
client_id: 'optional - override public Claude Code client_id (default: 9d1c250a-e61b-44d9-88ed-5944d1962f5e)',
|
|
107
|
+
scope: 'optional - override OAuth scope (default: user:profile user:inference user:sessions:claude_code user:mcp_servers user:file_upload)',
|
|
108
|
+
authorize_uri: 'optional - override authorize endpoint (default: https://claude.ai/oauth/authorize)',
|
|
109
|
+
token_uri: 'optional - override token endpoint (default: https://platform.claude.com/v1/oauth/token)',
|
|
110
|
+
redirect_uri: 'optional - override redirect_uri (default: https://platform.claude.com/oauth/code/callback)',
|
|
111
|
+
beta_flags: 'optional - anthropic-beta header value for OAuth requests',
|
|
112
|
+
enroll: 'optional - set true to force PKCE enrollment even when an API key is present'
|
|
113
|
+
}
|
|
81
114
|
},
|
|
82
115
|
gemini: {
|
|
83
116
|
base_uri: 'optional - Base URI for Gemini - Use private base OR defaults to https://generativelanguage.googleapis.com/v1beta',
|
|
@@ -416,13 +449,16 @@ module PWN
|
|
|
416
449
|
key = nil unless real_cfg.call(key)
|
|
417
450
|
|
|
418
451
|
oauth_configured = false
|
|
419
|
-
if
|
|
452
|
+
if %i[grok openai anthropic].include?(engine)
|
|
420
453
|
oauth = env[:ai][engine][:oauth]
|
|
421
454
|
oauth = env[:ai][engine][:oauth] = {} unless oauth.is_a?(Hash)
|
|
422
|
-
# OAuth is considered configured when
|
|
423
|
-
# stored
|
|
424
|
-
#
|
|
455
|
+
# OAuth is considered configured when a bearer_token / refresh_token
|
|
456
|
+
# is stored, enroll is truthy, or a non-placeholder client_id is set
|
|
457
|
+
# (module will run the singular enrollment flow).
|
|
425
458
|
oauth_configured = real_cfg.call(oauth[:bearer_token]) ||
|
|
459
|
+
real_cfg.call(oauth[:refresh_token]) ||
|
|
460
|
+
oauth[:enroll] == true ||
|
|
461
|
+
real_cfg.call(oauth[:client_id]) ||
|
|
426
462
|
(real_cfg.call(oauth[:client_id]) && real_cfg.call(oauth[:client_secret]))
|
|
427
463
|
end
|
|
428
464
|
|
|
@@ -433,9 +469,14 @@ module PWN
|
|
|
433
469
|
interactive = $stdin.tty? && $stdout.tty? && ENV['PWN_NONINTERACTIVE'].to_s.empty?
|
|
434
470
|
|
|
435
471
|
if key.nil? && !oauth_configured && interactive
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
472
|
+
enroll_hints = {
|
|
473
|
+
grok: 'or store ai.grok.oauth.refresh_token via pwn-vault -- run PWN::AI::Grok.obtain_oauth_bearer_token to enroll',
|
|
474
|
+
openai: 'or store ai.openai.oauth.refresh_token via pwn-vault -- run PWN::AI::OpenAI.obtain_oauth_bearer_token to enroll',
|
|
475
|
+
anthropic: 'or store ai.anthropic.oauth.refresh_token via pwn-vault -- run PWN::AI::Anthropic.obtain_oauth_bearer_token to enroll'
|
|
476
|
+
}
|
|
477
|
+
enroll_hint = enroll_hints[engine]
|
|
478
|
+
prompt = enroll_hint ? "#{engine} API Key (#{enroll_hint})" : "#{engine} API Key"
|
|
479
|
+
key = PWN::Plugins::AuthenticationHelper.mask_password(prompt: prompt)
|
|
439
480
|
env[:ai][engine][:key] = key
|
|
440
481
|
end
|
|
441
482
|
|
data/lib/pwn/cron.rb
CHANGED
|
@@ -231,8 +231,11 @@ module PWN
|
|
|
231
231
|
)
|
|
232
232
|
end
|
|
233
233
|
|
|
234
|
-
# P3 — backfill ORM/PRM labels when local :failure_only introspect is on
|
|
235
|
-
|
|
234
|
+
# P3 — backfill ORM/PRM labels when local :failure_only introspect is on.
|
|
235
|
+
# P13 — treat legacy alias offline_judge_nightly as the same job so
|
|
236
|
+
# install_defaults never double-seeds the 30 3 * * * slot.
|
|
237
|
+
offline_names = %w[curriculum_offline_judge offline_judge_nightly]
|
|
238
|
+
unless names.intersect?(offline_names)
|
|
236
239
|
seeded << create(
|
|
237
240
|
name: 'curriculum_offline_judge',
|
|
238
241
|
schedule: '30 3 * * *',
|
|
@@ -241,6 +244,15 @@ module PWN
|
|
|
241
244
|
enabled: true
|
|
242
245
|
)
|
|
243
246
|
end
|
|
247
|
+
# Disable duplicate alias if both exist (idempotent cleanup).
|
|
248
|
+
if names.include?('curriculum_offline_judge') && names.include?('offline_judge_nightly')
|
|
249
|
+
begin
|
|
250
|
+
dup = jobs.values.find { |j| j[:name].to_s == 'offline_judge_nightly' }
|
|
251
|
+
disable(id: dup[:id]) if dup && dup[:enabled]
|
|
252
|
+
rescue StandardError
|
|
253
|
+
nil
|
|
254
|
+
end
|
|
255
|
+
end
|
|
244
256
|
|
|
245
257
|
# M1/M3 — nightly memory GC so the injected MEMORY block stays high-signal
|
|
246
258
|
unless names.include?('learning_consolidate_nightly')
|
data/lib/pwn/version.rb
CHANGED