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.
Files changed (113) hide show
  1. codex_flow/__init__.py +28 -0
  2. codex_flow/__main__.py +9 -0
  3. codex_flow/cli.py +242 -0
  4. codex_flow/data/LICENSE +21 -0
  5. codex_flow/data/README.en.md +303 -0
  6. codex_flow/data/README.md +305 -0
  7. codex_flow/data/VERSION +1 -0
  8. codex_flow/data/apps/chatgpt-mcp/README.md +86 -0
  9. codex_flow/data/apps/chatgpt-mcp/__init__.py +1 -0
  10. codex_flow/data/apps/chatgpt-mcp/adapter.py +458 -0
  11. codex_flow/data/apps/chatgpt-mcp/server.py +358 -0
  12. codex_flow/data/apps/chatgpt-mcp/widget.html +927 -0
  13. codex_flow/data/apps/macos-overlay/README.en.md +121 -0
  14. codex_flow/data/apps/macos-overlay/README.md +123 -0
  15. codex_flow/data/apps/macos-overlay/Sources/Controllers/OverlayRuntimeState.swift +126 -0
  16. codex_flow/data/apps/macos-overlay/Sources/Controllers/OverlayScreenGeometry.swift +82 -0
  17. codex_flow/data/apps/macos-overlay/Sources/Controllers/OverlayWindowController.swift +1052 -0
  18. codex_flow/data/apps/macos-overlay/Sources/Localization.swift +197 -0
  19. codex_flow/data/apps/macos-overlay/Sources/Models/TelemetryData.swift +1557 -0
  20. codex_flow/data/apps/macos-overlay/Sources/Services/AccountSnapshotService.swift +1101 -0
  21. codex_flow/data/apps/macos-overlay/Sources/Services/FlowPilotInstanceLock.swift +153 -0
  22. codex_flow/data/apps/macos-overlay/Sources/Services/IPCServer.swift +298 -0
  23. codex_flow/data/apps/macos-overlay/Sources/Services/TelemetryQueryEngine.swift +800 -0
  24. codex_flow/data/apps/macos-overlay/Sources/Services/TelemetryWatcher.swift +135 -0
  25. codex_flow/data/apps/macos-overlay/Sources/Services/UpdateService.swift +610 -0
  26. codex_flow/data/apps/macos-overlay/Sources/Views/AccountView.swift +610 -0
  27. codex_flow/data/apps/macos-overlay/Sources/Views/AnalyticsView.swift +566 -0
  28. codex_flow/data/apps/macos-overlay/Sources/Views/AutostartView.swift +293 -0
  29. codex_flow/data/apps/macos-overlay/Sources/Views/BubbleView.swift +317 -0
  30. codex_flow/data/apps/macos-overlay/Sources/Views/HistoryView.swift +1124 -0
  31. codex_flow/data/apps/macos-overlay/Sources/Views/HoverRevealText.swift +165 -0
  32. codex_flow/data/apps/macos-overlay/Sources/Views/InspectorSkillsToolsView.swift +121 -0
  33. codex_flow/data/apps/macos-overlay/Sources/Views/LogoView.swift +182 -0
  34. codex_flow/data/apps/macos-overlay/Sources/Views/SleekSwitch.swift +117 -0
  35. codex_flow/data/apps/macos-overlay/Sources/Views/StrategyModeView.swift +561 -0
  36. codex_flow/data/apps/macos-overlay/Sources/Views/SummaryView.swift +1273 -0
  37. codex_flow/data/apps/macos-overlay/Sources/Views/UpdateView.swift +352 -0
  38. codex_flow/data/apps/macos-overlay/Sources/main.swift +340 -0
  39. codex_flow/data/apps/macos-overlay/Tests/OverlayScreenGeometryTests.swift +163 -0
  40. codex_flow/data/apps/macos-overlay/Tests/TelemetryPhase1ContractTests.swift +357 -0
  41. codex_flow/data/apps/macos-overlay/Tests/TelemetryQueryEngineConcurrencyTests.swift +221 -0
  42. codex_flow/data/apps/macos-overlay/Tests/TelemetryQuotaSelectionTests.swift +158 -0
  43. codex_flow/data/apps/macos-overlay/Tests/TelemetryWorkerTokenTests.swift +122 -0
  44. codex_flow/data/apps/macos-overlay/build.sh +75 -0
  45. codex_flow/data/benchmark/corpus.json +103 -0
  46. codex_flow/data/benchmark/manifest.example.json +41 -0
  47. codex_flow/data/benchmark/manifest.schema.json +137 -0
  48. codex_flow/data/benchmark/prices/gpt-5.6-2026-08-30.json +5 -0
  49. codex_flow/data/benchmark/profiles.json +90 -0
  50. codex_flow/data/benchmark/schema.json +77 -0
  51. codex_flow/data/benchmark/tasks.json +50 -0
  52. codex_flow/data/completions/codex-flow.bash +34 -0
  53. codex_flow/data/completions/codex-flow.zsh +52 -0
  54. codex_flow/data/glama.json +6 -0
  55. codex_flow/data/install-release.ps1 +126 -0
  56. codex_flow/data/install-release.sh +155 -0
  57. codex_flow/data/install.ps1 +349 -0
  58. codex_flow/data/install.sh +362 -0
  59. codex_flow/data/policy/benchmark.toml +49 -0
  60. codex_flow/data/policy/defaults.toml +70 -0
  61. codex_flow/data/scripts/analyze-benchmark.py +510 -0
  62. codex_flow/data/scripts/benchmark-local.py +171 -0
  63. codex_flow/data/scripts/check-recommendation.py +277 -0
  64. codex_flow/data/scripts/doctor.py +449 -0
  65. codex_flow/data/scripts/generate-release-manifest.py +74 -0
  66. codex_flow/data/scripts/localization.py +192 -0
  67. codex_flow/data/scripts/manage-hooks.py +448 -0
  68. codex_flow/data/scripts/manage-instructions.py +389 -0
  69. codex_flow/data/scripts/manage-shell.py +151 -0
  70. codex_flow/data/scripts/materialize-corpus.py +193 -0
  71. codex_flow/data/scripts/menu.py +646 -0
  72. codex_flow/data/scripts/migrations/0001_update_settings.py +80 -0
  73. codex_flow/data/scripts/package-release.py +132 -0
  74. codex_flow/data/scripts/render-benchmark-report.py +292 -0
  75. codex_flow/data/scripts/run-benchmark.py +829 -0
  76. codex_flow/data/scripts/strategies/__init__.py +28 -0
  77. codex_flow/data/scripts/strategies/balanced.py +115 -0
  78. codex_flow/data/scripts/strategies/base.py +363 -0
  79. codex_flow/data/scripts/strategies/efficient.py +158 -0
  80. codex_flow/data/scripts/strategies/lifecycle_runtime.py +590 -0
  81. codex_flow/data/scripts/strategies/quality.py +209 -0
  82. codex_flow/data/scripts/strategies/speed.py +108 -0
  83. codex_flow/data/scripts/strategies/task_budget_runtime.py +644 -0
  84. codex_flow/data/scripts/strategies/task_phase_runtime.py +341 -0
  85. codex_flow/data/scripts/strategies/work_unit_runtime.py +421 -0
  86. codex_flow/data/scripts/strategy_runtime.py +1091 -0
  87. codex_flow/data/scripts/telemetry.py +400 -0
  88. codex_flow/data/scripts/telemetry_core/__init__.py +192 -0
  89. codex_flow/data/scripts/telemetry_core/app_server.py +1192 -0
  90. codex_flow/data/scripts/telemetry_core/collector.py +1247 -0
  91. codex_flow/data/scripts/telemetry_core/common.py +421 -0
  92. codex_flow/data/scripts/telemetry_core/latency.py +593 -0
  93. codex_flow/data/scripts/telemetry_core/query.py +427 -0
  94. codex_flow/data/scripts/telemetry_core/quota_ledger.py +598 -0
  95. codex_flow/data/scripts/telemetry_core/render.py +460 -0
  96. codex_flow/data/scripts/telemetry_core/repair.py +223 -0
  97. codex_flow/data/scripts/ui.py +266 -0
  98. codex_flow/data/scripts/update-homebrew-formula.py +146 -0
  99. codex_flow/data/scripts/update_runtime_config.py +134 -0
  100. codex_flow/data/scripts/updater.py +1718 -0
  101. codex_flow/data/smithery.yaml +18 -0
  102. codex_flow/data/templates/agents/worker-explorer.toml +24 -0
  103. codex_flow/data/templates/agents/worker-implementer.toml +49 -0
  104. codex_flow/data/templates/agents/worker-reviewer.toml +25 -0
  105. codex_flow/data/templates/flow-pilot-instructions.md +35 -0
  106. codex_flow/data/templates/skills/flow-pilot/SKILL.md +577 -0
  107. codex_flow/mcp.py +35 -0
  108. codex_flow-2.1.13.dist-info/METADATA +342 -0
  109. codex_flow-2.1.13.dist-info/RECORD +113 -0
  110. codex_flow-2.1.13.dist-info/WHEEL +5 -0
  111. codex_flow-2.1.13.dist-info/entry_points.txt +3 -0
  112. codex_flow-2.1.13.dist-info/licenses/LICENSE +21 -0
  113. codex_flow-2.1.13.dist-info/top_level.txt +1 -0
