ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
from cachelib.cache import Cache
|
||||
|
||||
__all__ = ["Cache"]
|
||||
@@ -0,0 +1,17 @@
|
||||
class Cache:
|
||||
def __init__(self):
|
||||
self._values = {}
|
||||
|
||||
def get(self, key, default=None):
|
||||
return self._values.get(key, default)
|
||||
|
||||
def put(self, key, value):
|
||||
self._values[key] = value
|
||||
|
||||
def get_or_load(self, key, loader):
|
||||
cached = self.get(key)
|
||||
if cached is not None:
|
||||
return cached
|
||||
value = loader(key)
|
||||
self.put(key, value)
|
||||
return value
|
||||
@@ -0,0 +1,7 @@
|
||||
class Catalog:
|
||||
def __init__(self, cache, fetch_product):
|
||||
self.cache = cache
|
||||
self.fetch_product = fetch_product
|
||||
|
||||
def product(self, product_id):
|
||||
return self.cache.get_or_load(product_id, self.fetch_product)
|
||||
@@ -0,0 +1,40 @@
|
||||
import unittest
|
||||
|
||||
from cachelib import Cache
|
||||
|
||||
|
||||
class CacheContractTests(unittest.TestCase):
|
||||
def test_negative_lookup_is_loaded_once(self):
|
||||
cache = Cache()
|
||||
calls = []
|
||||
|
||||
def loader(key):
|
||||
calls.append(key)
|
||||
return None
|
||||
|
||||
self.assertIsNone(cache.get_or_load("missing", loader))
|
||||
self.assertIsNone(cache.get_or_load("missing", loader))
|
||||
self.assertEqual(calls, ["missing"])
|
||||
|
||||
def test_custom_default_still_distinguishes_missing_from_none(self):
|
||||
cache = Cache()
|
||||
marker = object()
|
||||
self.assertIs(cache.get("unknown", marker), marker)
|
||||
cache.put("known-none", None)
|
||||
self.assertIsNone(cache.get("known-none", marker))
|
||||
|
||||
def test_falsey_values_are_cached(self):
|
||||
cache = Cache()
|
||||
calls = []
|
||||
|
||||
def loader(key):
|
||||
calls.append(key)
|
||||
return 0
|
||||
|
||||
self.assertEqual(cache.get_or_load("zero", loader), 0)
|
||||
self.assertEqual(cache.get_or_load("zero", loader), 0)
|
||||
self.assertEqual(calls, ["zero"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"category": "contract-sensitive",
|
||||
"instruction": "Fix the cache so that negative lookups (a loader returning None) are cached instead of reloaded on every call. Preserve the public get(key, default=None), put, and get_or_load APIs, including the ability to distinguish a missing key when a caller supplies a custom default.",
|
||||
"test_command": ["python", "-m", "unittest", "discover", "-s", "tests", "-v"]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
"""Small account service used by the action-threshold experiment."""
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
def authenticate(store, username, password):
|
||||
profile = store.find(username.strip())
|
||||
if profile is None or profile.password != password:
|
||||
return None
|
||||
return profile
|
||||
@@ -0,0 +1,2 @@
|
||||
def lookup_profile(store, username):
|
||||
return store.find(username)
|
||||
@@ -0,0 +1,8 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Profile:
|
||||
username: str
|
||||
email: str
|
||||
password: str
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
from accounts.models import Profile
|
||||
|
||||
|
||||
def register(store, username, email, password):
|
||||
display_name = username.strip()
|
||||
key = display_name.lower()
|
||||
profile = Profile(display_name, email, password)
|
||||
store.save(key, profile)
|
||||
return profile
|
||||
@@ -0,0 +1,11 @@
|
||||
class AccountStore:
|
||||
def __init__(self):
|
||||
self._profiles = {}
|
||||
|
||||
def save(self, key, profile):
|
||||
if key in self._profiles:
|
||||
raise ValueError("username already exists")
|
||||
self._profiles[key] = profile
|
||||
|
||||
def find(self, key):
|
||||
return self._profiles.get(key)
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import unittest
|
||||
|
||||
from accounts.authentication import authenticate
|
||||
from accounts.directory import lookup_profile
|
||||
from accounts.registration import register
|
||||
from accounts.store import AccountStore
|
||||
|
||||
|
||||
class AccountIdentityTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.store = AccountStore()
|
||||
|
||||
def test_registration_preserves_display_name(self):
|
||||
profile = register(self.store, " Alice.Dev ", "a@example.com", "secret")
|
||||
self.assertEqual(profile.username, "Alice.Dev")
|
||||
|
||||
def test_login_ignores_case_and_whitespace(self):
|
||||
register(self.store, "Alice.Dev", "a@example.com", "secret")
|
||||
profile = authenticate(self.store, " ALICE.dev ", "secret")
|
||||
self.assertIsNotNone(profile)
|
||||
self.assertEqual(profile.username, "Alice.Dev")
|
||||
|
||||
def test_directory_lookup_uses_same_identity(self):
|
||||
register(self.store, "Alice.Dev", "a@example.com", "secret")
|
||||
self.assertIsNotNone(lookup_profile(self.store, " alice.DEV "))
|
||||
|
||||
def test_unicode_casefold_and_duplicate_detection(self):
|
||||
register(self.store, "Straße", "one@example.com", "secret")
|
||||
self.assertIsNotNone(authenticate(self.store, "STRASSE", "secret"))
|
||||
with self.assertRaises(ValueError):
|
||||
register(self.store, " strasse ", "two@example.com", "secret")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"category": "cross-cutting",
|
||||
"instruction": "Make usernames case-insensitive and insensitive to surrounding whitespace throughout registration, authentication, and directory lookup. Preserve the user's trimmed display casing in returned profiles, and handle Unicode usernames correctly. Keep the existing public APIs.",
|
||||
"test_command": ["python", "-m", "unittest", "discover", "-s", "tests", "-v"]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
"""Example application package."""
|
||||
@@ -0,0 +1,14 @@
|
||||
"""Runtime timeout configuration."""
|
||||
|
||||
DEFAULT_TIMEOUT = 30
|
||||
|
||||
|
||||
def resolve_timeout(explicit=None, env=None):
|
||||
"""Return a positive timeout using explicit > environment > default."""
|
||||
env = env or {}
|
||||
raw = env.get("AGENT_TIMEOUT", explicit)
|
||||
try:
|
||||
value = int(raw)
|
||||
except (TypeError, ValueError):
|
||||
return DEFAULT_TIMEOUT
|
||||
return value if value > 0 else DEFAULT_TIMEOUT
|
||||
@@ -0,0 +1,7 @@
|
||||
"""Worker construction kept separate from configuration parsing."""
|
||||
|
||||
from app.config import resolve_timeout
|
||||
|
||||
|
||||
def worker_options(timeout=None, env=None):
|
||||
return {"timeout": resolve_timeout(timeout, env), "retries": 2}
|
||||
@@ -0,0 +1,20 @@
|
||||
import unittest
|
||||
|
||||
from app.config import DEFAULT_TIMEOUT, resolve_timeout
|
||||
|
||||
|
||||
class ResolveTimeoutTests(unittest.TestCase):
|
||||
def test_explicit_value_wins_over_environment(self):
|
||||
self.assertEqual(resolve_timeout(12, {"AGENT_TIMEOUT": "45"}), 12)
|
||||
|
||||
def test_environment_is_used_without_explicit_value(self):
|
||||
self.assertEqual(resolve_timeout(None, {"AGENT_TIMEOUT": "45"}), 45)
|
||||
|
||||
def test_invalid_values_use_default(self):
|
||||
self.assertEqual(resolve_timeout("nope", {}), DEFAULT_TIMEOUT)
|
||||
self.assertEqual(resolve_timeout(0, {}), DEFAULT_TIMEOUT)
|
||||
self.assertEqual(resolve_timeout(-2, {}), DEFAULT_TIMEOUT)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"category": "localized",
|
||||
"instruction": "Fix the timeout configuration bug exposed by the tests. The public resolve_timeout API must remain unchanged. Explicit arguments should take precedence over AGENT_TIMEOUT, and invalid or non-positive values should fall back to the default.",
|
||||
"test_command": ["python", "-m", "unittest", "discover", "-s", "tests", "-v"]
|
||||
}
|
||||
Reference in New Issue
Block a user