@dmsdc-ai/aigentry-deliberation 0.0.34 → 0.0.36

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.
package/README.md CHANGED
@@ -15,10 +15,14 @@ MCP Deliberation Server — Multi-session AI deliberation with smart speaker ord
15
15
  - **Browser LLM integration**: CDP-based auto-turn for ChatGPT, Claude, Gemini browser tabs
16
16
  - **Chrome Extension support**: Side panel detection via title-based matching
17
17
  - **Cross-platform**: macOS (tmux + Terminal.app), Windows (Windows Terminal), Linux
18
+ - **Telepty bus transport**: structured `turn_request` delivery for telepty-managed sessions
19
+ - **User-confirmed speaker selection**: candidates must be confirmed before a session can start
18
20
  - **Obsidian archiving**: Auto-archive deliberation results to Obsidian vault
19
21
  - **Session monitoring**: Real-time tmux/terminal monitoring
20
22
  - **Vote enforcement**: Automatic [AGREE]/[DISAGREE]/[CONDITIONAL] vote marker requirement
21
23
  - **Dynamic CLI timeout**: Smart cold-start handling (180s first turn, 120s subsequent)
24
+ - **Split telepty timeouts**: 5s transport ack + 60s semantic response tracking
25
+ - **Typed synthesis envelopes**: validated structured payloads for downstream automation
22
26
  - **Runtime logging**: Session lifecycle event logging for observability
23
27
  - **Resilient browser automation**: 5-stage degradation state machine with 60s SLO
24
28
  - **Model routing**: Dynamic per-provider model selection based on prompt analysis
@@ -102,6 +106,7 @@ Claude Code, Codex CLI, Gemini CLI의 MCP 설정을 자동 점검하고 문제
102
106
  | `deliberation_list` | List archived sessions |
103
107
  | `deliberation_reset` | Reset session(s) |
104
108
  | `deliberation_speaker_candidates` | List available speakers |
109
+ | `deliberation_confirm_speakers` | Confirm the exact user-selected speaker set |
105
110
  | `deliberation_browser_llm_tabs` | List browser LLM tabs |
106
111
  | `deliberation_browser_auto_turn` | Auto-send turn to browser LLM |
107
112
  | `deliberation_route_turn` | Route turn to appropriate transport |
@@ -109,6 +114,29 @@ Claude Code, Codex CLI, Gemini CLI의 MCP 설정을 자동 점검하고 문제
109
114
  | `deliberation_cli_auto_turn` | Auto-send turn to CLI speaker |
110
115
  | `deliberation_cli_config` | Configure CLI settings |
111
116
 
117
+ ## Start Flow
118
+
119
+ Manual participant selection is enforced for both CLI speakers and telepty sessions.
120
+
121
+ ```text
122
+ 1. deliberation_speaker_candidates(...)
123
+ 2. User picks speakers in the TUI
124
+ 3. deliberation_confirm_speakers(selection_token: "<candidate-token>", speakers: [...])
125
+ 4. deliberation_start(selection_token: "<confirmed-token>", speakers: [...])
126
+ ```
127
+
128
+ Raw candidate tokens cannot start a deliberation.
129
+
130
+ ## Telepty Transport
131
+
132
+ Telepty-managed sessions are now routed through the telepty bus instead of raw PTY inject guidance.
133
+
134
+ - `deliberation_route_turn` publishes a typed `turn_request` envelope on `ws://localhost:3848/api/bus`
135
+ - transport delivery is tracked with a 5-second `inject_written` ack window
136
+ - semantic completion is tracked with a 60-second self-submit window
137
+ - `session_health` bus events are cached for operator visibility
138
+ - `deliberation_synthesize` validates and emits typed `deliberation_completed` envelopes for downstream automation
139
+
112
140
  ## Speaker Ordering Strategies
113
141
 
114
142
  | Strategy | Description |
@@ -179,6 +207,21 @@ cp skills/deliberation-gate/SKILL.md ~/.claude/skills/deliberation-gate/SKILL.md
179
207
 
180
208
  ## What's New
181
209
 
