glimmervoid 0.0.0-stage → 0.29.1

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.
Files changed (55) hide show
  1. package/LICENSE +48 -0
  2. package/README.md +197 -2
  3. package/dist/bin/glimmervoid.js +259 -0
  4. package/dist/chunks/adapters-DIavI9-i.js +2 -0
  5. package/dist/chunks/adapters-Dlvu1FVB.js +566 -0
  6. package/dist/chunks/agent-api-cli-ClOzm28U.js +71 -0
  7. package/dist/chunks/agent-api-core-D6LHrpSL.js +103 -0
  8. package/dist/chunks/agent-setup-cli-C1CQ8Nkk.js +137 -0
  9. package/dist/chunks/ascii-figure-core-pDAwtlKO.js +45 -0
  10. package/dist/chunks/child-process-safe-Cz22RwlG.js +69 -0
  11. package/dist/chunks/config-path-core-DFt-TemS.js +38 -0
  12. package/dist/chunks/config-store-DtPUFVaO.js +1400 -0
  13. package/dist/chunks/config-store-DtUGwi4-.js +2 -0
  14. package/dist/chunks/contracts-JKChPhZ0.js +2998 -0
  15. package/dist/chunks/grok-COekzawt.js +407 -0
  16. package/dist/chunks/hook-relay-core-BHfYFnYV.js +88 -0
  17. package/dist/chunks/ingest-core-DWI1Mbu4.js +342 -0
  18. package/dist/chunks/ingest-editor-core-BuI1gMF_.js +445 -0
  19. package/dist/chunks/loopback-post-C7C22eYi.js +79 -0
  20. package/dist/chunks/main-BVDjy7vH.js +42740 -0
  21. package/dist/chunks/node-pty-preflight-CK1knGIR.js +162 -0
  22. package/dist/chunks/pair-cli-BQQnhkkc.js +110 -0
  23. package/dist/chunks/path-doctor-C23VAqeu.js +63 -0
  24. package/dist/chunks/refocus-core-BKQKllq7.js +38 -0
  25. package/dist/chunks/relay-stdin-CpHvLu6M.js +20 -0
  26. package/dist/chunks/remote-config-BHoDFCpo.js +521 -0
  27. package/dist/chunks/rtk-hook-core-DRYrKwYP.js +26 -0
  28. package/dist/chunks/rtk-resolver-DDVVNRBT.js +2 -0
  29. package/dist/chunks/rtk-resolver-oGmO-ew7.js +58 -0
  30. package/dist/chunks/runtime-paths-CVvq20A4.js +51 -0
  31. package/dist/chunks/sandbox-deps-BwvbDBDl.js +67 -0
  32. package/dist/chunks/session-CJtOveHl.js +162 -0
  33. package/dist/chunks/spawn-command-Cc40FiZI.js +134 -0
  34. package/dist/chunks/visions-cli-DUZnopGY.js +98 -0
  35. package/dist/chunks/visions-setup-C_kJobsy.js +1753 -0
  36. package/dist/client/assets/favicon-CKygeLwW.svg +7 -0
  37. package/dist/client/assets/index-BTwYgSAH.js +248 -0
  38. package/dist/client/assets/index-DgA708PE.css +1 -0
  39. package/dist/client/index.html +108 -0
  40. package/dist/package.json +3 -0
  41. package/dist/scripts/postinstall-path-check.js +36 -0
  42. package/dist/server/index.js +92 -0
  43. package/dist/session/command-hook-relay.js +16 -0
  44. package/dist/session/hook-relay.js +24 -0
  45. package/dist/session/rtk-relay.js +90 -0
  46. package/dist/session/statusline-relay.js +82 -0
  47. package/dist/session/visions-relay.js +627 -0
  48. package/dist/tools/vscode-visions/extension.js +289 -0
  49. package/dist/tools/vscode-visions/lsp-convert.js +80 -0
  50. package/dist/tools/vscode-visions/package.json +32 -0
  51. package/dist/tools/vscode-visions/visions-lsp-core.js +112 -0
  52. package/package.json +95 -4
  53. package/scripts/postinstall.mjs +4 -0
  54. package/scripts/prepare-build.js +38 -0
  55. package/scripts/recover-handoff.mjs +82 -0
