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,518 @@
|
|
|
1
|
+
"""Strict contracts shared by the suggestion command and service.
|
|
2
|
+
|
|
3
|
+
The models define the in-process boundary before provider work begins and the
|
|
4
|
+
versioned envelopes emitted afterward. Provider adapters and command rendering
|
|
5
|
+
stay outside this module.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
from collections.abc import Mapping
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from enum import StrEnum
|
|
14
|
+
from typing import Literal
|
|
15
|
+
|
|
16
|
+
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
|
17
|
+
|
|
18
|
+
from .attachments import AttachmentBundle
|
|
19
|
+
|
|
20
|
+
SCHEMA_VERSION = 1
|
|
21
|
+
MAX_CONTEXT_CHARS = 5_000_000
|
|
22
|
+
MAX_AGENT_MESSAGE_CHARS = 2_000
|
|
23
|
+
|
|
24
|
+
SUGGESTIONS_RESULT_KIND = "suggestions.result"
|
|
25
|
+
SUGGESTIONS_HANDOFF_KIND = "suggestions.handoff"
|
|
26
|
+
_FEEDBACK_REASON_SEPARATOR = "\nReason: "
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class SuggestionHorizon(StrEnum):
|
|
30
|
+
"""When a suggestion should become useful to its caller."""
|
|
31
|
+
|
|
32
|
+
NOW = "now"
|
|
33
|
+
NEXT = "next"
|
|
34
|
+
LATER = "later"
|
|
35
|
+
ANY = "any"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class IdeaHorizon(StrEnum):
|
|
39
|
+
"""Horizon value stored on one idea; never the ``any`` filter wildcard."""
|
|
40
|
+
|
|
41
|
+
NOW = "now"
|
|
42
|
+
NEXT = "next"
|
|
43
|
+
LATER = "later"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class IdeaRelationship(StrEnum):
|
|
47
|
+
"""How an idea relates to the caller's stated goal."""
|
|
48
|
+
|
|
49
|
+
DIRECT = "direct"
|
|
50
|
+
ALTERNATIVE = "alternative"
|
|
51
|
+
ADJACENT = "adjacent"
|
|
52
|
+
EXPLORATORY = "exploratory"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class IdeaReadiness(StrEnum):
|
|
56
|
+
"""What must happen before an executor can start the idea."""
|
|
57
|
+
|
|
58
|
+
READY = "ready"
|
|
59
|
+
NEEDS_EVIDENCE = "needs_evidence"
|
|
60
|
+
NEEDS_DECISION = "needs_decision"
|
|
61
|
+
BLOCKED = "blocked"
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class RunStatus(StrEnum):
|
|
65
|
+
"""Terminal state of one suggestion run."""
|
|
66
|
+
|
|
67
|
+
COMPLETE = "complete"
|
|
68
|
+
PARTIAL = "partial"
|
|
69
|
+
NO_SUGGESTIONS = "no_suggestions"
|
|
70
|
+
NEEDS_INPUT = "needs_input"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class StopReason(StrEnum):
|
|
74
|
+
"""Why the workflow stopped when it did."""
|
|
75
|
+
|
|
76
|
+
COMPLETED = "completed"
|
|
77
|
+
COUNT_SHORTFALL = "count_shortfall"
|
|
78
|
+
ROUND_LIMIT = "round_limit"
|
|
79
|
+
TOKEN_LIMIT = "token_limit"
|
|
80
|
+
TIME_LIMIT = "time_limit"
|
|
81
|
+
PROVIDER_FAILED = "provider_failed"
|
|
82
|
+
DRY_RUN = "dry_run"
|
|
83
|
+
PARENT_MESSAGE = "parent_message"
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class SuggestionContextItem(BaseModel):
|
|
87
|
+
"""One labeled piece of caller-supplied context with a stable run-local ref."""
|
|
88
|
+
|
|
89
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
90
|
+
ref: str = Field(min_length=1, max_length=32)
|
|
91
|
+
kind: str = Field(min_length=1, max_length=64)
|
|
92
|
+
label: str = Field(min_length=1, max_length=256)
|
|
93
|
+
description: str = Field(min_length=1, max_length=4096)
|
|
94
|
+
content: str = Field(min_length=1, max_length=MAX_CONTEXT_CHARS)
|
|
95
|
+
source: str = Field(min_length=1, max_length=512)
|
|
96
|
+
caller_supplied: bool = True
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@dataclass(frozen=True, slots=True)
|
|
100
|
+
class SuggestionContextPrimitive:
|
|
101
|
+
"""SDK context primitive for one exact generator or critic context window."""
|
|
102
|
+
|
|
103
|
+
goal: str
|
|
104
|
+
description: str
|
|
105
|
+
items: tuple[SuggestionContextItem, ...] = ()
|
|
106
|
+
selected_categories: str = ""
|
|
107
|
+
kind: str = field(default="suggestion-context", init=False)
|
|
108
|
+
title: str = field(default="Suggestion Agent Context", init=False)
|
|
109
|
+
metadata: Mapping[str, object] = field(default_factory=dict)
|
|
110
|
+
primitive_id: str = field(default="suggestion-context:request", init=False)
|
|
111
|
+
primitive_frozen: bool = field(default=True, init=False)
|
|
112
|
+
|
|
113
|
+
def __post_init__(self) -> None:
|
|
114
|
+
if not isinstance(self.goal, str) or not self.goal.strip():
|
|
115
|
+
raise ValueError("Suggestion context goal must be a non-empty string.")
|
|
116
|
+
if not isinstance(self.description, str) or not self.description.strip():
|
|
117
|
+
raise ValueError("Suggestion context description must be a non-empty string.")
|
|
118
|
+
if not isinstance(self.items, tuple) or any(
|
|
119
|
+
not isinstance(item, SuggestionContextItem) for item in self.items
|
|
120
|
+
):
|
|
121
|
+
raise TypeError("Suggestion context items must be a tuple of SuggestionContextItem.")
|
|
122
|
+
if not isinstance(self.metadata, Mapping):
|
|
123
|
+
raise TypeError("Suggestion context metadata must be a mapping.")
|
|
124
|
+
|
|
125
|
+
def to_context_text(self) -> str:
|
|
126
|
+
sections = [f"Goal: {self.goal}", "", "<Selected Categories>"]
|
|
127
|
+
sections.append(self.selected_categories or "No category was selected.")
|
|
128
|
+
sections.extend(("</Selected Categories>", ""))
|
|
129
|
+
for item in self.items:
|
|
130
|
+
sections.extend(
|
|
131
|
+
(
|
|
132
|
+
f"## [{item.ref}] {item.label} ({item.kind})",
|
|
133
|
+
f"Source: {item.source}",
|
|
134
|
+
item.content,
|
|
135
|
+
"",
|
|
136
|
+
)
|
|
137
|
+
)
|
|
138
|
+
return "\n".join(sections).rstrip()
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class FeedbackType(StrEnum):
|
|
142
|
+
"""The explicit user reaction stored in project memory."""
|
|
143
|
+
|
|
144
|
+
ACCEPTED = "accepted"
|
|
145
|
+
REJECTED = "rejected"
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class SuggestionProjectRecord(BaseModel):
|
|
149
|
+
"""One catalog entry linking a project key to its memory file."""
|
|
150
|
+
|
|
151
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
152
|
+
key: str = Field(min_length=1, max_length=64, pattern=r"^[a-z0-9][a-z0-9_-]{0,63}$")
|
|
153
|
+
title: str = Field(min_length=1, max_length=200)
|
|
154
|
+
description: str = Field(min_length=1, max_length=4000)
|
|
155
|
+
memory_file: str = Field(min_length=1, max_length=256)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class SuggestionProjectCatalog(BaseModel):
|
|
159
|
+
"""Versioned catalog document containing all project summaries."""
|
|
160
|
+
|
|
161
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
162
|
+
schema_version: Literal[1] = 1
|
|
163
|
+
projects: tuple[SuggestionProjectRecord, ...] = ()
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class SuggestionFeedback(BaseModel):
|
|
167
|
+
"""One accepted or rejected suggestion recorded by an explicit user reaction."""
|
|
168
|
+
|
|
169
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
170
|
+
type: FeedbackType
|
|
171
|
+
suggestion: str = Field(min_length=1, max_length=8192)
|
|
172
|
+
reason: str | None = Field(default=None, max_length=8192)
|
|
173
|
+
created_at: str = Field(min_length=1, max_length=64)
|
|
174
|
+
|
|
175
|
+
def context_text(self) -> str:
|
|
176
|
+
# The one rendering of a reaction as run context; suggestion_from_context inverts it,
|
|
177
|
+
# so the label and reason separator are defined together and cannot drift apart.
|
|
178
|
+
reason = f"{_FEEDBACK_REASON_SEPARATOR}{self.reason}" if self.reason else ""
|
|
179
|
+
return f"{self.type.value.title()} suggestion: {self.suggestion}{reason}"
|
|
180
|
+
|
|
181
|
+
@staticmethod
|
|
182
|
+
def suggestion_from_context(text: str) -> str:
|
|
183
|
+
# Recovers the verbatim suggestion so rejected feedback can suppress a repeated idea.
|
|
184
|
+
body = text.split(": ", 1)[1] if ": " in text else text
|
|
185
|
+
return body.split(_FEEDBACK_REASON_SEPARATOR, 1)[0].strip()
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class SuggestionProjectMemory(BaseModel):
|
|
189
|
+
"""Versioned per-project feedback document."""
|
|
190
|
+
|
|
191
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
192
|
+
schema_version: Literal[1] = 1
|
|
193
|
+
project_key: str = Field(min_length=1, max_length=64)
|
|
194
|
+
feedback: tuple[SuggestionFeedback, ...] = ()
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class SuggestionFeedbackCapture(BaseModel):
|
|
198
|
+
"""Deterministic instructions a parent agent can use after explicit feedback."""
|
|
199
|
+
|
|
200
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
201
|
+
project_key: str = Field(min_length=1, max_length=64)
|
|
202
|
+
instruction: str = Field(min_length=1, max_length=1024)
|
|
203
|
+
accept_command: str = Field(min_length=1, max_length=1024)
|
|
204
|
+
reject_command: str = Field(min_length=1, max_length=1024)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class ContextManifestEntry(BaseModel):
|
|
208
|
+
"""What the manifest records about one context item without its body."""
|
|
209
|
+
|
|
210
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
211
|
+
ref: str = Field(min_length=1, max_length=32)
|
|
212
|
+
kind: str = Field(min_length=1, max_length=64)
|
|
213
|
+
source: str = Field(min_length=1, max_length=512)
|
|
214
|
+
chars: int = Field(ge=0, le=MAX_CONTEXT_CHARS)
|
|
215
|
+
sha256: str = Field(min_length=8, max_length=128)
|
|
216
|
+
status: Literal["included", "truncated", "omitted", "not_supplied"] = "included"
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
class SuggestionSettings(BaseModel):
|
|
220
|
+
"""The one validated settings object passed unchanged through the workflow."""
|
|
221
|
+
|
|
222
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
223
|
+
requested_count: int = Field(ge=2, le=15, default=5)
|
|
224
|
+
categories: tuple[str, ...] = ()
|
|
225
|
+
all_categories: bool = False
|
|
226
|
+
extra_compute: bool = False
|
|
227
|
+
horizon: SuggestionHorizon = SuggestionHorizon.ANY
|
|
228
|
+
rounds: int = Field(ge=1, le=8, default=2)
|
|
229
|
+
max_messages: int = Field(ge=0, le=8, default=2)
|
|
230
|
+
provider: str | None = None
|
|
231
|
+
critic_model: str | None = None
|
|
232
|
+
max_output_tokens: int | None = Field(default=None, gt=0, le=5_000_000)
|
|
233
|
+
max_total_tokens: int | None = Field(default=None, gt=0, le=20_000_000)
|
|
234
|
+
timeout_seconds: int | None = Field(default=None, gt=0, le=86_400)
|
|
235
|
+
dry_run: bool = False
|
|
236
|
+
|
|
237
|
+
@model_validator(mode="after")
|
|
238
|
+
def _validate_categories(self) -> SuggestionSettings:
|
|
239
|
+
if self.all_categories and self.categories:
|
|
240
|
+
raise ValueError("all_categories and categories cannot both be selected.")
|
|
241
|
+
return self
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
class SuggestionRequest(BaseModel):
|
|
245
|
+
"""Validated input to one suggestion run, built by the command layer."""
|
|
246
|
+
|
|
247
|
+
model_config = ConfigDict(extra="forbid", frozen=True, arbitrary_types_allowed=True)
|
|
248
|
+
goal: str = Field(min_length=1, max_length=4096)
|
|
249
|
+
context: SuggestionContextPrimitive
|
|
250
|
+
context_manifest: tuple[ContextManifestEntry, ...] = ()
|
|
251
|
+
context_warnings: tuple[str, ...] = ()
|
|
252
|
+
settings: SuggestionSettings
|
|
253
|
+
attachments: AttachmentBundle = Field(default_factory=AttachmentBundle)
|
|
254
|
+
project_key: str | None = Field(default=None, max_length=64)
|
|
255
|
+
prompt_version: str = Field(min_length=1, max_length=64, default="suggestions.v4")
|
|
256
|
+
|
|
257
|
+
@model_validator(mode="after")
|
|
258
|
+
def _context_goal_matches(self) -> SuggestionRequest:
|
|
259
|
+
if self.goal != self.context.goal:
|
|
260
|
+
raise ValueError("Suggestion request goal must match its context primitive goal.")
|
|
261
|
+
return self
|
|
262
|
+
|
|
263
|
+
@property
|
|
264
|
+
def context_items(self) -> tuple[SuggestionContextItem, ...]:
|
|
265
|
+
return self.context.items
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
class SuggestionDraft(BaseModel):
|
|
269
|
+
"""One model-produced candidate before the CLI assigns identity and a handoff."""
|
|
270
|
+
|
|
271
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
272
|
+
idea_id: str | None = Field(default=None, pattern=r"^idea-\d{3}$")
|
|
273
|
+
title: str = Field(min_length=1, max_length=256)
|
|
274
|
+
summary: str = Field(min_length=1, max_length=2048)
|
|
275
|
+
primary_category: str = Field(min_length=1, max_length=64)
|
|
276
|
+
secondary_categories: tuple[str, ...] = ()
|
|
277
|
+
horizon: IdeaHorizon = IdeaHorizon.NEXT
|
|
278
|
+
relationship: IdeaRelationship = IdeaRelationship.DIRECT
|
|
279
|
+
readiness: IdeaReadiness = IdeaReadiness.READY
|
|
280
|
+
why_now: str = Field(min_length=1, max_length=1024)
|
|
281
|
+
expected_benefit: str = Field(min_length=1, max_length=1024)
|
|
282
|
+
evidence_refs: tuple[str, ...] = ()
|
|
283
|
+
assumptions: tuple[str, ...] = ()
|
|
284
|
+
dependencies: tuple[str, ...] = ()
|
|
285
|
+
alternative_to: tuple[str, ...] = ()
|
|
286
|
+
first_action: str = Field(min_length=1, max_length=1024)
|
|
287
|
+
suggested_actions: tuple[str, ...] = Field(min_length=1, max_length=12)
|
|
288
|
+
decision_points: tuple[str, ...] = Field(default=(), max_length=12)
|
|
289
|
+
considerations: tuple[str, ...] = Field(default=(), min_length=8, max_length=10)
|
|
290
|
+
completion_criteria: str = Field(min_length=1, max_length=1024)
|
|
291
|
+
effort_estimate: str = Field(min_length=1, max_length=256)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class SuggestionCandidateBatch(BaseModel):
|
|
295
|
+
"""Structured output requested from the generator for initial and revision turns."""
|
|
296
|
+
|
|
297
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
298
|
+
ideas: tuple[SuggestionDraft, ...] = Field(max_length=30)
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
class SuggestionCriticHandoff(BaseModel):
|
|
302
|
+
"""One general review of the whole candidate slate, handed to the generator."""
|
|
303
|
+
|
|
304
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
305
|
+
handoff: str = Field(
|
|
306
|
+
min_length=1,
|
|
307
|
+
max_length=16384,
|
|
308
|
+
description=(
|
|
309
|
+
"The critic's complete review of the candidate slate, written for the generator "
|
|
310
|
+
"that will refine it. Grade the slate against the general suggestion rubric, name "
|
|
311
|
+
"candidates by identifier where a point concerns them, and cite the context "
|
|
312
|
+
"references behind every factual claim. The generator weighs this handoff with its "
|
|
313
|
+
"own judgment, so explain what is strong, what is weak, and why, rather than "
|
|
314
|
+
"issuing keep, revise, or reject verdicts."
|
|
315
|
+
),
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def _packet(models: tuple[BaseModel, ...]) -> str:
|
|
320
|
+
"""Render one typed model tuple as the compact JSON a model window reads."""
|
|
321
|
+
return json.dumps(
|
|
322
|
+
[model.model_dump(mode="json") for model in models],
|
|
323
|
+
sort_keys=True,
|
|
324
|
+
separators=(",", ":"),
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
@dataclass(frozen=True, slots=True)
|
|
329
|
+
class SuggestionEvidence:
|
|
330
|
+
"""One supplied record as a model sees it: its stable ref, its kind, its body."""
|
|
331
|
+
|
|
332
|
+
ref: str
|
|
333
|
+
kind: str
|
|
334
|
+
content: str
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
@dataclass(frozen=True, slots=True)
|
|
338
|
+
class SuggestionAgentContext:
|
|
339
|
+
"""SDK context primitive holding exactly what one workflow stage may read.
|
|
340
|
+
|
|
341
|
+
Caller-only data has no field here at all, so a stage cannot place a source
|
|
342
|
+
path, a label, a manifest entry, a setting, or workflow state such as rank,
|
|
343
|
+
revision, or handoff into a model window. Candidates travel as the same
|
|
344
|
+
`SuggestionDraft` contract the generator returns, so no parallel projection
|
|
345
|
+
can drift.
|
|
346
|
+
"""
|
|
347
|
+
|
|
348
|
+
description: str
|
|
349
|
+
evidence: tuple[SuggestionEvidence, ...] = ()
|
|
350
|
+
selected_categories: str = ""
|
|
351
|
+
candidates: tuple[SuggestionDraft, ...] = ()
|
|
352
|
+
kind: str = field(default="suggestion-context", init=False)
|
|
353
|
+
title: str = field(default="Suggestion Agent Context", init=False)
|
|
354
|
+
metadata: Mapping[str, object] = field(default_factory=dict, init=False)
|
|
355
|
+
primitive_id: str = field(default="suggestion-context:stage", init=False)
|
|
356
|
+
primitive_frozen: bool = field(default=True, init=False)
|
|
357
|
+
|
|
358
|
+
def __post_init__(self) -> None:
|
|
359
|
+
if not isinstance(self.description, str) or not self.description.strip():
|
|
360
|
+
raise ValueError("Suggestion agent context description must be a non-empty string.")
|
|
361
|
+
|
|
362
|
+
@classmethod
|
|
363
|
+
def for_stage(
|
|
364
|
+
cls,
|
|
365
|
+
context: SuggestionContextPrimitive,
|
|
366
|
+
selected_categories: str,
|
|
367
|
+
candidates: tuple[SuggestionDraft, ...] = (),
|
|
368
|
+
) -> SuggestionAgentContext:
|
|
369
|
+
"""Build one stage window from the caller snapshot without mutating it."""
|
|
370
|
+
return cls(
|
|
371
|
+
description="Stage context holds only evidence, category guidance, and candidates.",
|
|
372
|
+
evidence=tuple(
|
|
373
|
+
SuggestionEvidence(item.ref, item.kind, item.content) for item in context.items
|
|
374
|
+
),
|
|
375
|
+
selected_categories=selected_categories,
|
|
376
|
+
candidates=candidates,
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
def to_context_text(self) -> str:
|
|
380
|
+
# Every stage prompt already states the goal, so this window stays task data only.
|
|
381
|
+
sections = [
|
|
382
|
+
"<Selected Categories>",
|
|
383
|
+
self.selected_categories or "No category was selected.",
|
|
384
|
+
"</Selected Categories>",
|
|
385
|
+
"",
|
|
386
|
+
]
|
|
387
|
+
for item in self.evidence:
|
|
388
|
+
sections.extend((f"## [{item.ref}] {item.kind}", item.content, ""))
|
|
389
|
+
if self.candidates:
|
|
390
|
+
sections.extend(("<Candidates>", _packet(self.candidates), "</Candidates>"))
|
|
391
|
+
return "\n".join(sections).rstrip()
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
class SuggestionHandoffEvidence(BaseModel):
|
|
395
|
+
"""One context record embedded in a final action handoff."""
|
|
396
|
+
|
|
397
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
398
|
+
ref: str = Field(min_length=1, max_length=32)
|
|
399
|
+
source: str = Field(min_length=1, max_length=512)
|
|
400
|
+
content: str = Field(min_length=1, max_length=4096)
|
|
401
|
+
relevance: str = Field(min_length=1, max_length=1024)
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
class SuggestionHandoff(BaseModel):
|
|
405
|
+
"""Action-centered packet for evaluating and executing one selected idea."""
|
|
406
|
+
|
|
407
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
408
|
+
handoff_version: Literal[1] = 1
|
|
409
|
+
idea_id: str = Field(min_length=1, max_length=64)
|
|
410
|
+
idea_revision: int = Field(ge=1)
|
|
411
|
+
original_goal: str = Field(min_length=1, max_length=4096)
|
|
412
|
+
title: str = Field(min_length=1, max_length=256)
|
|
413
|
+
summary: str = Field(min_length=1, max_length=2048)
|
|
414
|
+
suggested_actions: tuple[str, ...] = Field(min_length=1, max_length=12)
|
|
415
|
+
decisions_along_way: tuple[str, ...] = Field(default=(), max_length=12)
|
|
416
|
+
considerations: tuple[str, ...] = Field(default=(), min_length=8, max_length=10)
|
|
417
|
+
evidence: tuple[SuggestionHandoffEvidence, ...] = ()
|
|
418
|
+
completion_checks: tuple[str, ...] = Field(min_length=1, max_length=12)
|
|
419
|
+
dependencies: tuple[str, ...] = ()
|
|
420
|
+
warnings: tuple[str, ...] = ()
|
|
421
|
+
forbidden_actions: tuple[str, ...] = ()
|
|
422
|
+
authority: Literal["not_granted_by_this_handoff"] = "not_granted_by_this_handoff"
|
|
423
|
+
stop_conditions: tuple[str, ...] = Field(min_length=1)
|
|
424
|
+
return_report: str = Field(min_length=1, max_length=2048)
|
|
425
|
+
execution_prompt: str = Field(min_length=1, max_length=16384)
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
class SuggestionIdea(BaseModel):
|
|
429
|
+
"""One ranked suggestion with its deterministic handoff."""
|
|
430
|
+
|
|
431
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
432
|
+
id: str = Field(pattern=r"^idea-\d{3}$")
|
|
433
|
+
revision: int = Field(ge=1)
|
|
434
|
+
rank: int = Field(ge=1)
|
|
435
|
+
title: str = Field(min_length=1, max_length=256)
|
|
436
|
+
summary: str = Field(min_length=1, max_length=2048)
|
|
437
|
+
primary_category: str = Field(min_length=1, max_length=64)
|
|
438
|
+
secondary_categories: tuple[str, ...] = ()
|
|
439
|
+
horizon: IdeaHorizon = IdeaHorizon.NEXT
|
|
440
|
+
relationship: IdeaRelationship = IdeaRelationship.DIRECT
|
|
441
|
+
readiness: IdeaReadiness = IdeaReadiness.READY
|
|
442
|
+
why_now: str = Field(min_length=1, max_length=1024)
|
|
443
|
+
expected_benefit: str = Field(min_length=1, max_length=1024)
|
|
444
|
+
evidence_refs: tuple[str, ...] = ()
|
|
445
|
+
assumptions: tuple[str, ...] = ()
|
|
446
|
+
dependencies: tuple[str, ...] = ()
|
|
447
|
+
alternative_to: tuple[str, ...] = ()
|
|
448
|
+
first_action: str = Field(min_length=1, max_length=1024)
|
|
449
|
+
suggested_actions: tuple[str, ...] = Field(min_length=1, max_length=12)
|
|
450
|
+
decision_points: tuple[str, ...] = Field(default=(), max_length=12)
|
|
451
|
+
considerations: tuple[str, ...] = Field(default=(), min_length=8, max_length=10)
|
|
452
|
+
completion_criteria: str = Field(min_length=1, max_length=1024)
|
|
453
|
+
effort_estimate: str = Field(min_length=1, max_length=256)
|
|
454
|
+
handoff: SuggestionHandoff
|
|
455
|
+
|
|
456
|
+
def to_draft(self) -> SuggestionDraft:
|
|
457
|
+
"""Project this reviewed idea back to the candidate contract agents reason over."""
|
|
458
|
+
# Identity stays as idea_id; CLI-owned workflow fields stay behind.
|
|
459
|
+
values = self.model_dump(exclude={"id", "revision", "rank", "handoff"})
|
|
460
|
+
return SuggestionDraft.model_validate({**values, "idea_id": self.id})
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
class SuggestionResult(BaseModel):
|
|
464
|
+
"""Whole validated outcome of one run, including shortfalls and usage."""
|
|
465
|
+
|
|
466
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
467
|
+
run_id: str = Field(min_length=1, max_length=64)
|
|
468
|
+
status: RunStatus = RunStatus.COMPLETE
|
|
469
|
+
goal: str = Field(min_length=1, max_length=4096)
|
|
470
|
+
project_key: str | None = Field(default=None, max_length=64)
|
|
471
|
+
requested_count: int = Field(ge=2, le=15)
|
|
472
|
+
returned_count: int = Field(ge=0, le=15)
|
|
473
|
+
settings: SuggestionSettings
|
|
474
|
+
context_manifest: tuple[ContextManifestEntry, ...] = ()
|
|
475
|
+
ideas: tuple[SuggestionIdea, ...] = ()
|
|
476
|
+
category_coverage: dict[str, int] = Field(default_factory=dict)
|
|
477
|
+
missing_context: tuple[str, ...] = ()
|
|
478
|
+
warnings: tuple[str, ...] = ()
|
|
479
|
+
usage: dict[str, int] = Field(default_factory=dict)
|
|
480
|
+
stop_reason: StopReason = StopReason.COMPLETED
|
|
481
|
+
parent_message: str | None = Field(default=None, max_length=MAX_AGENT_MESSAGE_CHARS)
|
|
482
|
+
feedback_capture: SuggestionFeedbackCapture | None = None
|
|
483
|
+
prompt_version: str = Field(min_length=1, max_length=64, default="suggestions.v4")
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
__all__ = [
|
|
487
|
+
"ContextManifestEntry",
|
|
488
|
+
"FeedbackType",
|
|
489
|
+
"IdeaHorizon",
|
|
490
|
+
"IdeaReadiness",
|
|
491
|
+
"IdeaRelationship",
|
|
492
|
+
"MAX_AGENT_MESSAGE_CHARS",
|
|
493
|
+
"MAX_CONTEXT_CHARS",
|
|
494
|
+
"RunStatus",
|
|
495
|
+
"SCHEMA_VERSION",
|
|
496
|
+
"SUGGESTIONS_HANDOFF_KIND",
|
|
497
|
+
"SUGGESTIONS_RESULT_KIND",
|
|
498
|
+
"StopReason",
|
|
499
|
+
"SuggestionAgentContext",
|
|
500
|
+
"SuggestionCandidateBatch",
|
|
501
|
+
"SuggestionContextItem",
|
|
502
|
+
"SuggestionContextPrimitive",
|
|
503
|
+
"SuggestionCriticHandoff",
|
|
504
|
+
"SuggestionDraft",
|
|
505
|
+
"SuggestionFeedback",
|
|
506
|
+
"SuggestionFeedbackCapture",
|
|
507
|
+
"SuggestionEvidence",
|
|
508
|
+
"SuggestionHandoff",
|
|
509
|
+
"SuggestionHandoffEvidence",
|
|
510
|
+
"SuggestionHorizon",
|
|
511
|
+
"SuggestionIdea",
|
|
512
|
+
"SuggestionProjectCatalog",
|
|
513
|
+
"SuggestionProjectMemory",
|
|
514
|
+
"SuggestionProjectRecord",
|
|
515
|
+
"SuggestionRequest",
|
|
516
|
+
"SuggestionResult",
|
|
517
|
+
"SuggestionSettings",
|
|
518
|
+
]
|