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 @@
|
||||
"""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"]
|
||||
}
|
||||
Reference in New Issue
Block a user