vidbyte-cli 0.1.0__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.
- vidbyte_cli/__init__.py +11 -0
- vidbyte_cli/__main__.py +6 -0
- vidbyte_cli/cli.py +18 -0
- vidbyte_cli/commands/__init__.py +86 -0
- vidbyte_cli/commands/agent_options.py +53 -0
- vidbyte_cli/commands/agents/__init__.py +31 -0
- vidbyte_cli/commands/agents/suggestion/__init__.py +38 -0
- vidbyte_cli/commands/agents/suggestion/prompts/__init__.py +3 -0
- vidbyte_cli/commands/agents/suggestion/prompts/all_categories.md +5 -0
- vidbyte_cli/commands/agents/suggestion/prompts/approaches.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/avoid.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/blockers.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/capability.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/categories.md +5 -0
- vidbyte_cli/commands/agents/suggestion/prompts/category.md +5 -0
- vidbyte_cli/commands/agents/suggestion/prompts/completed.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/constraint.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/context.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/count.md +5 -0
- vidbyte_cli/commands/agents/suggestion/prompts/critic_model.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/decision.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/dry_run.md +5 -0
- vidbyte_cli/commands/agents/suggestion/prompts/extra_compute.md +5 -0
- vidbyte_cli/commands/agents/suggestion/prompts/feedback_accept.md +7 -0
- vidbyte_cli/commands/agents/suggestion/prompts/feedback_group.md +7 -0
- vidbyte_cli/commands/agents/suggestion/prompts/feedback_project.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/feedback_reason.md +98 -0
- vidbyte_cli/commands/agents/suggestion/prompts/feedback_reject.md +7 -0
- vidbyte_cli/commands/agents/suggestion/prompts/feedback_suggestion.md +101 -0
- vidbyte_cli/commands/agents/suggestion/prompts/files.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/forbidden.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/goal.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/handoff.md +7 -0
- vidbyte_cli/commands/agents/suggestion/prompts/horizon.md +5 -0
- vidbyte_cli/commands/agents/suggestion/prompts/hypotheses.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/idea.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/in_progress.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/input.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/library.py +29 -0
- vidbyte_cli/commands/agents/suggestion/prompts/max_messages.md +5 -0
- vidbyte_cli/commands/agents/suggestion/prompts/max_output_tokens.md +5 -0
- vidbyte_cli/commands/agents/suggestion/prompts/max_total_tokens.md +5 -0
- vidbyte_cli/commands/agents/suggestion/prompts/mistakes.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/outcomes.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/project.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/project_create.md +7 -0
- vidbyte_cli/commands/agents/suggestion/prompts/project_description.md +98 -0
- vidbyte_cli/commands/agents/suggestion/prompts/project_group.md +7 -0
- vidbyte_cli/commands/agents/suggestion/prompts/project_key.md +96 -0
- vidbyte_cli/commands/agents/suggestion/prompts/project_list.md +7 -0
- vidbyte_cli/commands/agents/suggestion/prompts/project_title.md +99 -0
- vidbyte_cli/commands/agents/suggestion/prompts/provider.md +5 -0
- vidbyte_cli/commands/agents/suggestion/prompts/question.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/risks.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/rounds.md +5 -0
- vidbyte_cli/commands/agents/suggestion/prompts/run.md +5 -0
- vidbyte_cli/commands/agents/suggestion/prompts/success.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/timeout.md +5 -0
- vidbyte_cli/commands/agents/suggestion/prompts/trajectory.md +100 -0
- vidbyte_cli/commands/agents/suggestion/prompts/view.md +5 -0
- vidbyte_cli/commands/agents/suggestion/prompts/view_all.md +5 -0
- vidbyte_cli/commands/agents/suggestion/render.py +77 -0
- vidbyte_cli/commands/agents/suggestion/request_builder.py +240 -0
- vidbyte_cli/commands/agents/suggestion/suggest.py +154 -0
- vidbyte_cli/commands/agents/suggestion/suggestion_categories.py +77 -0
- vidbyte_cli/commands/agents/suggestion/suggestion_feedback.py +85 -0
- vidbyte_cli/commands/agents/suggestion/suggestion_handoff.py +67 -0
- vidbyte_cli/commands/agents/suggestion/suggestion_projects.py +95 -0
- vidbyte_cli/commands/auth/__init__.py +0 -0
- vidbyte_cli/commands/auth/login.py +100 -0
- vidbyte_cli/commands/auth/logout.py +41 -0
- vidbyte_cli/commands/auth/whoami.py +51 -0
- vidbyte_cli/commands/billing/__init__.py +20 -0
- vidbyte_cli/commands/billing/prompts/__init__.py +1 -0
- vidbyte_cli/commands/billing/prompts/confirm.md +16 -0
- vidbyte_cli/commands/billing/prompts/group.md +13 -0
- vidbyte_cli/commands/billing/prompts/idempotency_key.md +16 -0
- vidbyte_cli/commands/billing/prompts/library.py +18 -0
- vidbyte_cli/commands/billing/prompts/top_up.md +16 -0
- vidbyte_cli/commands/billing/top_up.py +65 -0
- vidbyte_cli/commands/config/__init__.py +0 -0
- vidbyte_cli/commands/config/get.py +45 -0
- vidbyte_cli/commands/config/set.py +39 -0
- vidbyte_cli/commands/provider/__init__.py +9 -0
- vidbyte_cli/commands/provider/login.py +102 -0
- vidbyte_cli/commands/provider/logout.py +45 -0
- vidbyte_cli/commands/provider/whoami.py +49 -0
- vidbyte_cli/commands/research/__init__.py +5 -0
- vidbyte_cli/commands/research/add.py +41 -0
- vidbyte_cli/commands/research/options.py +134 -0
- vidbyte_cli/commands/research/render.py +157 -0
- vidbyte_cli/commands/research/resume.py +37 -0
- vidbyte_cli/commands/research/start.py +37 -0
- vidbyte_cli/commands/research/status.py +32 -0
- vidbyte_cli/commands/research/thread.py +30 -0
- vidbyte_cli/commands/research/threads.py +35 -0
- vidbyte_cli/commands/research/watch.py +93 -0
- vidbyte_cli/commands/runtime/__init__.py +23 -0
- vidbyte_cli/commands/runtime/adversarial_team.py +41 -0
- vidbyte_cli/commands/runtime/doctor.py +44 -0
- vidbyte_cli/commands/runtime/list.py +47 -0
- vidbyte_cli/commands/runtime/persistence.py +141 -0
- vidbyte_cli/commands/runtime/same_host_ensemble.py +221 -0
- vidbyte_cli/commands/runtime/stages.py +553 -0
- vidbyte_cli/commands/runtime/task_board.py +1342 -0
- vidbyte_cli/commands/setup/__init__.py +0 -0
- vidbyte_cli/commands/setup/doctor.py +64 -0
- vidbyte_cli/commands/setup/prompts/__init__.py +1 -0
- vidbyte_cli/commands/setup/prompts/browser.md +7 -0
- vidbyte_cli/commands/setup/prompts/library.py +18 -0
- vidbyte_cli/commands/setup/prompts/star.md +13 -0
- vidbyte_cli/commands/setup/star.py +132 -0
- vidbyte_cli/lib/__init__.py +0 -0
- vidbyte_cli/lib/api/__init__.py +0 -0
- vidbyte_cli/lib/api/client.py +236 -0
- vidbyte_cli/lib/api/endpoints/__init__.py +0 -0
- vidbyte_cli/lib/api/endpoints/auth.py +24 -0
- vidbyte_cli/lib/api/endpoints/billing.py +36 -0
- vidbyte_cli/lib/api/endpoints/research.py +103 -0
- vidbyte_cli/lib/api/endpoints/runtime.py +113 -0
- vidbyte_cli/lib/api/problem.py +86 -0
- vidbyte_cli/lib/api/response.py +101 -0
- vidbyte_cli/lib/api/retry.py +116 -0
- vidbyte_cli/lib/api/runtime_payment.py +89 -0
- vidbyte_cli/lib/auth/__init__.py +16 -0
- vidbyte_cli/lib/auth/credentials.py +223 -0
- vidbyte_cli/lib/auth/input.py +59 -0
- vidbyte_cli/lib/auth/keyring_store.py +126 -0
- vidbyte_cli/lib/auth/provider_credentials.py +157 -0
- vidbyte_cli/lib/auth/provider_input.py +54 -0
- vidbyte_cli/lib/auth/provider_resolver.py +89 -0
- vidbyte_cli/lib/auth/provider_store.py +149 -0
- vidbyte_cli/lib/auth/provider_verifier.py +219 -0
- vidbyte_cli/lib/auth/resolver.py +63 -0
- vidbyte_cli/lib/auth/verifier.py +38 -0
- vidbyte_cli/lib/config/__init__.py +25 -0
- vidbyte_cli/lib/config/atomic.py +47 -0
- vidbyte_cli/lib/config/config.py +141 -0
- vidbyte_cli/lib/config/migration.py +81 -0
- vidbyte_cli/lib/config/models.py +145 -0
- vidbyte_cli/lib/config/paths.py +66 -0
- vidbyte_cli/lib/config/resolver.py +137 -0
- vidbyte_cli/lib/constants/__init__.py +1 -0
- vidbyte_cli/lib/constants/runtime.py +186 -0
- vidbyte_cli/lib/errors/__init__.py +12 -0
- vidbyte_cli/lib/errors/cli_error.py +86 -0
- vidbyte_cli/lib/errors/codes.py +43 -0
- vidbyte_cli/lib/errors/failures.py +2910 -0
- vidbyte_cli/lib/errors/handler.py +72 -0
- vidbyte_cli/lib/files/__init__.py +6 -0
- vidbyte_cli/lib/files/documents.py +94 -0
- vidbyte_cli/lib/files/store.py +156 -0
- vidbyte_cli/lib/io/__init__.py +16 -0
- vidbyte_cli/lib/io/attachments.py +129 -0
- vidbyte_cli/lib/io/codex_attachments.py +47 -0
- vidbyte_cli/lib/io/prompt.py +71 -0
- vidbyte_cli/lib/io/streams.py +37 -0
- vidbyte_cli/lib/io/terminal.py +66 -0
- vidbyte_cli/lib/output/__init__.py +7 -0
- vidbyte_cli/lib/output/formats.py +29 -0
- vidbyte_cli/lib/output/manager.py +95 -0
- vidbyte_cli/lib/output/models.py +49 -0
- vidbyte_cli/lib/runtime/__init__.py +9 -0
- vidbyte_cli/lib/runtime/application.py +134 -0
- vidbyte_cli/lib/runtime/context.py +250 -0
- vidbyte_cli/lib/runtime/options.py +159 -0
- vidbyte_cli/lib/runtime/version.py +30 -0
- vidbyte_cli/lib/runtime_primitives/__init__.py +28 -0
- vidbyte_cli/lib/runtime_primitives/executor.py +54 -0
- vidbyte_cli/lib/runtime_primitives/gate.py +105 -0
- vidbyte_cli/lib/runtime_primitives/hosts.py +45 -0
- vidbyte_cli/lib/runtime_primitives/planner.py +79 -0
- vidbyte_cli/lib/runtime_primitives/stages.py +338 -0
- vidbyte_cli/lib/runtime_primitives/task_board.py +982 -0
- vidbyte_cli/lib/runtime_primitives/task_board_checkpoints.py +473 -0
- vidbyte_cli/lib/runtime_primitives/task_board_system.md +33 -0
- vidbyte_cli/lib/runtime_primitives/task_board_tasks.py +111 -0
- vidbyte_cli/lib/runtime_primitives/verification.py +68 -0
- vidbyte_cli/services/__init__.py +5 -0
- vidbyte_cli/services/ensemble/__init__.py +7 -0
- vidbyte_cli/services/ensemble/prompts/__init__.py +6 -0
- vidbyte_cli/services/ensemble/prompts/implementer_system.md +546 -0
- vidbyte_cli/services/ensemble/prompts/implementer_turn.md +49 -0
- vidbyte_cli/services/ensemble/prompts/library.py +188 -0
- vidbyte_cli/services/ensemble/prompts/planner_system.md +728 -0
- vidbyte_cli/services/ensemble/prompts/planner_turn.md +6 -0
- vidbyte_cli/services/ensemble/prompts/role_system.md +104 -0
- vidbyte_cli/services/ensemble/prompts/role_turn.md +19 -0
- vidbyte_cli/services/ensemble/prompts/selector_final_turn.md +19 -0
- vidbyte_cli/services/ensemble/prompts/selector_round_turn.md +17 -0
- vidbyte_cli/services/ensemble/prompts/selector_system.md +89 -0
- vidbyte_cli/services/ensemble/runner.py +30 -0
- vidbyte_cli/services/ensemble/sdk.py +134 -0
- vidbyte_cli/services/ensemble/service.py +233 -0
- vidbyte_cli/services/ensemble/settings.py +60 -0
- vidbyte_cli/services/persistence/__init__.py +6 -0
- vidbyte_cli/services/persistence/prompts/__init__.py +6 -0
- vidbyte_cli/services/persistence/prompts/library.py +46 -0
- vidbyte_cli/services/persistence/prompts/persistence_system.md +1 -0
- vidbyte_cli/services/persistence/prompts/persistence_turn.md +3 -0
- vidbyte_cli/services/persistence/runner.py +35 -0
- vidbyte_cli/services/persistence/session.py +116 -0
- vidbyte_cli/services/suggestions/__init__.py +7 -0
- vidbyte_cli/services/suggestions/categories.py +270 -0
- vidbyte_cli/services/suggestions/context.py +222 -0
- vidbyte_cli/services/suggestions/extra_compute.py +53 -0
- vidbyte_cli/services/suggestions/handoff.py +173 -0
- vidbyte_cli/services/suggestions/message_tools.py +47 -0
- vidbyte_cli/services/suggestions/project.py +253 -0
- vidbyte_cli/services/suggestions/prompts/__init__.py +1 -0
- vidbyte_cli/services/suggestions/prompts/categories/__init__.py +3 -0
- vidbyte_cli/services/suggestions/prompts/categories/adjacent_opportunity.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/alternative.md +38 -0
- vidbyte_cli/services/suggestions/prompts/categories/big_bets.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/bottleneck.md +38 -0
- vidbyte_cli/services/suggestions/prompts/categories/business_growth.md +38 -0
- vidbyte_cli/services/suggestions/prompts/categories/completion.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/continuation.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/coordination.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/creative_exploration.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/cross_domain.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/delegation.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/experiment.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/feedback.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/goal_clarification.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/immediate_next_steps.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/investigation.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/learning.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/leverage.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/long_term_directions.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/preparation.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/prerequisite.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/prioritization.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/product_experience.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/quick_wins.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/reframing.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/risk_prevention.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/simplification.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/stop_or_defer.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/strategy.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/technical_possibilities.md +37 -0
- vidbyte_cli/services/suggestions/prompts/categories/verification.md +37 -0
- vidbyte_cli/services/suggestions/prompts/critic.md +209 -0
- vidbyte_cli/services/suggestions/prompts/critic_message.md +8 -0
- vidbyte_cli/services/suggestions/prompts/generator.md +64 -0
- vidbyte_cli/services/suggestions/prompts/library.py +72 -0
- vidbyte_cli/services/suggestions/prompts/message_generator_argument.md +1 -0
- vidbyte_cli/services/suggestions/prompts/message_generator_tool.md +1 -0
- vidbyte_cli/services/suggestions/prompts/message_parent_argument.md +1 -0
- vidbyte_cli/services/suggestions/prompts/message_parent_tool.md +1 -0
- vidbyte_cli/services/suggestions/prompts/message_receipt.md +1 -0
- vidbyte_cli/services/suggestions/prompts/revision.md +8 -0
- vidbyte_cli/services/suggestions/sdk.py +228 -0
- vidbyte_cli/services/suggestions/selection.py +78 -0
- vidbyte_cli/services/suggestions/service.py +540 -0
- vidbyte_cli/types/__init__.py +0 -0
- vidbyte_cli/types/api.py +101 -0
- vidbyte_cli/types/attachments.py +79 -0
- vidbyte_cli/types/ensemble.py +189 -0
- vidbyte_cli/types/provider.py +62 -0
- vidbyte_cli/types/research.py +260 -0
- vidbyte_cli/types/runtime.py +1098 -0
- vidbyte_cli/types/suggestions.py +518 -0
- vidbyte_cli-0.1.0.dist-info/METADATA +335 -0
- vidbyte_cli-0.1.0.dist-info/RECORD +269 -0
- vidbyte_cli-0.1.0.dist-info/WHEEL +5 -0
- vidbyte_cli-0.1.0.dist-info/entry_points.txt +2 -0
- vidbyte_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
- vidbyte_cli-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"""`vidbyte-cli runtime same-host-ensemble` parses options and renders one ensemble run.
|
|
2
|
+
|
|
3
|
+
Roles are never supplied here: the first stage generates them, so this command's whole input
|
|
4
|
+
surface is one validated `EnsembleInputs` value plus an admission-scoped idempotency key.
|
|
5
|
+
Admission is bought and verified here — through the same layered gate every runtime
|
|
6
|
+
primitive uses — before the runner is allowed to start any agent.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from datetime import UTC, datetime
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
import click
|
|
15
|
+
from pydantic import JsonValue, ValidationError
|
|
16
|
+
|
|
17
|
+
from ...lib.errors.failures import (
|
|
18
|
+
EnsembleHostUnsupported,
|
|
19
|
+
EnsembleInputsInvalid,
|
|
20
|
+
RuntimeAdmissionNotVerified,
|
|
21
|
+
)
|
|
22
|
+
from ...lib.output import OutputDocument
|
|
23
|
+
from ...lib.runtime.context import ApplicationContext
|
|
24
|
+
from ...lib.runtime_primitives.gate import RuntimeAdmissionGate
|
|
25
|
+
from ...services.ensemble.runner import EnsembleRunner
|
|
26
|
+
from ...services.ensemble.sdk import EnsembleSdk
|
|
27
|
+
from ...types.ensemble import (
|
|
28
|
+
EnsembleHost,
|
|
29
|
+
EnsembleInputs,
|
|
30
|
+
EnsembleReasoningEffort,
|
|
31
|
+
EnsembleResult,
|
|
32
|
+
)
|
|
33
|
+
from ...types.research import IdempotencyKey
|
|
34
|
+
from ...types.runtime import (
|
|
35
|
+
RuntimeAdmissionGrant,
|
|
36
|
+
RuntimeAdmissionRequest,
|
|
37
|
+
RuntimeHost,
|
|
38
|
+
RuntimeLaunchPlan,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# The environment variable carrying the optional grant HMAC key. When it is absent the
|
|
42
|
+
# gate's Layer 1 typed-grant checks still gate; a present key additionally enables the
|
|
43
|
+
# Layer 2 signature check.
|
|
44
|
+
_VERIFICATION_KEY_ENV_VAR = "RUNTIME_ADMISSION_SIGNING_KEY"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class SameHostEnsembleCommand:
|
|
48
|
+
"""Validates ensemble options, admits and verifies, runs the primitive, renders."""
|
|
49
|
+
|
|
50
|
+
def register(self, parent: click.Group) -> None:
|
|
51
|
+
# Only Codex is offered, because it is the one host with verified fork and sandbox.
|
|
52
|
+
@parent.command(
|
|
53
|
+
name="same-host-ensemble",
|
|
54
|
+
help=(
|
|
55
|
+
"Run a planner-led team of Codex agents on this machine: generated roles "
|
|
56
|
+
"propose approaches in read-only forks, a selector narrows them to one, "
|
|
57
|
+
"and a single writer implements it. Costs a 2c admission per run."
|
|
58
|
+
),
|
|
59
|
+
)
|
|
60
|
+
@click.argument("task")
|
|
61
|
+
@click.option(
|
|
62
|
+
"--host",
|
|
63
|
+
type=click.Choice(tuple(host.value for host in EnsembleHost)),
|
|
64
|
+
default=EnsembleHost.CODEX.value,
|
|
65
|
+
show_default=True,
|
|
66
|
+
help=(
|
|
67
|
+
"Which installed coding agent hosts the ensemble. Codex is the only host "
|
|
68
|
+
"with verified thread-fork and per-fork sandbox support, so it is the "
|
|
69
|
+
"only accepted value."
|
|
70
|
+
),
|
|
71
|
+
)
|
|
72
|
+
@click.option(
|
|
73
|
+
"--roles",
|
|
74
|
+
type=int,
|
|
75
|
+
default=3,
|
|
76
|
+
show_default=True,
|
|
77
|
+
help=(
|
|
78
|
+
"How many specialist roles the planner invents for this task (3-100). "
|
|
79
|
+
"More roles widen the approach slate the selector narrows; every role "
|
|
80
|
+
"runs concurrently in its own read-only fork against your subscription."
|
|
81
|
+
),
|
|
82
|
+
)
|
|
83
|
+
@click.option(
|
|
84
|
+
"--model",
|
|
85
|
+
default=None,
|
|
86
|
+
help=(
|
|
87
|
+
"Model override forwarded to every Codex turn and fork in the run. "
|
|
88
|
+
"Omit to use the provider default."
|
|
89
|
+
),
|
|
90
|
+
)
|
|
91
|
+
@click.option(
|
|
92
|
+
"--reasoning-effort",
|
|
93
|
+
type=click.Choice(tuple(effort.value for effort in EnsembleReasoningEffort)),
|
|
94
|
+
default=None,
|
|
95
|
+
help=(
|
|
96
|
+
"Reasoning effort forwarded to every Codex turn in the run "
|
|
97
|
+
"(none, minimal, low, medium, high, xhigh). "
|
|
98
|
+
"Omit to use the provider default."
|
|
99
|
+
),
|
|
100
|
+
)
|
|
101
|
+
@click.option(
|
|
102
|
+
"--idempotency-key",
|
|
103
|
+
"explicit_key",
|
|
104
|
+
default=None,
|
|
105
|
+
help=(
|
|
106
|
+
"Reuse a key to retry a priced admission without being charged twice. "
|
|
107
|
+
"Omit to generate one per invocation."
|
|
108
|
+
),
|
|
109
|
+
)
|
|
110
|
+
@click.pass_obj
|
|
111
|
+
def _run(
|
|
112
|
+
context: ApplicationContext,
|
|
113
|
+
task: str,
|
|
114
|
+
host: str,
|
|
115
|
+
roles: int,
|
|
116
|
+
model: str | None,
|
|
117
|
+
reasoning_effort: str | None,
|
|
118
|
+
explicit_key: str | None,
|
|
119
|
+
) -> None:
|
|
120
|
+
# Delegates parsed values to the class-owned execution method.
|
|
121
|
+
self.execute(
|
|
122
|
+
context,
|
|
123
|
+
self._inputs(task, host, roles, model, reasoning_effort),
|
|
124
|
+
explicit_key,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
def execute(
|
|
128
|
+
self,
|
|
129
|
+
context: ApplicationContext,
|
|
130
|
+
inputs: EnsembleInputs,
|
|
131
|
+
explicit_key: str | None = None,
|
|
132
|
+
) -> None:
|
|
133
|
+
# Everything free runs first: key validation, launch planning, host support, and
|
|
134
|
+
# SDK resolution all complete before the one paid admission is requested, and the
|
|
135
|
+
# layered gate verifies the grant before any agent is allowed to start.
|
|
136
|
+
key = str(IdempotencyKey.create(explicit_key))
|
|
137
|
+
plan = context.runtime_launch_planner().build(
|
|
138
|
+
inputs.task,
|
|
139
|
+
RuntimeHost(inputs.host.value),
|
|
140
|
+
Path.cwd(),
|
|
141
|
+
"runtime.same-host-ensemble@1",
|
|
142
|
+
)
|
|
143
|
+
if plan.host is not RuntimeHost.CODEX:
|
|
144
|
+
raise EnsembleHostUnsupported(plan.host.value)
|
|
145
|
+
sdk = EnsembleSdk.load()
|
|
146
|
+
grant = context.runtime_endpoints().admit_same_host_ensemble(
|
|
147
|
+
RuntimeAdmissionRequest(host=plan.host), key
|
|
148
|
+
)
|
|
149
|
+
self._verify(plan, grant, context)
|
|
150
|
+
result = EnsembleRunner().run(plan, inputs, sdk, grant)
|
|
151
|
+
self._render(context, result)
|
|
152
|
+
|
|
153
|
+
def _verify(
|
|
154
|
+
self,
|
|
155
|
+
plan: RuntimeLaunchPlan,
|
|
156
|
+
grant: RuntimeAdmissionGrant,
|
|
157
|
+
context: ApplicationContext,
|
|
158
|
+
) -> None:
|
|
159
|
+
# A rejected grant fails the run here, so no fork ever starts unverified.
|
|
160
|
+
verdict = RuntimeAdmissionGate().verify(
|
|
161
|
+
plan,
|
|
162
|
+
grant,
|
|
163
|
+
datetime.now(UTC),
|
|
164
|
+
context.environment.get(_VERIFICATION_KEY_ENV_VAR),
|
|
165
|
+
)
|
|
166
|
+
if not verdict.admitted:
|
|
167
|
+
raise RuntimeAdmissionNotVerified(verdict.reason)
|
|
168
|
+
|
|
169
|
+
def _inputs(
|
|
170
|
+
self,
|
|
171
|
+
task: str,
|
|
172
|
+
host: str,
|
|
173
|
+
roles: int,
|
|
174
|
+
model: str | None,
|
|
175
|
+
reasoning_effort: str | None,
|
|
176
|
+
) -> EnsembleInputs:
|
|
177
|
+
# Bounds live on the model, so they hold for any caller, not just this Click surface.
|
|
178
|
+
try:
|
|
179
|
+
return EnsembleInputs(
|
|
180
|
+
task=task,
|
|
181
|
+
host=EnsembleHost(host),
|
|
182
|
+
roles=roles,
|
|
183
|
+
model=model,
|
|
184
|
+
reasoning_effort=(
|
|
185
|
+
None if reasoning_effort is None else EnsembleReasoningEffort(reasoning_effort)
|
|
186
|
+
),
|
|
187
|
+
)
|
|
188
|
+
except (ValidationError, ValueError) as error:
|
|
189
|
+
raise EnsembleInputsInvalid(error) from error
|
|
190
|
+
|
|
191
|
+
def _render(self, context: ApplicationContext, result: EnsembleResult) -> None:
|
|
192
|
+
# The machine document carries every branch; the human summary leads with the outcome.
|
|
193
|
+
document: JsonValue = result.model_dump(mode="json")
|
|
194
|
+
context.output().result(
|
|
195
|
+
OutputDocument(kind="runtime.ensemble", data={"ensemble": document}),
|
|
196
|
+
self._summary(result),
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
def _summary(self, result: EnsembleResult) -> str:
|
|
200
|
+
# Roles and failures are listed before the implementation, so partial runs are obvious.
|
|
201
|
+
proposed, total = len(result.proposals), len(result.roles)
|
|
202
|
+
lines = [f"{proposed}/{total} roles proposed {result.candidates} approaches:"]
|
|
203
|
+
lines.extend(
|
|
204
|
+
f" {item.role}: {len(item.approaches)} approaches" for item in result.proposals
|
|
205
|
+
)
|
|
206
|
+
lines.extend(f" {item.role}: failed ({item.reason})" for item in result.failures)
|
|
207
|
+
lines.append(self._narrowing(result))
|
|
208
|
+
selected, verdict = result.selected.candidate, result.selected.verdict
|
|
209
|
+
lines.append(
|
|
210
|
+
f"selected {selected.candidate_id} ({selected.role}, score {verdict.score}): "
|
|
211
|
+
f"{selected.approach.title}"
|
|
212
|
+
)
|
|
213
|
+
lines.append(f" {verdict.rationale}")
|
|
214
|
+
lines.append("")
|
|
215
|
+
lines.append(result.implementation)
|
|
216
|
+
return "\n".join(lines)
|
|
217
|
+
|
|
218
|
+
def _narrowing(self, result: EnsembleResult) -> str:
|
|
219
|
+
# The ladder is the audit trail of the selection, so it prints even when it is short.
|
|
220
|
+
widths = [str(result.candidates), *(str(len(item.kept)) for item in result.rounds)]
|
|
221
|
+
return f"selection narrowed {' -> '.join(widths)} over {len(result.rounds)} round(s)"
|