pawly 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.
- pawly/__init__.py +154 -0
- pawly/__pycache__/__init__.cpython-311.pyc +0 -0
- pawly/__pycache__/__init__.cpython-313.pyc +0 -0
- pawly/__pycache__/action_selection.cpython-311.pyc +0 -0
- pawly/__pycache__/action_selection.cpython-313.pyc +0 -0
- pawly/__pycache__/api.cpython-311.pyc +0 -0
- pawly/__pycache__/api.cpython-313.pyc +0 -0
- pawly/__pycache__/contracts.cpython-311.pyc +0 -0
- pawly/__pycache__/contracts.cpython-313.pyc +0 -0
- pawly/__pycache__/decision_engine.cpython-311.pyc +0 -0
- pawly/__pycache__/decision_engine.cpython-313.pyc +0 -0
- pawly/__pycache__/pawprint_loader.cpython-311.pyc +0 -0
- pawly/__pycache__/pawprint_loader.cpython-313.pyc +0 -0
- pawly/__pycache__/protected_oss.cpython-311.pyc +0 -0
- pawly/__pycache__/protected_oss.cpython-313.pyc +0 -0
- pawly/__pycache__/runtime.cpython-311.pyc +0 -0
- pawly/__pycache__/runtime.cpython-313.pyc +0 -0
- pawly/__pycache__/runtime_bootstrap.cpython-311.pyc +0 -0
- pawly/__pycache__/runtime_bootstrap.cpython-313.pyc +0 -0
- pawly/__pycache__/runtime_decision.cpython-311.pyc +0 -0
- pawly/__pycache__/runtime_decision.cpython-313.pyc +0 -0
- pawly/__pycache__/runtime_execute.cpython-311.pyc +0 -0
- pawly/__pycache__/runtime_execute.cpython-313.pyc +0 -0
- pawly/__pycache__/runtime_flow.cpython-311.pyc +0 -0
- pawly/__pycache__/runtime_flow.cpython-313.pyc +0 -0
- pawly/__pycache__/runtime_ids.cpython-311.pyc +0 -0
- pawly/__pycache__/runtime_ids.cpython-313.pyc +0 -0
- pawly/__pycache__/runtime_report.cpython-311.pyc +0 -0
- pawly/__pycache__/runtime_report.cpython-313.pyc +0 -0
- pawly/__pycache__/runtime_request.cpython-311.pyc +0 -0
- pawly/__pycache__/runtime_request.cpython-313.pyc +0 -0
- pawly/__pycache__/runtime_result.cpython-311.pyc +0 -0
- pawly/__pycache__/runtime_result.cpython-313.pyc +0 -0
- pawly/__pycache__/runtime_scoring.cpython-311.pyc +0 -0
- pawly/__pycache__/runtime_scoring.cpython-313.pyc +0 -0
- pawly/__pycache__/shield.cpython-311.pyc +0 -0
- pawly/__pycache__/shield.cpython-313.pyc +0 -0
- pawly/__pycache__/skill_registry.cpython-311.pyc +0 -0
- pawly/__pycache__/skill_registry.cpython-313.pyc +0 -0
- pawly/__pycache__/task_request.cpython-311.pyc +0 -0
- pawly/__pycache__/task_request.cpython-313.pyc +0 -0
- pawly/__pycache__/types.cpython-311.pyc +0 -0
- pawly/__pycache__/types.cpython-313.pyc +0 -0
- pawly/action_selection.py +64 -0
- pawly/adapters/__init__.py +25 -0
- pawly/adapters/__pycache__/__init__.cpython-311.pyc +0 -0
- pawly/adapters/__pycache__/__init__.cpython-313.pyc +0 -0
- pawly/adapters/__pycache__/claude_skills.cpython-311.pyc +0 -0
- pawly/adapters/__pycache__/claude_skills.cpython-313.pyc +0 -0
- pawly/adapters/__pycache__/openai_agents.cpython-311.pyc +0 -0
- pawly/adapters/__pycache__/openai_agents.cpython-313.pyc +0 -0
- pawly/adapters/claude_skills.py +210 -0
- pawly/adapters/openai_agents.py +208 -0
- pawly/api.py +57 -0
- pawly/approval/__init__.py +18 -0
- pawly/approval/__pycache__/__init__.cpython-311.pyc +0 -0
- pawly/approval/__pycache__/__init__.cpython-313.pyc +0 -0
- pawly/approval/__pycache__/callback.cpython-311.pyc +0 -0
- pawly/approval/__pycache__/callback.cpython-313.pyc +0 -0
- pawly/approval/__pycache__/handler.cpython-311.pyc +0 -0
- pawly/approval/__pycache__/handler.cpython-313.pyc +0 -0
- pawly/approval/__pycache__/models.cpython-311.pyc +0 -0
- pawly/approval/__pycache__/models.cpython-313.pyc +0 -0
- pawly/approval/__pycache__/queue.cpython-311.pyc +0 -0
- pawly/approval/__pycache__/queue.cpython-313.pyc +0 -0
- pawly/approval/__pycache__/router.cpython-311.pyc +0 -0
- pawly/approval/__pycache__/router.cpython-313.pyc +0 -0
- pawly/approval/__pycache__/timeout.cpython-311.pyc +0 -0
- pawly/approval/__pycache__/timeout.cpython-313.pyc +0 -0
- pawly/approval/callback.py +16 -0
- pawly/approval/handler.py +34 -0
- pawly/approval/models.py +119 -0
- pawly/approval/queue.py +109 -0
- pawly/approval/router.py +66 -0
- pawly/approval/timeout.py +18 -0
- pawly/audit/__pycache__/diff.cpython-311.pyc +0 -0
- pawly/audit/__pycache__/diff.cpython-313.pyc +0 -0
- pawly/audit/__pycache__/events.cpython-311.pyc +0 -0
- pawly/audit/__pycache__/events.cpython-313.pyc +0 -0
- pawly/audit/__pycache__/ledger.cpython-311.pyc +0 -0
- pawly/audit/__pycache__/ledger.cpython-313.pyc +0 -0
- pawly/audit/__pycache__/replay.cpython-311.pyc +0 -0
- pawly/audit/__pycache__/replay.cpython-313.pyc +0 -0
- pawly/audit/diff.py +24 -0
- pawly/audit/events.py +156 -0
- pawly/audit/ledger.py +39 -0
- pawly/audit/replay.py +45 -0
- pawly/backends/__init__.py +39 -0
- pawly/backends/__pycache__/__init__.cpython-311.pyc +0 -0
- pawly/backends/__pycache__/__init__.cpython-313.pyc +0 -0
- pawly/backends/__pycache__/approval.cpython-311.pyc +0 -0
- pawly/backends/__pycache__/approval.cpython-313.pyc +0 -0
- pawly/backends/__pycache__/audit.cpython-311.pyc +0 -0
- pawly/backends/__pycache__/audit.cpython-313.pyc +0 -0
- pawly/backends/__pycache__/reviewer.cpython-311.pyc +0 -0
- pawly/backends/__pycache__/reviewer.cpython-313.pyc +0 -0
- pawly/backends/__pycache__/risk.cpython-311.pyc +0 -0
- pawly/backends/__pycache__/risk.cpython-313.pyc +0 -0
- pawly/backends/approval.py +85 -0
- pawly/backends/audit.py +189 -0
- pawly/backends/reviewer.py +127 -0
- pawly/backends/risk.py +71 -0
- pawly/budget/__pycache__/checker.cpython-311.pyc +0 -0
- pawly/budget/__pycache__/checker.cpython-313.pyc +0 -0
- pawly/budget/__pycache__/state.cpython-311.pyc +0 -0
- pawly/budget/__pycache__/state.cpython-313.pyc +0 -0
- pawly/budget/checker.py +37 -0
- pawly/budget/state.py +15 -0
- pawly/cli.py +44 -0
- pawly/contracts.py +153 -0
- pawly/decision_engine.py +6 -0
- pawly/escalation/__pycache__/patterns.cpython-311.pyc +0 -0
- pawly/escalation/__pycache__/patterns.cpython-313.pyc +0 -0
- pawly/escalation/patterns.py +33 -0
- pawly/gateway/__init__.py +4 -0
- pawly/gateway/__pycache__/__init__.cpython-311.pyc +0 -0
- pawly/gateway/__pycache__/__init__.cpython-313.pyc +0 -0
- pawly/gateway/__pycache__/adapter_support.cpython-311.pyc +0 -0
- pawly/gateway/__pycache__/adapter_support.cpython-313.pyc +0 -0
- pawly/gateway/__pycache__/protocol.cpython-311.pyc +0 -0
- pawly/gateway/__pycache__/protocol.cpython-313.pyc +0 -0
- pawly/gateway/__pycache__/result.cpython-311.pyc +0 -0
- pawly/gateway/__pycache__/result.cpython-313.pyc +0 -0
- pawly/gateway/__pycache__/wrapper.cpython-311.pyc +0 -0
- pawly/gateway/__pycache__/wrapper.cpython-313.pyc +0 -0
- pawly/gateway/adapter_support.py +56 -0
- pawly/gateway/protocol.py +24 -0
- pawly/gateway/result.py +67 -0
- pawly/gateway/wrapper.py +273 -0
- pawly/loader/__pycache__/schema_loader.cpython-311.pyc +0 -0
- pawly/loader/__pycache__/schema_loader.cpython-313.pyc +0 -0
- pawly/loader/__pycache__/yaml_loader.cpython-311.pyc +0 -0
- pawly/loader/__pycache__/yaml_loader.cpython-313.pyc +0 -0
- pawly/loader/schema_loader.py +51 -0
- pawly/loader/yaml_loader.py +164 -0
- pawly/memory/__pycache__/store.cpython-311.pyc +0 -0
- pawly/memory/__pycache__/store.cpython-313.pyc +0 -0
- pawly/memory/__pycache__/tiers.cpython-311.pyc +0 -0
- pawly/memory/__pycache__/tiers.cpython-313.pyc +0 -0
- pawly/memory/store.py +23 -0
- pawly/memory/tiers.py +9 -0
- pawly/middleware/__init__.py +1 -0
- pawly/middleware/__pycache__/__init__.cpython-311.pyc +0 -0
- pawly/middleware/__pycache__/__init__.cpython-313.pyc +0 -0
- pawly/middleware/__pycache__/hooks.cpython-311.pyc +0 -0
- pawly/middleware/__pycache__/hooks.cpython-313.pyc +0 -0
- pawly/middleware/hooks.py +20 -0
- pawly/pawprint_loader.py +301 -0
- pawly/performance/__pycache__/metrics.cpython-311.pyc +0 -0
- pawly/performance/__pycache__/metrics.cpython-313.pyc +0 -0
- pawly/performance/__pycache__/report.cpython-311.pyc +0 -0
- pawly/performance/__pycache__/report.cpython-313.pyc +0 -0
- pawly/performance/metrics.py +48 -0
- pawly/performance/report.py +44 -0
- pawly/policy/__init__.py +15 -0
- pawly/policy/__pycache__/__init__.cpython-311.pyc +0 -0
- pawly/policy/__pycache__/__init__.cpython-313.pyc +0 -0
- pawly/policy/__pycache__/base.cpython-311.pyc +0 -0
- pawly/policy/__pycache__/base.cpython-313.pyc +0 -0
- pawly/policy/__pycache__/heuristic.cpython-311.pyc +0 -0
- pawly/policy/__pycache__/heuristic.cpython-313.pyc +0 -0
- pawly/policy/__pycache__/resolve.cpython-311.pyc +0 -0
- pawly/policy/__pycache__/resolve.cpython-313.pyc +0 -0
- pawly/policy/base.py +84 -0
- pawly/policy/cloud.py +18 -0
- pawly/policy/heuristic.py +141 -0
- pawly/policy/resolve.py +60 -0
- pawly/policy_engine/__pycache__/decision.cpython-311.pyc +0 -0
- pawly/policy_engine/__pycache__/decision.cpython-313.pyc +0 -0
- pawly/policy_engine/__pycache__/engine.cpython-311.pyc +0 -0
- pawly/policy_engine/__pycache__/engine.cpython-313.pyc +0 -0
- pawly/policy_engine/__pycache__/models.cpython-311.pyc +0 -0
- pawly/policy_engine/__pycache__/models.cpython-313.pyc +0 -0
- pawly/policy_engine/__pycache__/runtime_overlay.cpython-311.pyc +0 -0
- pawly/policy_engine/__pycache__/runtime_overlay.cpython-313.pyc +0 -0
- pawly/policy_engine/decision.py +40 -0
- pawly/policy_engine/engine.py +152 -0
- pawly/policy_engine/models.py +62 -0
- pawly/policy_engine/risk.py +24 -0
- pawly/policy_engine/runtime_overlay.py +37 -0
- pawly/protected_oss.py +168 -0
- pawly/runtime.py +1004 -0
- pawly/runtime_bootstrap.py +104 -0
- pawly/runtime_decision.py +52 -0
- pawly/runtime_execute.py +59 -0
- pawly/runtime_flow.py +50 -0
- pawly/runtime_ids.py +19 -0
- pawly/runtime_report.py +18 -0
- pawly/runtime_request.py +23 -0
- pawly/runtime_result.py +142 -0
- pawly/runtime_scoring.py +25 -0
- pawly/schemas/decision.schema.json +38 -0
- pawly/schemas/intent.schema.json +33 -0
- pawly/schemas/report.schema.json +36 -0
- pawly/shield.py +436 -0
- pawly/skill_registry.py +31 -0
- pawly/task_request.py +27 -0
- pawly/types.py +15 -0
- pawly/validator/__pycache__/validator.cpython-311.pyc +0 -0
- pawly/validator/__pycache__/validator.cpython-313.pyc +0 -0
- pawly/validator/validator.py +177 -0
- pawly-0.1.0.dist-info/METADATA +7 -0
- pawly-0.1.0.dist-info/RECORD +206 -0
- pawly-0.1.0.dist-info/WHEEL +4 -0
- pawly-0.1.0.dist-info/entry_points.txt +2 -0
- pawly-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any, Literal
|
|
6
|
+
|
|
7
|
+
from pawly.backends.audit import AuditSink, build_default_audit_sink
|
|
8
|
+
from pawly.backends.reviewer import ReviewerPolicy
|
|
9
|
+
from pawly.backends.risk import RiskProvider
|
|
10
|
+
from pawly.budget.state import BudgetState
|
|
11
|
+
from pawly.memory.store import MemoryStore
|
|
12
|
+
from pawly.middleware.hooks import HookRegistry
|
|
13
|
+
from pawly.pawprint_loader import PawprintConfig, load_pawprint_file
|
|
14
|
+
from pawly.policy import resolve_action_routing_policies, resolve_reviewer_policy, resolve_reviewer_selection
|
|
15
|
+
from pawly.policy.base import Policy
|
|
16
|
+
from pawly.protected_oss import ProtectedAuditRedactingSink, is_protected_skill
|
|
17
|
+
from pawly.runtime_ids import RuntimeIdSequence
|
|
18
|
+
from pawly.validator.validator import PawprintValidator
|
|
19
|
+
|
|
20
|
+
ScoringPolicyFallbackMode = Literal["review", "heuristic", "deny"]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(slots=True)
|
|
24
|
+
class RuntimeConfig:
|
|
25
|
+
agent_path: Path
|
|
26
|
+
raw_pawprint_config: dict
|
|
27
|
+
pawprint_config: PawprintConfig
|
|
28
|
+
reviewer_name: str
|
|
29
|
+
reviewer_policy: ReviewerPolicy
|
|
30
|
+
local_scoring_policy: Policy
|
|
31
|
+
scoring_policy: Policy
|
|
32
|
+
fallback_scoring_policy: Policy
|
|
33
|
+
scoring_policy_fallback_mode: ScoringPolicyFallbackMode
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass(slots=True)
|
|
37
|
+
class RuntimeServices:
|
|
38
|
+
audit_sink: AuditSink
|
|
39
|
+
audit_ledger: object
|
|
40
|
+
validator: PawprintValidator
|
|
41
|
+
memory_store: MemoryStore
|
|
42
|
+
hooks: HookRegistry
|
|
43
|
+
budget_state: BudgetState = field(default_factory=BudgetState)
|
|
44
|
+
ids: RuntimeIdSequence = field(default_factory=RuntimeIdSequence)
|
|
45
|
+
decisions: list[dict[str, Any]] = field(default_factory=list)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass(slots=True)
|
|
49
|
+
class RuntimeBootstrap:
|
|
50
|
+
config: RuntimeConfig
|
|
51
|
+
services: RuntimeServices
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def bootstrap_runtime(
|
|
55
|
+
*,
|
|
56
|
+
agent_path: str | Path,
|
|
57
|
+
audit_path: str | Path | None,
|
|
58
|
+
policy: str,
|
|
59
|
+
policy_impl: ReviewerPolicy | None,
|
|
60
|
+
risk_provider: RiskProvider | None,
|
|
61
|
+
audit_sink: AuditSink | None,
|
|
62
|
+
scoring_policy_fallback_mode: ScoringPolicyFallbackMode,
|
|
63
|
+
scoring_policy: Policy | str | None,
|
|
64
|
+
reviewer: str | None,
|
|
65
|
+
reviewer_backend: ReviewerPolicy | None,
|
|
66
|
+
) -> RuntimeBootstrap:
|
|
67
|
+
resolved_agent_path = Path(agent_path)
|
|
68
|
+
validator = PawprintValidator()
|
|
69
|
+
loaded_pawprint = load_pawprint_file(resolved_agent_path, validator)
|
|
70
|
+
|
|
71
|
+
selected_policy, selected_policy_impl = resolve_reviewer_selection(
|
|
72
|
+
policy=policy,
|
|
73
|
+
policy_impl=policy_impl,
|
|
74
|
+
reviewer=reviewer,
|
|
75
|
+
reviewer_backend=reviewer_backend,
|
|
76
|
+
)
|
|
77
|
+
local_scoring_policy, scoring_policy_impl, fallback_scoring_policy = resolve_action_routing_policies(scoring_policy)
|
|
78
|
+
resolved_audit_sink = audit_sink or build_default_audit_sink(audit_path)
|
|
79
|
+
if is_protected_skill(loaded_pawprint.config):
|
|
80
|
+
resolved_audit_sink = ProtectedAuditRedactingSink(resolved_audit_sink, loaded_pawprint.config)
|
|
81
|
+
return RuntimeBootstrap(
|
|
82
|
+
config=RuntimeConfig(
|
|
83
|
+
agent_path=resolved_agent_path,
|
|
84
|
+
raw_pawprint_config=loaded_pawprint.raw_document,
|
|
85
|
+
pawprint_config=loaded_pawprint.config,
|
|
86
|
+
reviewer_name=selected_policy,
|
|
87
|
+
reviewer_policy=resolve_reviewer_policy(
|
|
88
|
+
selected_policy,
|
|
89
|
+
policy_impl=selected_policy_impl,
|
|
90
|
+
risk_provider=risk_provider,
|
|
91
|
+
),
|
|
92
|
+
local_scoring_policy=local_scoring_policy,
|
|
93
|
+
scoring_policy=scoring_policy_impl,
|
|
94
|
+
fallback_scoring_policy=fallback_scoring_policy,
|
|
95
|
+
scoring_policy_fallback_mode=scoring_policy_fallback_mode,
|
|
96
|
+
),
|
|
97
|
+
services=RuntimeServices(
|
|
98
|
+
audit_sink=resolved_audit_sink,
|
|
99
|
+
audit_ledger=getattr(resolved_audit_sink, "ledger", resolved_audit_sink),
|
|
100
|
+
validator=validator,
|
|
101
|
+
memory_store=MemoryStore("none"),
|
|
102
|
+
hooks=HookRegistry(),
|
|
103
|
+
),
|
|
104
|
+
)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
from pawly.contracts import Decision
|
|
6
|
+
from pawly.backends.reviewer import ReviewerPolicy, evaluate_reviewer_policy
|
|
7
|
+
from pawly.budget.checker import BudgetResult, check_budget
|
|
8
|
+
from pawly.budget.state import BudgetState
|
|
9
|
+
from pawly.pawprint_loader import PawprintConfig
|
|
10
|
+
from pawly.policy_engine.models import PolicyEvaluation
|
|
11
|
+
from pawly.policy_engine.runtime_overlay import apply_runtime_overlays
|
|
12
|
+
from pawly.types import Intent
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(slots=True)
|
|
16
|
+
class RuntimeDecisionState:
|
|
17
|
+
policy_evaluation: PolicyEvaluation
|
|
18
|
+
budget_result: BudgetResult
|
|
19
|
+
decision: Decision
|
|
20
|
+
runtime_overlays: dict[str, object]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def evaluate_core_policy(
|
|
24
|
+
policy: ReviewerPolicy,
|
|
25
|
+
*,
|
|
26
|
+
intent: Intent,
|
|
27
|
+
pawprint: PawprintConfig,
|
|
28
|
+
) -> PolicyEvaluation:
|
|
29
|
+
return evaluate_reviewer_policy(policy, intent, pawprint)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def evaluate_runtime_decision(
|
|
33
|
+
*,
|
|
34
|
+
policy: ReviewerPolicy,
|
|
35
|
+
intent: Intent,
|
|
36
|
+
pawprint: PawprintConfig,
|
|
37
|
+
raw_pawprint_config: dict,
|
|
38
|
+
budget_state: BudgetState,
|
|
39
|
+
) -> RuntimeDecisionState:
|
|
40
|
+
policy_evaluation = evaluate_core_policy(
|
|
41
|
+
policy,
|
|
42
|
+
intent=intent,
|
|
43
|
+
pawprint=pawprint,
|
|
44
|
+
)
|
|
45
|
+
budget_result = check_budget(raw_pawprint_config, budget_state, intent)
|
|
46
|
+
decision, runtime_overlays = apply_runtime_overlays(policy_evaluation, budget_result)
|
|
47
|
+
return RuntimeDecisionState(
|
|
48
|
+
policy_evaluation=policy_evaluation,
|
|
49
|
+
budget_result=budget_result,
|
|
50
|
+
decision=decision,
|
|
51
|
+
runtime_overlays=runtime_overlays,
|
|
52
|
+
)
|
pawly/runtime_execute.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pawly.contracts import Intent
|
|
4
|
+
from pawly.loader.schema_loader import load_pawprint_version
|
|
5
|
+
from pawly.protected_oss import apply_extraction_guardrail
|
|
6
|
+
from pawly.runtime_decision import evaluate_runtime_decision
|
|
7
|
+
from pawly.runtime_bootstrap import RuntimeConfig, RuntimeServices
|
|
8
|
+
from pawly.runtime_flow import (
|
|
9
|
+
build_before_hook_payload,
|
|
10
|
+
finalize_runtime_artifacts,
|
|
11
|
+
remember_allowed_decision,
|
|
12
|
+
validate_intent_or_raise,
|
|
13
|
+
)
|
|
14
|
+
from pawly.runtime_result import RuntimeDecisionResult, build_runtime_decision_artifacts
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def evaluate_runtime_intent(
|
|
18
|
+
*,
|
|
19
|
+
config: RuntimeConfig,
|
|
20
|
+
services: RuntimeServices,
|
|
21
|
+
intent: Intent,
|
|
22
|
+
) -> RuntimeDecisionResult:
|
|
23
|
+
validate_intent_or_raise(services.validator, intent)
|
|
24
|
+
services.hooks.run_before(build_before_hook_payload(intent, config.pawprint_config.id))
|
|
25
|
+
|
|
26
|
+
decision_state = evaluate_runtime_decision(
|
|
27
|
+
policy=config.reviewer_policy,
|
|
28
|
+
intent=intent,
|
|
29
|
+
pawprint=config.pawprint_config,
|
|
30
|
+
raw_pawprint_config=config.raw_pawprint_config,
|
|
31
|
+
budget_state=services.budget_state,
|
|
32
|
+
)
|
|
33
|
+
guarded_decision, guarded_runtime_overlays = apply_extraction_guardrail(
|
|
34
|
+
pawprint=config.pawprint_config,
|
|
35
|
+
policy_evaluation=decision_state.policy_evaluation,
|
|
36
|
+
decision=decision_state.decision,
|
|
37
|
+
runtime_overlays=decision_state.runtime_overlays,
|
|
38
|
+
intent=intent,
|
|
39
|
+
)
|
|
40
|
+
remember_allowed_decision(services.memory_store, intent, guarded_decision)
|
|
41
|
+
|
|
42
|
+
artifacts = build_runtime_decision_artifacts(
|
|
43
|
+
event_id=services.ids.next_event_id(),
|
|
44
|
+
decision_id=services.ids.next_decision_id(),
|
|
45
|
+
agent_id=config.pawprint_config.id,
|
|
46
|
+
pawprint_version=load_pawprint_version(),
|
|
47
|
+
intent=intent,
|
|
48
|
+
policy_evaluation=decision_state.policy_evaluation,
|
|
49
|
+
runtime_overlays=guarded_runtime_overlays,
|
|
50
|
+
decision=guarded_decision,
|
|
51
|
+
budget_result=decision_state.budget_result,
|
|
52
|
+
)
|
|
53
|
+
return finalize_runtime_artifacts(
|
|
54
|
+
validator=services.validator,
|
|
55
|
+
audit_sink=services.audit_sink,
|
|
56
|
+
hooks=services.hooks,
|
|
57
|
+
decisions=services.decisions,
|
|
58
|
+
artifacts=artifacts,
|
|
59
|
+
)
|
pawly/runtime_flow.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from pawly.contracts import Decision, Intent
|
|
6
|
+
from pawly.memory.store import MemoryStore
|
|
7
|
+
from pawly.middleware.hooks import HookRegistry
|
|
8
|
+
from pawly.runtime_result import RuntimeDecisionArtifacts, RuntimeDecisionResult
|
|
9
|
+
from pawly.validator.validator import PawprintValidator, SchemaValidationError
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def validate_intent_or_raise(validator: PawprintValidator, intent: Intent) -> None:
|
|
13
|
+
intent_validation = validator.validate_intent(intent.to_dict())
|
|
14
|
+
if not intent_validation.valid:
|
|
15
|
+
raise SchemaValidationError("; ".join(intent_validation.errors))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def build_before_hook_payload(intent: Intent, agent_id: str) -> dict[str, object]:
|
|
19
|
+
return {
|
|
20
|
+
"intent": intent.to_dict(),
|
|
21
|
+
"agent_id": agent_id,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def remember_allowed_decision(memory_store: MemoryStore, intent: Intent, decision: Decision) -> None:
|
|
26
|
+
if decision.type.value != "allow":
|
|
27
|
+
return
|
|
28
|
+
memory_store.remember(
|
|
29
|
+
"default",
|
|
30
|
+
{"intent": intent.to_dict(), "decision_type": decision.type.value},
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def finalize_runtime_artifacts(
|
|
35
|
+
*,
|
|
36
|
+
validator: PawprintValidator,
|
|
37
|
+
audit_sink: Any,
|
|
38
|
+
hooks: HookRegistry,
|
|
39
|
+
decisions: list[dict[str, Any]],
|
|
40
|
+
artifacts: RuntimeDecisionArtifacts,
|
|
41
|
+
) -> RuntimeDecisionResult:
|
|
42
|
+
audit_sink.append(artifacts.event)
|
|
43
|
+
decision_validation = validator.validate_decision(artifacts.result.decision.to_dict())
|
|
44
|
+
if not decision_validation.valid:
|
|
45
|
+
raise SchemaValidationError("; ".join(decision_validation.errors))
|
|
46
|
+
|
|
47
|
+
result_payload = artifacts.result.to_dict()
|
|
48
|
+
decisions.append(result_payload)
|
|
49
|
+
hooks.run_after(result_payload)
|
|
50
|
+
return artifacts.result
|
pawly/runtime_ids.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from itertools import count
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass(slots=True)
|
|
8
|
+
class RuntimeIdSequence:
|
|
9
|
+
_decision_counter: count = field(default_factory=lambda: count(1))
|
|
10
|
+
_event_counter: count = field(default_factory=lambda: count(1))
|
|
11
|
+
|
|
12
|
+
def next_intent_id(self) -> str:
|
|
13
|
+
return f"intent-{next(self._decision_counter)}"
|
|
14
|
+
|
|
15
|
+
def next_decision_id(self) -> str:
|
|
16
|
+
return f"decision-{next(self._decision_counter)}"
|
|
17
|
+
|
|
18
|
+
def next_event_id(self) -> str:
|
|
19
|
+
return f"event-{next(self._event_counter)}"
|
pawly/runtime_report.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pawly.pawprint_loader import PawprintConfig
|
|
4
|
+
from pawly.performance.report import build_daily_report
|
|
5
|
+
from pawly.validator.validator import PawprintValidator, SchemaValidationError
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def build_validated_runtime_report(
|
|
9
|
+
*,
|
|
10
|
+
validator: PawprintValidator,
|
|
11
|
+
pawprint: PawprintConfig,
|
|
12
|
+
decisions: list[dict],
|
|
13
|
+
) -> dict:
|
|
14
|
+
report = build_daily_report(pawprint, decisions)
|
|
15
|
+
validation = validator.validate_report(report)
|
|
16
|
+
if not validation.valid:
|
|
17
|
+
raise SchemaValidationError("; ".join(validation.errors))
|
|
18
|
+
return report
|
pawly/runtime_request.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from pawly.contracts import Intent
|
|
6
|
+
from pawly.task_request import TaskRequest
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def build_task_request_intent(
|
|
10
|
+
*,
|
|
11
|
+
task: str,
|
|
12
|
+
action: str,
|
|
13
|
+
confidence: float,
|
|
14
|
+
metadata: dict[str, Any] | None = None,
|
|
15
|
+
intent_id: str = "intent-from-task-request",
|
|
16
|
+
) -> Intent:
|
|
17
|
+
request = TaskRequest(
|
|
18
|
+
task=task,
|
|
19
|
+
action=action,
|
|
20
|
+
confidence=confidence,
|
|
21
|
+
metadata=metadata or {},
|
|
22
|
+
)
|
|
23
|
+
return request.to_intent(intent_id=intent_id)
|
pawly/runtime_result.py
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from pawly.contracts import Decision, Intent
|
|
7
|
+
from pawly.audit.events import AuditEvent
|
|
8
|
+
from pawly.budget.checker import BudgetResult
|
|
9
|
+
from pawly.policy_engine.models import PolicyEvaluation
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(slots=True)
|
|
13
|
+
class RuntimeDecisionArtifacts:
|
|
14
|
+
event: AuditEvent
|
|
15
|
+
result: RuntimeDecisionResult
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass(slots=True)
|
|
19
|
+
class RuntimeDecisionResult:
|
|
20
|
+
agent_id: str
|
|
21
|
+
pawprint_version: str
|
|
22
|
+
intent: Intent
|
|
23
|
+
policy_evaluation: PolicyEvaluation
|
|
24
|
+
runtime_overlays: dict[str, object]
|
|
25
|
+
decision_id: str
|
|
26
|
+
decision: Decision
|
|
27
|
+
budget_consumed: dict[str, float]
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def from_dict(cls, payload: dict[str, Any]) -> "RuntimeDecisionResult":
|
|
31
|
+
return cls(
|
|
32
|
+
agent_id=str(payload["agent_id"]),
|
|
33
|
+
pawprint_version=str(payload["pawprint_version"]),
|
|
34
|
+
intent=Intent.from_dict(payload["intent"]),
|
|
35
|
+
policy_evaluation=PolicyEvaluation.from_dict(payload["policy_evaluation"]),
|
|
36
|
+
runtime_overlays=dict(payload["runtime_overlays"]),
|
|
37
|
+
decision_id=str(payload["decision_id"]),
|
|
38
|
+
decision=Decision.from_dict(payload),
|
|
39
|
+
budget_consumed=dict(payload.get("budget_consumed", {})),
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
def to_dict(self) -> dict[str, object]:
|
|
43
|
+
return {
|
|
44
|
+
"agent_id": self.agent_id,
|
|
45
|
+
"pawprint_version": self.pawprint_version,
|
|
46
|
+
"intent": self.intent.to_dict(),
|
|
47
|
+
"policy_evaluation": self.policy_evaluation.to_dict(),
|
|
48
|
+
"runtime_overlays": self.runtime_overlays,
|
|
49
|
+
"decision_id": self.decision_id,
|
|
50
|
+
**self.decision.to_dict(),
|
|
51
|
+
"budget_consumed": self.budget_consumed,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def build_decision_audit_event(
|
|
56
|
+
*,
|
|
57
|
+
event_id: str,
|
|
58
|
+
decision_id: str,
|
|
59
|
+
agent_id: str,
|
|
60
|
+
pawprint_version: str,
|
|
61
|
+
intent: Intent,
|
|
62
|
+
policy_evaluation: PolicyEvaluation,
|
|
63
|
+
runtime_overlays: dict[str, object],
|
|
64
|
+
decision: Decision,
|
|
65
|
+
) -> AuditEvent:
|
|
66
|
+
intent_payload = intent.to_dict()
|
|
67
|
+
return AuditEvent.from_decision(
|
|
68
|
+
event_id=event_id,
|
|
69
|
+
decision_id=decision_id,
|
|
70
|
+
agent_id=agent_id,
|
|
71
|
+
pawprint_version=pawprint_version,
|
|
72
|
+
outcome=decision.type.value,
|
|
73
|
+
original_intent=intent_payload,
|
|
74
|
+
normalized_intent=intent_payload,
|
|
75
|
+
action_name=intent.action.name,
|
|
76
|
+
policy_evaluation=policy_evaluation.to_dict(),
|
|
77
|
+
runtime_overlays=runtime_overlays,
|
|
78
|
+
policy_references=decision.matched_rules,
|
|
79
|
+
final_decision=decision.to_dict(),
|
|
80
|
+
reason_codes=decision.reason_codes,
|
|
81
|
+
risk_score=decision.risk_score,
|
|
82
|
+
escalated_to=policy_evaluation.handoff_target if decision.type.value == "require_approval" else None,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def build_decision_result(
|
|
87
|
+
*,
|
|
88
|
+
agent_id: str,
|
|
89
|
+
pawprint_version: str,
|
|
90
|
+
intent: Intent,
|
|
91
|
+
policy_evaluation: PolicyEvaluation,
|
|
92
|
+
runtime_overlays: dict[str, object],
|
|
93
|
+
decision_id: str,
|
|
94
|
+
decision: Decision,
|
|
95
|
+
budget_result: BudgetResult,
|
|
96
|
+
) -> RuntimeDecisionResult:
|
|
97
|
+
return RuntimeDecisionResult(
|
|
98
|
+
agent_id=agent_id,
|
|
99
|
+
pawprint_version=pawprint_version,
|
|
100
|
+
intent=intent,
|
|
101
|
+
policy_evaluation=policy_evaluation,
|
|
102
|
+
runtime_overlays=runtime_overlays,
|
|
103
|
+
decision_id=decision_id,
|
|
104
|
+
decision=decision,
|
|
105
|
+
budget_consumed=budget_result.consumed,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def build_runtime_decision_artifacts(
|
|
110
|
+
*,
|
|
111
|
+
event_id: str,
|
|
112
|
+
decision_id: str,
|
|
113
|
+
agent_id: str,
|
|
114
|
+
pawprint_version: str,
|
|
115
|
+
intent: Intent,
|
|
116
|
+
policy_evaluation: PolicyEvaluation,
|
|
117
|
+
runtime_overlays: dict[str, object],
|
|
118
|
+
decision: Decision,
|
|
119
|
+
budget_result: BudgetResult,
|
|
120
|
+
) -> RuntimeDecisionArtifacts:
|
|
121
|
+
return RuntimeDecisionArtifacts(
|
|
122
|
+
event=build_decision_audit_event(
|
|
123
|
+
event_id=event_id,
|
|
124
|
+
decision_id=decision_id,
|
|
125
|
+
agent_id=agent_id,
|
|
126
|
+
pawprint_version=pawprint_version,
|
|
127
|
+
intent=intent,
|
|
128
|
+
policy_evaluation=policy_evaluation,
|
|
129
|
+
runtime_overlays=runtime_overlays,
|
|
130
|
+
decision=decision,
|
|
131
|
+
),
|
|
132
|
+
result=build_decision_result(
|
|
133
|
+
agent_id=agent_id,
|
|
134
|
+
pawprint_version=pawprint_version,
|
|
135
|
+
intent=intent,
|
|
136
|
+
policy_evaluation=policy_evaluation,
|
|
137
|
+
runtime_overlays=runtime_overlays,
|
|
138
|
+
decision_id=decision_id,
|
|
139
|
+
decision=decision,
|
|
140
|
+
budget_result=budget_result,
|
|
141
|
+
),
|
|
142
|
+
)
|
pawly/runtime_scoring.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping, Sequence
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from pawly.contracts import Action, PolicyScore
|
|
7
|
+
from pawly.policy.base import Policy
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def build_scoring_state(
|
|
11
|
+
*,
|
|
12
|
+
state: Mapping[str, Any] | None = None,
|
|
13
|
+
) -> dict[str, Any]:
|
|
14
|
+
if state is None:
|
|
15
|
+
return {}
|
|
16
|
+
return dict(state)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def score_actions(
|
|
20
|
+
*,
|
|
21
|
+
policy: Policy,
|
|
22
|
+
actions: Sequence[Action],
|
|
23
|
+
state: Mapping[str, Any] | None = None,
|
|
24
|
+
) -> list[PolicyScore]:
|
|
25
|
+
return policy.evaluate(build_scoring_state(state=state), actions)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"additionalProperties": true,
|
|
5
|
+
"required": ["type", "reason"],
|
|
6
|
+
"properties": {
|
|
7
|
+
"type": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"enum": ["allow", "deny", "require_approval", "simulate"]
|
|
10
|
+
},
|
|
11
|
+
"reason": { "type": "string", "minLength": 1 },
|
|
12
|
+
"source": { "type": "string" },
|
|
13
|
+
"reason_codes": {
|
|
14
|
+
"type": "array",
|
|
15
|
+
"items": { "type": "string" }
|
|
16
|
+
},
|
|
17
|
+
"matched_rules": {
|
|
18
|
+
"type": "array",
|
|
19
|
+
"items": { "type": "string" }
|
|
20
|
+
},
|
|
21
|
+
"risk_score": { "type": "number", "minimum": 0.0, "maximum": 1.0 },
|
|
22
|
+
"rewritten_action": {
|
|
23
|
+
"type": "object",
|
|
24
|
+
"additionalProperties": false,
|
|
25
|
+
"required": ["name", "arguments"],
|
|
26
|
+
"properties": {
|
|
27
|
+
"name": { "type": "string", "minLength": 1 },
|
|
28
|
+
"arguments": { "type": "object" },
|
|
29
|
+
"target": { "type": "string" }
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"audit_tags": {
|
|
33
|
+
"type": "array",
|
|
34
|
+
"items": { "type": "string" }
|
|
35
|
+
},
|
|
36
|
+
"worker_id": { "type": "string" }
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"additionalProperties": false,
|
|
5
|
+
"required": ["intent_id", "source", "action", "context", "metadata"],
|
|
6
|
+
"properties": {
|
|
7
|
+
"intent_id": { "type": "string", "minLength": 1 },
|
|
8
|
+
"source": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"enum": ["tool_call", "planner_output", "execution_request"]
|
|
11
|
+
},
|
|
12
|
+
"action": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"additionalProperties": false,
|
|
15
|
+
"required": ["name", "arguments"],
|
|
16
|
+
"properties": {
|
|
17
|
+
"name": { "type": "string", "minLength": 1 },
|
|
18
|
+
"arguments": { "type": "object" },
|
|
19
|
+
"target": { "type": "string" }
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"context": {
|
|
23
|
+
"type": "object",
|
|
24
|
+
"additionalProperties": false,
|
|
25
|
+
"required": ["summary", "confidence"],
|
|
26
|
+
"properties": {
|
|
27
|
+
"summary": { "type": "string" },
|
|
28
|
+
"confidence": { "type": "number", "minimum": 0.0, "maximum": 1.0 }
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"metadata": { "type": "object" }
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"additionalProperties": false,
|
|
5
|
+
"required": ["worker_id", "generated_at", "summary", "policy_summary", "runtime_overlay_summary"],
|
|
6
|
+
"properties": {
|
|
7
|
+
"worker_id": { "type": "string", "minLength": 1 },
|
|
8
|
+
"generated_at": { "type": "string", "minLength": 1 },
|
|
9
|
+
"summary": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"additionalProperties": false,
|
|
12
|
+
"required": ["status", "notes"],
|
|
13
|
+
"properties": {
|
|
14
|
+
"status": { "type": "string" },
|
|
15
|
+
"notes": { "type": "array", "items": { "type": "string" } }
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"policy_summary": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"additionalProperties": false,
|
|
21
|
+
"required": ["status", "notes"],
|
|
22
|
+
"properties": {
|
|
23
|
+
"status": { "type": "string" },
|
|
24
|
+
"notes": { "type": "array", "items": { "type": "string" } }
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"runtime_overlay_summary": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"additionalProperties": false,
|
|
30
|
+
"required": ["notes"],
|
|
31
|
+
"properties": {
|
|
32
|
+
"notes": { "type": "array", "items": { "type": "string" } }
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|