frontier-council 0.1.1__tar.gz → 0.1.2__tar.gz
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-0.1.1 → frontier_council-0.1.2}/PKG-INFO +8 -1
- {frontier_council-0.1.1 → frontier_council-0.1.2}/README.md +7 -0
- {frontier_council-0.1.1 → frontier_council-0.1.2}/frontier_council/__init__.py +1 -1
- {frontier_council-0.1.1 → frontier_council-0.1.2}/frontier_council/cli.py +70 -2
- {frontier_council-0.1.1 → frontier_council-0.1.2}/pyproject.toml +1 -1
- {frontier_council-0.1.1 → frontier_council-0.1.2}/.gitignore +0 -0
- {frontier_council-0.1.1 → frontier_council-0.1.2}/LICENSE +0 -0
- {frontier_council-0.1.1 → frontier_council-0.1.2}/frontier_council/council.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: frontier-council
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
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
|
|
|
@@ -57,8 +57,13 @@ frontier-council "Career question" --output transcript.md
|
|
|
57
57
|
|
|
58
58
|
# Share via GitHub Gist
|
|
59
59
|
frontier-council "Important decision" --share
|
|
60
|
+
|
|
61
|
+
# List past sessions
|
|
62
|
+
frontier-council --sessions
|
|
60
63
|
```
|
|
61
64
|
|
|
65
|
+
All sessions are auto-saved to `~/.frontier-council/sessions/` for later review.
|
|
66
|
+
|
|
62
67
|
## Options
|
|
63
68
|
|
|
64
69
|
| Flag | Description |
|
|
@@ -73,6 +78,8 @@ frontier-council "Important decision" --share
|
|
|
73
78
|
| `--persona TEXT` | Context about the person asking |
|
|
74
79
|
| `--advocate N` | Which speaker (1-5) should be devil's advocate (default: random) |
|
|
75
80
|
| `--quiet` | Suppress progress output |
|
|
81
|
+
| `--sessions` | List recent saved sessions |
|
|
82
|
+
| `--no-save` | Don't auto-save transcript to ~/.frontier-council/sessions/ |
|
|
76
83
|
|
|
77
84
|
## How It Works
|
|
78
85
|
|
|
@@ -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,
|
|
@@ -78,8 +94,33 @@ 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
|
+
|
|
83
124
|
# Auto-detect social context if not explicitly set
|
|
84
125
|
social_mode = args.social or detect_social_context(args.question)
|
|
85
126
|
if social_mode and not args.social and not args.quiet:
|
|
@@ -153,12 +194,38 @@ Examples:
|
|
|
153
194
|
print("=" * 60)
|
|
154
195
|
print()
|
|
155
196
|
|
|
156
|
-
# Save transcript
|
|
197
|
+
# Save transcript to user-specified location
|
|
157
198
|
if args.output:
|
|
158
199
|
Path(args.output).write_text(transcript)
|
|
159
200
|
if not args.quiet:
|
|
160
201
|
print(f"Transcript saved to: {args.output}")
|
|
161
202
|
|
|
203
|
+
# Auto-save to sessions directory
|
|
204
|
+
session_path = None
|
|
205
|
+
if not args.no_save:
|
|
206
|
+
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
|
|
207
|
+
slug = slugify(args.question)
|
|
208
|
+
filename = f"{timestamp}-{slug}.md"
|
|
209
|
+
session_path = get_sessions_dir() / filename
|
|
210
|
+
|
|
211
|
+
# Build full session content with metadata header
|
|
212
|
+
session_content = f"""# Council Session
|
|
213
|
+
|
|
214
|
+
**Question:** {args.question}
|
|
215
|
+
**Date:** {datetime.now().strftime("%Y-%m-%d %H:%M")}
|
|
216
|
+
**Rounds:** {args.rounds}
|
|
217
|
+
**Mode:** {"named" if args.named else "anonymous"}, {"blind" if use_blind else "no blind"}{", social" if social_mode else ""}
|
|
218
|
+
{f"**Context:** {args.context}" if args.context else ""}
|
|
219
|
+
{f"**Persona:** {args.persona}" if args.persona else ""}
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
{transcript}
|
|
224
|
+
"""
|
|
225
|
+
session_path.write_text(session_content)
|
|
226
|
+
if not args.quiet:
|
|
227
|
+
print(f"Session saved to: {session_path}")
|
|
228
|
+
|
|
162
229
|
# Share via gist
|
|
163
230
|
gist_url = None
|
|
164
231
|
if args.share:
|
|
@@ -190,10 +257,11 @@ Examples:
|
|
|
190
257
|
print("Error: 'gh' CLI not found. Install with: brew install gh", file=sys.stderr)
|
|
191
258
|
|
|
192
259
|
# Log to history
|
|
193
|
-
history_file =
|
|
260
|
+
history_file = get_sessions_dir().parent / "history.jsonl"
|
|
194
261
|
log_entry = {
|
|
195
262
|
"timestamp": datetime.now().isoformat(),
|
|
196
263
|
"question": args.question[:200],
|
|
264
|
+
"session": str(session_path) if session_path else None,
|
|
197
265
|
"gist": gist_url,
|
|
198
266
|
"context": args.context,
|
|
199
267
|
"rounds": args.rounds,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|