glimmervoid 0.39.0 → 0.40.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/README.md +1 -1
- package/dist/bin/glimmervoid.js +22 -25
- package/dist/chunks/{adapters-B9tP9MXC.js → adapters-B6tbX3Aj.js} +4 -3
- package/dist/chunks/{adapters-Buu6yI71.js → adapters-CXQfLoyj.js} +1 -1
- package/dist/chunks/agent-api-cli-BBech5lF.js +1 -0
- package/dist/chunks/{agent-api-cli-2_RwTTTJ.js → agent-api-cli-BNHJTmNW.js} +46 -17
- package/dist/chunks/agent-api-core-DDrJQEdE.js +304 -0
- package/dist/chunks/{agent-setup-cli-C1nFdgFg.js → agent-setup-cli-CeBBwKuL.js} +1 -1
- package/dist/chunks/config-store-BZpN2djp.js +1 -0
- package/dist/chunks/{config-store-n23JDU4E.js → config-store-DqMScSdg.js} +20 -1
- package/dist/chunks/contracts-CloExMlS.js +680 -0
- package/dist/chunks/{contracts-DYQW11de.js → control-messages-DpBaniJi.js} +1201 -1794
- package/dist/chunks/{git-version-DXozXVnb.js → git-version-CJQMfxtZ.js} +1 -1
- package/dist/chunks/{grok-DeGAXgZF.js → grok-BLzhApwT.js} +1 -1
- package/dist/chunks/{main-D4uwk-_M.js → main-DDU8IvFD.js} +26436 -24806
- package/dist/chunks/{pair-cli-D9DZBqk0.js → pair-cli-CsOVTQGJ.js} +2 -2
- package/dist/chunks/{remote-config-DiLwnzBq.js → remote-config-HlABuLTp.js} +1 -1
- package/dist/chunks/{session-D2EbiysG.js → session-BwB43SCa.js} +103 -43
- package/dist/chunks/{session-routes-BQAZzMKZ.js → session-routes-DNJzsckH.js} +23 -3
- package/dist/chunks/{settings-cli-DP4t-I9U.js → settings-cli-DkkbK-dj.js} +30 -156
- package/dist/chunks/settings-readout-core-DrXT4aWm.js +201 -0
- package/dist/chunks/{ssh-sign-cli-D2RIs-iN.js → ssh-sign-cli-CYeKRevK.js} +2 -2
- package/dist/client/assets/index-BK9jLR47.js +148 -0
- package/dist/client/assets/index-CU_uqJmi.css +2 -0
- package/dist/client/index.html +4 -3
- package/dist/server/index.js +1 -1
- package/package.json +2 -2
- package/dist/chunks/agent-api-cli-PfCov-qb.js +0 -1
- package/dist/chunks/agent-api-core-D2HLgBEe.js +0 -180
- package/dist/chunks/config-store-8Z9vkWvf.js +0 -1
- package/dist/client/assets/index-C0YUJwjz.css +0 -2
- package/dist/client/assets/index-w8lG-tk2.js +0 -148
package/dist/client/index.html
CHANGED
|
@@ -6,17 +6,18 @@
|
|
|
6
6
|
<meta name="color-scheme" content="dark light">
|
|
7
7
|
<link rel="icon" type="image/svg+xml" href="/assets/favicon-CKygeLwW.svg">
|
|
8
8
|
<title>Glimmervoid</title>
|
|
9
|
-
<style>html,body{background:var(--bg,#0a0810);height:100%;color:var(--text,#c8c0e0);font-family:var(--font-mono,"CommitMono", "Cascadia Code", "Fira Code", "Consolas", "Menlo", monospace);margin:0;padding:0}.app-shell{display:none}html:not([data-layout=phone]) .app-ready .app-shell{display:contents}.loading-screen{z-index:9999;background:#0a0810;flex-direction:column;justify-content:center;align-items:center;gap:20px;transition:opacity .3s;display:flex;position:fixed;inset:0}.loading-screen.fade-out{opacity:0;pointer-events:none}.loading-title{letter-spacing:.1em;color:#e8e0ff;text-transform:uppercase;font-family:CommitMono,Cascadia Code,Fira Code,Consolas,Menlo,monospace;font-size:20px;font-weight:700}.loading-title:before{content:"▸";color:#c084fc}.loading-status{color:#8276b0;letter-spacing:.04em;font-family:CommitMono,Cascadia Code,Fira Code,Consolas,Menlo,monospace;font-size:12px}.loading-spinner{border:2px solid #2a2440;border-top-color:#c084fc;border-radius:50%;width:28px;height:28px;animation:.8s linear infinite spin}@keyframes spin{to{transform:rotate(360deg)}}.shutdown-screen:not(.active) .loading-spinner{animation:none}.shutdown-screen{z-index:9999;-webkit-backdrop-filter:blur();backdrop-filter:blur();pointer-events:none;opacity:0;background:#0a081000;flex-direction:column;justify-content:center;align-items:center;gap:20px;transition:background .4s,-webkit-backdrop-filter .4s,backdrop-filter .4s,opacity .3s;display:flex;position:fixed;inset:0}.shutdown-screen.active{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);pointer-events:auto;opacity:1;background:#0a0810eb}.shutdown-status{color:#8276b0;letter-spacing:.04em;font-family:CommitMono,Cascadia Code,Fira Code,Consolas,Menlo,monospace;font-size:12px;transition:color .3s}.shutdown-screen.done .loading-spinner{opacity:.3;border-color:#2a2440;animation:none}.shutdown-screen.done .shutdown-status{color:#4a4268}</style>
|
|
10
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
+
<style>html,body{background:var(--bg,#0a0810);height:100%;color:var(--text,#c8c0e0);font-family:var(--font-mono,"CommitMono", "Cascadia Code", "Fira Code", "Consolas", "Menlo", monospace);margin:0;padding:0}.app-shell{display:none}html:not([data-layout=phone]) .app-ready .app-shell{display:contents}.loading-screen{z-index:9999;background:#0a0810;flex-direction:column;justify-content:center;align-items:center;gap:20px;transition:opacity .3s;display:flex;position:fixed;inset:0}.loading-screen.fade-out{opacity:0;pointer-events:none}.loading-title{letter-spacing:.1em;color:#e8e0ff;text-transform:uppercase;font-family:CommitMono,Cascadia Code,Fira Code,Consolas,Menlo,monospace;font-size:20px;font-weight:700}.loading-title:before{content:"▸";color:#c084fc}.loading-status{color:#8276b0;letter-spacing:.04em;font-family:CommitMono,Cascadia Code,Fira Code,Consolas,Menlo,monospace;font-size:12px}.loading-detail{color:#5e5584;text-align:center;text-wrap:balance;max-width:min(34ch,100vw - 32px);margin-top:-8px;font-family:CommitMono,Cascadia Code,Fira Code,Consolas,Menlo,monospace;font-size:12px;line-height:1.6}.loading-spinner{border:2px solid #2a2440;border-top-color:#c084fc;border-radius:50%;width:28px;height:28px;animation:.8s linear infinite spin}@keyframes spin{to{transform:rotate(360deg)}}.shutdown-screen:not(.active) .loading-spinner{animation:none}.shutdown-screen{z-index:9999;-webkit-backdrop-filter:blur();backdrop-filter:blur();pointer-events:none;opacity:0;background:#0a081000;flex-direction:column;justify-content:center;align-items:center;gap:20px;transition:background .4s,-webkit-backdrop-filter .4s,backdrop-filter .4s,opacity .3s;display:flex;position:fixed;inset:0}.shutdown-screen.active{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);pointer-events:auto;opacity:1;background:#0a0810eb}.shutdown-status{color:#8276b0;letter-spacing:.04em;font-family:CommitMono,Cascadia Code,Fira Code,Consolas,Menlo,monospace;font-size:12px;transition:color .3s}.shutdown-screen.done .loading-spinner{opacity:.3;border-color:#2a2440;animation:none}.shutdown-screen.done .shutdown-status{color:#4a4268}</style>
|
|
10
|
+
<script type="module" crossorigin src="/assets/index-BK9jLR47.js"></script>
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/zod-BRLv4KqJ.js">
|
|
12
12
|
<link rel="modulepreload" crossorigin href="/assets/xterm-kR64YvZ-.js">
|
|
13
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
13
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CU_uqJmi.css">
|
|
14
14
|
</head>
|
|
15
15
|
<body>
|
|
16
16
|
<div class="loading-screen" id="loading-screen">
|
|
17
17
|
<div class="loading-title">Glimmervoid</div>
|
|
18
18
|
<div class="loading-spinner"></div>
|
|
19
19
|
<div class="loading-status" id="loading-status">Connecting to server...</div>
|
|
20
|
+
<div class="loading-detail" id="loading-detail" hidden></div>
|
|
20
21
|
</div>
|
|
21
22
|
|
|
22
23
|
<div class="shutdown-screen" id="shutdown-screen">
|
package/dist/server/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "glimmervoid",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.40.0",
|
|
4
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
5
|
"main": "dist/server/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"scripts": {
|
|
56
56
|
"start": "node dist/server/index.js",
|
|
57
57
|
"lint": "biome check . --max-diagnostics=none",
|
|
58
|
-
"test": "node --import ./tests/helpers/isolate-home.ts --test \"tests/**/*.test.ts\"",
|
|
58
|
+
"test": "coherence spec --check && coherence lexicon --check && node --import ./tests/helpers/isolate-home.ts --test \"tests/**/*.test.ts\"",
|
|
59
59
|
"test:files": "node --import ./tests/helpers/isolate-home.ts --test",
|
|
60
60
|
"typecheck": "tsc --project tsconfig.json && tsc --project tsconfig.public.json && tsc --project tsconfig.browser-harness.json",
|
|
61
61
|
"test:browser": "node test/browser/harness.ts",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { n as runAgentApiCli, r as sessionLimitsHelpLines } from "./agent-api-cli-2_RwTTTJ.js";
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import { a as AgentEditRequest, i as AgentAttentionRequest, s as AgentSpawnRequest, t as AGENT_API_VERBS } from "./session-D2EbiysG.js";
|
|
2
|
-
import { c as spawnRoute, i as editRoute, n as attentionRoute, s as pushRoute, t as NO_OWN_WORKTREE_REASON } from "./session-routes-BQAZzMKZ.js";
|
|
3
|
-
import crypto from "node:crypto";
|
|
4
|
-
var MAX_SPAWNS_IN_FLIGHT = 1;
|
|
5
|
-
var SPAWNABLE_DEPTH = 0;
|
|
6
|
-
var REFUSAL_REASON = "unknown session";
|
|
7
|
-
var INVALID_BODY_STATUS = 400;
|
|
8
|
-
var PUSH_REFUSED_STATUS = 409;
|
|
9
|
-
var PUSH_REFUSAL_COPY = Object.freeze({
|
|
10
|
-
"no-worktree": () => NO_OWN_WORKTREE_REASON,
|
|
11
|
-
"merge-in-progress": () => "a merge for this session is already running, so try again when it ends",
|
|
12
|
-
"not-continuable": () => "this session cannot be merged in its current state",
|
|
13
|
-
destroyed: () => "this session is ending",
|
|
14
|
-
"nothing-to-commit": () => "no commit on this branch is missing from the integration branch, so commit your work first",
|
|
15
|
-
"rebase-conflict": ({ base, conflicts = [] }) => `this branch conflicts with ${base} in ${conflicts.join(", ") || "one or more files"}, so rebase onto ${base}, resolve the conflicts, commit, then push again`,
|
|
16
|
-
"not-fast-forward": ({ base }) => `${base} could not be fast-forwarded to this branch, and a push is never forced`,
|
|
17
|
-
"base-diverged": ({ base }) => `the local ${base} and origin/${base} have diverged, which the operator has to reconcile`
|
|
18
|
-
});
|
|
19
|
-
function tokensMatch(presented, expected) {
|
|
20
|
-
if (presented.length !== expected.length) return false;
|
|
21
|
-
try {
|
|
22
|
-
return crypto.timingSafeEqual(Buffer.from(presented, "utf8"), Buffer.from(expected, "utf8"));
|
|
23
|
-
} catch {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
function refused() {
|
|
28
|
-
return {
|
|
29
|
-
ok: false,
|
|
30
|
-
status: 404,
|
|
31
|
-
reason: REFUSAL_REASON
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
function decideAgentRequest({ sessionId, presentedToken, expectedToken, isLoopback }) {
|
|
35
|
-
if (!isLoopback) return refused();
|
|
36
|
-
if (!sessionId) return refused();
|
|
37
|
-
if (!expectedToken) return refused();
|
|
38
|
-
if (!presentedToken) return refused();
|
|
39
|
-
if (!tokensMatch(presentedToken, expectedToken)) return refused();
|
|
40
|
-
return { ok: true };
|
|
41
|
-
}
|
|
42
|
-
function refuseByRole(route) {
|
|
43
|
-
if (route.answers) return { ok: true };
|
|
44
|
-
return {
|
|
45
|
-
ok: false,
|
|
46
|
-
status: 403,
|
|
47
|
-
reason: route.reason
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
function decideSpawnAllowance({ liveChildren, lifetimeSpawns, inFlight, depth, isEphemeral }) {
|
|
51
|
-
const role = refuseByRole(spawnRoute({
|
|
52
|
-
isEphemeral,
|
|
53
|
-
isSpawnedChild: depth !== SPAWNABLE_DEPTH
|
|
54
|
-
}));
|
|
55
|
-
if (!role.ok) return role;
|
|
56
|
-
if (inFlight >= MAX_SPAWNS_IN_FLIGHT) return {
|
|
57
|
-
ok: false,
|
|
58
|
-
status: 429,
|
|
59
|
-
reason: "a spawn is already in flight"
|
|
60
|
-
};
|
|
61
|
-
if (liveChildren >= 3) return {
|
|
62
|
-
ok: false,
|
|
63
|
-
status: 429,
|
|
64
|
-
reason: `at most 3 spawned sessions may be live at once`
|
|
65
|
-
};
|
|
66
|
-
if (lifetimeSpawns >= 10) return {
|
|
67
|
-
ok: false,
|
|
68
|
-
status: 429,
|
|
69
|
-
reason: `this session has used its 10 spawns`
|
|
70
|
-
};
|
|
71
|
-
return { ok: true };
|
|
72
|
-
}
|
|
73
|
-
function decideAttentionAllowance(caller) {
|
|
74
|
-
return refuseByRole(attentionRoute(caller));
|
|
75
|
-
}
|
|
76
|
-
function decideEditAllowance(caller) {
|
|
77
|
-
return refuseByRole(editRoute(caller));
|
|
78
|
-
}
|
|
79
|
-
function describePushRouteRefusal(caller) {
|
|
80
|
-
const route = pushRoute(caller);
|
|
81
|
-
if (route.answers) return null;
|
|
82
|
-
return {
|
|
83
|
-
status: PUSH_REFUSED_STATUS,
|
|
84
|
-
body: {
|
|
85
|
-
ok: false,
|
|
86
|
-
reason: route.code,
|
|
87
|
-
error: route.reason
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
function isAgentApiVerb(verb) {
|
|
92
|
-
return AGENT_API_VERBS.includes(verb);
|
|
93
|
-
}
|
|
94
|
-
function refuseInvalidBody(issues) {
|
|
95
|
-
return {
|
|
96
|
-
ok: false,
|
|
97
|
-
status: INVALID_BODY_STATUS,
|
|
98
|
-
error: issues[0]?.message || "invalid request"
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
function parseAgentVerb(verb, payload) {
|
|
102
|
-
if (!isAgentApiVerb(verb)) return {
|
|
103
|
-
ok: false,
|
|
104
|
-
status: 404,
|
|
105
|
-
error: REFUSAL_REASON
|
|
106
|
-
};
|
|
107
|
-
if (verb === "board" || verb === "push" || verb === "limits") return {
|
|
108
|
-
ok: true,
|
|
109
|
-
verb
|
|
110
|
-
};
|
|
111
|
-
if (verb === "attention") {
|
|
112
|
-
const parsed = AgentAttentionRequest.safeParse(payload);
|
|
113
|
-
if (!parsed.success) return refuseInvalidBody(parsed.error.issues);
|
|
114
|
-
return {
|
|
115
|
-
ok: true,
|
|
116
|
-
verb,
|
|
117
|
-
request: parsed.data
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
if (verb === "edit") {
|
|
121
|
-
const parsed = AgentEditRequest.safeParse(payload);
|
|
122
|
-
if (!parsed.success) return refuseInvalidBody(parsed.error.issues);
|
|
123
|
-
return {
|
|
124
|
-
ok: true,
|
|
125
|
-
verb,
|
|
126
|
-
request: parsed.data
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
const parsed = AgentSpawnRequest.safeParse(payload);
|
|
130
|
-
if (!parsed.success) return refuseInvalidBody(parsed.error.issues);
|
|
131
|
-
return {
|
|
132
|
-
ok: true,
|
|
133
|
-
verb,
|
|
134
|
-
request: parsed.data
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
function describePushLanding(landing) {
|
|
138
|
-
if (!landing.merged) {
|
|
139
|
-
const reason = landing.reason || "unknown";
|
|
140
|
-
const explain = PUSH_REFUSAL_COPY[reason];
|
|
141
|
-
return {
|
|
142
|
-
status: PUSH_REFUSED_STATUS,
|
|
143
|
-
body: {
|
|
144
|
-
ok: false,
|
|
145
|
-
reason,
|
|
146
|
-
error: explain ? explain(landing) : `the merge stopped: ${reason}`
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
if (landing.pushed) return {
|
|
151
|
-
status: 200,
|
|
152
|
-
body: {
|
|
153
|
-
ok: true,
|
|
154
|
-
landedOn: landing.base ?? null,
|
|
155
|
-
pushed: true
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
return {
|
|
159
|
-
status: 200,
|
|
160
|
-
body: {
|
|
161
|
-
ok: true,
|
|
162
|
-
landedOn: landing.base ?? null,
|
|
163
|
-
pushed: false,
|
|
164
|
-
note: "landed locally and nothing was pushed, because the repository has no origin remote or origin did not take a fast-forward"
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
function deriveChildSessionName(parentName, existingNames) {
|
|
169
|
-
const base = `${String(parentName || "").trim() || "session"} agent`;
|
|
170
|
-
const taken = new Set(existingNames);
|
|
171
|
-
let candidate = base;
|
|
172
|
-
let suffix = 1;
|
|
173
|
-
while (taken.has(candidate)) {
|
|
174
|
-
suffix += 1;
|
|
175
|
-
candidate = `${base} ${suffix}`;
|
|
176
|
-
}
|
|
177
|
-
return candidate;
|
|
178
|
-
}
|
|
179
|
-
//#endregion
|
|
180
|
-
export { decideSpawnAllowance as a, describePushRouteRefusal as c, decideEditAllowance as i, isAgentApiVerb as l, decideAgentRequest as n, deriveChildSessionName as o, decideAttentionAllowance as r, describePushLanding as s, REFUSAL_REASON as t, parseAgentVerb as u };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { s as loadConfigFile } from "./config-store-n23JDU4E.js";
|