personal memory agent
1# SPDX-License-Identifier: AGPL-3.0-only
2# Copyright (c) 2026 sol pbc
3
4import argparse
5import sys
6
7from think.callosum import callosum_send
8from think.utils import require_solstone, setup_cli
9
10
11def main() -> None:
12 parser = argparse.ArgumentParser(description="Send a notification via callosum")
13 parser.add_argument("message", nargs="+", help="notification message text")
14 parser.add_argument("--title", help="notification title")
15 parser.add_argument("--icon", help="emoji icon")
16 parser.add_argument("--event", default="show", help="event name (default: show)")
17 parser.add_argument("--action", help="URL path to open on click")
18 parser.add_argument("--facet", help="facet context")
19 parser.add_argument("--app", help="source app name")
20 parser.add_argument("--badge", help="badge text or number")
21 parser.add_argument(
22 "--auto-dismiss",
23 type=int,
24 dest="auto_dismiss",
25 help="auto-dismiss after N milliseconds",
26 )
27 parser.add_argument(
28 "--no-dismiss",
29 action="store_true",
30 dest="no_dismiss",
31 help="make notification non-dismissible",
32 )
33
34 args = setup_cli(parser)
35 require_solstone()
36
37 message = " ".join(args.message)
38 kwargs = {"message": message}
39
40 if args.title is not None:
41 kwargs["title"] = args.title
42 if args.icon is not None:
43 kwargs["icon"] = args.icon
44 if args.action is not None:
45 kwargs["action"] = args.action
46 if args.facet is not None:
47 kwargs["facet"] = args.facet
48 if args.app is not None:
49 kwargs["app"] = args.app
50 if args.badge is not None:
51 kwargs["badge"] = args.badge
52 if args.auto_dismiss is not None:
53 kwargs["autoDismiss"] = args.auto_dismiss
54 if args.no_dismiss:
55 kwargs["dismissible"] = False
56
57 ok = callosum_send("notification", args.event, **kwargs)
58 if ok:
59 print("Notification sent", file=sys.stderr)
60 return
61
62 print("Failed to send notification (is callosum running?)", file=sys.stderr)
63 sys.exit(1)
64
65
66if __name__ == "__main__":
67 main()