clideck 1.30.2 → 1.30.4

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.
@@ -10,7 +10,7 @@
10
10
  "canResume": true,
11
11
  "resumeCommand": "claude --resume {{sessionId}}",
12
12
  "sessionIdPattern": "Session ID:\\s+([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})",
13
- "outputMarker": "\u23fa",
13
+ "outputMarker": "",
14
14
  "telemetryConfigPath": "~/.claude/settings.json",
15
15
  "telemetrySetup": "Required for working/idle status, Autopilot, notifications, and mobile remote.\n\nCliDeck will add start/stop hooks to ~/.claude/settings.json. Claude will ask for one-time approval on next launch.",
16
16
  "telemetryAutoSetup": {
@@ -35,7 +35,7 @@
35
35
  "canResume": true,
36
36
  "resumeCommand": "codex resume {{sessionId}}",
37
37
  "sessionIdPattern": "Session:\\s+([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})",
38
- "outputMarker": "\u2022",
38
+ "outputMarker": "",
39
39
  "telemetryConfigPath": "~/.codex/config.toml",
40
40
  "telemetryEnv": {
41
41
  "OTEL_LOGS_EXPORTER": "otlp",
@@ -59,7 +59,7 @@
59
59
  "canResume": true,
60
60
  "resumeCommand": "gemini --resume {{sessionId}}",
61
61
  "sessionIdPattern": "Session ID:\\s+([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})",
62
- "outputMarker": "\u2726",
62
+ "outputMarker": "",
63
63
  "telemetryConfigPath": "~/.gemini/settings.json",
64
64
  "telemetrySetup": "Required for working/idle status, resume, Autopilot, notifications, and mobile remote.\n\nCliDeck will add BeforeAgent/AfterAgent/SessionEnd/BeforeTool hooks to ~/.gemini/settings.json.",
65
65
  "telemetryAutoSetup": {
@@ -77,7 +77,7 @@
77
77
  "canResume": true,
78
78
  "resumeCommand": "opencode --session {{sessionId}}",
79
79
  "sessionIdPattern": "(ses_[a-zA-Z0-9]{10,})",
80
- "outputMarker": "\u2502",
80
+ "outputMarker": "",
81
81
  "bridge": "opencode",
82
82
  "pluginPath": "~/.config/opencode/plugins/clideck-bridge.js",
83
83
  "pluginSetup": "Install the CliDeck bridge plugin to enable real-time status and resume.\n\ncp opencode-plugin/clideck-bridge.js ~/.config/opencode/plugins/",
@@ -85,6 +85,24 @@
85
85
  "label": "Install plugin"
86
86
  }
87
87
  },
88
+ {
89
+ "presetId": "clideck-agent",
90
+ "name": "Clideck Agent",
91
+ "icon": "/img/clideck-agent.svg",
92
+ "command": "clideck-agent",
93
+ "isAgent": true,
94
+ "canResume": true,
95
+ "resumeCommand": "clideck-agent --resume {{sessionId}}",
96
+ "sessionIdPattern": null,
97
+ "outputMarker": "•",
98
+ "telemetryEnabled": true,
99
+ "telemetryEnv": {
100
+ "OTEL_LOGS_EXPORTER": "otlp",
101
+ "OTEL_EXPORTER_OTLP_PROTOCOL": "http/json",
102
+ "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:{{port}}",
103
+ "OTEL_LOGS_EXPORT_INTERVAL": "2000"
104
+ }
105
+ },
88
106
  {
89
107
  "presetId": "shell",
90
108
  "name": "Shell",
package/config.js CHANGED
@@ -124,7 +124,8 @@ function migrate(cfg) {
124
124
  if (cmd.sessionIdPattern === undefined) cmd.sessionIdPattern = preset?.sessionIdPattern || null;
125
125
  if (cmd.outputMarker === undefined) cmd.outputMarker = preset?.outputMarker || null;
126
126
  // Claude Code telemetry is built-in, always on
127
- if (preset?.presetId === 'claude-code') cmd.telemetryEnabled = true;
127
+ if (preset?.telemetryEnabled === true) cmd.telemetryEnabled = true;
128
+ else if (preset?.presetId === 'claude-code') cmd.telemetryEnabled = true;
128
129
  else if (cmd.telemetryEnabled === undefined) cmd.telemetryEnabled = false;
129
130
  if (cmd.telemetryStatus === undefined) cmd.telemetryStatus = null;
130
131
  // Sync bridge config from preset
package/handlers.js CHANGED
@@ -139,64 +139,69 @@ function detectTelemetryConfig(c) {
139
139
  const home = os.homedir();
140
140
  const port = '4000';
141
141
  let changed = false;
142
- let repairedAny = false;
143
- for (const cmd of c.commands || []) {
144
- const bin = binName(cmd.command);
145
- const preset = presets.find(p => binName(p.command) === bin);
146
- if (!preset) continue;
147
- let detected = false;
148
- let reason = '';
149
- if (preset.presetId === 'claude-code') {
150
- try {
151
- const s = JSON.parse(readFileSync(join(home, '.claude', 'settings.json'), 'utf8'));
152
- const hooks = s.hooks || {};
153
- detected = hasExistingHook(hooks.UserPromptSubmit, 'claude-hook.js', 'start')
154
- && hasExistingHook(hooks.Stop, 'claude-hook.js', 'stop')
155
- && hasExistingHook(hooks.StopFailure, 'claude-hook.js', 'stop')
156
- && hasExistingHook(hooks.PreToolUse, 'claude-hook.js', 'menu')
157
- && hooks.Notification?.some(h => h.matcher === 'idle_prompt' && hasExistingHook([h], 'claude-hook.js', 'idle'));
158
- if (!detected) reason = 'Needs re-patch';
159
- } catch {}
160
- } else if (preset.presetId === 'codex') {
161
- try {
162
- const content = readFileSync(join(home, '.codex', 'config.toml'), 'utf8');
163
- detected = codexConfigLooksHealthy(content, port);
164
- if (!detected) reason = 'Needs re-patch';
165
- } catch {}
166
- } else if (preset.presetId === 'gemini-cli') {
167
- try {
168
- const s = JSON.parse(readFileSync(join(home, '.gemini', 'settings.json'), 'utf8'));
169
- const hooks = s.hooks || {};
170
- detected = hasExistingHook(hooks.BeforeAgent, 'gemini-hook.js', 'start')
171
- && hasExistingHook(hooks.AfterAgent, 'gemini-hook.js', 'stop')
172
- && hasExistingHook(hooks.SessionEnd, 'gemini-hook.js', 'stop')
173
- && hasExistingHook(hooks.BeforeTool, 'gemini-hook.js', 'menu');
142
+ const attemptedRepairs = new Set();
143
+
144
+ for (let pass = 0; pass < 2; pass++) {
145
+ let repairedAny = false;
146
+ for (const cmd of c.commands || []) {
147
+ const bin = binName(cmd.command);
148
+ const preset = presets.find(p => binName(p.command) === bin);
149
+ if (!preset) continue;
150
+ let detected = false;
151
+ let reason = '';
152
+ if (preset.presetId === 'claude-code') {
153
+ try {
154
+ const s = JSON.parse(readFileSync(join(home, '.claude', 'settings.json'), 'utf8'));
155
+ const hooks = s.hooks || {};
156
+ detected = hasExistingHook(hooks.UserPromptSubmit, 'claude-hook.js', 'start')
157
+ && hasExistingHook(hooks.Stop, 'claude-hook.js', 'stop')
158
+ && hasExistingHook(hooks.StopFailure, 'claude-hook.js', 'stop')
159
+ && hasExistingHook(hooks.PreToolUse, 'claude-hook.js', 'menu')
160
+ && hooks.Notification?.some(h => h.matcher === 'idle_prompt' && hasExistingHook([h], 'claude-hook.js', 'idle'));
161
+ if (!detected) reason = 'Needs re-patch';
162
+ } catch {}
163
+ } else if (preset.presetId === 'codex') {
164
+ try {
165
+ const content = readFileSync(join(home, '.codex', 'config.toml'), 'utf8');
166
+ detected = codexConfigLooksHealthy(content, port);
167
+ if (!detected) reason = 'Needs re-patch';
168
+ } catch {}
169
+ } else if (preset.presetId === 'gemini-cli') {
170
+ try {
171
+ const s = JSON.parse(readFileSync(join(home, '.gemini', 'settings.json'), 'utf8'));
172
+ const hooks = s.hooks || {};
173
+ detected = hasExistingHook(hooks.BeforeAgent, 'gemini-hook.js', 'start')
174
+ && hasExistingHook(hooks.AfterAgent, 'gemini-hook.js', 'stop')
175
+ && hasExistingHook(hooks.SessionEnd, 'gemini-hook.js', 'stop')
176
+ && hasExistingHook(hooks.BeforeTool, 'gemini-hook.js', 'menu');
177
+ if (!detected) reason = 'Needs re-patch';
178
+ } catch {}
179
+ } else if (preset.presetId === 'opencode') {
180
+ detected = existsSync(join(opencodePluginDir, 'clideck-bridge.js')) || existsSync(join(opencodePluginDir, 'termix-bridge.js'));
174
181
  if (!detected) reason = 'Needs re-patch';
175
- } catch {}
176
- } else if (preset.presetId === 'opencode') {
177
- detected = existsSync(join(opencodePluginDir, 'clideck-bridge.js')) || existsSync(join(opencodePluginDir, 'termix-bridge.js'));
178
- if (!detected) reason = 'Needs re-patch';
179
- } else { continue; }
180
- if (preset.available && preset.minVersion && !preset.versionOk) {
181
- detected = false;
182
- reason = `Update required (${preset.minVersion}+)`;
183
- } else if (!detected && cmd.telemetryEnabled && preset.telemetryAutoSetup && preset.available && preset.versionOk) {
184
- const repaired = applyTelemetryConfig(preset);
185
- if (repaired.success) {
186
- repairedAny = true;
187
- continue;
182
+ } else { continue; }
183
+ if (preset.available && preset.minVersion && !preset.versionOk) {
184
+ detected = false;
185
+ reason = `Update required (${preset.minVersion}+)`;
186
+ } else if (!detected && cmd.telemetryEnabled && preset.telemetryAutoSetup && preset.available && preset.versionOk && !attemptedRepairs.has(preset.presetId)) {
187
+ attemptedRepairs.add(preset.presetId);
188
+ const repaired = applyTelemetryConfig(preset);
189
+ if (repaired.success) {
190
+ repairedAny = true;
191
+ continue;
192
+ }
188
193
  }
194
+ const nextEnabled = detected || (!!cmd.telemetryEnabled && !reason.startsWith('Update required'));
195
+ const nextStatus = detected ? { ok: true } : { ok: false, error: reason || 'Needs setup' };
196
+ if (cmd.telemetryEnabled !== nextEnabled || JSON.stringify(cmd.telemetryStatus || null) !== JSON.stringify(nextStatus)) {
197
+ cmd.telemetryEnabled = nextEnabled;
198
+ cmd.telemetryStatus = nextStatus;
199
+ changed = true;
200
+ }
201
+ preset.health = detected ? { ok: true } : { ok: false, reason: reason || 'Needs setup' };
189
202
  }
190
- const nextEnabled = detected || (!!cmd.telemetryEnabled && !reason.startsWith('Update required'));
191
- const nextStatus = detected ? { ok: true } : { ok: false, error: reason || 'Needs setup' };
192
- if (cmd.telemetryEnabled !== nextEnabled || JSON.stringify(cmd.telemetryStatus || null) !== JSON.stringify(nextStatus)) {
193
- cmd.telemetryEnabled = nextEnabled;
194
- cmd.telemetryStatus = nextStatus;
195
- changed = true;
196
- }
197
- preset.health = detected ? { ok: true } : { ok: false, reason: reason || 'Needs setup' };
203
+ if (!repairedAny) break;
198
204
  }
199
- if (repairedAny) return detectTelemetryConfig(c) || true;
200
205
  if (changed) console.log('Config: synced telemetry/plugin state from detected config files');
201
206
  return changed;
202
207
  }
@@ -251,10 +256,10 @@ function onConnection(ws) {
251
256
  if (choices && sess.presetId === 'codex') {
252
257
  const last = require('./telemetry-receiver').getLastEvent(msg.id);
253
258
  if (!last.startsWith('codex.sse_event:response.completed')) {
254
- console.log(`[codex] menu rejected — lastEvent=${last} session=${msg.id.slice(0,8)}`);
259
+ // console.log(`[codex] menu rejected — lastEvent=${last} session=${msg.id.slice(0,8)}`);
255
260
  choices = null;
256
261
  } else {
257
- console.log(`[codex] menu accepted session=${msg.id.slice(0,8)}`);
262
+ // console.log(`[codex] menu accepted session=${msg.id.slice(0,8)}`);
258
263
  }
259
264
  }
260
265
  if (choices && sess.presetId === 'claude-code' && msg.menuVersion && (sess._menuConsumedVersion || 0) >= msg.menuVersion) {
@@ -509,7 +514,7 @@ function onConnection(ws) {
509
514
  }
510
515
 
511
516
  case 'remote.getHistory': {
512
- ws.send(JSON.stringify({ type: 'remote.history', id: msg.id, turns: transcript.getLastTurns(msg.id, 20) }));
517
+ ws.send(JSON.stringify({ type: 'remote.history', id: msg.id, turns: transcript.getTurns(msg.id, 20, 'end') }));
513
518
  break;
514
519
  }
515
520
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clideck",
3
- "version": "1.30.2",
3
+ "version": "1.30.4",
4
4
  "description": "One screen for all your AI coding agents — run, monitor, and manage multiple CLI agents from a single browser tab",
5
5
  "main": "server.js",
6
6
  "bin": {
package/plugin-loader.js CHANGED
@@ -234,7 +234,7 @@ function buildApi(pluginId, pluginDir, state) {
234
234
 
235
235
  getRoles() { return JSON.parse(JSON.stringify(getConfigFn?.()?.roles || [])); },
236
236
  getProjects() { return JSON.parse(JSON.stringify(getConfigFn?.()?.projects || [])); },
237
- getTranscript(id, n) { return transcript.getLastTurns(id, n || 20); },
237
+ getTranscript(id, n, order) { return transcript.getTurns(id, n || 20, order || 'end'); },
238
238
  detectMenu(lines, presetId) { return transcript.detectMenu(lines, presetId); },
239
239
 
240
240
  addToolbarAction(opts) { state.actions.push({ ...opts, pluginId, slot: 'toolbar' }); },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "autopilot",
3
3
  "name": "Autopilot",
4
- "version": "0.16.0",
4
+ "version": "0.20.0",
5
5
  "author": "CliDeck",
6
6
  "description": "Multi-agent orchestration — routes output between agents automatically. Uses ~50 output tokens per routing decision.",
7
7
  "icon": "<svg class=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 6v6l4 2\"/></svg>",