@phenx-inc/ctlsurf 0.8.0 → 0.9.0
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/out/headless/index.mjs +144 -1
- package/out/headless/index.mjs.map +2 -2
- package/out/main/index.js +144 -0
- package/out/preload/index.js +2 -0
- package/out/renderer/assets/{cssMode-BQN8v2ok.js → cssMode-BdYp0fp9.js} +3 -3
- package/out/renderer/assets/{freemarker2-DbxGYYVp.js → freemarker2-Cya-9zr-.js} +1 -1
- package/out/renderer/assets/{handlebars-3auU1CAd.js → handlebars-EJs9W5Ub.js} +1 -1
- package/out/renderer/assets/{html-D8xFiRmI.js → html-Ex4qy2lh.js} +1 -1
- package/out/renderer/assets/{htmlMode-M3MApZ4n.js → htmlMode-CCm0aJ6C.js} +3 -3
- package/out/renderer/assets/{index---H6cxNl.js → index-Cj7K9-Ba.js} +265 -242
- package/out/renderer/assets/{index-B-iM7dFC.css → index-nvsNYP5c.css} +34 -0
- package/out/renderer/assets/{javascript-BO_ViZM5.js → javascript-B2niCouI.js} +2 -2
- package/out/renderer/assets/{jsonMode-CKp2zvZu.js → jsonMode-BgCUHaFo.js} +3 -3
- package/out/renderer/assets/{liquid-C1eHcrht.js → liquid-DOQmSo4G.js} +1 -1
- package/out/renderer/assets/{lspLanguageFeatures-CHWJx_Tl.js → lspLanguageFeatures-8SIcRAMh.js} +1 -1
- package/out/renderer/assets/{mdx-Qqdtk7fL.js → mdx-DuKdGNKE.js} +1 -1
- package/out/renderer/assets/{python-DKu7rNbs.js → python-BUa4XFG-.js} +1 -1
- package/out/renderer/assets/{razor-BOMpCo6z.js → razor-BUw8jho0.js} +1 -1
- package/out/renderer/assets/{transformers.web-DtSCnG36.js → transformers.web-_PuZoIho.js} +824 -19
- package/out/renderer/assets/{tsMode-yAjlPR-D.js → tsMode-8FLRnobw.js} +1 -1
- package/out/renderer/assets/{typescript-BiJRCUcL.js → typescript-rdwAjCi4.js} +1 -1
- package/out/renderer/assets/{xml-D4PvYeQq.js → xml-HOzT59Qg.js} +1 -1
- package/out/renderer/assets/{yaml-BeHVkmnS.js → yaml-B81JfLsW.js} +1 -1
- package/out/renderer/index.html +64 -2
- package/out/repro-toggle.mjs +305 -0
- package/package.json +1 -1
- package/src/main/index.ts +2 -0
- package/src/main/orchestrator.ts +13 -1
- package/src/main/transcripts.ts +134 -0
- package/src/preload/index.ts +3 -0
- package/src/renderer/App.tsx +25 -11
- package/src/renderer/components/FloatingMic.tsx +48 -0
- package/src/renderer/components/VoiceInput.tsx +36 -149
- package/src/renderer/index.html +62 -0
- package/src/renderer/lib/localWhisper.ts +46 -2
- package/src/renderer/lib/speech.ts +18 -0
- package/src/renderer/styles.css +34 -0
package/out/main/index.js
CHANGED
|
@@ -6282,6 +6282,138 @@ function capLength(str) {
|
|
|
6282
6282
|
if (str.length <= MAX_ENTRY_CHARS) return str;
|
|
6283
6283
|
return str.slice(0, MAX_ENTRY_CHARS) + `… [truncated, ${str.length} total chars]`;
|
|
6284
6284
|
}
|
|
6285
|
+
function readLatestAssistantReply(opts) {
|
|
6286
|
+
try {
|
|
6287
|
+
const cwd = stripTrailingSep(opts.cwd);
|
|
6288
|
+
if (opts.agentId === "claude") {
|
|
6289
|
+
const file = mostRecentClaudeFile(cwd, opts.claudeProjectsDir);
|
|
6290
|
+
if (!file) return null;
|
|
6291
|
+
const text = lastClaudeAssistant(file, cwd);
|
|
6292
|
+
return text ? capLength(text) : null;
|
|
6293
|
+
}
|
|
6294
|
+
const codexRoot = opts.codexSessionsDir || path.join(os.homedir(), ".codex", "sessions");
|
|
6295
|
+
for (const file of recentCodexRollouts(codexRoot)) {
|
|
6296
|
+
const text = lastCodexAgentMessage(file, cwd);
|
|
6297
|
+
if (text) return capLength(text);
|
|
6298
|
+
}
|
|
6299
|
+
return null;
|
|
6300
|
+
} catch {
|
|
6301
|
+
return null;
|
|
6302
|
+
}
|
|
6303
|
+
}
|
|
6304
|
+
function readLines(file) {
|
|
6305
|
+
try {
|
|
6306
|
+
return fs.readFileSync(file, "utf-8").split("\n");
|
|
6307
|
+
} catch {
|
|
6308
|
+
return [];
|
|
6309
|
+
}
|
|
6310
|
+
}
|
|
6311
|
+
function mostRecentClaudeFile(cwd, root) {
|
|
6312
|
+
const projectsRoot = root || path.join(os.homedir(), ".claude", "projects");
|
|
6313
|
+
const slug = cwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
6314
|
+
const dir = path.join(projectsRoot, slug);
|
|
6315
|
+
let names;
|
|
6316
|
+
try {
|
|
6317
|
+
names = fs.readdirSync(dir);
|
|
6318
|
+
} catch {
|
|
6319
|
+
return null;
|
|
6320
|
+
}
|
|
6321
|
+
let best = null;
|
|
6322
|
+
let bestMs = -Infinity;
|
|
6323
|
+
for (const name of names) {
|
|
6324
|
+
if (!name.endsWith(".jsonl")) continue;
|
|
6325
|
+
const fp = path.join(dir, name);
|
|
6326
|
+
try {
|
|
6327
|
+
const ms = fs.statSync(fp).mtimeMs;
|
|
6328
|
+
if (ms > bestMs) {
|
|
6329
|
+
bestMs = ms;
|
|
6330
|
+
best = fp;
|
|
6331
|
+
}
|
|
6332
|
+
} catch {
|
|
6333
|
+
}
|
|
6334
|
+
}
|
|
6335
|
+
return best;
|
|
6336
|
+
}
|
|
6337
|
+
function recentCodexRollouts(root) {
|
|
6338
|
+
const dirs = /* @__PURE__ */ new Set();
|
|
6339
|
+
const now = Date.now();
|
|
6340
|
+
for (const ms of [now, now - 24 * 60 * 60 * 1e3]) {
|
|
6341
|
+
const d = new Date(ms);
|
|
6342
|
+
const yyyy = String(d.getFullYear());
|
|
6343
|
+
const mm = String(d.getMonth() + 1).padStart(2, "0");
|
|
6344
|
+
const dd = String(d.getDate()).padStart(2, "0");
|
|
6345
|
+
dirs.add(path.join(root, yyyy, mm, dd));
|
|
6346
|
+
}
|
|
6347
|
+
const files = [];
|
|
6348
|
+
for (const dir of dirs) {
|
|
6349
|
+
let names;
|
|
6350
|
+
try {
|
|
6351
|
+
names = fs.readdirSync(dir);
|
|
6352
|
+
} catch {
|
|
6353
|
+
continue;
|
|
6354
|
+
}
|
|
6355
|
+
for (const name of names) {
|
|
6356
|
+
if (!name.startsWith("rollout-") || !name.endsWith(".jsonl")) continue;
|
|
6357
|
+
const fp = path.join(dir, name);
|
|
6358
|
+
try {
|
|
6359
|
+
files.push({ fp, ms: fs.statSync(fp).mtimeMs });
|
|
6360
|
+
} catch {
|
|
6361
|
+
}
|
|
6362
|
+
}
|
|
6363
|
+
}
|
|
6364
|
+
return files.sort((a, b2) => b2.ms - a.ms).map((f) => f.fp);
|
|
6365
|
+
}
|
|
6366
|
+
function lastClaudeAssistant(file, cwd) {
|
|
6367
|
+
const lines = readLines(file);
|
|
6368
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
6369
|
+
const trimmed = lines[i].trim();
|
|
6370
|
+
if (!trimmed) continue;
|
|
6371
|
+
let obj;
|
|
6372
|
+
try {
|
|
6373
|
+
obj = JSON.parse(trimmed);
|
|
6374
|
+
} catch {
|
|
6375
|
+
continue;
|
|
6376
|
+
}
|
|
6377
|
+
if (!obj || typeof obj !== "object") continue;
|
|
6378
|
+
if (obj.isMeta || obj.isSidechain || obj.type !== "assistant") continue;
|
|
6379
|
+
if (typeof obj.cwd === "string" && stripTrailingSep(obj.cwd) !== cwd) continue;
|
|
6380
|
+
const text = extractClaudeText(obj.message?.content, false);
|
|
6381
|
+
if (text) return text;
|
|
6382
|
+
}
|
|
6383
|
+
return null;
|
|
6384
|
+
}
|
|
6385
|
+
function lastCodexAgentMessage(file, cwd) {
|
|
6386
|
+
const lines = readLines(file);
|
|
6387
|
+
for (const line of lines) {
|
|
6388
|
+
const trimmed = line.trim();
|
|
6389
|
+
if (!trimmed) continue;
|
|
6390
|
+
let obj;
|
|
6391
|
+
try {
|
|
6392
|
+
obj = JSON.parse(trimmed);
|
|
6393
|
+
} catch {
|
|
6394
|
+
continue;
|
|
6395
|
+
}
|
|
6396
|
+
if (obj?.type === "session_meta") {
|
|
6397
|
+
const metaCwd = obj.payload?.cwd;
|
|
6398
|
+
if (typeof metaCwd === "string" && stripTrailingSep(metaCwd) !== cwd) return null;
|
|
6399
|
+
break;
|
|
6400
|
+
}
|
|
6401
|
+
}
|
|
6402
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
6403
|
+
const trimmed = lines[i].trim();
|
|
6404
|
+
if (!trimmed) continue;
|
|
6405
|
+
let obj;
|
|
6406
|
+
try {
|
|
6407
|
+
obj = JSON.parse(trimmed);
|
|
6408
|
+
} catch {
|
|
6409
|
+
continue;
|
|
6410
|
+
}
|
|
6411
|
+
if (obj?.type !== "event_msg" || obj.payload?.type !== "agent_message") continue;
|
|
6412
|
+
const text = typeof obj.payload.message === "string" ? obj.payload.message.trim() : "";
|
|
6413
|
+
if (text && !isCodexNoise(text)) return text;
|
|
6414
|
+
}
|
|
6415
|
+
return null;
|
|
6416
|
+
}
|
|
6285
6417
|
var bufferUtil = { exports: {} };
|
|
6286
6418
|
var constants;
|
|
6287
6419
|
var hasRequiredConstants;
|
|
@@ -11011,6 +11143,17 @@ class Orchestrator {
|
|
|
11011
11143
|
get speakRepliesEnabled() {
|
|
11012
11144
|
return !!this.settings.speakReplies;
|
|
11013
11145
|
}
|
|
11146
|
+
// Latest assistant reply from a tab's transcript, for on-demand "read aloud".
|
|
11147
|
+
// Defaults to the active tab. Returns null when the tab's agent has no native
|
|
11148
|
+
// transcript (only Claude Code / Codex do) or nothing has been said yet. Reads
|
|
11149
|
+
// the transcript directly, so it works regardless of the speakReplies setting.
|
|
11150
|
+
getLastReply(tabId) {
|
|
11151
|
+
const id = tabId || this.activeTabId;
|
|
11152
|
+
if (!id) return null;
|
|
11153
|
+
const tab = this.tabs.get(id);
|
|
11154
|
+
if (!tab || !supportsTranscriptLogging(tab.agent.id)) return null;
|
|
11155
|
+
return readLatestAssistantReply({ agentId: tab.agent.id, cwd: tab.cwd });
|
|
11156
|
+
}
|
|
11014
11157
|
setLogChat(enabled) {
|
|
11015
11158
|
this.settings.logChat = enabled;
|
|
11016
11159
|
this.saveSettings();
|
|
@@ -11793,6 +11936,7 @@ electron.ipcMain.handle("speak:set", (_event, enabled) => {
|
|
|
11793
11936
|
orchestrator.setSpeakReplies(!!enabled);
|
|
11794
11937
|
return { enabled: orchestrator.speakRepliesEnabled };
|
|
11795
11938
|
});
|
|
11939
|
+
electron.ipcMain.handle("agent:getLastReply", () => orchestrator.getLastReply());
|
|
11796
11940
|
electron.ipcMain.handle("tracking:get", () => ({ active: orchestrator.isActiveTabTracking() }));
|
|
11797
11941
|
electron.ipcMain.handle("tracking:set", async (_event, enabled) => {
|
|
11798
11942
|
await orchestrator.setActiveTabTracking(enabled);
|
package/out/preload/index.js
CHANGED
|
@@ -69,6 +69,8 @@ const api = {
|
|
|
69
69
|
electron.ipcRenderer.on("agent:message", listener);
|
|
70
70
|
return () => electron.ipcRenderer.removeListener("agent:message", listener);
|
|
71
71
|
},
|
|
72
|
+
// Latest assistant reply from the active tab's transcript (null if none).
|
|
73
|
+
getLastReply: () => electron.ipcRenderer.invoke("agent:getLastReply"),
|
|
72
74
|
// Filesystem
|
|
73
75
|
readDir: (dirPath) => electron.ipcRenderer.invoke("fs:readDir", dirPath),
|
|
74
76
|
readFile: (filePath) => electron.ipcRenderer.invoke("fs:readFile", filePath),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { c as createWebWorker, l as languages } from "./index
|
|
2
|
-
import { C as CompletionAdapter, H as HoverAdapter, D as DocumentHighlightAdapter, a as DefinitionAdapter, R as ReferenceAdapter, b as DocumentSymbolAdapter, c as RenameAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, e as DiagnosticsAdapter, S as SelectionRangeAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider } from "./lspLanguageFeatures-
|
|
3
|
-
import { h, i, j, t, k } from "./lspLanguageFeatures-
|
|
1
|
+
import { c as createWebWorker, l as languages } from "./index-Cj7K9-Ba.js";
|
|
2
|
+
import { C as CompletionAdapter, H as HoverAdapter, D as DocumentHighlightAdapter, a as DefinitionAdapter, R as ReferenceAdapter, b as DocumentSymbolAdapter, c as RenameAdapter, d as DocumentColorAdapter, F as FoldingRangeAdapter, e as DiagnosticsAdapter, S as SelectionRangeAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider } from "./lspLanguageFeatures-8SIcRAMh.js";
|
|
3
|
+
import { h, i, j, t, k } from "./lspLanguageFeatures-8SIcRAMh.js";
|
|
4
4
|
const STOP_WHEN_IDLE_FOR = 2 * 60 * 1e3;
|
|
5
5
|
class WorkerManager {
|
|
6
6
|
constructor(defaults) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { c as createWebWorker, l as languages } from "./index
|
|
2
|
-
import { H as HoverAdapter, D as DocumentHighlightAdapter, h as DocumentLinkAdapter, F as FoldingRangeAdapter, b as DocumentSymbolAdapter, S as SelectionRangeAdapter, c as RenameAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter } from "./lspLanguageFeatures-
|
|
3
|
-
import { a, e, d, R, i, j, t, k } from "./lspLanguageFeatures-
|
|
1
|
+
import { c as createWebWorker, l as languages } from "./index-Cj7K9-Ba.js";
|
|
2
|
+
import { H as HoverAdapter, D as DocumentHighlightAdapter, h as DocumentLinkAdapter, F as FoldingRangeAdapter, b as DocumentSymbolAdapter, S as SelectionRangeAdapter, c as RenameAdapter, f as DocumentFormattingEditProvider, g as DocumentRangeFormattingEditProvider, C as CompletionAdapter } from "./lspLanguageFeatures-8SIcRAMh.js";
|
|
3
|
+
import { a, e, d, R, i, j, t, k } from "./lspLanguageFeatures-8SIcRAMh.js";
|
|
4
4
|
const STOP_WHEN_IDLE_FOR = 2 * 60 * 1e3;
|
|
5
5
|
class WorkerManager {
|
|
6
6
|
constructor(defaults) {
|