frontier-council 0.1.1__py3-none-any.whl → 0.1.3__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.
- frontier_council/__init__.py +1 -1
- frontier_council/cli.py +75 -3
- {frontier_council-0.1.1.dist-info → frontier_council-0.1.3.dist-info}/METADATA +8 -1
- frontier_council-0.1.3.dist-info/RECORD +8 -0
- frontier_council-0.1.1.dist-info/RECORD +0 -8
- {frontier_council-0.1.1.dist-info → frontier_council-0.1.3.dist-info}/WHEEL +0 -0
- {frontier_council-0.1.1.dist-info → frontier_council-0.1.3.dist-info}/entry_points.txt +0 -0
- {frontier_council-0.1.1.dist-info → frontier_council-0.1.3.dist-info}/licenses/LICENSE +0 -0
frontier_council/__init__.py
CHANGED
frontier_council/cli.py
CHANGED
|
@@ -4,11 +4,27 @@ import argparse
|
|
|
4
4
|
import json
|
|
5
5
|
import os
|
|
6
6
|
import random
|
|
7
|
+
import re
|
|
7
8
|
import subprocess
|
|
8
9
|
import sys
|
|
9
10
|
from datetime import datetime
|
|
10
11
|
from pathlib import Path
|
|
11
12
|
|
|
13
|
+
|
|
14
|
+
def get_sessions_dir() -> Path:
|
|
15
|
+
"""Get the sessions directory, creating if needed."""
|
|
16
|
+
sessions_dir = Path.home() / ".frontier-council" / "sessions"
|
|
17
|
+
sessions_dir.mkdir(parents=True, exist_ok=True)
|
|
18
|
+
return sessions_dir
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def slugify(text: str, max_len: int = 40) -> str:
|
|
22
|
+
"""Convert text to a filename-safe slug."""
|
|
23
|
+
text = text.lower()
|
|
24
|
+
text = re.sub(r'[^\w\s-]', '', text)
|
|
25
|
+
text = re.sub(r'[\s_-]+', '-', text)
|
|
26
|
+
return text[:max_len].strip('-')
|
|
27
|
+
|
|
12
28
|
from .council import (
|
|
13
29
|
COUNCIL,
|
|
14
30
|
detect_social_context,
|
|
@@ -28,7 +44,7 @@ Examples:
|
|
|
28
44
|
frontier-council "Architecture choice" --rounds 3 --output transcript.md
|
|
29
45
|
""",
|
|
30
46
|
)
|
|
31
|
-
parser.add_argument("question", help="The question for the council to deliberate")
|
|
47
|
+
parser.add_argument("question", nargs="?", help="The question for the council to deliberate")
|
|
32
48
|
parser.add_argument(
|
|
33
49
|
"--rounds",
|
|
34
50
|
type=int,
|
|
@@ -78,8 +94,37 @@ Examples:
|
|
|
78
94
|
choices=[1, 2, 3, 4, 5],
|
|
79
95
|
help="Which speaker (1-5) should be devil's advocate (default: random)",
|
|
80
96
|
)
|
|
97
|
+
parser.add_argument(
|
|
98
|
+
"--no-save",
|
|
99
|
+
action="store_true",
|
|
100
|
+
help="Don't auto-save transcript to ~/.frontier-council/sessions/",
|
|
101
|
+
)
|
|
102
|
+
parser.add_argument(
|
|
103
|
+
"--sessions",
|
|
104
|
+
action="store_true",
|
|
105
|
+
help="List recent sessions and exit",
|
|
106
|
+
)
|
|
81
107
|
args = parser.parse_args()
|
|
82
108
|
|
|
109
|
+
# Handle --sessions flag
|
|
110
|
+
if args.sessions:
|
|
111
|
+
sessions_dir = get_sessions_dir()
|
|
112
|
+
sessions = sorted(sessions_dir.glob("*.md"), key=lambda p: p.stat().st_mtime, reverse=True)
|
|
113
|
+
if not sessions:
|
|
114
|
+
print("No sessions found.")
|
|
115
|
+
else:
|
|
116
|
+
print(f"Sessions in {sessions_dir}:\n")
|
|
117
|
+
for s in sessions[:20]: # Show last 20
|
|
118
|
+
mtime = datetime.fromtimestamp(s.stat().st_mtime).strftime("%Y-%m-%d %H:%M")
|
|
119
|
+
print(f" {mtime} {s.name}")
|
|
120
|
+
if len(sessions) > 20:
|
|
121
|
+
print(f"\n ... and {len(sessions) - 20} more")
|
|
122
|
+
sys.exit(0)
|
|
123
|
+
|
|
124
|
+
# Require question for normal operation
|
|
125
|
+
if not args.question:
|
|
126
|
+
parser.error("the following arguments are required: question")
|
|
127
|
+
|
|
83
128
|
# Auto-detect social context if not explicitly set
|
|
84
129
|
social_mode = args.social or detect_social_context(args.question)
|
|
85
130
|
if social_mode and not args.social and not args.quiet:
|
|
@@ -153,12 +198,38 @@ Examples:
|
|
|
153
198
|
print("=" * 60)
|
|
154
199
|
print()
|
|
155
200
|
|
|
156
|
-
# Save transcript
|
|
201
|
+
# Save transcript to user-specified location
|
|
157
202
|
if args.output:
|
|
158
203
|
Path(args.output).write_text(transcript)
|
|
159
204
|
if not args.quiet:
|
|
160
205
|
print(f"Transcript saved to: {args.output}")
|
|
161
206
|
|
|
207
|
+
# Auto-save to sessions directory
|
|
208
|
+
session_path = None
|
|
209
|
+
if not args.no_save:
|
|
210
|
+
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
|
|
211
|
+
slug = slugify(args.question)
|
|
212
|
+
filename = f"{timestamp}-{slug}.md"
|
|
213
|
+
session_path = get_sessions_dir() / filename
|
|
214
|
+
|
|
215
|
+
# Build full session content with metadata header
|
|
216
|
+
session_content = f"""# Council Session
|
|
217
|
+
|
|
218
|
+
**Question:** {args.question}
|
|
219
|
+
**Date:** {datetime.now().strftime("%Y-%m-%d %H:%M")}
|
|
220
|
+
**Rounds:** {args.rounds}
|
|
221
|
+
**Mode:** {"named" if args.named else "anonymous"}, {"blind" if use_blind else "no blind"}{", social" if social_mode else ""}
|
|
222
|
+
{f"**Context:** {args.context}" if args.context else ""}
|
|
223
|
+
{f"**Persona:** {args.persona}" if args.persona else ""}
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
{transcript}
|
|
228
|
+
"""
|
|
229
|
+
session_path.write_text(session_content)
|
|
230
|
+
if not args.quiet:
|
|
231
|
+
print(f"Session saved to: {session_path}")
|
|
232
|
+
|
|
162
233
|
# Share via gist
|
|
163
234
|
gist_url = None
|
|
164
235
|
if args.share:
|
|
@@ -190,10 +261,11 @@ Examples:
|
|
|
190
261
|
print("Error: 'gh' CLI not found. Install with: brew install gh", file=sys.stderr)
|
|
191
262
|
|
|
192
263
|
# Log to history
|
|
193
|
-
history_file =
|
|
264
|
+
history_file = get_sessions_dir().parent / "history.jsonl"
|
|
194
265
|
log_entry = {
|
|
195
266
|
"timestamp": datetime.now().isoformat(),
|
|
196
267
|
"question": args.question[:200],
|
|
268
|
+
"session": str(session_path) if session_path else None,
|
|
197
269
|
"gist": gist_url,
|
|
198
270
|
"context": args.context,
|
|
199
271
|
"rounds": args.rounds,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: frontier-council
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Multi-model deliberation for important decisions. 5 frontier LLMs debate, then a judge synthesizes consensus.
|
|
5
5
|
Project-URL: Homepage, https://github.com/terry-li-hm/frontier-council
|
|
6
6
|
Project-URL: Repository, https://github.com/terry-li-hm/frontier-council
|
|
@@ -80,8 +80,13 @@ frontier-council "Career question" --output transcript.md
|
|
|
80
80
|
|
|
81
81
|
# Share via GitHub Gist
|
|
82
82
|
frontier-council "Important decision" --share
|
|
83
|
+
|
|
84
|
+
# List past sessions
|
|
85
|
+
frontier-council --sessions
|
|
83
86
|
```
|
|
84
87
|
|
|
88
|
+
All sessions are auto-saved to `~/.frontier-council/sessions/` for later review.
|
|
89
|
+
|
|
85
90
|
## Options
|
|
86
91
|
|
|
87
92
|
| Flag | Description |
|
|
@@ -96,6 +101,8 @@ frontier-council "Important decision" --share
|
|
|
96
101
|
| `--persona TEXT` | Context about the person asking |
|
|
97
102
|
| `--advocate N` | Which speaker (1-5) should be devil's advocate (default: random) |
|
|
98
103
|
| `--quiet` | Suppress progress output |
|
|
104
|
+
| `--sessions` | List recent saved sessions |
|
|
105
|
+
| `--no-save` | Don't auto-save transcript to ~/.frontier-council/sessions/ |
|
|
99
106
|
|
|
100
107
|
## How It Works
|
|
101
108
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
frontier_council/__init__.py,sha256=lJJIdVKStG2zLYlKMtvIpxK3S2D0NsWK_ZIKc86y2VM,357
|
|
2
|
+
frontier_council/cli.py,sha256=JQ_4Hd5vqALEbLBA4madX9u5PN7oLy59MjmSfveiNV4,9925
|
|
3
|
+
frontier_council/council.py,sha256=u2ir34dNostBOhXUi1R0wFEfBIEgiRX8thiS5lRFnnU,30226
|
|
4
|
+
frontier_council-0.1.3.dist-info/METADATA,sha256=x3rZJOZpRNikTs8DOVwiHA4w7G4V_p4dvEYSNfnowvA,5229
|
|
5
|
+
frontier_council-0.1.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
6
|
+
frontier_council-0.1.3.dist-info/entry_points.txt,sha256=I3xjPK-nupfQz5PANVXUnXjuxlP-4-mykkA3wXhFOGY,63
|
|
7
|
+
frontier_council-0.1.3.dist-info/licenses/LICENSE,sha256=8qmwox7khp-AakNVvL-Ga25eYbsCtLx8RyXM4zKkX0w,1065
|
|
8
|
+
frontier_council-0.1.3.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
frontier_council/__init__.py,sha256=E9pFFmwBgrMqWytSCigjEnJ6sI_NpufL3FvXaYCnW1A,357
|
|
2
|
-
frontier_council/cli.py,sha256=BbM1cHWjAA0DBn4uyGKajaNAMxhKYQt-ZGNQ6hTnlkc,7337
|
|
3
|
-
frontier_council/council.py,sha256=u2ir34dNostBOhXUi1R0wFEfBIEgiRX8thiS5lRFnnU,30226
|
|
4
|
-
frontier_council-0.1.1.dist-info/METADATA,sha256=43yN-RjPztdcYqeuyljSt96KboV36tjOqCn3J70RPik,4973
|
|
5
|
-
frontier_council-0.1.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
6
|
-
frontier_council-0.1.1.dist-info/entry_points.txt,sha256=I3xjPK-nupfQz5PANVXUnXjuxlP-4-mykkA3wXhFOGY,63
|
|
7
|
-
frontier_council-0.1.1.dist-info/licenses/LICENSE,sha256=8qmwox7khp-AakNVvL-Ga25eYbsCtLx8RyXM4zKkX0w,1065
|
|
8
|
-
frontier_council-0.1.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|