@@ -0,0 +1,193 @@
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import json
6
+ import os
7
+ import shutil
8
+ import subprocess
9
+ from pathlib import Path, PurePosixPath
10
+
11
+ FIXED_DATE = "2026-01-01T00:00:00+00:00"
12
+ VALID_CLASSES = {"routine", "complex", "critical"}
13
+ VALID_EFFORTS = {"high", "xhigh", "max"}
14
+ VALID_STRATEGIES = {"direct", "flow", "runtime"}
15
+
16
+
17
+ def load_json(path: Path):
18
+ return json.loads(path.read_text())
19
+
20
+
21
+ def validate_relative_path(value: str) -> None:
22
+ p = PurePosixPath(value)
23
+ if not value or p.is_absolute() or ".." in p.parts or value.endswith("/"):
24
+ raise ValueError(f"unsafe corpus file path: {value!r}")
25
+
26
+
27
+ def validate(corpus: dict, profiles: dict, profile_name: str) -> dict:
28
+ if corpus.get("schema_version") not in {1, 2} or profiles.get("schema_version") != 2:
29
+ raise ValueError("unsupported corpus/profile schema")
30
+ tasks = corpus.get("tasks")
31
+ if not isinstance(tasks, list) or not tasks:
32
+ raise ValueError("corpus tasks must be a non-empty array")
33
+ seen: set[str] = set()
34
+ for task in tasks:
35
+ task_id = task.get("id")
36
+ if not isinstance(task_id, str) or not task_id:
37
+ raise ValueError("task id must be a non-empty string")
38
+ if task_id in seen:
39
+ raise ValueError(f"duplicate task id: {task_id}")
40
+ seen.add(task_id)
41
+ if task.get("class") not in VALID_CLASSES:
42
+ raise ValueError(f"invalid task class for {task_id}: {task.get('class')}")
43
+ if not isinstance(task.get("prompt"), str) or not task["prompt"].strip():
44
+ raise ValueError(f"empty prompt for {task_id}")
45
+ if not isinstance(task.get("verifier"), str) or not task["verifier"].strip():
46
+ raise ValueError(f"empty verifier for {task_id}")
47
+ files = task.get("files")
48
+ if not isinstance(files, dict) or not files:
49
+ raise ValueError(f"task {task_id} must contain seed files")
50
+ for rel, content in files.items():
51
+ if not isinstance(rel, str) or not isinstance(content, str):
52
+ raise ValueError(f"task {task_id} files must map string paths to string contents")
53
+ validate_relative_path(rel)
54
+
55
+ profile = profiles.get("profiles", {}).get(profile_name)
56
+ if not isinstance(profile, dict):
57
+ raise ValueError(f"missing profile: {profile_name}")
58
+ repetitions = profile.get("repetitions")
59
+ matrix = profile.get("matrix")
60
+ if not isinstance(repetitions, int) or repetitions < 1:
61
+ raise ValueError(f"profile {profile_name} repetitions must be >= 1")
62
+ if not isinstance(matrix, list) or not matrix:
63
+ raise ValueError(f"profile {profile_name} matrix must be non-empty")
64
+ seen_configs: set[str] = set()
65
+ controlled_efforts: set[str] = set()
66
+ for config in matrix:
67
+ strategy_id = config.get("id")
68
+ strategy = config.get("strategy")
69
+ if not isinstance(strategy_id, str) or not strategy_id:
70
+ raise ValueError(f"profile {profile_name} contains an empty strategy id")
71
+ if strategy_id in seen_configs:
72
+ raise ValueError(f"profile {profile_name} has duplicate strategy id: {strategy_id}")
73
+ seen_configs.add(strategy_id)
74
+ if strategy not in VALID_STRATEGIES:
75
+ raise ValueError(f"profile {profile_name} has invalid strategy: {strategy}")
76
+ reasoning_policy = config.get("reasoning_policy", "fixed")
77
+ if reasoning_policy not in {"fixed", "adaptive"}:
78
+ raise ValueError(f"profile {profile_name} strategy {strategy_id} has invalid reasoning policy")
79
+ if strategy == "direct" and reasoning_policy != "fixed":
80
+ raise ValueError(f"profile {profile_name} direct strategy {strategy_id} must use fixed reasoning")
81
+ actors = [config] if strategy == "direct" else [config.get("parent"), config.get("worker")]
82
+ for actor in actors:
83
+ if not isinstance(actor, dict) or not isinstance(actor.get("model"), str) or not actor["model"]:
84
+ raise ValueError(f"profile {profile_name} strategy {strategy_id} contains an empty model")
85
+ effort = actor.get("reasoning_effort")
86
+ if reasoning_policy == "fixed":
87
+ if effort not in VALID_EFFORTS:
88
+ raise ValueError(f"profile {profile_name} strategy {strategy_id} has invalid fixed reasoning effort: {effort}")
89
+ controlled_efforts.add(effort)
90
+ else:
91
+ if not isinstance(effort, dict) or set(effort) != VALID_CLASSES:
92
+ raise ValueError(f"profile {profile_name} adaptive strategy {strategy_id} must define per-class reasoning")
93
+ if any(value not in VALID_EFFORTS for value in effort.values()):
94
+ raise ValueError(f"profile {profile_name} strategy {strategy_id} has invalid adaptive reasoning effort")
95
+ if len(controlled_efforts) != 1:
96
+ raise ValueError(
97
+ f"profile {profile_name} must use one controlled reasoning effort across direct strategies and fixed flow"
98
+ )
99
+ return profile
100
+
101
+
102
+ def write_files(root: Path, files: dict[str, str]) -> None:
103
+ for rel, content in files.items():
104
+ target = root / rel
105
+ target.parent.mkdir(parents=True, exist_ok=True)
106
+ target.write_text(content)
107
+
108
+
109
+ def init_repo(repo: Path) -> str:
110
+ subprocess.run(["git", "init", "-q", str(repo)], check=True)
111
+ subprocess.run(["git", "-C", str(repo), "config", "user.name", "codex-flow benchmark"], check=True)
112
+ subprocess.run(["git", "-C", str(repo), "config", "user.email", "benchmark@codex-flow.invalid"], check=True)
113
+ subprocess.run(["git", "-C", str(repo), "add", "."], check=True)
114
+ env = os.environ.copy()
115
+ env.update({"GIT_AUTHOR_DATE": FIXED_DATE, "GIT_COMMITTER_DATE": FIXED_DATE})
116
+ subprocess.run(["git", "-C", str(repo), "commit", "-qm", "benchmark seed"], check=True, env=env)
117
+ return subprocess.check_output(["git", "-C", str(repo), "rev-parse", "HEAD"], text=True).strip()
118
+
119
+
120
+ def main() -> int:
121
+ ap = argparse.ArgumentParser()
122
+ ap.add_argument("--corpus", default="benchmark/corpus.json")
123
+ ap.add_argument("--profiles", default="benchmark/profiles.json")
124
+ ap.add_argument("--profile", choices=["quick", "full", "agentic"], default="quick")
125
+ ap.add_argument("--output-dir", required=True)
126
+ ap.add_argument("--manifest", required=True)
127
+ ap.add_argument("--timeout-seconds", type=int, default=900)
128
+ ap.add_argument("--max-repair-cycles", type=int, default=2)
129
+ args = ap.parse_args()
130
+ if args.timeout_seconds < 1:
131
+ raise ValueError("timeout-seconds must be >= 1")
132
+ if args.max_repair_cycles < 0:
133
+ raise ValueError("max-repair-cycles must be >= 0")
134
+
135
+ corpus = load_json(Path(args.corpus))
136
+ profiles = load_json(Path(args.profiles))
137
+ profile = validate(corpus, profiles, args.profile)
138
+
139
+ out = Path(args.output_dir).resolve()
140
+ if out.exists():
141
+ shutil.rmtree(out)
142
+ out.mkdir(parents=True)
143
+
144
+ manifest_tasks = []
145
+ for task in corpus["tasks"]:
146
+ task_root = out / task["id"]
147
+ repo = task_root / "repo"
148
+ verifier = task_root / "verify.py"
149
+ repo.mkdir(parents=True)
150
+ write_files(repo, task["files"])
151
+ verifier.write_text(task["verifier"])
152
+ commit = init_repo(repo)
153
+ manifest_tasks.append({
154
+ "id": task["id"],
155
+ "class": task["class"],
156
+ "source": str(repo),
157
+ "base_ref": commit,
158
+ "prompt": task["prompt"],
159
+ "verify": ["python3", str(verifier)],
160
+ })
161
+
162
+ manifest = {
163
+ "schema_version": 2,
164
+ "repetitions": profile["repetitions"],
165
+ "timeout_seconds": args.timeout_seconds,
166
+ "max_repair_cycles": args.max_repair_cycles,
167
+ "matrix": profile["matrix"],
168
+ "tasks": manifest_tasks,
169
+ }
170
+ manifest_path = Path(args.manifest).resolve()
171
+ manifest_path.parent.mkdir(parents=True, exist_ok=True)
172
+ manifest_path.write_text(json.dumps(manifest, indent=2) + "\n")
173
+ runs = len(manifest_tasks) * len(profile["matrix"]) * profile["repetitions"]
174
+ print(json.dumps({
175
+ "profile": args.profile,
176
+ "tasks": len(manifest_tasks),
177
+ "configurations": len(profile["matrix"]),
178
+ "strategies": [config["id"] for config in profile["matrix"]],
179
+ "controlled_reasoning_effort": next(iter({
180
+ actor["reasoning_effort"]
181
+ for config in profile["matrix"]
182
+ if config.get("reasoning_policy", "fixed") == "fixed"
183
+ for actor in ([config] if config["strategy"] == "direct" else [config["parent"], config["worker"]])
184
+ })),
185
+ "repetitions": profile["repetitions"],
186
+ "planned_runs": runs,
187
+ "manifest": str(manifest_path),
188
+ }, sort_keys=True))
189
+ return 0
190
+
191
+
192
+ if __name__ == "__main__":
193
+ raise SystemExit(main())