algo-cli-runtime 0.14.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.
- algo_cli/__init__.py +3 -0
- algo_cli/__main__.py +7 -0
- algo_cli/_internal/__init__.py +12 -0
- algo_cli/_internal/policy_chain.py +259 -0
- algo_cli/action_registry.py +1047 -0
- algo_cli/agent_blocks.py +550 -0
- algo_cli/agent_pipeline.py +1457 -0
- algo_cli/agent_threads.py +308 -0
- algo_cli/animations.py +316 -0
- algo_cli/cache_admission.py +209 -0
- algo_cli/capability_mask.py +66 -0
- algo_cli/chat_protocol.py +116 -0
- algo_cli/chatgpt_auth.py +510 -0
- algo_cli/chatgpt_client.py +657 -0
- algo_cli/code_rag.py +479 -0
- algo_cli/config.py +651 -0
- algo_cli/context_budget.py +679 -0
- algo_cli/credential_helpers.py +315 -0
- algo_cli/deliberation.py +29 -0
- algo_cli/display.py +1470 -0
- algo_cli/evals/__init__.py +21 -0
- algo_cli/evals/algorithm_effectiveness.py +560 -0
- algo_cli/evals/competitive_harness_rating.py +702 -0
- algo_cli/evals/cot_quality.py +220 -0
- algo_cli/evals/harness_retrieval_benchmark.py +401 -0
- algo_cli/evals/performance_regression.py +136 -0
- algo_cli/evals/scorecard_grading.py +308 -0
- algo_cli/evals/session_distribution.py +84 -0
- algo_cli/execution_guardrails.py +806 -0
- algo_cli/extensions_manifest.py +84 -0
- algo_cli/git_evidence.py +227 -0
- algo_cli/google_workspace.py +407 -0
- algo_cli/google_workspace_auth.py +523 -0
- algo_cli/harness.py +2587 -0
- algo_cli/identity.py +557 -0
- algo_cli/index_compute_lab.py +228 -0
- algo_cli/inference_harness.py +70 -0
- algo_cli/intelligence/__init__.py +1103 -0
- algo_cli/intelligence/acrobat_config.py +307 -0
- algo_cli/intelligence/acrobat_manifests.py +338 -0
- algo_cli/intelligence/acrobat_models.py +195 -0
- algo_cli/intelligence/acrobat_pipeline.py +295 -0
- algo_cli/intelligence/acrobat_runtime.py +302 -0
- algo_cli/intelligence/acrobat_security.py +261 -0
- algo_cli/intelligence/acrobat_workflows.py +226 -0
- algo_cli/intelligence/actionability.py +165 -0
- algo_cli/intelligence/adversarial_audit.py +136 -0
- algo_cli/intelligence/agent_arena.py +92 -0
- algo_cli/intelligence/agent_benchmark.py +236 -0
- algo_cli/intelligence/agent_runtime.py +171 -0
- algo_cli/intelligence/agents_as_tools.py +70 -0
- algo_cli/intelligence/artifact_binding.py +80 -0
- algo_cli/intelligence/autonomous_engineer.py +1976 -0
- algo_cli/intelligence/backpressure.py +99 -0
- algo_cli/intelligence/bloom_filter.py +186 -0
- algo_cli/intelligence/bonferroni.py +66 -0
- algo_cli/intelligence/boundary_compaction.py +98 -0
- algo_cli/intelligence/catalog_verifier.py +172 -0
- algo_cli/intelligence/cavecrew.py +118 -0
- algo_cli/intelligence/changelog.py +176 -0
- algo_cli/intelligence/checkpoint_resume.py +92 -0
- algo_cli/intelligence/circuit_breaker.py +88 -0
- algo_cli/intelligence/clarification_gate.py +101 -0
- algo_cli/intelligence/code_graph.py +180 -0
- algo_cli/intelligence/coderank.py +97 -0
- algo_cli/intelligence/consistent_hash.py +150 -0
- algo_cli/intelligence/consortium_synthesis.py +139 -0
- algo_cli/intelligence/construction/__init__.py +241 -0
- algo_cli/intelligence/construction/common.py +273 -0
- algo_cli/intelligence/construction/documents.py +496 -0
- algo_cli/intelligence/construction/labor_units.py +1395 -0
- algo_cli/intelligence/construction/payments.py +470 -0
- algo_cli/intelligence/construction/risk.py +784 -0
- algo_cli/intelligence/content_extractor.py +132 -0
- algo_cli/intelligence/context_adaptive.py +102 -0
- algo_cli/intelligence/context_ops.py +95 -0
- algo_cli/intelligence/count_min.py +145 -0
- algo_cli/intelligence/cow_state.py +103 -0
- algo_cli/intelligence/critic_loop.py +119 -0
- algo_cli/intelligence/cross_source.py +113 -0
- algo_cli/intelligence/daemon_mode.py +99 -0
- algo_cli/intelligence/dag_orchestration.py +151 -0
- algo_cli/intelligence/deep_research.py +155 -0
- algo_cli/intelligence/degenerate_detector.py +78 -0
- algo_cli/intelligence/delta_report.py +92 -0
- algo_cli/intelligence/discovery_event_log.py +92 -0
- algo_cli/intelligence/document_ingest.py +298 -0
- algo_cli/intelligence/dual_layer_validate.py +151 -0
- algo_cli/intelligence/echo_fidelity.py +73 -0
- algo_cli/intelligence/ema_tuning.py +104 -0
- algo_cli/intelligence/event_log.py +92 -0
- algo_cli/intelligence/evidence_graph.py +114 -0
- algo_cli/intelligence/extension_host.py +162 -0
- algo_cli/intelligence/extension_manifest.py +115 -0
- algo_cli/intelligence/falsification_suite.py +178 -0
- algo_cli/intelligence/finance/__init__.py +169 -0
- algo_cli/intelligence/finance/anomalies.py +135 -0
- algo_cli/intelligence/finance/ap_ar.py +351 -0
- algo_cli/intelligence/finance/cash.py +162 -0
- algo_cli/intelligence/finance/close.py +332 -0
- algo_cli/intelligence/finance/common.py +244 -0
- algo_cli/intelligence/finance/construction.py +135 -0
- algo_cli/intelligence/finance/controls.py +172 -0
- algo_cli/intelligence/finance/evidence.py +119 -0
- algo_cli/intelligence/finance/exceptions.py +157 -0
- algo_cli/intelligence/finance/reconciliations.py +254 -0
- algo_cli/intelligence/finance/revenue.py +109 -0
- algo_cli/intelligence/finance/tax.py +74 -0
- algo_cli/intelligence/finance/workpapers.py +111 -0
- algo_cli/intelligence/finding_record.py +120 -0
- algo_cli/intelligence/flow_dag.py +267 -0
- algo_cli/intelligence/gatherer.py +223 -0
- algo_cli/intelligence/golden_master.py +98 -0
- algo_cli/intelligence/graph_rag.py +195 -0
- algo_cli/intelligence/group_chat.py +143 -0
- algo_cli/intelligence/hash_dedup.py +145 -0
- algo_cli/intelligence/hyperloglog.py +128 -0
- algo_cli/intelligence/incremental_index.py +316 -0
- algo_cli/intelligence/index_store.py +16 -0
- algo_cli/intelligence/iteration_plan.py +133 -0
- algo_cli/intelligence/kernel_plugins.py +167 -0
- algo_cli/intelligence/lesson_catalog.py +135 -0
- algo_cli/intelligence/llm_fallback.py +169 -0
- algo_cli/intelligence/log2_histogram.py +267 -0
- algo_cli/intelligence/lsp_integration.py +147 -0
- algo_cli/intelligence/memory_evolution.py +117 -0
- algo_cli/intelligence/minhash_lsh.py +182 -0
- algo_cli/intelligence/multi_model_score.py +174 -0
- algo_cli/intelligence/multi_tier_grade.py +211 -0
- algo_cli/intelligence/negative_controls.py +113 -0
- algo_cli/intelligence/numeric_clamp.py +63 -0
- algo_cli/intelligence/occ_editor.py +66 -0
- algo_cli/intelligence/output_normalize.py +112 -0
- algo_cli/intelligence/parallel_delegation.py +98 -0
- algo_cli/intelligence/parallel_fanout.py +104 -0
- algo_cli/intelligence/permission_modes.py +105 -0
- algo_cli/intelligence/pre_push_gate.py +68 -0
- algo_cli/intelligence/prefetch.py +171 -0
- algo_cli/intelligence/process_framework.py +217 -0
- algo_cli/intelligence/project_graph.py +387 -0
- algo_cli/intelligence/query_expansion.py +146 -0
- algo_cli/intelligence/ralph_loop.py +117 -0
- algo_cli/intelligence/rate_limiter.py +153 -0
- algo_cli/intelligence/refactor_transaction.py +94 -0
- algo_cli/intelligence/research_workspace.py +108 -0
- algo_cli/intelligence/retraction_ledger.py +72 -0
- algo_cli/intelligence/saga_pattern.py +88 -0
- algo_cli/intelligence/session_fork.py +100 -0
- algo_cli/intelligence/shadow_editor.py +67 -0
- algo_cli/intelligence/shell_session.py +213 -0
- algo_cli/intelligence/source_registry.py +143 -0
- algo_cli/intelligence/spawn_scales.py +99 -0
- algo_cli/intelligence/stat_stability.py +104 -0
- algo_cli/intelligence/structural_validator.py +148 -0
- algo_cli/intelligence/subagent_spawner.py +111 -0
- algo_cli/intelligence/symmetric_verify.py +70 -0
- algo_cli/intelligence/task_classifier.py +129 -0
- algo_cli/intelligence/team_execution.py +122 -0
- algo_cli/intelligence/tiered_access.py +121 -0
- algo_cli/intelligence/utility_registry.py +159 -0
- algo_cli/intuition_engine.py +560 -0
- algo_cli/intuition_injector.py +82 -0
- algo_cli/kernels/__init__.py +5 -0
- algo_cli/kernels/manifest.py +763 -0
- algo_cli/main.py +3903 -0
- algo_cli/memory_candidates.py +541 -0
- algo_cli/memory_echo_veil.py +394 -0
- algo_cli/memory_runtime.py +112 -0
- algo_cli/model_info.py +548 -0
- algo_cli/model_profile.py +160 -0
- algo_cli/model_routing.py +74 -0
- algo_cli/oneshot.py +331 -0
- algo_cli/perf_telemetry.py +389 -0
- algo_cli/plugins.py +245 -0
- algo_cli/private_event_store.py +654 -0
- algo_cli/quantization/__init__.py +24 -0
- algo_cli/quantization/lloyd_max.py +98 -0
- algo_cli/quantization/turbo_quant.py +308 -0
- algo_cli/reasoning/__init__.py +46 -0
- algo_cli/reasoning/combinatorial.py +356 -0
- algo_cli/reasoning/graph_of_thought.py +297 -0
- algo_cli/reasoning/mcts.py +220 -0
- algo_cli/reasoning/neuro_symbolic.py +250 -0
- algo_cli/reasoning/react.py +246 -0
- algo_cli/reasoning/reflexion.py +225 -0
- algo_cli/reasoning/tree_of_thought.py +241 -0
- algo_cli/reasoning_bridge.py +150 -0
- algo_cli/reconciliation.py +284 -0
- algo_cli/reflex.py +385 -0
- algo_cli/resources/docs/ALGO.md +13958 -0
- algo_cli/resources/docs/algo-cli-algorithm-evidence-contract.md +60 -0
- algo_cli/resources/docs/algo-cli-execution-verification-contract.md +59 -0
- algo_cli/resources/docs/algo-cli-memory-lifecycle-contract.md +72 -0
- algo_cli/resources/docs/harness-extension-cleanup-recommendation.md +41 -0
- algo_cli/resources/docs/index-compute-lab-integration.md +32 -0
- algo_cli/resources/docs/inference-harness-loop-blueprint-2026-06.md +55 -0
- algo_cli/resources/docs/main-split-map.md +35 -0
- algo_cli/resources/docs/privacy-and-context.md +48 -0
- algo_cli/resources/docs/reflex-loop-v0.2.md +354 -0
- algo_cli/resources/skills/README.md +26 -0
- algo_cli/resources/skills/algo-cli.md +59 -0
- algo_cli/resources/skills/edit-file-precision.md +49 -0
- algo_cli/resources/skills/harness-search-first.md +47 -0
- algo_cli/resources/skills/memory-recall-ritual.md +51 -0
- algo_cli/resources/skills/qol-algorithms.md +224 -0
- algo_cli/resources/skills/smart-error-recovery.md +56 -0
- algo_cli/resources/skills/tool-selection-cheatsheet.md +65 -0
- algo_cli/retrieval_algorithms.py +127 -0
- algo_cli/runtime_qos.py +236 -0
- algo_cli/runtime_services.py +320 -0
- algo_cli/session_commands.py +95 -0
- algo_cli/session_mode.py +113 -0
- algo_cli/skills.py +430 -0
- algo_cli/slash_dispatch.py +1265 -0
- algo_cli/small_context.py +206 -0
- algo_cli/spawn_budget.py +89 -0
- algo_cli/task_ledger.py +84 -0
- algo_cli/task_router.py +197 -0
- algo_cli/tool_context.py +94 -0
- algo_cli/tool_contract.py +99 -0
- algo_cli/tool_policy.py +357 -0
- algo_cli/tool_runtime.py +647 -0
- algo_cli/tools.py +3056 -0
- algo_cli/url_scheme.py +174 -0
- algo_cli/verify.py +154 -0
- algo_cli/version_manifest.py +178 -0
- algo_cli/vision_screenshot_verify.py +76 -0
- algo_cli/workspace_resolver.py +68 -0
- algo_cli/x_account.py +209 -0
- algo_cli/xai_auth.py +374 -0
- algo_cli/xai_client.py +600 -0
- algo_cli_runtime-0.14.0.dist-info/METADATA +369 -0
- algo_cli_runtime-0.14.0.dist-info/RECORD +237 -0
- algo_cli_runtime-0.14.0.dist-info/WHEEL +4 -0
- algo_cli_runtime-0.14.0.dist-info/entry_points.txt +3 -0
- algo_cli_runtime-0.14.0.dist-info/licenses/LICENSE +21 -0
- ollama_cli/__init__.py +67 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
"""Credential helper interface for Algo CLI.
|
|
2
|
+
|
|
3
|
+
Provides a standard get/store/erase interface for credential backends,
|
|
4
|
+
inspired by Docker's docker-credential-<name> pattern.
|
|
5
|
+
|
|
6
|
+
Each credential helper is a Python class that implements:
|
|
7
|
+
- get(key: str) -> str | None
|
|
8
|
+
- store(key: str, value: str) -> None
|
|
9
|
+
- erase(key: str) -> None
|
|
10
|
+
- list_keys() -> list[str]
|
|
11
|
+
|
|
12
|
+
Built-in helpers:
|
|
13
|
+
- ollama-cloud (OLLAMA_API_KEY)
|
|
14
|
+
- xai-oauth (xAI OAuth tokens)
|
|
15
|
+
- google-workspace (Google Workspace OAuth tokens)
|
|
16
|
+
- github-token (GitHub API token)
|
|
17
|
+
- env (fallback: read from environment variables)
|
|
18
|
+
|
|
19
|
+
Custom helpers can be registered at runtime or discovered from
|
|
20
|
+
~/.algo_cli/credentials/ as Python modules with a create_helper() function.
|
|
21
|
+
"""
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import abc
|
|
25
|
+
import json
|
|
26
|
+
import logging
|
|
27
|
+
import os
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
from typing import Any
|
|
30
|
+
|
|
31
|
+
from .config import CONFIG_DIR, _atomic_write_text
|
|
32
|
+
|
|
33
|
+
logger = logging.getLogger(__name__)
|
|
34
|
+
|
|
35
|
+
CREDENTIALS_DIR = CONFIG_DIR / "credentials"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class CredentialHelper(abc.ABC):
|
|
39
|
+
"""Abstract base class for credential helpers."""
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
@abc.abstractmethod
|
|
43
|
+
def name(self) -> str:
|
|
44
|
+
"""Helper identifier (e.g. 'ollama-cloud')."""
|
|
45
|
+
...
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def description(self) -> str:
|
|
49
|
+
"""Short safe description for list/status UIs."""
|
|
50
|
+
doc = type(self).__doc__ or "Credential helper"
|
|
51
|
+
return " ".join(doc.strip().splitlines()[:1])
|
|
52
|
+
|
|
53
|
+
@abc.abstractmethod
|
|
54
|
+
def get(self, key: str) -> str | None:
|
|
55
|
+
"""Retrieve a credential value by key. Returns None if not found."""
|
|
56
|
+
...
|
|
57
|
+
|
|
58
|
+
@abc.abstractmethod
|
|
59
|
+
def store(self, key: str, value: str) -> None:
|
|
60
|
+
"""Store a credential value."""
|
|
61
|
+
...
|
|
62
|
+
|
|
63
|
+
@abc.abstractmethod
|
|
64
|
+
def erase(self, key: str) -> None:
|
|
65
|
+
"""Delete a credential by key."""
|
|
66
|
+
...
|
|
67
|
+
|
|
68
|
+
@abc.abstractmethod
|
|
69
|
+
def list_keys(self) -> list[str]:
|
|
70
|
+
"""List all stored credential keys."""
|
|
71
|
+
...
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class EnvCredentialHelper(CredentialHelper):
|
|
75
|
+
"""Fallback helper that reads from environment variables."""
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def name(self) -> str:
|
|
79
|
+
return "env"
|
|
80
|
+
|
|
81
|
+
def get(self, key: str) -> str | None:
|
|
82
|
+
return os.environ.get(key)
|
|
83
|
+
|
|
84
|
+
def store(self, key: str, value: str) -> None:
|
|
85
|
+
os.environ[key] = value
|
|
86
|
+
|
|
87
|
+
def erase(self, key: str) -> None:
|
|
88
|
+
os.environ.pop(key, None)
|
|
89
|
+
|
|
90
|
+
def list_keys(self) -> list[str]:
|
|
91
|
+
# Can't meaningfully list env vars as credential keys
|
|
92
|
+
return []
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class FileCredentialHelper(CredentialHelper):
|
|
96
|
+
"""File-based credential helper storing JSON in ~/.algo_cli/credentials/.
|
|
97
|
+
|
|
98
|
+
Each helper gets its own JSON file: <name>.json
|
|
99
|
+
Credentials are stored as {key: value} pairs.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
def __init__(self, helper_name: str, base_dir: Path | None = None):
|
|
103
|
+
self._name = helper_name
|
|
104
|
+
self._base_dir = base_dir or CREDENTIALS_DIR
|
|
105
|
+
self._file = self._base_dir / f"{helper_name}.json"
|
|
106
|
+
|
|
107
|
+
@property
|
|
108
|
+
def name(self) -> str:
|
|
109
|
+
return self._name
|
|
110
|
+
|
|
111
|
+
def _load(self) -> dict[str, str]:
|
|
112
|
+
try:
|
|
113
|
+
return json.loads(self._file.read_text(encoding="utf-8"))
|
|
114
|
+
except (FileNotFoundError, json.JSONDecodeError):
|
|
115
|
+
return {}
|
|
116
|
+
|
|
117
|
+
def _save(self, data: dict[str, str]) -> None:
|
|
118
|
+
self._base_dir.mkdir(parents=True, exist_ok=True)
|
|
119
|
+
_atomic_write_text(self._file, json.dumps(data, indent=2))
|
|
120
|
+
|
|
121
|
+
def get(self, key: str) -> str | None:
|
|
122
|
+
return self._load().get(key)
|
|
123
|
+
|
|
124
|
+
def store(self, key: str, value: str) -> None:
|
|
125
|
+
data = self._load()
|
|
126
|
+
data[key] = value
|
|
127
|
+
self._save(data)
|
|
128
|
+
|
|
129
|
+
def erase(self, key: str) -> None:
|
|
130
|
+
data = self._load()
|
|
131
|
+
data.pop(key, None)
|
|
132
|
+
self._save(data)
|
|
133
|
+
|
|
134
|
+
def list_keys(self) -> list[str]:
|
|
135
|
+
return list(self._load().keys())
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class OllamaCloudCredentialHelper(CredentialHelper):
|
|
139
|
+
"""Credential helper for OLLAMA_API_KEY.
|
|
140
|
+
|
|
141
|
+
Reads from environment first, falls back to the runtime env file,
|
|
142
|
+
then to the file-based credential store.
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
def __init__(self, file_helper: FileCredentialHelper | None = None):
|
|
146
|
+
self._file_helper = file_helper or FileCredentialHelper("ollama-cloud")
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def name(self) -> str:
|
|
150
|
+
return "ollama-cloud"
|
|
151
|
+
|
|
152
|
+
def get(self, key: str) -> str | None:
|
|
153
|
+
if key == "OLLAMA_API_KEY":
|
|
154
|
+
# Check env first
|
|
155
|
+
val = os.environ.get("OLLAMA_API_KEY", "").strip()
|
|
156
|
+
if val:
|
|
157
|
+
return val
|
|
158
|
+
# Check runtime env file
|
|
159
|
+
try:
|
|
160
|
+
from .config import load_runtime_env
|
|
161
|
+
load_runtime_env(override=True)
|
|
162
|
+
val = os.environ.get("OLLAMA_API_KEY", "").strip()
|
|
163
|
+
if val:
|
|
164
|
+
return val
|
|
165
|
+
except Exception:
|
|
166
|
+
pass
|
|
167
|
+
# Fall back to file store
|
|
168
|
+
return self._file_helper.get(key)
|
|
169
|
+
return self._file_helper.get(key)
|
|
170
|
+
|
|
171
|
+
def store(self, key: str, value: str) -> None:
|
|
172
|
+
self._file_helper.store(key, value)
|
|
173
|
+
|
|
174
|
+
def erase(self, key: str) -> None:
|
|
175
|
+
self._file_helper.erase(key)
|
|
176
|
+
|
|
177
|
+
def list_keys(self) -> list[str]:
|
|
178
|
+
return self._file_helper.list_keys()
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class XAIOAuthCredentialHelper(CredentialHelper):
|
|
182
|
+
"""Credential helper for xAI OAuth tokens.
|
|
183
|
+
|
|
184
|
+
Delegates to the existing xai_auth.json file, providing a standard
|
|
185
|
+
interface while keeping backward compatibility.
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
def __init__(self):
|
|
189
|
+
self._auth_file = CONFIG_DIR / "xai_auth.json"
|
|
190
|
+
|
|
191
|
+
@property
|
|
192
|
+
def name(self) -> str:
|
|
193
|
+
return "xai-oauth"
|
|
194
|
+
|
|
195
|
+
def _load(self) -> dict[str, Any]:
|
|
196
|
+
try:
|
|
197
|
+
return json.loads(self._auth_file.read_text(encoding="utf-8"))
|
|
198
|
+
except (FileNotFoundError, json.JSONDecodeError):
|
|
199
|
+
return {}
|
|
200
|
+
|
|
201
|
+
def get(self, key: str) -> str | None:
|
|
202
|
+
data = self._load()
|
|
203
|
+
return data.get(key)
|
|
204
|
+
|
|
205
|
+
def store(self, key: str, value: str) -> None:
|
|
206
|
+
data = self._load()
|
|
207
|
+
data[key] = value
|
|
208
|
+
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
|
209
|
+
_atomic_write_text(self._auth_file, json.dumps(data, indent=2))
|
|
210
|
+
|
|
211
|
+
def erase(self, key: str) -> None:
|
|
212
|
+
data = self._load()
|
|
213
|
+
data.pop(key, None)
|
|
214
|
+
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
|
215
|
+
_atomic_write_text(self._auth_file, json.dumps(data, indent=2))
|
|
216
|
+
|
|
217
|
+
def list_keys(self) -> list[str]:
|
|
218
|
+
return list(self._load().keys())
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
class GoogleWorkspaceCredentialHelper(CredentialHelper):
|
|
222
|
+
"""Credential helper for Google Workspace OAuth tokens.
|
|
223
|
+
|
|
224
|
+
Delegates to the existing google_workspace token file.
|
|
225
|
+
"""
|
|
226
|
+
|
|
227
|
+
def __init__(self):
|
|
228
|
+
self._auth_file = CONFIG_DIR / "google_workspace_tokens.json"
|
|
229
|
+
|
|
230
|
+
@property
|
|
231
|
+
def name(self) -> str:
|
|
232
|
+
return "google-workspace"
|
|
233
|
+
|
|
234
|
+
def _load(self) -> dict[str, Any]:
|
|
235
|
+
try:
|
|
236
|
+
return json.loads(self._auth_file.read_text(encoding="utf-8"))
|
|
237
|
+
except (FileNotFoundError, json.JSONDecodeError):
|
|
238
|
+
return {}
|
|
239
|
+
|
|
240
|
+
def get(self, key: str) -> str | None:
|
|
241
|
+
return self._load().get(key)
|
|
242
|
+
|
|
243
|
+
def store(self, key: str, value: str) -> None:
|
|
244
|
+
data = self._load()
|
|
245
|
+
data[key] = value
|
|
246
|
+
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
|
247
|
+
_atomic_write_text(self._auth_file, json.dumps(data, indent=2))
|
|
248
|
+
|
|
249
|
+
def erase(self, key: str) -> None:
|
|
250
|
+
data = self._load()
|
|
251
|
+
data.pop(key, None)
|
|
252
|
+
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
|
253
|
+
_atomic_write_text(self._auth_file, json.dumps(data, indent=2))
|
|
254
|
+
|
|
255
|
+
def list_keys(self) -> list[str]:
|
|
256
|
+
return list(self._load().keys())
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
# --- Registry ---
|
|
260
|
+
|
|
261
|
+
_REGISTRY: dict[str, CredentialHelper] = {}
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def register_helper(helper: CredentialHelper) -> None:
|
|
265
|
+
"""Register a credential helper."""
|
|
266
|
+
_REGISTRY[helper.name] = helper
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def get_helper(name: str) -> CredentialHelper | None:
|
|
270
|
+
"""Get a registered credential helper by name."""
|
|
271
|
+
return _REGISTRY.get(name)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def list_helpers() -> list[str]:
|
|
275
|
+
"""List all registered credential helper names."""
|
|
276
|
+
return sorted(_REGISTRY.keys())
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def get_credential(helper_name: str, key: str) -> str | None:
|
|
280
|
+
"""Convenience: get a credential via a named helper."""
|
|
281
|
+
helper = get_helper(helper_name)
|
|
282
|
+
if helper is None:
|
|
283
|
+
return None
|
|
284
|
+
return helper.get(key)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def store_credential(helper_name: str, key: str, value: str) -> bool:
|
|
288
|
+
"""Convenience: store a credential via a named helper. Returns False if helper not found."""
|
|
289
|
+
helper = get_helper(helper_name)
|
|
290
|
+
if helper is None:
|
|
291
|
+
return False
|
|
292
|
+
helper.store(key, value)
|
|
293
|
+
return True
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def erase_credential(helper_name: str, key: str) -> bool:
|
|
297
|
+
"""Convenience: erase a credential via a named helper. Returns False if helper not found."""
|
|
298
|
+
helper = get_helper(helper_name)
|
|
299
|
+
if helper is None:
|
|
300
|
+
return False
|
|
301
|
+
helper.erase(key)
|
|
302
|
+
return True
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def _init_default_helpers() -> None:
|
|
306
|
+
"""Register built-in credential helpers."""
|
|
307
|
+
register_helper(EnvCredentialHelper())
|
|
308
|
+
register_helper(FileCredentialHelper("github-token"))
|
|
309
|
+
register_helper(OllamaCloudCredentialHelper())
|
|
310
|
+
register_helper(XAIOAuthCredentialHelper())
|
|
311
|
+
register_helper(GoogleWorkspaceCredentialHelper())
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
# Initialize on import
|
|
315
|
+
_init_default_helpers()
|
algo_cli/deliberation.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Adaptive deliberation policy for non-interactive runs."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
_DEEP_CUES = (
|
|
7
|
+
"deep analysis",
|
|
8
|
+
"architecture decision",
|
|
9
|
+
"architectural tradeoff",
|
|
10
|
+
"security audit",
|
|
11
|
+
"threat model",
|
|
12
|
+
"formal proof",
|
|
13
|
+
"prove that",
|
|
14
|
+
"root cause analysis",
|
|
15
|
+
"compare strategies",
|
|
16
|
+
"evaluate alternatives",
|
|
17
|
+
"multi-system",
|
|
18
|
+
"ambiguous requirements",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def needs_deliberation(prompt: str) -> bool:
|
|
23
|
+
"""Enable model reasoning only when a one-shot task signals depth."""
|
|
24
|
+
|
|
25
|
+
lowered = (prompt or "").casefold()
|
|
26
|
+
return any(cue in lowered for cue in _DEEP_CUES)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
__all__ = ["needs_deliberation"]
|