clay-server 3.8.1 → 4.0.0-beta.10
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/lib/ask-user-mcp-server.js +5 -119
- package/lib/background-task-timing.js +105 -0
- package/lib/builtin-mates.js +6 -6
- package/lib/claude-hook-installer.js +15 -0
- package/lib/clay-history-mcp-server.js +62 -297
- package/lib/daemon.js +23 -1
- package/lib/debate-model-selection.js +119 -0
- package/lib/home-debate-tool-policy.js +164 -0
- package/lib/home-response-notifications.js +26 -0
- package/lib/knowledge-import.js +436 -0
- package/lib/knowledge-record-store.js +188 -0
- package/lib/knowledge-search.js +224 -0
- package/lib/mate-creation-mcp-server.js +55 -0
- package/lib/mate-knowledge-mcp-server.js +151 -0
- package/lib/mate-knowledge-migration.js +283 -0
- package/lib/mate-knowledge-service.js +488 -0
- package/lib/mate-knowledge-sync.js +482 -0
- package/lib/mate-ready-creation.js +95 -0
- package/lib/mates.js +2 -0
- package/lib/notes.js +2 -1
- package/lib/project-ask-user.js +64 -0
- package/lib/project-capsule-catalog.js +101 -0
- package/lib/project-connection.js +17 -0
- package/lib/project-debate-proposal.js +133 -17
- package/lib/project-debate.js +214 -110
- package/lib/project-delegated-follow-up.js +84 -0
- package/lib/project-delegated-session.js +53 -0
- package/lib/project-filesystem.js +7 -9
- package/lib/project-knowledge.js +23 -0
- package/lib/project-logs-comments.js +137 -0
- package/lib/project-logs-mcp-server.js +290 -0
- package/lib/project-logs-query.js +167 -0
- package/lib/project-logs-root.js +67 -0
- package/lib/project-logs-schema.js +259 -0
- package/lib/project-logs-service.js +357 -0
- package/lib/project-logs-snapshot.js +202 -0
- package/lib/project-logs-store.js +498 -0
- package/lib/project-logs-versioning.js +128 -0
- package/lib/project-logs.js +347 -0
- package/lib/project-mate-creation-proposal.js +120 -0
- package/lib/project-mate-interaction.js +14 -0
- package/lib/project-mate-knowledge.js +110 -0
- package/lib/project-memory.js +36 -7
- package/lib/project-models.js +157 -32
- package/lib/project-session-notes.js +2 -2
- package/lib/project-session-pair.js +8 -8
- package/lib/project-sessions.js +66 -51
- package/lib/project-vendor-login.js +414 -0
- package/lib/project-worker-proposal.js +25 -25
- package/lib/project-workspace-query.js +144 -0
- package/lib/project.js +433 -102
- package/lib/public/app.js +109 -48
- package/lib/public/css/avatar-imprints.css +0 -1
- package/lib/public/css/base.css +4 -0
- package/lib/public/css/capsule-ui.css +389 -0
- package/lib/public/css/command-palette.css +306 -6
- package/lib/public/css/home-capsule-library.css +243 -0
- package/lib/public/css/home-capsule-source.css +192 -0
- package/lib/public/css/home-debate-live.css +146 -0
- package/lib/public/css/home-debate-planning.css +125 -0
- package/lib/public/css/home-debates-archive.css +281 -0
- package/lib/public/css/home-hub.css +896 -405
- package/lib/public/css/home-mate-creation.css +34 -0
- package/lib/public/css/home-mate-model-picker.css +131 -0
- package/lib/public/css/home-mate-settings.css +344 -0
- package/lib/public/css/home-session-actions.css +265 -0
- package/lib/public/css/home-sidebar.css +667 -0
- package/lib/public/css/icon-strip.css +1 -2
- package/lib/public/css/input.css +79 -25
- package/lib/public/css/mates.css +7 -34
- package/lib/public/css/pane.css +1 -1
- package/lib/public/css/playbook.css +0 -80
- package/lib/public/css/project-logs.css +234 -0
- package/lib/public/css/scheduler.css +1 -1
- package/lib/public/css/sticky-notes.css +53 -117
- package/lib/public/css/tui-attention.css +0 -44
- package/lib/public/css/workspace-assignment.css +45 -0
- package/lib/public/fonts/source-serif-4/LICENSE.md +93 -0
- package/lib/public/fonts/source-serif-4/SourceSerif4Caption-Semibold.ttf.woff2 +0 -0
- package/lib/public/index.html +96 -74
- package/lib/public/modules/app-connection.js +100 -5
- package/lib/public/modules/app-dm.js +43 -160
- package/lib/public/modules/app-home-hub.js +328 -585
- package/lib/public/modules/app-message-cards.js +242 -0
- package/lib/public/modules/app-message-router.js +84 -0
- package/lib/public/modules/app-messages.js +124 -38
- package/lib/public/modules/app-notifications.js +8 -119
- package/lib/public/modules/app-panels.js +43 -2
- package/lib/public/modules/app-projects.js +9 -1
- package/lib/public/modules/app-rendering.js +21 -602
- package/lib/public/modules/avatar-imprint.js +11 -8
- package/lib/public/modules/background-tasks-ui.js +139 -16
- package/lib/public/modules/chat-bubble-renderer.js +152 -0
- package/lib/public/modules/chat-render-runtime.js +198 -0
- package/lib/public/modules/command-palette.js +225 -436
- package/lib/public/modules/dm-render.js +82 -0
- package/lib/public/modules/home-capsule-creation-intent.js +31 -0
- package/lib/public/modules/home-capsule-library.js +146 -0
- package/lib/public/modules/home-capsule-source.js +383 -0
- package/lib/public/modules/home-chat-identity.js +35 -0
- package/lib/public/modules/home-chat-scroll.js +77 -0
- package/lib/public/modules/home-chat-stream-state.js +34 -0
- package/lib/public/modules/home-composer-focus.js +25 -0
- package/lib/public/modules/home-conversations-sheet.js +179 -0
- package/lib/public/modules/home-debate-activity.js +48 -0
- package/lib/public/modules/home-debate-controls.js +295 -0
- package/lib/public/modules/home-debate-launch.js +41 -0
- package/lib/public/modules/home-debate-live.js +284 -0
- package/lib/public/modules/home-debate-models.js +73 -0
- package/lib/public/modules/home-debate-planning.js +335 -0
- package/lib/public/modules/home-debates-archive.js +279 -0
- package/lib/public/modules/home-dock-resize.js +74 -0
- package/lib/public/modules/home-dock.js +446 -0
- package/lib/public/modules/home-mate-chat.js +496 -0
- package/lib/public/modules/home-mate-creation.js +109 -0
- package/lib/public/modules/home-mate-model-picker.js +281 -0
- package/lib/public/modules/home-mate-selection.js +38 -0
- package/lib/public/modules/home-mate-settings-menu.js +131 -0
- package/lib/public/modules/home-mate-settings.js +383 -0
- package/lib/public/modules/home-session-actions.js +373 -0
- package/lib/public/modules/home-session-model-confirmation.js +13 -0
- package/lib/public/modules/home-shell.js +9 -0
- package/lib/public/modules/home-sidebar-chat-list.js +63 -0
- package/lib/public/modules/home-sidebar.js +165 -0
- package/lib/public/modules/home-sub-surface.js +19 -0
- package/lib/public/modules/home-surface-boot.js +68 -0
- package/lib/public/modules/home-surface.js +141 -0
- package/lib/public/modules/home-tools.js +271 -0
- package/lib/public/modules/markdown.js +50 -2
- package/lib/public/modules/mate-management.js +86 -0
- package/lib/public/modules/mate-sidebar.js +0 -8
- package/lib/public/modules/mate-wizard.js +0 -7
- package/lib/public/modules/mention.js +17 -19
- package/lib/public/modules/pane-bridge.js +9 -0
- package/lib/public/modules/profile.js +4 -5
- package/lib/public/modules/project-logs-ambient.js +238 -0
- package/lib/public/modules/project-logs-render.js +359 -0
- package/lib/public/modules/project-logs.js +328 -0
- package/lib/public/modules/project-settings.js +34 -28
- package/lib/public/modules/project-switcher.js +11 -5
- package/lib/public/modules/project-workspace-assignment.js +23 -0
- package/lib/public/modules/scheduler.js +17 -3
- package/lib/public/modules/search-clay-chat.js +402 -0
- package/lib/public/modules/server-settings.js +14 -12
- package/lib/public/modules/session-actions.js +1 -1
- package/lib/public/modules/sidebar-mates.js +56 -552
- package/lib/public/modules/sidebar-mobile.js +12 -73
- package/lib/public/modules/sidebar-presence.js +37 -0
- package/lib/public/modules/sidebar-sessions.js +25 -1
- package/lib/public/modules/split-pair-ui.js +13 -13
- package/lib/public/modules/split-view.js +7 -0
- package/lib/public/modules/sticky-notes.js +106 -53
- package/lib/public/modules/tool-input-composition.js +48 -0
- package/lib/public/modules/tool-llm-status.js +167 -0
- package/lib/public/modules/tool-palette.js +76 -4
- package/lib/public/modules/tool-renderer-advanced.js +285 -0
- package/lib/public/modules/tool-renderer-chart.js +158 -0
- package/lib/public/modules/tool-renderer-semantics.js +35 -0
- package/lib/public/modules/tool-renderer.js +464 -0
- package/lib/public/modules/tool-runtime.js +309 -0
- package/lib/public/modules/tool-ui-evaluator.js +97 -0
- package/lib/public/modules/tool-ui-tree.js +21 -0
- package/lib/public/modules/tui-attention.js +10 -0
- package/lib/public/modules/user-settings.js +16 -23
- package/lib/public/modules/vendor-login.js +287 -0
- package/lib/public/modules/worker-proposal.js +2 -2
- package/lib/public/modules/workspace-assignment-card.js +149 -0
- package/lib/public/modules/workspace-assignment-routing.js +4 -0
- package/lib/public/style.css +14 -2
- package/lib/runtime-env.js +65 -0
- package/lib/sdk-bridge.js +120 -32
- package/lib/sdk-message-processor.js +34 -13
- package/lib/server-home-capsule-creation.js +36 -0
- package/lib/server-home-chat-events.js +287 -0
- package/lib/server-home-chat.js +518 -0
- package/lib/server-home-clay-entry.js +65 -0
- package/lib/server-home-clay-session-links.js +26 -0
- package/lib/server-home-debate-planning.js +214 -0
- package/lib/server-home-debates.js +137 -0
- package/lib/server-home-mate-creation.js +261 -0
- package/lib/server-home-models.js +241 -0
- package/lib/server-home-preferences.js +61 -0
- package/lib/server-mates.js +37 -0
- package/lib/server-tools.js +377 -0
- package/lib/server.js +166 -59
- package/lib/session-pair-mcp-server.js +6 -6
- package/lib/sessions.js +22 -4
- package/lib/tool-capsule-source.js +142 -0
- package/lib/tool-control-mcp-server.js +126 -0
- package/lib/tool-llm.js +48 -0
- package/lib/tool-storage.js +77 -0
- package/lib/tool-ui-spec-advanced.js +82 -0
- package/lib/tool-ui-spec.js +261 -0
- package/lib/tools-registry.js +286 -0
- package/lib/users-home-dock-preferences.js +77 -0
- package/lib/users-home-surface-preferences.js +99 -0
- package/lib/users-preferences.js +4 -7
- package/lib/users.js +12 -0
- package/lib/whats-new-content.js +3 -3
- package/lib/workspace-assignment-service.js +420 -0
- package/lib/workspace-query-mcp-server.js +154 -0
- package/lib/workspace-query-service.js +492 -0
- package/lib/ws-schema.js +107 -12
- package/lib/yoke/adapters/acp.js +2 -1
- package/lib/yoke/adapters/antigravity.js +2 -1
- package/lib/yoke/adapters/claude-worker.js +11 -4
- package/lib/yoke/adapters/claude.js +141 -46
- package/lib/yoke/adapters/codex.js +79 -11
- package/lib/yoke/adapters/kiro.js +2 -1
- package/lib/yoke/claude-user-input.js +38 -0
- package/lib/yoke/codex-app-server.js +20 -2
- package/lib/yoke/codex-background-tasks.js +8 -2
- package/lib/yoke/codex-user-input.js +64 -0
- package/lib/yoke/complete-once.js +164 -0
- package/lib/yoke/index.js +5 -1
- package/lib/yoke/interface.js +19 -0
- package/lib/yoke/mcp-bridge-server.js +2 -6
- package/lib/yoke/user-input.js +254 -0
- package/package.json +4 -3
- package/lib/public/css/home-chat.css +0 -380
- package/lib/public/modules/home-chat.js +0 -438
- package/lib/server-clay-home.js +0 -245
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
// Automatic upgrade migration: legacy Mate memory and knowledge files into the
|
|
2
|
+
// Clay-wide append-only Knowledge backend.
|
|
3
|
+
//
|
|
4
|
+
// This module owns discovery, the run lock, and versioned state. The actual
|
|
5
|
+
// source-to-record work lives in mate-knowledge-sync.js, which is the same code
|
|
6
|
+
// the live write-through bridge uses, so a startup import and a post-mutation
|
|
7
|
+
// mirror can never disagree about how a source is represented.
|
|
8
|
+
//
|
|
9
|
+
// Properties this migration guarantees:
|
|
10
|
+
// - Non-destructive. Legacy files are read and never written, renamed, or
|
|
11
|
+
// removed. They stay the live source for the existing read paths.
|
|
12
|
+
// - Idempotent. Every source unit carries a stable import key, so a restart,
|
|
13
|
+
// a partial run, or a deleted state file re-imports nothing.
|
|
14
|
+
// - Overlap-safe. A run lock keeps two daemons from importing at once, and
|
|
15
|
+
// the importer folds away a duplicate even if the lock is bypassed.
|
|
16
|
+
// - Torn-input tolerant. An unparseable journal line is counted and skipped;
|
|
17
|
+
// it never aborts the run.
|
|
18
|
+
// - Honest. A source that cannot be represented is reported as a failure
|
|
19
|
+
// rather than silently truncated or skipped.
|
|
20
|
+
// - Isolated. Each user's Mates land in their own scope, derived from the
|
|
21
|
+
// Mate storage root that already separates users on disk.
|
|
22
|
+
|
|
23
|
+
var fs = require("fs");
|
|
24
|
+
var path = require("path");
|
|
25
|
+
var config = require("./config");
|
|
26
|
+
var recordStore = require("./knowledge-record-store");
|
|
27
|
+
var mateSync = require("./mate-knowledge-sync");
|
|
28
|
+
|
|
29
|
+
var MIGRATION_NAME = "mate-knowledge";
|
|
30
|
+
var MIGRATION_VERSION = 2;
|
|
31
|
+
var LOCK_STALE_MS = 10 * 60 * 1000;
|
|
32
|
+
|
|
33
|
+
function knowledgeRoot() {
|
|
34
|
+
return recordStore.knowledgeRoot();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function statePath(baseDir) {
|
|
38
|
+
return path.join(baseDir || knowledgeRoot(), "migration-state.json");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function lockPath(baseDir) {
|
|
42
|
+
return path.join(baseDir || knowledgeRoot(), ".mate-migration.lock");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function isMateDirName(name) {
|
|
46
|
+
return typeof name === "string" && name.indexOf("mate_") === 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function safeReadDir(dir) {
|
|
50
|
+
try {
|
|
51
|
+
return fs.readdirSync(dir, { withFileTypes: true });
|
|
52
|
+
} catch (e) {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function mateNames(matesRoot) {
|
|
58
|
+
var names = {};
|
|
59
|
+
try {
|
|
60
|
+
var parsed = JSON.parse(fs.readFileSync(path.join(matesRoot, "mates.json"), "utf8"));
|
|
61
|
+
var list = (parsed && parsed.mates) || [];
|
|
62
|
+
for (var i = 0; i < list.length; i++) {
|
|
63
|
+
if (list[i] && list[i].id) names[list[i].id] = list[i].name || null;
|
|
64
|
+
}
|
|
65
|
+
} catch (e) {
|
|
66
|
+
// A missing or corrupt registry only costs provenance detail.
|
|
67
|
+
}
|
|
68
|
+
return names;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function collectFromRoot(matesRoot, out) {
|
|
72
|
+
var names = mateNames(matesRoot);
|
|
73
|
+
var entries = safeReadDir(matesRoot);
|
|
74
|
+
for (var i = 0; i < entries.length; i++) {
|
|
75
|
+
if (!entries[i].isDirectory() || !isMateDirName(entries[i].name)) continue;
|
|
76
|
+
var scope = mateSync.scopeForMateDir(path.join(matesRoot, entries[i].name));
|
|
77
|
+
if (!scope) continue;
|
|
78
|
+
scope.mateName = names[entries[i].name] || null;
|
|
79
|
+
out.push(scope);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Both storage layouts are walked directly rather than through the Mate
|
|
84
|
+
// registry, so a Mate whose registry entry is missing or corrupt still gets
|
|
85
|
+
// its durable content migrated.
|
|
86
|
+
// single-user: {CONFIG_DIR}/mates/mate_*
|
|
87
|
+
// multi-user: {CONFIG_DIR}/mates/{userId}/mate_*
|
|
88
|
+
// OS users: roots supplied by the caller
|
|
89
|
+
function discoverMates(opts) {
|
|
90
|
+
var options = opts || {};
|
|
91
|
+
var out = [];
|
|
92
|
+
var matesHome = options.matesHome || path.join(config.CONFIG_DIR, "mates");
|
|
93
|
+
collectFromRoot(matesHome, out);
|
|
94
|
+
|
|
95
|
+
var entries = safeReadDir(matesHome);
|
|
96
|
+
for (var i = 0; i < entries.length; i++) {
|
|
97
|
+
if (!entries[i].isDirectory() || isMateDirName(entries[i].name)) continue;
|
|
98
|
+
collectFromRoot(path.join(matesHome, entries[i].name), out);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
var roots = options.extraRoots || [];
|
|
102
|
+
for (var r = 0; r < roots.length; r++) {
|
|
103
|
+
if (!roots[r] || !roots[r].matesRoot) continue;
|
|
104
|
+
collectFromRoot(roots[r].matesRoot, out);
|
|
105
|
+
}
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// --- Versioned state -------------------------------------------------
|
|
110
|
+
|
|
111
|
+
// State is a fast-path hint and an audit trail, never the authority. Deleting
|
|
112
|
+
// it makes the next run re-scan and import nothing, because the import keys
|
|
113
|
+
// already present in the records are what actually decide.
|
|
114
|
+
function loadState(baseDir) {
|
|
115
|
+
try {
|
|
116
|
+
var parsed = JSON.parse(fs.readFileSync(statePath(baseDir), "utf8"));
|
|
117
|
+
if (parsed && parsed.version === MIGRATION_VERSION && parsed.scopes) return parsed;
|
|
118
|
+
} catch (e) {}
|
|
119
|
+
return { version: MIGRATION_VERSION, migration: MIGRATION_NAME, scopes: {}, lastRunAt: 0 };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function saveState(baseDir, state) {
|
|
123
|
+
var target = statePath(baseDir);
|
|
124
|
+
try {
|
|
125
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
126
|
+
var temporary = target + ".tmp." + process.pid;
|
|
127
|
+
fs.writeFileSync(temporary, JSON.stringify(state, null, 2) + "\n");
|
|
128
|
+
config.chmodSafe(temporary, 0o600);
|
|
129
|
+
fs.renameSync(temporary, target);
|
|
130
|
+
} catch (e) {
|
|
131
|
+
// A migration that cannot record state still completed its imports.
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// --- Run lock ---------------------------------------------------------
|
|
136
|
+
|
|
137
|
+
function writeLock(target) {
|
|
138
|
+
var payload = JSON.stringify({ pid: process.pid, startedAt: Date.now() }) + "\n";
|
|
139
|
+
var fd = fs.openSync(target, "wx");
|
|
140
|
+
try {
|
|
141
|
+
fs.writeSync(fd, Buffer.from(payload, "utf8"));
|
|
142
|
+
} finally {
|
|
143
|
+
fs.closeSync(fd);
|
|
144
|
+
}
|
|
145
|
+
return target;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// A live holder always wins, no matter how long it has been running. Stealing
|
|
149
|
+
// a lock from a running daemon would let two daemons import at once and would
|
|
150
|
+
// let the first one unlink the second one's lock on completion. Age alone can
|
|
151
|
+
// only reclaim a lock whose holder is gone or unidentifiable.
|
|
152
|
+
function acquireLock(baseDir) {
|
|
153
|
+
var target = lockPath(baseDir);
|
|
154
|
+
try {
|
|
155
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
156
|
+
} catch (e) {}
|
|
157
|
+
try {
|
|
158
|
+
return writeLock(target);
|
|
159
|
+
} catch (e) {
|
|
160
|
+
if (!e || e.code !== "EEXIST") return null;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
var holder = null;
|
|
164
|
+
try {
|
|
165
|
+
holder = JSON.parse(fs.readFileSync(target, "utf8"));
|
|
166
|
+
} catch (e2) {}
|
|
167
|
+
|
|
168
|
+
var pid = holder && holder.pid;
|
|
169
|
+
if (pid && config.isPidAlive(pid)) return null;
|
|
170
|
+
|
|
171
|
+
// No identifiable holder: only reclaim once it is unambiguously abandoned.
|
|
172
|
+
if (!pid) {
|
|
173
|
+
var age = Date.now() - ((holder && holder.startedAt) || 0);
|
|
174
|
+
if (age < LOCK_STALE_MS) return null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
try {
|
|
178
|
+
fs.unlinkSync(target);
|
|
179
|
+
return writeLock(target);
|
|
180
|
+
} catch (e3) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function releaseLock(target) {
|
|
186
|
+
if (!target) return;
|
|
187
|
+
try { fs.unlinkSync(target); } catch (e) {}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// --- Entry point -------------------------------------------------------
|
|
191
|
+
|
|
192
|
+
function run(opts) {
|
|
193
|
+
var options = opts || {};
|
|
194
|
+
var baseDir = options.baseDir || knowledgeRoot();
|
|
195
|
+
var summary = mateSync.newSummary();
|
|
196
|
+
summary.migration = MIGRATION_NAME;
|
|
197
|
+
summary.version = MIGRATION_VERSION;
|
|
198
|
+
summary.scopes = 0;
|
|
199
|
+
|
|
200
|
+
var lock = acquireLock(baseDir);
|
|
201
|
+
if (!lock) {
|
|
202
|
+
summary.skipped = "locked";
|
|
203
|
+
return summary;
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
var mates = discoverMates(options);
|
|
207
|
+
var state = loadState(baseDir);
|
|
208
|
+
for (var i = 0; i < mates.length; i++) {
|
|
209
|
+
var before = summary.failed;
|
|
210
|
+
try {
|
|
211
|
+
mateSync.reconcileMate({
|
|
212
|
+
scope: mates[i],
|
|
213
|
+
mateName: mates[i].mateName,
|
|
214
|
+
baseDir: baseDir,
|
|
215
|
+
actor: { type: "migration" },
|
|
216
|
+
summary: summary,
|
|
217
|
+
});
|
|
218
|
+
} catch (e) {
|
|
219
|
+
summary.failed++;
|
|
220
|
+
summary.errors.push({ scopeId: mates[i].scopeId, message: e.message });
|
|
221
|
+
}
|
|
222
|
+
summary.scopes++;
|
|
223
|
+
state.scopes[mates[i].scopeId] = {
|
|
224
|
+
version: MIGRATION_VERSION,
|
|
225
|
+
mateId: mates[i].mateId,
|
|
226
|
+
userId: mates[i].userId,
|
|
227
|
+
completedAt: Date.now(),
|
|
228
|
+
// A scope with a failure is recorded as incomplete so it is never
|
|
229
|
+
// reported as migrated while a source is missing content.
|
|
230
|
+
complete: summary.failed === before,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
state.lastRunAt = Date.now();
|
|
234
|
+
saveState(baseDir, state);
|
|
235
|
+
return summary;
|
|
236
|
+
} finally {
|
|
237
|
+
releaseLock(lock);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Startup wrapper: never throws, never blocks boot, logs only when it did work
|
|
242
|
+
// or when a source could not be represented.
|
|
243
|
+
function runAtStartup(opts) {
|
|
244
|
+
var summary;
|
|
245
|
+
try {
|
|
246
|
+
summary = run(opts);
|
|
247
|
+
} catch (e) {
|
|
248
|
+
console.error("[knowledge-migration] Mate knowledge migration failed:", e.message);
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
if (summary.skipped === "locked") return summary;
|
|
252
|
+
if (summary.created > 0 || summary.revised > 0 || summary.deleted > 0) {
|
|
253
|
+
console.log("[knowledge-migration] Mate knowledge: " + summary.created + " imported, " +
|
|
254
|
+
summary.revised + " revised, " + summary.deleted + " tombstoned, " +
|
|
255
|
+
summary.unchanged + " unchanged across " + summary.scopes + " scope(s)");
|
|
256
|
+
}
|
|
257
|
+
if (summary.failed > 0) {
|
|
258
|
+
console.error("[knowledge-migration] " + summary.failed + " source(s) could not be migrated; " +
|
|
259
|
+
"legacy files remain authoritative. First error: " + (summary.errors[0] && summary.errors[0].message));
|
|
260
|
+
}
|
|
261
|
+
return summary;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
module.exports = {
|
|
265
|
+
MIGRATION_NAME: MIGRATION_NAME,
|
|
266
|
+
MIGRATION_VERSION: MIGRATION_VERSION,
|
|
267
|
+
LOCK_STALE_MS: LOCK_STALE_MS,
|
|
268
|
+
IDENTITY_FILES: mateSync.IDENTITY_FILES,
|
|
269
|
+
EXCLUDED_FILES: mateSync.EXCLUDED_FILES,
|
|
270
|
+
JOURNAL_KINDS: mateSync.JOURNAL_KINDS,
|
|
271
|
+
ownerKeyForRoot: mateSync.ownerKeyForRoot,
|
|
272
|
+
scopeIdFor: mateSync.scopeIdFor,
|
|
273
|
+
scopeForMateDir: mateSync.scopeForMateDir,
|
|
274
|
+
sourceKindFor: mateSync.sourceKindFor,
|
|
275
|
+
discoverMates: discoverMates,
|
|
276
|
+
statePath: statePath,
|
|
277
|
+
lockPath: lockPath,
|
|
278
|
+
loadState: loadState,
|
|
279
|
+
acquireLock: acquireLock,
|
|
280
|
+
releaseLock: releaseLock,
|
|
281
|
+
run: run,
|
|
282
|
+
runAtStartup: runAtStartup,
|
|
283
|
+
};
|