personal memory agent
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor(observer): extract create/revoke helpers from observer_cli

Keep observer registration writes behind shared helpers so install can reuse the same key lifecycle without duplicating CLI behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

+67 -32
+67 -32
observe/observer_cli.py
··· 107 107 return dt.strftime("%Y-%m-%d %H:%M") 108 108 109 109 110 - # === Subcommands === 111 - 112 - 113 - def cmd_create(args: argparse.Namespace) -> int: 114 - """Create a new observer registration.""" 115 - name = args.name 116 - 117 - if find_observer_by_name(name): 118 - print(f"Error: observer '{name}' already exists", file=sys.stderr) 119 - return 1 110 + def create_observer_record( 111 + name: str, *, permit_duplicate_name: bool = False 112 + ) -> tuple[dict, str]: 113 + """Create and save an observer record, returning the record and raw key.""" 114 + existing_active = [ 115 + observer 116 + for observer in list_observers() 117 + if observer.get("name") == name and not observer.get("revoked", False) 118 + ] 119 + if existing_active and not permit_duplicate_name: 120 + raise ValueError(f"observer already exists: {name}") 120 121 121 122 key = _generate_key() 122 123 observer_data = { ··· 133 134 } 134 135 135 136 if not save_observer(observer_data): 136 - print("Error: failed to save observer", file=sys.stderr) 137 - return 1 137 + raise RuntimeError("failed to save observer") 138 138 139 139 log_app_action( 140 140 app="observer", ··· 142 142 action="observer_create", 143 143 params={"name": name, "key_prefix": key[:8]}, 144 144 ) 145 + return observer_data, key 146 + 147 + 148 + def revoke_observer_record(identifier: str) -> dict: 149 + """Revoke an observer registration and return the mutated record.""" 150 + observer = _find_observer(identifier) 151 + if not observer: 152 + raise ValueError(f"observer not found: {identifier}") 153 + 154 + if observer.get("revoked", False): 155 + raise ValueError(f"observer already revoked: {observer.get('name')}") 156 + 157 + name = observer.get("name", "") 158 + key_prefix = observer.get("key", "")[:8] 159 + observer["revoked"] = True 160 + observer["revoked_at"] = now_ms() 161 + 162 + if not save_observer(observer): 163 + raise RuntimeError("failed to save observer") 164 + 165 + log_app_action( 166 + app="observer", 167 + facet=None, 168 + action="observer_revoke", 169 + params={"name": name, "key_prefix": key_prefix}, 170 + ) 171 + return observer 172 + 173 + 174 + # === Subcommands === 175 + 176 + 177 + def cmd_create(args: argparse.Namespace) -> int: 178 + """Create a new observer registration.""" 179 + name = args.name 180 + 181 + try: 182 + observer_data, key = create_observer_record(name) 183 + except ValueError: 184 + print(f"Error: observer '{name}' already exists", file=sys.stderr) 185 + return 1 186 + except RuntimeError: 187 + print("Error: failed to save observer", file=sys.stderr) 188 + return 1 145 189 146 190 if args.json_output: 147 191 print(json.dumps({"name": name, "key": key, "prefix": key[:8]})) ··· 219 263 """Revoke an observer registration (soft-delete).""" 220 264 identifier = args.identifier 221 265 222 - observer = _find_observer(identifier) 223 - if not observer: 224 - print(f"Error: observer '{identifier}' not found", file=sys.stderr) 266 + try: 267 + observer = revoke_observer_record(identifier) 268 + except ValueError as exc: 269 + message = str(exc) 270 + if message.startswith("observer not found:"): 271 + print(f"Error: observer '{identifier}' not found", file=sys.stderr) 272 + return 1 273 + name = message.removeprefix("observer already revoked: ") 274 + print(f"Observer '{name}' is already revoked.", file=sys.stderr) 225 275 return 1 226 - 227 - if observer.get("revoked", False): 228 - print(f"Observer '{observer.get('name')}' is already revoked.", file=sys.stderr) 276 + except RuntimeError: 277 + print("Error: failed to save observer", file=sys.stderr) 229 278 return 1 230 279 231 280 name = observer.get("name", "") 232 281 key_prefix = observer.get("key", "")[:8] 233 - 234 - observer["revoked"] = True 235 - observer["revoked_at"] = now_ms() 236 - 237 - if not save_observer(observer): 238 - print("Error: failed to save observer", file=sys.stderr) 239 - return 1 240 - 241 - log_app_action( 242 - app="observer", 243 - facet=None, 244 - action="observer_revoke", 245 - params={"name": name, "key_prefix": key_prefix}, 246 - ) 247 282 248 283 if args.json_output: 249 284 print(json.dumps({"name": name, "prefix": key_prefix, "revoked": True}))