clementine-agent 1.18.151 → 1.18.153
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/cli/dashboard.js +38 -5
- package/package.json +1 -1
package/dist/cli/dashboard.js
CHANGED
|
@@ -2047,9 +2047,36 @@ export async function cmdDashboard(opts) {
|
|
|
2047
2047
|
jsonParser(req, res, next);
|
|
2048
2048
|
});
|
|
2049
2049
|
// ── Dashboard authentication ────────────────────────────────────────
|
|
2050
|
-
|
|
2050
|
+
// 1.18.152 — persist the token across restarts. Before this, every
|
|
2051
|
+
// dashboard startup (manual restart, auto-respawn, crash recovery)
|
|
2052
|
+
// generated a fresh random token, which invalidated every browser
|
|
2053
|
+
// bookmark, open tab, and printed URL. Auto-respawn (1.18.146) +
|
|
2054
|
+
// auto-open browser (1.18.147) made this acutely visible — users
|
|
2055
|
+
// would re-open the dashboard and find the URL they had bookmarked
|
|
2056
|
+
// 401'd, then a new browser window would open with a different token,
|
|
2057
|
+
// and any hook commands installed in projects would silently 401 too.
|
|
2058
|
+
//
|
|
2059
|
+
// Fix: read the existing token if `~/.clementine/.dashboard-token`
|
|
2060
|
+
// already exists; only generate-and-persist on first-ever startup.
|
|
2061
|
+
// To rotate tokens deliberately, the user deletes the file and
|
|
2062
|
+
// restarts. Local-machine threat model assumes the home dir is
|
|
2063
|
+
// trusted (see feedback_security_model.md) — a persistent token here
|
|
2064
|
+
// is the same security posture as `~/.ssh/id_rsa`.
|
|
2051
2065
|
const tokenPath = path.join(BASE_DIR, '.dashboard-token');
|
|
2052
|
-
|
|
2066
|
+
let dashboardToken;
|
|
2067
|
+
try {
|
|
2068
|
+
const existing = readFileSync(tokenPath, 'utf-8').trim();
|
|
2069
|
+
// Strict format check — anything that doesn't look like a 48-hex-char
|
|
2070
|
+
// token (the format randomBytes(24).toString('hex') produces) gets
|
|
2071
|
+
// regenerated. Defends against truncated / corrupt files.
|
|
2072
|
+
if (!/^[a-f0-9]{48}$/.test(existing))
|
|
2073
|
+
throw new Error('invalid token format on disk');
|
|
2074
|
+
dashboardToken = existing;
|
|
2075
|
+
}
|
|
2076
|
+
catch {
|
|
2077
|
+
dashboardToken = randomBytes(24).toString('hex');
|
|
2078
|
+
writeFileSync(tokenPath, dashboardToken, { mode: 0o600 });
|
|
2079
|
+
}
|
|
2053
2080
|
// ── Remote access + session management ─────────────────────────────
|
|
2054
2081
|
const remoteConfig = loadRemoteConfig();
|
|
2055
2082
|
const sessions = new Map();
|
|
@@ -39458,9 +39485,15 @@ async function runWorkflow(name) {
|
|
|
39458
39485
|
// the list so the migrated workflow disappears (its .md is renamed to
|
|
39459
39486
|
// .md.migrated server-side and parseAllWorkflows stops picking it up).
|
|
39460
39487
|
async function migrateWorkflowToSkill(name) {
|
|
39461
|
-
|
|
39462
|
-
|
|
39463
|
-
|
|
39488
|
+
// 1.18.153 — escape \\n through the outer template literal. Without the
|
|
39489
|
+
// double-backslash the served HTML gets literal newlines INSIDE a single-
|
|
39490
|
+
// quoted JS string, which the browser parser rejects as
|
|
39491
|
+
// "Uncaught SyntaxError: Invalid or unexpected token". That kills the
|
|
39492
|
+
// entire inline script block, so no API calls fire, no data renders,
|
|
39493
|
+
// dashboard appears completely broken even though the server is healthy.
|
|
39494
|
+
if (!confirm('Migrate "' + name + '" into a skill folder?\\n\\n' +
|
|
39495
|
+
'• A new skill will be created at vault/00-System/skills/<slug>/SKILL.md\\n' +
|
|
39496
|
+
'• The original workflow .md will be renamed to .md.migrated (kept for rollback)\\n' +
|
|
39464
39497
|
'• The workflow stops firing; the skill is ready to schedule from the Skills tab')) return;
|
|
39465
39498
|
try {
|
|
39466
39499
|
var r = await apiFetch('/api/workflows/' + encodeURIComponent(name) + '/migrate-to-skill', {
|