210
+ ### v0.0.36
211
+ - **README refresh**: clarified the mandatory TUI speaker-selection flow and the confirmed-token handoff before `deliberation_start`
212
+ - **Telepty candidate docs**: documented active telepty session discovery with lightweight `session_id` + `host/pid` locators instead of heavy persisted process snapshots
213
+ - **Cross-project delivery docs**: clarified that active session lookup now resolves across project state directories, which unblocks cross-project `deliberation_respond` flows
214
+ - **Operator guidance**: documented telepty bus transport as the automation path and unmanaged/manual sessions as the fallback path
215
+
216
+ ### v0.0.35
217
+ - **Manual selection enforcement**: `deliberation_confirm_speakers` binds a fresh candidate snapshot to the exact user-picked speaker set before `deliberation_start`
218
+ - **Telepty session candidates**: active telepty sessions appear in speaker discovery with lightweight host/pid locators
219
+ - **Cross-project sessions**: session lookup/load/save now resolves active deliberations across project state directories
220
+ - **Telepty bus routing**: telepty speakers route via typed `turn_request` envelopes with 5s transport and 60s semantic timeout tracking
221
+ - **Structured synthesis envelopes**: `deliberation_synthesize` validates typed payloads before telepty bus publication
222
+ - **Codex CLI hardening**: reduced prompt budgets, lower-friction exec profile, and clearer timeout diagnostics
223
+ - **Packaging**: install path now preserves default config and includes required runtime modules (`clipboard.js`, `decision-engine.js`, `i18n.js`)
224
+
182
225
  ### v0.0.24
183
226
  - **Role inference**: Heading marker weight increased from +5 to +8, added critic(검증/평가/Review) and researcher(데이터/Data) patterns to reduce false positives
184
227
  - **Logging payload**: TURN log includes `suggested_role`, `role_drift`; CLI_TURN log includes `prior_turns`, `effective_timeout`