@@ -0,0 +1,289 @@
1
+ //#region tools/vscode-visions/extension.ts
2
+ var fs = require("node:fs");
3
+ var path = require("node:path");
4
+ var { spawn } = require("node:child_process");
5
+ var vscode = require("vscode");
6
+ var { createParserState, feedFrameBytes, serializeFrame } = require("./visions-lsp-core.js");
7
+ var { decideEditFreshness, toCodeActions, toDiagnostics, toWorkspaceEdit } = require("./lsp-convert.js");
8
+ var LANGUAGE_ID = "markdown";
9
+ var ACTIVITY_METHOD = "visions/editorActivity";
10
+ var CODE_ACTION_TIMEOUT_MS = 2e3;
11
+ var INITIAL_RESTART_MS = 1e3;
12
+ var MAX_RESTART_MS = 15e3;
13
+ function stampedRelayPath() {
14
+ try {
15
+ const stamp = JSON.parse(fs.readFileSync(path.join(__dirname, "relay-path.json"), "utf8"));
16
+ if (typeof stamp !== "object" || stamp === null) return "";
17
+ if (!("relayPath" in stamp) || typeof stamp.relayPath !== "string") return "";
18
+ return stamp.relayPath;
19
+ } catch {
20
+ return "";
21
+ }
22
+ }
23
+ function resolveRelayPath(settings, env) {
24
+ const candidates = [
25
+ settings.get("relayPath", ""),
26
+ env.GLIMMERVOID_RELAY_PATH || "",
27
+ stampedRelayPath()
28
+ ];
29
+ for (const candidate of candidates) if (candidate && fs.existsSync(candidate)) return candidate;
30
+ return "";
31
+ }
32
+ function relayArgs(relayPath, port) {
33
+ if (!Number.isInteger(port) || port <= 0) return [relayPath];
34
+ return [
35
+ relayPath,
36
+ "--port",
37
+ String(port)
38
+ ];
39
+ }
40
+ function activate(context) {
41
+ const output = vscode.window.createOutputChannel("Glimmervoid Visions");
42
+ const diagnostics = vscode.languages.createDiagnosticCollection("glimmervoid-visions");
43
+ context.subscriptions.push(output, diagnostics);
44
+ const settings = vscode.workspace.getConfiguration("glimmervoidVisions");
45
+ const relayPath = resolveRelayPath(settings, process.env);
46
+ if (!relayPath) {
47
+ output.appendLine("no relay found: reinstall with `glimmervoid visions install`, or set glimmervoidVisions.relayPath");
48
+ vscode.window.showErrorMessage("Glimmervoid Visions found no relay. Run `glimmervoid visions install` again, or set glimmervoidVisions.relayPath.");
49
+ return;
50
+ }
51
+ const client = createRelayClient({
52
+ relayPath,
53
+ port: settings.get("port", 0),
54
+ output,
55
+ diagnostics
56
+ });
57
+ context.subscriptions.push({ dispose: () => client.stop() });
58
+ client.start();
59
+ context.subscriptions.push(vscode.workspace.onDidOpenTextDocument((document) => client.didOpen(document)), vscode.workspace.onDidChangeTextDocument((event) => client.didChange(event.document)), vscode.workspace.onDidSaveTextDocument((document) => client.didSave(document)), vscode.workspace.onDidCloseTextDocument((document) => client.didClose(document)), vscode.languages.registerCodeActionsProvider({ language: LANGUAGE_ID }, { provideCodeActions: (document, range, actionContext) => client.codeActions(document, range, actionContext) }, { providedCodeActionKinds: [vscode.CodeActionKind.QuickFix] }));
60
+ }
61
+ function createRelayClient({ relayPath, port, output, diagnostics }) {
62
+ let child = null;
63
+ let parserState = createParserState();
64
+ let nextRequestId = 1;
65
+ let restartMs = INITIAL_RESTART_MS;
66
+ let restartTimer = null;
67
+ let isStopping = false;
68
+ const pendingById = /* @__PURE__ */ new Map();
69
+ const openVersionByUri = /* @__PURE__ */ new Map();
70
+ function send(message) {
71
+ if (!child || child.killed || !child.stdin.writable) return false;
72
+ child.stdin.write(serializeFrame(message));
73
+ return true;
74
+ }
75
+ function notify(method, params) {
76
+ return send({
77
+ jsonrpc: "2.0",
78
+ method,
79
+ params
80
+ });
81
+ }
82
+ function request(method, params, timeoutMs) {
83
+ return new Promise((resolve) => {
84
+ const id = nextRequestId;
85
+ nextRequestId += 1;
86
+ const timer = setTimeout(() => settle(id, null), timeoutMs);
87
+ pendingById.set(id, {
88
+ resolve,
89
+ timer
90
+ });
91
+ if (!send({
92
+ jsonrpc: "2.0",
93
+ id,
94
+ method,
95
+ params
96
+ })) settle(id, null);
97
+ });
98
+ }
99
+ function settle(id, result) {
100
+ const pending = pendingById.get(id);
101
+ if (!pending) return;
102
+ pendingById.delete(id);
103
+ clearTimeout(pending.timer);
104
+ pending.resolve(result);
105
+ }
106
+ function failPending() {
107
+ for (const id of [...pendingById.keys()]) settle(id, null);
108
+ }
109
+ function isMirrored(document) {
110
+ return document.languageId === LANGUAGE_ID;
111
+ }
112
+ function reportActivity(document, method) {
113
+ if (document.uri.scheme !== "file") return;
114
+ notify(ACTIVITY_METHOD, {
115
+ uri: document.uri.toString(),
116
+ method
117
+ });
118
+ }
119
+ function didOpen(document) {
120
+ if (!isMirrored(document)) {
121
+ reportActivity(document, "textDocument/didOpen");
122
+ return;
123
+ }
124
+ openVersionByUri.set(document.uri.toString(), document.version);
125
+ notify("textDocument/didOpen", { textDocument: {
126
+ uri: document.uri.toString(),
127
+ languageId: document.languageId,
128
+ version: document.version,
129
+ text: document.getText()
130
+ } });
131
+ }
132
+ function didChange(document) {
133
+ if (!isMirrored(document)) return;
134
+ if (!openVersionByUri.has(document.uri.toString())) {
135
+ didOpen(document);
136
+ return;
137
+ }
138
+ openVersionByUri.set(document.uri.toString(), document.version);
139
+ notify("textDocument/didChange", {
140
+ textDocument: {
141
+ uri: document.uri.toString(),
142
+ version: document.version
143
+ },
144
+ contentChanges: [{ text: document.getText() }]
145
+ });
146
+ }
147
+ function didSave(document) {
148
+ if (!isMirrored(document)) {
149
+ reportActivity(document, "textDocument/didSave");
150
+ return;
151
+ }
152
+ notify("textDocument/didSave", { textDocument: { uri: document.uri.toString() } });
153
+ }
154
+ function didClose(document) {
155
+ if (!isMirrored(document)) {
156
+ reportActivity(document, "textDocument/didClose");
157
+ return;
158
+ }
159
+ openVersionByUri.delete(document.uri.toString());
160
+ diagnostics.delete(document.uri);
161
+ notify("textDocument/didClose", { textDocument: { uri: document.uri.toString() } });
162
+ }
163
+ async function codeActions(document, range, actionContext) {
164
+ if (!isMirrored(document)) return [];
165
+ return toCodeActions(vscode, await request("textDocument/codeAction", {
166
+ textDocument: { uri: document.uri.toString() },
167
+ range: {
168
+ start: range.start,
169
+ end: range.end
170
+ },
171
+ context: {
172
+ diagnostics: [],
173
+ triggerKind: actionContext?.triggerKind
174
+ }
175
+ }, CODE_ACTION_TIMEOUT_MS));
176
+ }
177
+ function versionOfUri(uri) {
178
+ if (!openVersionByUri.has(uri)) return null;
179
+ return openVersionByUri.get(uri) ?? null;
180
+ }
181
+ async function handleApplyEdit(id, params) {
182
+ const edit = params?.edit;
183
+ const freshness = decideEditFreshness(edit, versionOfUri);
184
+ if (!freshness.fresh) {
185
+ output.appendLine(`applyEdit refused: ${freshness.reason}`);
186
+ return send({
187
+ jsonrpc: "2.0",
188
+ id,
189
+ result: { applied: false }
190
+ });
191
+ }
192
+ return send({
193
+ jsonrpc: "2.0",
194
+ id,
195
+ result: { applied: await vscode.workspace.applyEdit(toWorkspaceEdit(vscode, edit)) }
196
+ });
197
+ }
198
+ function handleMessage(message) {
199
+ if (message?.method === "textDocument/publishDiagnostics") {
200
+ const uri = message.params?.uri;
201
+ if (typeof uri !== "string") return;
202
+ diagnostics.set(vscode.Uri.parse(uri), toDiagnostics(vscode, message.params?.diagnostics));
203
+ return;
204
+ }
205
+ if (message?.method === "workspace/applyEdit" && message.id !== void 0) {
206
+ handleApplyEdit(message.id, message.params);
207
+ return;
208
+ }
209
+ if (message?.id !== void 0 && message.method === void 0) settle(message.id, message.result ?? null);
210
+ }
211
+ function openMirroredDocuments() {
212
+ for (const document of vscode.workspace.textDocuments) didOpen(document);
213
+ }
214
+ async function handshake() {
215
+ await request("initialize", {
216
+ processId: process.pid,
217
+ rootUri: null,
218
+ capabilities: {},
219
+ clientInfo: { name: "glimmervoid-visions-extension" }
220
+ }, CODE_ACTION_TIMEOUT_MS);
221
+ notify("initialized", {});
222
+ openMirroredDocuments();
223
+ }
224
+ function scheduleRestart() {
225
+ if (isStopping || restartTimer) return;
226
+ output.appendLine(`relay exited; restarting in ${restartMs}ms`);
227
+ restartTimer = setTimeout(() => {
228
+ restartTimer = null;
229
+ start();
230
+ }, restartMs);
231
+ restartMs = Math.min(restartMs * 2, MAX_RESTART_MS);
232
+ }
233
+ function start() {
234
+ if (isStopping) return;
235
+ parserState = createParserState();
236
+ openVersionByUri.clear();
237
+ const relay = spawn(process.execPath, relayArgs(relayPath, port), {
238
+ env: {
239
+ ...process.env,
240
+ ELECTRON_RUN_AS_NODE: "1"
241
+ },
242
+ windowsHide: true
243
+ });
244
+ child = relay;
245
+ output.appendLine(`relay started: ${relayPath}`);
246
+ relay.stdout.on("data", (chunk) => {
247
+ const parsed = feedFrameBytes(parserState, Buffer.from(chunk));
248
+ parserState = parsed.state;
249
+ for (const message of parsed.messages) handleMessage(message);
250
+ });
251
+ relay.stderr.on("data", (chunk) => output.append(String(chunk)));
252
+ relay.on("error", (error) => output.appendLine(`relay failed to start: ${error.message}`));
253
+ relay.on("exit", (code) => {
254
+ failPending();
255
+ diagnostics.clear();
256
+ output.appendLine(`relay exit code ${code}`);
257
+ scheduleRestart();
258
+ });
259
+ handshake();
260
+ }
261
+ function stop() {
262
+ isStopping = true;
263
+ if (restartTimer) clearTimeout(restartTimer);
264
+ restartTimer = null;
265
+ failPending();
266
+ if (!child) return;
267
+ notify("shutdown", {});
268
+ notify("exit", {});
269
+ child.kill();
270
+ child = null;
271
+ }
272
+ return {
273
+ codeActions,
274
+ didChange,
275
+ didClose,
276
+ didOpen,
277
+ didSave,
278
+ start,
279
+ stop
280
+ };
281
+ }
282
+ function deactivate() {}
283
+ module.exports = {
284
+ activate,
285
+ deactivate,
286
+ resolveRelayPath,
287
+ relayArgs
288
+ };
289
+ //#endregion
@@ -0,0 +1,80 @@
1
+ //#region tools/vscode-visions/lsp-convert.ts
2
+ var SEVERITY_BY_LSP = {
3
+ 1: "Error",
4
+ 2: "Warning",
5
+ 3: "Information",
6
+ 4: "Hint"
7
+ };
8
+ function toPosition(vscodeApi, position) {
9
+ const line = Number.isInteger(position?.line) ? Number(position?.line) : 0;
10
+ const character = Number.isInteger(position?.character) ? Number(position?.character) : 0;
11
+ return new vscodeApi.Position(line, character);
12
+ }
13
+ function toRange(vscodeApi, range) {
14
+ return new vscodeApi.Range(toPosition(vscodeApi, range?.start), toPosition(vscodeApi, range?.end));
15
+ }
16
+ function toDiagnostic(vscodeApi, diagnostic) {
17
+ const converted = new vscodeApi.Diagnostic(toRange(vscodeApi, diagnostic?.range), typeof diagnostic?.message === "string" ? diagnostic.message : "", vscodeApi.DiagnosticSeverity[SEVERITY_BY_LSP[Number(diagnostic?.severity)] || "Warning"]);
18
+ if (diagnostic?.code !== void 0) converted.code = diagnostic.code;
19
+ if (typeof diagnostic?.source === "string") converted.source = diagnostic.source;
20
+ return converted;
21
+ }
22
+ function toDiagnostics(vscodeApi, diagnostics) {
23
+ if (!Array.isArray(diagnostics)) return [];
24
+ return diagnostics.map((diagnostic) => toDiagnostic(vscodeApi, diagnostic));
25
+ }
26
+ function documentChangesOf(edit) {
27
+ const changes = edit?.documentChanges;
28
+ if (!Array.isArray(changes)) return [];
29
+ return changes.filter((change) => typeof change?.textDocument?.uri === "string");
30
+ }
31
+ function toWorkspaceEdit(vscodeApi, edit) {
32
+ const workspaceEdit = new vscodeApi.WorkspaceEdit();
33
+ for (const change of documentChangesOf(edit)) {
34
+ const uri = vscodeApi.Uri.parse(change.textDocument.uri);
35
+ for (const textEdit of Array.isArray(change.edits) ? change.edits : []) workspaceEdit.replace(uri, toRange(vscodeApi, textEdit?.range), typeof textEdit?.newText === "string" ? textEdit.newText : "");
36
+ }
37
+ return workspaceEdit;
38
+ }
39
+ function toCodeAction(vscodeApi, action) {
40
+ const converted = new vscodeApi.CodeAction(typeof action?.title === "string" ? action.title : "Visions fix", vscodeApi.CodeActionKind.QuickFix);
41
+ if (action?.edit) converted.edit = toWorkspaceEdit(vscodeApi, action.edit);
42
+ const diagnostics = action?.diagnostics;
43
+ if (Array.isArray(diagnostics)) converted.diagnostics = toDiagnostics(vscodeApi, diagnostics);
44
+ return converted;
45
+ }
46
+ function toCodeActions(vscodeApi, actions) {
47
+ if (!Array.isArray(actions)) return [];
48
+ return actions.map((action) => toCodeAction(vscodeApi, action));
49
+ }
50
+ function decideEditFreshness(edit, versionOfUri) {
51
+ const changes = documentChangesOf(edit);
52
+ if (changes.length === 0) return {
53
+ fresh: false,
54
+ reason: "no-document-changes"
55
+ };
56
+ for (const change of changes) {
57
+ const expected = change.textDocument.version;
58
+ if (expected === null || expected === void 0) continue;
59
+ const current = versionOfUri(change.textDocument.uri);
60
+ if (current === null || current === void 0) continue;
61
+ if (current !== expected) return {
62
+ fresh: false,
63
+ reason: "stale-version"
64
+ };
65
+ }
66
+ return {
67
+ fresh: true,
68
+ reason: "ok"
69
+ };
70
+ }
71
+ module.exports = {
72
+ decideEditFreshness,
73
+ toCodeAction,
74
+ toCodeActions,
75
+ toDiagnostic,
76
+ toDiagnostics,
77
+ toRange,
78
+ toWorkspaceEdit
79
+ };
80
+ //#endregion
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "glimmervoid-visions",
3
+ "displayName": "Glimmervoid Visions",
4
+ "publisher": "johnwaters",
5
+ "version": "0.3.0",
6
+ "private": true,
7
+ "engines": {
8
+ "vscode": "^1.85.0"
9
+ },
10
+ "main": "./extension.js",
11
+ "activationEvents": [
12
+ "onStartupFinished"
13
+ ],
14
+ "contributes": {
15
+ "configuration": {
16
+ "title": "Glimmervoid Visions",
17
+ "properties": {
18
+ "glimmervoidVisions.relayPath": {
19
+ "type": "string",
20
+ "default": "",
21
+ "description": "Absolute path to the visions relay (dist/session/visions-relay.js in an installed package, session/visions-relay.ts in a source checkout). Empty uses the path stamped at install time."
22
+ },
23
+ "glimmervoidVisions.port": {
24
+ "type": "number",
25
+ "default": 0,
26
+ "description": "Relay port. Use 0 to let the relay choose its fallback."
27
+ }
28
+ }
29
+ }
30
+ },
31
+ "description": "Mirrors markdown buffers to the Glimmervoid daemon and shows its findings and silent fixes."
32
+ }
@@ -0,0 +1,112 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region server/core/visions-lsp-core.ts
3
+ var HEADER_END = "\r\n\r\n";
4
+ var CONTENT_LENGTH_RE = /^content-length:\s*(\d+)\s*$/i;
5
+ function createParserState() {
6
+ return {
7
+ buffer: Buffer.alloc(0),
8
+ neededBodyBytes: null
9
+ };
10
+ }
11
+ function feedFrameBytes(state, chunk) {
12
+ const nextState = state || createParserState();
13
+ nextState.buffer = Buffer.concat([nextState.buffer, chunk]);
14
+ const messages = [];
15
+ while (true) {
16
+ const bodyBytes = readNeededBodyBytes(nextState);
17
+ if (bodyBytes === null) break;
18
+ if (typeof bodyBytes !== "number") {
19
+ messages.push(bodyBytes);
20
+ nextState.neededBodyBytes = null;
21
+ continue;
22
+ }
23
+ if (nextState.buffer.length < bodyBytes) break;
24
+ const body = nextState.buffer.subarray(0, bodyBytes);
25
+ nextState.buffer = nextState.buffer.subarray(bodyBytes);
26
+ nextState.neededBodyBytes = null;
27
+ messages.push(parseBody(body));
28
+ }
29
+ return {
30
+ state: nextState,
31
+ messages
32
+ };
33
+ }
34
+ function readNeededBodyBytes(state) {
35
+ if (state.neededBodyBytes !== null) return state.neededBodyBytes;
36
+ const headerEndAt = state.buffer.indexOf(HEADER_END);
37
+ if (headerEndAt === -1) return null;
38
+ const headerText = state.buffer.subarray(0, headerEndAt).toString("ascii");
39
+ state.buffer = state.buffer.subarray(headerEndAt + 4);
40
+ const contentLength = contentLengthFromHeader(headerText);
41
+ if (contentLength === null) {
42
+ state.buffer = Buffer.alloc(0);
43
+ return {
44
+ parseError: true,
45
+ reason: "missing-content-length",
46
+ raw: headerText
47
+ };
48
+ }
49
+ state.neededBodyBytes = contentLength;
50
+ return state.neededBodyBytes;
51
+ }
52
+ function contentLengthFromHeader(headerText) {
53
+ const lines = headerText.split("\r\n");
54
+ for (const line of lines) {
55
+ const match = line.match(CONTENT_LENGTH_RE);
56
+ if (!match) continue;
57
+ return Number(match[1]);
58
+ }
59
+ return null;
60
+ }
61
+ function parseBody(body) {
62
+ const raw = body.toString("utf8");
63
+ try {
64
+ return JSON.parse(raw);
65
+ } catch {
66
+ return {
67
+ parseError: true,
68
+ raw
69
+ };
70
+ }
71
+ }
72
+ function serializeFrame(messageObject) {
73
+ const body = JSON.stringify(messageObject);
74
+ const bodyBytes = Buffer.byteLength(body, "utf8");
75
+ return Buffer.from(`Content-Length: ${bodyBytes}\r\n\r\n${body}`, "utf8");
76
+ }
77
+ function classifyMessage(msg) {
78
+ if (!msg || typeof msg !== "object") return {
79
+ kind: "invalid",
80
+ method: void 0,
81
+ id: void 0
82
+ };
83
+ const fields = msg;
84
+ const hasMethod = typeof fields.method === "string";
85
+ const hasId = Object.hasOwn(msg, "id");
86
+ const method = typeof fields.method === "string" ? fields.method : void 0;
87
+ if (hasMethod && hasId) return {
88
+ kind: "request",
89
+ method,
90
+ id: fields.id
91
+ };
92
+ if (hasMethod) return {
93
+ kind: "notification",
94
+ method,
95
+ id: void 0
96
+ };
97
+ if (hasId) return {
98
+ kind: "response",
99
+ method: void 0,
100
+ id: fields.id
101
+ };
102
+ return {
103
+ kind: "invalid",
104
+ method: void 0,
105
+ id: void 0
106
+ };
107
+ }
108
+ //#endregion
109
+ exports.classifyMessage = classifyMessage;
110
+ exports.createParserState = createParserState;
111
+ exports.feedFrameBytes = feedFrameBytes;
112
+ exports.serializeFrame = serializeFrame;
package/package.json CHANGED
@@ -1,6 +1,97 @@
1
1
  {
2
2
  "name": "glimmervoid",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.29.1",
4
+ "description": "Mission control for coding agents: run and supervise Claude Code, Codex and Grok sessions in parallel git worktrees from one local browser dashboard",
5
+ "main": "dist/server/index.js",
6
+ "type": "module",
7
+ "imports": {
8
+ "#shared/*": "./shared/*"
9
+ },
10
+ "bin": {
11
+ "glimmervoid": "dist/bin/glimmervoid.js"
12
+ },
13
+ "files": [
14
+ "dist/",
15
+ "!dist/client/pictures/",
16
+ "!dist/client/AGENTS.md",
17
+ "scripts/postinstall.mjs",
18
+ "scripts/recover-handoff.mjs",
19
+ "scripts/prepare-build.js"
20
+ ],
21
+ "engines": {
22
+ "node": ">=22.18.0"
23
+ },
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "author": "John C. Waters <john@johncwaters.com>",
28
+ "license": "MIT",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/johncwaters/glimmervoid.git"
32
+ },
33
+ "homepage": "https://github.com/johncwaters/glimmervoid#readme",
34
+ "bugs": {
35
+ "url": "https://github.com/johncwaters/glimmervoid/issues"
36
+ },
37
+ "keywords": [
38
+ "claude",
39
+ "claude-code",
40
+ "codex",
41
+ "coding-agents",
42
+ "ai-agents",
43
+ "agent-orchestrator",
44
+ "agent-manager",
45
+ "parallel-agents",
46
+ "git-worktree",
47
+ "terminal",
48
+ "dashboard",
49
+ "session-manager",
50
+ "xterm",
51
+ "windows",
52
+ "linux",
53
+ "macos"
54
+ ],
55
+ "scripts": {
56
+ "start": "node dist/server/index.js",
57
+ "lint": "biome check .",
58
+ "test": "node --import ./tests/helpers/isolate-home.ts --test \"tests/**/*.test.ts\"",
59
+ "typecheck": "tsc --project tsconfig.json && tsc --project tsconfig.public.json && tsc --project tsconfig.browser-harness.json",
60
+ "test:browser": "node test/browser/harness.ts",
61
+ "site:capture": "node test/site-capture/capture.ts",
62
+ "site:record": "node test/site-capture/record.ts",
63
+ "site:dev": "npm --prefix site run dev",
64
+ "site:build": "npm --prefix site run build",
65
+ "test:container": "docker build -f test/container/Dockerfile -t glimmervoid-remote-test . && docker run --rm glimmervoid-remote-test",
66
+ "dev": "vite",
67
+ "build": "node scripts/build.mjs",
68
+ "postinstall": "node scripts/postinstall.mjs",
69
+ "prepare": "node scripts/prepare-build.js",
70
+ "release": "node scripts/release.ts",
71
+ "docs:config": "node scripts/generate-config-docs.ts"
72
+ },
73
+ "dependencies": {
74
+ "@parcel/watcher": "^2.6.0",
75
+ "@xterm/addon-fit": "^0.11.0",
76
+ "@xterm/addon-serialize": "^0.14.0",
77
+ "@xterm/addon-webgl": "^0.19.0",
78
+ "@xterm/headless": "^6.0.0",
79
+ "@xterm/xterm": "^6.0.0",
80
+ "express": "^5.2.1",
81
+ "node-pty": "^1.1.0",
82
+ "ws": "^8.22.0",
83
+ "zod": "^4.6.5"
84
+ },
85
+ "allowScripts": {
86
+ "node-pty": true
87
+ },
88
+ "devDependencies": {
89
+ "@biomejs/biome": "^2.5.14",
90
+ "@tailwindcss/vite": "^4.3.3",
91
+ "@types/node": "^26.6.3",
92
+ "playwright-core": "1.63.0",
93
+ "tailwindcss": "^4.3.3",
94
+ "typescript": "^7.0.2",
95
+ "vite": "^8.3.1"
96
+ }
97
+ }
@@ -0,0 +1,4 @@
1
+ try {
2
+ await import('../dist/scripts/postinstall-path-check.js');
3
+ } catch {
4
+ }
@@ -0,0 +1,38 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+
5
+ const viteBin = path.join(import.meta.dirname, '..', 'node_modules', '.bin', process.platform === 'win32' ? 'vite.cmd' : 'vite');
6
+
7
+ function npmInvocation(args) {
8
+ const npmExecPath = process.env.npm_execpath;
9
+ if (npmExecPath && /\.[cm]?js$/.test(npmExecPath)) {
10
+ return { command: process.execPath, args: [npmExecPath, ...args], shell: false };
11
+ }
12
+ if (process.platform === 'win32') {
13
+ return { command: 'npm', args, shell: true };
14
+ }
15
+ return { command: 'npm', args, shell: false };
16
+ }
17
+
18
+ function runNpm(args, env = {}) {
19
+ const invocation = npmInvocation(args);
20
+ const child = spawnSync(invocation.command, invocation.args, {
21
+ env: { ...process.env, ...env, npm_config_global: 'false' },
22
+ stdio: 'inherit',
23
+ shell: invocation.shell,
24
+ });
25
+ if (child.error) {
26
+ console.error(`prepare-build: npm failed to start: ${child.error.message}`);
27
+ process.exit(1);
28
+ }
29
+ if (child.status === 0) return;
30
+ process.exit(child.status || 1);
31
+ }
32
+
33
+ if (!fs.existsSync(viteBin)) {
34
+ runNpm(['ci', '--include=dev', '--ignore-scripts', '--no-audit', '--no-fund']);
35
+ }
36
+ runNpm(['run', 'build']);
37
+
38
+ spawnSync(process.execPath, [path.join(import.meta.dirname, 'postinstall.mjs')], { stdio: 'inherit' });