portage-cli 0.13.0 → 0.14.0
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/CHANGELOG.md +22 -0
- data/README.md +61 -1
- data/exe/portage-console +2 -1
- data/lib/portage/cli/buy.rb +11 -2
- data/lib/portage/cli/console.rb +8 -0
- data/lib/portage/cli/generate/agent_profile.rb +25 -13
- data/lib/portage/cli/handoff_reconciler.rb +11 -3
- data/lib/portage/cli/mcp/runner.rb +128 -0
- data/lib/portage/cli/mcp/server.rb +70 -0
- data/lib/portage/cli/mcp/tools.rb +527 -0
- data/lib/portage/cli/order_history.rb +127 -0
- data/lib/portage/cli/version.rb +1 -1
- data/lib/portage/cli.rb +55 -1
- metadata +50 -4
data/lib/portage/cli/version.rb
CHANGED
data/lib/portage/cli.rb
CHANGED
|
@@ -17,6 +17,7 @@ require_relative "cli/find"
|
|
|
17
17
|
require_relative "cli/compare"
|
|
18
18
|
require_relative "cli/check"
|
|
19
19
|
require_relative "cli/history"
|
|
20
|
+
require_relative "cli/order_history"
|
|
20
21
|
require_relative "cli/quotes"
|
|
21
22
|
require_relative "cli/money"
|
|
22
23
|
require_relative "cli/human_prompt"
|
|
@@ -77,6 +78,7 @@ module Portage
|
|
|
77
78
|
[--velocity-count N --velocity-window-seconds N]
|
|
78
79
|
[--allow HOST ...] [--clear-allowlist]
|
|
79
80
|
[--require-approval person|any|off] (lowering asks at a terminal)
|
|
81
|
+
portage orders list [--query Q] [--limit N] [--json]
|
|
80
82
|
portage orders reconcile [--checkout ID] [--json]
|
|
81
83
|
portage index build [--sources a,b] [--queries FILE] [--dry-run] [--export DIR] [--json]
|
|
82
84
|
portage index refresh [--sources a,b] [--queries FILE] [--dry-run] [--export DIR] [--json]
|
|
@@ -95,6 +97,7 @@ module Portage
|
|
|
95
97
|
portage setup [--json] (interactive wizard on a TTY; --json/no TTY: today's doctor report)
|
|
96
98
|
portage generate adapter NAME [--dir DIR]
|
|
97
99
|
portage generate agent-profile [--out FILE] [--key-out FILE] [--rotate]
|
|
100
|
+
portage mcp (MCP server on stdio for the shopper's agent; read-only and quotes only)
|
|
98
101
|
portage --version
|
|
99
102
|
|
|
100
103
|
proxy flags (buy/find/compare/check/doctor/payment enroll):
|
|
@@ -108,7 +111,8 @@ module Portage
|
|
|
108
111
|
"history" => :run_history, "payment" => :run_payment, "policy" => :run_policy,
|
|
109
112
|
"orders" => :run_orders, "index" => :run_index, "browser" => :run_browser,
|
|
110
113
|
"doctor" => :run_doctor,
|
|
111
|
-
"configure" => :run_doctor, "setup" => :run_setup, "generate" => :run_generate
|
|
114
|
+
"configure" => :run_doctor, "setup" => :run_setup, "generate" => :run_generate,
|
|
115
|
+
"mcp" => :run_mcp }.freeze
|
|
112
116
|
|
|
113
117
|
VERSION_FLAGS = %w[--version -v version].freeze
|
|
114
118
|
|
|
@@ -123,6 +127,19 @@ module Portage
|
|
|
123
127
|
1
|
|
124
128
|
end
|
|
125
129
|
|
|
130
|
+
# `portage mcp` (docs/plans/buyer-mcp-server.md): the buyer MCP server
|
|
131
|
+
# on stdio. Loaded only here, so other commands don't pay for it.
|
|
132
|
+
def self.run_mcp(argv)
|
|
133
|
+
unless argv.empty?
|
|
134
|
+
warn USAGE
|
|
135
|
+
return 1
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
require_relative "cli/mcp/server"
|
|
139
|
+
::MCP::Server::Transports::StdioTransport.new(Mcp::Server.build).open
|
|
140
|
+
0
|
|
141
|
+
end
|
|
142
|
+
|
|
126
143
|
# So a packaged install (Homebrew's `test do` block, `portage doctor`)
|
|
127
144
|
# can confirm which release it's running without hitting the network.
|
|
128
145
|
def self.run_version
|
|
@@ -1217,12 +1234,49 @@ module Portage
|
|
|
1217
1234
|
# an error, so a scheduled run never needs its own filtering logic.
|
|
1218
1235
|
def self.run_orders(argv)
|
|
1219
1236
|
sub = argv.first && !argv.first.start_with?("-") ? argv.shift : nil
|
|
1237
|
+
return run_orders_list(argv) if sub == "list"
|
|
1220
1238
|
return run_orders_reconcile(argv) if sub == "reconcile"
|
|
1221
1239
|
|
|
1222
1240
|
warn USAGE
|
|
1223
1241
|
1
|
|
1224
1242
|
end
|
|
1225
1243
|
|
|
1244
|
+
def self.run_orders_list(argv)
|
|
1245
|
+
opts = {}
|
|
1246
|
+
OptionParser.new do |parser|
|
|
1247
|
+
parser.on("--query Q") { |v| opts[:query] = v }
|
|
1248
|
+
parser.on("--limit N", Integer) { |v| opts[:limit] = v }
|
|
1249
|
+
parser.on("--json") { opts[:json] = true }
|
|
1250
|
+
end.parse!(argv)
|
|
1251
|
+
raise OptionParser::InvalidArgument, "--limit must be positive" if opts[:limit]&.<(1)
|
|
1252
|
+
|
|
1253
|
+
entries = OrderHistory.new.call(query: opts[:query], limit: opts[:limit])
|
|
1254
|
+
puts opts[:json] ? JSON.pretty_generate(entries) : format_orders(entries)
|
|
1255
|
+
0
|
|
1256
|
+
rescue OptionParser::ParseError => e
|
|
1257
|
+
warn "#{e.message}\n#{USAGE}"
|
|
1258
|
+
1
|
|
1259
|
+
end
|
|
1260
|
+
|
|
1261
|
+
def self.format_orders(entries)
|
|
1262
|
+
return "(no orders)" if entries.empty?
|
|
1263
|
+
|
|
1264
|
+
entries.map { |entry| format_order(entry) }.join("\n\n")
|
|
1265
|
+
end
|
|
1266
|
+
|
|
1267
|
+
def self.format_order(entry)
|
|
1268
|
+
items = entry["items"].map { |item| " #{item['title'] || item['product_id']} x#{item['quantity']}" }
|
|
1269
|
+
link = entry.values_at("permalink_url", "checkout_url").compact.first
|
|
1270
|
+
adjustments = entry["adjustments"].map { |adj| " #{adj['type']}: #{adj['status']}" }
|
|
1271
|
+
[order_head(entry), *items, (" #{link}" if link), *adjustments].compact.join("\n")
|
|
1272
|
+
end
|
|
1273
|
+
|
|
1274
|
+
def self.order_head(entry)
|
|
1275
|
+
total = Money.format_amount(entry["total"], entry["currency"]) if entry["total"]
|
|
1276
|
+
[entry["recorded_at"], entry["shop"], entry["order_id"] || entry["outcome"], total,
|
|
1277
|
+
"[#{entry['source']}]"].compact.join(" — ")
|
|
1278
|
+
end
|
|
1279
|
+
|
|
1226
1280
|
def self.run_orders_reconcile(argv)
|
|
1227
1281
|
opts = {}
|
|
1228
1282
|
OptionParser.new do |parser|
|
metadata
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: portage-cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.14.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tom Whitbread
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: base64
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0.2'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0.2'
|
|
13
27
|
- !ruby/object:Gem::Dependency
|
|
14
28
|
name: irb
|
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -24,20 +38,34 @@ dependencies:
|
|
|
24
38
|
- - ">="
|
|
25
39
|
- !ruby/object:Gem::Version
|
|
26
40
|
version: '1.6'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: mcp
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0.24'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0.24'
|
|
27
55
|
- !ruby/object:Gem::Dependency
|
|
28
56
|
name: portage-ucp
|
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
|
30
58
|
requirements:
|
|
31
59
|
- - "~>"
|
|
32
60
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '0.
|
|
61
|
+
version: '0.16'
|
|
34
62
|
type: :runtime
|
|
35
63
|
prerelease: false
|
|
36
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
65
|
requirements:
|
|
38
66
|
- - "~>"
|
|
39
67
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '0.
|
|
68
|
+
version: '0.16'
|
|
41
69
|
- !ruby/object:Gem::Dependency
|
|
42
70
|
name: portage-ucp-client
|
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -86,6 +114,20 @@ dependencies:
|
|
|
86
114
|
- - "~>"
|
|
87
115
|
- !ruby/object:Gem::Version
|
|
88
116
|
version: '2.9'
|
|
117
|
+
- !ruby/object:Gem::Dependency
|
|
118
|
+
name: benchmark
|
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - "~>"
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '0.4'
|
|
124
|
+
type: :development
|
|
125
|
+
prerelease: false
|
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - "~>"
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '0.4'
|
|
89
131
|
- !ruby/object:Gem::Dependency
|
|
90
132
|
name: rspec
|
|
91
133
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -253,10 +295,14 @@ files:
|
|
|
253
295
|
- lib/portage/cli/index/store.rb
|
|
254
296
|
- lib/portage/cli/install_doctor.rb
|
|
255
297
|
- lib/portage/cli/macos_notifier.rb
|
|
298
|
+
- lib/portage/cli/mcp/runner.rb
|
|
299
|
+
- lib/portage/cli/mcp/server.rb
|
|
300
|
+
- lib/portage/cli/mcp/tools.rb
|
|
256
301
|
- lib/portage/cli/money.rb
|
|
257
302
|
- lib/portage/cli/notifier.rb
|
|
258
303
|
- lib/portage/cli/offer_choice.rb
|
|
259
304
|
- lib/portage/cli/offer_sources.rb
|
|
305
|
+
- lib/portage/cli/order_history.rb
|
|
260
306
|
- lib/portage/cli/payment_methods.rb
|
|
261
307
|
- lib/portage/cli/payment_methods/env_backend.rb
|
|
262
308
|
- lib/portage/cli/payment_methods/keychain_backend.rb
|