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,100 @@
|
|
|
1
|
+
**Parent Trajectory**
|
|
2
|
+
Parent Trajectory is the named larger effort value that this command accepts for one suggestion workflow.
|
|
3
|
+
It gives the parent agent a stable way to state the path and intent supplied by the parent agent or larger effort.
|
|
4
|
+
This value is completely optional. Supplying it is helpful when the additional signal can change the next action.
|
|
5
|
+
The command keeps this value as caller task data and does not treat it as an instruction to execute work.
|
|
6
|
+
The value is carried into the bounded request with its source and semantic identity intact.
|
|
7
|
+
A precise value gives the generator and independent critic more signal than a broad label or an unstated assumption.
|
|
8
|
+
|
|
9
|
+
**Purpose of Parent Trajectory**
|
|
10
|
+
The purpose of Parent Trajectory is to make the path and intent supplied by the parent agent or larger effort explicit before candidate generation starts.
|
|
11
|
+
That explicit record lets the workflow compare ideas against the situation the caller actually described.
|
|
12
|
+
It also lets the critic explain whether a candidate is supported, missing evidence, or in conflict.
|
|
13
|
+
The field is most valuable when its content changes feasibility, novelty, timing, risk, or the definition of progress.
|
|
14
|
+
A short accurate statement is more useful than a long narrative that hides the decision-relevant fact.
|
|
15
|
+
The resulting ideas should refer to this signal only when the connection is material and explain why it matters.
|
|
16
|
+
|
|
17
|
+
**When not to use Parent Trajectory**
|
|
18
|
+
Do not provide Parent Trajectory merely because the option exists or because an empty value would look complete.
|
|
19
|
+
Omit it when the caller has no reliable signal of this kind and let the workflow mark the context as missing.
|
|
20
|
+
Do not use this field to smuggle execution instructions, credentials, private data, or a second command configuration.
|
|
21
|
+
Use a narrower context option when the statement has a clearly different meaning such as a risk, decision, or prohibition.
|
|
22
|
+
Avoid repeating the goal or copying an entire unrelated transcript because repetition lowers the signal available to the critic.
|
|
23
|
+
If the caller is unsure whether the record is current, state that uncertainty in the value rather than presenting it as a fact.
|
|
24
|
+
|
|
25
|
+
**Parent Trajectory inputs**
|
|
26
|
+
The value is one nonempty text statement per repeated option.
|
|
27
|
+
Repeated occurrences remain separate records so the agent can cite and compare them without parsing a delimiter.
|
|
28
|
+
Whitespace around a value is trimmed at the request boundary, while an empty value is rejected before provider work.
|
|
29
|
+
The command does not reinterpret the content as an identifier unless the option contract explicitly says it is one.
|
|
30
|
+
Use plain caller-readable text and keep each record focused on one fact, choice, boundary, or result.
|
|
31
|
+
The input is bounded before it enters the agent context so oversized content becomes an explicit truncation or omission.
|
|
32
|
+
A caller should keep related facts separate when their provenance, confidence, or expected effect differs enough to influence review.
|
|
33
|
+
|
|
34
|
+
**Defaults and precedence for Parent Trajectory**
|
|
35
|
+
When it is omitted, the default is no supplied larger effort..
|
|
36
|
+
Command-line values are the only source for this field, and the run does not read a separate configuration document.
|
|
37
|
+
Environment variables do not silently populate this context value, which keeps an invocation reproducible.
|
|
38
|
+
When multiple values are supplied, their command-line order becomes their stable context order.
|
|
39
|
+
Explicit caller input therefore takes precedence over absence, while other settings such as count and rounds remain independent.
|
|
40
|
+
The result manifest records what was supplied and whether the bounded value was included, truncated, or omitted.
|
|
41
|
+
Use the manifest and warnings to distinguish absence from an explicitly bounded value when a downstream agent needs to explain why a suggestion changed.
|
|
42
|
+
|
|
43
|
+
**Parent Trajectory output contract**
|
|
44
|
+
Parent Trajectory is not printed as a separate progress message because stdout is reserved for the command result.
|
|
45
|
+
For a model-backed run, the value appears inside the fresh managed context window used by the relevant agent.
|
|
46
|
+
For dry-run output, the manifest exposes source identity and bounded character information without exposing file bodies by default.
|
|
47
|
+
Human output summarizes the resulting suggestions, while JSON and JSONL output preserve stable machine-readable fields.
|
|
48
|
+
Errors go to the CLI error channel as typed envelopes with a repair-oriented description and no secret echo.
|
|
49
|
+
The field influences ideas and handoffs but never grants authority, starts work, or changes the caller's permissions.
|
|
50
|
+
|
|
51
|
+
**How to use Parent Trajectory**
|
|
52
|
+
Use the command below as the smallest valid invocation shape for this value.
|
|
53
|
+
Replace each brace-delimited placeholder with the caller's actual text while preserving shell quoting around spaces.
|
|
54
|
+
Repeat the option when more than one independent record should be supplied.
|
|
55
|
+
Combine the option with a precise goal because the field is evidence or context rather than a standalone task.
|
|
56
|
+
Add category and budget options only when they answer a real selection or resource question.
|
|
57
|
+
The command remains a single argv-built request and does not require a temporary configuration file.
|
|
58
|
+
Keep the invocation close to the caller's actual decision so another agent can reproduce the request without guessing omitted context, quoting, or precedence.
|
|
59
|
+
|
|
60
|
+
```text
|
|
61
|
+
vidbyte-cli agents suggest run --goal "{goal}" --trajectory "{parent trajectory}"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Examples for Parent Trajectory**
|
|
65
|
+
A minimal example supplies only the required goal and leaves this optional signal absent when it has no value.
|
|
66
|
+
A normal example adds one focused record that directly changes how the next action should be judged.
|
|
67
|
+
An advanced example repeats the option for several independent records and combines it with a selected category.
|
|
68
|
+
Piping is appropriate only for a caller that captures the emitted result document, because input itself is passed through argv.
|
|
69
|
+
JSON output is the stable choice when another agent will inspect identifiers, manifests, warnings, and handoffs.
|
|
70
|
+
If an example fails, preserve the same goal and correct the named input or path before changing the reasoning settings.
|
|
71
|
+
|
|
72
|
+
```text
|
|
73
|
+
vidbyte-cli agents suggest run --goal "{goal}" --trajectory "{parent trajectory}"
|
|
74
|
+
vidbyte-cli --json agents suggest run --goal "{goal}" --trajectory "{value}"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Related commands for Parent Trajectory**
|
|
78
|
+
Use agents suggest categories --view-all when the caller needs to choose a reasoning lens before running.
|
|
79
|
+
Use agents suggest categories --view {category-id} when one category needs a fuller conceptual definition.
|
|
80
|
+
Use the other context options when the signal is more accurately a decision, constraint, risk, or current commitment.
|
|
81
|
+
Use agents suggest handoff only after a result document exists and a specific idea identifier has been selected.
|
|
82
|
+
Use dry-run when the request shape and file manifest need inspection without credentials or model usage.
|
|
83
|
+
These commands share the same result conventions but do not imply that one command can authorize another.
|
|
84
|
+
Choose the narrowest neighboring command that answers the immediate question, then return to this option when the run itself needs the signal.
|
|
85
|
+
|
|
86
|
+
**Failure modes for Parent Trajectory**
|
|
87
|
+
A missing required value fails before the provider is loaded because the request dataclass requires a meaningful boundary.
|
|
88
|
+
An empty repeated value fails as invalid input instead of becoming a misleading blank context record.
|
|
89
|
+
An unsupported path, malformed JSON file, directory, or unreadable file fails with a typed context error.
|
|
90
|
+
An oversized value is truncated only within the documented bound and the result records that status as a warning.
|
|
91
|
+
A provider or schema failure is reported as a provider failure and is never converted into a false no-suggestions result.
|
|
92
|
+
Recover by correcting the specific value named by the error, rerunning dry-run when useful, and preserving the same intent.
|
|
93
|
+
|
|
94
|
+
**Authentication and permissions for Parent Trajectory**
|
|
95
|
+
This input itself does not grant access to files, providers, accounts, repositories, or execution tools.
|
|
96
|
+
Text values are available to local validation without credentials, while model-backed runs still require the configured provider.
|
|
97
|
+
The --files option reads only paths explicitly named by the caller and does not scan a workspace or agent history.
|
|
98
|
+
Read-only deny-all settings apply to generator and critic agents so suggestions cannot mutate the host through this workflow.
|
|
99
|
+
Provider credentials are used only when a real model-backed run is requested and are never copied into result prose.
|
|
100
|
+
Permission failures should be repaired at the provider or filesystem boundary rather than by weakening the context contract.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
View one expands a single category into its full high-level definition. Pass the exact category identifier shown by the all-categories view. The result includes the authored description and the considerations that guide suggestions of that type.
|
|
2
|
+
|
|
3
|
+
Use this view when a caller needs to understand the distinction between nearby categories before selecting one. The command reads packaged content locally and makes no model call. An unknown identifier is rejected before any output is produced.
|
|
4
|
+
|
|
5
|
+
The expanded definition is informative guidance, not an instruction to execute work. It preserves the category's conceptual boundary while leaving concrete actions to a later suggestion run.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
View all returns the high-level summary of every category in the suggestion registry. It is useful when an agent needs to choose a reasoning lens before building a run.
|
|
2
|
+
|
|
3
|
+
The default output is the same complete summary list, so callers do not need a separate discovery step. Use the expanded view when the short description is not enough to decide which category fits the goal. This read does not invoke a model or inspect credentials.
|
|
4
|
+
|
|
5
|
+
The summaries come from the same registry that validates run selections and supplies category context. They describe opportunity types at a conceptual level and intentionally omit provider, prompt, and implementation mechanics.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Renders suggestion results for human and machine consumers.
|
|
2
|
+
|
|
3
|
+
Human output prints ranked titles with categories and first actions; JSON
|
|
4
|
+
output emits the versioned envelope. Only results reach stdout, because the
|
|
5
|
+
application layer routes diagnostics to stderr before this module ever runs.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from ....lib.output import OutputDocument
|
|
11
|
+
from ....lib.runtime.context import ApplicationContext as Context
|
|
12
|
+
from ....types.suggestions import (
|
|
13
|
+
SUGGESTIONS_HANDOFF_KIND,
|
|
14
|
+
SUGGESTIONS_RESULT_KIND,
|
|
15
|
+
SuggestionFeedbackCapture,
|
|
16
|
+
SuggestionHandoff,
|
|
17
|
+
SuggestionIdea,
|
|
18
|
+
SuggestionResult,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SuggestionRenderer:
|
|
23
|
+
"""Formats batches and handoffs without touching provider or filesystem state."""
|
|
24
|
+
|
|
25
|
+
def __init__(self) -> None:
|
|
26
|
+
# Stateless; formatting depends only on the documents passed per call.
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
def render_result(self, context: Context, result: SuggestionResult) -> None:
|
|
30
|
+
# Emits the envelope for machines and a ranked list for humans.
|
|
31
|
+
context.output().result(
|
|
32
|
+
OutputDocument(kind=SUGGESTIONS_RESULT_KIND, data=result.model_dump(mode="json")),
|
|
33
|
+
self._human_result(result),
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
def render_handoff(self, context: Context, handoff: SuggestionHandoff) -> None:
|
|
37
|
+
# Emits the handoff envelope plus its copyable execution prompt.
|
|
38
|
+
context.output().result(
|
|
39
|
+
OutputDocument(kind=SUGGESTIONS_HANDOFF_KIND, data=handoff.model_dump(mode="json")),
|
|
40
|
+
handoff.execution_prompt,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
def _human_result(self, result: SuggestionResult) -> str:
|
|
44
|
+
# One block per idea so a person can scan ranks without parsing JSON.
|
|
45
|
+
# A generator that stopped to ask for input returns its question instead of ideas.
|
|
46
|
+
if result.parent_message is not None:
|
|
47
|
+
rendered = f"Input needed for: {result.goal}\n\n{result.parent_message}"
|
|
48
|
+
elif not result.ideas:
|
|
49
|
+
rendered = f"No suggestions for: {result.goal}"
|
|
50
|
+
else:
|
|
51
|
+
blocks: list[str] = []
|
|
52
|
+
for idea in result.ideas:
|
|
53
|
+
blocks.append(self._human_idea(idea))
|
|
54
|
+
header = self._human_header(result)
|
|
55
|
+
rendered = header + "\n\n" + "\n\n".join(blocks)
|
|
56
|
+
if result.feedback_capture is not None:
|
|
57
|
+
rendered += "\n\n" + self._human_feedback(result.feedback_capture)
|
|
58
|
+
return rendered
|
|
59
|
+
|
|
60
|
+
def _human_idea(self, idea: SuggestionIdea) -> str:
|
|
61
|
+
# One ranked line plus its first action on a second line.
|
|
62
|
+
lead = f"#{idea.rank} {idea.id} [{idea.primary_category}]"
|
|
63
|
+
return f"{lead} {idea.title}\n First action: {idea.first_action}"
|
|
64
|
+
|
|
65
|
+
def _human_header(self, result: SuggestionResult) -> str:
|
|
66
|
+
# Counts plus goal plus status so shortfalls read plainly.
|
|
67
|
+
counts = f"{result.returned_count}/{result.requested_count}"
|
|
68
|
+
return f"{counts} ideas for: {result.goal} [{result.status.value}]"
|
|
69
|
+
|
|
70
|
+
def _human_feedback(self, capture: SuggestionFeedbackCapture) -> str:
|
|
71
|
+
# A static reminder for the parent agent that never implies feedback already exists.
|
|
72
|
+
return (
|
|
73
|
+
"Feedback capture: call accept or reject only after explicit user feedback; "
|
|
74
|
+
f"use project '{capture.project_key}'.\n"
|
|
75
|
+
f" Accept: {capture.accept_command}\n"
|
|
76
|
+
f" Reject: {capture.reject_command}"
|
|
77
|
+
)
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"""Builds one strict suggestion request from parsed command values.
|
|
2
|
+
|
|
3
|
+
The input dataclass owns argv validation and the builder owns file and project resolution.
|
|
4
|
+
Caller-facing help is kept at the CLI boundary and never copied into agent context.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any, cast
|
|
12
|
+
|
|
13
|
+
from pydantic import ValidationError
|
|
14
|
+
|
|
15
|
+
from ....lib.config import VidbytePaths
|
|
16
|
+
from ....lib.errors.failures import (
|
|
17
|
+
SuggestionContextUnreadable,
|
|
18
|
+
SuggestionInputInvalid,
|
|
19
|
+
SuggestionProjectInvalid,
|
|
20
|
+
)
|
|
21
|
+
from ....services.suggestions.categories import SuggestionCategories
|
|
22
|
+
from ....services.suggestions.context import SuggestionContextBuilder
|
|
23
|
+
from ....services.suggestions.project import SuggestionProject, SuggestionProjectKey
|
|
24
|
+
from ....types.suggestions import (
|
|
25
|
+
SuggestionContextPrimitive,
|
|
26
|
+
SuggestionHorizon,
|
|
27
|
+
SuggestionRequest,
|
|
28
|
+
SuggestionSettings,
|
|
29
|
+
)
|
|
30
|
+
from ...agent_options import AgentAttachmentOptions
|
|
31
|
+
|
|
32
|
+
_CONTEXT_FIELD_NAMES = (
|
|
33
|
+
"context",
|
|
34
|
+
"completed",
|
|
35
|
+
"in_progress",
|
|
36
|
+
"decision",
|
|
37
|
+
"constraint",
|
|
38
|
+
"avoid",
|
|
39
|
+
"mistakes",
|
|
40
|
+
"forbidden",
|
|
41
|
+
"approaches",
|
|
42
|
+
"outcomes",
|
|
43
|
+
"blockers",
|
|
44
|
+
"hypotheses",
|
|
45
|
+
"risks",
|
|
46
|
+
"trajectory",
|
|
47
|
+
"question",
|
|
48
|
+
"capability",
|
|
49
|
+
"success",
|
|
50
|
+
)
|
|
51
|
+
_HORIZONS = frozenset(item.value for item in SuggestionHorizon)
|
|
52
|
+
_PROVIDERS = frozenset({"openai"})
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass(frozen=True, slots=True)
|
|
56
|
+
class SuggestionRunInput:
|
|
57
|
+
"""Strict, canonical representation of one Click invocation."""
|
|
58
|
+
|
|
59
|
+
goal: str = ""
|
|
60
|
+
project: str | None = None
|
|
61
|
+
context: tuple[str, ...] = ()
|
|
62
|
+
completed: tuple[str, ...] = ()
|
|
63
|
+
in_progress: tuple[str, ...] = ()
|
|
64
|
+
decision: tuple[str, ...] = ()
|
|
65
|
+
constraint: tuple[str, ...] = ()
|
|
66
|
+
avoid: tuple[str, ...] = ()
|
|
67
|
+
mistakes: tuple[str, ...] = ()
|
|
68
|
+
forbidden: tuple[str, ...] = ()
|
|
69
|
+
approaches: tuple[str, ...] = ()
|
|
70
|
+
outcomes: tuple[str, ...] = ()
|
|
71
|
+
blockers: tuple[str, ...] = ()
|
|
72
|
+
hypotheses: tuple[str, ...] = ()
|
|
73
|
+
risks: tuple[str, ...] = ()
|
|
74
|
+
trajectory: tuple[str, ...] = ()
|
|
75
|
+
question: tuple[str, ...] = ()
|
|
76
|
+
capability: tuple[str, ...] = ()
|
|
77
|
+
success: tuple[str, ...] = ()
|
|
78
|
+
files: tuple[Path, ...] = ()
|
|
79
|
+
attachments: tuple[Path, ...] = ()
|
|
80
|
+
count: int = 5
|
|
81
|
+
categories: tuple[str, ...] = ()
|
|
82
|
+
all_categories: bool = False
|
|
83
|
+
extra_compute: bool = False
|
|
84
|
+
horizon: str = "any"
|
|
85
|
+
rounds: int = 2
|
|
86
|
+
max_messages: int = 2
|
|
87
|
+
provider: str | None = None
|
|
88
|
+
critic_model: str | None = None
|
|
89
|
+
max_output_tokens: int | None = None
|
|
90
|
+
max_total_tokens: int | None = None
|
|
91
|
+
timeout_seconds: int | None = None
|
|
92
|
+
dry_run: bool = False
|
|
93
|
+
|
|
94
|
+
def __post_init__(self) -> None:
|
|
95
|
+
self._validate_goal()
|
|
96
|
+
self._validate_context_values()
|
|
97
|
+
self._validate_files()
|
|
98
|
+
self._validate_attachments()
|
|
99
|
+
self._validate_selection()
|
|
100
|
+
self._validate_execution_settings()
|
|
101
|
+
self._validate_limits()
|
|
102
|
+
|
|
103
|
+
def _validate_goal(self) -> None:
|
|
104
|
+
if not self.goal.strip() or len(self.goal) > 4096:
|
|
105
|
+
raise ValueError("goal must be a non-empty string of at most 4096 characters")
|
|
106
|
+
if self.project is not None and type(self.project) is not str:
|
|
107
|
+
raise TypeError("project must be omitted or a string")
|
|
108
|
+
|
|
109
|
+
def _validate_context_values(self) -> None:
|
|
110
|
+
for name in _CONTEXT_FIELD_NAMES:
|
|
111
|
+
values = getattr(self, name)
|
|
112
|
+
if not isinstance(values, tuple) or any(
|
|
113
|
+
type(value) is not str or not value.strip() for value in values
|
|
114
|
+
):
|
|
115
|
+
raise ValueError(f"{name} must contain only non-empty strings")
|
|
116
|
+
|
|
117
|
+
def _validate_files(self) -> None:
|
|
118
|
+
if not isinstance(self.files, tuple) or any(
|
|
119
|
+
not isinstance(path, Path) for path in self.files
|
|
120
|
+
):
|
|
121
|
+
raise TypeError("files must contain only pathlib.Path values")
|
|
122
|
+
|
|
123
|
+
def _validate_attachments(self) -> None:
|
|
124
|
+
# Keeps the shared resolver's input contract explicit at the request boundary.
|
|
125
|
+
if not isinstance(self.attachments, tuple) or any(
|
|
126
|
+
not isinstance(path, Path) for path in self.attachments
|
|
127
|
+
):
|
|
128
|
+
raise TypeError("attachments must contain only pathlib.Path values")
|
|
129
|
+
|
|
130
|
+
def _validate_selection(self) -> None:
|
|
131
|
+
if type(self.count) is not int or not 2 <= self.count <= 15:
|
|
132
|
+
raise ValueError("count must be between 2 and 15")
|
|
133
|
+
if not isinstance(self.categories, tuple) or any(
|
|
134
|
+
type(category) is not str or not category.strip() for category in self.categories
|
|
135
|
+
):
|
|
136
|
+
raise ValueError("categories must contain only non-empty strings")
|
|
137
|
+
if len(set(self.categories)) != len(self.categories):
|
|
138
|
+
raise ValueError("categories must not contain duplicates")
|
|
139
|
+
SuggestionCategories().require_known(self.categories)
|
|
140
|
+
if type(self.all_categories) is not bool or type(self.extra_compute) is not bool:
|
|
141
|
+
raise TypeError("all_categories and extra_compute must be booleans")
|
|
142
|
+
if self.all_categories and self.categories:
|
|
143
|
+
raise ValueError("all_categories and categories cannot both be selected")
|
|
144
|
+
|
|
145
|
+
def _validate_execution_settings(self) -> None:
|
|
146
|
+
if type(self.horizon) is not str or self.horizon not in _HORIZONS:
|
|
147
|
+
raise ValueError("horizon must be now, next, later, or any")
|
|
148
|
+
if type(self.rounds) is not int or not 1 <= self.rounds <= 8:
|
|
149
|
+
raise ValueError("rounds must be between 1 and 8")
|
|
150
|
+
if type(self.max_messages) is not int or not 0 <= self.max_messages <= 8:
|
|
151
|
+
raise ValueError("max_messages must be between 0 and 8")
|
|
152
|
+
if type(self.provider) is not str and self.provider is not None:
|
|
153
|
+
raise TypeError("provider must be omitted or a string")
|
|
154
|
+
if self.provider is not None and self.provider not in _PROVIDERS:
|
|
155
|
+
raise ValueError("provider must be openai or omitted")
|
|
156
|
+
if self.critic_model is not None and (
|
|
157
|
+
type(self.critic_model) is not str or not self.critic_model.strip()
|
|
158
|
+
):
|
|
159
|
+
raise ValueError("critic_model must be omitted or a non-empty string")
|
|
160
|
+
|
|
161
|
+
def _validate_limits(self) -> None:
|
|
162
|
+
if any(
|
|
163
|
+
value is not None and (type(value) is not int or value <= 0)
|
|
164
|
+
for value in (self.max_output_tokens, self.max_total_tokens, self.timeout_seconds)
|
|
165
|
+
):
|
|
166
|
+
raise ValueError("token and timeout limits must be positive integers")
|
|
167
|
+
if self.max_output_tokens is not None and self.max_output_tokens > 5_000_000:
|
|
168
|
+
raise ValueError("max_output_tokens cannot exceed 5000000")
|
|
169
|
+
if self.max_total_tokens is not None and self.max_total_tokens > 20_000_000:
|
|
170
|
+
raise ValueError("max_total_tokens cannot exceed 20000000")
|
|
171
|
+
if self.timeout_seconds is not None and self.timeout_seconds > 86_400:
|
|
172
|
+
raise ValueError("timeout_seconds cannot exceed 86400")
|
|
173
|
+
if type(self.dry_run) is not bool:
|
|
174
|
+
raise TypeError("dry_run must be a boolean")
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class SuggestionRequestBuilder:
|
|
178
|
+
"""Resolves one validated invocation into a service request."""
|
|
179
|
+
|
|
180
|
+
def build(self, raw: dict[str, object], paths: VidbytePaths | None = None) -> SuggestionRequest:
|
|
181
|
+
try:
|
|
182
|
+
values = SuggestionRunInput(**cast(dict[str, Any], raw))
|
|
183
|
+
except (TypeError, ValueError) as error:
|
|
184
|
+
raise SuggestionInputInvalid() from error
|
|
185
|
+
fields = {
|
|
186
|
+
name: getattr(values, name) for name in _CONTEXT_FIELD_NAMES if getattr(values, name)
|
|
187
|
+
}
|
|
188
|
+
project_key = self._project_key(values.project)
|
|
189
|
+
if project_key is not None:
|
|
190
|
+
# Project memory joins after caller flags, so caller refs keep their numbering.
|
|
191
|
+
fields.update(SuggestionProject(paths).context_fields(project_key))
|
|
192
|
+
try:
|
|
193
|
+
snapshot = SuggestionContextBuilder().build(fields, values.files)
|
|
194
|
+
except ValueError as error:
|
|
195
|
+
raise SuggestionContextUnreadable(str(error)) from error
|
|
196
|
+
attachments = AgentAttachmentOptions().resolve({"attachments": values.attachments})
|
|
197
|
+
try:
|
|
198
|
+
settings = SuggestionSettings(
|
|
199
|
+
requested_count=values.count,
|
|
200
|
+
categories=values.categories,
|
|
201
|
+
all_categories=values.all_categories,
|
|
202
|
+
extra_compute=values.extra_compute,
|
|
203
|
+
horizon=SuggestionHorizon(values.horizon),
|
|
204
|
+
rounds=values.rounds,
|
|
205
|
+
max_messages=values.max_messages,
|
|
206
|
+
provider=values.provider,
|
|
207
|
+
critic_model=values.critic_model,
|
|
208
|
+
max_output_tokens=values.max_output_tokens,
|
|
209
|
+
max_total_tokens=values.max_total_tokens,
|
|
210
|
+
timeout_seconds=values.timeout_seconds,
|
|
211
|
+
dry_run=values.dry_run,
|
|
212
|
+
)
|
|
213
|
+
return SuggestionRequest(
|
|
214
|
+
goal=values.goal,
|
|
215
|
+
context=SuggestionContextPrimitive(
|
|
216
|
+
goal=values.goal,
|
|
217
|
+
description="Caller-supplied task data for this suggestion run.",
|
|
218
|
+
items=snapshot.items,
|
|
219
|
+
selected_categories=SuggestionCategories().prompt_section(values.categories),
|
|
220
|
+
),
|
|
221
|
+
context_manifest=snapshot.manifest,
|
|
222
|
+
context_warnings=snapshot.warnings,
|
|
223
|
+
settings=settings,
|
|
224
|
+
attachments=attachments,
|
|
225
|
+
project_key=project_key.value if project_key else None,
|
|
226
|
+
)
|
|
227
|
+
except (ValidationError, ValueError) as error:
|
|
228
|
+
raise SuggestionInputInvalid() from error
|
|
229
|
+
|
|
230
|
+
def _project_key(self, project: str | None) -> SuggestionProjectKey | None:
|
|
231
|
+
# A malformed key is a project error, not a goal error, so its repair names --project.
|
|
232
|
+
if project is None:
|
|
233
|
+
return None
|
|
234
|
+
try:
|
|
235
|
+
return SuggestionProjectKey(project)
|
|
236
|
+
except (TypeError, ValueError) as error:
|
|
237
|
+
raise SuggestionProjectInvalid(str(error)) from error
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
__all__ = ["SuggestionRequestBuilder", "SuggestionRunInput"]
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""Parses suggest-run options, then invokes the validated suggestion service.
|
|
2
|
+
|
|
3
|
+
The command owns only argv shape and Click choices. Request and settings
|
|
4
|
+
validation complete before the service loads the provider or starts an agent.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
import click
|
|
12
|
+
|
|
13
|
+
from ....lib.runtime.context import ApplicationContext as Context
|
|
14
|
+
from ....services.suggestions.categories import SuggestionCategories
|
|
15
|
+
from ....services.suggestions.service import SuggestionService
|
|
16
|
+
from ...agent_options import AgentAttachmentOptions
|
|
17
|
+
from .prompts.library import SuggestionHelpLibrary
|
|
18
|
+
from .render import SuggestionRenderer
|
|
19
|
+
from .request_builder import SuggestionRequestBuilder
|
|
20
|
+
|
|
21
|
+
_HELP = SuggestionHelpLibrary()
|
|
22
|
+
_COMMAND_HELP = _HELP.load("run")
|
|
23
|
+
_GOAL_HELP = _HELP.load("goal")
|
|
24
|
+
_PROJECT_HELP = _HELP.load("project")
|
|
25
|
+
_CONTEXT_HELP = _HELP.load("context")
|
|
26
|
+
_FILES_HELP = _HELP.load("files")
|
|
27
|
+
_COMPLETED_HELP = _HELP.load("completed")
|
|
28
|
+
_IN_PROGRESS_HELP = _HELP.load("in_progress")
|
|
29
|
+
_DECISION_HELP = _HELP.load("decision")
|
|
30
|
+
_CONSTRAINT_HELP = _HELP.load("constraint")
|
|
31
|
+
_AVOID_HELP = _HELP.load("avoid")
|
|
32
|
+
_QUESTION_HELP = _HELP.load("question")
|
|
33
|
+
_CAPABILITY_HELP = _HELP.load("capability")
|
|
34
|
+
_SUCCESS_HELP = _HELP.load("success")
|
|
35
|
+
_COUNT_HELP = _HELP.load("count")
|
|
36
|
+
_CATEGORY_HELP = _HELP.load("category")
|
|
37
|
+
_ALL_CATEGORIES_HELP = _HELP.load("all_categories")
|
|
38
|
+
_HORIZON_HELP = _HELP.load("horizon")
|
|
39
|
+
_ROUNDS_HELP = _HELP.load("rounds")
|
|
40
|
+
_MAX_MESSAGES_HELP = _HELP.load("max_messages")
|
|
41
|
+
_PROVIDER_HELP = _HELP.load("provider")
|
|
42
|
+
_CRITIC_MODEL_HELP = _HELP.load("critic_model")
|
|
43
|
+
_EXTRA_COMPUTE_HELP = _HELP.load("extra_compute")
|
|
44
|
+
_MAX_OUTPUT_TOKENS_HELP = _HELP.load("max_output_tokens")
|
|
45
|
+
_MAX_TOTAL_TOKENS_HELP = _HELP.load("max_total_tokens")
|
|
46
|
+
_TIMEOUT_HELP = _HELP.load("timeout")
|
|
47
|
+
_DRY_RUN_HELP = _HELP.load("dry_run")
|
|
48
|
+
_MISTAKES_HELP = _HELP.load("mistakes")
|
|
49
|
+
_FORBIDDEN_HELP = _HELP.load("forbidden")
|
|
50
|
+
_APPROACHES_HELP = _HELP.load("approaches")
|
|
51
|
+
_OUTCOMES_HELP = _HELP.load("outcomes")
|
|
52
|
+
_BLOCKERS_HELP = _HELP.load("blockers")
|
|
53
|
+
_HYPOTHESES_HELP = _HELP.load("hypotheses")
|
|
54
|
+
_RISKS_HELP = _HELP.load("risks")
|
|
55
|
+
_TRAJECTORY_HELP = _HELP.load("trajectory")
|
|
56
|
+
_ATTACHMENT_OPTIONS = AgentAttachmentOptions()
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class SuggestRunCommand:
|
|
60
|
+
"""Validates run options ahead of any model call, then renders the result."""
|
|
61
|
+
|
|
62
|
+
def register(self, parent: click.Group) -> None:
|
|
63
|
+
# Attaches run with goal, context, generation, and budget controls.
|
|
64
|
+
@parent.command(name="run", help=_COMMAND_HELP)
|
|
65
|
+
@click.option("--goal", default=None, help=_GOAL_HELP)
|
|
66
|
+
@click.option("--project", default=None, help=_PROJECT_HELP)
|
|
67
|
+
@click.option("--context", "context", multiple=True, help=_CONTEXT_HELP)
|
|
68
|
+
@click.option(
|
|
69
|
+
"--files",
|
|
70
|
+
"files",
|
|
71
|
+
multiple=True,
|
|
72
|
+
type=click.Path(path_type=Path),
|
|
73
|
+
help=_FILES_HELP,
|
|
74
|
+
)
|
|
75
|
+
@_ATTACHMENT_OPTIONS.apply
|
|
76
|
+
@click.option("--completed", "completed", multiple=True, help=_COMPLETED_HELP)
|
|
77
|
+
@click.option("--in-progress", "in_progress", multiple=True, help=_IN_PROGRESS_HELP)
|
|
78
|
+
@click.option("--decision", "decision", multiple=True, help=_DECISION_HELP)
|
|
79
|
+
@click.option("--constraint", "constraint", multiple=True, help=_CONSTRAINT_HELP)
|
|
80
|
+
@click.option("--avoid", "avoid", multiple=True, help=_AVOID_HELP)
|
|
81
|
+
@click.option("--mistakes", "mistakes", multiple=True, help=_MISTAKES_HELP)
|
|
82
|
+
@click.option("--forbidden", "forbidden", multiple=True, help=_FORBIDDEN_HELP)
|
|
83
|
+
@click.option("--approaches", "approaches", multiple=True, help=_APPROACHES_HELP)
|
|
84
|
+
@click.option("--outcomes", "outcomes", multiple=True, help=_OUTCOMES_HELP)
|
|
85
|
+
@click.option("--blockers", "blockers", multiple=True, help=_BLOCKERS_HELP)
|
|
86
|
+
@click.option("--hypotheses", "hypotheses", multiple=True, help=_HYPOTHESES_HELP)
|
|
87
|
+
@click.option("--risks", "risks", multiple=True, help=_RISKS_HELP)
|
|
88
|
+
@click.option("--trajectory", "trajectory", multiple=True, help=_TRAJECTORY_HELP)
|
|
89
|
+
@click.option("--question", "question", multiple=True, help=_QUESTION_HELP)
|
|
90
|
+
@click.option("--capability", "capability", multiple=True, help=_CAPABILITY_HELP)
|
|
91
|
+
@click.option("--success", "success", multiple=True, help=_SUCCESS_HELP)
|
|
92
|
+
@click.option(
|
|
93
|
+
"--count", type=click.IntRange(2, 15), default=5, show_default=True, help=_COUNT_HELP
|
|
94
|
+
)
|
|
95
|
+
@click.option(
|
|
96
|
+
"--category",
|
|
97
|
+
"categories",
|
|
98
|
+
multiple=True,
|
|
99
|
+
type=click.Choice(SuggestionCategories().ids()),
|
|
100
|
+
help=_CATEGORY_HELP,
|
|
101
|
+
)
|
|
102
|
+
@click.option("--all-categories", is_flag=True, default=False, help=_ALL_CATEGORIES_HELP)
|
|
103
|
+
@click.option(
|
|
104
|
+
"--horizon",
|
|
105
|
+
type=click.Choice(("now", "next", "later", "any")),
|
|
106
|
+
default="any",
|
|
107
|
+
show_default=True,
|
|
108
|
+
help=_HORIZON_HELP,
|
|
109
|
+
)
|
|
110
|
+
@click.option(
|
|
111
|
+
"--rounds", type=click.IntRange(1, 8), default=2, show_default=True, help=_ROUNDS_HELP
|
|
112
|
+
)
|
|
113
|
+
@click.option(
|
|
114
|
+
"--max-messages",
|
|
115
|
+
"max_messages",
|
|
116
|
+
type=click.IntRange(0, 8),
|
|
117
|
+
default=2,
|
|
118
|
+
show_default=True,
|
|
119
|
+
help=_MAX_MESSAGES_HELP,
|
|
120
|
+
)
|
|
121
|
+
@click.option(
|
|
122
|
+
"--provider",
|
|
123
|
+
type=click.Choice(("openai",)),
|
|
124
|
+
default=None,
|
|
125
|
+
help=_PROVIDER_HELP,
|
|
126
|
+
)
|
|
127
|
+
@click.option("--critic-model", "critic_model", default=None, help=_CRITIC_MODEL_HELP)
|
|
128
|
+
@click.option("--extra-compute", is_flag=True, default=False, help=_EXTRA_COMPUTE_HELP)
|
|
129
|
+
@click.option(
|
|
130
|
+
"--max-output-tokens",
|
|
131
|
+
type=click.IntRange(1, 5000000),
|
|
132
|
+
default=None,
|
|
133
|
+
help=_MAX_OUTPUT_TOKENS_HELP,
|
|
134
|
+
)
|
|
135
|
+
@click.option(
|
|
136
|
+
"--max-total-tokens",
|
|
137
|
+
type=click.IntRange(1, 20000000),
|
|
138
|
+
default=None,
|
|
139
|
+
help=_MAX_TOTAL_TOKENS_HELP,
|
|
140
|
+
)
|
|
141
|
+
@click.option(
|
|
142
|
+
"--timeout-seconds", type=click.IntRange(1, 86400), default=None, help=_TIMEOUT_HELP
|
|
143
|
+
)
|
|
144
|
+
@click.option("--dry-run", is_flag=True, default=False, help=_DRY_RUN_HELP)
|
|
145
|
+
@click.pass_obj
|
|
146
|
+
def _run(ctx: Context, /, **kwargs: object) -> None:
|
|
147
|
+
# Delegates parsed values to the testable execution method.
|
|
148
|
+
self.execute(ctx, kwargs)
|
|
149
|
+
|
|
150
|
+
def execute(self, context: Context, raw: dict[str, object]) -> None:
|
|
151
|
+
# Everything invalid fails here, before files are read or models run.
|
|
152
|
+
request = SuggestionRequestBuilder().build(raw, context.paths())
|
|
153
|
+
result = SuggestionService().run(request)
|
|
154
|
+
SuggestionRenderer().render_result(context, result)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Lists or expands the suggestion category registry without model work."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
from pydantic import JsonValue
|
|
7
|
+
|
|
8
|
+
from ....lib.output import OutputDocument
|
|
9
|
+
from ....lib.runtime.context import ApplicationContext as Context
|
|
10
|
+
from ....services.suggestions.categories import (
|
|
11
|
+
SCHEMA_VERSION,
|
|
12
|
+
CategoryDefinition,
|
|
13
|
+
SuggestionCategories,
|
|
14
|
+
)
|
|
15
|
+
from ....services.suggestions.prompts.library import SuggestionPrompts
|
|
16
|
+
from .prompts.library import SuggestionHelpLibrary
|
|
17
|
+
|
|
18
|
+
_COMMAND_HELP = SuggestionHelpLibrary().load("categories")
|
|
19
|
+
_VIEW_ALL_HELP = SuggestionHelpLibrary().load("view_all")
|
|
20
|
+
_VIEW_HELP = SuggestionHelpLibrary().load("view")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class SuggestionCategoriesCommand:
|
|
24
|
+
"""Renders summaries for all categories or the full definition for one category."""
|
|
25
|
+
|
|
26
|
+
def register(self, parent: click.Group) -> None:
|
|
27
|
+
# The Choice is registry-owned, so CLI validation and displayed ids cannot drift.
|
|
28
|
+
@parent.command(name="categories", help=_COMMAND_HELP)
|
|
29
|
+
@click.option("--view-all", is_flag=True, help=_VIEW_ALL_HELP)
|
|
30
|
+
@click.option(
|
|
31
|
+
"--view",
|
|
32
|
+
"view_id",
|
|
33
|
+
type=click.Choice(SuggestionCategories().ids()),
|
|
34
|
+
default=None,
|
|
35
|
+
help=_VIEW_HELP,
|
|
36
|
+
)
|
|
37
|
+
@click.pass_obj
|
|
38
|
+
def _categories(ctx: Context, view_all: bool, view_id: str | None) -> None:
|
|
39
|
+
self.execute(ctx, view_all=view_all, view_id=view_id)
|
|
40
|
+
|
|
41
|
+
def execute(self, context: Context, *, view_all: bool, view_id: str | None) -> None:
|
|
42
|
+
if view_all and view_id:
|
|
43
|
+
raise click.UsageError("--view-all and --view cannot be used together.")
|
|
44
|
+
registry = SuggestionCategories()
|
|
45
|
+
prompts = SuggestionPrompts()
|
|
46
|
+
if view_id:
|
|
47
|
+
definition = registry.describe(view_id)
|
|
48
|
+
entries: list[JsonValue] = [
|
|
49
|
+
self._expanded(definition, prompts.category_prompt(definition.prompt_name))
|
|
50
|
+
]
|
|
51
|
+
human = prompts.category_prompt(definition.prompt_name)
|
|
52
|
+
else:
|
|
53
|
+
entries = [self._summary(item) for item in registry.definitions()]
|
|
54
|
+
human = "\n\n".join(self._human_summary(item) for item in registry.definitions())
|
|
55
|
+
data: dict[str, JsonValue] = {
|
|
56
|
+
"schema_version": SCHEMA_VERSION,
|
|
57
|
+
"view": "category" if view_id else "all",
|
|
58
|
+
"categories": entries,
|
|
59
|
+
}
|
|
60
|
+
context.output().result(OutputDocument(kind="suggestions.categories", data=data), human)
|
|
61
|
+
|
|
62
|
+
def _summary(self, item: CategoryDefinition) -> dict[str, JsonValue]:
|
|
63
|
+
return {"id": item.category_id, "title": item.title, "summary": item.summary}
|
|
64
|
+
|
|
65
|
+
def _expanded(self, item: CategoryDefinition, prompt: str) -> dict[str, JsonValue]:
|
|
66
|
+
return {
|
|
67
|
+
"id": item.category_id,
|
|
68
|
+
"title": item.title,
|
|
69
|
+
"summary": item.summary,
|
|
70
|
+
"prompt": prompt,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
def _human_summary(self, item: CategoryDefinition) -> str:
|
|
74
|
+
return f"{item.category_id} — {item.title}: {item.summary}"
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
__all__ = ["SuggestionCategoriesCommand"]
|