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,60 @@
|
|
|
1
|
+
"""One run's shared collaborators, and the sandbox policy for each of its four stages.
|
|
2
|
+
|
|
3
|
+
This is where "exactly one agent may write" is decided, so the invariant is checkable by
|
|
4
|
+
reading a single file: `root`, `proposal`, and `selector` are read-only, `implementer` is not.
|
|
5
|
+
It also carries the run's sdk, prompts, and inputs so the service does not thread them
|
|
6
|
+
everywhere.
|
|
7
|
+
|
|
8
|
+
Each stage gets a complete system prompt of its own rather than an addition to the previous
|
|
9
|
+
stage's, because a fork inherits its parent's prompt unless it is replaced.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
from ...types.ensemble import (
|
|
18
|
+
EnsembleInputs,
|
|
19
|
+
GeneratedRole,
|
|
20
|
+
RolePlan,
|
|
21
|
+
RoleProposal,
|
|
22
|
+
SelectionRound,
|
|
23
|
+
)
|
|
24
|
+
from .prompts.library import EnsemblePrompts
|
|
25
|
+
from .sdk import EnsembleSdk
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class EnsembleStages:
|
|
29
|
+
"""Holds one run's collaborators and builds the settings each stage needs."""
|
|
30
|
+
|
|
31
|
+
def __init__(self, sdk: EnsembleSdk, inputs: EnsembleInputs, cwd: Path) -> None:
|
|
32
|
+
# One instance per run, so working directory and caller options cannot drift by stage.
|
|
33
|
+
self.sdk = sdk
|
|
34
|
+
self.inputs = inputs
|
|
35
|
+
self.prompts = EnsemblePrompts()
|
|
36
|
+
self._cwd = cwd
|
|
37
|
+
|
|
38
|
+
def root(self) -> Any:
|
|
39
|
+
# Stage one designs the roster and only reads, so it gets no write access either.
|
|
40
|
+
prompt = self.prompts.planner_system_prompt(self.inputs.roles)
|
|
41
|
+
return self.sdk.root_settings(prompt, RolePlan, self._codex(write=False))
|
|
42
|
+
|
|
43
|
+
def proposal(self, role: GeneratedRole) -> Any:
|
|
44
|
+
# Stage two: read-only, and its structured output is what makes it a proposal.
|
|
45
|
+
prompt = self.prompts.role_system_prompt(role)
|
|
46
|
+
return self.sdk.fork_settings(role.name, prompt, RoleProposal, self._codex(write=False))
|
|
47
|
+
|
|
48
|
+
def selector(self) -> Any:
|
|
49
|
+
# Stage three reads the workspace to check a candidate's premise, but never edits it.
|
|
50
|
+
prompt = self.prompts.selector_system_prompt()
|
|
51
|
+
return self.sdk.fork_settings("selector", prompt, SelectionRound, self._codex(write=False))
|
|
52
|
+
|
|
53
|
+
def implementer(self) -> Any:
|
|
54
|
+
# Stage four is the only bundle in this file that enables workspace writes.
|
|
55
|
+
prompt = self.prompts.implementer_system_prompt()
|
|
56
|
+
return self.sdk.fork_settings("implementer", prompt, None, self._codex(write=True))
|
|
57
|
+
|
|
58
|
+
def _codex(self, *, write: bool) -> Any:
|
|
59
|
+
# Provider settings are built by the sdk module; only the write axis is decided here.
|
|
60
|
+
return self.sdk.codex_settings(self.inputs, self._cwd, write=write)
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"""The persistence primitive: one Codex thread driven through a fixed continuation loop.
|
|
2
|
+
|
|
3
|
+
This module stays free of imports on purpose. `runner` reaches the admission boundary in
|
|
4
|
+
`lib/`, so re-exporting it here would make importing `session` or a prompt drag that along.
|
|
5
|
+
Import the module you actually need.
|
|
6
|
+
"""
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"""Both persistence prompts, as Markdown, plus the loader that fills their placeholders.
|
|
2
|
+
|
|
3
|
+
The `.md` files here are the prompts themselves — authored text, reviewed as prose rather
|
|
4
|
+
than as code. `library.py` holds the only Python in this package. Import it directly; this
|
|
5
|
+
module stays empty so reading a prompt never pulls in the session that sends it.
|
|
6
|
+
"""
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Loads the Markdown prompts in this package and fills their `{{placeholder}}` slots.
|
|
2
|
+
|
|
3
|
+
No prompt text lives here — every sentence an agent reads is in a `.md` file beside this one,
|
|
4
|
+
so a prompt change is a prose diff. This class only reads those files and substitutes values.
|
|
5
|
+
|
|
6
|
+
Substitution is a literal replace rather than `str.format`, because a task may contain braces
|
|
7
|
+
that a format string would try to interpret.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from importlib import resources
|
|
13
|
+
|
|
14
|
+
# The package the `.md` files sit in, named explicitly so resolution does not depend on how
|
|
15
|
+
# this module was imported. They ship in the wheel via `[tool.setuptools.package-data]`.
|
|
16
|
+
_ANCHOR = "vidbyte_cli.services.persistence.prompts"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class PersistencePrompts:
|
|
20
|
+
"""Reads each prompt file once and renders it with the values one run supplies."""
|
|
21
|
+
|
|
22
|
+
def __init__(self) -> None:
|
|
23
|
+
# One cache per session; the files are immutable package data, so reading twice is waste.
|
|
24
|
+
self._cache: dict[str, str] = {}
|
|
25
|
+
|
|
26
|
+
def system_prompt(self) -> str:
|
|
27
|
+
# The standing instruction the thread keeps across every continuation turn.
|
|
28
|
+
return self._read("persistence_system")
|
|
29
|
+
|
|
30
|
+
def turn_prompt(self, original_task: str) -> str:
|
|
31
|
+
# Each continuation restates the exact task, so a long loop cannot drift off it.
|
|
32
|
+
return self._render("persistence_turn", original_task=original_task)
|
|
33
|
+
|
|
34
|
+
def _render(self, name: str, **values: str) -> str:
|
|
35
|
+
# A literal replace, because a task holding braces would break a format string.
|
|
36
|
+
rendered = self._read(name)
|
|
37
|
+
for key, value in values.items():
|
|
38
|
+
rendered = rendered.replace("{{" + key + "}}", value)
|
|
39
|
+
return rendered
|
|
40
|
+
|
|
41
|
+
def _read(self, name: str) -> str:
|
|
42
|
+
# Read through `importlib.resources` so the prompts resolve from the installed wheel.
|
|
43
|
+
if name not in self._cache:
|
|
44
|
+
source = resources.files(_ANCHOR).joinpath(f"{name}.md")
|
|
45
|
+
self._cache[name] = source.read_text(encoding="utf-8")
|
|
46
|
+
return self._cache[name]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Work on the user's task using the tools and context available in this session. Preserve the user's intent and constraints throughout subsequent requests to continue or improve the work. Report what you accomplished accurately, including anything that remains unresolved.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
Very good job, keep working I think you can do a better job.... Revisit the work you have completed and identify the most useful improvements that still serve the original request. Check your assumptions, look for omissions, and verify the parts that need evidence. Improve the result with concrete work wherever you find a meaningful gap. Keep the original scope and constraints in force, and explain any genuine blocker that prevents further progress.
|
|
2
|
+
|
|
3
|
+
Here is the original task in case your forgot {{original_task}}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""The last gate a persistence run passes before its first paid turn.
|
|
2
|
+
|
|
3
|
+
The command buys and verifies the admission; this class re-checks the receipt against the
|
|
4
|
+
plan independently, so a caller that skipped verification still cannot start an agent. It
|
|
5
|
+
holds no endpoints and never touches the network.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from ...lib.errors.failures import RuntimeAdmissionNotVerified
|
|
11
|
+
from ...lib.runtime_primitives.executor import RuntimeExecutor
|
|
12
|
+
from ...types.runtime import PersistenceResult as Result
|
|
13
|
+
from ...types.runtime import PersistenceSettings as Tier
|
|
14
|
+
from ...types.runtime import RuntimeAdmissionVerdict as Verdict
|
|
15
|
+
from ...types.runtime import RuntimeLaunchPlan as Plan
|
|
16
|
+
from .session import PersistentCodexSession as Session
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class PersistenceRunner:
|
|
20
|
+
"""Checks admission at the final boundary before the Codex session can start."""
|
|
21
|
+
|
|
22
|
+
def __init__(self, executor: RuntimeExecutor | None = None) -> None:
|
|
23
|
+
# Shares one verdict policy with every other primitive rather than restating it.
|
|
24
|
+
self._executor = executor or RuntimeExecutor()
|
|
25
|
+
|
|
26
|
+
def run(self, plan: Plan, settings: Tier, session: Session, verdict: Verdict) -> Result:
|
|
27
|
+
# The session cannot run until the exact requested capability has been admitted.
|
|
28
|
+
self._executor.require_verdict(plan, verdict)
|
|
29
|
+
self._require_persistence_plan(plan)
|
|
30
|
+
return session.run(plan, settings)
|
|
31
|
+
|
|
32
|
+
def _require_persistence_plan(self, plan: Plan) -> None:
|
|
33
|
+
# A genuine receipt bought for another product must not open this execution path.
|
|
34
|
+
if plan.capability_id != "runtime.persistence@1" or plan.host.value != "codex":
|
|
35
|
+
raise RuntimeAdmissionNotVerified("persistence_plan_invalid")
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Runs a fixed continuation loop through the SDK's CodexHarnessAgent.
|
|
2
|
+
|
|
3
|
+
The SDK owns transport and thread resumption. This adapter owns exact task input,
|
|
4
|
+
turn limits, progress, and rejection of incomplete or changed-thread results.
|
|
5
|
+
Every sentence a model reads comes from `prompts/`, never from a string literal here.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import asyncio
|
|
11
|
+
from collections.abc import Callable, Mapping
|
|
12
|
+
from typing import TYPE_CHECKING
|
|
13
|
+
|
|
14
|
+
from ...lib.constants.runtime import PersistenceCodexConfig, PersistenceLimit
|
|
15
|
+
from ...lib.constants.runtime import PersistenceProgress as Progress
|
|
16
|
+
from ...lib.errors.failures import PersistenceHostFailed
|
|
17
|
+
from ...types.runtime import PersistenceResult, PersistenceSettings
|
|
18
|
+
from ...types.runtime import RuntimeLaunchPlan as Plan
|
|
19
|
+
from .prompts.library import PersistencePrompts
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from vidbyte.agents.codex import CodexHarnessAgent
|
|
23
|
+
from vidbyte.agents.types import AgentMessage
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class PersistentCodexSession:
|
|
27
|
+
"""One invocation's environment and SDK agent, prepared before paid admission."""
|
|
28
|
+
|
|
29
|
+
def __init__(self, environment: Mapping[str, str], progress: Callable[[str], None]) -> None:
|
|
30
|
+
self._environment = dict(environment)
|
|
31
|
+
self._progress = progress
|
|
32
|
+
self._prompts = PersistencePrompts()
|
|
33
|
+
self._agent: CodexHarnessAgent | None = None
|
|
34
|
+
|
|
35
|
+
def prepare(self, plan: Plan) -> None:
|
|
36
|
+
# Construction validates local SDK settings without starting a paid model turn.
|
|
37
|
+
from vidbyte.agents.codex import CodexHarnessAgent
|
|
38
|
+
from vidbyte.lib.dataclasses.codex import (
|
|
39
|
+
CodexAgentSettings,
|
|
40
|
+
CodexClientSettings,
|
|
41
|
+
CodexHarnessAgentSettings,
|
|
42
|
+
CodexThreadSettings,
|
|
43
|
+
)
|
|
44
|
+
from vidbyte.lib.enums.codex import CodexSandbox
|
|
45
|
+
|
|
46
|
+
client = CodexClientSettings(
|
|
47
|
+
codex_bin=str(plan.executable),
|
|
48
|
+
cwd=str(plan.working_directory),
|
|
49
|
+
env=self._environment,
|
|
50
|
+
config_overrides=tuple(setting.value for setting in PersistenceCodexConfig),
|
|
51
|
+
)
|
|
52
|
+
self._agent = CodexHarnessAgent(
|
|
53
|
+
CodexHarnessAgentSettings(
|
|
54
|
+
name="persistence",
|
|
55
|
+
system_prompt=self._prompts.system_prompt(),
|
|
56
|
+
codex=CodexAgentSettings(
|
|
57
|
+
client=client,
|
|
58
|
+
thread=CodexThreadSettings(sandbox=CodexSandbox.WORKSPACE_WRITE),
|
|
59
|
+
),
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
def run(self, plan: Plan, settings: PersistenceSettings) -> PersistenceResult:
|
|
64
|
+
from vidbyte.lib.errors import CodexAgentError
|
|
65
|
+
|
|
66
|
+
if self._agent is None:
|
|
67
|
+
raise PersistenceHostFailed()
|
|
68
|
+
try:
|
|
69
|
+
return asyncio.run(self._run(plan, settings))
|
|
70
|
+
except (CodexAgentError, TimeoutError) as error:
|
|
71
|
+
# SDK diagnostics may carry task content; only the static CLI failure is public.
|
|
72
|
+
raise PersistenceHostFailed() from error
|
|
73
|
+
|
|
74
|
+
async def _run(self, plan: Plan, settings: PersistenceSettings) -> PersistenceResult:
|
|
75
|
+
continuation = self._prompts.turn_prompt(plan.task)
|
|
76
|
+
self._progress(Progress.STARTING)
|
|
77
|
+
reply = await self._turn(plan.task)
|
|
78
|
+
session_id = self._session_id(reply, "")
|
|
79
|
+
self._progress(Progress.INITIAL_COMPLETE)
|
|
80
|
+
# The chosen strength, not a model's claim of completion, controls the loop.
|
|
81
|
+
for index in range(settings.repeat_count):
|
|
82
|
+
self._progress(self._continuation_progress(index, settings.repeat_count))
|
|
83
|
+
reply = await self._turn(continuation)
|
|
84
|
+
self._session_id(reply, session_id)
|
|
85
|
+
self._progress(Progress.COMPLETE)
|
|
86
|
+
return PersistenceResult(
|
|
87
|
+
session_id=session_id, continuation_turns=settings.repeat_count, text=reply.content
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
async def _turn(self, prompt: str) -> AgentMessage:
|
|
91
|
+
from vidbyte.lib.dataclasses.codex import CodexRunInput
|
|
92
|
+
|
|
93
|
+
if self._agent is None:
|
|
94
|
+
raise PersistenceHostFailed()
|
|
95
|
+
# Timeout cancels arun so the SDK's async client unwinds before the loop can continue.
|
|
96
|
+
async with asyncio.timeout(PersistenceLimit.TURN_TIMEOUT_SECONDS):
|
|
97
|
+
return await self._agent.arun(CodexRunInput.text(prompt))
|
|
98
|
+
|
|
99
|
+
def _session_id(self, reply: AgentMessage, previous: str) -> str:
|
|
100
|
+
data = reply.codex
|
|
101
|
+
if data is None or data.status != "completed" or not data.final_response:
|
|
102
|
+
raise PersistenceHostFailed()
|
|
103
|
+
if not data.thread_id.strip() or (previous and data.thread_id != previous):
|
|
104
|
+
raise PersistenceHostFailed()
|
|
105
|
+
if self._agent is None or self._agent.thread_id != data.thread_id:
|
|
106
|
+
raise PersistenceHostFailed()
|
|
107
|
+
return str(data.thread_id)
|
|
108
|
+
|
|
109
|
+
def _continuation_progress(self, index: int, count: int) -> Progress:
|
|
110
|
+
if index == count - 1:
|
|
111
|
+
return Progress.FINAL
|
|
112
|
+
if index * 3 < count:
|
|
113
|
+
return Progress.EARLY
|
|
114
|
+
if index * 3 < count * 2:
|
|
115
|
+
return Progress.MIDDLE
|
|
116
|
+
return Progress.LATE
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"""Owns the single versioned vocabulary of suggestion categories.
|
|
2
|
+
|
|
3
|
+
The registry maps each accepted identifier to exactly one authored prompt asset.
|
|
4
|
+
Commands, agent context, and result validation all consume this same mapping.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
|
|
11
|
+
SCHEMA_VERSION = 1
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True, slots=True)
|
|
15
|
+
class CategoryDefinition:
|
|
16
|
+
"""One category identifier and its high-level caller-facing summary."""
|
|
17
|
+
|
|
18
|
+
category_id: str
|
|
19
|
+
title: str
|
|
20
|
+
summary: str
|
|
21
|
+
prompt_name: str
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def description(self) -> str:
|
|
25
|
+
"""Keep the public description name readable to existing consumers."""
|
|
26
|
+
return self.summary
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class SuggestionCategories:
|
|
30
|
+
"""Provides the ordered category registry and one-to-one prompt mapping."""
|
|
31
|
+
|
|
32
|
+
def __init__(self) -> None:
|
|
33
|
+
self._definitions = (
|
|
34
|
+
CategoryDefinition(
|
|
35
|
+
"continuation",
|
|
36
|
+
"Continuation",
|
|
37
|
+
"Advance an accepted plan with its next bounded step.",
|
|
38
|
+
"continuation",
|
|
39
|
+
),
|
|
40
|
+
CategoryDefinition(
|
|
41
|
+
"prerequisite",
|
|
42
|
+
"Prerequisite",
|
|
43
|
+
"Create or secure a condition required by intended work.",
|
|
44
|
+
"prerequisite",
|
|
45
|
+
),
|
|
46
|
+
CategoryDefinition(
|
|
47
|
+
"completion",
|
|
48
|
+
"Completion",
|
|
49
|
+
"Close a specific unfinished obligation in the current task.",
|
|
50
|
+
"completion",
|
|
51
|
+
),
|
|
52
|
+
CategoryDefinition(
|
|
53
|
+
"bottleneck",
|
|
54
|
+
"Bottleneck",
|
|
55
|
+
"Relieve the constraint that limits useful progress.",
|
|
56
|
+
"bottleneck",
|
|
57
|
+
),
|
|
58
|
+
CategoryDefinition(
|
|
59
|
+
"verification",
|
|
60
|
+
"Verification",
|
|
61
|
+
"Test a consequential claim before relying on it.",
|
|
62
|
+
"verification",
|
|
63
|
+
),
|
|
64
|
+
CategoryDefinition(
|
|
65
|
+
"experiment",
|
|
66
|
+
"Experiment",
|
|
67
|
+
"Run a bounded test that can change a decision.",
|
|
68
|
+
"experiment",
|
|
69
|
+
),
|
|
70
|
+
CategoryDefinition(
|
|
71
|
+
"investigation",
|
|
72
|
+
"Investigation",
|
|
73
|
+
"Gather the smallest reliable evidence needed for a decision.",
|
|
74
|
+
"investigation",
|
|
75
|
+
),
|
|
76
|
+
CategoryDefinition(
|
|
77
|
+
"alternative",
|
|
78
|
+
"Alternative",
|
|
79
|
+
"Compare a materially different route to the same goal.",
|
|
80
|
+
"alternative",
|
|
81
|
+
),
|
|
82
|
+
CategoryDefinition(
|
|
83
|
+
"simplification",
|
|
84
|
+
"Simplification",
|
|
85
|
+
"Remove complexity while preserving essential value.",
|
|
86
|
+
"simplification",
|
|
87
|
+
),
|
|
88
|
+
CategoryDefinition(
|
|
89
|
+
"stop_or_defer",
|
|
90
|
+
"Stop or Defer",
|
|
91
|
+
"Stop or postpone work whose present value is insufficient.",
|
|
92
|
+
"stop_or_defer",
|
|
93
|
+
),
|
|
94
|
+
CategoryDefinition(
|
|
95
|
+
"risk_prevention",
|
|
96
|
+
"Risk Prevention",
|
|
97
|
+
"Prevent a plausible failure with a proportionate guard.",
|
|
98
|
+
"risk_prevention",
|
|
99
|
+
),
|
|
100
|
+
CategoryDefinition(
|
|
101
|
+
"leverage",
|
|
102
|
+
"Leverage",
|
|
103
|
+
"Create one asset that benefits several credible future tasks.",
|
|
104
|
+
"leverage",
|
|
105
|
+
),
|
|
106
|
+
CategoryDefinition(
|
|
107
|
+
"strategy",
|
|
108
|
+
"Strategy",
|
|
109
|
+
"Choose a broader direction that coordinates several actions.",
|
|
110
|
+
"strategy",
|
|
111
|
+
),
|
|
112
|
+
CategoryDefinition(
|
|
113
|
+
"adjacent_opportunity",
|
|
114
|
+
"Adjacent Opportunity",
|
|
115
|
+
"Capture nearby value enabled by current work.",
|
|
116
|
+
"adjacent_opportunity",
|
|
117
|
+
),
|
|
118
|
+
CategoryDefinition(
|
|
119
|
+
"cross_domain",
|
|
120
|
+
"Cross-Domain",
|
|
121
|
+
"Transfer a useful mechanism from another field.",
|
|
122
|
+
"cross_domain",
|
|
123
|
+
),
|
|
124
|
+
CategoryDefinition(
|
|
125
|
+
"preparation",
|
|
126
|
+
"Preparation",
|
|
127
|
+
"Build readiness for an anticipated event or demand.",
|
|
128
|
+
"preparation",
|
|
129
|
+
),
|
|
130
|
+
CategoryDefinition(
|
|
131
|
+
"coordination",
|
|
132
|
+
"Coordination",
|
|
133
|
+
"Resolve ownership, sequencing, or dependency alignment.",
|
|
134
|
+
"coordination",
|
|
135
|
+
),
|
|
136
|
+
CategoryDefinition(
|
|
137
|
+
"goal_clarification",
|
|
138
|
+
"Goal Clarification",
|
|
139
|
+
"Define the intended outcome and how success will be recognized.",
|
|
140
|
+
"goal_clarification",
|
|
141
|
+
),
|
|
142
|
+
CategoryDefinition(
|
|
143
|
+
"creative_exploration",
|
|
144
|
+
"Creative Exploration",
|
|
145
|
+
"Generate concrete possibilities outside current assumptions.",
|
|
146
|
+
"creative_exploration",
|
|
147
|
+
),
|
|
148
|
+
CategoryDefinition(
|
|
149
|
+
"delegation",
|
|
150
|
+
"Delegation",
|
|
151
|
+
"Move work to the person or agent best placed to carry it.",
|
|
152
|
+
"delegation",
|
|
153
|
+
),
|
|
154
|
+
CategoryDefinition(
|
|
155
|
+
"learning",
|
|
156
|
+
"Learning",
|
|
157
|
+
"Build the smallest useful skill or knowledge for an upcoming task.",
|
|
158
|
+
"learning",
|
|
159
|
+
),
|
|
160
|
+
CategoryDefinition(
|
|
161
|
+
"feedback",
|
|
162
|
+
"Feedback",
|
|
163
|
+
"Seek a specific reaction that could change the work.",
|
|
164
|
+
"feedback",
|
|
165
|
+
),
|
|
166
|
+
CategoryDefinition(
|
|
167
|
+
"reframing",
|
|
168
|
+
"Reframing",
|
|
169
|
+
"Interpret the problem differently to unlock a better next move.",
|
|
170
|
+
"reframing",
|
|
171
|
+
),
|
|
172
|
+
CategoryDefinition(
|
|
173
|
+
"prioritization",
|
|
174
|
+
"Prioritization",
|
|
175
|
+
"Choose what deserves attention among competing commitments.",
|
|
176
|
+
"prioritization",
|
|
177
|
+
),
|
|
178
|
+
CategoryDefinition(
|
|
179
|
+
"immediate_next_steps",
|
|
180
|
+
"Immediate Next Steps",
|
|
181
|
+
"Identify what can be acted on now from the current state.",
|
|
182
|
+
"immediate_next_steps",
|
|
183
|
+
),
|
|
184
|
+
CategoryDefinition(
|
|
185
|
+
"quick_wins",
|
|
186
|
+
"Quick Wins",
|
|
187
|
+
"Find a small, inexpensive action with useful near-term payoff.",
|
|
188
|
+
"quick_wins",
|
|
189
|
+
),
|
|
190
|
+
CategoryDefinition(
|
|
191
|
+
"long_term_directions",
|
|
192
|
+
"Long-Term Directions",
|
|
193
|
+
"Consider capabilities or directions worth pursuing over time.",
|
|
194
|
+
"long_term_directions",
|
|
195
|
+
),
|
|
196
|
+
CategoryDefinition(
|
|
197
|
+
"big_bets",
|
|
198
|
+
"Big Bets",
|
|
199
|
+
"Examine ambitious changes with high upside and meaningful uncertainty.",
|
|
200
|
+
"big_bets",
|
|
201
|
+
),
|
|
202
|
+
CategoryDefinition(
|
|
203
|
+
"business_growth",
|
|
204
|
+
"Business and Growth",
|
|
205
|
+
"Improve reach, sustainability, revenue, or customer value.",
|
|
206
|
+
"business_growth",
|
|
207
|
+
),
|
|
208
|
+
CategoryDefinition(
|
|
209
|
+
"product_experience",
|
|
210
|
+
"Product and Experience",
|
|
211
|
+
"Improve what people can use and how it feels to use it.",
|
|
212
|
+
"product_experience",
|
|
213
|
+
),
|
|
214
|
+
CategoryDefinition(
|
|
215
|
+
"technical_possibilities",
|
|
216
|
+
"Technical Possibilities",
|
|
217
|
+
"Explore what technology could make materially better or possible.",
|
|
218
|
+
"technical_possibilities",
|
|
219
|
+
),
|
|
220
|
+
)
|
|
221
|
+
self._by_id = {item.category_id: item for item in self._definitions}
|
|
222
|
+
|
|
223
|
+
def ids(self) -> tuple[str, ...]:
|
|
224
|
+
"""Return identifiers in stable display and selection order."""
|
|
225
|
+
return tuple(item.category_id for item in self._definitions)
|
|
226
|
+
|
|
227
|
+
def definitions(self) -> tuple[CategoryDefinition, ...]:
|
|
228
|
+
"""Return the immutable registry entries."""
|
|
229
|
+
return self._definitions
|
|
230
|
+
|
|
231
|
+
def is_known(self, category_id: str) -> bool:
|
|
232
|
+
"""Accept only exact registry identifiers."""
|
|
233
|
+
return category_id in self._by_id
|
|
234
|
+
|
|
235
|
+
def require_known(self, category_ids: tuple[str, ...]) -> tuple[str, ...]:
|
|
236
|
+
"""Validate selected identifiers without adding inferred categories."""
|
|
237
|
+
unknown = [item for item in category_ids if item not in self._by_id]
|
|
238
|
+
if unknown:
|
|
239
|
+
raise ValueError(f"unknown suggestion categories: {', '.join(sorted(unknown))}")
|
|
240
|
+
if len(set(category_ids)) != len(category_ids):
|
|
241
|
+
raise ValueError("suggestion categories must not contain duplicates")
|
|
242
|
+
return category_ids
|
|
243
|
+
|
|
244
|
+
def describe(self, category_id: str) -> CategoryDefinition:
|
|
245
|
+
"""Return one already-validated category definition."""
|
|
246
|
+
return self._by_id[category_id]
|
|
247
|
+
|
|
248
|
+
def category_prompt_exists(self, prompt_name: str) -> bool:
|
|
249
|
+
"""Check that one registry entry resolves to a packaged prompt asset."""
|
|
250
|
+
from .prompts.library import SuggestionPrompts
|
|
251
|
+
|
|
252
|
+
try:
|
|
253
|
+
return bool(SuggestionPrompts().category_prompt(prompt_name))
|
|
254
|
+
except (FileNotFoundError, OSError):
|
|
255
|
+
return False
|
|
256
|
+
|
|
257
|
+
def prompt_section(self, category_ids: tuple[str, ...] | None = None) -> str:
|
|
258
|
+
"""Render exactly the selected prompt assets in the selected order."""
|
|
259
|
+
from .prompts.library import SuggestionPrompts
|
|
260
|
+
|
|
261
|
+
selected = (
|
|
262
|
+
self._definitions
|
|
263
|
+
if not category_ids
|
|
264
|
+
else tuple(self._by_id[item] for item in category_ids)
|
|
265
|
+
)
|
|
266
|
+
prompts = SuggestionPrompts()
|
|
267
|
+
return "\n\n".join(prompts.category_prompt(item.prompt_name) for item in selected)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
__all__ = ["SCHEMA_VERSION", "CategoryDefinition", "SuggestionCategories"]
|