@open-agent-toolkit/cli 0.2.21 → 0.2.22
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/assets/public-package-versions.json +4 -4
- package/assets/skills/explainer-kit/SKILL.md +1 -1
- package/assets/skills/explainer-kit/scripts/lib/html-safety.mjs +8 -1
- package/assets/skills/explainer-kit/scripts/lib/qa.mjs +5 -5
- package/assets/skills/explainer-kit/scripts/lib/recipes.mjs +5 -4
- package/assets/skills/explainer-kit/scripts/render-qa.mjs +6 -1
- package/assets/skills/explainer-kit/scripts/run.mjs +3 -10
- package/assets/skills/oat-brainstorm/SKILL.md +1 -1
- package/assets/skills/oat-brainstorm/scripts/helper.js +18 -11
- package/assets/skills/oat-brainstorm/scripts/server.cjs +109 -55
- package/assets/skills/oat-explainer-kit/SKILL.md +1 -1
- package/dist/commands/init/tools/index.d.ts.map +1 -1
- package/dist/commands/init/tools/index.js +4 -4
- package/dist/engine/compute-plan.js +3 -3
- package/package.json +2 -2
|
@@ -580,7 +580,14 @@ function srcsetCandidates(value) {
|
|
|
580
580
|
}
|
|
581
581
|
|
|
582
582
|
function compactUrl(value) {
|
|
583
|
-
|
|
583
|
+
// Strip C0 controls, ASCII space, and DEL without a control-char regex
|
|
584
|
+
// (oxlint/eslint no-control-regex flags those literals even when intentional).
|
|
585
|
+
let compact = '';
|
|
586
|
+
for (const ch of value) {
|
|
587
|
+
const code = ch.codePointAt(0);
|
|
588
|
+
if (code > 0x20 && code !== 0x7f) compact += ch;
|
|
589
|
+
}
|
|
590
|
+
return compact.toLowerCase();
|
|
584
591
|
}
|
|
585
592
|
|
|
586
593
|
// Shared with the render QA structural check so both call sites enforce one
|
|
@@ -770,7 +770,7 @@ function normalizeClaim(value) {
|
|
|
770
770
|
throw new TypeError('Cohesion claims must be strings, numbers, or booleans.');
|
|
771
771
|
}
|
|
772
772
|
|
|
773
|
-
function validateProbeResult(result,
|
|
773
|
+
function validateProbeResult(result, id, width, request) {
|
|
774
774
|
if (
|
|
775
775
|
!isPlainObject(result) ||
|
|
776
776
|
typeof result.pageOverflowX !== 'boolean' ||
|
|
@@ -779,7 +779,7 @@ function validateProbeResult(result, artifactId, width, request) {
|
|
|
779
779
|
!isPlainObject(result.keyboard)
|
|
780
780
|
) {
|
|
781
781
|
throw new TypeError(
|
|
782
|
-
`Browser probe for ${
|
|
782
|
+
`Browser probe for ${id} at ${width}px returned an invalid result.`,
|
|
783
783
|
);
|
|
784
784
|
}
|
|
785
785
|
if (
|
|
@@ -791,17 +791,17 @@ function validateProbeResult(result, artifactId, width, request) {
|
|
|
791
791
|
typeof result.animationsDisabled !== 'boolean')
|
|
792
792
|
) {
|
|
793
793
|
throw new TypeError(
|
|
794
|
-
`Browser layout probe for ${
|
|
794
|
+
`Browser layout probe for ${id} at ${width}px returned an invalid result.`,
|
|
795
795
|
);
|
|
796
796
|
}
|
|
797
797
|
if (request.themeToggle && !isPlainObject(result.themeToggle)) {
|
|
798
798
|
throw new TypeError(
|
|
799
|
-
`Browser theme probe for ${
|
|
799
|
+
`Browser theme probe for ${id} at ${width}px returned an invalid result.`,
|
|
800
800
|
);
|
|
801
801
|
}
|
|
802
802
|
if (request.scenario !== 'default' && !isPlainObject(result.deckLayout)) {
|
|
803
803
|
throw new TypeError(
|
|
804
|
-
`Browser deck probe for ${
|
|
804
|
+
`Browser deck probe for ${id} at ${width}px returned an invalid result.`,
|
|
805
805
|
);
|
|
806
806
|
}
|
|
807
807
|
}
|
|
@@ -116,9 +116,7 @@ export function evaluateExpansionProposals(recipe, proposals) {
|
|
|
116
116
|
const seenIds = new Set();
|
|
117
117
|
const acceptedByProfile = new Map();
|
|
118
118
|
const acceptedByType = new Map();
|
|
119
|
-
const maxPerType = new Map(
|
|
120
|
-
Object.entries(expansion.limits.maxPerType ?? {}),
|
|
121
|
-
);
|
|
119
|
+
const maxPerType = new Map(Object.entries(expansion.limits.maxPerType ?? {}));
|
|
122
120
|
|
|
123
121
|
if (!Array.isArray(proposals)) {
|
|
124
122
|
return {
|
|
@@ -180,7 +178,10 @@ export function evaluateExpansionProposals(recipe, proposals) {
|
|
|
180
178
|
// A declared type cap binds across profiles, so proposals cannot spread
|
|
181
179
|
// over sibling profiles that share one artifact type to evade it.
|
|
182
180
|
const typeCount = acceptedByType.get(profile.type) ?? 0;
|
|
183
|
-
if (
|
|
181
|
+
if (
|
|
182
|
+
maxPerType.has(profile.type) &&
|
|
183
|
+
typeCount >= maxPerType.get(profile.type)
|
|
184
|
+
) {
|
|
184
185
|
rejected.push({
|
|
185
186
|
...structuredClone(proposal),
|
|
186
187
|
status: 'rejected',
|
|
@@ -74,7 +74,12 @@ export async function runRenderQaStage({
|
|
|
74
74
|
};
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
return probeSiteArtifacts({
|
|
77
|
+
return probeSiteArtifacts({
|
|
78
|
+
siteDir,
|
|
79
|
+
artifacts,
|
|
80
|
+
probe: browserProbe,
|
|
81
|
+
widths,
|
|
82
|
+
});
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
async function probeSiteArtifacts({ siteDir, artifacts, probe, widths }) {
|
|
@@ -441,8 +441,7 @@ async function hydrateResumableState(state) {
|
|
|
441
441
|
state.resumedApprovalStatus = approval.status;
|
|
442
442
|
// Reopened stages rerun against the corrected content, so carrying their
|
|
443
443
|
// prior warnings forward would outlive the fix that resolved them.
|
|
444
|
-
const rerunning =
|
|
445
|
-
approval.status === 'rejected' ? REOPENED_ON_REJECTION : [];
|
|
444
|
+
const rerunning = approval.status === 'rejected' ? REOPENED_ON_REJECTION : [];
|
|
446
445
|
state.warnings.push(
|
|
447
446
|
...record.stages
|
|
448
447
|
.filter(({ id }) => !rerunning.includes(id))
|
|
@@ -1039,11 +1038,7 @@ async function authorArtifact(state, artifact, author, trust) {
|
|
|
1039
1038
|
}
|
|
1040
1039
|
const retained = {
|
|
1041
1040
|
...structuredClone(result),
|
|
1042
|
-
provenance: resolveAuthorProvenance(
|
|
1043
|
-
result.provenance,
|
|
1044
|
-
trust,
|
|
1045
|
-
artifact.id,
|
|
1046
|
-
),
|
|
1041
|
+
provenance: resolveAuthorProvenance(result.provenance, trust, artifact.id),
|
|
1047
1042
|
};
|
|
1048
1043
|
const retainedValidation = validateContract('author-result/v2', retained);
|
|
1049
1044
|
if (!retainedValidation.valid) {
|
|
@@ -1115,9 +1110,7 @@ function markdownContentModel(artifact, slug, markdown, artifactLinks) {
|
|
|
1115
1110
|
|
|
1116
1111
|
// Prose between the document title and the first `##` is authored content,
|
|
1117
1112
|
// so it is carried as a leading section rather than silently dropped.
|
|
1118
|
-
const bodyStart = titleMatch
|
|
1119
|
-
? titleMatch.index + titleMatch[0].length
|
|
1120
|
-
: 0;
|
|
1113
|
+
const bodyStart = titleMatch ? titleMatch.index + titleMatch[0].length : 0;
|
|
1121
1114
|
const lead = markdown.slice(bodyStart, headings[0].index).trim();
|
|
1122
1115
|
const authoredIds = new Set(
|
|
1123
1116
|
headings.map((heading) => slugify(heading[1].trim())),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: oat-brainstorm
|
|
3
|
-
version: 1.1.
|
|
3
|
+
version: 1.1.2
|
|
4
4
|
description: Use when the user explicitly invokes the `brainstorm` verb, including `/oat-brainstorm`, "let's brainstorm", "brainstorm this", "can we brainstorm X", or "help me brainstorm X". For ambiguous exploratory phrasing ("I've been thinking", "what if", "help me think through"), do NOT auto-enter; respond conversationally and offer mode only after ≥2 sustained exploratory turns. Do NOT use for review, debug, PR, status, implementation, or active-workflow questions.
|
|
5
5
|
disable-model-invocation: false
|
|
6
6
|
user-invocable: true
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
(function() {
|
|
2
|
-
const WS_URL =
|
|
1
|
+
(function () {
|
|
2
|
+
const WS_URL = `ws://${window.location.host}`;
|
|
3
3
|
let ws = null;
|
|
4
4
|
let eventQueue = [];
|
|
5
5
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
ws = new WebSocket(WS_URL);
|
|
8
8
|
|
|
9
9
|
ws.onopen = () => {
|
|
10
|
-
eventQueue.forEach(e => ws.send(JSON.stringify(e)));
|
|
10
|
+
eventQueue.forEach((e) => ws.send(JSON.stringify(e)));
|
|
11
11
|
eventQueue = [];
|
|
12
12
|
};
|
|
13
13
|
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
type: 'click',
|
|
42
42
|
text: target.textContent.trim(),
|
|
43
43
|
choice: target.dataset.choice,
|
|
44
|
-
id: target.id || null
|
|
44
|
+
id: target.id || null,
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
// Update indicator bar (defer so toggleSelect runs first)
|
|
@@ -51,12 +51,16 @@
|
|
|
51
51
|
const container = target.closest('.options') || target.closest('.cards');
|
|
52
52
|
const selected = container ? container.querySelectorAll('.selected') : [];
|
|
53
53
|
if (selected.length === 0) {
|
|
54
|
-
indicator.textContent =
|
|
54
|
+
indicator.textContent =
|
|
55
|
+
'Click an option above, then return to the terminal';
|
|
55
56
|
} else if (selected.length === 1) {
|
|
56
|
-
const label =
|
|
57
|
-
|
|
57
|
+
const label =
|
|
58
|
+
selected[0]
|
|
59
|
+
.querySelector('h3, .content h3, .card-body h3')
|
|
60
|
+
?.textContent?.trim() || selected[0].dataset.choice;
|
|
61
|
+
indicator.innerHTML = `<span class="selected-text">${label} selected</span> — return to terminal to continue`;
|
|
58
62
|
} else {
|
|
59
|
-
indicator.innerHTML =
|
|
63
|
+
indicator.innerHTML = `<span class="selected-text">${selected.length} selected</span> — return to terminal to continue`;
|
|
60
64
|
}
|
|
61
65
|
}, 0);
|
|
62
66
|
});
|
|
@@ -64,11 +68,13 @@
|
|
|
64
68
|
// Frame UI: selection tracking
|
|
65
69
|
window.selectedChoice = null;
|
|
66
70
|
|
|
67
|
-
window.toggleSelect = function(el) {
|
|
71
|
+
window.toggleSelect = function (el) {
|
|
68
72
|
const container = el.closest('.options') || el.closest('.cards');
|
|
69
73
|
const multi = container && container.dataset.multiselect !== undefined;
|
|
70
74
|
if (container && !multi) {
|
|
71
|
-
container
|
|
75
|
+
container
|
|
76
|
+
.querySelectorAll('.option, .card')
|
|
77
|
+
.forEach((o) => o.classList.remove('selected'));
|
|
72
78
|
}
|
|
73
79
|
if (multi) {
|
|
74
80
|
el.classList.toggle('selected');
|
|
@@ -81,7 +87,8 @@
|
|
|
81
87
|
// Expose API for explicit use
|
|
82
88
|
window.brainstorm = {
|
|
83
89
|
send: sendEvent,
|
|
84
|
-
choice: (value, metadata = {}) =>
|
|
90
|
+
choice: (value, metadata = {}) =>
|
|
91
|
+
sendEvent({ type: 'choice', value, ...metadata }),
|
|
85
92
|
};
|
|
86
93
|
|
|
87
94
|
connect();
|
|
@@ -5,11 +5,14 @@ const path = require('path');
|
|
|
5
5
|
|
|
6
6
|
// ========== WebSocket Protocol (RFC 6455) ==========
|
|
7
7
|
|
|
8
|
-
const OPCODES = { TEXT: 0x01, CLOSE: 0x08, PING: 0x09, PONG:
|
|
8
|
+
const OPCODES = { TEXT: 0x01, CLOSE: 0x08, PING: 0x09, PONG: 0x0a };
|
|
9
9
|
const WS_MAGIC = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
|
|
10
10
|
|
|
11
11
|
function computeAcceptKey(clientKey) {
|
|
12
|
-
return crypto
|
|
12
|
+
return crypto
|
|
13
|
+
.createHash('sha1')
|
|
14
|
+
.update(clientKey + WS_MAGIC)
|
|
15
|
+
.digest('base64');
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
function encodeFrame(opcode, payload) {
|
|
@@ -40,9 +43,9 @@ function decodeFrame(buffer) {
|
|
|
40
43
|
if (buffer.length < 2) return null;
|
|
41
44
|
|
|
42
45
|
const secondByte = buffer[1];
|
|
43
|
-
const opcode = buffer[0] &
|
|
46
|
+
const opcode = buffer[0] & 0x0f;
|
|
44
47
|
const masked = (secondByte & 0x80) !== 0;
|
|
45
|
-
let payloadLen = secondByte &
|
|
48
|
+
let payloadLen = secondByte & 0x7f;
|
|
46
49
|
let offset = 2;
|
|
47
50
|
|
|
48
51
|
if (!masked) throw new Error('Client frames must be masked');
|
|
@@ -73,18 +76,29 @@ function decodeFrame(buffer) {
|
|
|
73
76
|
|
|
74
77
|
// ========== Configuration ==========
|
|
75
78
|
|
|
76
|
-
const PORT =
|
|
79
|
+
const PORT =
|
|
80
|
+
process.env.BRAINSTORM_PORT || 49152 + Math.floor(Math.random() * 16383);
|
|
77
81
|
const HOST = process.env.BRAINSTORM_HOST || '127.0.0.1';
|
|
78
|
-
const URL_HOST =
|
|
82
|
+
const URL_HOST =
|
|
83
|
+
process.env.BRAINSTORM_URL_HOST ||
|
|
84
|
+
(HOST === '127.0.0.1' ? 'localhost' : HOST);
|
|
79
85
|
const SESSION_DIR = process.env.BRAINSTORM_DIR || '/tmp/brainstorm';
|
|
80
86
|
const CONTENT_DIR = path.join(SESSION_DIR, 'content');
|
|
81
87
|
const STATE_DIR = path.join(SESSION_DIR, 'state');
|
|
82
|
-
let ownerPid = process.env.BRAINSTORM_OWNER_PID
|
|
88
|
+
let ownerPid = process.env.BRAINSTORM_OWNER_PID
|
|
89
|
+
? Number(process.env.BRAINSTORM_OWNER_PID)
|
|
90
|
+
: null;
|
|
83
91
|
|
|
84
92
|
const MIME_TYPES = {
|
|
85
|
-
'.html': 'text/html',
|
|
86
|
-
'.
|
|
87
|
-
'.
|
|
93
|
+
'.html': 'text/html',
|
|
94
|
+
'.css': 'text/css',
|
|
95
|
+
'.js': 'application/javascript',
|
|
96
|
+
'.json': 'application/json',
|
|
97
|
+
'.png': 'image/png',
|
|
98
|
+
'.jpg': 'image/jpeg',
|
|
99
|
+
'.jpeg': 'image/jpeg',
|
|
100
|
+
'.gif': 'image/gif',
|
|
101
|
+
'.svg': 'image/svg+xml',
|
|
88
102
|
};
|
|
89
103
|
|
|
90
104
|
// ========== Templates and Constants ==========
|
|
@@ -98,9 +112,15 @@ h1 { color: #333; } p { color: #666; }</style>
|
|
|
98
112
|
<body><h1>Brainstorm Companion</h1>
|
|
99
113
|
<p>Waiting for the agent to push a screen...</p></body></html>`;
|
|
100
114
|
|
|
101
|
-
const frameTemplate = fs.readFileSync(
|
|
102
|
-
|
|
103
|
-
|
|
115
|
+
const frameTemplate = fs.readFileSync(
|
|
116
|
+
path.join(__dirname, 'frame-template.html'),
|
|
117
|
+
'utf-8',
|
|
118
|
+
);
|
|
119
|
+
const helperScript = fs.readFileSync(
|
|
120
|
+
path.join(__dirname, 'helper.js'),
|
|
121
|
+
'utf-8',
|
|
122
|
+
);
|
|
123
|
+
const helperInjection = `<script>\n${helperScript}\n</script>`;
|
|
104
124
|
|
|
105
125
|
// ========== Helper Functions ==========
|
|
106
126
|
|
|
@@ -114,9 +134,10 @@ function wrapInFrame(content) {
|
|
|
114
134
|
}
|
|
115
135
|
|
|
116
136
|
function getNewestScreen() {
|
|
117
|
-
const files = fs
|
|
118
|
-
.
|
|
119
|
-
.
|
|
137
|
+
const files = fs
|
|
138
|
+
.readdirSync(CONTENT_DIR)
|
|
139
|
+
.filter((f) => f.endsWith('.html'))
|
|
140
|
+
.map((f) => {
|
|
120
141
|
const fp = path.join(CONTENT_DIR, f);
|
|
121
142
|
return { path: fp, mtime: fs.statSync(fp).mtime.getTime() };
|
|
122
143
|
})
|
|
@@ -131,11 +152,13 @@ function handleRequest(req, res) {
|
|
|
131
152
|
if (req.method === 'GET' && req.url === '/') {
|
|
132
153
|
const screenFile = getNewestScreen();
|
|
133
154
|
let html = screenFile
|
|
134
|
-
? (raw => isFullDocument(raw) ? raw : wrapInFrame(raw))(
|
|
155
|
+
? ((raw) => (isFullDocument(raw) ? raw : wrapInFrame(raw)))(
|
|
156
|
+
fs.readFileSync(screenFile, 'utf-8'),
|
|
157
|
+
)
|
|
135
158
|
: WAITING_PAGE;
|
|
136
159
|
|
|
137
160
|
if (html.includes('</body>')) {
|
|
138
|
-
html = html.replace('</body>', helperInjection
|
|
161
|
+
html = html.replace('</body>', `${helperInjection}\n</body>`);
|
|
139
162
|
} else {
|
|
140
163
|
html += helperInjection;
|
|
141
164
|
}
|
|
@@ -166,14 +189,17 @@ const clients = new Set();
|
|
|
166
189
|
|
|
167
190
|
function handleUpgrade(req, socket) {
|
|
168
191
|
const key = req.headers['sec-websocket-key'];
|
|
169
|
-
if (!key) {
|
|
192
|
+
if (!key) {
|
|
193
|
+
socket.destroy();
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
170
196
|
|
|
171
197
|
const accept = computeAcceptKey(key);
|
|
172
198
|
socket.write(
|
|
173
199
|
'HTTP/1.1 101 Switching Protocols\r\n' +
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
200
|
+
'Upgrade: websocket\r\n' +
|
|
201
|
+
'Connection: Upgrade\r\n' +
|
|
202
|
+
`Sec-WebSocket-Accept: ${accept}\r\n\r\n`,
|
|
177
203
|
);
|
|
178
204
|
|
|
179
205
|
let buffer = Buffer.alloc(0);
|
|
@@ -185,7 +211,7 @@ function handleUpgrade(req, socket) {
|
|
|
185
211
|
let result;
|
|
186
212
|
try {
|
|
187
213
|
result = decodeFrame(buffer);
|
|
188
|
-
} catch
|
|
214
|
+
} catch {
|
|
189
215
|
socket.end(encodeFrame(OPCODES.CLOSE, Buffer.alloc(0)));
|
|
190
216
|
clients.delete(socket);
|
|
191
217
|
return;
|
|
@@ -233,14 +259,18 @@ function handleMessage(text) {
|
|
|
233
259
|
console.log(JSON.stringify({ source: 'user-event', ...event }));
|
|
234
260
|
if (event.choice) {
|
|
235
261
|
const eventsFile = path.join(STATE_DIR, 'events');
|
|
236
|
-
fs.appendFileSync(eventsFile, JSON.stringify(event)
|
|
262
|
+
fs.appendFileSync(eventsFile, `${JSON.stringify(event)}\n`);
|
|
237
263
|
}
|
|
238
264
|
}
|
|
239
265
|
|
|
240
266
|
function broadcast(msg) {
|
|
241
267
|
const frame = encodeFrame(OPCODES.TEXT, Buffer.from(JSON.stringify(msg)));
|
|
242
268
|
for (const socket of clients) {
|
|
243
|
-
try {
|
|
269
|
+
try {
|
|
270
|
+
socket.write(frame);
|
|
271
|
+
} catch {
|
|
272
|
+
clients.delete(socket);
|
|
273
|
+
}
|
|
244
274
|
}
|
|
245
275
|
}
|
|
246
276
|
|
|
@@ -260,14 +290,15 @@ const debounceTimers = new Map();
|
|
|
260
290
|
// ========== Server Startup ==========
|
|
261
291
|
|
|
262
292
|
function startServer() {
|
|
263
|
-
if (!fs.existsSync(CONTENT_DIR))
|
|
293
|
+
if (!fs.existsSync(CONTENT_DIR))
|
|
294
|
+
fs.mkdirSync(CONTENT_DIR, { recursive: true });
|
|
264
295
|
if (!fs.existsSync(STATE_DIR)) fs.mkdirSync(STATE_DIR, { recursive: true });
|
|
265
296
|
|
|
266
297
|
// Track known files to distinguish new screens from updates.
|
|
267
298
|
// macOS fs.watch reports 'rename' for both new files and overwrites,
|
|
268
299
|
// so we can't rely on eventType alone.
|
|
269
300
|
const knownFiles = new Set(
|
|
270
|
-
fs.readdirSync(CONTENT_DIR).filter(f => f.endsWith('.html'))
|
|
301
|
+
fs.readdirSync(CONTENT_DIR).filter((f) => f.endsWith('.html')),
|
|
271
302
|
);
|
|
272
303
|
|
|
273
304
|
const server = http.createServer(handleRequest);
|
|
@@ -276,25 +307,31 @@ function startServer() {
|
|
|
276
307
|
const watcher = fs.watch(CONTENT_DIR, (eventType, filename) => {
|
|
277
308
|
if (!filename || !filename.endsWith('.html')) return;
|
|
278
309
|
|
|
279
|
-
if (debounceTimers.has(filename))
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
if (
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
310
|
+
if (debounceTimers.has(filename))
|
|
311
|
+
clearTimeout(debounceTimers.get(filename));
|
|
312
|
+
debounceTimers.set(
|
|
313
|
+
filename,
|
|
314
|
+
setTimeout(() => {
|
|
315
|
+
debounceTimers.delete(filename);
|
|
316
|
+
const filePath = path.join(CONTENT_DIR, filename);
|
|
317
|
+
|
|
318
|
+
if (!fs.existsSync(filePath)) return; // file was deleted
|
|
319
|
+
touchActivity();
|
|
320
|
+
|
|
321
|
+
if (!knownFiles.has(filename)) {
|
|
322
|
+
knownFiles.add(filename);
|
|
323
|
+
const eventsFile = path.join(STATE_DIR, 'events');
|
|
324
|
+
if (fs.existsSync(eventsFile)) fs.unlinkSync(eventsFile);
|
|
325
|
+
console.log(JSON.stringify({ type: 'screen-added', file: filePath }));
|
|
326
|
+
} else {
|
|
327
|
+
console.log(
|
|
328
|
+
JSON.stringify({ type: 'screen-updated', file: filePath }),
|
|
329
|
+
);
|
|
330
|
+
}
|
|
295
331
|
|
|
296
|
-
|
|
297
|
-
|
|
332
|
+
broadcast({ type: 'reload' });
|
|
333
|
+
}, 100),
|
|
334
|
+
);
|
|
298
335
|
});
|
|
299
336
|
watcher.on('error', (err) => console.error('fs.watch error:', err.message));
|
|
300
337
|
|
|
@@ -304,7 +341,7 @@ function startServer() {
|
|
|
304
341
|
if (fs.existsSync(infoFile)) fs.unlinkSync(infoFile);
|
|
305
342
|
fs.writeFileSync(
|
|
306
343
|
path.join(STATE_DIR, 'server-stopped'),
|
|
307
|
-
JSON.stringify({ reason, timestamp: Date.now() })
|
|
344
|
+
`${JSON.stringify({ reason, timestamp: Date.now() })}\n`,
|
|
308
345
|
);
|
|
309
346
|
watcher.close();
|
|
310
347
|
clearInterval(lifecycleCheck);
|
|
@@ -313,13 +350,19 @@ function startServer() {
|
|
|
313
350
|
|
|
314
351
|
function ownerAlive() {
|
|
315
352
|
if (!ownerPid) return true;
|
|
316
|
-
try {
|
|
353
|
+
try {
|
|
354
|
+
process.kill(ownerPid, 0);
|
|
355
|
+
return true;
|
|
356
|
+
} catch (e) {
|
|
357
|
+
return e.code === 'EPERM';
|
|
358
|
+
}
|
|
317
359
|
}
|
|
318
360
|
|
|
319
361
|
// Check every 60s: exit if owner process died or idle for 30 minutes
|
|
320
362
|
const lifecycleCheck = setInterval(() => {
|
|
321
363
|
if (!ownerAlive()) shutdown('owner process exited');
|
|
322
|
-
else if (Date.now() - lastActivity > IDLE_TIMEOUT_MS)
|
|
364
|
+
else if (Date.now() - lastActivity > IDLE_TIMEOUT_MS)
|
|
365
|
+
shutdown('idle timeout');
|
|
323
366
|
}, 60 * 1000);
|
|
324
367
|
lifecycleCheck.unref();
|
|
325
368
|
|
|
@@ -327,10 +370,17 @@ function startServer() {
|
|
|
327
370
|
// was wrong (common on WSL, Tailscale SSH, and cross-user scenarios).
|
|
328
371
|
// Disable monitoring and rely on the idle timeout instead.
|
|
329
372
|
if (ownerPid) {
|
|
330
|
-
try {
|
|
331
|
-
|
|
373
|
+
try {
|
|
374
|
+
process.kill(ownerPid, 0);
|
|
375
|
+
} catch (e) {
|
|
332
376
|
if (e.code !== 'EPERM') {
|
|
333
|
-
console.log(
|
|
377
|
+
console.log(
|
|
378
|
+
JSON.stringify({
|
|
379
|
+
type: 'owner-pid-invalid',
|
|
380
|
+
pid: ownerPid,
|
|
381
|
+
reason: 'dead at startup',
|
|
382
|
+
}),
|
|
383
|
+
);
|
|
334
384
|
ownerPid = null;
|
|
335
385
|
}
|
|
336
386
|
}
|
|
@@ -338,12 +388,16 @@ function startServer() {
|
|
|
338
388
|
|
|
339
389
|
server.listen(PORT, HOST, () => {
|
|
340
390
|
const info = JSON.stringify({
|
|
341
|
-
type: 'server-started',
|
|
342
|
-
|
|
343
|
-
|
|
391
|
+
type: 'server-started',
|
|
392
|
+
port: Number(PORT),
|
|
393
|
+
host: HOST,
|
|
394
|
+
url_host: URL_HOST,
|
|
395
|
+
url: `http://${URL_HOST}:${PORT}`,
|
|
396
|
+
screen_dir: CONTENT_DIR,
|
|
397
|
+
state_dir: STATE_DIR,
|
|
344
398
|
});
|
|
345
399
|
console.log(info);
|
|
346
|
-
fs.writeFileSync(path.join(STATE_DIR, 'server-info'), info
|
|
400
|
+
fs.writeFileSync(path.join(STATE_DIR, 'server-info'), `${info}\n`);
|
|
347
401
|
});
|
|
348
402
|
}
|
|
349
403
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/init/tools/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/init/tools/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EAEnB,MAAM,sBAAsB,CAAC;AAQ9B,OAAO,EACL,KAAK,mBAAmB,EAGzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,YAAY,EAGlB,MAAM,iCAAiC,CAAC;AASzC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EACL,KAAK,SAAS,EAIf,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC7B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACxB,MAAM,uBAAuB,CAAC;AAU/B,OAAO,EAEL,KAAK,+BAA+B,EACpC,KAAK,8BAA8B,EACpC,MAAM,iDAAiD,CAAC;AAEzD,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC3B,MAAM,6BAA6B,CAAC;AAerC,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAC1B,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC5B,MAAM,+BAA+B,CAAC;AAEvC,KAAK,YAAY,GAAG,SAAS,GAAG,MAAM,CAAC;AACvC,KAAK,iBAAiB,GAAG,YAAY,GAAG,MAAM,CAAC;AAC/C,MAAM,MAAM,QAAQ,GAChB,MAAM,GACN,OAAO,GACP,MAAM,GACN,WAAW,GACX,SAAS,GACT,oBAAoB,GACpB,UAAU,GACV,YAAY,CAAC;AAEjB,MAAM,WAAW,qBAAqB;IACpC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,gBAAgB,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7E,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,SAAS,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9D,mBAAmB,EAAE,CAAC,CAAC,SAAS,MAAM,EACpC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,EAC/B,GAAG,EAAE,aAAa,KACf,OAAO,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACzB,eAAe,EAAE,CAAC,CAAC,SAAS,MAAM,EAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,EAC1B,GAAG,EAAE,aAAa,KACf,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACvB,WAAW,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACzE,WAAW,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACzE,YAAY,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC5E,gBAAgB,EAAE,CAChB,OAAO,EAAE,uBAAuB,KAC7B,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACrC,cAAc,EAAE,CACd,OAAO,EAAE,qBAAqB,KAC3B,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnC,wBAAwB,EAAE,CACxB,OAAO,EAAE,+BAA+B,KACrC,OAAO,CAAC,8BAA8B,CAAC,CAAC;IAC7C,eAAe,EAAE,CACf,OAAO,EAAE,sBAAsB,KAC5B,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACpC,iBAAiB,EAAE,CACjB,OAAO,EAAE,wBAAwB,KAC9B,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACtC,iBAAiB,EAAE,CACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,KACX,OAAO,CAAC,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC,CAAC;IAC/C,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,aAAa,EAAE,CACb,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EAAE,KACZ,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,GAAG,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACjD,cAAc,EAAE,CACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAAE,KACjB,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjC,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,iBAAiB,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,MAAM,EAAE,CAAC;IACnD,qBAAqB,EAAE,CACrB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAClC,qBAAqB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5E;AAUD,UAAU,oBAAoB;IAC5B,cAAc,EAAE,aAAa,EAAE,CAAC;CACjC;AAwKD,UAAU,eAAe;IACvB,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,eAAe,EAAE,EACvB,OAAO,EAAE,eAAe,EAAE,GACzB,MAAM,CASR;AA4GD,wBAAgB,2BAA2B,IAAI,oBAAoB,GAAG,IAAI,CAIzE;AA2TD,UAAU,aAAa;IACrB,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,iBAAiB,CAAC;CAC1B;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,MAAM,CA8CxE;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,qBAAqB,GAClC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAqfrB;AAED,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,QAAQ,EAAE,CAAC,CAErB;AAED,wBAAgB,sBAAsB,CACpC,SAAS,GAAE,OAAO,CAAC,qBAAqB,CAAM,GAC7C,OAAO,CAsET"}
|
|
@@ -947,11 +947,11 @@ export function createInitToolsCommand(overrides = {}) {
|
|
|
947
947
|
for (const packCommand of packCommands) {
|
|
948
948
|
command.addCommand(packCommand);
|
|
949
949
|
}
|
|
950
|
-
command.action(async (_options,
|
|
951
|
-
const context = dependencies.buildCommandContext(readGlobalOptions(
|
|
950
|
+
command.action(async (_options, actionCommand) => {
|
|
951
|
+
const context = dependencies.buildCommandContext(readGlobalOptions(actionCommand));
|
|
952
952
|
const selectedPacks = await runInitTools(context, dependencies);
|
|
953
|
-
setInstalledCanonicalPaths(
|
|
954
|
-
await reconcileAfterInstall(
|
|
953
|
+
setInstalledCanonicalPaths(actionCommand, canonicalPathsForPacks(selectedPacks));
|
|
954
|
+
await reconcileAfterInstall(actionCommand);
|
|
955
955
|
});
|
|
956
956
|
return command;
|
|
957
957
|
}
|
|
@@ -232,9 +232,9 @@ async function classifyObsoleteMappingRetirement(manifestEntry, scopeRoot) {
|
|
|
232
232
|
}
|
|
233
233
|
async function classifyOperation(canonicalEntry, providerPath, strategy, renderedContent) {
|
|
234
234
|
if (strategy === 'symlink') {
|
|
235
|
-
let
|
|
235
|
+
let providerStat;
|
|
236
236
|
try {
|
|
237
|
-
|
|
237
|
+
providerStat = await lstat(providerPath);
|
|
238
238
|
}
|
|
239
239
|
catch (error) {
|
|
240
240
|
if (typeof error === 'object' &&
|
|
@@ -248,7 +248,7 @@ async function classifyOperation(canonicalEntry, providerPath, strategy, rendere
|
|
|
248
248
|
}
|
|
249
249
|
throw error;
|
|
250
250
|
}
|
|
251
|
-
if (!
|
|
251
|
+
if (!providerStat.isSymbolicLink()) {
|
|
252
252
|
return {
|
|
253
253
|
operation: 'update_symlink',
|
|
254
254
|
reason: 'provider path is not a symlink',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-agent-toolkit/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.22",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Open Agent Toolkit CLI",
|
|
6
6
|
"homepage": "https://github.com/voxmedia/open-agent-toolkit/tree/main/packages/cli",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"ora": "^9.0.0",
|
|
35
35
|
"yaml": "2.8.2",
|
|
36
36
|
"zod": "^3.25.76",
|
|
37
|
-
"@open-agent-toolkit/control-plane": "0.2.
|
|
37
|
+
"@open-agent-toolkit/control-plane": "0.2.22"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^22.10.0",
|