clay-server 5.2.0-beta.4 → 5.2.0-beta.5
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/account-auth-socket.js +1 -0
- package/lib/builtin-mates.js +17 -14
- package/lib/canonical-clay-record-authority.js +15 -0
- package/lib/canonical-clay-scheduling-authority.js +19 -0
- package/lib/claude-hook-installer.js +28 -0
- package/lib/clay-mate-chat-receipts.js +26 -0
- package/lib/clay-mate-chat.js +87 -0
- package/lib/clay-mate-knowledge-input.js +26 -0
- package/lib/clay-mate-knowledge.js +95 -0
- package/lib/clay-mate-lifecycle.js +95 -0
- package/lib/clay-product-control-input.js +33 -0
- package/lib/clay-product-control-tools.js +51 -0
- package/lib/clay-product-control.js +237 -0
- package/lib/clay-project-lifecycle.js +154 -0
- package/lib/clay-project-record-input.js +44 -0
- package/lib/clay-project-records.js +83 -0
- package/lib/clay-scheduling-input.js +21 -0
- package/lib/clay-scheduling-receipts.js +26 -0
- package/lib/clay-scheduling.js +119 -0
- package/lib/clay-screen-controls.js +96 -0
- package/lib/clay-workspace-controls.js +83 -0
- package/lib/clay-workspace-input.js +17 -0
- package/lib/clay-workspace-receipts.js +26 -0
- package/lib/daemon-project-access.js +11 -0
- package/lib/daemon-project-lifecycle-callbacks.js +15 -0
- package/lib/daemon-project-lifecycle.js +262 -0
- package/lib/daemon-projects.js +1 -1
- package/lib/daemon.js +73 -221
- package/lib/issues-service.js +29 -15
- package/lib/knowledge-db-import.js +5 -4
- package/lib/knowledge-db-service.js +9 -6
- package/lib/knowledge-document-index.js +2 -1
- package/lib/knowledge-product-operations.js +46 -0
- package/lib/mate-creation-mcp-server.js +2 -0
- package/lib/mate-knowledge-canonical-access.js +10 -0
- package/lib/mate-knowledge-service.js +7 -4
- package/lib/mate-lifecycle-service.js +94 -0
- package/lib/mate-message-delivery.js +43 -0
- package/lib/mate-ready-creation.js +9 -1
- package/lib/mate-schedule-input.js +29 -0
- package/lib/mate-schedule-lifecycle.js +151 -0
- package/lib/mate-scheduling.js +103 -0
- package/lib/mates.js +4 -3
- package/lib/notes-checklist.js +50 -0
- package/lib/notes.js +49 -3
- package/lib/os-users.js +20 -5
- package/lib/project-admin-overview.js +51 -0
- package/lib/project-ask-user.js +4 -2
- package/lib/project-delegated-follow-up.js +2 -1
- package/lib/project-directory-claim.js +65 -0
- package/lib/project-file-operations.js +61 -0
- package/lib/project-filesystem.js +13 -87
- package/lib/project-full-access.js +23 -2
- package/lib/project-knowledge.js +32 -18
- package/lib/project-lifecycle-operations.js +98 -0
- package/lib/project-lifecycle-process-witness.js +32 -0
- package/lib/project-lifecycle-runtime.js +50 -0
- package/lib/project-linux-access.js +22 -0
- package/lib/project-logs-canonical-clay.js +27 -0
- package/lib/project-logs-clay-query.js +16 -0
- package/lib/project-logs-schema.js +4 -2
- package/lib/project-logs-service.js +8 -7
- package/lib/project-logs.js +1 -0
- package/lib/project-loop.js +1 -0
- package/lib/project-mate-chat-control.js +55 -0
- package/lib/project-mate-creation-proposal.js +18 -3
- package/lib/project-models.js +14 -31
- package/lib/project-notifications.js +74 -16
- package/lib/project-ownership.js +77 -0
- package/lib/project-pair-result-delivery.js +14 -3
- package/lib/project-pending-message-queue.js +1 -0
- package/lib/project-product-control.js +87 -0
- package/lib/project-product-session-queue.js +46 -0
- package/lib/project-push-access.js +28 -0
- package/lib/project-scheduled-message-queue.js +30 -0
- package/lib/project-scheduled-messages.js +63 -64
- package/lib/project-scheduled-task-control.js +83 -0
- package/lib/project-scheduled-tasks.js +13 -2
- package/lib/project-scheduling-access.js +10 -0
- package/lib/project-session-actions.js +65 -0
- package/lib/project-session-delete.js +8 -1
- package/lib/project-session-github.js +47 -12
- package/lib/project-session-history-actions.js +165 -0
- package/lib/project-session-runtime-actions.js +63 -0
- package/lib/project-session-vendor.js +54 -0
- package/lib/project-sessions.js +64 -241
- package/lib/project-user-message.js +30 -1
- package/lib/project-workspace-operations.js +126 -0
- package/lib/project-workspace-query.js +9 -2
- package/lib/project.js +95 -3
- package/lib/public/css/clay-tool-activity.css +51 -0
- package/lib/public/css/home-mate-creation.css +5 -0
- package/lib/public/css/overlays.css +4 -2
- package/lib/public/css/project-admin-overview.css +13 -0
- package/lib/public/css/session-folders.css +11 -0
- package/lib/public/css/session-github.css +3 -0
- package/lib/public/css/sticky-notes.css +61 -1
- package/lib/public/index.html +1 -1
- package/lib/public/modules/admin-settings-projects.js +6 -2
- package/lib/public/modules/app-connection.js +8 -1
- package/lib/public/modules/app-message-router.js +1 -1
- package/lib/public/modules/app-messages.js +18 -3
- package/lib/public/modules/app-projects.js +5 -0
- package/lib/public/modules/clay-owner-navigation.js +27 -0
- package/lib/public/modules/clay-tool-activity.js +140 -0
- package/lib/public/modules/clay-tool-presentation.js +338 -0
- package/lib/public/modules/command-palette.js +1 -1
- package/lib/public/modules/default-ai.js +11 -3
- package/lib/public/modules/home-debate-planning.js +5 -5
- package/lib/public/modules/home-mate-chat.js +8 -6
- package/lib/public/modules/home-mate-creation.js +73 -1
- package/lib/public/modules/personal-settings-dialog.js +7 -1
- package/lib/public/modules/project-access-recovery.js +17 -0
- package/lib/public/modules/project-admin-overview.js +21 -0
- package/lib/public/modules/session-folder-layout.js +1 -1
- package/lib/public/modules/session-folder-view-menu.js +9 -0
- package/lib/public/modules/session-github.js +65 -8
- package/lib/public/modules/sidebar-session-folders-ui.js +1 -1
- package/lib/public/modules/sticky-note-markdown.js +72 -6
- package/lib/public/modules/sticky-notes-actions.js +30 -0
- package/lib/public/modules/sticky-notes-browser.js +9 -2
- package/lib/public/modules/sticky-notes-card.js +23 -7
- package/lib/public/modules/sticky-notes-checklist.js +71 -0
- package/lib/public/modules/sticky-notes-editor.js +108 -44
- package/lib/public/modules/sticky-notes-shared.js +50 -2
- package/lib/public/modules/sticky-notes-state.js +66 -0
- package/lib/public/modules/sticky-notes.js +34 -51
- package/lib/public/modules/thinking-lifecycle.js +33 -3
- package/lib/public/modules/thinking-view.js +23 -1
- package/lib/public/modules/tools.js +34 -6
- package/lib/public/modules/user-settings-appearance.js +10 -3
- package/lib/public/modules/user-settings-editors.js +1 -1
- package/lib/public/modules/user-settings-layout.js +11 -2
- package/lib/public/modules/user-settings-preferences.js +6 -2
- package/lib/public/modules/user-settings-profile.js +12 -2
- package/lib/public/modules/user-settings.js +3 -2
- package/lib/public/style.css +2 -0
- package/lib/scheduled-task-records.js +3 -1
- package/lib/scheduler.js +2 -0
- package/lib/sdk-bridge.js +220 -21
- package/lib/sdk-message-processor.js +2 -0
- package/lib/sdk-response-recovery.js +155 -0
- package/lib/server-admin.js +63 -16
- package/lib/server-dm.js +1 -1
- package/lib/server-global-ws.js +10 -20
- package/lib/server-home-chat-events.js +7 -3
- package/lib/server-home-chat.js +4 -16
- package/lib/server-home-mate-creation.js +1 -0
- package/lib/server-home-mcp-consent.js +3 -3
- package/lib/server-mates.js +25 -67
- package/lib/server-owner-ui.js +77 -0
- package/lib/server-path-access.js +38 -0
- package/lib/server-project-removal.js +22 -0
- package/lib/server.js +99 -29
- package/lib/session-config-transition.js +45 -0
- package/lib/session-folders.js +7 -2
- package/lib/session-github.js +9 -2
- package/lib/session-visibility.js +5 -2
- package/lib/sessions.js +10 -0
- package/lib/terminal-manager.js +52 -0
- package/lib/users-permissions.js +2 -8
- package/lib/users.js +4 -0
- package/lib/workspace-query-access.js +4 -1
- package/lib/ws-schema.js +8 -2
- package/lib/yoke/adapters/claude.js +47 -8
- package/lib/yoke/adapters/codex.js +52 -111
- package/lib/yoke/claude-worker-startup.js +28 -0
- package/lib/yoke/codex-idle-recovery.js +81 -1
- package/lib/yoke/codex-recovery-admission.js +164 -0
- package/lib/yoke/session-tool-transport.js +3 -0
- package/package.json +1 -1
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { clayToolGroupSummary } from './clay-tool-presentation.js';
|
|
2
|
+
import { applyClayToolItem, applyClayToolResult, finishClayToolItem, findEndedClayTool, clayToolResultGroup, bindToolGroupDisclosure, syncToolGroupDisclosure, syncClayToolGroup } from './clay-tool-activity.js';
|
|
1
3
|
import { escapeHtml, copyToClipboard } from './utils.js';
|
|
2
4
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
3
5
|
import { renderMarkdown, highlightCodeBlocks, renderMermaidBlocks } from './markdown.js';
|
|
@@ -76,6 +78,8 @@ function findToolGroup(groupId) {
|
|
|
76
78
|
}
|
|
77
79
|
|
|
78
80
|
function toolGroupSummary(group) {
|
|
81
|
+
var claySummary = clayToolGroupSummary(group, tools);
|
|
82
|
+
if (claySummary) return claySummary;
|
|
79
83
|
var names = group.toolNames;
|
|
80
84
|
var count = names.length;
|
|
81
85
|
var allDone = group.doneCount >= count;
|
|
@@ -167,6 +171,8 @@ function updateToolGroupHeader(group) {
|
|
|
167
171
|
header.style.display = "none";
|
|
168
172
|
group.el.classList.remove("collapsed");
|
|
169
173
|
}
|
|
174
|
+
syncToolGroupDisclosure(group.el);
|
|
175
|
+
syncClayToolGroup(group);
|
|
170
176
|
}
|
|
171
177
|
|
|
172
178
|
function isPlanFile(filePath) {
|
|
@@ -1628,9 +1634,9 @@ export function createToolItem(id, name) {
|
|
|
1628
1634
|
}
|
|
1629
1635
|
|
|
1630
1636
|
applyProjectAssistantIdentity(groupEl, identity);
|
|
1631
|
-
groupEl
|
|
1632
|
-
groupEl.
|
|
1633
|
-
if (
|
|
1637
|
+
bindToolGroupDisclosure(groupEl, function () {
|
|
1638
|
+
var group = findToolGroup(groupEl.dataset.groupId);
|
|
1639
|
+
if (group) group.userToggled = true;
|
|
1634
1640
|
});
|
|
1635
1641
|
|
|
1636
1642
|
ctx.addToMessages(groupEl);
|
|
@@ -1640,6 +1646,8 @@ export function createToolItem(id, name) {
|
|
|
1640
1646
|
el: groupEl,
|
|
1641
1647
|
id: "g" + toolGroupCounter,
|
|
1642
1648
|
toolNames: [],
|
|
1649
|
+
toolIds: [],
|
|
1650
|
+
toolRecords: {},
|
|
1643
1651
|
toolCount: 0,
|
|
1644
1652
|
doneCount: 0,
|
|
1645
1653
|
errorCount: 0,
|
|
@@ -1666,17 +1674,21 @@ export function createToolItem(id, name) {
|
|
|
1666
1674
|
|
|
1667
1675
|
el.querySelector(".tool-name").textContent = name;
|
|
1668
1676
|
|
|
1677
|
+
tools[id] = { el: el, name: name, input: null, done: false, groupId: currentToolGroup.id };
|
|
1678
|
+
applyClayToolItem(tools[id]);
|
|
1679
|
+
|
|
1669
1680
|
// Append to group instead of messages directly
|
|
1670
1681
|
currentToolGroup.el.querySelector(".tool-group-items").appendChild(el);
|
|
1671
1682
|
currentToolGroup.toolNames.push(name);
|
|
1683
|
+
currentToolGroup.toolIds.push(id);
|
|
1684
|
+
currentToolGroup.toolRecords[id] = tools[id];
|
|
1672
1685
|
currentToolGroup.toolCount++;
|
|
1673
1686
|
updateToolGroupHeader(currentToolGroup);
|
|
1674
1687
|
|
|
1675
1688
|
refreshIcons();
|
|
1676
1689
|
maybeScrollToBottom();
|
|
1677
1690
|
|
|
1678
|
-
tools[id]
|
|
1679
|
-
ctx.setActivity("Running " + name + "...");
|
|
1691
|
+
ctx.setActivity(tools[id].clayActivity ? tools[id].clayActivity.label : "Running " + name + "...");
|
|
1680
1692
|
}
|
|
1681
1693
|
|
|
1682
1694
|
export function updateToolExecuting(id, name, input) {
|
|
@@ -1684,6 +1696,12 @@ export function updateToolExecuting(id, name, input) {
|
|
|
1684
1696
|
if (!tool) return;
|
|
1685
1697
|
|
|
1686
1698
|
tool.input = input;
|
|
1699
|
+
if (applyClayToolItem(tool)) {
|
|
1700
|
+
ctx.setActivity(tool.clayActivity.label);
|
|
1701
|
+
updateToolGroupHeader(findToolGroup(tool.groupId));
|
|
1702
|
+
maybeScrollToBottom();
|
|
1703
|
+
return;
|
|
1704
|
+
}
|
|
1687
1705
|
var descEl = tool.el.querySelector(".tool-desc");
|
|
1688
1706
|
descEl.textContent = toolSummary(name, input);
|
|
1689
1707
|
|
|
@@ -1893,9 +1911,17 @@ function isImagePath(filePath) {
|
|
|
1893
1911
|
}
|
|
1894
1912
|
|
|
1895
1913
|
export function updateToolResult(id, content, isError, images) {
|
|
1896
|
-
var tool = tools[id];
|
|
1914
|
+
var tool = tools[id] || findEndedClayTool(ctx.messagesEl, id);
|
|
1897
1915
|
if (!tool) return;
|
|
1898
1916
|
|
|
1917
|
+
if (applyClayToolResult(tool, content, isError)) {
|
|
1918
|
+
markToolDone(id, tool.clayActivity.phase === "error" || tool.clayActivity.phase === "cancelled");
|
|
1919
|
+
applyClayToolItem(tool);
|
|
1920
|
+
updateToolGroupHeader(clayToolResultGroup(tool, findToolGroup(tool.groupId)));
|
|
1921
|
+
maybeScrollToBottom();
|
|
1922
|
+
return;
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1899
1925
|
// Re-render the sublabel from the now-complete input (streaming can have
|
|
1900
1926
|
// built it from a partial one), but in its terminal form: a result has
|
|
1901
1927
|
// arrived, so this call is no longer running.
|
|
@@ -2026,6 +2052,7 @@ export function markToolDone(id, isError) {
|
|
|
2026
2052
|
icon.innerHTML = '<span class="check">' + iconHtml("check") + '</span>';
|
|
2027
2053
|
}
|
|
2028
2054
|
refreshIcons();
|
|
2055
|
+
finishClayToolItem(tool, findToolGroup(tool.groupId));
|
|
2029
2056
|
|
|
2030
2057
|
// Update group state
|
|
2031
2058
|
if (tool.groupId) {
|
|
@@ -2244,6 +2271,7 @@ export function removeToolFromGroup(toolId) {
|
|
|
2244
2271
|
var group = findToolGroup(tool.groupId);
|
|
2245
2272
|
if (!group) return;
|
|
2246
2273
|
group.toolCount--;
|
|
2274
|
+
if (group.toolIds) group.toolIds = group.toolIds.filter(function (id) { return id !== toolId; });
|
|
2247
2275
|
// Remove tool name from the names array (remove first occurrence)
|
|
2248
2276
|
var idx = group.toolNames.indexOf(tool.name);
|
|
2249
2277
|
if (idx !== -1) group.toolNames.splice(idx, 1);
|
|
@@ -31,7 +31,11 @@ function addTerminalTypography(section) {
|
|
|
31
31
|
var option = document.createElement('option'); option.value = font.family; option.textContent = font.label; family.appendChild(option);
|
|
32
32
|
});
|
|
33
33
|
function sync() {
|
|
34
|
-
if (store.get('userTerminalDirty'))
|
|
34
|
+
if (store.get('userTerminalDirty')) {
|
|
35
|
+
var dirty = family.value !== getTerminalFontFamily() || size.value !== String(getTerminalFontSize());
|
|
36
|
+
store.set({userTerminalDirty:dirty});
|
|
37
|
+
if (dirty) return;
|
|
38
|
+
}
|
|
35
39
|
var value = getTerminalFontFamily();
|
|
36
40
|
if (!Array.from(family.options).some(function (option) { return option.value === value; })) {
|
|
37
41
|
var option = document.createElement('option'); option.value = value; option.textContent = 'Custom font'; family.appendChild(option);
|
|
@@ -41,7 +45,10 @@ function addTerminalTypography(section) {
|
|
|
41
45
|
family.dispatchEvent(new Event('settings-sync'));
|
|
42
46
|
}
|
|
43
47
|
async function save() {
|
|
44
|
-
var
|
|
48
|
+
var dirty = family.value !== getTerminalFontFamily() || size.value !== String(getTerminalFontSize());
|
|
49
|
+
store.set({userTerminalDirty:dirty});
|
|
50
|
+
if (!dirty) {retry.hidden = true;status.textContent = '';status.dataset.state = '';return;}
|
|
51
|
+
var value = Number(size.value);
|
|
45
52
|
if (!Number.isInteger(value) || value < 9 || value > 32) { status.textContent = 'Choose a whole size from 9 to 32.'; status.dataset.state = 'error'; return; }
|
|
46
53
|
family.disabled = true; size.disabled = true; retry.hidden = true; status.textContent = 'Saving…'; status.dataset.state = '';
|
|
47
54
|
try {
|
|
@@ -50,6 +57,6 @@ function addTerminalTypography(section) {
|
|
|
50
57
|
finally { family.disabled = false; size.disabled = false; family.dispatchEvent(new Event('settings-sync')); }
|
|
51
58
|
}
|
|
52
59
|
family.onchange = save; size.onchange = save; retry.onclick = save;
|
|
53
|
-
size.oninput = function () { store.set({ userTerminalDirty:
|
|
60
|
+
size.oninput = function () { store.set({ userTerminalDirty: family.value !== getTerminalFontFamily() || size.value !== String(getTerminalFontSize()) }); };
|
|
54
61
|
onTerminalFontChange(sync); sync(); enhanceSettingsSelects(content);
|
|
55
62
|
}
|
|
@@ -19,6 +19,6 @@ function wrapEditor(content, title, summary) {
|
|
|
19
19
|
}
|
|
20
20
|
export function initPersonalEditors() {
|
|
21
21
|
var allow=document.getElementById('us-claude-allow-list');var permission=wrapEditor(allow.closest('.settings-card'),'Personal allow rules',function(){var count=(store.get('userAllowSaved') || []).length;return count+' personal rules. Managed defaults apply separately.';});
|
|
22
|
-
permission.done.textContent='Cancel';permission.done.onclick=function(){function cancel(){allow.value=(store.get('userAllowSaved') || []).join('\n');store.set({userAllowDirty:false});permission.content.hidden=true;permission.state.hidden=false;permission.edit.hidden=false;permission.edit.focus();}if(store.get('userAllowDirty'))showConfirmDialog('Discard unsaved command rules?', 'Discard',cancel);else cancel();};
|
|
22
|
+
permission.done.textContent='Cancel';permission.done.onclick=function(){function cancel(){allow.value=(store.get('userAllowSaved') || []).join('\n');store.set({userAllowDirty:false,userAllowNeedsRetry:false});permission.content.hidden=true;permission.state.hidden=false;permission.edit.hidden=false;permission.edit.focus();}if(store.get('userAllowDirty'))showConfirmDialog('Discard unsaved command rules?', 'Discard',cancel);else cancel();};
|
|
23
23
|
store.subscribe(function(state,previous){if(state.userAllowSaved!==previous.userAllowSaved){permission.state.textContent=(state.userAllowSaved || []).length+' personal rules. Managed defaults apply separately.';if(previous.userAllowDirty && !state.userAllowDirty){permission.content.hidden=true;permission.state.hidden=false;permission.edit.hidden=false;permission.edit.focus();}}});
|
|
24
24
|
}
|
|
@@ -69,12 +69,21 @@ export function loadUserSettingsExtras(page) {
|
|
|
69
69
|
if (page === 'us-ai') { mountDefaultAi(document.getElementById('us-default-ai')); requestDefaultAi(); var ws=getWs();if(ws && ws.readyState===1)ws.send(JSON.stringify({type:'get_claude_allow_list'})); }
|
|
70
70
|
}
|
|
71
71
|
export function finishUserSettingsExtras() {closeSpeechPicker();unmountDefaultAi(document.getElementById('us-default-ai'));}
|
|
72
|
-
export function guardUserSettingsLeave(done) {
|
|
72
|
+
export function guardUserSettingsLeave(done, destination) {
|
|
73
|
+
var active = document.querySelector('#user-settings .us-section.active');
|
|
74
|
+
var page = active && active.dataset.section;
|
|
75
|
+
if (destination && resolveUserSettingsPage(destination) === page) {done();return;}
|
|
76
|
+
function leaving(id) {return !destination || page === id;}
|
|
73
77
|
var pin = document.getElementById('us-pin-form');
|
|
74
78
|
var pinDirty = pin && !pin.classList.contains('hidden') && Array.from(pin.querySelectorAll('input')).some(function (input) {return !!input.value;});
|
|
75
79
|
var key = document.getElementById('us-linear-key');
|
|
76
80
|
if(store.get('speechPopup'))return;
|
|
77
|
-
var dirty =
|
|
81
|
+
var dirty = leaving('us-integrations') && (store.get('personalEmailDirty') || store.get('personalLinearDirty') || key && key.value) ||
|
|
82
|
+
leaving('us-chat') && store.get('userVoiceDirty') ||
|
|
83
|
+
leaving('us-notifications') && store.get('notificationDraft') ||
|
|
84
|
+
leaving('us-appearance') && (store.get('appearanceDraft') || store.get('userTerminalDirty')) ||
|
|
85
|
+
leaving('us-account') && (store.get('userProfileDirty') || pinDirty) ||
|
|
86
|
+
leaving('us-ai') && (store.get('defaultAiDraftDirty') || store.get('userAllowDirty'));
|
|
78
87
|
if (!dirty) {done();return;}
|
|
79
88
|
showConfirmDialog('Your unsaved changes will remain in this tab. Leave this editor and keep the draft?', 'Keep draft and leave', done);
|
|
80
89
|
}
|
|
@@ -27,7 +27,10 @@ export function initPersonalPreferences() {
|
|
|
27
27
|
catch(error){preferenceStatus('us-layout-switcher',error.message+' Try again.',true);}
|
|
28
28
|
finally{controls.forEach(function(el){el.disabled=false;});}
|
|
29
29
|
};});
|
|
30
|
-
var textarea=document.getElementById('us-claude-allow-list');textarea.oninput=function(){
|
|
30
|
+
var textarea=document.getElementById('us-claude-allow-list');textarea.oninput=function(){
|
|
31
|
+
var patterns=textarea.value.split('\n').map(function(line){return line.trim();}).filter(Boolean);
|
|
32
|
+
store.set({userAllowDirty:!!store.get('userAllowNeedsRetry') || JSON.stringify(patterns)!==JSON.stringify(store.get('userAllowSaved') || [])});
|
|
33
|
+
};
|
|
31
34
|
document.getElementById('us-claude-allow-save').onclick=function(){
|
|
32
35
|
var ws=getWs();if(!ws || ws.readyState!==1){preferenceStatus('us-claude-allow-list','Disconnected. Your draft is retained.',true);return;}
|
|
33
36
|
this.disabled=true;preferenceStatus('us-claude-allow-list','Saving…');ws.send(JSON.stringify({type:'set_claude_user_allow_list',patterns:textarea.value.split('\n').map(function(line){return line.trim();}).filter(Boolean)}));
|
|
@@ -37,11 +40,12 @@ export function initPersonalPreferences() {
|
|
|
37
40
|
export function handlePersonalSettingsMessage(msg) {
|
|
38
41
|
if(msg.type==='claude_allow_list') {
|
|
39
42
|
store.set({userAllowSaved:msg.user || []});
|
|
43
|
+
if(store.get('userAllowDirty'))document.getElementById('us-claude-allow-list').oninput();
|
|
40
44
|
if(store.get('userAllowDirty'))return;
|
|
41
45
|
}
|
|
42
46
|
if(msg.type==='set_claude_user_allow_list_result') {
|
|
43
47
|
document.getElementById('us-claude-allow-save').disabled=false;
|
|
44
|
-
if(msg.ok)store.set({userAllowDirty:msg.effective===false,userAllowSaved:msg.patterns || []});
|
|
48
|
+
if(msg.ok)store.set({userAllowDirty:msg.effective===false,userAllowNeedsRetry:msg.effective===false,userAllowSaved:msg.patterns || []});
|
|
45
49
|
var message=msg.ok ? (msg.effective===false ? 'Saved to your account, but not installed in Claude. Check filesystem access, then Save to retry.' : 'Saved. Applies on the next Claude invocation.') : msg.error || 'Save failed. Your draft is retained.';
|
|
46
50
|
preferenceStatus('us-claude-allow-list',message,!msg.ok || msg.effective===false);
|
|
47
51
|
}
|
|
@@ -13,10 +13,20 @@ export function initPersonalProfile() {
|
|
|
13
13
|
name.after(form); var input = form.querySelector('input');
|
|
14
14
|
function close() { form.hidden = true; name.hidden = false; edit.hidden = false; edit.focus(); }
|
|
15
15
|
edit.onclick = function () {
|
|
16
|
-
if (!store.get('userProfileDirty'))
|
|
16
|
+
if (!store.get('userProfileDirty')) {
|
|
17
|
+
input.value = name.textContent || getProfile().name;
|
|
18
|
+
store.set({userProfileSavedName:input.value.trim()});
|
|
19
|
+
}
|
|
17
20
|
form.hidden = false; name.hidden = true; edit.hidden = true; input.focus(); input.select();
|
|
18
21
|
};
|
|
19
|
-
input.oninput = function () { store.set({ userProfileDirty:
|
|
22
|
+
input.oninput = function () { store.set({ userProfileDirty: input.value.trim() !== store.get('userProfileSavedName') }); };
|
|
23
|
+
store.subscribe(function (state, previous) {
|
|
24
|
+
if (state.userSettingsProfile === previous.userSettingsProfile || !state.userSettingsProfile) return;
|
|
25
|
+
var data = state.userSettingsProfile;
|
|
26
|
+
var saved = data.name || data.displayName || data.username || 'Clay User';
|
|
27
|
+
if (!state.userProfileDirty) input.value = saved;
|
|
28
|
+
store.set({userProfileSavedName:saved.trim(), userProfileDirty:input.value.trim() !== saved.trim()});
|
|
29
|
+
});
|
|
20
30
|
form.onsubmit = async function (event) {
|
|
21
31
|
event.preventDefault(); var save = form.querySelector('[type=submit]'); var status = form.querySelector('[role=status]');
|
|
22
32
|
if (!input.value.trim()) { status.textContent = 'Enter a display name.'; return; }
|
|
@@ -75,7 +75,7 @@ export function initUserSettings() {
|
|
|
75
75
|
for (var i = 0; i < navItems.length; i++) {
|
|
76
76
|
navItems[i].addEventListener('click', function () {
|
|
77
77
|
var section = this.dataset.section;
|
|
78
|
-
guardUserSettingsLeave(function () { switchSection(section); });
|
|
78
|
+
guardUserSettingsLeave(function () { switchSection(section); }, section);
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
81
|
|
|
@@ -83,7 +83,8 @@ export function initUserSettings() {
|
|
|
83
83
|
var navDropdown = document.getElementById('user-settings-nav-dropdown');
|
|
84
84
|
if (navDropdown) {
|
|
85
85
|
navDropdown.addEventListener('change', function () {
|
|
86
|
-
var value = this.value; guardUserSettingsLeave(function () {switchSection(value);});
|
|
86
|
+
var value = this.value; guardUserSettingsLeave(function () {switchSection(value);}, value);
|
|
87
|
+
this.value = settingsEl.querySelector('.us-section.active').dataset.section;
|
|
87
88
|
});
|
|
88
89
|
}
|
|
89
90
|
|
package/lib/public/style.css
CHANGED
|
@@ -18,6 +18,7 @@ function createScheduledTaskRecords(ctx) {
|
|
|
18
18
|
var runs = Array.isArray(record.runs) ? record.runs : [];
|
|
19
19
|
var readiness = ctx.runtimeStatus ? ctx.runtimeStatus(record) : null;
|
|
20
20
|
return {
|
|
21
|
+
createdBy: record.createdBy || null, updatedBy: record.updatedBy || null,
|
|
21
22
|
id: record.id, revision: Number(record.updatedAt || 0), name: record.name || "",
|
|
22
23
|
instructions: record.task || record.prompt || record.instructions || "",
|
|
23
24
|
cron: record.cron || null, date: record.date || null, time: record.time || null,
|
|
@@ -49,7 +50,7 @@ function createScheduledTaskRecords(ctx) {
|
|
|
49
50
|
return { ok: true, record: publicRecord(record) };
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
function update(session, id, revision, patch) {
|
|
53
|
+
function update(session, id, revision, patch, actor) {
|
|
53
54
|
if (typeof id !== "string" || !ID_PATTERN.test(id)) return { ok: false, error: "Scheduled task id is invalid." };
|
|
54
55
|
var record = ctx.registry.getById(id);
|
|
55
56
|
if (!record) return { ok: false, error: "Scheduled task not found." };
|
|
@@ -94,6 +95,7 @@ function createScheduledTaskRecords(ctx) {
|
|
|
94
95
|
}
|
|
95
96
|
try {
|
|
96
97
|
var updateData = Object.assign({}, checked.value);
|
|
98
|
+
if (actor) updateData.updatedBy = actor;
|
|
97
99
|
if (claimOwner) { updateData.ownerId = session.ownerId; updateData.enabled = true; }
|
|
98
100
|
if (updateData.cron) {
|
|
99
101
|
updateData.date = record.cron && !record.scheduleRule ? record.date || null : null;
|
package/lib/scheduler.js
CHANGED
|
@@ -239,6 +239,7 @@ function createLoopRegistry(opts) {
|
|
|
239
239
|
|
|
240
240
|
function register(data) {
|
|
241
241
|
var rec = {
|
|
242
|
+
createdBy: data.createdBy || null, updatedBy: data.updatedBy || null, creationFingerprint: data.creationFingerprint || null,
|
|
242
243
|
id: data.id || ("loop_" + Date.now() + "_" + require("crypto").randomBytes(3).toString("hex")),
|
|
243
244
|
name: data.name || "Untitled",
|
|
244
245
|
task: data.task || "",
|
|
@@ -297,6 +298,7 @@ function createLoopRegistry(opts) {
|
|
|
297
298
|
if (!rec) return null;
|
|
298
299
|
var previous = Object.assign({}, rec);
|
|
299
300
|
|
|
301
|
+
if (data.updatedBy !== undefined) rec.updatedBy = data.updatedBy;
|
|
300
302
|
if (data.name !== undefined) rec.name = data.name;
|
|
301
303
|
if (data.cron !== undefined) rec.cron = data.cron;
|
|
302
304
|
if (data.enabled !== undefined) rec.enabled = data.enabled;
|