clay-server 5.1.0-beta.1 → 5.1.0-beta.3
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/LICENSES/README.md +4 -0
- package/LICENSES/dicebear-avatars.md +16 -0
- package/bin/cli.js +9 -91
- package/lib/builtin-mates.js +7 -7
- package/lib/daemon-project-access.js +7 -1
- package/lib/daemon-settings.js +11 -0
- package/lib/daemon.js +10 -37
- package/lib/dicebear-avatar.js +62 -0
- package/lib/knowledge-db-service.js +175 -0
- package/lib/knowledge-db-validation.js +0 -0
- package/lib/knowledge-document-index.js +49 -0
- package/lib/knowledge-draft-store.js +56 -0
- package/lib/knowledge-file-store.js +199 -0
- package/lib/knowledge-markdown.js +128 -0
- package/lib/linear-store.js +35 -8
- package/lib/mate-identity-file.js +39 -0
- package/lib/mate-knowledge-mcp-server.js +29 -6
- package/lib/mate-knowledge-service.js +23 -2
- package/lib/mate-knowledge-sync.js +37 -22
- package/lib/mate-ready-creation.js +2 -1
- package/lib/mate-workspace-color.js +4 -0
- package/lib/mates-identity.js +4 -4
- package/lib/mates-prompts.js +4 -3
- package/lib/mates.js +30 -11
- package/lib/os-users.js +5 -16
- package/lib/project-connection.js +36 -9
- package/lib/project-debate-proposal.js +6 -0
- package/lib/project-debate-workspace.js +43 -0
- package/lib/project-debate.js +4 -2
- package/lib/project-filesystem.js +21 -39
- package/lib/project-knowledge.js +315 -136
- package/lib/project-mate-creation-proposal.js +1 -0
- package/lib/project-mate-interaction.js +7 -6
- package/lib/project-server-settings.js +31 -0
- package/lib/project-sessions.js +92 -182
- package/lib/project-user-knowledge.js +60 -0
- package/lib/project.js +62 -21
- package/lib/public/app.js +79 -71
- package/lib/public/clay-studio-wordmark-bold.svg +20 -0
- package/lib/public/css/clay-workspace.css +105 -0
- package/lib/public/css/debates-workbench.css +47 -0
- package/lib/public/css/home-debate-live.css +26 -0
- package/lib/public/css/home-hub.css +3 -1
- package/lib/public/css/home-mate-model-picker.css +15 -131
- package/lib/public/css/home-mate-settings.css +168 -16
- package/lib/public/css/icon-strip.css +249 -32
- package/lib/public/css/input.css +3 -1
- package/lib/public/css/mate-conversation.css +176 -0
- package/lib/public/css/mate-knowledge-workbench.css +118 -0
- package/lib/public/css/mate-workspace-color.css +16 -0
- package/lib/public/css/mates.css +28 -28
- package/lib/public/css/menus.css +3 -0
- package/lib/public/css/messages.css +1 -114
- package/lib/public/css/mobile-nav.css +16 -16
- package/lib/public/css/overlays.css +15 -0
- package/lib/public/css/project-logs.css +7 -0
- package/lib/public/css/project-mate-creation.css +105 -0
- package/lib/public/css/project-settings-modal.css +56 -0
- package/lib/public/css/right-workbench.css +3 -3
- package/lib/public/css/server-settings-system.css +125 -0
- package/lib/public/css/session-folders.css +80 -21
- package/lib/public/css/session-github.css +25 -16
- package/lib/public/css/settings-ui.css +247 -22
- package/lib/public/css/shared-browser.css +7 -3
- package/lib/public/css/sidebar.css +183 -107
- package/lib/public/css/title-bar.css +156 -1
- package/lib/public/css/worker-delegation.css +47 -0
- package/lib/public/css/worker-proposal.css +72 -150
- package/lib/public/css/you.css +74 -0
- package/lib/public/index.html +206 -548
- package/lib/public/modules/account-island.js +232 -0
- package/lib/public/modules/admin-settings-email.js +197 -0
- package/lib/public/modules/admin-settings-invitations.js +183 -0
- package/lib/public/modules/admin-settings-projects.js +198 -0
- package/lib/public/modules/admin-settings-ui.js +100 -0
- package/lib/public/modules/admin-settings-users.js +331 -0
- package/lib/public/modules/admin.js +19 -949
- package/lib/public/modules/app-cursors.js +19 -43
- package/lib/public/modules/app-debate-ui.js +4 -3
- package/lib/public/modules/app-dm.js +0 -2
- package/lib/public/modules/app-header.js +106 -0
- package/lib/public/modules/app-message-router.js +12 -3
- package/lib/public/modules/app-messages.js +47 -61
- package/lib/public/modules/app-notifications.js +4 -7
- package/lib/public/modules/app-projects.js +5 -38
- package/lib/public/modules/app-rate-limit.js +70 -12
- package/lib/public/modules/app-rendering.js +12 -13
- package/lib/public/modules/avatar.js +30 -9
- package/lib/public/modules/chat-render-runtime.js +16 -4
- package/lib/public/modules/command-palette.js +2 -15
- package/lib/public/modules/context-sources.js +27 -18
- package/lib/public/modules/cursor-sharing-preference.js +3 -3
- package/lib/public/modules/debate-controls.js +299 -0
- package/lib/public/modules/debate.js +2 -0
- package/lib/public/modules/debates-workbench.js +339 -0
- package/lib/public/modules/default-ai.js +88 -65
- package/lib/public/modules/header-tui-font.js +10 -20
- package/lib/public/modules/home-debate-controls.js +18 -289
- package/lib/public/modules/home-mate-avatar-editor.js +228 -0
- package/lib/public/modules/home-mate-color-picker.js +66 -0
- package/lib/public/modules/home-mate-creation.js +1 -1
- package/lib/public/modules/home-mate-instructions.js +90 -0
- package/lib/public/modules/home-mate-model-picker.js +80 -271
- package/lib/public/modules/home-mate-profile-editor.js +72 -0
- package/lib/public/modules/home-mate-settings.js +118 -125
- package/lib/public/modules/home-shell.js +3 -0
- package/lib/public/modules/home-surface-boot.js +1 -9
- package/lib/public/modules/icon-strip-tooltip.js +95 -0
- package/lib/public/modules/knowledge-db-edit-state.js +35 -0
- package/lib/public/modules/knowledge-db-workbench.js +234 -0
- package/lib/public/modules/knowledge-history-state.js +55 -0
- package/lib/public/modules/knowledge-markdown-editor.js +57 -0
- package/lib/public/modules/knowledge-preview-links.js +70 -0
- package/lib/public/modules/knowledge-workbench-shell.js +21 -0
- package/lib/public/modules/linear-settings.js +3 -2
- package/lib/public/modules/markdown.js +5 -6
- package/lib/public/modules/mate-knowledge-workbench-state.js +174 -0
- package/lib/public/modules/mate-knowledge-workbench.js +500 -0
- package/lib/public/modules/mate-knowledge.js +11 -3
- package/lib/public/modules/mate-management.js +54 -10
- package/lib/public/modules/mate-sidebar.js +11 -1
- package/lib/public/modules/mate-workspace-color.js +33 -0
- package/lib/public/modules/mention.js +5 -13
- package/lib/public/modules/notification-settings.js +81 -0
- package/lib/public/modules/notifications.js +44 -28
- package/lib/public/modules/personal-settings-dialog.js +51 -0
- package/lib/public/modules/profile.js +66 -24
- package/lib/public/modules/project-chat-identity.js +79 -0
- package/lib/public/modules/project-debate-planning-workspace.js +250 -0
- package/lib/public/modules/project-debate-workspace.js +185 -0
- package/lib/public/modules/project-header-identity.js +127 -0
- package/lib/public/modules/project-logs-render.js +9 -4
- package/lib/public/modules/project-mate-creation-workspace.js +414 -0
- package/lib/public/modules/project-mate-navigation.js +238 -0
- package/lib/public/modules/project-session-navigation.js +29 -0
- package/lib/public/modules/project-settings-environment.js +106 -0
- package/lib/public/modules/project-settings.js +72 -628
- package/lib/public/modules/project-switcher.js +6 -8
- package/lib/public/modules/projects-hub-view.js +5 -6
- package/lib/public/modules/projects-hub.js +2 -6
- package/lib/public/modules/qrcode.js +27 -8
- package/lib/public/modules/search-clay-chat.js +8 -11
- package/lib/public/modules/server-settings-controls.js +316 -0
- package/lib/public/modules/server-settings-environment.js +194 -0
- package/lib/public/modules/server-settings-navigation.js +39 -0
- package/lib/public/modules/server-settings-state.js +54 -0
- package/lib/public/modules/server-settings.js +116 -788
- package/lib/public/modules/server-storage-settings.js +84 -0
- package/lib/public/modules/session-activity-tooltip.js +12 -0
- package/lib/public/modules/session-create-form.js +86 -14
- package/lib/public/modules/session-create.js +50 -7
- package/lib/public/modules/session-github.js +2 -1
- package/lib/public/modules/session-list-visibility.js +41 -0
- package/lib/public/modules/session-presence-ui.js +3 -0
- package/lib/public/modules/session-title-marquee.js +51 -0
- package/lib/public/modules/settings-env-values.js +34 -0
- package/lib/public/modules/settings-select.js +121 -0
- package/lib/public/modules/shared-browser.js +22 -12
- package/lib/public/modules/sidebar-mates.js +3 -50
- package/lib/public/modules/sidebar-mobile.js +63 -60
- package/lib/public/modules/sidebar-projects.js +84 -97
- package/lib/public/modules/sidebar-session-folders-ui.js +2 -2
- package/lib/public/modules/sidebar-session-hierarchy.js +149 -70
- package/lib/public/modules/sidebar-sessions.js +49 -50
- package/lib/public/modules/sidebar.js +11 -13
- package/lib/public/modules/stt-picker.js +14 -5
- package/lib/public/modules/terminal-prefs.js +22 -0
- package/lib/public/modules/theme.js +88 -52
- package/lib/public/modules/thinking-lifecycle.js +7 -6
- package/lib/public/modules/tool-palette-order.js +4 -3
- package/lib/public/modules/tool-palette.js +13 -3
- package/lib/public/modules/tools.js +22 -22
- package/lib/public/modules/user-settings-account.js +318 -0
- package/lib/public/modules/user-settings-appearance.js +55 -0
- package/lib/public/modules/user-settings-editors.js +24 -0
- package/lib/public/modules/user-settings-integrations.js +104 -0
- package/lib/public/modules/user-settings-layout.js +80 -0
- package/lib/public/modules/user-settings-preferences.js +48 -0
- package/lib/public/modules/user-settings-profile.js +53 -0
- package/lib/public/modules/user-settings-themes.js +38 -0
- package/lib/public/modules/user-settings-voice.js +75 -0
- package/lib/public/modules/user-settings.js +53 -480
- package/lib/public/modules/worker-proposal.js +42 -8
- package/lib/public/modules/worker-runtime-picker.js +115 -0
- package/lib/public/modules/you-activity.js +121 -0
- package/lib/public/modules/you.js +251 -0
- package/lib/public/style.css +20 -8
- package/lib/public/vendor/codemirror/LICENSE +21 -0
- package/lib/public/vendor/codemirror/codemirror.css +344 -0
- package/lib/public/vendor/codemirror/codemirror.js +9884 -0
- package/lib/public/vendor/codemirror/continuelist.js +101 -0
- package/lib/public/vendor/codemirror/markdown.js +886 -0
- package/lib/public/vendor/codemirror/show-hint.css +37 -0
- package/lib/public/vendor/codemirror/show-hint.js +523 -0
- package/lib/sdk-bridge.js +15 -3
- package/lib/sdk-message-processor.js +16 -4
- package/lib/sdk-quota-snapshot.js +37 -0
- package/lib/server-admin.js +11 -0
- package/lib/server-appearance-settings.js +71 -0
- package/lib/server-home-chat-events.js +1 -1
- package/lib/server-home-chat.js +25 -3
- package/lib/server-home-debate-planning.js +4 -1
- package/lib/server-home-debates.js +2 -0
- package/lib/server-home-mate-creation.js +4 -1
- package/lib/server-linear.js +14 -8
- package/lib/server-mate-instructions.js +44 -0
- package/lib/server-mates.js +14 -4
- package/lib/server-notification-settings.js +67 -0
- package/lib/server-palette.js +1 -1
- package/lib/server-settings.js +69 -1
- package/lib/server-storage.js +57 -0
- package/lib/server-user-knowledge.js +119 -0
- package/lib/server.js +31 -3
- package/lib/session-visibility.js +7 -2
- package/lib/sessions.js +35 -10
- package/lib/startup-projects.js +40 -0
- package/lib/storage-native-walk.js +85 -0
- package/lib/storage-usage.js +144 -0
- package/lib/user-knowledge-service.js +167 -0
- package/lib/users-permissions.js +7 -0
- package/lib/users-preferences.js +0 -74
- package/lib/users-project-mate-filter-preferences.js +39 -0
- package/lib/users.js +6 -4
- package/lib/workspace-query-access.js +4 -1
- package/lib/ws-schema.js +52 -4
- package/lib/yoke/acp-process-manager.js +2 -2
- package/lib/yoke/adapters/codex.js +12 -52
- package/lib/yoke/codex-app-server.js +2 -2
- package/lib/yoke/codex-model-catalog.js +52 -0
- package/lib/yoke/codex-rate-limits.js +26 -0
- package/package.json +12 -3
package/lib/project-knowledge.js
CHANGED
|
@@ -1,184 +1,363 @@
|
|
|
1
|
-
var fs = require("fs");
|
|
2
1
|
var path = require("path");
|
|
2
|
+
var crypto = require("crypto");
|
|
3
3
|
var mateSync = require("./mate-knowledge-sync");
|
|
4
|
+
var knowledgeFiles = require("./knowledge-file-store");
|
|
5
|
+
var markdown = require("./knowledge-markdown");
|
|
6
|
+
var draftStore = require("./knowledge-draft-store");
|
|
7
|
+
var documentIndexModule = require("./knowledge-document-index");
|
|
8
|
+
var knowledgeDbModule = require("./knowledge-db-service");
|
|
9
|
+
var knowledgeImport = require("./knowledge-import");
|
|
4
10
|
|
|
5
|
-
/**
|
|
6
|
-
* Attach knowledge file management to a project context.
|
|
7
|
-
*
|
|
8
|
-
* ctx fields:
|
|
9
|
-
* cwd, isMate, sendTo, matesModule, projectOwnerId
|
|
10
|
-
*/
|
|
11
11
|
function attachKnowledge(ctx) {
|
|
12
12
|
var cwd = ctx.cwd;
|
|
13
13
|
var isMate = ctx.isMate;
|
|
14
14
|
var sendTo = ctx.sendTo;
|
|
15
15
|
var matesModule = ctx.matesModule;
|
|
16
16
|
var getProjectOwnerId = ctx.getProjectOwnerId;
|
|
17
|
+
var metadataKey = crypto.createHash("sha256").update(path.resolve(cwd)).digest("hex").slice(0, 24);
|
|
18
|
+
var metadataRoot = path.join(ctx.knowledgeBaseDir || path.join(cwd, ".clay"), "knowledge-documents", metadataKey);
|
|
19
|
+
var files = knowledgeFiles.createKnowledgeFileStore(cwd, { metaDir: metadataRoot });
|
|
20
|
+
var drafts = draftStore.createKnowledgeDraftStore(ctx.knowledgeBaseDir || path.join(cwd, ".clay"), path.resolve(cwd));
|
|
21
|
+
var indexer = documentIndexModule.createKnowledgeDocumentIndex({ list: listKnowledgeFiles, read: readEntry, maxDocumentBytes: knowledgeFiles.MAX_CONTENT_BYTES });
|
|
22
|
+
var dbScope = isMate ? mateSync.scopeForMateDir(cwd) : null;
|
|
23
|
+
var dbImporter = dbScope ? knowledgeImport.createKnowledgeImporter({ scopeId: dbScope.scopeId, baseDir: ctx.knowledgeBaseDir }) : null;
|
|
24
|
+
var databases = isMate ? knowledgeDbModule.createKnowledgeDbService({
|
|
25
|
+
projectDir: cwd,
|
|
26
|
+
authorizeTextReference: function (id) { return files.list().some(function (file) { return file.id === id && file.itemType === "text"; }); },
|
|
27
|
+
projectSummary: dbImporter ? function (summary) {
|
|
28
|
+
return dbImporter.importRecord({ importKey: "knowledge-database:" + summary.databaseId, sourceHash: String(summary.revision) + ":" + String(summary.archived),
|
|
29
|
+
kind: "knowledge-database-summary", name: summary.name, content: summary.content,
|
|
30
|
+
source: { namespace: "knowledge-database", databaseId: summary.databaseId, relPath: "knowledge/.clay-db/databases.db" }, actor: summary.actor });
|
|
31
|
+
} : null,
|
|
32
|
+
}) : null;
|
|
33
|
+
var databaseReady = databases && databases.hasStore() ? databases.initialize() : null;
|
|
34
|
+
if (databaseReady) databaseReady.catch(function (error) { console.error("[knowledge-db] Failed to initialize:", error.message); });
|
|
35
|
+
|
|
36
|
+
function canWrite(ws) {
|
|
37
|
+
if (typeof ctx.canManageKnowledge === "function") return ctx.canManageKnowledge(ws) === true;
|
|
38
|
+
var ownerId = getProjectOwnerId();
|
|
39
|
+
return !ownerId || !!(ws && ws._clayUser && ws._clayUser.id === ownerId);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function actor(ws) {
|
|
43
|
+
var user = (ws && ws._clayUser) || null;
|
|
44
|
+
return { type: user ? "user" : "system", userId: user ? user.id : null, displayName: user ? (user.displayName || user.username) : null };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function mirror(ws, name) {
|
|
48
|
+
if (!isMate) return { ok: true, names: [] };
|
|
49
|
+
var summary = mateSync.syncMateSource({ mateDir: cwd, fileName: name, baseDir: ctx.knowledgeBaseDir, actor: actor(ws) });
|
|
50
|
+
return { ok: !!summary && summary.failed === 0, names: [name], error: summary && summary.errors[0] ? summary.errors[0].message : "Knowledge index synchronization failed." };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function mirrorMany(ws, names) {
|
|
54
|
+
var failures = [];
|
|
55
|
+
for (var i = 0; i < names.length; i++) {
|
|
56
|
+
var mirrored = mirror(ws, names[i]);
|
|
57
|
+
if (!mirrored.ok) failures.push(mirrored.error);
|
|
58
|
+
}
|
|
59
|
+
return { ok: failures.length === 0, names: names.slice(), error: failures[0] || null };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function addSyncState(payload, sync) {
|
|
63
|
+
if (sync.ok) return payload;
|
|
64
|
+
return Object.assign(payload, { indexSyncPending: true, syncNames: sync.names, syncError: sync.error });
|
|
65
|
+
}
|
|
17
66
|
|
|
18
67
|
function listKnowledgeFiles() {
|
|
19
|
-
var
|
|
20
|
-
var
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
68
|
+
var listed = files.list();
|
|
69
|
+
for (var i = 0; i < listed.length; i++) listed[i].common = false;
|
|
70
|
+
if (!isMate) return listed;
|
|
71
|
+
var mateCtx = matesModule.buildMateCtx(getProjectOwnerId());
|
|
72
|
+
var thisMateId = path.basename(cwd);
|
|
73
|
+
for (var p = 0; p < listed.length; p++) listed[p].promoted = matesModule.isPromoted(mateCtx, thisMateId, listed[p].name);
|
|
74
|
+
var common = matesModule.getCommonKnowledgeForMate(mateCtx, thisMateId);
|
|
75
|
+
for (var c = 0; c < common.length; c++) {
|
|
76
|
+
if (common[c].ownMateId !== thisMateId) listed.push(Object.assign({}, common[c], { id: "shared:" + common[c].ownMateId + ":" + common[c].name,
|
|
77
|
+
itemType: /\.jsonl$/i.test(common[c].name) ? "db" : "text", writable: false, revision: null }));
|
|
78
|
+
}
|
|
79
|
+
return listed;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function listKnowledgeItems(ws) {
|
|
83
|
+
var textItems = listKnowledgeFiles();
|
|
84
|
+
if (!databases || !databases.hasStore()) return textItems;
|
|
85
|
+
function combine(result) { return textItems.concat(result.databases.map(function (item) { return Object.assign({}, item, { writable: canWrite(ws), common: false }); })); }
|
|
86
|
+
if (databases.isReady()) return combine(databases.listCached({}));
|
|
87
|
+
return databaseReady.then(function () { return combine(databases.listCached({})); });
|
|
88
|
+
}
|
|
34
89
|
|
|
35
|
-
|
|
90
|
+
function response(ws, msg, payload) {
|
|
91
|
+
sendTo(ws, Object.assign({ requestId: msg.requestId || null }, payload));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function failure(ws, msg, error, extra) {
|
|
95
|
+
response(ws, msg, Object.assign({ type: "knowledge_error", operation: msg.type, name: msg.name || msg.from || null,
|
|
96
|
+
code: error.code || "FAILED", error: error.message || "Knowledge operation failed.", currentRevision: error.currentRevision || null }, extra || {}));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function requireWrite(ws, msg) {
|
|
100
|
+
if (canWrite(ws)) return true;
|
|
101
|
+
failure(ws, msg, Object.assign(new Error("Only the Mate owner can change Knowledge documents."), { code: "FORBIDDEN" }));
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function readEntry(file) {
|
|
106
|
+
if (file.common && file.ownMateId && isMate) {
|
|
36
107
|
var mateCtx = matesModule.buildMateCtx(getProjectOwnerId());
|
|
37
|
-
|
|
38
|
-
for (var pi = 0; pi < files.length; pi++) {
|
|
39
|
-
files[pi].promoted = matesModule.isPromoted(mateCtx, thisMateId, files[pi].name);
|
|
40
|
-
}
|
|
41
|
-
var commonFiles = matesModule.getCommonKnowledgeForMate(mateCtx, thisMateId);
|
|
42
|
-
for (var ci = 0; ci < commonFiles.length; ci++) {
|
|
43
|
-
if (commonFiles[ci].ownMateId !== thisMateId) {
|
|
44
|
-
files.push(commonFiles[ci]);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
108
|
+
return matesModule.readCommonKnowledgeFile(mateCtx, file.ownMateId, file.name);
|
|
47
109
|
}
|
|
48
|
-
return files;
|
|
110
|
+
return files.read(file.name).content;
|
|
49
111
|
}
|
|
50
112
|
|
|
51
|
-
function
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
113
|
+
function documentIndex() {
|
|
114
|
+
return indexer.reconcile();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function findDocument(index, name, id) {
|
|
118
|
+
var matches;
|
|
119
|
+
if (id) { matches = index.filter(function (item) { return item.id === id; }); return matches.length === 1 ? matches[0] : null; }
|
|
120
|
+
matches = index.filter(function (item) { return item.name === name; });
|
|
121
|
+
return matches.length === 1 ? matches[0] : null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function linksFor(index, target) {
|
|
125
|
+
var outgoing = []; var backlinks = [];
|
|
126
|
+
for (var i = 0; i < target.parsed.links.length; i++) {
|
|
127
|
+
var link = target.parsed.links[i]; var resolved = markdown.resolveLink(target.name, link, index, target.id);
|
|
128
|
+
var headingValid = !link.heading || !!(resolved && resolved.parsed.headings.some(function (heading) { return heading.slug === markdown.slug(link.heading); }));
|
|
129
|
+
outgoing.push({ kind: link.kind, raw: link.raw, label: link.alias || link.target || link.heading, target: link.target, heading: link.heading,
|
|
130
|
+
headingValid: headingValid, documentId: resolved && resolved.id || null, documentKey: resolved && resolved.key || null,
|
|
131
|
+
name: resolved && resolved.name || null, external: link.external === true, self: !link.target && !!link.heading, unresolved: !resolved && !link.external });
|
|
132
|
+
}
|
|
133
|
+
for (var d = 0; d < index.length; d++) {
|
|
134
|
+
if (index[d] === target) continue;
|
|
135
|
+
for (var l = 0; l < index[d].parsed.links.length; l++) {
|
|
136
|
+
var resolvedTarget = markdown.resolveLink(index[d].name, index[d].parsed.links[l], index, index[d].id);
|
|
137
|
+
if (resolvedTarget && resolvedTarget.id === target.id) {
|
|
138
|
+
backlinks.push({ documentId: index[d].id, documentKey: index[d].key, name: index[d].name, heading: index[d].parsed.links[l].heading,
|
|
139
|
+
snippet: markdown.snippet(index[d].content, index[d].parsed.links[l].start) }); break;
|
|
60
140
|
}
|
|
61
141
|
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
142
|
+
}
|
|
143
|
+
return { outgoing: outgoing, backlinks: backlinks };
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function relativeLink(from, to, withExtension) {
|
|
147
|
+
var value = path.posix.relative(path.posix.dirname(from), to) || path.posix.basename(to);
|
|
148
|
+
if (withExtension === false) value = value.replace(/\.md$/i, "");
|
|
149
|
+
return value;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function rewriteMoveLinks(index, target, nextName) {
|
|
153
|
+
var changes = [];
|
|
154
|
+
for (var i = 0; i < index.length; i++) {
|
|
155
|
+
var source = index[i];
|
|
156
|
+
if (source.common || source.itemType === "db" || !source.writable) continue;
|
|
157
|
+
var replacements = [];
|
|
158
|
+
for (var l = 0; l < source.parsed.links.length; l++) {
|
|
159
|
+
var link = source.parsed.links[l]; var resolved = markdown.resolveLink(source.name, link, index, source.id);
|
|
160
|
+
if (!resolved || source.id !== target.id && resolved.id !== target.id) continue;
|
|
161
|
+
var sourceAfter = source.id === target.id ? nextName : source.name;
|
|
162
|
+
var targetAfter = resolved.id === target.id ? nextName : resolved.name;
|
|
163
|
+
var nextTarget = relativeLink(sourceAfter, targetAfter, link.kind === "markdown" || link.kind === "image");
|
|
164
|
+
var suffix = link.heading ? "#" + link.heading : ""; var replacement;
|
|
165
|
+
if (link.kind === "wiki" || link.kind === "embed") replacement = (link.kind === "embed" ? "!" : "") + "[[" + nextTarget + suffix + (link.alias ? "|" + link.alias : "") + "]]";
|
|
166
|
+
else replacement = (link.kind === "image" ? "!" : "") + "[" + link.alias + "](" + nextTarget + suffix + ")";
|
|
167
|
+
replacements.push({ start: link.start, end: link.end, value: replacement });
|
|
74
168
|
}
|
|
169
|
+
if (!replacements.length) continue;
|
|
170
|
+
var content = source.content;
|
|
171
|
+
for (var r = replacements.length - 1; r >= 0; r--) content = content.slice(0, replacements[r].start) + replacements[r].value + content.slice(replacements[r].end);
|
|
172
|
+
changes.push({ id: source.id, name: source.name, revision: source.revision, content: content, count: replacements.length });
|
|
75
173
|
}
|
|
76
|
-
return
|
|
174
|
+
return changes;
|
|
77
175
|
}
|
|
78
176
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
displayName: user ? (user.displayName || user.username) : null,
|
|
92
|
-
},
|
|
93
|
-
});
|
|
177
|
+
function searchFiles(query, offset, limit) {
|
|
178
|
+
var start = Math.max(0, Number(offset) || 0); var count = Math.max(1, Math.min(100, Number(limit) || 50)); var direct = indexer.search(query, start, count); var needle = String(query || "").trim().toLowerCase();
|
|
179
|
+
if (!databases || !databases.hasStore()) return direct;
|
|
180
|
+
function combineSearch(result) {
|
|
181
|
+
var databaseMatches = result.databases.filter(function (item) { return needle && (item.name.toLowerCase().indexOf(needle) !== -1 || item.schema.some(function (field) { return field.name.toLowerCase().indexOf(needle) !== -1 || field.type.indexOf(needle) !== -1; })); }).map(function (item) { return Object.assign({}, item, { itemType: "db", writable: true, common: false, snippet: "Database · " + item.recordCount + " records" }); });
|
|
182
|
+
if (!databaseMatches.length) return direct;
|
|
183
|
+
var files = direct.files.slice(); var textTotal = direct.total; var databaseOffset = Math.max(0, start - textTotal); var room = count - files.length;
|
|
184
|
+
if (room > 0) files = files.concat(databaseMatches.slice(databaseOffset, databaseOffset + room));
|
|
185
|
+
return { files: files, total: textTotal + databaseMatches.length, offset: start, limit: count, complete: direct.complete, errors: direct.errors };
|
|
186
|
+
}
|
|
187
|
+
if (databases.isReady()) return combineSearch(databases.listCached({}));
|
|
188
|
+
return databaseReady.then(function () { return combineSearch(databases.listCached({})); });
|
|
94
189
|
}
|
|
95
190
|
|
|
96
191
|
function handleKnowledgeMessage(ws, msg) {
|
|
97
192
|
if (msg.type === "knowledge_list") {
|
|
98
|
-
|
|
193
|
+
try { var listed = listKnowledgeItems(ws); if (listed && typeof listed.then === "function") listed.then(function (items) { response(ws, msg, { type: "knowledge_list", files: items, drafts: drafts.list(ws && ws._clayUser && ws._clayUser.id || "system") }); }).catch(function (error) { failure(ws, msg, error); }); else response(ws, msg, { type: "knowledge_list", files: listed, drafts: drafts.list(ws && ws._clayUser && ws._clayUser.id || "system") }); } catch (error) { failure(ws, msg, error); }
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
if (msg.type === "knowledge_search") {
|
|
197
|
+
try { var searched = searchFiles(msg.query, msg.offset, msg.limit); if (searched && typeof searched.then === "function") searched.then(function (result) { response(ws, msg, Object.assign({ type: "knowledge_search_results", query: String(msg.query || "") }, result)); }).catch(function (error) { failure(ws, msg, error); }); else response(ws, msg, Object.assign({ type: "knowledge_search_results", query: String(msg.query || "") }, searched)); } catch (error) { failure(ws, msg, error); }
|
|
99
198
|
return true;
|
|
100
199
|
}
|
|
101
|
-
|
|
102
200
|
if (msg.type === "knowledge_read") {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
var
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
var
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
201
|
+
try {
|
|
202
|
+
if (msg.common && msg.ownMateId && isMate) {
|
|
203
|
+
if (!knowledgeFiles.validName(msg.name)) throw new Error("Invalid knowledge file name.");
|
|
204
|
+
var mateCtx = matesModule.buildMateCtx(getProjectOwnerId());
|
|
205
|
+
var sharedContent = matesModule.readCommonKnowledgeFile(mateCtx, msg.ownMateId, msg.name);
|
|
206
|
+
var sharedParsed = markdown.parse(sharedContent); var sharedIndexState = documentIndex();
|
|
207
|
+
var sharedIndexed = findDocument(sharedIndexState.documents, msg.name, msg.documentId); var sharedRelations = sharedIndexed ? linksFor(sharedIndexState.documents, sharedIndexed) : { outgoing: [], backlinks: [] };
|
|
208
|
+
response(ws, msg, { type: "knowledge_content", name: msg.name, content: sharedContent, common: true, ownMateId: msg.ownMateId, writable: false, revision: null,
|
|
209
|
+
outline: sharedParsed.headings, outgoing: sharedRelations.outgoing, backlinks: sharedRelations.backlinks,
|
|
210
|
+
properties: sharedParsed.properties, tags: sharedParsed.tags, propertyErrors: sharedParsed.propertyErrors,
|
|
211
|
+
indexComplete: sharedIndexState.complete, indexErrors: sharedIndexState.errors });
|
|
212
|
+
} else {
|
|
213
|
+
var item = files.read(msg.name);
|
|
214
|
+
var indexState = documentIndex(); var indexed = findDocument(indexState.documents, item.name, msg.documentId || item.id); var relations = indexed ? linksFor(indexState.documents, indexed) : { outgoing: [], backlinks: [] };
|
|
215
|
+
var parsed = indexed ? indexed.parsed : markdown.parse(item.content);
|
|
216
|
+
var userId = ws && ws._clayUser && ws._clayUser.id || "system"; var recovered = drafts.read(userId, item.id);
|
|
217
|
+
response(ws, msg, { type: "knowledge_content", id: item.id, name: item.name, content: item.content, revision: item.revision, itemType: item.itemType,
|
|
218
|
+
writable: item.itemType === "text" && canWrite(ws), outline: parsed.headings, outgoing: relations.outgoing, backlinks: relations.backlinks,
|
|
219
|
+
properties: parsed.properties, tags: parsed.tags, propertyErrors: parsed.propertyErrors, recoveredDraft: recovered,
|
|
220
|
+
indexComplete: indexState.complete, indexErrors: indexState.errors });
|
|
120
221
|
}
|
|
121
|
-
}
|
|
222
|
+
} catch (error) { failure(ws, msg, error); }
|
|
122
223
|
return true;
|
|
123
224
|
}
|
|
124
|
-
|
|
125
225
|
if (msg.type === "knowledge_save") {
|
|
126
|
-
if (!
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
226
|
+
if (!requireWrite(ws, msg)) return true;
|
|
227
|
+
try {
|
|
228
|
+
var saved = files.save(msg.name, msg.content, msg.expectedRevision || null);
|
|
229
|
+
var savedSync = mirror(ws, saved.name);
|
|
230
|
+
if (msg.documentId) drafts.remove(ws._clayUser && ws._clayUser.id || "system", msg.documentId, msg.draftVersion);
|
|
231
|
+
response(ws, msg, addSyncState({ type: "knowledge_saved", id: saved.id, name: saved.name, revision: saved.revision }, savedSync));
|
|
232
|
+
sendTo(ws, { type: "knowledge_list", files: listKnowledgeFiles() });
|
|
233
|
+
} catch (error) { failure(ws, msg, error); }
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
if (msg.type === "knowledge_rename") {
|
|
237
|
+
if (!requireWrite(ws, msg)) return true;
|
|
238
|
+
try {
|
|
239
|
+
var beforeMoveState = documentIndex(); var beforeMove = beforeMoveState.documents; var moveTarget = findDocument(beforeMove, msg.from, msg.documentId); var linkChanges = moveTarget ? rewriteMoveLinks(beforeMove, moveTarget, msg.name) : [];
|
|
240
|
+
var renamed = files.rename(msg.from, msg.name, msg.expectedRevision || null); var linkUpdateFailures = []; var updatedLinks = 0;
|
|
241
|
+
var updatedDocuments = []; var mirrorNames = [msg.from, renamed.name];
|
|
242
|
+
for (var u = 0; u < linkChanges.length; u++) {
|
|
243
|
+
var change = linkChanges[u]; var writeName = change.id === renamed.id ? renamed.name : change.name; var expected = change.id === renamed.id ? renamed.revision : change.revision;
|
|
244
|
+
try { var rewritten = files.save(writeName, change.content, expected); updatedLinks += change.count; updatedDocuments.push(rewritten); mirrorNames.push(rewritten.name); }
|
|
245
|
+
catch (linkError) { linkUpdateFailures.push({ name: writeName, error: linkError.message }); }
|
|
246
|
+
}
|
|
247
|
+
renamed = files.read(renamed.name);
|
|
248
|
+
var uniqueMirrorNames = mirrorNames.filter(function (name, at) { return mirrorNames.indexOf(name) === at; }); var renameSync = mirrorMany(ws, uniqueMirrorNames);
|
|
249
|
+
response(ws, msg, addSyncState({ type: "knowledge_renamed", id: renamed.id, from: msg.from, name: renamed.name, revision: renamed.revision,
|
|
250
|
+
content: renamed.content, updatedLinks: updatedLinks, linkUpdateFailures: linkUpdateFailures,
|
|
251
|
+
updatedDocuments: updatedDocuments.map(function (item) { return { id: item.id, name: item.name, content: item.content, revision: item.revision }; }) }, renameSync));
|
|
252
|
+
sendTo(ws, { type: "knowledge_list", files: listKnowledgeFiles() });
|
|
253
|
+
} catch (error) { failure(ws, msg, error); }
|
|
135
254
|
return true;
|
|
136
255
|
}
|
|
137
|
-
|
|
138
256
|
if (msg.type === "knowledge_delete") {
|
|
139
|
-
if (!msg
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
sendTo(ws, { type: "knowledge_deleted", name: safeName });
|
|
147
|
-
sendTo(ws, { type: "knowledge_list", files: listKnowledgeFilesBasic() });
|
|
257
|
+
if (!requireWrite(ws, msg)) return true;
|
|
258
|
+
try {
|
|
259
|
+
var removed = files.remove(msg.name, msg.expectedRevision || null);
|
|
260
|
+
var deleteSync = mirror(ws, removed.name);
|
|
261
|
+
response(ws, msg, addSyncState({ type: "knowledge_deleted", name: removed.name }, deleteSync));
|
|
262
|
+
sendTo(ws, { type: "knowledge_list", files: listKnowledgeFiles() });
|
|
263
|
+
} catch (error) { failure(ws, msg, error); }
|
|
148
264
|
return true;
|
|
149
265
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
sendTo(ws, { type: "knowledge_list", files: listKnowledgeFiles() });
|
|
266
|
+
if (msg.type === "knowledge_sync") {
|
|
267
|
+
if (!requireWrite(ws, msg)) return true;
|
|
268
|
+
try {
|
|
269
|
+
var syncNames = Array.isArray(msg.names) ? msg.names.slice(0, 4) : [msg.name];
|
|
270
|
+
if (!syncNames.length) throw new Error("A Knowledge source is required.");
|
|
271
|
+
for (var n = 0; n < syncNames.length; n++) if (!knowledgeFiles.validName(syncNames[n])) throw new Error("Invalid knowledge file name.");
|
|
272
|
+
var retrySync = mirrorMany(ws, syncNames);
|
|
273
|
+
if (!retrySync.ok) throw Object.assign(new Error(retrySync.error), { code: "SYNC_FAILED" });
|
|
274
|
+
response(ws, msg, { type: "knowledge_synced", names: syncNames });
|
|
275
|
+
} catch (error) { failure(ws, msg, error, { diskCommitted: true, names: msg.names || [msg.name] }); }
|
|
161
276
|
return true;
|
|
162
277
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
278
|
+
if (msg.type === "knowledge_draft_save") {
|
|
279
|
+
if (!requireWrite(ws, msg)) return true;
|
|
280
|
+
try {
|
|
281
|
+
var savedDraft = drafts.save(ws._clayUser && ws._clayUser.id || "system", msg.documentId, { name: msg.name, content: msg.content, baseRevision: msg.baseRevision,
|
|
282
|
+
cursor: msg.cursor, clientVersion: msg.clientVersion, newDocument: msg.newDocument });
|
|
283
|
+
response(ws, msg, { type: "knowledge_draft_saved", documentId: msg.documentId, savedAt: savedDraft.savedAt, clientVersion: savedDraft.clientVersion });
|
|
284
|
+
} catch (error) { failure(ws, msg, error); }
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
if (msg.type === "knowledge_draft_delete") {
|
|
288
|
+
if (!requireWrite(ws, msg)) return true;
|
|
289
|
+
try { var removedDraft = drafts.remove(ws._clayUser && ws._clayUser.id || "system", msg.documentId, msg.throughVersion); response(ws, msg, { type: "knowledge_draft_deleted", documentId: msg.documentId, removed: removedDraft }); }
|
|
290
|
+
catch (error) { failure(ws, msg, error); }
|
|
291
|
+
return true;
|
|
292
|
+
}
|
|
293
|
+
if (msg.type === "knowledge_discard_draft") {
|
|
294
|
+
if (!requireWrite(ws, msg)) return true;
|
|
295
|
+
try {
|
|
296
|
+
var disk = files.read(msg.name); if (msg.expectedRevision && disk.revision !== msg.expectedRevision) throw Object.assign(new Error("The disk version changed again."), { code: "STALE", currentRevision: disk.revision });
|
|
297
|
+
var removed = drafts.remove(ws._clayUser && ws._clayUser.id || "system", msg.documentId, msg.throughVersion);
|
|
298
|
+
response(ws, msg, { type: "knowledge_draft_discarded", documentId: msg.documentId, removed: removed, id: disk.id, name: disk.name, content: disk.content, revision: disk.revision });
|
|
299
|
+
} catch (error) { failure(ws, msg, error); }
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
if (msg.type === "knowledge_history") {
|
|
303
|
+
try { response(ws, msg, { type: "knowledge_history", documentId: msg.documentId, versions: files.history(msg.documentId) }); }
|
|
304
|
+
catch (error) { failure(ws, msg, error); }
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
if (msg.type === "knowledge_history_read") {
|
|
308
|
+
try { response(ws, msg, Object.assign({ type: "knowledge_history_version", documentId: msg.documentId }, files.readHistory(msg.documentId, msg.version))); }
|
|
309
|
+
catch (error) { failure(ws, msg, error); }
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
312
|
+
if (msg.type === "knowledge_deleted_list") {
|
|
313
|
+
if (!databases || !databases.hasStore()) { try { response(ws, msg, { type: "knowledge_deleted_list", files: files.deleted() }); } catch (error) { failure(ws, msg, error); } return true; }
|
|
314
|
+
databases.list({ archived: true }).then(function (result) { var archivedDatabases = result.databases.map(function (item) { return Object.assign({}, item, { itemType: "db", writable: canWrite(ws) }); }); response(ws, msg, { type: "knowledge_deleted_list", files: files.deleted().concat(archivedDatabases) }); }).catch(function (error) { failure(ws, msg, error); });
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
317
|
+
if (msg.type === "knowledge_restore") {
|
|
318
|
+
if (!requireWrite(ws, msg)) return true;
|
|
319
|
+
try {
|
|
320
|
+
var restored = files.restore(msg.documentId, msg.version, msg.name, msg.expectedRevision || null); var restoreSync = mirror(ws, restored.name);
|
|
321
|
+
response(ws, msg, addSyncState({ type: "knowledge_restored", id: restored.id, name: restored.name, revision: restored.revision }, restoreSync));
|
|
322
|
+
sendTo(ws, { type: "knowledge_list", files: listKnowledgeFiles() });
|
|
323
|
+
} catch (error) { failure(ws, msg, error); }
|
|
324
|
+
return true;
|
|
325
|
+
}
|
|
326
|
+
if (msg.type === "knowledge_promote" || msg.type === "knowledge_depromote") {
|
|
327
|
+
if (!isMate || !requireWrite(ws, msg)) return true;
|
|
328
|
+
try {
|
|
329
|
+
if (!knowledgeFiles.validName(msg.name)) throw new Error("Invalid knowledge file name.");
|
|
330
|
+
var promoteCtx = matesModule.buildMateCtx(getProjectOwnerId());
|
|
331
|
+
var mateId = path.basename(cwd);
|
|
332
|
+
if (msg.type === "knowledge_promote") {
|
|
333
|
+
var mate = matesModule.getMate(promoteCtx, mateId);
|
|
334
|
+
matesModule.promoteKnowledge(promoteCtx, mateId, mate && mate.name, msg.name);
|
|
335
|
+
} else matesModule.depromoteKnowledge(promoteCtx, mateId, msg.name);
|
|
336
|
+
response(ws, msg, { type: msg.type === "knowledge_promote" ? "knowledge_promoted" : "knowledge_depromoted", name: msg.name });
|
|
337
|
+
sendTo(ws, { type: "knowledge_list", files: listKnowledgeFiles() });
|
|
338
|
+
} catch (error) { failure(ws, msg, error); }
|
|
339
|
+
return true;
|
|
340
|
+
}
|
|
341
|
+
var dbOperations = {
|
|
342
|
+
knowledge_db_create: { method: "create", reply: "knowledge_db_created" }, knowledge_db_read: { method: "read", reply: "knowledge_db_content", read: true },
|
|
343
|
+
knowledge_db_rename: { method: "rename", reply: "knowledge_db_renamed" }, knowledge_db_archive: { method: "archive", reply: "knowledge_db_archived" },
|
|
344
|
+
knowledge_db_recover: { method: "recover", reply: "knowledge_db_recovered" }, knowledge_db_schema_save: { method: "updateSchema", reply: "knowledge_db_schema_saved" },
|
|
345
|
+
knowledge_db_view_save: { method: "saveView", reply: "knowledge_db_view_saved" }, knowledge_db_record_create: { method: "createRecord", reply: "knowledge_db_record_created" },
|
|
346
|
+
knowledge_db_record_read: { method: "readRecord", reply: "knowledge_db_record_content", read: true }, knowledge_db_record_update: { method: "updateRecord", reply: "knowledge_db_record_updated" },
|
|
347
|
+
knowledge_db_record_archive: { method: "archiveRecord", reply: "knowledge_db_record_archived" }, knowledge_db_record_recover: { method: "recoverRecord", reply: "knowledge_db_record_recovered" },
|
|
348
|
+
knowledge_db_query: { method: "query", reply: "knowledge_db_query_results", read: true }, knowledge_db_sync: { method: "retryProjection", reply: "knowledge_db_synced" },
|
|
349
|
+
};
|
|
350
|
+
if (dbOperations[msg.type]) {
|
|
351
|
+
if (!isMate) { failure(ws, msg, new Error("Knowledge databases are available only inside a Mate project.")); return true; }
|
|
352
|
+
var operation = dbOperations[msg.type]; if (!operation.read && !requireWrite(ws, msg)) return true;
|
|
353
|
+
var args = Object.assign({}, msg, { actor: actor(ws) }); delete args.type; delete args.requestId;
|
|
354
|
+
Promise.resolve(databases[operation.method](args)).then(function (result) { response(ws, msg, Object.assign({ type: operation.reply }, result)); }).catch(function (error) { failure(ws, msg, error, { databaseId: msg.databaseId || null, recordId: msg.recordId || null }); });
|
|
172
355
|
return true;
|
|
173
356
|
}
|
|
174
|
-
|
|
175
357
|
return false;
|
|
176
358
|
}
|
|
177
359
|
|
|
178
|
-
return {
|
|
179
|
-
handleKnowledgeMessage: handleKnowledgeMessage,
|
|
180
|
-
listKnowledgeFiles: listKnowledgeFiles,
|
|
181
|
-
};
|
|
360
|
+
return { handleKnowledgeMessage: handleKnowledgeMessage, listKnowledgeFiles: listKnowledgeFiles, databases: databases };
|
|
182
361
|
}
|
|
183
362
|
|
|
184
363
|
module.exports = { attachKnowledge: attachKnowledge };
|
|
@@ -98,6 +98,7 @@ function attachMateCreationProposal(ctx) {
|
|
|
98
98
|
return ctx.createReadyMate(ws, session.ownerId || null, Object.assign({}, entry.definition, { vendor: vendor, model: selected.value }));
|
|
99
99
|
}).then(function (mate) {
|
|
100
100
|
session.homeMateCreationPhase = "created";
|
|
101
|
+
if (typeof ctx.persistSession === "function") ctx.persistSession(session);
|
|
101
102
|
record(session, { type: "mate_creation_proposal_resolved", proposalId: msg.proposalId, action: "create", mateId: mate.id, mateName: (mate.profile && mate.profile.displayName) || mate.name || "Mate" });
|
|
102
103
|
entry.resolve({ action: "create", mateId: mate.id });
|
|
103
104
|
}).catch(function (error) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
var resolveMateIdentityFile = require('./mate-identity-file').resolveMateIdentityFile;
|
|
1
2
|
var fs = require("fs");
|
|
2
3
|
var path = require("path");
|
|
3
4
|
var crypto = require("crypto");
|
|
@@ -729,12 +730,12 @@ function attachMateInteraction(ctx) {
|
|
|
729
730
|
"Read it, then answer the user's question directly. Be concise and give your honest take.\n" +
|
|
730
731
|
"You are not driving the session, so do not run tools or take actions unless the user explicitly asks; commenting and advising is the default.";
|
|
731
732
|
} else {
|
|
732
|
-
// Load Mate
|
|
733
|
+
// Load Mate AGENTS.md
|
|
733
734
|
var mateDir = matesModule.getMateDir(mateCtx, msg.mateId);
|
|
734
735
|
try {
|
|
735
|
-
claudeMd = fs.readFileSync(
|
|
736
|
+
claudeMd = fs.readFileSync(resolveMateIdentityFile(mateDir), "utf8");
|
|
736
737
|
} catch (e) {
|
|
737
|
-
//
|
|
738
|
+
// AGENTS.md may not exist for new mates
|
|
738
739
|
}
|
|
739
740
|
|
|
740
741
|
// Load session digests (unified: uses memory-summary.md if available)
|
|
@@ -758,8 +759,8 @@ function attachMateInteraction(ctx) {
|
|
|
758
759
|
onDone: mentionCallbacks.onDone,
|
|
759
760
|
onError: mentionCallbacks.onError,
|
|
760
761
|
canUseTool: function (toolName, input, toolOpts) {
|
|
761
|
-
//
|
|
762
|
-
if (sm.currentPermissionMode === "bypassPermissions" && toolName !== "AskUserQuestion") {
|
|
762
|
+
// Read the caller's live mode so reused mentions follow session changes.
|
|
763
|
+
if ((session.permissionMode || sm.currentPermissionMode) === "bypassPermissions" && toolName !== "AskUserQuestion") {
|
|
763
764
|
return Promise.resolve({ behavior: "allow", updatedInput: input });
|
|
764
765
|
}
|
|
765
766
|
// Use the shared whitelist from sdk-bridge (read-only tools + safe bash commands)
|
|
@@ -826,7 +827,7 @@ function attachMateInteraction(ctx) {
|
|
|
826
827
|
function loadMateClaudeMd(mateCtx, mateId) {
|
|
827
828
|
var mateDir = matesModule.getMateDir(mateCtx, mateId);
|
|
828
829
|
try {
|
|
829
|
-
return fs.readFileSync(
|
|
830
|
+
return fs.readFileSync(resolveMateIdentityFile(mateDir), "utf8");
|
|
830
831
|
} catch (e) {
|
|
831
832
|
return "";
|
|
832
833
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Server administration messages. Every mutation returns an acknowledgement.
|
|
2
|
+
var SETTINGS = {
|
|
3
|
+
set_pin: { callback: 'onSetPin', field: 'pin', valid: function (value) { return value === null || typeof value === 'string' && /^\d{6}$/.test(value); }, timing: 'Applies to new sign-ins.' },
|
|
4
|
+
set_keep_awake: { callback: 'onSetKeepAwake', field: 'value', timing: 'Applies while the daemon is running.' },
|
|
5
|
+
set_inherit_groups: { callback: 'onSetInheritGroups', field: 'value', timing: 'Applies to newly spawned agent and terminal processes.' },
|
|
6
|
+
set_image_retention: { callback: 'onSetImageRetention', field: 'days', valid: function (value) { return Number.isInteger(value) && value >= 0 && value <= 36500; }, timing: 'The next cleanup applies this period to existing images.' }
|
|
7
|
+
};
|
|
8
|
+
function handleServerSettings(ctx, ws, msg) {
|
|
9
|
+
var entry = SETTINGS[msg.type];
|
|
10
|
+
if (!entry) return false;
|
|
11
|
+
function reply(data) { ctx.sendTo(ws, Object.assign({ type: msg.type + '_result' }, data)); }
|
|
12
|
+
if (ctx.usersModule.isMultiUser()) {
|
|
13
|
+
var id = ws._clayUser && ws._clayUser.id;
|
|
14
|
+
var user = id && ctx.usersModule.findUserById(id);
|
|
15
|
+
if (!user || user.role !== 'admin') { reply({ ok: false, error: 'Administrator access required.' }); return true; }
|
|
16
|
+
}
|
|
17
|
+
var value = msg[entry.field];
|
|
18
|
+
if (entry.valid ? !entry.valid(value) : typeof value !== 'boolean') { reply({ ok: false, error: 'Invalid setting value.' }); return true; }
|
|
19
|
+
var opts = ctx.opts;
|
|
20
|
+
try {
|
|
21
|
+
var config = opts.onGetDaemonConfig ? opts.onGetDaemonConfig() : {};
|
|
22
|
+
if (msg.type === 'set_keep_awake' && config.platform !== 'darwin') throw new Error('Keep awake requires macOS.');
|
|
23
|
+
if (msg.type === 'set_inherit_groups') throw new Error('Group inheritance is automatic in OS-user mode and is no longer configurable.');
|
|
24
|
+
if (typeof opts[entry.callback] !== 'function') throw new Error('This runtime does not support saving this setting.');
|
|
25
|
+
var result = opts[entry.callback](value);
|
|
26
|
+
reply(Object.assign({}, result, { timing: entry.timing }));
|
|
27
|
+
if (result.ok && msg.type === 'set_keep_awake') ctx.send({ type: 'keep_awake_changed', keepAwake: result.keepAwake });
|
|
28
|
+
} catch (error) { reply({ ok: false, error: error.message || 'Could not save this setting.' }); }
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
module.exports = { handleServerSettings: handleServerSettings };
|