clitrigger 0.2.8 → 0.2.9
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/dist/client/assets/{index-BjSdQnnM.css → index-BwUXJf1U.css} +1 -1
- package/dist/client/assets/index-DI7n7r9n.js +748 -0
- package/dist/client/index.html +2 -2
- package/dist/server/db/queries.d.ts +15 -1
- package/dist/server/db/queries.d.ts.map +1 -1
- package/dist/server/db/queries.js +51 -0
- package/dist/server/db/queries.js.map +1 -1
- package/dist/server/db/schema.d.ts.map +1 -1
- package/dist/server/db/schema.js +11 -0
- package/dist/server/db/schema.js.map +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +4 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/routes/files.d.ts.map +1 -1
- package/dist/server/routes/files.js +122 -0
- package/dist/server/routes/files.js.map +1 -1
- package/dist/server/routes/logs.d.ts.map +1 -1
- package/dist/server/routes/logs.js +4 -5
- package/dist/server/routes/logs.js.map +1 -1
- package/dist/server/routes/projects.js +2 -2
- package/dist/server/routes/projects.js.map +1 -1
- package/dist/server/routes/session-aliases.d.ts +3 -0
- package/dist/server/routes/session-aliases.d.ts.map +1 -0
- package/dist/server/routes/session-aliases.js +88 -0
- package/dist/server/routes/session-aliases.js.map +1 -0
- package/dist/server/routes/sessions.d.ts.map +1 -1
- package/dist/server/routes/sessions.js +4 -0
- package/dist/server/routes/sessions.js.map +1 -1
- package/dist/server/routes/vault.d.ts +3 -0
- package/dist/server/routes/vault.d.ts.map +1 -0
- package/dist/server/routes/vault.js +184 -0
- package/dist/server/routes/vault.js.map +1 -0
- package/dist/server/services/cli-adapters.d.ts +1 -1
- package/dist/server/services/cli-adapters.d.ts.map +1 -1
- package/dist/server/services/cli-adapters.js +31 -0
- package/dist/server/services/cli-adapters.js.map +1 -1
- package/dist/server/services/discussion-orchestrator.d.ts.map +1 -1
- package/dist/server/services/discussion-orchestrator.js +29 -13
- package/dist/server/services/discussion-orchestrator.js.map +1 -1
- package/dist/server/services/file-scanner.d.ts +26 -0
- package/dist/server/services/file-scanner.d.ts.map +1 -0
- package/dist/server/services/file-scanner.js +244 -0
- package/dist/server/services/file-scanner.js.map +1 -0
- package/dist/server/services/memory-inject-hook.d.ts +3 -1
- package/dist/server/services/memory-inject-hook.d.ts.map +1 -1
- package/dist/server/services/memory-inject-hook.js +49 -0
- package/dist/server/services/memory-inject-hook.js.map +1 -1
- package/dist/server/services/orchestrator.d.ts +2 -0
- package/dist/server/services/orchestrator.d.ts.map +1 -1
- package/dist/server/services/orchestrator.js +5 -10
- package/dist/server/services/orchestrator.js.map +1 -1
- package/dist/server/services/project-status.d.ts +10 -0
- package/dist/server/services/project-status.d.ts.map +1 -0
- package/dist/server/services/project-status.js +34 -0
- package/dist/server/services/project-status.js.map +1 -0
- package/dist/server/services/session-manager.d.ts.map +1 -1
- package/dist/server/services/session-manager.js +19 -2
- package/dist/server/services/session-manager.js.map +1 -1
- package/dist/server/services/vault-injector.d.ts +14 -0
- package/dist/server/services/vault-injector.d.ts.map +1 -0
- package/dist/server/services/vault-injector.js +106 -0
- package/dist/server/services/vault-injector.js.map +1 -0
- package/dist/server/services/vault-retriever.d.ts +7 -0
- package/dist/server/services/vault-retriever.d.ts.map +1 -0
- package/dist/server/services/vault-retriever.js +108 -0
- package/dist/server/services/vault-retriever.js.map +1 -0
- package/dist/server/websocket/events.d.ts +2 -0
- package/dist/server/websocket/events.d.ts.map +1 -1
- package/electron/main.cjs +74 -8
- package/package.json +1 -1
- package/dist/client/assets/index-CCQfo9GC.js +0 -735
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import * as queries from '../db/queries.js';
|
|
2
|
+
import { scanVault } from './file-scanner.js';
|
|
3
|
+
import { runHeadless, resolveCliTool } from './memory-ingest.js';
|
|
4
|
+
const RETRIEVAL_MAX_FILES = 10;
|
|
5
|
+
const RETRIEVAL_TIMEOUT_MS = 60_000;
|
|
6
|
+
const FILE_LIST_BUDGET_CHARS = 7000;
|
|
7
|
+
const TASK_QUERY_MAX_CHARS = 4000;
|
|
8
|
+
function firstSentence(text, maxLen = 140) {
|
|
9
|
+
const flat = text.replace(/\s+/g, ' ').trim();
|
|
10
|
+
if (!flat)
|
|
11
|
+
return '';
|
|
12
|
+
const cut = flat.slice(0, maxLen);
|
|
13
|
+
return cut.length < flat.length ? `${cut}…` : cut;
|
|
14
|
+
}
|
|
15
|
+
function buildCandidatePool(files) {
|
|
16
|
+
const sorted = [...files].sort((a, b) => (b.mtime ?? '').localeCompare(a.mtime ?? ''));
|
|
17
|
+
const lines = [];
|
|
18
|
+
const pathSet = new Set();
|
|
19
|
+
let used = 0;
|
|
20
|
+
for (const f of sorted) {
|
|
21
|
+
const tagStr = f.tags.length > 0 ? ` [${f.tags.join(', ')}]` : '';
|
|
22
|
+
const summary = firstSentence(f.bodyPreview);
|
|
23
|
+
const line = `- path="${f.relativePath}" title="${f.title}"${tagStr}${summary ? ` — ${summary}` : ''}`;
|
|
24
|
+
if (used + line.length > FILE_LIST_BUDGET_CHARS && lines.length > 0)
|
|
25
|
+
break;
|
|
26
|
+
lines.push(line);
|
|
27
|
+
pathSet.add(f.relativePath);
|
|
28
|
+
used += line.length + 1;
|
|
29
|
+
}
|
|
30
|
+
return { lines, pathSet };
|
|
31
|
+
}
|
|
32
|
+
const RETRIEVAL_PROMPT_HEADER = `You are selecting the most relevant wiki files for an upcoming task. The selected files will be injected into the task prompt as long-term context.
|
|
33
|
+
|
|
34
|
+
# Task
|
|
35
|
+
{TASK}
|
|
36
|
+
|
|
37
|
+
# Available wiki files
|
|
38
|
+
{ENTRIES}
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
Output ONLY a JSON array of file paths (no prose, no code fences):
|
|
43
|
+
["path/to/file1.md", "path/to/file2.md"]
|
|
44
|
+
|
|
45
|
+
Rules:
|
|
46
|
+
- Pick at most ${RETRIEVAL_MAX_FILES} files directly relevant to the task.
|
|
47
|
+
- Prefer fewer high-relevance files over many tangential ones.
|
|
48
|
+
- Return [] if nothing is meaningfully relevant — do not pad.`;
|
|
49
|
+
function safeParsePathArray(raw, validPaths) {
|
|
50
|
+
const cleaned = raw.trim().replace(/^```(?:json)?\s*/, '').replace(/\s*```\s*$/, '');
|
|
51
|
+
let parsed;
|
|
52
|
+
try {
|
|
53
|
+
parsed = JSON.parse(cleaned);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
const m = cleaned.match(/\[[\s\S]*\]/);
|
|
57
|
+
if (!m)
|
|
58
|
+
return [];
|
|
59
|
+
try {
|
|
60
|
+
parsed = JSON.parse(m[0]);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (!Array.isArray(parsed))
|
|
67
|
+
return [];
|
|
68
|
+
const paths = [];
|
|
69
|
+
for (const item of parsed) {
|
|
70
|
+
const p = String(item);
|
|
71
|
+
if (validPaths.has(p) && !paths.includes(p))
|
|
72
|
+
paths.push(p);
|
|
73
|
+
if (paths.length >= RETRIEVAL_MAX_FILES)
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
return paths;
|
|
77
|
+
}
|
|
78
|
+
export async function selectRelevantFiles(projectId, projectRoot, taskQuery, excludePatterns) {
|
|
79
|
+
const project = queries.getProjectById(projectId);
|
|
80
|
+
if (!project)
|
|
81
|
+
return { selectedPaths: [], candidateCount: 0, reason: 'no-candidates' };
|
|
82
|
+
const trimmedQuery = (taskQuery || '').trim();
|
|
83
|
+
if (!trimmedQuery)
|
|
84
|
+
return { selectedPaths: [], candidateCount: 0, reason: 'no-query' };
|
|
85
|
+
const candidates = scanVault(projectRoot, excludePatterns);
|
|
86
|
+
if (candidates.length === 0)
|
|
87
|
+
return { selectedPaths: [], candidateCount: 0, reason: 'no-candidates' };
|
|
88
|
+
const { lines, pathSet } = buildCandidatePool(candidates);
|
|
89
|
+
if (lines.length === 0)
|
|
90
|
+
return { selectedPaths: [], candidateCount: 0, reason: 'no-candidates' };
|
|
91
|
+
const prompt = RETRIEVAL_PROMPT_HEADER
|
|
92
|
+
.replace('{TASK}', trimmedQuery.slice(0, TASK_QUERY_MAX_CHARS))
|
|
93
|
+
.replace('{ENTRIES}', lines.join('\n'));
|
|
94
|
+
const cliTool = resolveCliTool(project.cli_tool);
|
|
95
|
+
let raw;
|
|
96
|
+
try {
|
|
97
|
+
raw = await runHeadless(cliTool, prompt, RETRIEVAL_TIMEOUT_MS);
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
console.warn('[vault-retriever] runHeadless failed:', err instanceof Error ? err.message : err);
|
|
101
|
+
return { selectedPaths: [], candidateCount: candidates.length, reason: 'cli-error' };
|
|
102
|
+
}
|
|
103
|
+
const paths = safeParsePathArray(raw, pathSet);
|
|
104
|
+
return paths.length === 0
|
|
105
|
+
? { selectedPaths: [], candidateCount: candidates.length, reason: 'no-match' }
|
|
106
|
+
: { selectedPaths: paths, candidateCount: candidates.length };
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=vault-retriever.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vault-retriever.js","sourceRoot":"","sources":["../../../src/server/services/vault-retriever.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAkB,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEjE,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAC/B,MAAM,oBAAoB,GAAG,MAAM,CAAC;AACpC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AACpC,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAQlC,SAAS,aAAa,CAAC,IAAY,EAAE,MAAM,GAAG,GAAG;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAClC,OAAO,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;AACpD,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAkB;IAC5C,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACtC,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAC7C,CAAC;IAEF,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAClE,MAAM,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,YAAY,YAAY,CAAC,CAAC,KAAK,IAAI,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACvG,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,sBAAsB,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM;QAC3E,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;QAC5B,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC5B,CAAC;AAED,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;;iBAcf,mBAAmB;;8DAE0B,CAAC;AAE/D,SAAS,kBAAkB,CAAC,GAAW,EAAE,UAAuB;IAC9D,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IACrF,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACvC,IAAI,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC;QAClB,IAAI,CAAC;YAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,EAAE,CAAC;QAAC,CAAC;IACzD,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IACtC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QACvB,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3D,IAAI,KAAK,CAAC,MAAM,IAAI,mBAAmB;YAAE,MAAM;IACjD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,SAAiB,EACjB,WAAmB,EACnB,SAAiB,EACjB,eAA0B;IAE1B,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IAClD,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,cAAc,EAAE,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAEvF,MAAM,YAAY,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,IAAI,CAAC,YAAY;QAAE,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,cAAc,EAAE,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAEvF,MAAM,UAAU,GAAG,SAAS,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;IAC3D,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,cAAc,EAAE,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAEtG,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAC1D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,cAAc,EAAE,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAEjG,MAAM,MAAM,GAAG,uBAAuB;SACnC,OAAO,CAAC,QAAQ,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC;SAC9D,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAE1C,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,oBAAoB,CAAC,CAAC;IACjE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,uCAAuC,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAChG,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,cAAc,EAAE,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACvF,CAAC;IAED,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC/C,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;QACvB,CAAC,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,cAAc,EAAE,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE;QAC9E,CAAC,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,cAAc,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC;AAClE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../src/server/websocket/events.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GACf;IAAE,IAAI,EAAE,qBAAqB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC1I;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACtE;IAAE,IAAI,EAAE,wBAAwB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../src/server/websocket/events.ts"],"names":[],"mappings":"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"}
|
package/electron/main.cjs
CHANGED
|
@@ -125,15 +125,78 @@ function createWindow(port) {
|
|
|
125
125
|
`http://127.0.0.1:${port}`,
|
|
126
126
|
`http://localhost:${port}`,
|
|
127
127
|
];
|
|
128
|
-
|
|
128
|
+
// Parse a `features` CSV string like "popup,width=800,height=540,left=120,top=80"
|
|
129
|
+
// into numeric x/y/width/height we can forward into Electron's
|
|
130
|
+
// overrideBrowserWindowOptions. Electron drops the features-derived sizing
|
|
131
|
+
// when override is returned, so this re-forwards what the renderer asked
|
|
132
|
+
// for; without it the popout would spawn at Electron's default cascade
|
|
133
|
+
// position instead of under the user's cursor (drag-out is unusable).
|
|
134
|
+
const parseFeatures = (features) => {
|
|
135
|
+
const out = {};
|
|
136
|
+
if (typeof features !== 'string') return out;
|
|
137
|
+
for (const part of features.split(',')) {
|
|
138
|
+
const eq = part.indexOf('=');
|
|
139
|
+
if (eq < 0) continue;
|
|
140
|
+
const key = part.slice(0, eq).trim().toLowerCase();
|
|
141
|
+
const val = Number(part.slice(eq + 1).trim());
|
|
142
|
+
if (!Number.isFinite(val)) continue;
|
|
143
|
+
if (key === 'width') out.width = val;
|
|
144
|
+
else if (key === 'height') out.height = val;
|
|
145
|
+
else if (key === 'left') out.x = val;
|
|
146
|
+
else if (key === 'top') out.y = val;
|
|
147
|
+
}
|
|
148
|
+
return out;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
mainWindow.webContents.setWindowOpenHandler(({ url, features }) => {
|
|
129
152
|
const isLocal = localOrigins.some((o) => url.startsWith(o));
|
|
130
153
|
if (!isLocal) {
|
|
131
154
|
shell.openExternal(url);
|
|
132
155
|
return { action: 'deny' };
|
|
133
156
|
}
|
|
157
|
+
// Session pop-out windows: open as a real OS child window with the same
|
|
158
|
+
// preload + isolation as the main window. Without overrideBrowserWindowOptions
|
|
159
|
+
// Electron uses small defaults and doesn't apply the preload, which
|
|
160
|
+
// breaks IME reset + auto-updater bridges the popout may also call.
|
|
161
|
+
let popoutPath;
|
|
162
|
+
try { popoutPath = new URL(url).pathname; } catch { popoutPath = ''; }
|
|
163
|
+
if (popoutPath.startsWith('/popout/')) {
|
|
164
|
+
const feat = parseFeatures(features);
|
|
165
|
+
return {
|
|
166
|
+
action: 'allow',
|
|
167
|
+
overrideBrowserWindowOptions: {
|
|
168
|
+
width: feat.width || 800,
|
|
169
|
+
height: feat.height || 540,
|
|
170
|
+
// x/y intentionally only forwarded when supplied — Electron treats
|
|
171
|
+
// an absent x/y as "let the OS place the window" which is the right
|
|
172
|
+
// default for the button-click path.
|
|
173
|
+
...(typeof feat.x === 'number' ? { x: feat.x } : {}),
|
|
174
|
+
...(typeof feat.y === 'number' ? { y: feat.y } : {}),
|
|
175
|
+
minWidth: 360,
|
|
176
|
+
minHeight: 240,
|
|
177
|
+
backgroundColor: nativeTheme.shouldUseDarkColors ? '#0f0f0f' : '#ffffff',
|
|
178
|
+
webPreferences: {
|
|
179
|
+
preload: path.join(__dirname, 'preload.cjs'),
|
|
180
|
+
contextIsolation: true,
|
|
181
|
+
nodeIntegration: false,
|
|
182
|
+
sandbox: false,
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
}
|
|
134
187
|
return { action: 'allow' };
|
|
135
188
|
});
|
|
136
189
|
|
|
190
|
+
// Newly-created child windows (popouts) inherit the main window's
|
|
191
|
+
// setWindowOpenHandler but not the lock-screen focus-recovery handler.
|
|
192
|
+
// Attach the same focus → webContents.focus() bridge so xterm typing
|
|
193
|
+
// doesn't go dead after resume.
|
|
194
|
+
mainWindow.webContents.on('did-create-window', (childWin) => {
|
|
195
|
+
childWin.on('focus', () => {
|
|
196
|
+
if (!childWin.isDestroyed()) childWin.webContents.focus();
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
137
200
|
mainWindow.loadURL(`http://127.0.0.1:${port}`);
|
|
138
201
|
|
|
139
202
|
if (!app.isPackaged) {
|
|
@@ -152,7 +215,16 @@ function createWindow(port) {
|
|
|
152
215
|
});
|
|
153
216
|
}
|
|
154
217
|
|
|
155
|
-
ipcMain.on('ime:reset', () => {
|
|
218
|
+
ipcMain.on('ime:reset', (event) => {
|
|
219
|
+
// Route the focus call to the sender's webContents so popout child
|
|
220
|
+
// windows reclaim their own keyboard focus, not the main window's.
|
|
221
|
+
// Falls back to mainWindow only if the sender is gone (race during
|
|
222
|
+
// teardown).
|
|
223
|
+
const sender = event && event.sender;
|
|
224
|
+
if (sender && !sender.isDestroyed()) {
|
|
225
|
+
sender.focus();
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
156
228
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
157
229
|
mainWindow.webContents.focus();
|
|
158
230
|
}
|
|
@@ -230,12 +302,6 @@ function setupAutoUpdater() {
|
|
|
230
302
|
setTimeout(() => checkForUpdates({ silent: true }), 5000);
|
|
231
303
|
}
|
|
232
304
|
|
|
233
|
-
ipcMain.on('ime:reset', () => {
|
|
234
|
-
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
235
|
-
mainWindow.webContents.focus();
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
|
|
239
305
|
function buildMenu() {
|
|
240
306
|
const isMac = process.platform === 'darwin';
|
|
241
307
|
const template = [
|