package/clipboard.js ADDED
@@ -0,0 +1,178 @@
1
+
2
+ import { execFileSync, spawnSync } from "child_process";
3
+
4
+ function commandExistsInPath(command) {
5
+ try {
6
+ const isWin = process.platform === "win32";
7
+ execFileSync(isWin ? "where" : "which", [command], { stdio: "ignore" });
8
+ return true;
9
+ } catch {
10
+ return false;
11
+ }
12
+ }
13
+
14
+ function resolveClipboardReader() {
15
+ if (process.platform === "darwin") {
16
+ if (commandExistsInPath("pbpaste")) {
17
+ return { cmd: "pbpaste", args: [] };
18
+ }
19
+ return { cmd: "osascript", args: ["-e", "get the clipboard as «class utf8»"] };
20
+ }
21
+ if (process.platform === "win32") {
22
+ const windowsShell = ["powershell.exe", "powershell", "pwsh.exe", "pwsh"]
23
+ .find(cmd => commandExistsInPath(cmd));
24
+ if (windowsShell) {
25
+ return { cmd: windowsShell, args: ["-NoProfile", "-Command", "Get-Clipboard -Raw"] };
26
+ }
27
+ }
28
+ if (commandExistsInPath("wl-paste")) {
29
+ return { cmd: "wl-paste", args: ["-n"] };
30
+ }
31
+ if (commandExistsInPath("xclip")) {
32
+ return { cmd: "xclip", args: ["-selection", "clipboard", "-o"] };
33
+ }
34
+ if (commandExistsInPath("xsel")) {
35
+ return { cmd: "xsel", args: ["--clipboard", "--output"] };
36
+ }
37
+ return null;
38
+ }
39
+
40
+ function resolveClipboardWriter() {
41
+ if (process.platform === "darwin") {
42
+ if (commandExistsInPath("pbcopy")) {
43
+ return { cmd: "pbcopy", args: [] };
44
+ }
45
+ return null;
46
+ }
47
+ if (process.platform === "win32") {
48
+ if (commandExistsInPath("clip.exe") || commandExistsInPath("clip")) {
49
+ return { cmd: "clip", args: [] };
50
+ }
51
+ const windowsShell = ["powershell.exe", "powershell", "pwsh.exe", "pwsh"]
52
+ .find(cmd => commandExistsInPath(cmd));
53
+ if (windowsShell) {
54
+ return { cmd: windowsShell, args: ["-NoProfile", "-Command", "[Console]::In.ReadToEnd() | Set-Clipboard"] };
55
+ }
56
+ }
57
+ if (commandExistsInPath("wl-copy")) {
58
+ return { cmd: "wl-copy", args: [] };
59
+ }
60
+ if (commandExistsInPath("xclip")) {
61
+ return { cmd: "xclip", args: ["-selection", "clipboard"] };
62
+ }
63
+ if (commandExistsInPath("xsel")) {
64
+ return { cmd: "xsel", args: ["--clipboard", "--input"] };
65
+ }
66
+ return null;
67
+ }
68
+
69
+ const COMMON_ENV = {
70
+ LANG: "ko_KR.UTF-8",
71
+ LC_ALL: "ko_KR.UTF-8",
72
+ PATH: process.env.PATH
73
+ };
74
+
75
+ export function readClipboardText() {
76
+ const tool = resolveClipboardReader();
77
+ if (!tool) {
78
+ throw new Error("No supported clipboard read command found (pbpaste/wl-paste/xclip/xsel etc).");
79
+ }
80
+ const res = spawnSync(tool.cmd, tool.args, {
81
+ encoding: "utf-8",
82
+ stdio: ["ignore", "pipe", "pipe"],
83
+ maxBuffer: 10 * 1024 * 1024,
84
+ env: COMMON_ENV,
85
+ timeout: 3000,
86
+ });
87
+
88
+ if (res.error) throw res.error;
89
+ if (res.status !== 0) {
90
+ const err = res.stderr ? res.stderr.toString() : "Unknown error";
91
+ throw new Error(`Clipboard read failed: ${err}`);
92
+ }
93
+
94
+ return res.stdout.toString();
95
+ }
96
+
97
+ export function writeClipboardText(text) {
98
+ const tool = resolveClipboardWriter();
99
+
100
+ // AppleScript fallback logic
101
+ const tryAppleScript = (txt) => {
102
+ if (process.platform !== "darwin") return false;
103
+ try {
104
+ const escaped = txt.replace(/["\\]/g, '\\$&');
105
+ const scriptRes = spawnSync("osascript", ["-e", `set the clipboard to "${escaped}"`], { timeout: 3000 });
106
+ return scriptRes.status === 0;
107
+ } catch {
108
+ return false;
109
+ }
110
+ };
111
+
112
+ if (!tool) {
113
+ if (tryAppleScript(text)) return;
114
+ throw new Error("No supported clipboard write command found.");
115
+ }
116
+
117
+ const res = spawnSync(tool.cmd, tool.args, {
118
+ input: text,
119
+ encoding: "utf-8",
120
+ stdio: ["pipe", "ignore", "pipe"],
121
+ maxBuffer: 10 * 1024 * 1024,
122
+ timeout: 3000,
123
+ env: COMMON_ENV
124
+ });
125
+
126
+ if (res.error || res.status !== 0) {
127
+ if (tryAppleScript(text)) return;
128
+ throw res.error || new Error(`Clipboard write failed with status ${res.status}`);
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Capture current clipboard image to a file (macOS only for now)
134
+ * @param {string} targetPath
135
+ * @returns {boolean} success
136
+ */
137
+ export function captureClipboardImage(targetPath) {
138
+ if (process.platform !== "darwin") return false;
139
+
140
+ // Using osascript to save PNG data from clipboard
141
+ const script = `
142
+ try
143
+ set theFile to (POSIX file "${targetPath}")
144
+ set theImage to the clipboard as «class PNGf»
145
+ set theOpenFile to open for access theFile with write permission
146
+ set eof theOpenFile to 0
147
+ write theImage to theOpenFile
148
+ close access theOpenFile
149
+ return true
150
+ on error
151
+ try
152
+ close access theFile
153
+ end try
154
+ return false
155
+ end try
156
+ `;
157
+
158
+ const res = spawnSync("osascript", ["-e", script], { timeout: 5000 });
159
+ return res.stdout.toString().trim() === "true";
160
+ }
161
+
162
+ /**
163
+ * Check if clipboard contains an image
164
+ * @returns {boolean}
165
+ */
166
+ export function hasClipboardImage() {
167
+ if (process.platform !== "darwin") return false;
168
+ const script = `
169
+ try
170
+ (the clipboard as «class PNGf»)
171
+ return true
172
+ on error
173
+ return false
174
+ end try
175
+ `;
176
+ const res = spawnSync("osascript", ["-e", script], { timeout: 3000 });
177
+ return res.stdout.toString().trim() === "true";
178
+ }