codex-flow 2.1.13__py3-none-any.whl
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.
- codex_flow/__init__.py +28 -0
- codex_flow/__main__.py +9 -0
- codex_flow/cli.py +242 -0
- codex_flow/data/LICENSE +21 -0
- codex_flow/data/README.en.md +303 -0
- codex_flow/data/README.md +305 -0
- codex_flow/data/VERSION +1 -0
- codex_flow/data/apps/chatgpt-mcp/README.md +86 -0
- codex_flow/data/apps/chatgpt-mcp/__init__.py +1 -0
- codex_flow/data/apps/chatgpt-mcp/adapter.py +458 -0
- codex_flow/data/apps/chatgpt-mcp/server.py +358 -0
- codex_flow/data/apps/chatgpt-mcp/widget.html +927 -0
- codex_flow/data/apps/macos-overlay/README.en.md +121 -0
- codex_flow/data/apps/macos-overlay/README.md +123 -0
- codex_flow/data/apps/macos-overlay/Sources/Controllers/OverlayRuntimeState.swift +126 -0
- codex_flow/data/apps/macos-overlay/Sources/Controllers/OverlayScreenGeometry.swift +82 -0
- codex_flow/data/apps/macos-overlay/Sources/Controllers/OverlayWindowController.swift +1052 -0
- codex_flow/data/apps/macos-overlay/Sources/Localization.swift +197 -0
- codex_flow/data/apps/macos-overlay/Sources/Models/TelemetryData.swift +1557 -0
- codex_flow/data/apps/macos-overlay/Sources/Services/AccountSnapshotService.swift +1101 -0
- codex_flow/data/apps/macos-overlay/Sources/Services/FlowPilotInstanceLock.swift +153 -0
- codex_flow/data/apps/macos-overlay/Sources/Services/IPCServer.swift +298 -0
- codex_flow/data/apps/macos-overlay/Sources/Services/TelemetryQueryEngine.swift +800 -0
- codex_flow/data/apps/macos-overlay/Sources/Services/TelemetryWatcher.swift +135 -0
- codex_flow/data/apps/macos-overlay/Sources/Services/UpdateService.swift +610 -0
- codex_flow/data/apps/macos-overlay/Sources/Views/AccountView.swift +610 -0
- codex_flow/data/apps/macos-overlay/Sources/Views/AnalyticsView.swift +566 -0
- codex_flow/data/apps/macos-overlay/Sources/Views/AutostartView.swift +293 -0
- codex_flow/data/apps/macos-overlay/Sources/Views/BubbleView.swift +317 -0
- codex_flow/data/apps/macos-overlay/Sources/Views/HistoryView.swift +1124 -0
- codex_flow/data/apps/macos-overlay/Sources/Views/HoverRevealText.swift +165 -0
- codex_flow/data/apps/macos-overlay/Sources/Views/InspectorSkillsToolsView.swift +121 -0
- codex_flow/data/apps/macos-overlay/Sources/Views/LogoView.swift +182 -0
- codex_flow/data/apps/macos-overlay/Sources/Views/SleekSwitch.swift +117 -0
- codex_flow/data/apps/macos-overlay/Sources/Views/StrategyModeView.swift +561 -0
- codex_flow/data/apps/macos-overlay/Sources/Views/SummaryView.swift +1273 -0
- codex_flow/data/apps/macos-overlay/Sources/Views/UpdateView.swift +352 -0
- codex_flow/data/apps/macos-overlay/Sources/main.swift +340 -0
- codex_flow/data/apps/macos-overlay/Tests/OverlayScreenGeometryTests.swift +163 -0
- codex_flow/data/apps/macos-overlay/Tests/TelemetryPhase1ContractTests.swift +357 -0
- codex_flow/data/apps/macos-overlay/Tests/TelemetryQueryEngineConcurrencyTests.swift +221 -0
- codex_flow/data/apps/macos-overlay/Tests/TelemetryQuotaSelectionTests.swift +158 -0
- codex_flow/data/apps/macos-overlay/Tests/TelemetryWorkerTokenTests.swift +122 -0
- codex_flow/data/apps/macos-overlay/build.sh +75 -0
- codex_flow/data/benchmark/corpus.json +103 -0
- codex_flow/data/benchmark/manifest.example.json +41 -0
- codex_flow/data/benchmark/manifest.schema.json +137 -0
- codex_flow/data/benchmark/prices/gpt-5.6-2026-08-30.json +5 -0
- codex_flow/data/benchmark/profiles.json +90 -0
- codex_flow/data/benchmark/schema.json +77 -0
- codex_flow/data/benchmark/tasks.json +50 -0
- codex_flow/data/completions/codex-flow.bash +34 -0
- codex_flow/data/completions/codex-flow.zsh +52 -0
- codex_flow/data/glama.json +6 -0
- codex_flow/data/install-release.ps1 +126 -0
- codex_flow/data/install-release.sh +155 -0
- codex_flow/data/install.ps1 +349 -0
- codex_flow/data/install.sh +362 -0
- codex_flow/data/policy/benchmark.toml +49 -0
- codex_flow/data/policy/defaults.toml +70 -0
- codex_flow/data/scripts/analyze-benchmark.py +510 -0
- codex_flow/data/scripts/benchmark-local.py +171 -0
- codex_flow/data/scripts/check-recommendation.py +277 -0
- codex_flow/data/scripts/doctor.py +449 -0
- codex_flow/data/scripts/generate-release-manifest.py +74 -0
- codex_flow/data/scripts/localization.py +192 -0
- codex_flow/data/scripts/manage-hooks.py +448 -0
- codex_flow/data/scripts/manage-instructions.py +389 -0
- codex_flow/data/scripts/manage-shell.py +151 -0
- codex_flow/data/scripts/materialize-corpus.py +193 -0
- codex_flow/data/scripts/menu.py +646 -0
- codex_flow/data/scripts/migrations/0001_update_settings.py +80 -0
- codex_flow/data/scripts/package-release.py +132 -0
- codex_flow/data/scripts/render-benchmark-report.py +292 -0
- codex_flow/data/scripts/run-benchmark.py +829 -0
- codex_flow/data/scripts/strategies/__init__.py +28 -0
- codex_flow/data/scripts/strategies/balanced.py +115 -0
- codex_flow/data/scripts/strategies/base.py +363 -0
- codex_flow/data/scripts/strategies/efficient.py +158 -0
- codex_flow/data/scripts/strategies/lifecycle_runtime.py +590 -0
- codex_flow/data/scripts/strategies/quality.py +209 -0
- codex_flow/data/scripts/strategies/speed.py +108 -0
- codex_flow/data/scripts/strategies/task_budget_runtime.py +644 -0
- codex_flow/data/scripts/strategies/task_phase_runtime.py +341 -0
- codex_flow/data/scripts/strategies/work_unit_runtime.py +421 -0
- codex_flow/data/scripts/strategy_runtime.py +1091 -0
- codex_flow/data/scripts/telemetry.py +400 -0
- codex_flow/data/scripts/telemetry_core/__init__.py +192 -0
- codex_flow/data/scripts/telemetry_core/app_server.py +1192 -0
- codex_flow/data/scripts/telemetry_core/collector.py +1247 -0
- codex_flow/data/scripts/telemetry_core/common.py +421 -0
- codex_flow/data/scripts/telemetry_core/latency.py +593 -0
- codex_flow/data/scripts/telemetry_core/query.py +427 -0
- codex_flow/data/scripts/telemetry_core/quota_ledger.py +598 -0
- codex_flow/data/scripts/telemetry_core/render.py +460 -0
- codex_flow/data/scripts/telemetry_core/repair.py +223 -0
- codex_flow/data/scripts/ui.py +266 -0
- codex_flow/data/scripts/update-homebrew-formula.py +146 -0
- codex_flow/data/scripts/update_runtime_config.py +134 -0
- codex_flow/data/scripts/updater.py +1718 -0
- codex_flow/data/smithery.yaml +18 -0
- codex_flow/data/templates/agents/worker-explorer.toml +24 -0
- codex_flow/data/templates/agents/worker-implementer.toml +49 -0
- codex_flow/data/templates/agents/worker-reviewer.toml +25 -0
- codex_flow/data/templates/flow-pilot-instructions.md +35 -0
- codex_flow/data/templates/skills/flow-pilot/SKILL.md +577 -0
- codex_flow/mcp.py +35 -0
- codex_flow-2.1.13.dist-info/METADATA +342 -0
- codex_flow-2.1.13.dist-info/RECORD +113 -0
- codex_flow-2.1.13.dist-info/WHEEL +5 -0
- codex_flow-2.1.13.dist-info/entry_points.txt +3 -0
- codex_flow-2.1.13.dist-info/licenses/LICENSE +21 -0
- codex_flow-2.1.13.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Combine
|
|
3
|
+
|
|
4
|
+
public enum AppLanguage: String {
|
|
5
|
+
case zh
|
|
6
|
+
case en
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
public final class AppLocalization: ObservableObject {
|
|
10
|
+
public static let shared = AppLocalization()
|
|
11
|
+
|
|
12
|
+
@Published public private(set) var language: AppLanguage
|
|
13
|
+
private var refreshTimer: Timer?
|
|
14
|
+
|
|
15
|
+
private init() {
|
|
16
|
+
language = Self.resolveLanguage()
|
|
17
|
+
refreshTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
|
|
18
|
+
guard let self = self else { return }
|
|
19
|
+
let resolved = Self.resolveLanguage()
|
|
20
|
+
if resolved != self.language {
|
|
21
|
+
self.language = resolved
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
deinit {
|
|
27
|
+
refreshTimer?.invalidate()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public func text(_ english: String, _ chinese: String) -> String {
|
|
31
|
+
language == .zh ? chinese : english
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public static func resolveLanguage() -> AppLanguage {
|
|
35
|
+
let env = ProcessInfo.processInfo.environment
|
|
36
|
+
if let rawOverride = env["CODEX_FLOW_LANGUAGE"], !rawOverride.isEmpty {
|
|
37
|
+
return resolve(normalize(rawOverride) ?? "auto")
|
|
38
|
+
}
|
|
39
|
+
return resolve(configuredLanguage())
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public static func configuredLanguage() -> String {
|
|
43
|
+
let env = ProcessInfo.processInfo.environment
|
|
44
|
+
let home = FileManager.default.homeDirectoryForCurrentUser
|
|
45
|
+
let codexHome = env["CODEX_HOME"] ?? home.appendingPathComponent(".codex").path
|
|
46
|
+
let policy = URL(fileURLWithPath: codexHome).appendingPathComponent("codex-flow.toml")
|
|
47
|
+
guard let text = try? String(contentsOf: policy, encoding: .utf8) else { return "auto" }
|
|
48
|
+
|
|
49
|
+
var inUI = false
|
|
50
|
+
for rawLine in text.components(separatedBy: .newlines) {
|
|
51
|
+
let line = rawLine.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
52
|
+
if line.hasPrefix("[") && line.hasSuffix("]") {
|
|
53
|
+
inUI = line == "[ui]"
|
|
54
|
+
continue
|
|
55
|
+
}
|
|
56
|
+
guard inUI else { continue }
|
|
57
|
+
let noComment = line.split(separator: "#", maxSplits: 1, omittingEmptySubsequences: false)[0]
|
|
58
|
+
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
59
|
+
guard let eq = noComment.firstIndex(of: "=") else { continue }
|
|
60
|
+
let key = noComment[..<eq].trimmingCharacters(in: .whitespacesAndNewlines)
|
|
61
|
+
guard key == "language" else { continue }
|
|
62
|
+
let rawValue = noComment[noComment.index(after: eq)...]
|
|
63
|
+
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
64
|
+
.trimmingCharacters(in: CharacterSet(charactersIn: "\"'"))
|
|
65
|
+
return normalize(rawValue) ?? "auto"
|
|
66
|
+
}
|
|
67
|
+
return "auto"
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public static func systemLanguage() -> AppLanguage {
|
|
71
|
+
for candidate in Locale.preferredLanguages {
|
|
72
|
+
if let normalized = normalize(candidate), normalized != "auto" {
|
|
73
|
+
return normalized == "zh" ? .zh : .en
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let env = ProcessInfo.processInfo.environment
|
|
78
|
+
for key in ["LC_ALL", "LC_MESSAGES", "LANGUAGE", "LANG"] {
|
|
79
|
+
if let normalized = normalize(env[key]), normalized != "auto" {
|
|
80
|
+
return normalized == "zh" ? .zh : .en
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return .en
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private static func resolve(_ normalized: String) -> AppLanguage {
|
|
87
|
+
switch normalized {
|
|
88
|
+
case "zh": return .zh
|
|
89
|
+
case "en": return .en
|
|
90
|
+
default: return systemLanguage()
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private static func normalize(_ raw: String?) -> String? {
|
|
95
|
+
let value = (raw ?? "")
|
|
96
|
+
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
97
|
+
.lowercased()
|
|
98
|
+
.replacingOccurrences(of: "_", with: "-")
|
|
99
|
+
if value.isEmpty || ["auto", "system", "default"].contains(value) { return "auto" }
|
|
100
|
+
if value == "zh" || value.hasPrefix("zh-") || value.hasPrefix("chinese") { return "zh" }
|
|
101
|
+
if value == "en" || value.hasPrefix("en-") || value.hasPrefix("english") { return "en" }
|
|
102
|
+
return nil
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private enum FlowPilotDateFormatters {
|
|
107
|
+
static let lock = NSLock()
|
|
108
|
+
static let clock = make("HH:mm")
|
|
109
|
+
static let dateTime = make("MM-dd HH:mm")
|
|
110
|
+
static let fullDateTime = make("yyyy-MM-dd HH:mm")
|
|
111
|
+
|
|
112
|
+
private static func make(_ format: String) -> DateFormatter {
|
|
113
|
+
let formatter = DateFormatter()
|
|
114
|
+
formatter.dateFormat = format
|
|
115
|
+
return formatter
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
static func string(from date: Date, format: DateFormatter) -> String {
|
|
119
|
+
lock.lock()
|
|
120
|
+
defer { lock.unlock() }
|
|
121
|
+
// Locale and time zone can change while a long-running menu-bar app is
|
|
122
|
+
// alive, so refresh those lightweight properties while reusing the
|
|
123
|
+
// expensive formatter instances themselves.
|
|
124
|
+
format.locale = Locale.current
|
|
125
|
+
format.timeZone = TimeZone.current
|
|
126
|
+
return format.string(from: date)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@inline(__always)
|
|
131
|
+
public func L(_ english: String, _ chinese: String) -> String {
|
|
132
|
+
AppLocalization.shared.text(english, chinese)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/// User-facing local date/time with a calendar date. Same-year timestamps stay
|
|
136
|
+
/// compact; cross-year timestamps include the year to avoid ambiguity.
|
|
137
|
+
public func formatLocalDateTime(_ date: Date) -> String {
|
|
138
|
+
let currentYear = Calendar.current.component(.year, from: Date())
|
|
139
|
+
let targetYear = Calendar.current.component(.year, from: date)
|
|
140
|
+
let formatter = currentYear == targetYear
|
|
141
|
+
? FlowPilotDateFormatters.dateTime
|
|
142
|
+
: FlowPilotDateFormatters.fullDateTime
|
|
143
|
+
return FlowPilotDateFormatters.string(from: date, format: formatter)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
public func localizedRole(_ role: String) -> String {
|
|
147
|
+
switch role.lowercased() {
|
|
148
|
+
case "parent": return L("parent", "父 Agent")
|
|
149
|
+
case "worker", "subagent": return L("worker", "Worker")
|
|
150
|
+
default: return role
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
public extension OverlayTab {
|
|
155
|
+
var localizedTitle: String {
|
|
156
|
+
switch self {
|
|
157
|
+
case .inspector: return L("Inspector", "任务")
|
|
158
|
+
case .history: return L("History", "历史")
|
|
159
|
+
case .analytics: return L("Analytics", "统计")
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
public extension QuotaWindow {
|
|
165
|
+
/// User-facing reset time deliberately includes a calendar date. A bare
|
|
166
|
+
/// clock time is ambiguous for weekly windows and was especially confusing
|
|
167
|
+
/// around midnight/year boundaries.
|
|
168
|
+
var localizedFormattedResetsAt: String? {
|
|
169
|
+
guard let r = resetsAt, r > 0 else { return nil }
|
|
170
|
+
let date = Date(timeIntervalSince1970: r > 1_000_000_000_000 ? r / 1000.0 : r)
|
|
171
|
+
if date <= Date() {
|
|
172
|
+
return L("resets now", "立即重置")
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
let value = formatLocalDateTime(date)
|
|
176
|
+
return L("resets \(value)", "\(value) 重置")
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
public extension TaskRun {
|
|
181
|
+
var localizedFormattedDate: String {
|
|
182
|
+
guard let s = startedAtMs else { return "--:--" }
|
|
183
|
+
let date = Date(timeIntervalSince1970: s / 1000.0)
|
|
184
|
+
if Calendar.current.isDateInToday(date) {
|
|
185
|
+
let value = FlowPilotDateFormatters.string(from: date, format: FlowPilotDateFormatters.clock)
|
|
186
|
+
return L("Today \(value)", "今天 \(value)")
|
|
187
|
+
}
|
|
188
|
+
return FlowPilotDateFormatters.string(from: date, format: FlowPilotDateFormatters.dateTime)
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
public extension ChatSession {
|
|
193
|
+
var localizedRunsSummary: String {
|
|
194
|
+
let count = runs.count
|
|
195
|
+
return count == 1 ? L("1 session", "1 次会话") : L("\(count) sessions", "\(count) 轮会话")
|
|
196
|
+
}
|
|
197
|
+
}
|